Browse Source

Don't cache attachments to disk, only avatars and headers

pixelfed
Shadowfacts 3 years ago
parent
commit
86d064dc6e
Signed by: shadowfacts GPG Key ID: 94A5AB95422746E5
  1. 14
      Tusker.xcodeproj/project.pbxproj
  2. 50
      Tusker/Caching/Cache.swift
  3. 35
      Tusker/Caching/ImageCache.swift

14
Tusker.xcodeproj/project.pbxproj

@ -134,6 +134,7 @@
D6E0DC8E216EDF1E00369478 /* Previewing.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E0DC8D216EDF1E00369478 /* Previewing.swift */; };
D6E6F26321603F8B006A8599 /* CharacterCounter.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26221603F8B006A8599 /* CharacterCounter.swift */; };
D6E6F26521604242006A8599 /* CharacterCounterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6E6F26421604242006A8599 /* CharacterCounterTests.swift */; };
D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F1F84C2193B56E00F5FE67 /* Cache.swift */; };
D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */; };
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EF21251A2900CF0F2B /* MastodonController.swift */; };
/* End PBXBuildFile section */
@ -333,6 +334,7 @@
D6E0DC8D216EDF1E00369478 /* Previewing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Previewing.swift; sourceTree = "<group>"; };
D6E6F26221603F8B006A8599 /* CharacterCounter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounter.swift; sourceTree = "<group>"; };
D6E6F26421604242006A8599 /* CharacterCounterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CharacterCounterTests.swift; sourceTree = "<group>"; };
D6F1F84C2193B56E00F5FE67 /* Cache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cache.swift; sourceTree = "<group>"; };
D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
D6F953EF21251A2900CF0F2B /* MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -773,9 +775,9 @@
D627FF73217BBC9700CC0648 /* AppRouter.swift */,
D64D0AAC2128D88B005A6F37 /* LocalData.swift */,
D627FF75217E923E00CC0648 /* DraftsManager.swift */,
04DACE8D212CC7CC009840C4 /* ImageCache.swift */,
D6028B9A2150811100F223B9 /* MastodonCache.swift */,
D6C693EE216192C2007D6A6D /* TuskerNavigationDelegate.swift */,
D6F1F84E2193B9BE00F5FE67 /* Caching */,
D6757A7A2157E00100721E32 /* XCallbackURL */,
D62D241E217AA46B005076CC /* Shortcuts */,
D663626021360A9600C9CBA2 /* Preferences */,
@ -808,6 +810,15 @@
path = TuskerUITests;
sourceTree = "<group>";
};
D6F1F84E2193B9BE00F5FE67 /* Caching */ = {
isa = PBXGroup;
children = (
D6F1F84C2193B56E00F5FE67 /* Cache.swift */,
04DACE8D212CC7CC009840C4 /* ImageCache.swift */,
);
path = Caching;
sourceTree = "<group>";
};
D6F953F121251A2F00CF0F2B /* Controllers */ = {
isa = PBXGroup;
children = (
@ -1188,6 +1199,7 @@
D641C773213CAA25004B4513 /* NotificationsTableViewController.swift in Sources */,
D6757A7C2157E01900721E32 /* XCBManager.swift in Sources */,
D6C693CF216125FC007D6A6D /* SilentActionPermissionTableViewCell.swift in Sources */,
D6F1F84D2193B56E00F5FE67 /* Cache.swift in Sources */,
D6757A7E2157E02600721E32 /* XCBRequestSpec.swift in Sources */,
D667E5F12134D5050057A976 /* UIViewController+Delegates.swift in Sources */,
D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */,

50
Tusker/Caching/Cache.swift

@ -0,0 +1,50 @@
//
// Cache.swift
// Tusker
//
// Created by Shadowfacts on 11/7/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import Foundation
import Cache
/// Wrapper around Cache library that provides an API for transparently using any storage type
enum Cache<T> {
case memory(MemoryStorage<T>)
case disk(DiskStorage<T>)
case hybrid(HybridStorage<T>)
func existsObject(forKey key: String) throws -> Bool {
switch self {
case let .memory(memory):
return try memory.existsObject(forKey: key)
case let .disk(disk):
return try disk.existsObject(forKey: key)
case let .hybrid(hybrid):
return try hybrid.existsObject(forKey: key)
}
}
func object(forKey key: String) throws -> T {
switch self {
case let .memory(memory):
return try memory.object(forKey: key)
case let .disk(disk):
return try disk.object(forKey: key)
case let .hybrid(hybrid):
return try hybrid.object(forKey: key)
}
}
func setObject(_ object: T, forKey key: String, expiry: Expiry? = nil) throws {
switch self {
case let .memory(memory):
memory.setObject(object, forKey: key, expiry: expiry)
case let .disk(disk):
try disk.setObject(object, forKey: key, expiry: expiry)
case let .hybrid(hybrid):
try hybrid.setObject(object, forKey: key, expiry: expiry)
}
}
}

35
Tusker/ImageCache.swift → Tusker/Caching/ImageCache.swift

@ -11,25 +11,34 @@ import Cache
class ImageCache {
static let avatars = ImageCache(name: "Avatars")
static let headers = ImageCache(name: "Headers")
static let attachments = ImageCache(name: "Attachments", diskExpiry: .seconds(60 * 60), memoryExpiry: .seconds(60))
static let avatars = ImageCache(name: "Avatars", memoryExpiry: .seconds(60 * 60), diskExpiry: .seconds(60 * 60 * 24))
static let headers = ImageCache(name: "Headers", memoryExpiry: .seconds(60 * 60), diskExpiry: .seconds(60 * 60 * 24))
static let attachments = ImageCache(name: "Attachments", memoryExpiry: .seconds(60 * 2))
let storage: Storage<UIImage>
let cache: Cache<UIImage>
var requests = [URL: Request]()
init(name: String, diskExpiry: Expiry = .seconds(60 * 60 * 24), memoryExpiry: Expiry = .seconds(60 * 60)) {
self.storage = try! Storage(
diskConfig: DiskConfig(name: name, expiry: diskExpiry),
memoryConfig: MemoryConfig(expiry: memoryExpiry),
transformer: TransformerFactory.forImage())
init(name: String, memoryExpiry expiry: Expiry) {
let storage = MemoryStorage<UIImage>(config: MemoryConfig(expiry: expiry))
self.cache = .memory(storage)
}
init(name: String, diskExpiry expiry: Expiry) {
let storage = try! DiskStorage<UIImage>(config: DiskConfig(name: name, expiry: expiry), transformer: TransformerFactory.forImage())
self.cache = .disk(storage)
}
init(name: String, memoryExpiry: Expiry, diskExpiry: Expiry) {
let memory = MemoryStorage<UIImage>(config: MemoryConfig(expiry: memoryExpiry))
let disk = try! DiskStorage<UIImage>(config: DiskConfig(name: name, expiry: diskExpiry), transformer: TransformerFactory.forImage())
self.cache = .hybrid(HybridStorage(memoryStorage: memory, diskStorage: disk))
}
func get(_ url: URL, completion: ((UIImage?) -> Void)?) {
let key = url.absoluteString
if (try? storage.existsObject(forKey: key)) ?? false,
let image = try? storage.object(forKey: key) {
if (try? cache.existsObject(forKey: key)) ?? false,
let image = try? cache.object(forKey: key) {
completion?(image)
} else {
if let completion = completion, let request = requests[url] {
@ -38,14 +47,14 @@ class ImageCache {
let request = Request(url: url, completion: completion)
requests[url] = request
request.run { (image) in
try? self.storage.setObject(image, forKey: key)
try? self.cache.setObject(image, forKey: key)
}
}
}
}
func get(_ url: URL) -> UIImage? {
return try? storage.object(forKey: url.absoluteString)
return try? cache.object(forKey: url.absoluteString)
}
func cancel(_ url: URL) {
Loading…
Cancel
Save