Purge cache (IOS-14)

This commit is contained in:
Nathan Mattes 2023-06-28 09:02:14 +02:00
parent 951f46353f
commit 6b12224578
3 changed files with 70 additions and 82 deletions

View File

@ -10,7 +10,7 @@ protocol AboutViewControllerDelegate: AnyObject {
class AboutViewController: UIViewController {
let tableView: UITableView
let sections: [AboutSettingsSection]
private(set) var sections: [AboutSettingsSection] = []
var tableViewDataSource: UITableViewDiffableDataSource<AboutSettingsSection, AboutSettingsEntry>?
weak var delegate: AboutViewControllerDelegate?
@ -20,17 +20,6 @@ class AboutViewController: UIViewController {
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(AboutMastodonTableViewCell.self, forCellReuseIdentifier: AboutMastodonTableViewCell.reuseIdentifier)
sections = [
AboutSettingsSection(entries: [
.evenMoreSettings,
.contributeToMastodon,
.privacyPolicy
]),
AboutSettingsSection(entries: [
.clearMediaCache(AppContext.shared.currentDiskUsage())
])
]
super.init(nibName: nil, bundle: nil)
let tableViewDataSource = UITableViewDiffableDataSource<AboutSettingsSection, AboutSettingsEntry>(tableView: tableView) { [weak self] tableView, indexPath, itemIdentifier in
@ -58,6 +47,20 @@ class AboutViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
update(with:
[AboutSettingsSection(entries: [
.evenMoreSettings,
.contributeToMastodon,
.privacyPolicy
]),
AboutSettingsSection(entries: [
.clearMediaCache(AppContext.shared.currentDiskUsage())
])]
)
}
func update(with sections: [AboutSettingsSection]) {
self.sections = sections
var snapshot = NSDiffableDataSourceSnapshot<AboutSettingsSection, AboutSettingsEntry>()
@ -66,7 +69,7 @@ class AboutViewController: UIViewController {
snapshot.appendItems(section.entries)
}
tableViewDataSource?.apply(snapshot)
tableViewDataSource?.apply(snapshot, animatingDifferences: false)
}
}

View File

@ -2,6 +2,7 @@
import UIKit
import AuthenticationServices
import MastodonCore
protocol SettingsCoordinatorDelegate: AnyObject {
func logout(_ settingsCoordinator: SettingsCoordinator)
@ -71,9 +72,18 @@ extension SettingsCoordinator: AboutViewControllerDelegate {
case .privacyPolicy:
delegate?.openPrivacyURL(self)
case .clearMediaCache(_):
//TODO: appContext.purgeCache()
//FIXME: maybe we should inject an AppContext/AuthContext here instead of delegating everything to SceneCoordinator?
break
AppContext.shared.purgeCache()
viewController.update(with:
[AboutSettingsSection(entries: [
.evenMoreSettings,
.contributeToMastodon,
.privacyPolicy
]),
AboutSettingsSection(entries: [
.clearMediaCache(AppContext.shared.currentDiskUsage())
])]
)
}
}
}

View File

@ -126,76 +126,51 @@ extension AppContext {
return formatter
}()
private static let purgeCacheWorkingQueue = DispatchQueue(label: "org.joinmastodon.app.AppContext.purgeCacheWorkingQueue")
public func purgeCache() -> AnyPublisher<ByteCount, Never> {
Publishers.MergeMany([
AppContext.purgeAlamofireImageCache(),
AppContext.purgeTemporaryDirectory(),
])
.reduce(0, +)
.eraseToAnyPublisher()
public func purgeCache() {
ImageDownloader.defaultURLCache().removeAllCachedResponses()
let fileManager = FileManager.default
let temporaryDirectoryURL = fileManager.temporaryDirectory
let fileKeys: [URLResourceKey] = [.fileSizeKey, .isDirectoryKey]
if let directoryEnumerator = fileManager.enumerator(
at: temporaryDirectoryURL,
includingPropertiesForKeys: fileKeys,
options: .skipsHiddenFiles) {
for case let fileURL as URL in directoryEnumerator {
guard let resourceValues = try? fileURL.resourceValues(forKeys: Set(fileKeys)),
resourceValues.isDirectory == false else {
continue
}
try? fileManager.removeItem(at: fileURL)
}
}
}
// In Bytes
public func currentDiskUsage() -> Int {
let alamoFireDiskBytes = ImageDownloader.defaultURLCache().currentDiskUsage
//TODO: Add temp directory files
return alamoFireDiskBytes
}
private static func purgeAlamofireImageCache() -> AnyPublisher<ByteCount, Never> {
Future<ByteCount, Never> { promise in
AppContext.purgeCacheWorkingQueue.async {
// clean image cache for AlamofireImage
let diskBytes = ImageDownloader.defaultURLCache().currentDiskUsage
ImageDownloader.defaultURLCache().removeAllCachedResponses()
let currentDiskBytes = ImageDownloader.defaultURLCache().currentDiskUsage
let purgedDiskBytes = max(0, diskBytes - currentDiskBytes)
promise(.success(purgedDiskBytes))
}
}
.eraseToAnyPublisher()
}
private static func purgeTemporaryDirectory() -> AnyPublisher<ByteCount, Never> {
Future<ByteCount, Never> { promise in
AppContext.purgeCacheWorkingQueue.async {
let fileManager = FileManager.default
let temporaryDirectoryURL = fileManager.temporaryDirectory
let resourceKeys = Set<URLResourceKey>([.fileSizeKey, .isDirectoryKey])
guard let directoryEnumerator = fileManager.enumerator(
at: temporaryDirectoryURL,
includingPropertiesForKeys: Array(resourceKeys),
options: .skipsHiddenFiles
) else {
promise(.success(0))
return
}
var fileURLs: [URL] = []
var totalFileSizeInBytes = 0
for case let fileURL as URL in directoryEnumerator {
guard let resourceValues = try? fileURL.resourceValues(forKeys: resourceKeys),
let isDirectory = resourceValues.isDirectory else {
continue
}
guard !isDirectory else {
continue
}
fileURLs.append(fileURL)
totalFileSizeInBytes += resourceValues.fileSize ?? 0
}
for fileURL in fileURLs {
try? fileManager.removeItem(at: fileURL)
}
promise(.success(totalFileSizeInBytes))
}
}
.eraseToAnyPublisher()
}
var tempFilesDiskBytes = 0
let fileManager = FileManager.default
let temporaryDirectoryURL = fileManager.temporaryDirectory
let fileKeys: [URLResourceKey] = [.fileSizeKey, .isDirectoryKey]
if let directoryEnumerator = fileManager.enumerator(
at: temporaryDirectoryURL,
includingPropertiesForKeys: fileKeys,
options: .skipsHiddenFiles) {
for case let fileURL as URL in directoryEnumerator {
guard let resourceValues = try? fileURL.resourceValues(forKeys: Set(fileKeys)),
resourceValues.isDirectory == false else {
continue
}
tempFilesDiskBytes += resourceValues.fileSize ?? 0
}
}
return alamoFireDiskBytes + tempFilesDiskBytes
}
}