From 4ce23204776970bb599b96708790487f41f63ce2 Mon Sep 17 00:00:00 2001 From: Esenbek Date: Wed, 29 May 2024 16:20:14 +0600 Subject: [PATCH] Add fallback icon urls for coins --- .../project.pbxproj | 14 ++++++- .../CexWithdrawViewController.swift | 2 +- .../CexWithdraw/CexWithdrawViewModel.swift | 5 ++- .../Coin/CoinOverview/CoinOverviewView.swift | 7 +--- .../CoinOverviewViewController.swift | 4 +- .../CoinOverviewViewItemFactory.swift | 4 +- .../CoinOverview/CoinOverviewViewModel.swift | 4 +- .../ManageWalletsViewController.swift | 16 ++++---- .../ManageWalletsViewModel.swift | 18 +++------ .../Market/Coins/MarketCoinsView.swift | 16 +++----- .../Modules/Market/MarketSearchView.swift | 5 +-- .../Market/Pairs/MarketPairsView.swift | 22 ++++------- .../Modules/MultiSwap/MultiSwapView.swift | 10 +---- .../MultiSwapTokenSelectView.swift | 7 +--- .../Platforms/BaseSendViewController.swift | 2 +- .../SendEvm/SendEvmViewController.swift | 2 +- .../Modules/SendNew/PreSendView.swift | 4 +- .../Modules/SendNew/SendField.swift | 8 +--- .../SendTron/SendTronViewController.swift | 2 +- .../Swap/CoinCard/SwapCoinCardCell.swift | 6 +-- .../Swap/CoinCard/SwapCoinCardViewModel.swift | 4 +- .../SwapNew/InputCard/SwapInputCardView.swift | 6 +-- .../TransactionTokenSelectView.swift | 5 +-- .../Modules/Wallet/BalanceViewItem.swift | 8 ++-- .../ReceiveSelectCoinViewController.swift | 2 +- .../ReceiveSelectCoinViewModel.swift | 4 +- .../Views/WalletTokenBalanceCell.swift | 2 +- .../WalletTokenBalanceViewItemFactory.swift | 8 ++-- .../WalletTokenBalanceViewModel.swift | 4 +- .../WalletTokenListViewItemFactory.swift | 8 ++-- .../Wallet/Views/BalanceCoinIconHolder.swift | 9 +++-- .../Modules/Wallet/Views/BalanceTopView.swift | 2 +- .../Wallet/WalletViewItemFactory.swift | 8 ++-- .../Extensions/CellElement.swift | 16 +++++--- .../Extensions/UIImageView.swift | 37 ++++++++++++++++++ .../UserInterface/SwiftUI/CoinIconView.swift | 39 +++++++++++++++++++ 36 files changed, 174 insertions(+), 146 deletions(-) create mode 100644 UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/UIImageView.swift create mode 100644 UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/CoinIconView.swift diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index 8419de7e2a..21f395d142 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -2908,6 +2908,8 @@ D09200C6293F21720091981A /* RestoreNonStandardViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C0293F21710091981A /* RestoreNonStandardViewModel.swift */; }; D09200C8293F21720091981A /* RestoreNonStandardModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C1293F21720091981A /* RestoreNonStandardModule.swift */; }; D09200C9293F21720091981A /* RestoreNonStandardModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09200C1293F21720091981A /* RestoreNonStandardModule.swift */; }; + D09C5C632C076C0E00E6909E /* CoinIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09C5C622C076C0E00E6909E /* CoinIconView.swift */; }; + D09C5C642C076C0E00E6909E /* CoinIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09C5C622C076C0E00E6909E /* CoinIconView.swift */; }; D09D768C2A2E066E004311E6 /* SendTronConfirmationModule.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09D768B2A2E066E004311E6 /* SendTronConfirmationModule.swift */; }; D09D768E2A2E06D6004311E6 /* SendTronConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09D768D2A2E06D6004311E6 /* SendTronConfirmationViewController.swift */; }; D09D768F2A2E06D6004311E6 /* SendTronConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D09D768D2A2E06D6004311E6 /* SendTronConfirmationViewController.swift */; }; @@ -2920,6 +2922,8 @@ D0A6902C2C00ACF600E59296 /* CautionDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A6902A2C00ACF600E59296 /* CautionDataSource.swift */; }; D0A6902E2C04969300E59296 /* CautionDataSourceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A6902D2C04969300E59296 /* CautionDataSourceViewModel.swift */; }; D0A6902F2C04969300E59296 /* CautionDataSourceViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A6902D2C04969300E59296 /* CautionDataSourceViewModel.swift */; }; + D0A690342C05D01C00E59296 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A690332C05D01C00E59296 /* UIImageView.swift */; }; + D0A690352C05D01C00E59296 /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A690332C05D01C00E59296 /* UIImageView.swift */; }; D0A980A92B5E3C0900127AF4 /* StepChangeButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A980A82B5E3C0900127AF4 /* StepChangeButtonsView.swift */; }; D0A980AA2B5E3C0900127AF4 /* StepChangeButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A980A82B5E3C0900127AF4 /* StepChangeButtonsView.swift */; }; D0A980AF2B60E73F00127AF4 /* LegacyFeeSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A980AE2B60E73F00127AF4 /* LegacyFeeSettingsView.swift */; }; @@ -4893,12 +4897,14 @@ D09200BF293F21700091981A /* RestoreNonStandardViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreNonStandardViewController.swift; sourceTree = ""; }; D09200C0293F21710091981A /* RestoreNonStandardViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreNonStandardViewModel.swift; sourceTree = ""; }; D09200C1293F21720091981A /* RestoreNonStandardModule.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RestoreNonStandardModule.swift; sourceTree = ""; }; + D09C5C622C076C0E00E6909E /* CoinIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoinIconView.swift; sourceTree = ""; }; D09D768B2A2E066E004311E6 /* SendTronConfirmationModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTronConfirmationModule.swift; sourceTree = ""; }; D09D768D2A2E06D6004311E6 /* SendTronConfirmationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTronConfirmationViewController.swift; sourceTree = ""; }; D09D76902A2E0753004311E6 /* SendTronConfirmationViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTronConfirmationViewModel.swift; sourceTree = ""; }; D09D76932A2E07BD004311E6 /* SendTronConfirmationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendTronConfirmationService.swift; sourceTree = ""; }; D0A6902A2C00ACF600E59296 /* CautionDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CautionDataSource.swift; sourceTree = ""; }; D0A6902D2C04969300E59296 /* CautionDataSourceViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CautionDataSourceViewModel.swift; sourceTree = ""; }; + D0A690332C05D01C00E59296 /* UIImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = ""; }; D0A980A82B5E3C0900127AF4 /* StepChangeButtonsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StepChangeButtonsView.swift; sourceTree = ""; }; D0A980AE2B60E73F00127AF4 /* LegacyFeeSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacyFeeSettingsView.swift; sourceTree = ""; }; D0C2260F2A66A3BC007101F7 /* PersonalSupportModule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PersonalSupportModule.swift; sourceTree = ""; }; @@ -5494,6 +5500,7 @@ ABC9AF26FDCB363793BF66E1 /* Integer.swift */, ABC9A776346AF62265896CA1 /* CellElement.swift */, 11B353356496AA219686B993 /* UIWindow.swift */, + D0A690332C05D01C00E59296 /* UIImageView.swift */, ); path = Extensions; sourceTree = ""; @@ -5728,6 +5735,7 @@ D3B73E2F2BDFC5580067429D /* PriceRow.swift */, D3833B042BF4AFB800ACECFB /* MarqueeView.swift */, 6BB14F742C01D04200E879B2 /* CheckBoxUiView.swift */, + D09C5C622C076C0E00E6909E /* CoinIconView.swift */, ); path = SwiftUI; sourceTree = ""; @@ -10717,6 +10725,7 @@ 11B35AB989198F423D880695 /* PoolGroupFactory.swift in Sources */, D3F9B0352BE3B3A7009FFA95 /* EvmDecorator.swift in Sources */, D09D76952A2E07BD004311E6 /* SendTronConfirmationService.swift in Sources */, + D09C5C642C076C0E00E6909E /* CoinIconView.swift in Sources */, 11B358A1409FB729B1C3013E /* PoolSource.swift in Sources */, ABC9A52E08E5C57665C07DBC /* PseudoAccessoryView.swift in Sources */, ABC9AC10D815702B812CFFB7 /* NftAssetOverviewService.swift in Sources */, @@ -10794,6 +10803,7 @@ ABC9A04655D81FE5198B786F /* SendEip1155ViewModel.swift in Sources */, ABC9A0B58626A1E0C4248162 /* SendEip1155Service.swift in Sources */, ABC9A140E5EF9D0AD4234689 /* SendEip1155ViewController.swift in Sources */, + D0A690352C05D01C00E59296 /* UIImageView.swift in Sources */, ABC9AF1729BA19223BB39E06 /* SendEip721ViewModel.swift in Sources */, ABC9AFA3570AE29F26623FBF /* SendEip721ViewController.swift in Sources */, ABC9A95E667DD7BD26602D8E /* SendEip721Service.swift in Sources */, @@ -12295,6 +12305,7 @@ 11B3515A1106B2AE8509263E /* Pool.swift in Sources */, D3F9B0342BE3B3A7009FFA95 /* EvmDecorator.swift in Sources */, 11B3541BC8A0EF1066EBA464 /* NonSpamPoolProvider.swift in Sources */, + D09C5C632C076C0E00E6909E /* CoinIconView.swift in Sources */, 11B3594DD9B54E11190B4CD5 /* PoolProvider.swift in Sources */, 11B351E4BD2180A5D6D59F23 /* PoolGroup.swift in Sources */, 11B35AC389ACC3E4096EC645 /* PoolGroupFactory.swift in Sources */, @@ -12372,6 +12383,7 @@ 11B355028142F82D805752AF /* NftDoubleCell.swift in Sources */, 11B35FF1D956D812F815FA86 /* NftImageView.swift in Sources */, 11B35DF3813AEB74E254A05A /* NftAssetView.swift in Sources */, + D0A690342C05D01C00E59296 /* UIImageView.swift in Sources */, ABC9A13DB3ADB580D59F66E4 /* SendEip1155ViewModel.swift in Sources */, ABC9A4CD35CF43C88EC13909 /* SendEip1155Service.swift in Sources */, ABC9ACA04EBC7AF903A01FE3 /* SendEip1155ViewController.swift in Sources */, @@ -13929,7 +13941,7 @@ repositoryURL = "https://github.com/horizontalsystems/MarketKit.Swift"; requirement = { kind = exactVersion; - version = 3.0.6; + version = 3.0.8; }; }; D3604E7D28F03C1D0066C366 /* XCRemoteSwiftPackageReference "Chart" */ = { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewController.swift index 272606ba68..1babc95e9e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewController.swift @@ -56,7 +56,7 @@ class CexWithdrawViewController: ThemeViewController, ICexWithdrawNetworkSelectD iconImageView.snp.makeConstraints { make in make.size.equalTo(CGFloat.iconSize24) } - iconImageView.setImage(withUrlString: viewModel.coinImageUrl, placeholder: nil) + iconImageView.setImage(coin: viewModel.coin) view.addSubview(tableView) tableView.snp.makeConstraints { maker in diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewModel.swift index 137f4ed3e3..b80a24bd8f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Cex/CexWithdraw/CexWithdrawViewModel.swift @@ -2,6 +2,7 @@ import BigInt import Combine import Foundation import HsExtensions +import MarketKit import RxCocoa import RxSwift @@ -65,8 +66,8 @@ extension CexWithdrawViewModel { service.cexAsset.coinCode } - var coinImageUrl: String { - service.cexAsset.coin?.imageUrl ?? "" + var coin: Coin? { + service.cexAsset.coin } var selectedNetworkIndex: Int? { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewView.swift index 7daa4e35c7..5229414738 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewView.swift @@ -27,12 +27,7 @@ struct CoinOverviewView: View { ScrollView { VStack(spacing: 0) { HStack(spacing: .margin16) { - KFImage.url(URL(string: coin.imageUrl)) - .resizable() - .placeholder { - Circle().fill(Color.themeSteel20) - } - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: coin) Text(coin.name).themeBody() diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewController.swift index 8ae3320662..280840b70e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewController.swift @@ -225,8 +225,8 @@ extension CoinOverviewViewController { rows: [ tableView.universalRow56( id: "coin-info", - image: .url(viewItem.imageUrl, placeholder: viewItem.imagePlaceholderName), - title: .body(viewItem.name, color: .themeGray), + image: .url(viewItem.coin), + title: .body(viewItem.coin.name, color: .themeGray), value: .subhead1(viewItem.marketCapRank, color: .themeGray), backgroundStyle: .transparent, isFirst: true, diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewItemFactory.swift index c866ff440a..03198dd18f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewItemFactory.swift @@ -211,10 +211,8 @@ extension CoinOverviewViewItemFactory { return CoinOverviewViewModel.ViewItem( coinViewItem: CoinOverviewViewModel.CoinViewItem( - name: coin.name, marketCapRank: marketCapRank, - imageUrl: coin.imageUrl, - imagePlaceholderName: "placeholder_circle_32" + coin: coin ), marketCapRank: marketCapRank, diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModel.swift index ead2f4da40..7dab7f575b 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinOverview/CoinOverviewViewModel.swift @@ -103,10 +103,8 @@ extension CoinOverviewViewModel { extension CoinOverviewViewModel { struct CoinViewItem { - let name: String let marketCapRank: String? - let imageUrl: String - let imagePlaceholderName: String + let coin: Coin } struct ViewItem { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewController.swift index 1c2b682854..61730a34a0 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewController.swift @@ -1,5 +1,6 @@ import Combine import ComponentKit +import MarketKit import RxCocoa import RxSwift import SectionsTableView @@ -133,9 +134,9 @@ class ManageWalletsViewController: ThemeSearchViewController { private func showBottomSheet(viewItem: ManageWalletsViewModel.CoinViewItem, items: [BottomSheetModule.Item]) { let viewController = BottomSheetModule.viewController( - image: .remote(url: viewItem.coinImageUrl, placeholder: viewItem.coinPlaceholderImageName), - title: viewItem.coinCode, - subtitle: viewItem.coinName, + image: .remote(url: viewItem.coin.imageUrl, placeholder: viewItem.coinPlaceholderImageName), + title: viewItem.coin.code, + subtitle: viewItem.coin.name, items: items ) @@ -163,14 +164,11 @@ extension ManageWalletsViewController: SectionsDataSource { private func rootElement(index: Int, viewItem: ManageWalletsViewModel.ViewItem, forceToggleOn: Bool? = nil) -> CellBuilderNew.CellElement { .hStack([ .image32 { component in - component.setImage( - urlString: viewItem.imageUrl, - placeholder: viewItem.placeholderImageName.flatMap { UIImage(named: $0) } - ) + component.imageView.setImage(coin: viewItem.coin, placeholder: viewItem.placeholderImageName) }, .vStackCentered([ .hStack([ - .textElement(text: .body(viewItem.title), parameters: .highHugging), + .textElement(text: .body(viewItem.coin.code), parameters: .highHugging), .margin8, .badge { component in component.isHidden = viewItem.badge == nil @@ -181,7 +179,7 @@ extension ManageWalletsViewController: SectionsDataSource { .text { _ in }, ]), .margin(1), - .textElement(text: .subhead2(viewItem.subtitle)), + .textElement(text: .subhead2(viewItem.coin.name)), ]), .secondaryCircleButton { [weak self] component in component.isHidden = !viewItem.hasInfo diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewModel.swift index 3cdfe211de..80ef0fa70f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/ManageWallets/ManageWalletsViewModel.swift @@ -29,10 +29,8 @@ class ManageWalletsViewModel { return ViewItem( uid: String(item.token.hashValue), - imageUrl: token.coin.imageUrl, + coin: token.coin, placeholderImageName: token.placeholderImageName, - title: token.coin.code, - subtitle: token.coin.name, badge: item.token.badge, enabled: item.enabled, hasInfo: item.hasInfo @@ -88,10 +86,8 @@ extension ManageWalletsViewModel { } let coinViewItem = CoinViewItem( - coinImageUrl: infoItem.token.coin.imageUrl, - coinPlaceholderImageName: infoItem.token.placeholderImageName, - coinName: infoItem.token.coin.name, - coinCode: infoItem.token.coin.code + coin: infoItem.token.coin, + coinPlaceholderImageName: infoItem.token.placeholderImageName ) switch infoItem.type { @@ -119,20 +115,16 @@ extension ManageWalletsViewModel { extension ManageWalletsViewModel { struct ViewItem { let uid: String - let imageUrl: String + let coin: Coin let placeholderImageName: String? - let title: String - let subtitle: String let badge: String? let enabled: Bool let hasInfo: Bool } struct CoinViewItem { - let coinImageUrl: String + let coin: Coin let coinPlaceholderImageName: String - let coinName: String - let coinCode: String } struct InfoViewItem { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift index a7618a6bda..04dd5cdac4 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift @@ -114,8 +114,7 @@ struct MarketCoinsView: View { presentedFullCoin = marketInfo.fullCoin }) { itemContent( - imageUrl: URL(string: coin.imageUrl), - code: coin.code, + coin: coin, marketCap: marketInfo.marketCap, price: marketInfo.price.flatMap { ValueFormatter.instance.formatFull(currency: viewModel.currency, value: $0) } ?? "n/a".localized, rank: marketInfo.marketCapRank, @@ -133,8 +132,7 @@ struct MarketCoinsView: View { ThemeList(Array(0 ... 10)) { index in ListRow { itemContent( - imageUrl: nil, - code: "CODE", + coin: nil, marketCap: 123_456, price: "$123.45", rank: 12, @@ -146,16 +144,12 @@ struct MarketCoinsView: View { .simultaneousGesture(DragGesture(minimumDistance: 0), including: .all) } - @ViewBuilder private func itemContent(imageUrl: URL?, code: String, marketCap: Decimal?, price: String, rank: Int?, diff: Decimal?) -> some View { - KFImage.url(imageUrl) - .resizable() - .placeholder { Circle().fill(Color.themeSteel20) } - .clipShape(Circle()) - .frame(width: .iconSize32, height: .iconSize32) + @ViewBuilder private func itemContent(coin: Coin?, marketCap: Decimal?, price: String, rank: Int?, diff: Decimal?) -> some View { + CoinIconView(coin: coin) VStack(spacing: 1) { HStack(spacing: .margin8) { - Text(code).textBody() + Text(coin?.code ?? "CODE").textBody() Spacer() Text(price).textBody() } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketSearchView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketSearchView.swift index 19027a4913..08e4802908 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketSearchView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketSearchView.swift @@ -52,10 +52,7 @@ struct MarketSearchView: View { viewModel.handleOpen(coinUid: coin.uid) presentedFullCoin = fullCoin }) { - KFImage.url(URL(string: coin.imageUrl)) - .resizable() - .placeholder { Circle().fill(Color.themeSteel20) } - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: coin) VStack(spacing: 1) { Text(coin.code).themeBody() diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Pairs/MarketPairsView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Pairs/MarketPairsView.swift index ae77a14c94..32df1390b9 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Pairs/MarketPairsView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Pairs/MarketPairsView.swift @@ -52,8 +52,8 @@ struct MarketPairsView: View { } }) { itemContent( - frontImageUrl: pair.baseCoinUid.flatMap { URL(string: Coin.imageUrl(uid: $0)) }, - backImageUrl: pair.targetCoinUid.flatMap { URL(string: Coin.imageUrl(uid: $0)) }, + frontCoin: pair.baseCoin, + backCoin: pair.targetCoin, base: pair.base, target: pair.target, volume: pair.volume.flatMap { ValueFormatter.instance.formatShort(currency: viewModel.currency, value: $0) } ?? "n/a".localized, @@ -73,8 +73,8 @@ struct MarketPairsView: View { ThemeList(Array(0 ... 10)) { _ in ListRow { itemContent( - frontImageUrl: nil, - backImageUrl: nil, + frontCoin: nil, + backCoin: nil, base: "CODE", target: "CODE", volume: "$123.4 B", @@ -89,7 +89,7 @@ struct MarketPairsView: View { .simultaneousGesture(DragGesture(minimumDistance: 0), including: .all) } - @ViewBuilder private func itemContent(frontImageUrl: URL?, backImageUrl: URL?, base: String, target: String, volume: String, marketName: String, rank: Int, price: String) -> some View { + @ViewBuilder private func itemContent(frontCoin: Coin?, backCoin: Coin?, base: String, target: String, volume: String, marketName: String, rank: Int, price: String) -> some View { ZStack(alignment: .leading) { HStack { Spacer() @@ -98,11 +98,7 @@ struct MarketPairsView: View { .fill(Color.themeTyler) .frame(width: .iconSize32, height: .iconSize32) - KFImage.url(backImageUrl) - .resizable() - .placeholder { Circle().fill(Color.themeSteel20) } - .clipShape(Circle()) - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: backCoin) } } @@ -111,11 +107,7 @@ struct MarketPairsView: View { .fill(Color.themeTyler) .frame(width: .iconSize32, height: .iconSize32) - KFImage.url(frontImageUrl) - .resizable() - .placeholder { Circle().fill(Color.themeSteel20) } - .clipShape(Circle()) - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: frontCoin) } } .frame(width: 52) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/MultiSwapView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/MultiSwapView.swift index 32ce74ef45..2e5e8db7a7 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/MultiSwapView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/MultiSwapView.swift @@ -300,15 +300,7 @@ struct MultiSwapView: View { @ViewBuilder private func selectorButton(token: Token?, action: @escaping () -> Void) -> some View { Button(action: action) { HStack(spacing: .margin8) { - KFImage.url(token.flatMap { - URL(string: $0.coin.imageUrl) - }) - .resizable() - .placeholder { - Circle().fill(Color.themeSteel20) - } - .clipShape(Circle()) - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: token.map(\.coin)) if let token { VStack(alignment: .leading, spacing: 1) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/TokenSelect/MultiSwapTokenSelectView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/TokenSelect/MultiSwapTokenSelectView.swift index c6531116ea..e1085c4c71 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/TokenSelect/MultiSwapTokenSelectView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/MultiSwap/TokenSelect/MultiSwapTokenSelectView.swift @@ -28,12 +28,7 @@ struct MultiSwapTokenSelectView: View { currentToken = item.token isPresented = false }) { - KFImage.url(URL(string: item.token.coin.imageUrl)) - .resizable() - .placeholder { - Image(item.token.placeholderImageName) - } - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: item.token.coin, placeholder: item.token.placeholderImageName) VStack(spacing: 1) { HStack(spacing: .margin8) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Send/Platforms/BaseSendViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Send/Platforms/BaseSendViewController.swift index 8c058fcece..b6bc3e90c2 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Send/Platforms/BaseSendViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Send/Platforms/BaseSendViewController.swift @@ -76,7 +76,7 @@ class BaseSendViewController: ThemeViewController, SectionsDataSource { iconImageView.snp.makeConstraints { make in make.size.equalTo(CGFloat.iconSize24) } - iconImageView.setImage(withUrlString: viewModel.token.coin.imageUrl, placeholder: UIImage(named: viewModel.token.placeholderImageName)) + iconImageView.setImage(coin: viewModel.token.coin, placeholder: viewModel.token.placeholderImageName) iconImageView.tintColor = .themeGray } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/SendEvm/SendEvmViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/SendEvm/SendEvmViewController.swift index fd8333976d..bf4bc623f5 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/SendEvm/SendEvmViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/SendEvm/SendEvmViewController.swift @@ -60,7 +60,7 @@ class SendEvmViewController: ThemeViewController { iconImageView.snp.makeConstraints { make in make.size.equalTo(CGFloat.iconSize24) } - iconImageView.setImage(withUrlString: viewModel.token.coin.imageUrl, placeholder: UIImage(named: viewModel.token.placeholderImageName)) + iconImageView.setImage(coin: viewModel.token.coin, placeholder: viewModel.token.placeholderImageName) view.addSubview(tableView) tableView.snp.makeConstraints { maker in diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/PreSendView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/PreSendView.swift index 181bf9372b..5a02cf3eaf 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/PreSendView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/PreSendView.swift @@ -71,9 +71,7 @@ struct PreSendView: View { .toolbar { ToolbarItem(placement: .navigationBarLeading) { if showIcon { - KFImage.url(URL(string: viewModel.token.coin.imageUrl)) - .resizable() - .frame(width: .iconSize24, height: .iconSize24) + CoinIconView(coin: viewModel.token.coin) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/SendField.swift b/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/SendField.swift index 3229bc466f..c75e0e76b1 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/SendField.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/SendNew/SendField.swift @@ -15,13 +15,7 @@ enum SendField { switch self { case let .amount(title, token, coinValueType, currencyValue, type): ListRow { - KFImage.url(URL(string: token.coin.imageUrl)) - .resizable() - .placeholder { - Circle().fill(Color.themeSteel20) - } - .clipShape(Circle()) - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: token.coin) HStack(spacing: .margin4) { VStack(alignment: .leading, spacing: 1) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/SendTron/SendTronViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/SendTron/SendTronViewController.swift index d251d0e2d4..9513bb602f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/SendTron/SendTronViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/SendTron/SendTronViewController.swift @@ -64,7 +64,7 @@ class SendTronViewController: ThemeViewController { iconImageView.snp.makeConstraints { make in make.size.equalTo(CGFloat.iconSize24) } - iconImageView.setImage(withUrlString: viewModel.token.coin.imageUrl, placeholder: UIImage(named: viewModel.token.placeholderImageName)) + iconImageView.setImage(coin: viewModel.token.coin, placeholder: viewModel.token.placeholderImageName) view.addSubview(tableView) tableView.snp.makeConstraints { maker in diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardCell.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardCell.swift index af501ace44..252529948e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardCell.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardCell.swift @@ -145,11 +145,7 @@ extension SwapCoinCardCell { } private func set(tokenViewItem: SwapCoinCardViewModel.TokenViewItem?) { - if let urlString = tokenViewItem?.iconUrlString { - tokenIconImageView.setImage(withUrlString: urlString, placeholder: tokenViewItem.flatMap { UIImage(named: $0.placeholderIconName) }) - } else { - tokenIconImageView.image = tokenViewItem.flatMap { UIImage(named: $0.placeholderIconName) } - } + tokenIconImageView.setImage(coin: tokenViewItem?.coin, placeholder: tokenViewItem?.placeholderIconName) if let tokenViewItem { tokenSelectButton.setTitle(tokenViewItem.title, for: .normal) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardViewModel.swift index 704ed64a9d..10709dde3f 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Swap/CoinCard/SwapCoinCardViewModel.swift @@ -53,7 +53,7 @@ class SwapCoinCardViewModel { } private func sync(token: MarketKit.Token?) { - tokenViewItemRelay.accept(token.map { TokenViewItem(title: $0.coin.code, iconUrlString: $0.coin.imageUrl, placeholderIconName: $0.placeholderImageName) }) + tokenViewItemRelay.accept(token.map { TokenViewItem(title: $0.coin.code, coin: $0.coin, placeholderIconName: $0.placeholderImageName) }) } private func sync(balance: Decimal?) { @@ -119,7 +119,7 @@ extension SwapCoinCardViewModel { extension SwapCoinCardViewModel { struct TokenViewItem { let title: String - let iconUrlString: String + let coin: Coin let placeholderIconName: String } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/SwapNew/InputCard/SwapInputCardView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/SwapNew/InputCard/SwapInputCardView.swift index ecfe0d35db..f877361b27 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/SwapNew/InputCard/SwapInputCardView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/SwapNew/InputCard/SwapInputCardView.swift @@ -138,11 +138,7 @@ extension SwapInputCardView { } private func set(tokenViewItem: SwapCoinCardViewModel.TokenViewItem?) { - if let urlString = tokenViewItem?.iconUrlString { - tokenSelectView.tokenImage.setImage(urlString: urlString, placeholder: tokenViewItem.flatMap { UIImage(named: $0.placeholderIconName) }) - } else { - tokenSelectView.tokenImage.imageView.image = tokenViewItem.flatMap { UIImage(named: $0.placeholderIconName) } ?? UIImage(named: "placeholder_circle_32") - } + tokenSelectView.tokenImage.imageView.setImage(coin: tokenViewItem?.coin, placeholder: tokenViewItem?.placeholderIconName) if let tokenViewItem { tokenSelectView.tokenButton.setTitle(tokenViewItem.title, for: .normal) diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Transactions/TransactionFilter/TransactionTokenSelectView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Transactions/TransactionFilter/TransactionTokenSelectView.swift index 17addfbb82..8a00c82c33 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Transactions/TransactionFilter/TransactionTokenSelectView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Transactions/TransactionFilter/TransactionTokenSelectView.swift @@ -36,10 +36,7 @@ struct TransactionTokenSelectView: View { viewModel.set(currentToken: token) presentationMode.wrappedValue.dismiss() }) { - KFImage.url(URL(string: token.coin.imageUrl)) - .resizable() - .placeholder { Image(token.placeholderImageName) } - .frame(width: .iconSize32, height: .iconSize32) + CoinIconView(coin: token.coin, placeholder: token.placeholderImageName) VStack(spacing: 1) { HStack(spacing: .margin8) { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/BalanceViewItem.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/BalanceViewItem.swift index bd84a69011..0a38c662ac 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/BalanceViewItem.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/BalanceViewItem.swift @@ -9,8 +9,8 @@ struct BalanceViewItem { struct BalanceTopViewItem { let isMainNet: Bool - let iconUrlString: String? - let placeholderIconName: String + let coin: Coin? + let placeholderIconName: String? let name: String let blockchainBadge: String? @@ -43,7 +43,7 @@ enum BalanceDiffType { extension BalanceTopViewItem: Equatable { static func == (lhs: BalanceTopViewItem, rhs: BalanceTopViewItem) -> Bool { lhs.isMainNet == rhs.isMainNet && - lhs.iconUrlString == rhs.iconUrlString && + lhs.coin == rhs.coin && lhs.name == rhs.name && lhs.blockchainBadge == rhs.blockchainBadge && lhs.syncSpinnerProgress == rhs.syncSpinnerProgress && @@ -100,7 +100,7 @@ extension BalanceViewItem: CustomStringConvertible { extension BalanceTopViewItem: CustomStringConvertible { var description: String { - "[iconUrlString: \(iconUrlString ?? "nil"); name: \(name); blockchainBadge: \(blockchainBadge ?? "nil"); syncSpinnerProgress: \(syncSpinnerProgress.map { "\($0)" } ?? "nil"); indefiniteSearchCircle: \(indefiniteSearchCircle); failedImageViewVisible: \(failedImageViewVisible); primaryValue: \(primaryValue.map { "[text: \($0.text ?? "nil"); dimmed: \($0.dimmed)]" } ?? "nil"); secondaryInfo: \(secondaryInfo)]" + "[coin: \(coin?.name ?? "nil"); name: \(name); blockchainBadge: \(blockchainBadge ?? "nil"); syncSpinnerProgress: \(syncSpinnerProgress.map { "\($0)" } ?? "nil"); indefiniteSearchCircle: \(indefiniteSearchCircle); failedImageViewVisible: \(failedImageViewVisible); primaryValue: \(primaryValue.map { "[text: \($0.text ?? "nil"); dimmed: \($0.dimmed)]" } ?? "nil"); secondaryInfo: \(secondaryInfo)]" } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewController.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewController.swift index 29545ae399..0a42aec6bc 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewController.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewController.swift @@ -88,7 +88,7 @@ extension ReceiveSelectCoinViewController: SectionsDataSource { return tableView.universalRow62( id: viewItem.uid, - image: .url(viewItem.imageUrl, placeholder: "placeholder_circle_32"), + image: .url(viewItem.coin), title: .body(viewItem.title), description: .subhead2(viewItem.description), backgroundStyle: .transparent, diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewModel.swift index eaece4363d..fc60dabb4e 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Receive/SelectCoin/ReceiveSelectCoinViewModel.swift @@ -22,7 +22,7 @@ class ReceiveSelectCoinViewModel { private func sync(coins: [FullCoin]) { viewItems = coins.map { fullCoin -> ViewItem in - ViewItem(uid: fullCoin.coin.uid, imageUrl: fullCoin.coin.imageUrl, title: fullCoin.coin.code, description: fullCoin.coin.name) + ViewItem(uid: fullCoin.coin.uid, coin: fullCoin.coin, title: fullCoin.coin.code, description: fullCoin.coin.name) } } } @@ -42,7 +42,7 @@ extension ReceiveSelectCoinViewModel { extension ReceiveSelectCoinViewModel { struct ViewItem { let uid: String - let imageUrl: String? + let coin: Coin? let title: String let description: String } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/Views/WalletTokenBalanceCell.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/Views/WalletTokenBalanceCell.swift index e7ec18935f..5f18edc284 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/Views/WalletTokenBalanceCell.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/Views/WalletTokenBalanceCell.swift @@ -71,7 +71,7 @@ class WalletTokenBalanceCell: UITableViewCell { func bind(viewItem: WalletTokenBalanceViewModel.ViewItem, onTapError: (() -> Void)?) { testnetImageView.isHidden = viewItem.isMainNet coinIconView.bind( - iconUrlString: viewItem.iconUrlString, + coin: viewItem.coin, placeholderIconName: viewItem.placeholderIconName, spinnerProgress: viewItem.syncSpinnerProgress, indefiniteSearchCircle: viewItem.indefiniteSearchCircle, diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift index dc1ea0e164..5e09fef204 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewItemFactory.swift @@ -39,8 +39,8 @@ class WalletTokenBalanceViewItemFactory { return WalletTokenBalanceViewModel.ViewItem( isMainNet: item.isMainNet, - iconUrlString: iconUrlString(coin: item.element.coin, state: state), - placeholderIconName: item.element.wallet?.token.placeholderImageName ?? "placeholder_circle_32", + coin: stateAwareCoin(coin: item.element.coin, state: state), + placeholderIconName: item.element.wallet?.token.placeholderImageName, syncSpinnerProgress: syncSpinnerProgress(state: state), indefiniteSearchCircle: indefiniteSearchCircle(state: state), failedImageViewVisible: failedImageViewVisible(state: state), @@ -74,10 +74,10 @@ class WalletTokenBalanceViewItemFactory { } } - private func iconUrlString(coin: Coin?, state: AdapterState) -> String? { + private func stateAwareCoin(coin: Coin?, state: AdapterState) -> Coin? { switch state { case .notSynced: return nil - default: return coin?.imageUrl + default: return coin } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewModel.swift index c1001c6ad5..4e5d100192 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Token/DataSources/WalletTokenBalance/WalletTokenBalanceViewModel.swift @@ -138,8 +138,8 @@ extension WalletTokenBalanceViewModel { struct ViewItem { let isMainNet: Bool - let iconUrlString: String? - let placeholderIconName: String + let coin: Coin? + let placeholderIconName: String? let syncSpinnerProgress: Int? let indefiniteSearchCircle: Bool diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/TokenList/WalletTokenListViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/TokenList/WalletTokenListViewItemFactory.swift index d71e6e7c81..5428f4a194 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/TokenList/WalletTokenListViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/TokenList/WalletTokenListViewItemFactory.swift @@ -11,8 +11,8 @@ class WalletTokenListViewItemFactory { return BalanceTopViewItem( isMainNet: item.isMainNet, - iconUrlString: iconUrlString(coin: item.element.coin, state: state), - placeholderIconName: item.element.wallet?.token.placeholderImageName ?? "placeholder_circle_32", + coin: stateAwareCoin(coin: item.element.coin, state: state), + placeholderIconName: item.element.wallet?.token.placeholderImageName, name: item.element.name, blockchainBadge: item.element.wallet?.badge, syncSpinnerProgress: syncSpinnerProgress(state: state), @@ -43,10 +43,10 @@ class WalletTokenListViewItemFactory { } } - private func iconUrlString(coin: Coin?, state: AdapterState) -> String? { + private func stateAwareCoin(coin: Coin?, state: AdapterState) -> Coin? { switch state { case .notSynced: return nil - default: return coin?.imageUrl + default: return coin } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceCoinIconHolder.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceCoinIconHolder.swift index 59b19aefbd..8e5270134b 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceCoinIconHolder.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceCoinIconHolder.swift @@ -1,5 +1,6 @@ import ComponentKit import HUD +import MarketKit import ThemeKit import UIKit @@ -49,12 +50,12 @@ class BalanceCoinIconHolder: UIView { onTapError?() } - func bind(iconUrlString: String?, placeholderIconName: String, spinnerProgress: Int?, indefiniteSearchCircle: Bool, failViewVisible: Bool, onTapError: (() -> Void)?) { + func bind(coin: Coin?, placeholderIconName: String?, spinnerProgress: Int?, indefiniteSearchCircle: Bool, failViewVisible: Bool, onTapError: (() -> Void)?) { self.onTapError = onTapError - coinIconImageView.isHidden = iconUrlString == nil - if let iconUrlString { - coinIconImageView.setImage(withUrlString: iconUrlString, placeholder: UIImage(named: placeholderIconName)) + coinIconImageView.isHidden = coin == nil + if let coin { + coinIconImageView.setImage(coin: coin, placeholder: placeholderIconName) } else { coinIconImageView.image = nil } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceTopView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceTopView.swift index 9fcdee0c32..53df65cf97 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceTopView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/Views/BalanceTopView.swift @@ -102,7 +102,7 @@ class BalanceTopView: UIView { func bind(viewItem: BalanceTopViewItem, onTapError: (() -> Void)?) { coinIconView.bind( - iconUrlString: viewItem.iconUrlString, + coin: viewItem.coin, placeholderIconName: viewItem.placeholderIconName, spinnerProgress: viewItem.syncSpinnerProgress, indefiniteSearchCircle: viewItem.indefiniteSearchCircle, diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift index e05aeecf2e..a0dda38c09 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Wallet/WalletViewItemFactory.swift @@ -11,8 +11,8 @@ class WalletViewItemFactory { return BalanceTopViewItem( isMainNet: item.isMainNet, - iconUrlString: iconUrlString(coin: item.element.coin, state: state), - placeholderIconName: item.element.wallet?.token.placeholderImageName ?? "placeholder_circle_32", + coin: stateAwareCoin(coin: item.element.coin, state: state), + placeholderIconName: item.element.wallet?.token.placeholderImageName, name: item.element.name, blockchainBadge: item.element.wallet?.badge, syncSpinnerProgress: syncSpinnerProgress(state: state), @@ -43,10 +43,10 @@ class WalletViewItemFactory { } } - private func iconUrlString(coin: Coin?, state: AdapterState) -> String? { + private func stateAwareCoin(coin: Coin?, state: AdapterState) -> Coin? { switch state { case .notSynced: return nil - default: return coin?.imageUrl + default: return coin } } diff --git a/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/CellElement.swift b/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/CellElement.swift index b16633546c..09203435e2 100644 --- a/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/CellElement.swift +++ b/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/CellElement.swift @@ -1,4 +1,5 @@ import ComponentKit +import MarketKit import UIKit extension CellBuilderNew.CellElement { // prepared cell elements for most frequency used layouts @@ -42,9 +43,12 @@ extension CellBuilderNew.CellElement { // prepared cell elements for most freque if let image = image.image { // setup local image component.imageView.image = image } else if let url = image.url { // setup global url with placeholder - component.imageView.setImage(withUrlString: url, placeholder: image.placeholder.flatMap { - UIImage(named: $0) - }) + component.imageView.setImage( + withUrlString: url, + placeholder: image.placeholder.flatMap { UIImage(named: $0) } + ) + } else if let coin = image.coin { + component.imageView.setImage(coin: coin) } else { component.isHidden = true } @@ -84,12 +88,14 @@ extension CellBuilderNew.CellElement { // prepared cell elements for most freque extension CellBuilderNew.CellElement { struct Image { - static func local(_ image: UIImage?) -> Self { Image(image: image, url: nil, placeholder: nil) } - static func url(_ url: String?, placeholder: String? = nil) -> Self { Image(image: nil, url: url, placeholder: placeholder) } + static func local(_ image: UIImage?) -> Self { Image(image: image, url: nil, placeholder: nil, coin: nil) } + static func url(_ url: String?, placeholder: String? = nil) -> Self { Image(image: nil, url: url, placeholder: placeholder, coin: nil) } + static func url(_ coin: Coin?) -> Self { Image(image: nil, url: nil, placeholder: nil, coin: coin) } let image: UIImage? let url: String? let placeholder: String? + let coin: Coin? } enum ImageSize { diff --git a/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/UIImageView.swift b/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/UIImageView.swift new file mode 100644 index 0000000000..ce67351262 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/UserInterface/Extensions/UIImageView.swift @@ -0,0 +1,37 @@ +import Alamofire +import Kingfisher +import MarketKit +import UIKit + +extension UIImageView { + func setImage(coin: Coin?, placeholder: String? = nil) { + let options: [KingfisherOptionsInfoItem] = [.scaleFactor(UIScreen.main.scale)] + let placeholder = UIImage(named: placeholder ?? "placeholder_circle_32") + + if let alternativeUrlString = coin?.image, let alternativeUrl = URL(string: alternativeUrlString) { + if ImageCache.default.isCached(forKey: alternativeUrlString) { + kf.setImage( + with: alternativeUrl, + placeholder: placeholder, + options: options + ) + } else { + kf.setImage( + with: URL(string: coin?.imageUrl ?? ""), + placeholder: placeholder, + options: options + [.alternativeSources([.network(alternativeUrl)])] + ) + } + } else { + kf.setImage( + with: URL(string: coin?.imageUrl ?? ""), + placeholder: placeholder, + options: options + ) + + return + } + + cornerRadius = CGFloat.iconSize32 / 2 + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/CoinIconView.swift b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/CoinIconView.swift new file mode 100644 index 0000000000..31c84fc9a2 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/UserInterface/SwiftUI/CoinIconView.swift @@ -0,0 +1,39 @@ +import Kingfisher +import MarketKit +import SwiftUI + +struct CoinIconView: View { + let coin: Coin? + let placeholder: String + + init(coin: Coin?, placeholder: String = "placeholder_circle_32") { + self.coin = coin + self.placeholder = placeholder + } + + var body: some View { + if let alternativeUrlString = coin?.image, let alternativeUrl = URL(string: alternativeUrlString) { + if ImageCache.default.isCached(forKey: alternativeUrlString) { + icon(alternativeUrl) + .clipShape(Circle()) + .frame(width: .iconSize32, height: .iconSize32) + } else { + icon(coin.flatMap { URL(string: $0.imageUrl) }).alternativeSources([.network(alternativeUrl)]) + .clipShape(Circle()) + .frame(width: .iconSize32, height: .iconSize32) + } + } else { + icon(coin.flatMap { URL(string: $0.imageUrl) }) + .clipShape(Circle()) + .frame(width: .iconSize32, height: .iconSize32) + } + } + + @ViewBuilder func icon(_ url: URL?) -> some KFImageProtocol { + KFImage.url(url) + .resizable() + .placeholder { + Image(placeholder) + } + } +}