parent
cb5b70a23a
commit
da88303a22
|
@ -23,6 +23,7 @@ class MastodonController: ObservableObject {
|
|||
@available(*, message: "do something less dumb")
|
||||
static var first: MastodonController { all.first!.value }
|
||||
|
||||
@MainActor
|
||||
static func getForAccount(_ account: UserAccountInfo) -> MastodonController {
|
||||
if let controller = all[account] {
|
||||
return controller
|
||||
|
@ -51,6 +52,7 @@ class MastodonController: ObservableObject {
|
|||
let client: Client!
|
||||
let instanceFeatures = InstanceFeatures()
|
||||
|
||||
@Published private(set) var accountID: String?
|
||||
@Published private(set) var account: Account!
|
||||
@Published private(set) var instance: Instance?
|
||||
@Published private(set) var instanceInfo: InstanceInfo!
|
||||
|
@ -69,6 +71,8 @@ class MastodonController: ObservableObject {
|
|||
accountInfo != nil
|
||||
}
|
||||
|
||||
// main-actor b/c fetchActiveAccountID and fetchActiveInstance use the viewContext
|
||||
@MainActor
|
||||
init(instanceURL: URL, accountInfo: UserAccountInfo?) {
|
||||
self.instanceURL = instanceURL
|
||||
self.accountInfo = accountInfo
|
||||
|
@ -81,6 +85,7 @@ class MastodonController: ObservableObject {
|
|||
self.client.accessToken = accountInfo?.accessToken
|
||||
|
||||
if !transient {
|
||||
fetchActiveAccountID()
|
||||
fetchActiveInstance()
|
||||
}
|
||||
|
||||
|
@ -119,6 +124,7 @@ class MastodonController: ObservableObject {
|
|||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
@MainActor
|
||||
convenience init(instanceURL: URL, transient: Bool) {
|
||||
precondition(transient, "account info must be provided if transient is false")
|
||||
self.init(instanceURL: instanceURL, accountInfo: nil)
|
||||
|
@ -242,13 +248,14 @@ class MastodonController: ObservableObject {
|
|||
DispatchQueue.main.async {
|
||||
self.account = account
|
||||
}
|
||||
self.persistentContainer.backgroundContext.perform {
|
||||
if let accountMO = self.persistentContainer.account(for: account.id, in: self.persistentContainer.backgroundContext) {
|
||||
let context = self.persistentContainer.backgroundContext
|
||||
context.perform {
|
||||
if let accountMO = self.persistentContainer.account(for: account.id, in: context) {
|
||||
accountMO.updateFrom(apiAccount: account, container: self.persistentContainer)
|
||||
accountMO.active = true
|
||||
} else {
|
||||
// the first time the user's account is added to the store,
|
||||
// increment its reference count so that it's never removed
|
||||
self.persistentContainer.addOrUpdate(account: account)
|
||||
let account = self.persistentContainer.addOrUpdateSynchronously(account: account, in: context)
|
||||
account.active = true
|
||||
}
|
||||
completion?(.success(account))
|
||||
}
|
||||
|
@ -367,16 +374,22 @@ class MastodonController: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func fetchActiveAccountID() {
|
||||
let req = AccountMO.fetchRequest()
|
||||
req.predicate = NSPredicate(format: "active = YES")
|
||||
if let activeAccount = try? persistentContainer.viewContext.fetch(req).first {
|
||||
accountID = activeAccount.id
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
private func fetchActiveInstance() {
|
||||
persistentContainer.performBackgroundTask { context in
|
||||
if let activeInstance = try? context.fetch(ActiveInstance.fetchRequest()).first {
|
||||
if let activeInstance = try? persistentContainer.viewContext.fetch(ActiveInstance.fetchRequest()).first {
|
||||
let info = InstanceInfo(activeInstance: activeInstance)
|
||||
DispatchQueue.main.async {
|
||||
self.instanceInfo = info
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getCustomEmojis(completion: @escaping ([Emoji]) -> Void) {
|
||||
if let emojis = self.customEmojis {
|
||||
|
|
|
@ -25,6 +25,8 @@ public final class AccountMO: NSManagedObject, AccountProtocol {
|
|||
}
|
||||
|
||||
@NSManaged public var acct: String
|
||||
/// Whether this AccountMO is the active (logged-in) account.
|
||||
@NSManaged public var active: Bool
|
||||
@NSManaged public var avatar: URL?
|
||||
@NSManaged public var botCD: Bool
|
||||
@NSManaged public var createdAt: Date
|
||||
|
|
|
@ -311,6 +311,14 @@ class MastodonCachePersistentStore: NSPersistentCloudKitContainer {
|
|||
}
|
||||
}
|
||||
|
||||
/// The caller is responsible for calling this on a queue appropriate for `context`.
|
||||
func addOrUpdateSynchronously(account: Account, in context: NSManagedObjectContext) -> AccountMO {
|
||||
let accountMO = self.upsert(account: account, in: context)
|
||||
self.save(context: context)
|
||||
self.accountSubject.send(account.id)
|
||||
return accountMO
|
||||
}
|
||||
|
||||
func relationship(forAccount id: String, in context: NSManagedObjectContext? = nil) -> RelationshipMO? {
|
||||
let context = context ?? viewContext
|
||||
let request: NSFetchRequest<RelationshipMO> = RelationshipMO.fetchRequest()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="21754" systemVersion="22D49" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
|
||||
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
||||
<attribute name="acct" attributeType="String"/>
|
||||
<attribute name="active" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
||||
<attribute name="botCD" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
|
|
Loading…
Reference in New Issue