Replace Kingfisher with SDWebImage

This commit is contained in:
Justin Mazzocchi 2021-02-22 15:59:33 -08:00
parent 8b2acf1ace
commit 23a7725840
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
35 changed files with 215 additions and 250 deletions

View file

@ -1,7 +1,7 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
import Kingfisher
import SDWebImage
import ServiceLayer
struct ImageCacheConfiguration {
@ -14,19 +14,23 @@ struct ImageCacheConfiguration {
extension ImageCacheConfiguration {
func configure() throws {
KingfisherManager.shared.cache = try ImageCache(
name: Self.name,
cacheDirectoryURL: Self.directoryURL)
try KingfisherManager.shared.defaultOptions = [
.cacheSerializer(ImageCacheSerializer(service: .init(environment: environment)))
]
SDImageCache.defaultDiskCacheDirectory = Self.imageCacheDirectoryURL?.path
ImageDiskCache.service = try ImageSerializationService(environment: environment)
SDImageCacheConfig.default.diskCacheClass = ImageDiskCache.self
if let legacyImageCacheDirectoryURL = Self.legacyImageCacheDirectoryURL,
FileManager.default.fileExists(atPath: legacyImageCacheDirectoryURL.path) {
try? FileManager.default.removeItem(at: legacyImageCacheDirectoryURL)
}
}
}
private extension ImageCacheConfiguration {
static let name = "Images"
static let directoryURL = FileManager.default.containerURL(
static let cachesDirectoryURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: AppEnvironment.appGroup)?
.appendingPathComponent("Library")
.appendingPathComponent("Caches")
static let imageCacheDirectoryURL = cachesDirectoryURL?.appendingPathComponent("com.metabolist.metatext.images")
static let legacyImageCacheDirectoryURL =
cachesDirectoryURL?.appendingPathComponent("com.onevcat.Kingfisher.ImageCache.Images")
}

View file

@ -1,27 +0,0 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
import Kingfisher
import ServiceLayer
struct ImageCacheSerializer {
private let service: ImageSerializationService
init(service: ImageSerializationService) {
self.service = service
}
}
extension ImageCacheSerializer: CacheSerializer {
func data(with image: KFCrossPlatformImage, original: Data?) -> Data? {
guard let data = image.kf.data(format: original?.kf.imageFormat ?? .unknown) else { return nil }
return try? service.serialize(data: data)
}
func image(with data: Data, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
guard let deserialized = try? service.deserialize(data: data) else { return nil }
return KingfisherWrapper.image(data: deserialized, options: .init())
}
}

View file

@ -0,0 +1,39 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
import SDWebImage
import ServiceLayer
final class ImageDiskCache: SDDiskCache {
static var service: ImageSerializationService?
private let cachePath: String
required init?(cachePath: String, config: SDImageCacheConfig) {
self.cachePath = cachePath
super.init(cachePath: cachePath, config: config)
}
override func data(forKey key: String) -> Data? {
guard let data = super.data(forKey: key) else { return nil }
return try? Self.service?.deserialize(data: data)
}
override func setData(_ data: Data?, forKey key: String) {
guard let data = data else {
super.setData(nil, forKey: key)
return
}
super.setData(try? Self.service?.serialize(data: data), forKey: key)
}
override func cachePath(forKey key: String) -> String? {
guard let service = Self.service else { return super.cachePath(forKey: key) }
return (cachePath as NSString).appendingPathComponent(service.cacheKey(forKey: key))
}
}

View file

@ -1,15 +0,0 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
import Kingfisher
struct PrefetchRequestModifier: ImageDownloadRequestModifier {
func modified(for request: URLRequest) -> URLRequest? {
var mutableRequest = request
mutableRequest.allowsExpensiveNetworkAccess = false
mutableRequest.allowsConstrainedNetworkAccess = false
return request
}
}

View file

@ -1,6 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import Mastodon
import UIKit
import ViewModels
@ -12,17 +11,15 @@ extension NSMutableAttributedString {
while let tokenRange = string.range(of: token) {
let attachment = AnimatedTextAttachment()
let url: URL
if !identityContext.appPreferences.shouldReduceMotion,
identityContext.appPreferences.animateCustomEmojis {
url = emoji.url
attachment.imageURL = emoji.url
} else {
url = emoji.staticUrl
attachment.imageURL = emoji.staticUrl
}
attachment.accessibilityLabel = emoji.shortcode
attachment.kf.setImage(with: url, attributedView: view)
replaceCharacters(in: NSRange(tokenRange, in: string), with: NSAttributedString(attachment: attachment))
}
}

View file

@ -35,16 +35,15 @@
D021A69025C3E4B8008A0C0D /* EmojiContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07EC7E225B13DD3006DF726 /* EmojiContentConfiguration.swift */; };
D021A69525C3E4C1008A0C0D /* EmojiView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D07EC7F125B13E57006DF726 /* EmojiView.swift */; };
D021A6A625C3E584008A0C0D /* EditAttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05936E825AA3F3D00754FDF /* EditAttachmentView.swift */; };
D025B14625C4D26B001C69A8 /* ImageCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */; };
D025B14725C4D26B001C69A8 /* ImageCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */; };
D025B14D25C4E482001C69A8 /* ImageCacheConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */; };
D025B14E25C4E482001C69A8 /* ImageCacheConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */; };
D025B15B25C4EA7D001C69A8 /* ImageCacheConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */; };
D025B16025C4EA81001C69A8 /* ImageCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */; };
D025B16A25C4EB18001C69A8 /* ServiceLayer in Frameworks */ = {isa = PBXBuildFile; productRef = D025B16925C4EB18001C69A8 /* ServiceLayer */; };
D025B17025C4EB58001C69A8 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = D025B16F25C4EB58001C69A8 /* Kingfisher */; };
D025B17E25C500BC001C69A8 /* CapsuleButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D025B17D25C500BC001C69A8 /* CapsuleButton.swift */; };
D02E1F95250B13210071AD56 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02E1F94250B13210071AD56 /* SafariView.swift */; };
D035D8F925E4338D00E597C9 /* ImageDiskCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035D8F825E4338D00E597C9 /* ImageDiskCache.swift */; };
D035D8FE25E4339800E597C9 /* ImageDiskCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035D8F825E4338D00E597C9 /* ImageDiskCache.swift */; };
D035D90325E4388800E597C9 /* ImageDiskCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035D8F825E4338D00E597C9 /* ImageDiskCache.swift */; };
D035F86925B7F2ED00DC75ED /* MainNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035F86825B7F2ED00DC75ED /* MainNavigationViewController.swift */; };
D035F86F25B7F30E00DC75ED /* MainNavigationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035F86E25B7F30E00DC75ED /* MainNavigationView.swift */; };
D035F87D25B7F61600DC75ED /* TimelinesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D035F87C25B7F61600DC75ED /* TimelinesViewController.swift */; };
@ -60,9 +59,11 @@
D036EBB8259FE29800EC1CFC /* Status+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0849C7E25903C4900A5EBCC /* Status+Extensions.swift */; };
D036EBC2259FE2AD00EC1CFC /* UIVIewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E7AD3825870B13005F5E2D /* UIVIewController+Extensions.swift */; };
D03D87F425C23C44004DCBB2 /* SecondaryNavigationTitleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03D87F325C23C44004DCBB2 /* SecondaryNavigationTitleView.swift */; };
D0477F1525C68BAC005C5368 /* PrefetchRequestModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0477F1425C68BAC005C5368 /* PrefetchRequestModifier.swift */; };
D0477F2C25C6EBAD005C5368 /* OpenInDefaultBrowserActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0477F2B25C6EBAD005C5368 /* OpenInDefaultBrowserActivity.swift */; };
D0477F4625C72E50005C5368 /* CapsuleLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0477F4525C72E50005C5368 /* CapsuleLabel.swift */; };
D04F34B625E42ABE00714251 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = D04F34B525E42ABE00714251 /* SDWebImage */; };
D04F34BC25E42ADC00714251 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = D04F34BB25E42ADC00714251 /* SDWebImage */; };
D04F34C225E42AE500714251 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = D04F34C125E42AE500714251 /* SDWebImage */; };
D04F9E8E259E9C950081B0C9 /* ViewModels in Frameworks */ = {isa = PBXBuildFile; productRef = D04F9E8D259E9C950081B0C9 /* ViewModels */; };
D05936CF25A8D79800754FDF /* EditAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05936CE25A8D79800754FDF /* EditAttachmentViewController.swift */; };
D05936D025A8D79800754FDF /* EditAttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D05936CE25A8D79800754FDF /* EditAttachmentViewController.swift */; };
@ -206,8 +207,6 @@
D0F0B12E251A97E400942152 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0B12D251A97E400942152 /* TableViewController.swift */; };
D0F0B136251AA12700942152 /* CollectionItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0B135251AA12700942152 /* CollectionItem+Extensions.swift */; };
D0F4362D25C10B9600E4F896 /* AddIdentityViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F4362C25C10B9600E4F896 /* AddIdentityViewController.swift */; };
D0F5880525A7E4C500E3A49C /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = D0F5880425A7E4C500E3A49C /* Kingfisher */; };
D0F5880F25A7E6CC00E3A49C /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = D0F5880E25A7E6CC00E3A49C /* Kingfisher */; };
D0FCC105259C4E61000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
D0FCC106259C4E62000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
D0FE1C8F253686F9003EF1EB /* PlayerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FE1C8E253686F9003EF1EB /* PlayerView.swift */; };
@ -273,10 +272,10 @@
D021A61925C36C1A008A0C0D /* IdentityContentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdentityContentConfiguration.swift; sourceTree = "<group>"; };
D021A62B25C38570008A0C0D /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = "<group>"; };
D021A63525C38ADB008A0C0D /* AcknowledgmentsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgmentsView.swift; sourceTree = "<group>"; };
D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCacheSerializer.swift; sourceTree = "<group>"; };
D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageCacheConfiguration.swift; sourceTree = "<group>"; };
D025B17D25C500BC001C69A8 /* CapsuleButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsuleButton.swift; sourceTree = "<group>"; };
D02E1F94250B13210071AD56 /* SafariView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariView.swift; sourceTree = "<group>"; };
D035D8F825E4338D00E597C9 /* ImageDiskCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageDiskCache.swift; sourceTree = "<group>"; };
D035F86825B7F2ED00DC75ED /* MainNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationViewController.swift; sourceTree = "<group>"; };
D035F86E25B7F30E00DC75ED /* MainNavigationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationView.swift; sourceTree = "<group>"; };
D035F87C25B7F61600DC75ED /* TimelinesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesViewController.swift; sourceTree = "<group>"; };
@ -289,7 +288,6 @@
D036AA0B254B612B009094DF /* NotificationContentConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationContentConfiguration.swift; sourceTree = "<group>"; };
D036AA16254CA823009094DF /* StatusBodyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusBodyView.swift; sourceTree = "<group>"; };
D03D87F325C23C44004DCBB2 /* SecondaryNavigationTitleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondaryNavigationTitleView.swift; sourceTree = "<group>"; };
D0477F1425C68BAC005C5368 /* PrefetchRequestModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrefetchRequestModifier.swift; sourceTree = "<group>"; };
D0477F2B25C6EBAD005C5368 /* OpenInDefaultBrowserActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenInDefaultBrowserActivity.swift; sourceTree = "<group>"; };
D0477F4525C72E50005C5368 /* CapsuleLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapsuleLabel.swift; sourceTree = "<group>"; };
D047FA8C24C3E21200AF17C5 /* Metatext.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Metatext.app; sourceTree = BUILT_PRODUCTS_DIR; };
@ -434,8 +432,8 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D0F5880525A7E4C500E3A49C /* Kingfisher in Frameworks */,
D0E2C1D124FD97F000854680 /* ViewModels in Frameworks */,
D04F34B625E42ABE00714251 /* SDWebImage in Frameworks */,
D0FE7C8025C4C79F00203957 /* PreviewViewModels in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -451,7 +449,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D0F5880F25A7E6CC00E3A49C /* Kingfisher in Frameworks */,
D04F34BC25E42ADC00714251 /* SDWebImage in Frameworks */,
D04F9E8E259E9C950081B0C9 /* ViewModels in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -460,7 +458,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
D025B17025C4EB58001C69A8 /* Kingfisher in Frameworks */,
D04F34C225E42AE500714251 /* SDWebImage in Frameworks */,
D025B16A25C4EB18001C69A8 /* ServiceLayer in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -823,9 +821,8 @@
isa = PBXGroup;
children = (
D025B14C25C4E482001C69A8 /* ImageCacheConfiguration.swift */,
D025B14525C4D26A001C69A8 /* ImageCacheSerializer.swift */,
D0FE1C9725368A9D003EF1EB /* PlayerCache.swift */,
D0477F1425C68BAC005C5368 /* PrefetchRequestModifier.swift */,
D035D8F825E4338D00E597C9 /* ImageDiskCache.swift */,
);
path = Caches;
sourceTree = "<group>";
@ -852,8 +849,8 @@
name = Metatext;
packageProductDependencies = (
D0E2C1D024FD97F000854680 /* ViewModels */,
D0F5880425A7E4C500E3A49C /* Kingfisher */,
D0FE7C7F25C4C79F00203957 /* PreviewViewModels */,
D04F34B525E42ABE00714251 /* SDWebImage */,
);
productName = "Metatext (iOS)";
productReference = D047FA8C24C3E21200AF17C5 /* Metatext.app */;
@ -894,7 +891,7 @@
name = "Share Extension";
packageProductDependencies = (
D04F9E8D259E9C950081B0C9 /* ViewModels */,
D0F5880E25A7E6CC00E3A49C /* Kingfisher */,
D04F34BB25E42ADC00714251 /* SDWebImage */,
);
productName = "Share Extension";
productReference = D08E526C257C36CA00FA2C5F /* Share Extension.appex */;
@ -915,7 +912,7 @@
name = "Notification Service Extension";
packageProductDependencies = (
D025B16925C4EB18001C69A8 /* ServiceLayer */,
D025B16F25C4EB58001C69A8 /* Kingfisher */,
D04F34C125E42AE500714251 /* SDWebImage */,
);
productName = "Notification Service Extension";
productReference = D0E5361924E3EB4D00FB1CE1 /* Notification Service Extension.appex */;
@ -957,7 +954,7 @@
);
mainGroup = D047FA7F24C3E21000AF17C5;
packageReferences = (
D0F5880325A7E4C500E3A49C /* XCRemoteSwiftPackageReference "Kingfisher" */,
D04F34B425E42ABE00714251 /* XCRemoteSwiftPackageReference "SDWebImage" */,
);
productRefGroup = D047FA8D24C3E21200AF17C5 /* Products */;
projectDirPath = "";
@ -1060,7 +1057,6 @@
D0477F2C25C6EBAD005C5368 /* OpenInDefaultBrowserActivity.swift in Sources */,
D0DD50CB256B1F24004A04F7 /* ReportView.swift in Sources */,
D07F4D9825D493E300F61133 /* MuteView.swift in Sources */,
D0477F1525C68BAC005C5368 /* PrefetchRequestModifier.swift in Sources */,
D097F41B25BE3E1A00859F2C /* SearchScope+Extensions.swift in Sources */,
D0CEC10125E337C900FEF5A6 /* AnimatedTextAttachment.swift in Sources */,
D035F8B325B9616000DC75ED /* Timeline+Extensions.swift in Sources */,
@ -1080,6 +1076,7 @@
D021A60A25C36B32008A0C0D /* IdentityTableViewCell.swift in Sources */,
D0849C7F25903C4900A5EBCC /* Status+Extensions.swift in Sources */,
D0F4362D25C10B9600E4F896 /* AddIdentityViewController.swift in Sources */,
D035D8F925E4338D00E597C9 /* ImageDiskCache.swift in Sources */,
D0625E59250F092900502611 /* StatusTableViewCell.swift in Sources */,
D0E569DB2529319100FA1D72 /* LoadMoreView.swift in Sources */,
D05936FF25AA94EA00754FDF /* MarkAttachmentsSensitiveView.swift in Sources */,
@ -1136,7 +1133,6 @@
D036AA0C254B612B009094DF /* NotificationContentConfiguration.swift in Sources */,
D08B8D3D253F929E00B1EBEF /* ImageViewController.swift in Sources */,
D035F86925B7F2ED00DC75ED /* MainNavigationViewController.swift in Sources */,
D025B14625C4D26B001C69A8 /* ImageCacheSerializer.swift in Sources */,
D0B8510C25259E56004E0744 /* LoadMoreTableViewCell.swift in Sources */,
D08E52612579D2E100FA2C5F /* DomainBlocksView.swift in Sources */,
D01F41E424F8889700D55A2D /* AttachmentsView.swift in Sources */,
@ -1226,8 +1222,8 @@
D088406E25AFBBE200BB749B /* EmojiPickerViewController.swift in Sources */,
D0E39B8725D9B7FD009C10F8 /* AutocompleteDataSource.swift in Sources */,
D00CB23325C92F2D008EF267 /* Attachment+Extensions.swift in Sources */,
D035D8FE25E4339800E597C9 /* ImageDiskCache.swift in Sources */,
D0D93ECA25D9C76500C622ED /* AutocompleteItemView.swift in Sources */,
D025B14725C4D26B001C69A8 /* ImageCacheSerializer.swift in Sources */,
D036EBB8259FE29800EC1CFC /* Status+Extensions.swift in Sources */,
D021A6A625C3E584008A0C0D /* EditAttachmentView.swift in Sources */,
D0D93ED925D9CBE200C622ED /* AutocompleteItemCollectionViewCell.swift in Sources */,
@ -1241,9 +1237,9 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D035D90325E4388800E597C9 /* ImageDiskCache.swift in Sources */,
D0E5361C24E3EB4D00FB1CE1 /* NotificationService.swift in Sources */,
D025B15B25C4EA7D001C69A8 /* ImageCacheConfiguration.swift in Sources */,
D025B16025C4EA81001C69A8 /* ImageCacheSerializer.swift in Sources */,
D059376125ABE2E800754FDF /* XMLUnescaper.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1642,12 +1638,12 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
D0F5880325A7E4C500E3A49C /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
D04F34B425E42ABE00714251 /* XCRemoteSwiftPackageReference "SDWebImage" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher";
repositoryURL = "https://github.com/SDWebImage/SDWebImage";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.1.0;
minimumVersion = 5.10.4;
};
};
/* End XCRemoteSwiftPackageReference section */
@ -1657,10 +1653,20 @@
isa = XCSwiftPackageProductDependency;
productName = ServiceLayer;
};
D025B16F25C4EB58001C69A8 /* Kingfisher */ = {
D04F34B525E42ABE00714251 /* SDWebImage */ = {
isa = XCSwiftPackageProductDependency;
package = D0F5880325A7E4C500E3A49C /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
package = D04F34B425E42ABE00714251 /* XCRemoteSwiftPackageReference "SDWebImage" */;
productName = SDWebImage;
};
D04F34BB25E42ADC00714251 /* SDWebImage */ = {
isa = XCSwiftPackageProductDependency;
package = D04F34B425E42ABE00714251 /* XCRemoteSwiftPackageReference "SDWebImage" */;
productName = SDWebImage;
};
D04F34C125E42AE500714251 /* SDWebImage */ = {
isa = XCSwiftPackageProductDependency;
package = D04F34B425E42ABE00714251 /* XCRemoteSwiftPackageReference "SDWebImage" */;
productName = SDWebImage;
};
D04F9E8D259E9C950081B0C9 /* ViewModels */ = {
isa = XCSwiftPackageProductDependency;
@ -1670,16 +1676,6 @@
isa = XCSwiftPackageProductDependency;
productName = ViewModels;
};
D0F5880425A7E4C500E3A49C /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = D0F5880325A7E4C500E3A49C /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
};
D0F5880E25A7E6CC00E3A49C /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = D0F5880325A7E4C500E3A49C /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
};
D0FE7C7F25C4C79F00203957 /* PreviewViewModels */ = {
isa = XCSwiftPackageProductDependency;
productName = PreviewViewModels;

View file

@ -20,12 +20,12 @@
}
},
{
"package": "Kingfisher",
"repositoryURL": "https://github.com/onevcat/Kingfisher",
"package": "SDWebImage",
"repositoryURL": "https://github.com/SDWebImage/SDWebImage",
"state": {
"branch": null,
"revision": "daebf8ddf974164d1b9a050c8231e263f3106b09",
"version": "6.1.0"
"revision": "a6b6e44eadf0d39250c10a7cc0e3b91d0bdb0e94",
"version": "5.10.4"
}
}
]

View file

@ -1,17 +1,15 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import Mastodon
import SDWebImage
import ServiceLayer
import UserNotifications
final class NotificationService: UNNotificationServiceExtension {
private let environment = AppEnvironment.live(
userNotificationCenter: .current(),
reduceMotion: { false })
override init() {
super.init()
try? ImageCacheConfiguration(environment: Self.environment).configure()
}
var contentHandler: ((UNNotificationContent) -> Void)?
@ -25,7 +23,7 @@ final class NotificationService: UNNotificationServiceExtension {
guard let bestAttemptContent = bestAttemptContent else { return }
let parsingService = PushNotificationParsingService(environment: environment)
let parsingService = PushNotificationParsingService(environment: Self.environment)
let decryptedJSON: Data
let identityId: Identity.Id
let pushNotification: PushNotification
@ -43,14 +41,14 @@ final class NotificationService: UNNotificationServiceExtension {
bestAttemptContent.title = pushNotification.title
bestAttemptContent.body = XMLUnescaper(string: pushNotification.body).unescape()
let appPreferences = AppPreferences(environment: environment)
let appPreferences = AppPreferences(environment: Self.environment)
if appPreferences.notificationSounds.contains(pushNotification.notificationType) {
bestAttemptContent.sound = .default
}
if appPreferences.notificationAccountName,
let accountName = try? AllIdentitiesService(environment: environment).identity(id: identityId)?.handle {
let accountName = try? AllIdentitiesService(environment: Self.environment).identity(id: identityId)?.handle {
bestAttemptContent.subtitle = accountName
}
@ -71,6 +69,10 @@ final class NotificationService: UNNotificationServiceExtension {
}
private extension NotificationService {
private static let environment = AppEnvironment.live(
userNotificationCenter: .current(),
reduceMotion: { false })
static func addImage(url: URL,
bestAttemptContent: UNMutableNotificationContent,
contentHandler: @escaping (UNNotificationContent) -> Void) {
@ -78,31 +80,17 @@ private extension NotificationService {
let fileURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
.appendingPathComponent(fileName)
KingfisherManager.shared.retrieveImage(with: url) {
switch $0 {
case let .success(result):
let format: ImageFormat
switch fileURL.pathExtension.lowercased() {
case "jpg", "jpeg":
format = .JPEG
case "gif":
format = .GIF
case "png":
format = .PNG
default:
format = .unknown
}
SDWebImageManager.shared.loadImage(with: url, options: [], progress: nil) { _, data, _, _, _, _ in
if let data = data {
do {
try result.image.kf.data(format: format)?.write(to: fileURL)
try data.write(to: fileURL)
bestAttemptContent.attachments =
[try UNNotificationAttachment(identifier: fileName, url: fileURL)]
contentHandler(bestAttemptContent)
} catch {
contentHandler(bestAttemptContent)
}
case .failure:
} else {
contentHandler(bestAttemptContent)
}
}

View file

@ -1,5 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Base16
import CryptoKit
import Foundation
import Secrets
@ -20,4 +21,8 @@ public extension ImageSerializationService {
func deserialize(data: Data) throws -> Data {
try ChaChaPoly.open(.init(combined: data), using: key)
}
func cacheKey(forKey key: String) -> String {
Data(SHA256.hash(data: Data(key.utf8))).base16EncodedString()
}
}

View file

@ -1,7 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVKit
import Kingfisher
import ServiceLayer
import SwiftUI
import ViewModels
@ -30,9 +29,4 @@ private extension MetatextApp {
static let environment = AppEnvironment.live(
userNotificationCenter: .current(),
reduceMotion: { UIAccessibility.isReduceMotionEnabled })
static let imageCacheName = "Images"
static let imageCacheDirectoryURL = FileManager.default.containerURL(
forSecurityApplicationGroupIdentifier: AppEnvironment.appGroup)?
.appendingPathComponent("Library")
.appendingPathComponent("Caches")
}

View file

@ -1,9 +1,9 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Combine
import Kingfisher
import Mastodon
import SafariServices
import SDWebImage
import SwiftUI
import ViewModels
@ -18,7 +18,7 @@ final class AddIdentityViewController: UIViewController {
private let welcomeLabel = UILabel()
private let instanceAndButtonsStackView = UIStackView()
private let instanceStackView = UIStackView()
private let instanceImageView = AnimatedImageView()
private let instanceImageView = SDAnimatedImageView()
private let instanceTitleLabel = UILabel()
private let instanceURLLabel = UILabel()
private let buttonsStackView = UIStackView()
@ -110,7 +110,7 @@ private extension AddIdentityViewController {
instanceImageView.contentMode = .scaleAspectFill
instanceImageView.layer.cornerRadius = .defaultCornerRadius
instanceImageView.clipsToBounds = true
instanceImageView.kf.indicatorType = .activity
instanceImageView.sd_imageIndicator = SDWebImageActivityIndicator.large
buttonsStackView.axis = .vertical
buttonsStackView.spacing = .defaultSpacing
@ -259,7 +259,7 @@ private extension AddIdentityViewController {
if let instance = instance {
self.instanceTitleLabel.text = instance.title
self.instanceURLLabel.text = instance.uri
self.instanceImageView.kf.setImage(with: instance.thumbnail)
self.instanceImageView.sd_setImage(with: instance.thumbnail)
self.instanceStackView.isHidden_stackViewSafe = false
if instance.registrations {

View file

@ -1,14 +1,14 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVFoundation
import Kingfisher
import Mastodon
import SDWebImage
import UIKit
import ViewModels
final class ImageViewController: UIViewController {
let scrollView = UIScrollView()
let imageView = AnimatedImageView()
let imageView = SDAnimatedImageView()
let playerView = PlayerView()
private let viewModel: AttachmentViewModel?
@ -55,7 +55,8 @@ final class ImageViewController: UIViewController {
contentView.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
imageView.kf.indicatorType = .activity
imageView.sd_imageIndicator = SDWebImageActivityIndicator.large
imageView.autoPlayAnimatedImage = false
contentView.addSubview(playerView)
playerView.translatesAutoresizingMaskIntoConstraints = false
@ -109,20 +110,11 @@ final class ImageViewController: UIViewController {
case .image:
imageView.tag = viewModel.tag
playerView.isHidden = true
imageView.kf.setImage(
with: viewModel.attachment.previewUrl,
options: [.onlyFromCache],
completionHandler: { [weak self] in
guard let self = self else { return }
if case .success = $0 {
self.imageView.kf.indicatorType = .none
}
let placeholderKey = viewModel.attachment.previewUrl?.absoluteString
let placeholderImage = SDImageCache.shared.imageFromCache(forKey: placeholderKey)
self.imageView.kf.setImage(
with: viewModel.attachment.url,
options: [.keepCurrentImageWhileLoading])
})
imageView.sd_setImage(with: viewModel.attachment.url, placeholderImage: placeholderImage)
case .gifv:
playerView.tag = viewModel.tag
imageView.isHidden = true
@ -143,7 +135,7 @@ final class ImageViewController: UIViewController {
} else if let imageURL = imageURL {
imageView.tag = imageURL.hashValue
playerView.isHidden = true
imageView.kf.setImage(with: imageURL)
imageView.sd_setImage(with: imageURL)
}
contentView.accessibilityLabel = viewModel?.attachment.type.accessibilityName

View file

@ -2,7 +2,6 @@
import AVFoundation
import Combine
import Kingfisher
import PhotosUI
import SwiftUI
import UniformTypeIdentifiers

View file

@ -2,9 +2,9 @@
import AVKit
import Combine
import Kingfisher
import Mastodon
import SafariServices
import SDWebImage
import SwiftUI
import ViewModels
@ -280,13 +280,8 @@ extension TableViewController: UITableViewDataSourcePrefetching {
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
let urls = indexPaths.compactMap(dataSource.itemIdentifier(for:))
.reduce(Set<URL>()) { $0.union($1.mediaPrefetchURLs(identityContext: viewModel.identityContext)) }
var imageOptions = KingfisherManager.shared.defaultOptions
imageOptions.append(.requestModifier(PrefetchRequestModifier()))
for url in urls {
KingfisherManager.shared.retrieveImage(with: url, completionHandler: nil)
}
SDWebImagePrefetcher.shared.prefetchURLs(Array(urls))
}
}

View file

@ -1,6 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import SwiftUI
import ViewModels

View file

@ -1,6 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import SwiftUI
import ViewModels

View file

@ -1,6 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import SwiftUI
import ViewModels

View file

@ -1,16 +1,16 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
// swiftlint:disable file_length
final class AccountHeaderView: UIView {
let headerImageBackgroundView = UIView()
let headerImageView = AnimatedImageView()
let headerImageView = SDAnimatedImageView()
let headerButton = UIButton()
let avatarBackgroundView = UIView()
let avatarImageView = AnimatedImageView()
let avatarImageView = SDAnimatedImageView()
let avatarButton = UIButton()
let relationshipButtonsStackView = UIStackView()
let followButton = UIButton(type: .system)
@ -37,8 +37,8 @@ final class AccountHeaderView: UIView {
var viewModel: ProfileViewModel {
didSet {
if let accountViewModel = viewModel.accountViewModel {
headerImageView.kf.setImage(with: accountViewModel.headerURL) { [weak self] in
if case let .success(result) = $0, result.image.size != Self.missingHeaderImageSize {
headerImageView.sd_setImage(with: accountViewModel.headerURL) { [weak self] image, _, _, _ in
if let image = image, image.size != Self.missingHeaderImageSize {
self?.headerButton.isEnabled = true
}
}
@ -46,7 +46,7 @@ final class AccountHeaderView: UIView {
headerButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.header.accessibility-label-%@", comment: ""),
accountViewModel.displayName)
avatarImageView.kf.setImage(with: accountViewModel.avatarURL(profile: true))
avatarImageView.sd_setImage(with: accountViewModel.avatarURL(profile: true))
avatarImageView.tag = accountViewModel.avatarURL(profile: true).hashValue
avatarButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.avatar.accessibility-label-%@", comment: ""),

View file

@ -1,6 +1,6 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class AnimatedAttachmentLabel: UILabel, EmojiInsertable {
@ -18,7 +18,7 @@ final class AnimatedAttachmentLabel: UILabel, EmojiInsertable {
guard let attributedText = attributedText else { return }
var attachmentImageViews = Set<AnimatedImageView>()
var attachmentImageViews = Set<SDAnimatedImageView>()
attributedText.enumerateAttribute(
.attachment,
@ -29,7 +29,7 @@ final class AnimatedAttachmentLabel: UILabel, EmojiInsertable {
}
for subview in subviews {
guard let attachmentImageView = subview as? AnimatedImageView else { continue }
guard let attachmentImageView = subview as? SDAnimatedImageView else { continue }
if !attachmentImageViews.contains(attachmentImageView) {
attachmentImageView.removeFromSuperview()
@ -49,6 +49,7 @@ final class AnimatedAttachmentLabel: UILabel, EmojiInsertable {
animatedAttachment.imageView.image = animatedAttachment.image
animatedAttachment.imageView.contentMode = .scaleAspectFit
animatedAttachment.imageView.center.y = center.y
animatedAttachment.imageView.sd_setImage(with: animatedAttachment.imageURL)
if animatedAttachment.imageView.superview != self {
addSubview(animatedAttachment.imageView)

View file

@ -1,10 +1,11 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class AnimatedTextAttachment: NSTextAttachment {
var imageView = AnimatedImageView()
var imageURL: URL?
var imageView = SDAnimatedImageView()
var imageBounds: CGRect?
override func image(forBounds imageBounds: CGRect,

View file

@ -1,6 +1,6 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class AnimatingLayoutManager: NSLayoutManager {
@ -13,7 +13,7 @@ final class AnimatingLayoutManager: NSLayoutManager {
return
}
var attachmentImageViews = Set<AnimatedImageView>()
var attachmentImageViews = Set<SDAnimatedImageView>()
textStorage.enumerateAttribute(
.attachment,
@ -24,7 +24,7 @@ final class AnimatingLayoutManager: NSLayoutManager {
}
for subview in view?.subviews ?? [] {
guard let attachmentImageView = subview as? AnimatedImageView else { continue }
guard let attachmentImageView = subview as? SDAnimatedImageView else { continue }
if !attachmentImageViews.contains(attachmentImageView) {
attachmentImageView.removeFromSuperview()
@ -42,6 +42,7 @@ final class AnimatingLayoutManager: NSLayoutManager {
animatedAttachment.imageView.frame = boundingRect(forGlyphRange: range, in: textContainer)
animatedAttachment.imageView.image = animatedAttachment.image
animatedAttachment.imageView.contentMode = .scaleAspectFit
animatedAttachment.imageView.sd_setImage(with: animatedAttachment.imageURL)
if animatedAttachment.imageView.superview != view {
view?.addSubview(animatedAttachment.imageView)

View file

@ -2,13 +2,13 @@
import AVKit
import Combine
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
final class AttachmentView: UIView {
let playerView = PlayerView()
let imageView = AnimatedImageView()
let imageView = SDAnimatedImageView()
let removeButton = UIButton(type: .close)
let editIcon = UIImageView()
let selectionButton = UIButton()
@ -105,6 +105,7 @@ private extension AttachmentView {
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.autoPlayAnimatedImage = false
imageView.tag = viewModel.tag
let blurEffect = UIBlurEffect(style: .systemUltraThinMaterial)
@ -168,11 +169,9 @@ private extension AttachmentView {
switch viewModel.attachment.type {
case .image, .video, .gifv:
imageView.kf.setImage(
with: viewModel.attachment.previewUrl,
completionHandler: { [weak self] _ in
self?.layoutSubviews()
})
imageView.sd_setImage(with: viewModel.attachment.previewUrl) { [weak self] _, _, _, _ in
self?.layoutSubviews()
}
case .audio:
playImageView.image = UIImage(systemName: "waveform.circle",
withConfiguration: UIImage.SymbolConfiguration(textStyle: .largeTitle))

View file

@ -1,7 +1,7 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import Mastodon
import SDWebImage
import UIKit
import ViewModels
@ -20,7 +20,7 @@ final class CardView: UIView {
.appendingWithSeparator(viewModel.title)
imageView.isHidden = viewModel.imageURL == nil
imageView.kf.setImage(with: viewModel.imageURL)
imageView.sd_setImage(with: viewModel.imageURL)
titleLabel.text = viewModel.title
descriptionLabel.text = viewModel.description

View file

@ -1,12 +1,12 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
final class CompositionView: UIView {
let avatarImageView = AnimatedImageView()
let avatarImageView = SDAnimatedImageView()
let changeIdentityButton = UIButton()
let spoilerTextField = UITextField()
let textView = ImagePastableTextView()
@ -199,7 +199,7 @@ private extension CompositionView {
? $0.identity.account?.avatar
: $0.identity.account?.avatarStatic
self.avatarImageView.kf.setImage(with: avatarURL)
self.avatarImageView.sd_setImage(with: avatarURL)
self.changeIdentityButton.accessibilityLabel = $0.identity.handle
self.changeIdentityButton.accessibilityHint =
NSLocalizedString("compose.change-identity-button.accessibility-hint", comment: "")
@ -290,10 +290,11 @@ private extension CompositionView {
}
func changeIdentityMenu(identities: [Identity]) -> UIMenu {
let processor = RoundCornerImageProcessor(radius: .widthFraction(0.5))
var imageOptions = KingfisherManager.shared.defaultOptions
imageOptions.append(.processor(processor))
let imageTransformer = SDImageRoundCornerTransformer(
radius: .greatestFiniteMagnitude,
corners: .allCorners,
borderWidth: 0,
borderColor: nil)
return UIMenu(children: identities.map { identity in
UIDeferredMenuElement { completion in
@ -302,10 +303,12 @@ private extension CompositionView {
}
if let image = identity.image {
KingfisherManager.shared.retrieveImage(with: image, options: imageOptions) {
if case let .success(value) = $0 {
action.image = value.image
}
SDWebImageManager.shared.loadImage(
with: image,
options: [.transformAnimatedImage],
context: [.imageTransformer: imageTransformer],
progress: nil) { (image, _, _, _, _, _) in
action.image = image
completion([action])
}

View file

@ -1,10 +1,10 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class EmojiView: UIView {
private let imageView = AnimatedImageView()
private let imageView = SDAnimatedImageView()
private let emojiLabel = UILabel()
private var emojiConfiguration: EmojiContentConfiguration
@ -74,7 +74,8 @@ private extension EmojiView {
imageView.isHidden = false
emojiLabel.isHidden = true
imageView.kf.setImage(with: emoji.url)
// TODO: Use static URL if emoji animation preference is false
imageView.sd_setImage(with: emoji.url)
accessibilityLabel = emoji.shortcode
} else {
imageView.isHidden = true

View file

@ -1,12 +1,12 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import Mastodon
import SDWebImage
import UIKit
import ViewModels
final class AccountView: UIView {
let avatarImageView = AnimatedImageView()
let avatarImageView = SDAnimatedImageView()
let displayNameLabel = AnimatedAttachmentLabel()
let accountLabel = UILabel()
let noteTextView = TouchFallthroughTextView()
@ -199,7 +199,7 @@ private extension AccountView {
func applyAccountConfiguration() {
let viewModel = accountConfiguration.viewModel
avatarImageView.kf.setImage(with: viewModel.avatarURL(profile: false))
avatarImageView.sd_setImage(with: viewModel.avatarURL(profile: false))
let mutableDisplayName = NSMutableAttributedString(string: viewModel.displayName)

View file

@ -1,10 +1,10 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class AutocompleteItemView: UIView {
private let imageView = AnimatedImageView()
private let imageView = SDAnimatedImageView()
private let primaryLabel = AnimatedAttachmentLabel()
private let secondaryLabel = UILabel()
private let stackView = UIStackView()
@ -78,7 +78,7 @@ private extension AutocompleteItemView {
? account.avatar
: account.avatarStatic
imageView.kf.setImage(with: avatarURL)
imageView.sd_setImage(with: avatarURL)
imageView.isHidden = false
let mutableDisplayName = NSMutableAttributedString(string: account.displayName)

View file

@ -1,10 +1,10 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class IdentityView: UIView {
let imageView = AnimatedImageView()
let imageView = SDAnimatedImageView()
let nameLabel = AnimatedAttachmentLabel()
let secondaryLabel = UILabel()
@ -84,7 +84,7 @@ private extension IdentityView {
func applyIdentityConfiguration() {
let viewModel = identityConfiguration.viewModel
imageView.kf.setImage(with: viewModel.identity.image)
imageView.sd_setImage(with: viewModel.identity.image)
imageView.autoPlayAnimatedImage = viewModel.identityContext.appPreferences.animateAvatars == .everywhere
if let displayName = viewModel.identity.account?.displayName,

View file

@ -1,10 +1,10 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
final class InstanceView: UIView {
private let imageView = AnimatedImageView()
private let imageView = SDAnimatedImageView()
private let titleLabel = UILabel()
private let uriLabel = UILabel()
private var instanceConfiguration: InstanceContentConfiguration
@ -77,7 +77,8 @@ private extension InstanceView {
func applyInstanceConfiguration() {
let viewModel = instanceConfiguration.viewModel
imageView.kf.setImage(with: viewModel.instance.thumbnail)
imageView.sd_setImage(with: viewModel.instance.thumbnail)
imageView.autoPlayAnimatedImage = !UIAccessibility.isReduceMotionEnabled
titleLabel.text = viewModel.instance.title
uriLabel.text = viewModel.instance.uri

View file

@ -1,13 +1,13 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import Mastodon
import SDWebImage
import UIKit
import ViewModels
final class NotificationView: UIView {
private let iconImageView = UIImageView()
private let avatarImageView = AnimatedImageView()
private let avatarImageView = SDAnimatedImageView()
private let avatarButton = UIButton()
private let typeLabel = AnimatedAttachmentLabel()
private let timeLabel = UILabel()
@ -166,7 +166,7 @@ private extension NotificationView {
func applyNotificationConfiguration() {
let viewModel = notificationConfiguration.viewModel
avatarImageView.kf.setImage(with: viewModel.accountViewModel.avatarURL())
avatarImageView.sd_setImage(with: viewModel.accountViewModel.avatarURL())
switch viewModel.type {
case .follow:

View file

@ -2,13 +2,13 @@
// swiftlint:disable file_length
import Combine
import Kingfisher
import Mastodon
import SDWebImage
import UIKit
import ViewModels
final class StatusView: UIView {
let avatarImageView = AnimatedImageView()
let avatarImageView = SDAnimatedImageView()
let avatarButton = UIButton()
let infoIcon = UIImageView()
let infoLabel = AnimatedAttachmentLabel()
@ -417,7 +417,7 @@ private extension StatusView {
menuButton.menu = menu(viewModel: viewModel)
avatarImageView.kf.setImage(with: viewModel.avatarURL)
avatarImageView.sd_setImage(with: viewModel.avatarURL)
avatarButton.accessibilityLabel = String.localizedStringWithFormat(
NSLocalizedString("account.avatar.accessibility-label-%@", comment: ""),
viewModel.accountViewModel.displayName)

View file

@ -1,6 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
@ -23,11 +23,11 @@ final class ConversationAvatarsView: UIView {
rightStackView.isHidden = accountCount == 1
for (index, accountViewModel) in accountViewModels.enumerated() {
let imageView = AnimatedImageView()
let imageView = SDAnimatedImageView()
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.kf.setImage(with: accountViewModel.avatarURL())
imageView.sd_setImage(with: accountViewModel.avatarURL())
if accountCount == 2 && index == 1
|| accountCount == 3 && index != 0

View file

@ -1,14 +1,14 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Combine
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
final class EditThumbnailView: UIView {
let playerView = PlayerView()
let imageView = UIImageView()
let previewImageView = UIImageView()
let imageView = SDAnimatedImageView()
let previewImageView = SDAnimatedImageView()
let promptBackgroundView = UIVisualEffectView(effect: UIBlurEffect(style: .systemChromeMaterial))
let thumbnailPromptLabel = UILabel()
@ -94,7 +94,7 @@ private extension EditThumbnailView {
addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
imageView.kf.indicatorType = .activity
imageView.sd_imageIndicator = SDWebImageActivityIndicator.large
addSubview(playerView)
playerView.translatesAutoresizingMaskIntoConstraints = false
@ -137,25 +137,16 @@ private extension EditThumbnailView {
previewImageView.contentMode = .scaleAspectFill
previewImageView.clipsToBounds = true
previewImageView.layer.cornerRadius = .defaultCornerRadius
previewImageView.kf.setImage(with: viewModel.attachment.previewUrl)
previewImageView.sd_setImage(with: viewModel.attachment.previewUrl)
switch viewModel.attachment.type {
case .image:
playerView.isHidden = true
imageView.kf.setImage(
with: viewModel.attachment.previewUrl,
options: [.onlyFromCache],
completionHandler: { [weak self] in
guard let self = self else { return }
if case .success = $0 {
self.imageView.kf.indicatorType = .none
}
let placeholderKey = viewModel.attachment.previewUrl?.absoluteString
let placeholderImage = SDImageCache.shared.imageFromCache(forKey: placeholderKey)
self.imageView.kf.setImage(
with: self.viewModel.attachment.url,
options: [.keepCurrentImageWhileLoading])
})
imageView.sd_setImage(with: viewModel.attachment.url, placeholderImage: placeholderImage)
case .gifv:
imageView.isHidden = true
let player = PlayerCache.shared.player(url: viewModel.attachment.url)

View file

@ -1,7 +1,7 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Combine
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
@ -28,17 +28,18 @@ final class SecondaryNavigationButton: UIBarButtonItem {
])
viewModel.identityContext.$identity.sink {
button.kf.setImage(
button.sd_setImage(
with: $0.image,
for: .normal,
placeholder: UIImage(systemName: "line.horizontal.3"))
placeholderImage: UIImage(systemName: "line.horizontal.3"))
}
.store(in: &cancellables)
let processor = RoundCornerImageProcessor(radius: .widthFraction(0.5))
var imageOptions = KingfisherManager.shared.defaultOptions
imageOptions.append(.processor(processor))
let imageTransformer = SDImageRoundCornerTransformer(
radius: .greatestFiniteMagnitude,
corners: .allCorners,
borderWidth: 0,
borderColor: nil)
viewModel.$recentIdentities.sink { identities in
button.menu = UIMenu(children: identities.map { identity in
@ -48,10 +49,12 @@ final class SecondaryNavigationButton: UIBarButtonItem {
}
if let image = identity.image {
KingfisherManager.shared.retrieveImage(with: image, options: imageOptions) {
if case let .success(value) = $0 {
action.image = value.image
}
SDWebImageManager.shared.loadImage(
with: image,
options: [.transformAnimatedImage],
context: [.imageTransformer: imageTransformer],
progress: nil) { (image, _, _, _, _, _) in
action.image = image
completion([action])
}

View file

@ -1,12 +1,12 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Kingfisher
import SDWebImage
import UIKit
import ViewModels
final class SecondaryNavigationTitleView: UIView {
private let viewModel: NavigationViewModel
private let avatarImageView = AnimatedImageView()
private let avatarImageView = SDAnimatedImageView()
private let displayNameLabel = AnimatedAttachmentLabel()
private let accountLabel = UILabel()
private let stackView = UIStackView()
@ -70,7 +70,7 @@ private extension SecondaryNavigationTitleView {
? viewModel.identityContext.identity.account?.avatar
: viewModel.identityContext.identity.account?.avatarStatic
avatarImageView.kf.setImage(with: avatarURL)
avatarImageView.sd_setImage(with: avatarURL)
if let displayName = viewModel.identityContext.identity.account?.displayName,
!displayName.isEmpty {