parent
cb5b70a23a
commit
da88303a22
|
@ -23,6 +23,7 @@ class MastodonController: ObservableObject {
|
||||||
@available(*, message: "do something less dumb")
|
@available(*, message: "do something less dumb")
|
||||||
static var first: MastodonController { all.first!.value }
|
static var first: MastodonController { all.first!.value }
|
||||||
|
|
||||||
|
@MainActor
|
||||||
static func getForAccount(_ account: UserAccountInfo) -> MastodonController {
|
static func getForAccount(_ account: UserAccountInfo) -> MastodonController {
|
||||||
if let controller = all[account] {
|
if let controller = all[account] {
|
||||||
return controller
|
return controller
|
||||||
|
@ -51,6 +52,7 @@ class MastodonController: ObservableObject {
|
||||||
let client: Client!
|
let client: Client!
|
||||||
let instanceFeatures = InstanceFeatures()
|
let instanceFeatures = InstanceFeatures()
|
||||||
|
|
||||||
|
@Published private(set) var accountID: String?
|
||||||
@Published private(set) var account: Account!
|
@Published private(set) var account: Account!
|
||||||
@Published private(set) var instance: Instance?
|
@Published private(set) var instance: Instance?
|
||||||
@Published private(set) var instanceInfo: InstanceInfo!
|
@Published private(set) var instanceInfo: InstanceInfo!
|
||||||
|
@ -69,6 +71,8 @@ class MastodonController: ObservableObject {
|
||||||
accountInfo != nil
|
accountInfo != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// main-actor b/c fetchActiveAccountID and fetchActiveInstance use the viewContext
|
||||||
|
@MainActor
|
||||||
init(instanceURL: URL, accountInfo: UserAccountInfo?) {
|
init(instanceURL: URL, accountInfo: UserAccountInfo?) {
|
||||||
self.instanceURL = instanceURL
|
self.instanceURL = instanceURL
|
||||||
self.accountInfo = accountInfo
|
self.accountInfo = accountInfo
|
||||||
|
@ -81,6 +85,7 @@ class MastodonController: ObservableObject {
|
||||||
self.client.accessToken = accountInfo?.accessToken
|
self.client.accessToken = accountInfo?.accessToken
|
||||||
|
|
||||||
if !transient {
|
if !transient {
|
||||||
|
fetchActiveAccountID()
|
||||||
fetchActiveInstance()
|
fetchActiveInstance()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +124,7 @@ class MastodonController: ObservableObject {
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MainActor
|
||||||
convenience init(instanceURL: URL, transient: Bool) {
|
convenience init(instanceURL: URL, transient: Bool) {
|
||||||
precondition(transient, "account info must be provided if transient is false")
|
precondition(transient, "account info must be provided if transient is false")
|
||||||
self.init(instanceURL: instanceURL, accountInfo: nil)
|
self.init(instanceURL: instanceURL, accountInfo: nil)
|
||||||
|
@ -242,13 +248,14 @@ class MastodonController: ObservableObject {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.account = account
|
self.account = account
|
||||||
}
|
}
|
||||||
self.persistentContainer.backgroundContext.perform {
|
let context = self.persistentContainer.backgroundContext
|
||||||
if let accountMO = self.persistentContainer.account(for: account.id, in: self.persistentContainer.backgroundContext) {
|
context.perform {
|
||||||
|
if let accountMO = self.persistentContainer.account(for: account.id, in: context) {
|
||||||
accountMO.updateFrom(apiAccount: account, container: self.persistentContainer)
|
accountMO.updateFrom(apiAccount: account, container: self.persistentContainer)
|
||||||
|
accountMO.active = true
|
||||||
} else {
|
} else {
|
||||||
// the first time the user's account is added to the store,
|
let account = self.persistentContainer.addOrUpdateSynchronously(account: account, in: context)
|
||||||
// increment its reference count so that it's never removed
|
account.active = true
|
||||||
self.persistentContainer.addOrUpdate(account: account)
|
|
||||||
}
|
}
|
||||||
completion?(.success(account))
|
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() {
|
private func fetchActiveInstance() {
|
||||||
persistentContainer.performBackgroundTask { context in
|
if let activeInstance = try? persistentContainer.viewContext.fetch(ActiveInstance.fetchRequest()).first {
|
||||||
if let activeInstance = try? context.fetch(ActiveInstance.fetchRequest()).first {
|
|
||||||
let info = InstanceInfo(activeInstance: activeInstance)
|
let info = InstanceInfo(activeInstance: activeInstance)
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.instanceInfo = info
|
self.instanceInfo = info
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCustomEmojis(completion: @escaping ([Emoji]) -> Void) {
|
func getCustomEmojis(completion: @escaping ([Emoji]) -> Void) {
|
||||||
if let emojis = self.customEmojis {
|
if let emojis = self.customEmojis {
|
||||||
|
|
|
@ -25,6 +25,8 @@ public final class AccountMO: NSManagedObject, AccountProtocol {
|
||||||
}
|
}
|
||||||
|
|
||||||
@NSManaged public var acct: String
|
@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 avatar: URL?
|
||||||
@NSManaged public var botCD: Bool
|
@NSManaged public var botCD: Bool
|
||||||
@NSManaged public var createdAt: Date
|
@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? {
|
func relationship(forAccount id: String, in context: NSManagedObjectContext? = nil) -> RelationshipMO? {
|
||||||
let context = context ?? viewContext
|
let context = context ?? viewContext
|
||||||
let request: NSFetchRequest<RelationshipMO> = RelationshipMO.fetchRequest()
|
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="">
|
<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">
|
<entity name="Account" representedClassName="AccountMO" syncable="YES">
|
||||||
<attribute name="acct" attributeType="String"/>
|
<attribute name="acct" attributeType="String"/>
|
||||||
|
<attribute name="active" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||||
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
<attribute name="avatar" optional="YES" attributeType="URI"/>
|
||||||
<attribute name="botCD" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
<attribute name="botCD" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||||
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="createdAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
|
Loading…
Reference in New Issue