From c8357ad362632d9f1272a7c1673821d4c0f3686e Mon Sep 17 00:00:00 2001 From: EA Date: Thu, 16 May 2024 12:26:48 +0600 Subject: [PATCH] Add watchlist swipe actions to new Market module --- .../project.pbxproj | 20 ++++++++ .../Storage/FavoriteCoinRecordStorage.swift | 24 ++++----- .../Backup/ICloud/AppBackupProvider.swift | 2 +- .../Modules/Coin/CoinPageService.swift | 7 ++- .../Modules/Favorites/FavoritesManager.swift | 49 +++++++++++-------- .../Market/Coins/MarketCoinsView.swift | 6 ++- .../Market/Favorites/FavoritesModifier.swift | 33 +++++++++++++ .../Market/Favorites/FavoritesViewModel.swift | 26 ++++++++++ .../MarketWatchlistService.swift | 7 ++- .../Watchlist/MarketWatchlistView.swift | 12 ++++- .../Watchlist/MarketWatchlistViewModel.swift | 39 ++++++++++++--- .../BackupApp/Backup/BackupAppViewModel.swift | 2 +- 12 files changed, 177 insertions(+), 50 deletions(-) create mode 100644 UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesModifier.swift create mode 100644 UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesViewModel.swift diff --git a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj index 6b7af6a631..26e2b14c8d 100644 --- a/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj +++ b/UnstoppableWallet/UnstoppableWallet.xcodeproj/project.pbxproj @@ -2982,6 +2982,10 @@ D31C4764238BF176008CB818 /* FeeRateState.swift in Sources */ = {isa = PBXBuildFile; fileRef = D31C475A238BF175008CB818 /* FeeRateState.swift */; }; D339A93D29126D0F00B895BE /* HsCryptoKit in Frameworks */ = {isa = PBXBuildFile; productRef = D339A93C29126D0F00B895BE /* HsCryptoKit */; }; D339A93F29126D2A00B895BE /* HsCryptoKit in Frameworks */ = {isa = PBXBuildFile; productRef = D339A93E29126D2A00B895BE /* HsCryptoKit */; }; + D3402AEE2BF5D58B003BF6F8 /* FavoritesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3402AED2BF5D58B003BF6F8 /* FavoritesViewModel.swift */; }; + D3402AEF2BF5D58B003BF6F8 /* FavoritesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3402AED2BF5D58B003BF6F8 /* FavoritesViewModel.swift */; }; + D3402AF12BF5D59D003BF6F8 /* FavoritesModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3402AF02BF5D59D003BF6F8 /* FavoritesModifier.swift */; }; + D3402AF22BF5D59D003BF6F8 /* FavoritesModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D3402AF02BF5D59D003BF6F8 /* FavoritesModifier.swift */; }; D3447DEA25E38300009928D9 /* WalletConnectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B968B299A67FC7FEAE3 /* WalletConnectManager.swift */; }; D3447DEB25E38300009928D9 /* WalletConnectManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 11B35B968B299A67FC7FEAE3 /* WalletConnectManager.swift */; }; D34903172BE8DF48005F147B /* BinanceSendHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = D34903162BE8DF48005F147B /* BinanceSendHandler.swift */; }; @@ -4885,6 +4889,8 @@ D3285F5120BD158F00644076 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D3373D9420BEC7B30082BC4A /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; D3373DB120C52F640082BC4A /* LaunchScreen.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = ""; }; + D3402AED2BF5D58B003BF6F8 /* FavoritesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesViewModel.swift; sourceTree = ""; }; + D3402AF02BF5D59D003BF6F8 /* FavoritesModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoritesModifier.swift; sourceTree = ""; }; D34903162BE8DF48005F147B /* BinanceSendHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinanceSendHandler.swift; sourceTree = ""; }; D34903192BE8DF5F005F147B /* BinancePreSendHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BinancePreSendHandler.swift; sourceTree = ""; }; D34E941B21F86C3500AD8E90 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -7722,6 +7728,7 @@ 58AAA9EB9618EBC895D0B123 /* Market */ = { isa = PBXGroup; children = ( + D3402AEC2BF5D569003BF6F8 /* Favorites */, D3833AFA2BF335B800ACECFB /* News */, D3833AF02BF20B7200ACECFB /* Pairs */, D3833AEC2BF1F0AC00ACECFB /* Platform */, @@ -9288,6 +9295,15 @@ path = UnstoppableWallet; sourceTree = ""; }; + D3402AEC2BF5D569003BF6F8 /* Favorites */ = { + isa = PBXGroup; + children = ( + D3402AED2BF5D58B003BF6F8 /* FavoritesViewModel.swift */, + D3402AF02BF5D59D003BF6F8 /* FavoritesModifier.swift */, + ); + path = Favorites; + sourceTree = ""; + }; D3833AD52BEE1A2900ACECFB /* Watchlist */ = { isa = PBXGroup; children = ( @@ -10619,12 +10635,14 @@ 11B35052C5059CDD8E4BA940 /* BackupMnemonicWordCell.swift in Sources */, 11B35DF1D8B5125CF13A1812 /* RestoreMnemonicHintView.swift in Sources */, 11B35C8A1082D0A8F0B354B1 /* RestoreMnemonicHintCell.swift in Sources */, + D3402AF22BF5D59D003BF6F8 /* FavoritesModifier.swift in Sources */, 11B35AC9650545DEBC6C2C90 /* EvmAccountRestoreState.swift in Sources */, 11B35EBC6D5608F23DF8581E /* EvmAccountRestoreStateManager.swift in Sources */, 11B35C43886D9A0F0C69EF33 /* EvmAccountRestoreStateStorage.swift in Sources */, 11B35B100187D9909A8490A7 /* NftAdapterManager.swift in Sources */, 11B35EC3B9E9C778183E1136 /* EvmNftAdapter.swift in Sources */, 11B350F58D6907C9A9A79F6B /* NftViewController.swift in Sources */, + D3402AEF2BF5D58B003BF6F8 /* FavoritesViewModel.swift in Sources */, 11B3593134900A8FC7C075B6 /* NftService.swift in Sources */, 11B35B6C74E672B2699E8207 /* NftModule.swift in Sources */, 11B35F8649859802080BA580 /* NftViewModel.swift in Sources */, @@ -12177,12 +12195,14 @@ 6BCD53022A161F4100993F20 /* ICloudBackupTermsViewModel.swift in Sources */, 11B35066480B6EB9F124EBC0 /* ExtendedKeyService.swift in Sources */, 11B359601D8967EEE00B5991 /* BackupMnemonicWordsCell.swift in Sources */, + D3402AF12BF5D59D003BF6F8 /* FavoritesModifier.swift in Sources */, 11B3590E40C88ADD16DEEABB /* BackupMnemonicWordCell.swift in Sources */, 11B35FD18C255E2C6D75F38A /* RestoreMnemonicHintView.swift in Sources */, 11B356BCDD5E64C6D6F49489 /* RestoreMnemonicHintCell.swift in Sources */, 11B35B152001ADE5E98D1414 /* EvmAccountRestoreState.swift in Sources */, 11B3573F7ED8577EF9F12EF9 /* EvmAccountRestoreStateManager.swift in Sources */, 11B3563B5D19C7A4EDFC8FC1 /* EvmAccountRestoreStateStorage.swift in Sources */, + D3402AEE2BF5D58B003BF6F8 /* FavoritesViewModel.swift in Sources */, 11B356C6C07BE3588A5D52DE /* NftAdapterManager.swift in Sources */, 11B3583C1A73A11974ADAEBB /* EvmNftAdapter.swift in Sources */, 11B3575108E28705A2F47BA9 /* NftViewController.swift in Sources */, diff --git a/UnstoppableWallet/UnstoppableWallet/Core/Storage/FavoriteCoinRecordStorage.swift b/UnstoppableWallet/UnstoppableWallet/Core/Storage/FavoriteCoinRecordStorage.swift index bcbd06869e..ed1ddde25d 100644 --- a/UnstoppableWallet/UnstoppableWallet/Core/Storage/FavoriteCoinRecordStorage.swift +++ b/UnstoppableWallet/UnstoppableWallet/Core/Storage/FavoriteCoinRecordStorage.swift @@ -9,43 +9,43 @@ class FavoriteCoinRecordStorage { } extension FavoriteCoinRecordStorage { - var favoriteCoinRecords: [FavoriteCoinRecord] { - try! dbPool.read { db in + func favoriteCoinRecords() throws -> [FavoriteCoinRecord] { + try dbPool.read { db in try FavoriteCoinRecord.fetchAll(db) } } - func save(favoriteCoinRecord: FavoriteCoinRecord) { - _ = try! dbPool.write { db in + func save(favoriteCoinRecord: FavoriteCoinRecord) throws { + _ = try dbPool.write { db in try favoriteCoinRecord.insert(db) } } - func save(favoriteCoinRecords: [FavoriteCoinRecord]) { - _ = try? dbPool.write { db in + func save(favoriteCoinRecords: [FavoriteCoinRecord]) throws { + _ = try dbPool.write { db in for record in favoriteCoinRecords { try record.insert(db) } } } - func deleteAll() { - _ = try! dbPool.write { db in + func deleteAll() throws { + _ = try dbPool.write { db in try FavoriteCoinRecord .deleteAll(db) } } - func deleteFavoriteCoinRecord(coinUid: String) { - _ = try! dbPool.write { db in + func deleteFavoriteCoinRecord(coinUid: String) throws { + _ = try dbPool.write { db in try FavoriteCoinRecord .filter(FavoriteCoinRecord.Columns.coinUid == coinUid) .deleteAll(db) } } - func favoriteCoinRecordExists(coinUid: String) -> Bool { - try! dbPool.read { db in + func favoriteCoinRecordExists(coinUid: String) throws -> Bool { + try dbPool.read { db in try FavoriteCoinRecord .filter(FavoriteCoinRecord.Columns.coinUid == coinUid) .fetchCount(db) > 0 diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Backup/ICloud/AppBackupProvider.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Backup/ICloud/AppBackupProvider.swift index d9f33e1ad6..3458a90929 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Backup/ICloud/AppBackupProvider.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Backup/ICloud/AppBackupProvider.swift @@ -125,7 +125,7 @@ class AppBackupProvider { let syncSources = EvmSyncSourceManager.SyncSourceBackup(selected: selected, custom: []) return RawFullBackup( accounts: accounts, - watchlistIds: favoritesManager.allCoinUids, + watchlistIds: Array(favoritesManager.coinUids), contacts: contactManager.backupContactBook?.contacts ?? [], settings: settings(evmSyncSources: syncSources), customSyncSources: custom diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageService.swift index 0f133c66cd..d724038b0a 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Coin/CoinPageService.swift @@ -1,3 +1,4 @@ +import Combine import Foundation import MarketKit import RxRelay @@ -6,7 +7,7 @@ import RxSwift class CoinPageService { let fullCoin: FullCoin private let favoritesManager: FavoritesManager - private let disposeBag = DisposeBag() + private var cancellables = Set() private let favoriteRelay = PublishRelay() private(set) var favorite: Bool = false { @@ -21,7 +22,9 @@ class CoinPageService { self.fullCoin = fullCoin self.favoritesManager = favoritesManager - subscribe(disposeBag, favoritesManager.coinUidsUpdatedObservable) { [weak self] in self?.syncFavorite() } + favoritesManager.coinUidsPublisher + .sink { [weak self] _ in self?.syncFavorite() } + .store(in: &cancellables) syncFavorite() } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Favorites/FavoritesManager.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Favorites/FavoritesManager.swift index 5eda17f1c3..8995332985 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Favorites/FavoritesManager.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Favorites/FavoritesManager.swift @@ -1,58 +1,65 @@ -import RxCocoa -import RxSwift +import Combine import WidgetKit class FavoritesManager { private let storage: FavoriteCoinRecordStorage private let sharedStorage: SharedLocalStorage - private let coinUidsUpdatedRelay = PublishRelay() + private let coinUidsSubject = PassthroughSubject, Never>() + + var coinUids: Set { + didSet { + coinUidsSubject.send(coinUids) + syncSharedStorage() + } + } init(storage: FavoriteCoinRecordStorage, sharedStorage: SharedLocalStorage) { self.storage = storage self.sharedStorage = sharedStorage + do { + let records = try storage.favoriteCoinRecords() + coinUids = Set(records.map(\.coinUid)) + } catch { + coinUids = Set() + } + syncSharedStorage() } private func syncSharedStorage() { - sharedStorage.set(value: allCoinUids, for: AppWidgetConstants.keyFavoriteCoinUids) + sharedStorage.set(value: Array(coinUids), for: AppWidgetConstants.keyFavoriteCoinUids) WidgetCenter.shared.reloadTimelines(ofKind: AppWidgetConstants.watchlistWidgetKind) } } extension FavoritesManager { - var coinUidsUpdatedObservable: Observable { - coinUidsUpdatedRelay.asObservable() - } - - var allCoinUids: [String] { - storage.favoriteCoinRecords.map(\.coinUid) + var coinUidsPublisher: AnyPublisher, Never> { + coinUidsSubject.eraseToAnyPublisher() } func add(coinUid: String) { - storage.save(favoriteCoinRecord: FavoriteCoinRecord(coinUid: coinUid)) - coinUidsUpdatedRelay.accept(()) - syncSharedStorage() + coinUids.insert(coinUid) + try? storage.save(favoriteCoinRecord: FavoriteCoinRecord(coinUid: coinUid)) } func add(coinUids: [String]) { - storage.save(favoriteCoinRecords: coinUids.map { FavoriteCoinRecord(coinUid: $0) }) - coinUidsUpdatedRelay.accept(()) - syncSharedStorage() + self.coinUids.formUnion(coinUids) + try? storage.save(favoriteCoinRecords: coinUids.map { FavoriteCoinRecord(coinUid: $0) }) } func removeAll() { - storage.deleteAll() + coinUids = Set() + try? storage.deleteAll() } func remove(coinUid: String) { - storage.deleteFavoriteCoinRecord(coinUid: coinUid) - coinUidsUpdatedRelay.accept(()) - syncSharedStorage() + coinUids.remove(coinUid) + try? storage.deleteFavoriteCoinRecord(coinUid: coinUid) } func isFavorite(coinUid: String) -> Bool { - storage.favoriteCoinRecordExists(coinUid: coinUid) + coinUids.contains(coinUid) } } diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift index 51d5b98b95..cfd8eae6ec 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Coins/MarketCoinsView.swift @@ -4,6 +4,7 @@ import SwiftUI struct MarketCoinsView: View { @ObservedObject var viewModel: MarketCoinsViewModel + @StateObject var favoritesViewModel = FavoritesViewModel() @State private var sortBySelectorPresented = false @State private var topSelectorPresented = false @@ -107,11 +108,11 @@ struct MarketCoinsView: View { @ViewBuilder private func list(marketInfos: [MarketInfo]) -> some View { ThemeList(items: marketInfos) { marketInfo in + let coin = marketInfo.fullCoin.coin + ClickableRow(action: { presentedFullCoin = marketInfo.fullCoin }) { - let coin = marketInfo.fullCoin.coin - itemContent( imageUrl: URL(string: coin.imageUrl), code: coin.code, @@ -121,6 +122,7 @@ struct MarketCoinsView: View { diff: marketInfo.priceChangeValue(timePeriod: viewModel.timePeriod) ) } + .favoriteSwipeActions(viewModel: favoritesViewModel, coinUid: coin.uid) } .themeListStyle(.transparent) .refreshable { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesModifier.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesModifier.swift new file mode 100644 index 0000000000..ed3b8b42bd --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesModifier.swift @@ -0,0 +1,33 @@ +import SwiftUI + +struct FavoritesModifier: ViewModifier { + @ObservedObject var viewModel: FavoritesViewModel + let coinUid: String + + func body(content: Content) -> some View { + content + .swipeActions { + if viewModel.coinUids.contains(coinUid) { + Button { + viewModel.remove(coinUid: coinUid) + } label: { + Image("star_off_24").renderingMode(.template) + } + .tint(.themeLucian) + } else { + Button { + viewModel.add(coinUid: coinUid) + } label: { + Image("star_24").renderingMode(.template) + } + .tint(.themeJacob) + } + } + } +} + +extension View { + func favoriteSwipeActions(viewModel: FavoritesViewModel, coinUid: String) -> some View { + modifier(FavoritesModifier(viewModel: viewModel, coinUid: coinUid)) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesViewModel.swift new file mode 100644 index 0000000000..ac2b9a7fc6 --- /dev/null +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Favorites/FavoritesViewModel.swift @@ -0,0 +1,26 @@ +import Combine + +class FavoritesViewModel: ObservableObject { + private let favoritesManager = App.shared.favoritesManager + private var cancellables = Set() + + @Published var coinUids: Set + + init() { + coinUids = favoritesManager.coinUids + + favoritesManager.coinUidsPublisher + .sink { [weak self] in self?.coinUids = $0 } + .store(in: &cancellables) + } +} + +extension FavoritesViewModel { + func add(coinUid: String) { + favoritesManager.add(coinUid: coinUid) + } + + func remove(coinUid: String) { + favoritesManager.remove(coinUid: coinUid) + } +} diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistService.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistService.swift index a05b1f1580..188a3b9e24 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistService.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/MarketWatchlist/MarketWatchlistService.swift @@ -43,7 +43,7 @@ class MarketWatchlistService: IMarketSingleSortHeaderService { } private func syncCoinUids() { - coinUids = favoritesManager.allCoinUids + coinUids = Array(favoritesManager.coinUids) if case let .loaded(marketInfos, _, _) = state { let newMarketInfos = marketInfos.filter { marketInfo in @@ -107,7 +107,10 @@ extension MarketWatchlistService: IMarketListService { } .store(in: &cancellables) - subscribe(disposeBag, favoritesManager.coinUidsUpdatedObservable) { [weak self] in self?.syncCoinUids() } + favoritesManager.coinUidsPublisher + .sink { [weak self] _ in self?.syncCoinUids() } + .store(in: &cancellables) + subscribe(disposeBag, appManager.willEnterForegroundObservable) { [weak self] in self?.syncMarketInfos() } syncCoinUids() diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistView.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistView.swift index 0a98d456c0..41722b4ff7 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistView.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistView.swift @@ -108,11 +108,11 @@ struct MarketWatchlistView: View { @ViewBuilder private func list(marketInfos: [MarketInfo], signals: [String: TechnicalAdvice.Advice]) -> some View { ThemeList(items: marketInfos) { marketInfo in + let coin = marketInfo.fullCoin.coin + ClickableRow(action: { presentedFullCoin = marketInfo.fullCoin }) { - let coin = marketInfo.fullCoin.coin - itemContent( imageUrl: URL(string: coin.imageUrl), code: coin.code, @@ -123,6 +123,14 @@ struct MarketWatchlistView: View { signal: viewModel.showSignals ? signals[coin.uid] : nil ) } + .swipeActions { + Button(role: .destructive) { + viewModel.remove(coinUid: coin.uid) + } label: { + Image("star_off_24").renderingMode(.template) + } + .tint(.themeLucian) + } } .themeListStyle(.transparent) .refreshable { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistViewModel.swift index fbeaaefcd8..579f5d40bb 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Market/Watchlist/MarketWatchlistViewModel.swift @@ -2,14 +2,17 @@ import Combine import Foundation import HsExtensions import MarketKit -import RxSwift class MarketWatchlistViewModel: ObservableObject { + private let keySortBy = "market-watchlist-sort-by" + private let keyTimePeriod = "market-watchlist-time-period" + private let keyShowSignals = "market-watchlist-show-signals" + private let marketKit = App.shared.marketKit private let currencyManager = App.shared.currencyManager private let favoritesManager = App.shared.favoritesManager + private let userDefaultsStorage = App.shared.userDefaultsStorage - private let disposeBag = DisposeBag() private var cancellables = Set() private var tasks = Set() @@ -23,26 +26,42 @@ class MarketWatchlistViewModel: ObservableObject { @Published var state: State = .loading - var sortBy: MarketModule.SortBy = .gainers { + var sortBy: MarketModule.SortBy { didSet { syncState() + + userDefaultsStorage.set(value: sortBy.rawValue, for: keySortBy) } } - var timePeriod: HsTimePeriod = .day1 { + var timePeriod: HsTimePeriod { didSet { syncState() + + userDefaultsStorage.set(value: timePeriod.rawValue, for: keyTimePeriod) } } - var showSignals: Bool = false { + var showSignals: Bool { didSet { syncState() + + userDefaultsStorage.set(value: showSignals, for: keyShowSignals) } } + init() { + let sortByRaw: String? = userDefaultsStorage.value(for: keySortBy) + sortBy = sortByRaw.flatMap { MarketModule.SortBy(rawValue: $0) } ?? .gainers + + let timePeriodRaw: String? = userDefaultsStorage.value(for: keyTimePeriod) + timePeriod = timePeriodRaw.flatMap { HsTimePeriod(rawValue: $0) } ?? .day1 + + showSignals = userDefaultsStorage.value(for: keyShowSignals) ?? true + } + private func syncCoinUids() { - coinUids = favoritesManager.allCoinUids + coinUids = Array(favoritesManager.coinUids) if case let .loaded(marketInfos, signals) = internalState { let newMarketInfos = marketInfos.filter { marketInfo in @@ -128,7 +147,9 @@ extension MarketWatchlistViewModel { } .store(in: &cancellables) - subscribe(disposeBag, favoritesManager.coinUidsUpdatedObservable) { [weak self] in self?.syncCoinUids() } + favoritesManager.coinUidsPublisher + .sink { [weak self] _ in self?.syncCoinUids() } + .store(in: &cancellables) syncCoinUids() } @@ -136,6 +157,10 @@ extension MarketWatchlistViewModel { func refresh() async { await _syncMarketInfos() } + + func remove(coinUid: String) { + favoritesManager.remove(coinUid: coinUid) + } } extension MarketWatchlistViewModel { diff --git a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/BackupApp/Backup/BackupAppViewModel.swift b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/BackupApp/Backup/BackupAppViewModel.swift index 0d12ce176b..4dbf6f4528 100644 --- a/UnstoppableWallet/UnstoppableWallet/Modules/Settings/BackupApp/Backup/BackupAppViewModel.swift +++ b/UnstoppableWallet/UnstoppableWallet/Modules/Settings/BackupApp/Backup/BackupAppViewModel.swift @@ -149,7 +149,7 @@ extension BackupAppViewModel { return BackupAppModule.items( watchAccountCount: accounts(watch: true).count, - watchlistCount: favoritesManager.allCoinUids.count, + watchlistCount: favoritesManager.coinUids.count, contactAddressCount: contacts.count, blockchainSourcesCount: evmSyncSourceManager.customSyncSources(blockchainType: nil).count )