diff --git a/Features/WalletTab/Sources/Types/WalletSceneSheetType.swift b/Features/WalletTab/Sources/Types/WalletSceneSheetType.swift new file mode 100644 index 000000000..a3a15c9e2 --- /dev/null +++ b/Features/WalletTab/Sources/Types/WalletSceneSheetType.swift @@ -0,0 +1,100 @@ +// Copyright (c). Gem Wallet. All rights reserved. + +import Foundation +import InfoSheet +import Primitives +import SwiftUI + +public enum WalletSceneSheetType: Identifiable, Sendable { + case wallets + case selectAssetType(SelectAssetType) + case info(InfoSheetType) + case url(URL) + case transferData(TransferData) + case perpetualRecipientData(PerpetualRecipientData) + case setPriceAlert(AssetId) + + public var id: String { + switch self { + case .wallets: "wallets" + case let .selectAssetType(type): "select-asset-type-\(type.id)" + case let .info(type): "info-\(type.id)" + case let .url(url): "url-\(url)" + case let .transferData(data): "transfer-data-\(data.id)" + case let .perpetualRecipientData(data): "perpetual-recipient-data-\(data.id)" + case let .setPriceAlert(assetId): "set-price-alert-\(assetId.identifier)" + } + } +} + +// MARK: - Binding extensions + +extension Binding where Value == WalletSceneSheetType? { + public var selectAssetType: Binding { + Binding( + get: { + if case .selectAssetType(let type) = wrappedValue { + return type + } + return nil + }, + set: { newValue in + wrappedValue = newValue.map { .selectAssetType($0) } + } + ) + } + + public var transferData: Binding { + Binding( + get: { + if case .transferData(let data) = wrappedValue { + return data + } + return nil + }, + set: { newValue in + wrappedValue = newValue.map { .transferData($0) } + } + ) + } + + public var perpetualRecipientData: Binding { + Binding( + get: { + if case .perpetualRecipientData(let data) = wrappedValue { + return data + } + return nil + }, + set: { newValue in + wrappedValue = newValue.map { .perpetualRecipientData($0) } + } + ) + } + + public var wallets: Binding { + Binding( + get: { + if case .wallets = wrappedValue { return true } + return false + }, + set: { newValue in + wrappedValue = newValue ? .wallets : nil + } + ) + } + + public var setPriceAlert: Binding { + Binding( + get: { + if case .setPriceAlert(let assetId) = wrappedValue { + return assetId + } + return nil + }, + set: { newValue in + wrappedValue = newValue.map { .setPriceAlert($0) } + } + ) + } +} diff --git a/Features/WalletTab/Sources/ViewModels/WalletSceneViewModel.swift b/Features/WalletTab/Sources/ViewModels/WalletSceneViewModel.swift index 35d60a69b..b89bc3cbb 100644 --- a/Features/WalletTab/Sources/ViewModels/WalletSceneViewModel.swift +++ b/Features/WalletTab/Sources/ViewModels/WalletSceneViewModel.swift @@ -36,15 +36,8 @@ public final class WalletSceneViewModel: Sendable { public var assets: [AssetData] = [] public var banners: [Banner] = [] - // TODO: - separate presenting sheet state logic to separate type public var isPresentingSelectedAssetInput: Binding - public var isPresentingWallets = false - public var isPresentingSelectAssetType: SelectAssetType? - public var isPresentingInfoSheet: InfoSheetType? - public var isPresentingUrl: URL? = nil - public var isPresentingTransferData: TransferData? - public var isPresentingPerpetualRecipientData: PerpetualRecipientData? - public var isPresentingSetPriceAlert: AssetId? + public var isPresentingSheet: WalletSceneSheetType? public var isPresentingToastMessage: ToastMessage? public var isPresentingSearch = false @@ -143,13 +136,13 @@ extension WalletSceneViewModel { isLoadingAssets = false } } - + public func onSelectWalletBar() { - isPresentingWallets.toggle() + isPresentingSheet = .wallets } public func onSelectManage() { - isPresentingSelectAssetType = .manage + isPresentingSheet = .selectAssetType(.manage) } public func onToggleSearch() { @@ -164,7 +157,7 @@ extension WalletSceneViewModel { case .sell, .swap, .more, .stake, .deposit, .withdraw: fatalError() } - isPresentingSelectAssetType = selectType + isPresentingSheet = .selectAssetType(selectType) } func onCloseBanner(banner: Banner) { @@ -172,7 +165,7 @@ extension WalletSceneViewModel { } func onSelectWatchWalletInfo() { - isPresentingInfoSheet = .watchWallet + isPresentingSheet = .info(.watchWallet) } func onBanner(action: BannerAction) { @@ -181,11 +174,13 @@ extension WalletSceneViewModel { Task { try await handleBanner(action: action) } case .button(let bannerButton): switch bannerButton { - case .buy: isPresentingSelectAssetType = .buy - case .receive: isPresentingSelectAssetType = .receive(.asset) + case .buy: isPresentingSheet = .selectAssetType(.buy) + case .receive: isPresentingSheet = .selectAssetType(.receive(.asset)) } } - isPresentingUrl = action.url + if let url = action.url { + isPresentingSheet = .url(url) + } } func onHideAsset(_ assetId: AssetId) { @@ -229,18 +224,17 @@ extension WalletSceneViewModel { let preferences = WalletPreferences(walletId: wallet.id) isLoadingAssets = !preferences.completeInitialLoadAssets && preferences.assetsTimestamp == .zero } - + public func onTransferComplete() { - isPresentingTransferData = nil + isPresentingSheet = nil } - + public func onSetPriceAlertComplete(message: String) { - isPresentingSetPriceAlert = nil + isPresentingSheet = nil isPresentingToastMessage = ToastMessage(title: message, image: SystemImage.bellFill) } } - // MARK: - Private extension WalletSceneViewModel { diff --git a/Gem/Navigation/Wallet/WalletNavigationStack.swift b/Gem/Navigation/Wallet/WalletNavigationStack.swift index fa190f09c..a25e8bbae 100644 --- a/Gem/Navigation/Wallet/WalletNavigationStack.swift +++ b/Gem/Navigation/Wallet/WalletNavigationStack.swift @@ -121,7 +121,7 @@ struct WalletNavigationStack: View { assetModel: AssetViewModel(asset: $0.asset), priceAlertService: priceAlertService, walletId: model.wallet.walletId, - isPresentingSetPriceAlert: $model.isPresentingSetPriceAlert + isPresentingSetPriceAlert: $model.isPresentingSheet.setPriceAlert ) ) } @@ -129,16 +129,16 @@ struct WalletNavigationStack: View { PerpetualsNavigationView( wallet: model.wallet, perpetualService: perpetualService, - isPresentingSelectAssetType: $model.isPresentingSelectAssetType + isPresentingSelectAssetType: $model.isPresentingSheet.selectAssetType ) } - .navigationDestination(for: Scenes.Perpetual.self) { + .navigationDestination(for: Scenes.Perpetual.self) { scene in PerpetualNavigationView( - perpetualData: $0.perpetualData, + perpetualData: scene.perpetualData, wallet: model.wallet, perpetualService: perpetualService, - isPresentingTransferData: $model.isPresentingTransferData, - isPresentingPerpetualRecipientData: $model.isPresentingPerpetualRecipientData + isPresentingTransferData: $model.isPresentingSheet.transferData, + isPresentingPerpetualRecipientData: $model.isPresentingSheet.perpetualRecipientData ) } .navigationDestination(for: Scenes.AssetPriceAlert.self) { @@ -150,50 +150,49 @@ struct WalletNavigationStack: View { ) ) } - .sheet(item: $model.isPresentingSelectAssetType) { - SelectAssetSceneNavigationStack( - model: SelectAssetViewModel( + .sheet(item: $model.isPresentingSheet) { sheet in + switch sheet { + case let .selectAssetType(value): + SelectAssetSceneNavigationStack( + model: SelectAssetViewModel( + wallet: model.wallet, + selectType: value, + searchService: AssetSearchService(assetsService: assetsService), + walletsService: walletsService, + priceAlertService: priceAlertService + ), + isPresentingSelectType: $model.isPresentingSheet.selectAssetType + ) + case let .info(type): + InfoSheetScene(type: type) + case let .perpetualRecipientData(perpetualRecipientData): + PerpetualPositionNavigationStack( + perpetualRecipientData: perpetualRecipientData, wallet: model.wallet, - selectType: $0, - searchService: AssetSearchService(assetsService: assetsService), - walletsService: walletsService, - priceAlertService: priceAlertService - ), - isPresentingSelectType: $model.isPresentingSelectAssetType - ) - } - .sheet(isPresented: $model.isPresentingWallets) { - WalletsNavigationStack(isPresentingWallets: $model.isPresentingWallets) - } - .sheet(item: $model.isPresentingInfoSheet) { - InfoSheetScene(type: $0) - } - .sheet(item: $model.isPresentingTransferData) { - ConfirmTransferNavigationStack( - wallet: model.wallet, - transferData: $0, - onComplete: model.onTransferComplete - ) - } - .sheet(item: $model.isPresentingPerpetualRecipientData) { - PerpetualPositionNavigationStack( - perpetualRecipientData: $0, - wallet: model.wallet, - onComplete: { - model.isPresentingPerpetualRecipientData = nil - } - ) - } - .sheet(item: $model.isPresentingSetPriceAlert) { assetId in - SetPriceAlertNavigationStack( - model: SetPriceAlertViewModel( - walletId: model.wallet.walletId, - assetId: assetId, - priceAlertService: priceAlertService - ) { model.onSetPriceAlertComplete(message: $0) } - ) + onComplete: { + model.isPresentingSheet = nil + } + ) + case let .transferData(transferData): + ConfirmTransferNavigationStack( + wallet: model.wallet, + transferData: transferData, + onComplete: model.onTransferComplete + ) + case let .url(url): + SFSafariView(url: url) + case .wallets: + WalletsNavigationStack(isPresentingWallets: $model.isPresentingSheet.wallets) + case let .setPriceAlert(assetId): + SetPriceAlertNavigationStack( + model: SetPriceAlertViewModel( + walletId: model.wallet.walletId, + assetId: assetId, + priceAlertService: priceAlertService + ) { model.onSetPriceAlertComplete(message: $0) } + ) + } } - .safariSheet(url: $model.isPresentingUrl) .toast(message: $model.isPresentingToastMessage) } }