Tie JSON cache to domain based unique identifier

This commit is contained in:
Marcus Kida 2023-12-27 10:35:00 +01:00
parent 275fa53f80
commit 82cc0f2f3f
No known key found for this signature in database
GPG Key ID: 19FF64E08013CA40
6 changed files with 40 additions and 36 deletions

View File

@ -626,10 +626,10 @@ extension SceneCoordinator: SettingsCoordinatorDelegate {
try await self.appContext.authenticationService.signOutMastodonUser(
authenticationBox: authContext.mastodonAuthenticationBox
)
let userId = authContext.mastodonAuthenticationBox.userID
FileManager.default.invalidateHomeTimelineCache(for: userId)
FileManager.default.invalidateNotificationsAll(for: userId)
FileManager.default.invalidateNotificationsMentions(for: userId)
let userIdentifier = authContext.mastodonAuthenticationBox
FileManager.default.invalidateHomeTimelineCache(for: userIdentifier)
FileManager.default.invalidateNotificationsAll(for: userIdentifier)
FileManager.default.invalidateNotificationsMentions(for: userIdentifier)
self.setup()
}

View File

@ -8,15 +8,15 @@ extension FileManager {
private static let cacheItemsLimit: Int = 100 // max number of items to cache
// Retrieve
func cachedHomeTimeline(for userId: String) throws -> [MastodonStatus] {
func cachedHomeTimeline(for userId: UserIdentifier) throws -> [MastodonStatus] {
try cached(timeline: .homeTimeline(userId)).map(MastodonStatus.fromEntity)
}
func cachedNotificationsAll(for userId: String) throws -> [Mastodon.Entity.Notification] {
func cachedNotificationsAll(for userId: UserIdentifier) throws -> [Mastodon.Entity.Notification] {
try cached(timeline: .notificationsAll(userId))
}
func cachedNotificationsMentions(for userId: String) throws -> [Mastodon.Entity.Notification] {
func cachedNotificationsMentions(for userId: UserIdentifier) throws -> [Mastodon.Entity.Notification] {
try cached(timeline: .notificationsMentions(userId))
}
@ -38,16 +38,16 @@ extension FileManager {
}
// Create
func cacheHomeTimeline(items: [MastodonStatus], for userId: String) {
cache(items.map { $0.entity }, timeline: .homeTimeline(userId))
func cacheHomeTimeline(items: [MastodonStatus], for userIdentifier: UserIdentifier) {
cache(items.map { $0.entity }, timeline: .homeTimeline(userIdentifier))
}
func cacheNotificationsAll(items: [Mastodon.Entity.Notification], for userId: String) {
cache(items, timeline: .notificationsAll(userId))
func cacheNotificationsAll(items: [Mastodon.Entity.Notification], for userIdentifier: UserIdentifier) {
cache(items, timeline: .notificationsAll(userIdentifier))
}
func cacheNotificationsMentions(items: [Mastodon.Entity.Notification], for userId: String) {
cache(items, timeline: .notificationsMentions(userId))
func cacheNotificationsMentions(items: [Mastodon.Entity.Notification], for userIdentifier: UserIdentifier) {
cache(items, timeline: .notificationsMentions(userIdentifier))
}
private func cache<T: Encodable>(_ items: [T], timeline: Persistence) {
@ -71,15 +71,15 @@ extension FileManager {
}
// Delete
func invalidateHomeTimelineCache(for userId: String) {
func invalidateHomeTimelineCache(for userId: UserIdentifier) {
invalidate(timeline: .homeTimeline(userId))
}
func invalidateNotificationsAll(for userId: String) {
func invalidateNotificationsAll(for userId: UserIdentifier) {
invalidate(timeline: .notificationsAll(userId))
}
func invalidateNotificationsMentions(for userId: String) {
func invalidateNotificationsMentions(for userId: UserIdentifier) {
invalidate(timeline: .notificationsMentions(userId))
}

View File

@ -386,10 +386,10 @@ extension HomeTimelineViewController {
@objc func signOutAction(_ sender: UIAction) {
Task { @MainActor in
try await context.authenticationService.signOutMastodonUser(authenticationBox: viewModel.authContext.mastodonAuthenticationBox)
let userId = viewModel.authContext.mastodonAuthenticationBox.userID
FileManager.default.invalidateHomeTimelineCache(for: userId)
FileManager.default.invalidateNotificationsAll(for: userId)
FileManager.default.invalidateNotificationsMentions(for: userId)
let userIdentifier = viewModel.authContext.mastodonAuthenticationBox
FileManager.default.invalidateHomeTimelineCache(for: userIdentifier)
FileManager.default.invalidateNotificationsAll(for: userIdentifier)
FileManager.default.invalidateNotificationsMentions(for: userIdentifier)
self.coordinator.setup()
}
}

View File

@ -84,7 +84,7 @@ final class HomeTimelineViewModel: NSObject {
self.fetchedResultsController = FeedFetchedResultsController(context: context, authContext: authContext)
self.homeTimelineNavigationBarTitleViewModel = HomeTimelineNavigationBarTitleViewModel(context: context)
super.init()
self.fetchedResultsController.records = (try? FileManager.default.cachedHomeTimeline(for: authContext.mastodonAuthenticationBox.userID).map {
self.fetchedResultsController.records = (try? FileManager.default.cachedHomeTimeline(for: authContext.mastodonAuthenticationBox).map {
MastodonFeed.fromStatus($0, kind: .home)
}) ?? []
@ -111,7 +111,7 @@ final class HomeTimelineViewModel: NSObject {
guard let status = feed.status else { return nil }
return status
}
FileManager.default.cacheHomeTimeline(items: items, for: authContext.mastodonAuthenticationBox.userID)
FileManager.default.cacheHomeTimeline(items: items, for: authContext.mastodonAuthenticationBox)
})
.store(in: &disposeBag)

View File

@ -56,11 +56,11 @@ final class NotificationTimelineViewModel {
switch scope {
case .everything:
self.feedFetchedResultsController.records = (try? FileManager.default.cachedNotificationsAll(for: authContext.mastodonAuthenticationBox.userID))?.map({ notification in
self.feedFetchedResultsController.records = (try? FileManager.default.cachedNotificationsAll(for: authContext.mastodonAuthenticationBox))?.map({ notification in
MastodonFeed.fromNotification(notification, kind: .notificationAll)
}) ?? []
case .mentions:
self.feedFetchedResultsController.records = (try? FileManager.default.cachedNotificationsMentions(for: authContext.mastodonAuthenticationBox.userID))?.map({ notification in
self.feedFetchedResultsController.records = (try? FileManager.default.cachedNotificationsMentions(for: authContext.mastodonAuthenticationBox))?.map({ notification in
MastodonFeed.fromNotification(notification, kind: .notificationMentions)
}) ?? []
}
@ -75,9 +75,9 @@ final class NotificationTimelineViewModel {
}
switch self.scope {
case .everything:
FileManager.default.cacheNotificationsAll(items: items, for: authContext.mastodonAuthenticationBox.userID)
FileManager.default.cacheNotificationsAll(items: items, for: authContext.mastodonAuthenticationBox)
case .mentions:
FileManager.default.cacheNotificationsMentions(items: items, for: authContext.mastodonAuthenticationBox.userID)
FileManager.default.cacheNotificationsMentions(items: items, for: authContext.mastodonAuthenticationBox)
}
})
.store(in: &disposeBag)

View File

@ -10,20 +10,24 @@ import Foundation
public enum Persistence {
case searchHistory
case homeTimeline(String)
case notificationsMentions(String)
case notificationsAll(String)
case homeTimeline(UserIdentifier)
case notificationsMentions(UserIdentifier)
case notificationsAll(UserIdentifier)
private func uniqueUserDomainIdentifier(for userIdentifier: UserIdentifier) -> String {
"\(userIdentifier.userID)@\(userIdentifier.domain)"
}
private var filename: String {
switch self {
case .searchHistory:
return "search_history"
case let .homeTimeline(userId):
return "home_timeline_\(userId)"
case let .notificationsMentions(userId):
return "notifications_mentions_\(userId)"
case let .notificationsAll(userId):
return "notifications_all_\(userId)"
return "search_history" // todo: @zeitschlag should this be user-scoped as well?
case let .homeTimeline(userIdentifier):
return "home_timeline_\(uniqueUserDomainIdentifier(for: userIdentifier))"
case let .notificationsMentions(userIdentifier):
return "notifications_mentions_\(uniqueUserDomainIdentifier(for: userIdentifier))"
case let .notificationsAll(userIdentifier):
return "notifications_all_\(uniqueUserDomainIdentifier(for: userIdentifier))"
}
}