Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #7026: Remove SDWebImageSVGNativeCoder and use `WebImageDownloa…
Browse files Browse the repository at this point in the history
…der` to decode web images in Wallet (#7881)
  • Loading branch information
nuo-xu authored Aug 18, 2023
1 parent ec757aa commit 639c7d4
Show file tree
Hide file tree
Showing 18 changed files with 109 additions and 121 deletions.
17 changes: 0 additions & 17 deletions App/Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
441A6360272445F9001492C3 /* StatDataModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 441A635F272444DE001492C3 /* StatDataModel.swift */; };
5E8CD8E123D5E3DA00548FC0 /* libarchive.2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E8CD8E023D5E3D100548FC0 /* libarchive.2.tbd */; };
5EE5918123A290E000E8E8DE /* CoreNFC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F926647A234D4EF400359492 /* CoreNFC.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
7DDAF2232930091600D955A2 /* SDWebImageSVGNativeCoder in Frameworks */ = {isa = PBXBuildFile; productRef = 7DDAF2222930091600D955A2 /* SDWebImageSVGNativeCoder */; };
7DDE6308292FEC9500B8B585 /* SDWebImage in Frameworks */ = {isa = PBXBuildFile; productRef = 7DDE6307292FEC9500B8B585 /* SDWebImage */; };
CA0391B4271E1023000EB13C /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA0391B3271E1023000EB13C /* WidgetKit.framework */; };
CA0391B6271E1023000EB13C /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CA0391B5271E1023000EB13C /* SwiftUI.framework */; };
Expand Down Expand Up @@ -356,7 +355,6 @@
27D972E628BD4D9900DDCF79 /* BraveNews in Frameworks */,
27D7FF5329BA69330096DD93 /* BraveShields in Frameworks */,
27FA217F2837FB0100FA2C45 /* BraveShared in Frameworks */,
7DDAF2232930091600D955A2 /* SDWebImageSVGNativeCoder in Frameworks */,
27D7FF7329BB816E0096DD93 /* PrivateCDN in Frameworks */,
27FA21812837FB0100FA2C45 /* BraveWallet in Frameworks */,
0A1DF486244A2ECB00541FE4 /* NetworkExtension.framework in Frameworks */,
Expand Down Expand Up @@ -796,7 +794,6 @@
27466BB0288EDB9C00584C90 /* RuntimeWarnings */,
27D972E528BD4D9900DDCF79 /* BraveNews */,
7DDE6307292FEC9500B8B585 /* SDWebImage */,
7DDAF2222930091600D955A2 /* SDWebImageSVGNativeCoder */,
2759468E29CCB6350094BDDE /* GRDWireGuardKit */,
27C1C5EC29B6AA8800739BE5 /* Preferences */,
27D7FF5229BA69330096DD93 /* BraveShields */,
Expand Down Expand Up @@ -885,7 +882,6 @@
packageReferences = (
2775689A25ACF7B500C129AF /* XCRemoteSwiftPackageReference "SwiftKeychainWrapper" */,
7DDE6306292FEC9500B8B585 /* XCRemoteSwiftPackageReference "SDWebImage" */,
7DDAF2212930091600D955A2 /* XCRemoteSwiftPackageReference "SDWebImageSVGNativeCoder" */,
272FC5B22979F3DF0027C53D /* XCRemoteSwiftPackageReference "SDWebImageSwiftUI" */,
27F344A429847EEC00933B31 /* XCRemoteSwiftPackageReference "swift-collections" */,
);
Expand Down Expand Up @@ -3106,14 +3102,6 @@
minimumVersion = 1.0.0;
};
};
7DDAF2212930091600D955A2 /* XCRemoteSwiftPackageReference "SDWebImageSVGNativeCoder" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SDWebImage/SDWebImageSVGNativeCoder.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.1.1;
};
};
7DDE6306292FEC9500B8B585 /* XCRemoteSwiftPackageReference "SDWebImage" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/SDWebImage/SDWebImage.git";
Expand Down Expand Up @@ -3223,11 +3211,6 @@
isa = XCSwiftPackageProductDependency;
productName = Storage;
};
7DDAF2222930091600D955A2 /* SDWebImageSVGNativeCoder */ = {
isa = XCSwiftPackageProductDependency;
package = 7DDAF2212930091600D955A2 /* XCRemoteSwiftPackageReference "SDWebImageSVGNativeCoder" */;
productName = SDWebImageSVGNativeCoder;
};
7DDE6307292FEC9500B8B585 /* SDWebImage */ = {
isa = XCSwiftPackageProductDependency;
package = 7DDE6306292FEC9500B8B585 /* XCRemoteSwiftPackageReference "SDWebImage" */;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,6 @@
"version" : "5.10.3"
}
},
{
"identity" : "sdwebimagesvgnativecoder",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/SDWebImageSVGNativeCoder.git",
"state" : {
"revision" : "2e5522fa9d95b2bfccbf38b1c97cd68f06931b02",
"version" : "0.1.1"
}
},
{
"identity" : "sdwebimageswiftui",
"kind" : "remoteSourceControl",
Expand All @@ -80,15 +71,6 @@
"version" : "5.6.0"
}
},
{
"identity" : "svgnative-xcode",
"kind" : "remoteSourceControl",
"location" : "https://github.com/SDWebImage/svgnative-Xcode.git",
"state" : {
"revision" : "46c0196664b445c59d8c9c2f55c076cd9869f980",
"version" : "0.1.0-beta"
}
},
{
"identity" : "swift-algorithms",
"kind" : "remoteSourceControl",
Expand Down
2 changes: 0 additions & 2 deletions App/iOS/Delegates/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import Storage
import AVFoundation
import MessageUI
import SDWebImage
import SDWebImageSVGNativeCoder
import SwiftKeychainWrapper
import LocalAuthentication
import CoreSpotlight
Expand Down Expand Up @@ -89,7 +88,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
MenuHelper.defaultHelper.setItems()

SDImageCodersManager.shared.addCoder(PrivateCDNImageCoder())
SDImageCodersManager.shared.addCoder(SDImageSVGNativeCoder.shared)

// Temporary fix for Bug 1390871 - NSInvalidArgumentException: -[WKContentView menuHelperFindInPage]: unrecognized selector
if let clazz = NSClassFromString("WKCont" + "ent" + "View"), let swizzledMethod = class_getInstanceMethod(TabWebViewMenuHelper.self, #selector(TabWebViewMenuHelper.swizzledMenuHelperFindInPage)) {
Expand Down
2 changes: 0 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ var package = Package(
.package(url: "https://github.com/airbnb/lottie-ios", from: "3.1.9"),
.package(url: "https://github.com/jrendel/SwiftKeychainWrapper", from: "4.0.1"),
.package(url: "https://github.com/SDWebImage/SDWebImage", exact: "5.10.3"),
.package(url: "https://github.com/SDWebImage/SDWebImageSVGNativeCoder", from: "0.1.1"),
.package(url: "https://github.com/SDWebImage/SDWebImageSwiftUI", from: "2.2.0"),
.package(url: "https://github.com/nmdias/FeedKit", from: "9.1.2"),
.package(url: "https://github.com/brave/PanModal", revision: "e4c07f8e6c5df937051fabc47e1e92901e1d068b"),
Expand Down Expand Up @@ -134,7 +133,6 @@ var package = Package(
"DesignSystem",
"PanModal",
"SDWebImage",
"SDWebImageSVGNativeCoder",
"SnapKit",
.product(name: "Introspect", package: "SwiftUI-Introspect"),
"Then",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ extension BrowserViewController {
func presentWallet() {
guard let walletStore = self.walletStore ?? newWalletStore() else { return }
walletStore.origin = nil
let vc = WalletHostingViewController(walletStore: walletStore)
let vc = WalletHostingViewController(walletStore: walletStore, webImageDownloader: braveCore.webImageDownloader)
vc.delegate = self
self.dismiss(animated: true) {
self.present(vc, animated: true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import Growth

extension WalletStore {
/// Creates a WalletStore based on whether or not the user is in Private Mode
static func from(ipfsApi: IpfsAPI, privateMode: Bool) -> WalletStore? {
static func from(
ipfsApi: IpfsAPI,
privateMode: Bool
) -> WalletStore? {
guard
let keyringService = BraveWallet.KeyringServiceFactory.get(privateMode: privateMode),
let rpcService = BraveWallet.JsonRpcServiceFactory.get(privateMode: privateMode),
Expand Down Expand Up @@ -100,7 +103,8 @@ extension BrowserViewController {
let controller = WalletPanelHostingController(
walletStore: walletStore,
tabDappStore: tabDappStore,
origin: origin
origin: origin,
webImageDownloader: braveCore.webImageDownloader
)
controller.delegate = self
let popover = PopoverController(contentController: controller)
Expand Down Expand Up @@ -143,6 +147,7 @@ extension BrowserViewController: BraveWalletDelegate {
public func walletPanel(_ panel: WalletPanelHostingController, presentWalletWithContext: PresentingContext, walletStore: WalletStore) {
let walletHostingController = WalletHostingViewController(
walletStore: walletStore,
webImageDownloader: braveCore.webImageDownloader,
presentingContext: presentWalletWithContext
)
walletHostingController.delegate = self
Expand Down
2 changes: 1 addition & 1 deletion Sources/BraveNews/Customize/SourceLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ private struct SourceImageView: View {
.frame(width: imageHeight*2, height: imageHeight)
.overlay(
source.coverURL.map {
WebImageReader(url: $0) { image, isFinished in
WebImageReader(url: $0) { image in
if let image {
Image(uiImage: image)
.resizable()
Expand Down
99 changes: 43 additions & 56 deletions Sources/BraveUI/SwiftUI/WebImageReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,83 +5,70 @@

import SwiftUI
import SDWebImage
import SDWebImageSVGNativeCoder

private class WalletWebImageManager: ObservableObject {
/// loaded image, note when progressive loading, this will published multiple times with different partial image
@Published public var image: UIImage?
/// loaded image data, may be nil if hit from memory cache. This will only published once loading is finished
@Published public var isFinished: Bool = false
/// loading error
@Published public var error: Error?

private var manager = SDWebImageManager.shared
private var operation: SDWebImageOperation?
public protocol WebImageDownloaderType: AnyObject {
func downloadImage(url: URL) async -> UIImage?
func imageFromData(data: Data) async -> UIImage?
}

private var supportedCoders: [SDImageCoder] = [SDImageSVGNativeCoder.shared, SDImageAPNGCoder.shared, SDImageGIFCoder.shared]

init() {}
struct WebImageDownloaderKey: EnvironmentKey {
static var defaultValue: WebImageDownloaderType = SDWebImageManager.shared
}

func load(url: URL?, options: SDWebImageOptions = []) {
operation = manager.loadImage(
with: url, options: options, progress: nil,
completed: { [weak self] image, data, error, _, finished, _ in
guard let self = self else { return }
self.image = image
self.error = error
if finished {
self.isFinished = true
}
})
extension EnvironmentValues {
public var webImageDownloader: WebImageDownloaderType {
get { self[WebImageDownloaderKey.self] }
set { self[WebImageDownloaderKey.self] = newValue }
}
}

func cancel() {
operation?.cancel()
operation = nil
extension SDWebImageManager: WebImageDownloaderType {
public func downloadImage(url: URL) async -> UIImage? {
var operation: SDWebImageCombinedOperation?
return await withTaskCancellationHandler {
await withCheckedContinuation { continuation in
operation = loadImage(with: url, progress: nil) { image, _, _, _, _, _ in
continuation.resume(returning: image)
}
}
} onCancel: { [operation] in
operation?.cancel()
}
}

func load(base64Str: String, options: [SDImageCoderOption: Any] = [:]) {
guard base64Str.hasPrefix("data:image/") else { return }
guard let dataString = base64Str.separatedBy(",").last else { return }

let data = Data(base64Encoded: dataString, options: .ignoreUnknownCharacters)
for coder in supportedCoders where coder.canDecode(from: data) {
image = coder.decodedImage(with: data, options: options)
break
}
public func imageFromData(data: Data) async -> UIImage? {
SDImageCodersManager.shared.decodedImage(with: data)
}
}

public struct WebImageReader<Content: View>: View {
@StateObject private var imageManager: WalletWebImageManager = .init()
var url: URL?
var options: SDWebImageOptions
var coderOptions: [SDImageCoderOption: Any]
var url: URL

@Environment(\.webImageDownloader) private var imageDownloader: WebImageDownloaderType

@State private var image: UIImage?

private var content: (_ image: UIImage?, _ isFinished: Bool) -> Content
private var content: (_ image: UIImage?) -> Content

public init(
url: URL?,
options: SDWebImageOptions = [],
coderOptions: [SDImageCoderOption: Any] = [:],
@ViewBuilder content: @escaping (_ image: UIImage?, _ isFinished: Bool) -> Content
url: URL,
@ViewBuilder content: @escaping (_ image: UIImage?) -> Content
) {
self.content = content
self.url = url
self.options = options
self.coderOptions = coderOptions
}

public var body: some View {
content(imageManager.image, imageManager.isFinished)
.onAppear {
if let urlString = url?.absoluteString {
if urlString.hasPrefix("data:image/") {
imageManager.load(base64Str: urlString)
} else if !imageManager.isFinished {
imageManager.load(url: url, options: options)
}
content(image)
.task {
if url.absoluteString.hasPrefix("data:image/"),
let dataString = url.absoluteString.separatedBy(",").last,
let data = Data(base64Encoded: dataString, options: .ignoreUnknownCharacters) {
image = await imageDownloader.imageFromData(data: data)
} else {
image = await imageDownloader.downloadImage(url: url)
}
}
.id(url)
}
}
6 changes: 4 additions & 2 deletions Sources/BraveWallet/Crypto/AssetIconView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ struct AssetIconView: View {
image
.resizable()
.aspectRatio(contentMode: .fit)
} else {
WebImageReader(url: URL(string: token.logo)) { image, isFinished in
} else if let url = URL(string: token.logo) {
WebImageReader(url: url) { image in
if let image = image {
Image(uiImage: image)
.resizable()
Expand All @@ -68,6 +68,8 @@ struct AssetIconView: View {
fallbackMonogram
}
}
} else {
fallbackMonogram
}
}
.frame(width: min(length, maxLength ?? length), height: min(length, maxLength ?? length))
Expand Down
4 changes: 4 additions & 0 deletions Sources/BraveWallet/Crypto/CryptoView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import Preferences
public struct CryptoView: View {
var walletStore: WalletStore
@ObservedObject var keyringStore: KeyringStore
var webImageDownloader: WebImageDownloaderType
var presentingContext: PresentingContext
@Environment(\.presentationMode) @Binding private var presentationMode

Expand All @@ -26,10 +27,12 @@ public struct CryptoView: View {
public init(
walletStore: WalletStore,
keyringStore: KeyringStore,
webImageDownloader: WebImageDownloaderType,
presentingContext: PresentingContext
) {
self.walletStore = walletStore
self.keyringStore = keyringStore
self.webImageDownloader = webImageDownloader
self.presentingContext = presentingContext
}

Expand Down Expand Up @@ -272,6 +275,7 @@ public struct CryptoView: View {
.init(action: { [appRatingRequestAction] in
appRatingRequestAction?()
}))
.environment(\.webImageDownloader, webImageDownloader)
.onChange(of: visibleScreen) { newValue in
if case .panelUnlockOrSetup = presentingContext, newValue == .crypto {
dismissAction()
Expand Down
Loading

0 comments on commit 639c7d4

Please sign in to comment.