2023-12-04 11:04:00 +01:00
|
|
|
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
|
|
|
|
|
|
|
import Foundation
|
|
|
|
import MastodonSDK
|
|
|
|
|
2024-01-11 14:10:47 +01:00
|
|
|
public extension FileManager {
|
|
|
|
|
2023-12-04 11:04:00 +01:00
|
|
|
// Retrieve
|
2024-01-11 14:10:47 +01:00
|
|
|
func cachedHomeTimeline(for userId: UserIdentifier) throws -> [MastodonStatus] {
|
2023-12-04 11:04:00 +01:00
|
|
|
try cached(timeline: .homeTimeline(userId)).map(MastodonStatus.fromEntity)
|
|
|
|
}
|
2024-01-11 14:10:47 +01:00
|
|
|
|
|
|
|
func cachedNotificationsAll(for userId: UserIdentifier) throws -> [Mastodon.Entity.Notification] {
|
2023-12-04 11:04:00 +01:00
|
|
|
try cached(timeline: .notificationsAll(userId))
|
|
|
|
}
|
2024-01-11 14:10:47 +01:00
|
|
|
|
|
|
|
func cachedNotificationsMentions(for userId: UserIdentifier) throws -> [Mastodon.Entity.Notification] {
|
2023-12-04 11:04:00 +01:00
|
|
|
try cached(timeline: .notificationsMentions(userId))
|
|
|
|
}
|
|
|
|
|
2024-01-11 14:10:47 +01:00
|
|
|
// Create
|
|
|
|
func cacheHomeTimeline(items: [MastodonStatus], for userIdentifier: UserIdentifier) {
|
|
|
|
cache(items.map { $0.entity }, timeline: .homeTimeline(userIdentifier))
|
|
|
|
}
|
|
|
|
|
|
|
|
func cacheNotificationsAll(items: [Mastodon.Entity.Notification], for userIdentifier: UserIdentifier) {
|
|
|
|
cache(items, timeline: .notificationsAll(userIdentifier))
|
|
|
|
}
|
|
|
|
|
|
|
|
func cacheNotificationsMentions(items: [Mastodon.Entity.Notification], for userIdentifier: UserIdentifier) {
|
|
|
|
cache(items, timeline: .notificationsMentions(userIdentifier))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete
|
|
|
|
func invalidateHomeTimelineCache(for userId: UserIdentifier) {
|
|
|
|
invalidate(timeline: .homeTimeline(userId))
|
|
|
|
}
|
|
|
|
|
|
|
|
func invalidateNotificationsAll(for userId: UserIdentifier) {
|
|
|
|
invalidate(timeline: .notificationsAll(userId))
|
|
|
|
}
|
|
|
|
|
|
|
|
func invalidateNotificationsMentions(for userId: UserIdentifier) {
|
|
|
|
invalidate(timeline: .notificationsMentions(userId))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private extension FileManager {
|
|
|
|
static let cacheItemsLimit: Int = 100 // max number of items to cache
|
|
|
|
|
|
|
|
func cached<T: Decodable>(timeline: Persistence) throws -> [T] {
|
2023-12-04 11:04:00 +01:00
|
|
|
guard let cachesDirectory else { return [] }
|
|
|
|
|
|
|
|
let filePath = timeline.filepath(baseURL: cachesDirectory)
|
|
|
|
|
|
|
|
guard let data = try? Data(contentsOf: filePath) else { return [] }
|
|
|
|
|
|
|
|
do {
|
|
|
|
let items = try JSONDecoder().decode([T].self, from: data)
|
|
|
|
|
|
|
|
return items
|
|
|
|
} catch {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-11 14:10:47 +01:00
|
|
|
|
|
|
|
func cache<T: Encodable>(_ items: [T], timeline: Persistence) {
|
2023-12-04 11:04:00 +01:00
|
|
|
guard let cachesDirectory else { return }
|
|
|
|
|
|
|
|
let processableItems: [T]
|
|
|
|
if items.count > Self.cacheItemsLimit {
|
|
|
|
processableItems = items.dropLast(items.count - Self.cacheItemsLimit)
|
|
|
|
} else {
|
|
|
|
processableItems = items
|
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
|
|
|
let data = try JSONEncoder().encode(processableItems)
|
|
|
|
|
|
|
|
let filePath = timeline.filepath(baseURL: cachesDirectory)
|
|
|
|
try data.write(to: filePath)
|
|
|
|
} catch {
|
|
|
|
debugPrint(error.localizedDescription)
|
|
|
|
}
|
|
|
|
}
|
2024-01-11 14:10:47 +01:00
|
|
|
|
|
|
|
func invalidate(timeline: Persistence) {
|
2023-12-04 11:04:00 +01:00
|
|
|
guard let cachesDirectory else { return }
|
|
|
|
|
|
|
|
let filePath = timeline.filepath(baseURL: cachesDirectory)
|
|
|
|
|
|
|
|
try? removeItem(at: filePath)
|
|
|
|
}
|
|
|
|
}
|