diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt index 7fab19081f..231660ff27 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsClient.kt @@ -1,6 +1,7 @@ package com.tangem.tap.common.analytics.handlers.appsflyer import android.content.Context +import com.appsflyer.AppsFlyerConversionListener import com.appsflyer.AppsFlyerLib import com.appsflyer.attribution.AppsFlyerRequestListener import com.tangem.core.analytics.api.EventLogger @@ -17,18 +18,49 @@ internal class AppsFlyerClient( private val appsFlyerLib: AppsFlyerLib = AppsFlyerLib.getInstance() private val eventConverter = UnderscoreAnalyticsEventConverter() + private val logEventListener = object : AppsFlyerRequestListener { + override fun onSuccess() { + Timber.tag("AppsFlyerClient").i("AppsFlyerRequestListener send") + } + + override fun onError(p0: Int, p1: String) { + Timber.tag("AppsFlyerClient").e("AppsFlyerRequestListener onError: $p0, $p1") + } + } init { - appsFlyerLib.init(key, null, context) - appsFlyerLib.start(context, key, object : AppsFlyerRequestListener { - override fun onSuccess() { - Timber.d("AppsFlyer initialized successfully") + val conversionListener = object : AppsFlyerConversionListener { + override fun onConversionDataSuccess(p0: Map?) { + Timber.i("AppsFlyer conversion data success: ${p0.orEmpty()}") } + override fun onConversionDataFail(p0: String?) { + Timber.e("AppsFlyer conversion data failure: ${p0.orEmpty()}") + } + override fun onAppOpenAttribution(p0: Map?) { + Timber.i("AppsFlyer app open attribution: ${p0.orEmpty()}") + } + override fun onAttributionFailure(p0: String?) { + Timber.e("AppsFlyer attribution failure: ${p0.orEmpty()}") + } + } - override fun onError(p0: Int, p1: String) { - Timber.e("AppsFlyer initialization error: $p0, $p1") - } - }) + appsFlyerLib.run { + setAppId(context.packageName) + setDebugLog(true) + + init(key, conversionListener, context) + Timber.i("Starting AppsFlyer SDK") + start(context, key, object : AppsFlyerRequestListener { + override fun onSuccess() { + Timber.i("AppsFlyer initialized successfully") + } + + override fun onError(p0: Int, p1: String) { + Timber.e("AppsFlyer initialization error: $p0, $p1") + } + }) + Timber.i("AppsFlyer SDK started") + } } override fun setUserId(userId: String) { @@ -40,10 +72,12 @@ internal class AppsFlyerClient( } override fun logEvent(event: String, params: Map) { + Timber.tag("AppsFlyer").i("Logging event: $event with params: $params") appsFlyerLib.logEvent( context, event, eventConverter.convertEventParams(params), + logEventListener, ) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsHandler.kt index cda56807ee..14a35c89cd 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/appsflyer/AppsFlyerAnalyticsHandler.kt @@ -6,19 +6,26 @@ import com.tangem.core.analytics.models.AnalyticsEvent import com.tangem.core.analytics.models.AppsFlyerIncludedEvent import com.tangem.core.analytics.models.AppsFlyerOnlyEvent import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder +import timber.log.Timber class AppsFlyerAnalyticsHandler( private val client: AppsFlyerAnalyticsClient, ) : AnalyticsHandler, AnalyticsUserIdHandler { + init { + Timber.tag("AppsFlyer").i("AppsFlyer Analytics Handler created") + } + override fun id(): String = ID override fun send(event: AnalyticsEvent) { when (event) { is AppsFlyerOnlyEvent -> { + Timber.tag("AppsFlyer").i("Sending event to AppsFlyer: ${event.id} with params: ${event.params}") client.logEvent(event.id, event.params) } is AppsFlyerIncludedEvent -> { + Timber.tag("AppsFlyer").i("Sending event to AppsFlyer: ${event.id} with params: ${event.params}") client.logEvent( event = AnalyticsEvent(category = event.category, event = event.appsFlyerReplacedEvent).id, params = event.params, @@ -40,10 +47,16 @@ class AppsFlyerAnalyticsHandler( } class Builder : AnalyticsHandlerBuilder { + init { + Timber.tag("AppsFlyer").i("AppsFlyer Analytics Handler Builder created") + } + override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler = AppsFlyerAnalyticsHandler( client = if (data.logConfig.isAppsflyerLogEnabled) { + Timber.tag("AppsFlyer").i("AppsFlyer log enabled, mock client created") AppsFlyerLogClient(data.jsonConverter) } else { + Timber.tag("AppsFlyer").i("AppsFlyer log disabled, real client created") AppsFlyerClient(data.application, data.config.appsFlyerApiKey) }, ) diff --git a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt index c73c840784..b887bb2de7 100644 --- a/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt +++ b/features/swap/impl/src/main/java/com/tangem/feature/swap/model/SwapModel.kt @@ -1119,6 +1119,7 @@ internal class SwapModel @Inject constructor( } } + @Suppress("LongMethod") private fun onTokenSelect(id: String) { val tokens = dataState.tokensDataState ?: return val (foundToken, foundAccount) = getSelectedTokenAndAccount(tokens, id) @@ -1149,6 +1150,8 @@ internal class SwapModel @Inject constructor( coin = newToken, isFromCurrency = true, ) + } else { + fromTokenBalanceJobHolder.cancel() } } else { fromToken = initialFromStatus @@ -1167,6 +1170,8 @@ internal class SwapModel @Inject constructor( coin = newToken, isFromCurrency = false, ) + } else { + toTokenBalanceJobHolder.cancel() } } @@ -1221,6 +1226,7 @@ internal class SwapModel @Inject constructor( } } + @Suppress("LongMethod", "CyclomaticComplexMethod") private fun subscribeToCoinBalanceUpdates( userWalletId: UserWalletId, coin: CryptoCurrency.Coin, @@ -1243,20 +1249,25 @@ internal class SwapModel @Inject constructor( ).getOrNull() ?: currencyStatus, ) - uiState = if (isFromCurrency) { - dataState = dataState.copy( - fromCryptoCurrency = currencyStatus, - fromAccount = account, - ) - stateBuilder.updateSendCurrencyBalance(uiState, currencyStatus) - } else { - dataState = dataState.copy( - toCryptoCurrency = currencyStatus, - toAccount = account, - ) - stateBuilder.updateReceiveCurrencyBalance(uiState, currencyStatus) + uiState = when { + isFromCurrency && currencyStatus.currency.id == dataState.fromCryptoCurrency?.currency?.id -> { + dataState = dataState.copy( + fromCryptoCurrency = currencyStatus, + fromAccount = account, + ) + stateBuilder.updateSendCurrencyBalance(uiState, currencyStatus) + } + !isFromCurrency && currencyStatus.currency.id == dataState.toCryptoCurrency?.currency?.id -> { + dataState = dataState.copy( + toCryptoCurrency = currencyStatus, + toAccount = account, + ) + stateBuilder.updateReceiveCurrencyBalance(uiState, currencyStatus) + } + else -> { + uiState + } } - startLoadingQuotesFromLastState(isSilent = true) } } else { @@ -1276,14 +1287,19 @@ internal class SwapModel @Inject constructor( ).getOrNull() ?: status, ) - uiState = if (isFromCurrency) { - dataState = dataState.copy(fromCryptoCurrency = status) - stateBuilder.updateSendCurrencyBalance(uiState, status) - } else { - dataState = dataState.copy(toCryptoCurrency = status) - stateBuilder.updateReceiveCurrencyBalance(uiState, status) + uiState = when { + isFromCurrency && status.currency.id == dataState.fromCryptoCurrency?.currency?.id -> { + dataState = dataState.copy(fromCryptoCurrency = status) + stateBuilder.updateSendCurrencyBalance(uiState, status) + } + !isFromCurrency && status.currency.id == dataState.toCryptoCurrency?.currency?.id -> { + dataState = dataState.copy(toCryptoCurrency = status) + stateBuilder.updateReceiveCurrencyBalance(uiState, status) + } + else -> { + uiState + } } - startLoadingQuotesFromLastState(isSilent = true) } }.flowOn(dispatchers.main) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/singlecurrency/TangemPayCardMainBlock.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/singlecurrency/TangemPayCardMainBlock.kt index 0c7551a2b4..c155df8fd4 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/singlecurrency/TangemPayCardMainBlock.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/components/singlecurrency/TangemPayCardMainBlock.kt @@ -1,5 +1,6 @@ package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency +import android.content.res.Configuration import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* import androidx.compose.material3.Surface @@ -9,13 +10,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.tangem.common.ui.R +import com.tangem.core.ui.extensions.TextReference import com.tangem.core.ui.extensions.orMaskWithStars import com.tangem.core.ui.extensions.resolveReference import com.tangem.core.ui.extensions.stringResourceSafe import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview import com.tangem.feature.wallet.presentation.wallet.state.model.TangemPayState +import com.tangem.feature.wallet.presentation.wallet.ui.components.visa.TangemPayMainScreenBlock @Composable internal fun TangemPayCardMainBlock( @@ -33,8 +38,9 @@ internal fun TangemPayCardMainBlock( modifier = Modifier .fillMaxWidth() .height(IntrinsicSize.Min) - .padding(horizontal = 16.dp, vertical = 12.dp), + .padding(horizontal = 12.dp, vertical = 16.dp), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp), ) { Image( painter = painterResource(R.drawable.img_visa_36), @@ -42,20 +48,15 @@ internal fun TangemPayCardMainBlock( modifier = Modifier.size(36.dp), ) - Spacer(Modifier.width(12.dp)) - Column( modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.Center, + verticalArrangement = Arrangement.spacedBy(2.dp), ) { Text( text = stringResourceSafe(R.string.tangempay_payment_account), style = TangemTheme.typography.subtitle2, color = TangemTheme.colors.text.primary1, ) - - Spacer(Modifier.height(6.dp)) - Text( text = state.lastFourDigits.resolveReference(), style = TangemTheme.typography.caption2, @@ -64,6 +65,7 @@ internal fun TangemPayCardMainBlock( } Column( modifier = Modifier.fillMaxHeight(), + verticalArrangement = Arrangement.spacedBy(2.dp), horizontalAlignment = Alignment.End, ) { Text( @@ -72,14 +74,30 @@ internal fun TangemPayCardMainBlock( color = TangemTheme.colors.text.primary1, textAlign = TextAlign.End, ) - Text( text = state.balanceSymbol.resolveReference(), - style = TangemTheme.typography.body2, + style = TangemTheme.typography.caption2, color = TangemTheme.colors.text.tertiary, textAlign = TextAlign.End, ) } } } +} + +@Preview(showBackground = true) +@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun TangemPayCardMainBlockPreview() { + TangemThemePreview { + TangemPayMainScreenBlock( + TangemPayState.Card( + lastFourDigits = TextReference.Str("*1234"), + balanceText = TextReference.Str("$ 0.00"), + balanceSymbol = TextReference.Str("USDC"), + onClick = {}, + ), + isBalanceHidden = false, + ) + } } \ No newline at end of file