Implement MastodonAccountInMemoryCache (I)OS-140)

This commit is contained in:
Marcus Kida 2023-05-09 11:15:24 +02:00
parent 9d2e8eca16
commit c7c635d32a
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
5 changed files with 84 additions and 7 deletions

View File

@ -22,8 +22,8 @@ extension FollowingListViewModel {
configuration: UserSection.Configuration(
userTableViewCellDelegate: userTableViewCellDelegate
),
followedUsers: followedUserIds.eraseToAnyPublisher(),
blockedUsers: blockedUserIds.eraseToAnyPublisher()
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher()
)
// workaround to append loader wrong animation issue

View File

@ -69,7 +69,8 @@ extension SendPostIntentHandler: SendPostIntentHandling {
domain: authentication.domain,
userID: authentication.userID,
appAuthorization: .init(accessToken: authentication.appAccessToken),
userAuthorization: .init(accessToken: authentication.userAccessToken)
userAuthorization: .init(accessToken: authentication.userAccessToken),
inMemoryCache: .sharedCache(for: authentication.objectID.description)
)
}

View File

@ -15,19 +15,22 @@ public struct MastodonAuthenticationBox: UserIdentifier {
public let userID: MastodonUser.ID
public let appAuthorization: Mastodon.API.OAuth.Authorization
public let userAuthorization: Mastodon.API.OAuth.Authorization
public let inMemoryCache: MastodonAccountInMemoryCache
public init(
authenticationRecord: ManagedObjectRecord<MastodonAuthentication>,
domain: String,
userID: MastodonUser.ID,
appAuthorization: Mastodon.API.OAuth.Authorization,
userAuthorization: Mastodon.API.OAuth.Authorization
userAuthorization: Mastodon.API.OAuth.Authorization,
inMemoryCache: MastodonAccountInMemoryCache
) {
self.authenticationRecord = authenticationRecord
self.domain = domain
self.userID = userID
self.appAuthorization = appAuthorization
self.userAuthorization = userAuthorization
self.inMemoryCache = inMemoryCache
}
}
@ -39,8 +42,26 @@ extension MastodonAuthenticationBox {
domain: authentication.domain,
userID: authentication.userID,
appAuthorization: Mastodon.API.OAuth.Authorization(accessToken: authentication.appAccessToken),
userAuthorization: Mastodon.API.OAuth.Authorization(accessToken: authentication.userAccessToken)
userAuthorization: Mastodon.API.OAuth.Authorization(accessToken: authentication.userAccessToken),
inMemoryCache: .sharedCache(for: authentication.objectID.description)
)
}
}
public class MastodonAccountInMemoryCache {
@Published public var followingUserIds: [String] = []
@Published public var blockedUserIds: [String] = []
static var sharedCaches = [String: MastodonAccountInMemoryCache]()
public static func sharedCache(for key: String) -> MastodonAccountInMemoryCache {
if let sharedCache = sharedCaches[key] {
return sharedCache
}
let sharedCache = MastodonAccountInMemoryCache()
sharedCaches[key] = sharedCache
return sharedCache
}
}

View File

@ -12,6 +12,8 @@ import CoreData
import CoreDataStack
import MastodonSDK
private typealias IterativeResponse = (ids: [String], maxID: String?)
public final class AuthenticationService: NSObject {
var disposeBag = Set<AnyCancellable>()
@ -25,6 +27,46 @@ public final class AuthenticationService: NSObject {
// output
@Published public var mastodonAuthentications: [ManagedObjectRecord<MastodonAuthentication>] = []
@Published public var mastodonAuthenticationBoxes: [MastodonAuthenticationBox] = []
private func fetchFollowedBlockedUserIds(
_ authBox: MastodonAuthenticationBox,
_ previousFollowingIDs: [String]? = nil,
_ maxID: String? = nil
) async throws {
guard let apiService = apiService else { return }
let followingResponse = try await fetchFollowing(maxID, apiService, authBox)
let followingIds = (previousFollowingIDs ?? []) + followingResponse.ids
if let nextMaxID = followingResponse.maxID {
return try await fetchFollowedBlockedUserIds(authBox, followingIds, nextMaxID)
}
let blockedIds = try await apiService.getBlocked(
authenticationBox: authBox
).value.map { $0.id }
authBox.inMemoryCache.followingUserIds = followingIds
authBox.inMemoryCache.blockedUserIds = blockedIds
}
private func fetchFollowing(
_ maxID: String?,
_ apiService: APIService,
_ mastodonAuthenticationBox: MastodonAuthenticationBox
) async throws -> IterativeResponse {
let response = try await apiService.following(
userID: mastodonAuthenticationBox.userID,
maxID: maxID,
authenticationBox: mastodonAuthenticationBox
)
let ids: [String] = response.value.map { $0.id }
let maxID: String? = response.link?.maxID
return (ids, maxID)
}
public let updateActiveUserAccountPublisher = PassthroughSubject<Void, Never>()
init(
@ -50,6 +92,18 @@ public final class AuthenticationService: NSObject {
super.init()
mastodonAuthenticationFetchedResultsController.delegate = self
$mastodonAuthenticationBoxes
.sink { [weak self] boxes in
Task { [weak self] in
for authBox in boxes {
do { try await self?.fetchFollowedBlockedUserIds(authBox) }
catch {}
}
}
}
.store(in: &disposeBag)
// TODO: verify credentials for active authentication

View File

@ -267,7 +267,8 @@ extension NotificationService {
domain: authentication.domain,
userID: authentication.userID,
appAuthorization: .init(accessToken: authentication.appAccessToken),
userAuthorization: .init(accessToken: authentication.userAccessToken)
userAuthorization: .init(accessToken: authentication.userAccessToken),
inMemoryCache: .sharedCache(for: authentication.objectID.description)
)
}
}