diff --git a/p2p_wallet/Common/Services/AnalyticsManager/Events/KeyAppAnalyticsEvent.swift b/p2p_wallet/Common/Services/AnalyticsManager/Events/KeyAppAnalyticsEvent.swift index 4cee9e6d84..5b808e3010 100644 --- a/p2p_wallet/Common/Services/AnalyticsManager/Events/KeyAppAnalyticsEvent.swift +++ b/p2p_wallet/Common/Services/AnalyticsManager/Events/KeyAppAnalyticsEvent.swift @@ -34,10 +34,35 @@ enum KeyAppAnalyticsEvent: AnalyticsEvent { case mainScreenCashOutBar case mainScreenOpened(isSellEnabled: Bool) - case mainCopyAddress + case mainScreenAddressClick + case mainScreenAmountClick + case mainScreenAddMoneyClick + case mainScreenWithdrawClick + case mainScreenMainClick case mainScreenTokenDetailsOpen(tokenTicker: String) case mainScreenBuyToken(tokenName: String) case mainScreenHiddenTokens + + case mainScreenCryptoClick + case mainScreenSendClick + case mainScreenHistoryClick + case mainScreenSettingsClick + + case userAggregateBalanceBase(amountUsd: Double, currency: String) + case userHasPositiveBalanceBase(state: Bool) + + // MARK: - Crypto + + case cryptoScreenOpened + case cryptoAmountClick + case cryptoReceiveClick + case cryptoSwapClick + case cryptoTokenClick(tokenName: String) + case cryptoClaimTransferredViewed(claimCount: Int) + case cryptoClaimTransferredClick + + case userAggregateBalanceTokens(amountUsd: Double, currency: String) + case userHasPositiveBalanceTokens(state: Bool) // MARK: - Tokens diff --git a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Accounts/CryptoAccountsViewModel.swift b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Accounts/CryptoAccountsViewModel.swift index c3fa9659f6..1ad66bbae6 100644 --- a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Accounts/CryptoAccountsViewModel.swift +++ b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Accounts/CryptoAccountsViewModel.swift @@ -15,6 +15,7 @@ final class CryptoAccountsViewModel: BaseViewModel, ObservableObject { // MARK: - Dependencies + private let analyticsManager: AnalyticsManager private let solanaAccountsService: SolanaAccountsService private let ethereumAccountsService: EthereumAccountsService private let userActionService: UserActionService @@ -38,12 +39,14 @@ final class CryptoAccountsViewModel: BaseViewModel, ObservableObject { // MARK: - Initialization init( + analyticsManager: AnalyticsManager = Resolver.resolve(), solanaAccountsService: SolanaAccountsService = Resolver.resolve(), ethereumAccountsService: EthereumAccountsService = Resolver.resolve(), userActionService: UserActionService = Resolver.resolve(), favouriteAccountsStore: FavouriteAccountsDataSource = Resolver.resolve(), navigation: PassthroughSubject ) { + self.analyticsManager = analyticsManager self.solanaAccountsService = solanaAccountsService self.ethereumAccountsService = ethereumAccountsService self.userActionService = userActionService @@ -91,10 +94,12 @@ final class CryptoAccountsViewModel: BaseViewModel, ObservableObject { homeAccountsAggregator.transform(input: (solanaAccounts, ethereumAccounts)) } .receive(on: RunLoop.main) - .sink { transfer, primary, secondary in - self.transferAccounts = transfer - self.accounts = primary - self.hiddenAccounts = secondary + .sink { [weak self] transfer, primary, secondary in + self?.transferAccounts = transfer + self?.accounts = primary + self?.hiddenAccounts = secondary + + self?.analyticsManager.log(event: .cryptoClaimTransferredViewed(claimCount: transfer.count)) } .store(in: &subscriptions) } @@ -114,6 +119,7 @@ final class CryptoAccountsViewModel: BaseViewModel, ObservableObject { case let renderableAccount as RenderableSolanaAccount: switch event { case .tap: + analyticsManager.log(event: .cryptoTokenClick(tokenName: renderableAccount.account.token.symbol)) navigation.send(.solanaAccount(renderableAccount.account)) case .visibleToggle: let pubkey = renderableAccount.account.address @@ -132,7 +138,10 @@ final class CryptoAccountsViewModel: BaseViewModel, ObservableObject { case let renderableAccount as RenderableEthereumAccount: switch event { + case .tap: + analyticsManager.log(event: .cryptoTokenClick(tokenName: renderableAccount.account.token.symbol)) case .extraButtonTap: + analyticsManager.log(event: .cryptoClaimTransferredClick) navigation.send(.claim(renderableAccount.account, renderableAccount.userAction)) default: break diff --git a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelView.swift b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelView.swift index 83ce07dd65..e0ccaf87e9 100644 --- a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelView.swift +++ b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelView.swift @@ -21,9 +21,11 @@ struct CryptoActionsPanelView: View { actions: viewModel.actions, balance: viewModel.balance, usdAmount: "", - action: { action in - self.viewModel.actionClicked(action) - } + action: viewModel.actionClicked, + balanceTapAction: viewModel.balanceTapped ) + .onAppear { + viewModel.viewDidAppear() + } } } diff --git a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelViewModel.swift b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelViewModel.swift index f2a2219e42..f1ea6a957c 100644 --- a/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelViewModel.swift +++ b/p2p_wallet/Scenes/Main/Crypto/Components/Crypto Actions Panel/CryptoActionsPanelViewModel.swift @@ -1,3 +1,4 @@ +import AnalyticsManager import Combine import Foundation import Resolver @@ -12,6 +13,7 @@ final class CryptoActionsPanelViewModel: BaseViewModel, ObservableObject { // MARK: - Dependencies @Injected var solanaAccountsService: SolanaAccountsService + @Injected var analyticsManager: AnalyticsManager // MARK: - Properties @@ -57,11 +59,24 @@ final class CryptoActionsPanelViewModel: BaseViewModel, ObservableObject { case .receive: guard let pubkey = try? PublicKey(string: solanaAccountsService.state.value.nativeWallet?.address) else { return } + analyticsManager.log(event: .cryptoReceiveClick) navigation.send(.receive(publicKey: pubkey)) case .swap: + analyticsManager.log(event: .cryptoSwapClick) navigation.send(.swap) default: break } } + + func balanceTapped() { + analyticsManager.log(event: .cryptoAmountClick) + } + + func viewDidAppear() { + if let balance = Double(balance) { + analyticsManager.log(event: .userAggregateBalanceTokens(amountUsd: balance, currency: Defaults.fiat.code)) + analyticsManager.log(event: .userHasPositiveBalanceTokens(state: balance > 0)) + } + } } diff --git a/p2p_wallet/Scenes/Main/Crypto/Container/CryptoViewModel.swift b/p2p_wallet/Scenes/Main/Crypto/Container/CryptoViewModel.swift index 6317674598..7c9ca04cd1 100644 --- a/p2p_wallet/Scenes/Main/Crypto/Container/CryptoViewModel.swift +++ b/p2p_wallet/Scenes/Main/Crypto/Container/CryptoViewModel.swift @@ -54,10 +54,8 @@ final class CryptoViewModel: BaseViewModel, ObservableObject { if available(.solanaNegativeStatus) { solanaTracker.startTracking() } - - analyticsManager.log( - event: .mainScreenWalletsOpen(isSellEnabled: sellDataService.isAvailable) - ) + + analyticsManager.log(event: .cryptoScreenOpened) } } diff --git a/p2p_wallet/Scenes/Main/NewHome/HomeViewModel.swift b/p2p_wallet/Scenes/Main/NewHome/HomeViewModel.swift index 371f5740f0..24b12bfe8c 100644 --- a/p2p_wallet/Scenes/Main/NewHome/HomeViewModel.swift +++ b/p2p_wallet/Scenes/Main/NewHome/HomeViewModel.swift @@ -67,7 +67,7 @@ class HomeViewModel: ObservableObject { text = L10n.addressWasCopiedToClipboard } notificationsService.showToast(title: "🖤", text: text, haptic: true) - analyticsManager.log(event: .mainCopyAddress) + analyticsManager.log(event: .mainScreenAddressClick) } func updateAddressIfNeeded() { diff --git a/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsView.swift b/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsView.swift index 152aac49f6..ae28cace86 100644 --- a/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsView.swift +++ b/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsView.swift @@ -38,6 +38,9 @@ struct HomeAccountsView: View { scrollAnimationIsEnded = false } } + .onAppear { + viewModel.viewDidAppear() + } } private var header: some View { @@ -45,7 +48,8 @@ struct HomeAccountsView: View { actions: [], balance: viewModel.balance, usdAmount: viewModel.usdcAmount, - action: { _ in } + action: { _ in }, + balanceTapAction: viewModel.balanceTapped ) } diff --git a/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsViewModel.swift b/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsViewModel.swift index c45f7a7272..e7d5209802 100644 --- a/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsViewModel.swift +++ b/p2p_wallet/Scenes/Main/NewHome/Subview/AccountList/HomeAccountsViewModel.swift @@ -172,14 +172,27 @@ final class HomeAccountsViewModel: BaseViewModel, ObservableObject { func actionClicked(_ action: HomeAction) { switch action { case .addMoney: + analyticsManager.log(event: .mainScreenAddMoneyClick) navigation.send(.addMoney) - case .withdraw: break + case .withdraw: + analyticsManager.log(event: .mainScreenWithdrawClick) } } func scrollToTop() { scrollOnTheTop = true } + + func viewDidAppear() { + if let balance = Double(balance) { + analyticsManager.log(event: .userAggregateBalanceBase(amountUsd: balance, currency: Defaults.fiat.code)) + analyticsManager.log(event: .userHasPositiveBalanceBase(state: balance > 0)) + } + } + + func balanceTapped() { + analyticsManager.log(event: .mainScreenAmountClick) + } func hiddenTokensTapped() { analyticsManager.log(event: .mainScreenHiddenTokens) diff --git a/p2p_wallet/Scenes/TabBar/TabBarController.swift b/p2p_wallet/Scenes/TabBar/TabBarController.swift index 4ada864eef..31b9355180 100644 --- a/p2p_wallet/Scenes/TabBar/TabBarController.swift +++ b/p2p_wallet/Scenes/TabBar/TabBarController.swift @@ -314,13 +314,24 @@ extension TabBarController: UITabBarControllerDelegate { return true } - if TabItem(rawValue: selectedIndex) == .send { - return false - } else if TabItem(rawValue: selectedIndex) == .wallet, - (viewController as! UINavigationController).viewControllers.count == 1, - self.selectedIndex == selectedIndex - { - homeTabClickedTwicelySubject.send() + if let tabItem = TabItem(rawValue: selectedIndex) { + switch tabItem { + case .wallet: + viewModel.walletTapped() + + if (viewController as! UINavigationController).viewControllers.count == 1, self.selectedIndex == selectedIndex { + homeTabClickedTwicelySubject.send() + } + case .crypto: + viewModel.cryptoTapped() + case .send: + viewModel.sendTapped() + return false + case .history: + viewModel.historyTapped() + case .settings: + viewModel.settingsTapped() + } } customTabBar.updateSelectedViewPositionIfNeeded() diff --git a/p2p_wallet/Scenes/TabBar/TabBarViewModel.swift b/p2p_wallet/Scenes/TabBar/TabBarViewModel.swift index 2a03d6a33c..d83dde0c97 100644 --- a/p2p_wallet/Scenes/TabBar/TabBarViewModel.swift +++ b/p2p_wallet/Scenes/TabBar/TabBarViewModel.swift @@ -1,3 +1,4 @@ +import AnalyticsManager import Combine import Wormhole import Foundation @@ -22,6 +23,8 @@ final class TabBarViewModel { @Injected private var userActionService: UserActionService @Injected private var ethereumAccountsService: EthereumAccountsService @Injected private var solanaAccountsService: SolanaAccountsService + + @Injected private var analyticsManager: AnalyticsManager // Input let viewDidLoad = PassthroughSubject() @@ -65,6 +68,26 @@ final class TabBarViewModel { }) .store(in: &cancellables) } + + func walletTapped() { + analyticsManager.log(event: .mainScreenMainClick) + } + + func cryptoTapped() { + analyticsManager.log(event: .mainScreenCryptoClick) + } + + func sendTapped() { + analyticsManager.log(event: .mainScreenSendClick) + } + + func historyTapped() { + analyticsManager.log(event: .mainScreenHistoryClick) + } + + func settingsTapped() { + analyticsManager.log(event: .mainScreenSettingsClick) + } } // MARK: - Output diff --git a/p2p_wallet/UI/SwiftUI/ActionsPanel/ActionsPanelView.swift b/p2p_wallet/UI/SwiftUI/ActionsPanel/ActionsPanelView.swift index d65256beda..e95b31482e 100644 --- a/p2p_wallet/UI/SwiftUI/ActionsPanel/ActionsPanelView.swift +++ b/p2p_wallet/UI/SwiftUI/ActionsPanel/ActionsPanelView.swift @@ -7,7 +7,8 @@ struct ActionsPanelView: View { let balance: String let usdAmount: String let action: (WalletActionType) -> Void - + let balanceTapAction: (() -> ())? + var body: some View { VStack(alignment: .center, spacing: 0) { if !balance.isEmpty { @@ -16,6 +17,9 @@ struct ActionsPanelView: View { .foregroundColor(Color(Asset.Colors.night.color)) .padding(.top, 24) .padding(.bottom, usdAmount.isEmpty ? 46 : 12) + .onTapGesture { + balanceTapAction?() + } } else { Rectangle() .fill(Color.clear)