forked from shadowfacts/Tusker
Add createdAt to AccountPreferences and TimelinePosition to guard against race conditions when creating/migrating
This commit is contained in:
parent
91b7ce3008
commit
d4c560d7fc
|
@ -155,12 +155,14 @@ class MastodonController: ObservableObject {
|
|||
// are available when Filterers are constructed
|
||||
loadCachedFilters()
|
||||
|
||||
if let existing = try? persistentContainer.viewContext.fetch(AccountPreferences.fetchRequest(account: accountInfo!)).first {
|
||||
accountPreferences = existing
|
||||
} else {
|
||||
accountPreferences = AccountPreferences.default(account: accountInfo!, context: persistentContainer.viewContext)
|
||||
persistentContainer.save(context: persistentContainer.viewContext)
|
||||
}
|
||||
loadAccountPreferences()
|
||||
|
||||
NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange, object: persistentContainer.persistentStoreCoordinator)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [unowned self] _ in
|
||||
self.loadAccountPreferences()
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
|
||||
Task {
|
||||
do {
|
||||
|
@ -177,6 +179,16 @@ class MastodonController: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func loadAccountPreferences() {
|
||||
if let existing = try? persistentContainer.viewContext.fetch(AccountPreferences.fetchRequest(account: accountInfo!)).first {
|
||||
accountPreferences = existing
|
||||
} else {
|
||||
accountPreferences = AccountPreferences.default(account: accountInfo!, context: persistentContainer.viewContext)
|
||||
persistentContainer.save(context: persistentContainer.viewContext)
|
||||
}
|
||||
}
|
||||
|
||||
func getOwnAccount(completion: ((Result<Account, Client.Error>) -> Void)? = nil) {
|
||||
if account != nil {
|
||||
completion?(.success(account))
|
||||
|
|
|
@ -16,10 +16,12 @@ public final class AccountPreferences: NSManagedObject {
|
|||
@nonobjc class func fetchRequest(account: LocalData.UserAccountInfo) -> NSFetchRequest<AccountPreferences> {
|
||||
let req = NSFetchRequest<AccountPreferences>(entityName: "AccountPreferences")
|
||||
req.predicate = NSPredicate(format: "accountID = %@", account.id)
|
||||
req.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
|
||||
return req
|
||||
}
|
||||
|
||||
@NSManaged public var accountID: String
|
||||
@NSManaged var createdAt: Date
|
||||
@NSManaged var pinnedTimelinesData: Data?
|
||||
|
||||
@LazilyDecoding(from: \AccountPreferences.pinnedTimelinesData, fallback: [])
|
||||
|
@ -28,6 +30,7 @@ public final class AccountPreferences: NSManagedObject {
|
|||
static func `default`(account: LocalData.UserAccountInfo, context: NSManagedObjectContext) -> AccountPreferences {
|
||||
let prefs = AccountPreferences(context: context)
|
||||
prefs.accountID = account.id
|
||||
prefs.createdAt = Date()
|
||||
prefs.pinnedTimelines = [.home, .public(local: true), .public(local: false)]
|
||||
return prefs
|
||||
}
|
||||
|
|
|
@ -16,10 +16,12 @@ public final class TimelinePosition: NSManagedObject {
|
|||
@nonobjc class func fetchRequest(timeline: Timeline, account: LocalData.UserAccountInfo) -> NSFetchRequest<TimelinePosition> {
|
||||
let req = NSFetchRequest<TimelinePosition>(entityName: "TimelinePosition")
|
||||
req.predicate = NSPredicate(format: "accountID = %@ AND timelineKind = %@", account.id, toTimelineKind(timeline))
|
||||
req.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
|
||||
return req
|
||||
}
|
||||
|
||||
@NSManaged public var accountID: String
|
||||
@NSManaged public var createdAt: Date
|
||||
@NSManaged private var timelineKind: String
|
||||
@NSManaged public var centerStatusID: String?
|
||||
@NSManaged private var statusIDsData: Data?
|
||||
|
@ -36,6 +38,7 @@ public final class TimelinePosition: NSManagedObject {
|
|||
self.init(context: context)
|
||||
self.timeline = timeline
|
||||
self.accountID = account.id
|
||||
self.createdAt = Date()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22A380" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21513" systemVersion="22C65" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
||||
<attribute name="acct" attributeType="String"/>
|
||||
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
||||
|
@ -30,6 +30,7 @@
|
|||
</entity>
|
||||
<entity name="AccountPreferences" representedClassName="AccountPreferences" syncable="YES">
|
||||
<attribute name="accountID" optional="YES" attributeType="String"/>
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="pinnedTimelinesData" optional="YES" attributeType="Binary"/>
|
||||
</entity>
|
||||
<entity name="Filter" representedClassName="FilterMO" syncable="YES">
|
||||
|
@ -120,6 +121,7 @@
|
|||
<entity name="TimelinePosition" representedClassName="TimelinePosition" syncable="YES">
|
||||
<attribute name="accountID" optional="YES" attributeType="String"/>
|
||||
<attribute name="centerStatusID" optional="YES" attributeType="String"/>
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="statusIDsData" optional="YES" attributeType="Binary" valueTransformerName="TimelinePositionStatusIDsTransformer"/>
|
||||
<attribute name="timelineKind" optional="YES" attributeType="String"/>
|
||||
</entity>
|
||||
|
|
Loading…
Reference in New Issue