1a6c17e308
This commit moves Kingfisher data to Apple's designated caches folder to avoid it from being backed up to iCloud. Closes: https://github.com/damus-io/damus/issues/2993 Changelog-Fixed: Fixed issue where cached images would be backed up to iCloud Signed-off-by: Daniel D’Aquino <daniel@daquino.me>
80 lines
3.6 KiB
Swift
80 lines
3.6 KiB
Swift
//
|
||
// ImageCacheMigrations.swift
|
||
// damus
|
||
//
|
||
// Created by Daniel D’Aquino on 2025-04-26.
|
||
//
|
||
|
||
import Foundation
|
||
import Kingfisher
|
||
|
||
struct ImageCacheMigrations {
|
||
static func migrateKingfisherCacheIfNeeded() {
|
||
let fileManager = FileManager.default
|
||
let defaults = UserDefaults.standard
|
||
let migration1Key = "KingfisherCacheMigrated" // Never ever changes
|
||
let migration2Key = "KingfisherCacheMigratedV2" // Never ever changes
|
||
|
||
let migration1Done = defaults.bool(forKey: migration1Key)
|
||
let migration2Done = defaults.bool(forKey: migration2Key)
|
||
|
||
guard !migration1Done || !migration2Done else {
|
||
// All migrations are already done. Skip.
|
||
return
|
||
}
|
||
|
||
let oldCachePath = migration1Done ? migration1KingfisherCachePath() : migration0KingfisherCachePath()
|
||
|
||
// New shared cache location
|
||
let newCachePath = kingfisherCachePath().path
|
||
|
||
if fileManager.fileExists(atPath: oldCachePath) {
|
||
do {
|
||
// Move the old cache to the new location
|
||
try fileManager.moveItem(atPath: oldCachePath, toPath: newCachePath)
|
||
Log.info("Successfully migrated Kingfisher cache to %s", for: .storage, newCachePath)
|
||
} catch {
|
||
do {
|
||
// Cache data is not essential, fallback to deleting the cache and starting all over
|
||
// It's better than leaving significant garbage data stuck indefinitely on the user's phone
|
||
try fileManager.removeItem(atPath: newCachePath)
|
||
try fileManager.removeItem(atPath: oldCachePath)
|
||
}
|
||
catch {
|
||
Log.error("Failed to migrate cache: %s", for: .storage, error.localizedDescription)
|
||
return // Do not mark them as complete, we can try again next time the user reloads the app
|
||
}
|
||
}
|
||
}
|
||
|
||
// Mark migrations as complete
|
||
defaults.set(true, forKey: migration1Key)
|
||
defaults.set(true, forKey: migration2Key)
|
||
}
|
||
|
||
static private func migration0KingfisherCachePath() -> String {
|
||
// Implementation note: These are old, so they should not be changed
|
||
let defaultCache = ImageCache.default
|
||
return defaultCache.diskStorage.directoryURL.path
|
||
}
|
||
|
||
static private func migration1KingfisherCachePath() -> String {
|
||
// Implementation note: These are old, so they are hard-coded on purpose, because we can't change these values from the past.
|
||
let groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.damus")!
|
||
return groupURL.appendingPathComponent("ImageCache").path
|
||
}
|
||
|
||
/// The latest path for kingfisher to store cached images on.
|
||
///
|
||
/// Documentation references:
|
||
/// - https://developer.apple.com/documentation/foundation/filemanager/containerurl(forsecurityapplicationgroupidentifier:)#:~:text=The%20system%20creates%20only%20the%20Library/Caches%20subdirectory%20automatically
|
||
/// - https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html#:~:text=Put%20data%20cache,files%20as%20needed.
|
||
static func kingfisherCachePath() -> URL {
|
||
let groupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.DAMUS_APP_GROUP_IDENTIFIER)!
|
||
return groupURL
|
||
.appendingPathComponent("Library")
|
||
.appendingPathComponent("Caches")
|
||
.appendingPathComponent(Constants.IMAGE_CACHE_DIRNAME)
|
||
}
|
||
}
|