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
|
// are available when Filterers are constructed
|
||||||
loadCachedFilters()
|
loadCachedFilters()
|
||||||
|
|
||||||
if let existing = try? persistentContainer.viewContext.fetch(AccountPreferences.fetchRequest(account: accountInfo!)).first {
|
loadAccountPreferences()
|
||||||
accountPreferences = existing
|
|
||||||
} else {
|
NotificationCenter.default.publisher(for: .NSPersistentStoreRemoteChange, object: persistentContainer.persistentStoreCoordinator)
|
||||||
accountPreferences = AccountPreferences.default(account: accountInfo!, context: persistentContainer.viewContext)
|
.receive(on: DispatchQueue.main)
|
||||||
persistentContainer.save(context: persistentContainer.viewContext)
|
.sink { [unowned self] _ in
|
||||||
|
self.loadAccountPreferences()
|
||||||
}
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
|
||||||
Task {
|
Task {
|
||||||
do {
|
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) {
|
func getOwnAccount(completion: ((Result<Account, Client.Error>) -> Void)? = nil) {
|
||||||
if account != nil {
|
if account != nil {
|
||||||
completion?(.success(account))
|
completion?(.success(account))
|
||||||
|
|
|
@ -16,10 +16,12 @@ public final class AccountPreferences: NSManagedObject {
|
||||||
@nonobjc class func fetchRequest(account: LocalData.UserAccountInfo) -> NSFetchRequest<AccountPreferences> {
|
@nonobjc class func fetchRequest(account: LocalData.UserAccountInfo) -> NSFetchRequest<AccountPreferences> {
|
||||||
let req = NSFetchRequest<AccountPreferences>(entityName: "AccountPreferences")
|
let req = NSFetchRequest<AccountPreferences>(entityName: "AccountPreferences")
|
||||||
req.predicate = NSPredicate(format: "accountID = %@", account.id)
|
req.predicate = NSPredicate(format: "accountID = %@", account.id)
|
||||||
|
req.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged public var accountID: String
|
@NSManaged public var accountID: String
|
||||||
|
@NSManaged var createdAt: Date
|
||||||
@NSManaged var pinnedTimelinesData: Data?
|
@NSManaged var pinnedTimelinesData: Data?
|
||||||
|
|
||||||
@LazilyDecoding(from: \AccountPreferences.pinnedTimelinesData, fallback: [])
|
@LazilyDecoding(from: \AccountPreferences.pinnedTimelinesData, fallback: [])
|
||||||
|
@ -28,6 +30,7 @@ public final class AccountPreferences: NSManagedObject {
|
||||||
static func `default`(account: LocalData.UserAccountInfo, context: NSManagedObjectContext) -> AccountPreferences {
|
static func `default`(account: LocalData.UserAccountInfo, context: NSManagedObjectContext) -> AccountPreferences {
|
||||||
let prefs = AccountPreferences(context: context)
|
let prefs = AccountPreferences(context: context)
|
||||||
prefs.accountID = account.id
|
prefs.accountID = account.id
|
||||||
|
prefs.createdAt = Date()
|
||||||
prefs.pinnedTimelines = [.home, .public(local: true), .public(local: false)]
|
prefs.pinnedTimelines = [.home, .public(local: true), .public(local: false)]
|
||||||
return prefs
|
return prefs
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,12 @@ public final class TimelinePosition: NSManagedObject {
|
||||||
@nonobjc class func fetchRequest(timeline: Timeline, account: LocalData.UserAccountInfo) -> NSFetchRequest<TimelinePosition> {
|
@nonobjc class func fetchRequest(timeline: Timeline, account: LocalData.UserAccountInfo) -> NSFetchRequest<TimelinePosition> {
|
||||||
let req = NSFetchRequest<TimelinePosition>(entityName: "TimelinePosition")
|
let req = NSFetchRequest<TimelinePosition>(entityName: "TimelinePosition")
|
||||||
req.predicate = NSPredicate(format: "accountID = %@ AND timelineKind = %@", account.id, toTimelineKind(timeline))
|
req.predicate = NSPredicate(format: "accountID = %@ AND timelineKind = %@", account.id, toTimelineKind(timeline))
|
||||||
|
req.sortDescriptors = [NSSortDescriptor(key: "createdAt", ascending: true)]
|
||||||
return req
|
return req
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged public var accountID: String
|
@NSManaged public var accountID: String
|
||||||
|
@NSManaged public var createdAt: Date
|
||||||
@NSManaged private var timelineKind: String
|
@NSManaged private var timelineKind: String
|
||||||
@NSManaged public var centerStatusID: String?
|
@NSManaged public var centerStatusID: String?
|
||||||
@NSManaged private var statusIDsData: Data?
|
@NSManaged private var statusIDsData: Data?
|
||||||
|
@ -36,6 +38,7 @@ public final class TimelinePosition: NSManagedObject {
|
||||||
self.init(context: context)
|
self.init(context: context)
|
||||||
self.timeline = timeline
|
self.timeline = timeline
|
||||||
self.accountID = account.id
|
self.accountID = account.id
|
||||||
|
self.createdAt = Date()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?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">
|
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
||||||
<attribute name="acct" attributeType="String"/>
|
<attribute name="acct" attributeType="String"/>
|
||||||
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
||||||
|
@ -30,6 +30,7 @@
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="AccountPreferences" representedClassName="AccountPreferences" syncable="YES">
|
<entity name="AccountPreferences" representedClassName="AccountPreferences" syncable="YES">
|
||||||
<attribute name="accountID" optional="YES" attributeType="String"/>
|
<attribute name="accountID" optional="YES" attributeType="String"/>
|
||||||
|
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
<attribute name="pinnedTimelinesData" optional="YES" attributeType="Binary"/>
|
<attribute name="pinnedTimelinesData" optional="YES" attributeType="Binary"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="Filter" representedClassName="FilterMO" syncable="YES">
|
<entity name="Filter" representedClassName="FilterMO" syncable="YES">
|
||||||
|
@ -120,6 +121,7 @@
|
||||||
<entity name="TimelinePosition" representedClassName="TimelinePosition" syncable="YES">
|
<entity name="TimelinePosition" representedClassName="TimelinePosition" syncable="YES">
|
||||||
<attribute name="accountID" optional="YES" attributeType="String"/>
|
<attribute name="accountID" optional="YES" attributeType="String"/>
|
||||||
<attribute name="centerStatusID" 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="statusIDsData" optional="YES" attributeType="Binary" valueTransformerName="TimelinePositionStatusIDsTransformer"/>
|
||||||
<attribute name="timelineKind" optional="YES" attributeType="String"/>
|
<attribute name="timelineKind" optional="YES" attributeType="String"/>
|
||||||
</entity>
|
</entity>
|
||||||
|
|
Loading…
Reference in New Issue