From 9aa840f892b5a3671e756e821632001b17563982 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 12 Dec 2023 20:42:39 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .../tap/di/domain/SettingsDomainModule.kt | 17 ++ .../local/preferences/PreferencesKeys.kt | 4 + core/res/src/main/res/values-ru/strings.xml | 5 + core/res/src/main/res/values/strings.xml | 5 + .../notifications/NotificationConfig.kt | 20 ++- .../NotificationWithBackground.kt | 170 ++++++++++++++++++ .../main/res/drawable/ic_swap_promo_34.xml | 20 +++ .../img_swap_promo_banner_background.webp | Bin 0 -> 12392 bytes .../settings/DefaultSwapPromoRepository.kt | 54 ++++++ .../data/settings/di/SettingsDataModule.kt | 8 + .../ShouldShowSwapPromoTokenUseCase.kt | 11 ++ .../ShouldShowSwapPromoWalletUseCase.kt | 11 ++ .../repositories/SwapPromoRepository.kt | 13 ++ 13 files changed, 331 insertions(+), 7 deletions(-) create mode 100644 core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt create mode 100644 core/ui/src/main/res/drawable/ic_swap_promo_34.xml create mode 100644 core/ui/src/main/res/drawable/img_swap_promo_banner_background.webp create mode 100644 data/settings/src/main/java/com/tangem/data/settings/DefaultSwapPromoRepository.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoTokenUseCase.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoWalletUseCase.kt create mode 100644 domain/settings/src/main/java/com/tangem/domain/settings/repositories/SwapPromoRepository.kt diff --git a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt index 1c596a4b4d..7334227d99 100644 --- a/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt +++ b/app/src/main/java/com/tangem/tap/di/domain/SettingsDomainModule.kt @@ -8,6 +8,7 @@ import com.tangem.domain.balancehiding.repositories.BalanceHidingRepository import com.tangem.domain.settings.* import com.tangem.domain.settings.repositories.AppRatingRepository import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.domain.settings.repositories.SwapPromoRepository import com.tangem.tap.domain.TangemSdkManager import com.tangem.tap.domain.settings.DefaultLegacySettingsRepository import dagger.Module @@ -103,4 +104,20 @@ internal object SettingsDomainModule { fun provideIsWalletsScrollPreviewEnabled(settingsRepository: SettingsRepository): IsWalletsScrollPreviewEnabled { return IsWalletsScrollPreviewEnabled(settingsRepository = settingsRepository) } + + @Provides + @ViewModelScoped + fun provideShouldShowSwapPromoWalletUseCase( + swapPromoRepository: SwapPromoRepository, + ): ShouldShowSwapPromoWalletUseCase { + return ShouldShowSwapPromoWalletUseCase(swapPromoRepository) + } + + @Provides + @ViewModelScoped + fun provideShouldShowSwapPromoTokenUseCase( + swapPromoRepository: SwapPromoRepository, + ): ShouldShowSwapPromoTokenUseCase { + return ShouldShowSwapPromoTokenUseCase(swapPromoRepository) + } } \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt index d10a9dab4f..26d5b3cf08 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/local/preferences/PreferencesKeys.kt @@ -42,6 +42,10 @@ object PreferencesKeys { val WALLETS_BALANCES_STATES_KEY by lazy { stringPreferencesKey(name = "walletsBalancesStates") } val LAST_SWAPPED_CRYPTOCURRENCY_ID_KEY by lazy { stringPreferencesKey(name = "lastSwappedCryptoCurrency") } + + val IS_WALLET_SWAP_PROMO_SHOW_KEY by lazy { booleanPreferencesKey(name = "isWalletSwapPromoShown") } + + val IS_TOKEN_SWAP_PROMO_SHOW_KEY by lazy { booleanPreferencesKey(name = "isTokenSwapPromoShown") } } /** Preferences keys set that should be migrated from "PreferencesDataSource" to a new DataStore */ diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 391fe57950..21bec9195d 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -244,6 +244,8 @@ 1INCH токены будут зачислены на адрес вашего кошелька в сети %s в течение 48 часов Чтобы получить доступ ко всем сетям, вам необходимо отсканировать карту Отсканируйте карту + Обменивайте свои цифровые активы между различными сетями + Кроссчейн-своп теперь доступен Токены Добавить Изменить @@ -539,6 +541,9 @@ Токен %1$s является основной валютой в сети %2$s и не может быть скрыт до тех пор, пока у вас в списке есть другие токены этой сети. Невозможно скрыть %s Нет цены + Обменяйте этот токен на другие активы в вашем портфеле + Представляем кроссчейн-своп + Обменять контракт: %s У вас еще нет транзакций Не удалось загрузить историю транзакций.\nНажмите на кнопку перезагрузки, чтобы обновить информацию. diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 08c1787e9b..3088fc97ea 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -263,6 +263,8 @@ 1INCH tokens will be credited to your %s wallet address within 48 hours To access all the networks you need to scan the card Scan your card + Swap multiple currencies across several blockchains + Cross-chain swaps are now available Tokens Add Edit @@ -569,6 +571,9 @@ The %1$s token is the main currency on the %2$s network and cannot be hidden as long as you have other tokens on this network in the list. Unable to hide %s No rate + Exchange this token for other assets in your portfolio + Introducing cross-chain swaps + Exchange now contract: %s You don\'t have any transactions yet Failed to load transaction history.\nClick on reload button to update the information. diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationConfig.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationConfig.kt index 1992043a9e..c6180da951 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationConfig.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationConfig.kt @@ -6,12 +6,13 @@ import com.tangem.core.ui.extensions.TextReference /** * Notification component state * - * @property title title - * @property subtitle subtitle - * @property iconResId icon resource id - * @property buttonsState buttons state - * @property onClick lambda be invoked when notification is clicked - * @property onCloseClick lambda be invoked when close button is clicked + * @property title title + * @property subtitle subtitle + * @property iconResId icon resource id + * @property backgroundResId background resource id + * @property buttonsState buttons state + * @property onClick lambda be invoked when notification is clicked + * @property onCloseClick lambda be invoked when close button is clicked * [REDACTED_AUTHOR] */ @@ -19,6 +20,7 @@ data class NotificationConfig( val title: TextReference, val subtitle: TextReference, @DrawableRes val iconResId: Int, + @DrawableRes val backgroundResId: Int? = null, val buttonsState: ButtonsState? = null, val onClick: (() -> Unit)? = null, val onCloseClick: (() -> Unit)? = null, @@ -33,7 +35,11 @@ data class NotificationConfig( val onClick: () -> Unit, ) : ButtonsState() - data class SecondaryButtonConfig(val text: TextReference, val onClick: () -> Unit) : ButtonsState() + data class SecondaryButtonConfig( + val text: TextReference, + @DrawableRes val iconResId: Int? = null, + val onClick: () -> Unit, + ) : ButtonsState() data class PairButtonsConfig( val primaryText: TextReference, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt new file mode 100644 index 0000000000..072a7389f6 --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt @@ -0,0 +1,170 @@ +package com.tangem.core.ui.components.notifications + +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.defaultMinSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.material.Icon +import androidx.compose.material.Text +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension +import androidx.constraintlayout.compose.Visibility +import com.tangem.core.ui.R +import com.tangem.core.ui.components.SecondaryButtonIconStart +import com.tangem.core.ui.extensions.resolveReference +import com.tangem.core.ui.extensions.resourceReference +import com.tangem.core.ui.extensions.stringReference +import com.tangem.core.ui.res.TangemTheme + +/** + * Custom notification with image background + * @see [Swap Promo](https://www.figma.com/file/Vs6SkVsFnUPsSCNwlnVf5U/Android-%E2%80%93-UI?type=design&node-id=8713-6307&mode=dev) + */ +@Suppress("LongMethod", "DestructuringDeclarationWithTooManyEntries") +@Composable +fun NotificationWithBackground(config: NotificationConfig, modifier: Modifier = Modifier) { + val button = config.buttonsState as? NotificationConfig.ButtonsState.SecondaryButtonConfig + + ConstraintLayout( + modifier = modifier + .defaultMinSize(minHeight = TangemTheme.dimens.size62) + .fillMaxWidth() + .clip(TangemTheme.shapes.roundedCornersXMedium), + ) { + val (iconRef, titleRef, subtitleRef, closeIconRef, buttonRef, backgroundRef) = createRefs() + + val spacing2 = TangemTheme.dimens.spacing2 + val spacing12 = TangemTheme.dimens.spacing12 + val spacing14 = TangemTheme.dimens.spacing14 + + Image( + painter = painterResource(config.backgroundResId ?: R.drawable.img_swap_promo_banner_background), + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.constrainAs(backgroundRef) { + top.linkTo(parent.top) + start.linkTo(parent.start) + end.linkTo(parent.end) + bottom.linkTo(parent.bottom) + width = Dimension.fillToConstraints + height = Dimension.fillToConstraints + visibility = if (config.backgroundResId == null) Visibility.Gone else Visibility.Visible + }, + ) + Image( + painter = painterResource(config.iconResId), + contentDescription = null, + modifier = Modifier.constrainAs(iconRef) { + start.linkTo(parent.start, spacing12) + linkTo(titleRef.top, subtitleRef.bottom, bias = 0.1f) + }, + ) + Text( + text = config.title.resolveReference(), + style = TangemTheme.typography.button, + color = TangemTheme.colors.text.constantWhite, + modifier = Modifier.constrainAs(titleRef) { + top.linkTo(parent.top, spacing12) + start.linkTo(iconRef.end, spacing12) + end.linkTo(closeIconRef.start, spacing2) + width = Dimension.fillToConstraints + }, + ) + Text( + text = config.subtitle.resolveReference(), + style = TangemTheme.typography.caption2, + color = TangemTheme.colors.text.constantWhite, + modifier = Modifier.constrainAs(subtitleRef) { + top.linkTo(titleRef.bottom, spacing2) + start.linkTo(iconRef.end, spacing12) + end.linkTo(parent.end, spacing12) + bottom.linkTo(buttonRef.top, spacing12, spacing14) + width = Dimension.fillToConstraints + }, + ) + Icon( + painter = painterResource(id = R.drawable.ic_close_24), + contentDescription = null, + tint = TangemTheme.colors.text.constantWhite, + modifier = Modifier + .size(TangemTheme.dimens.size16) + .constrainAs(closeIconRef) { + top.linkTo(parent.top, spacing12) + end.linkTo(parent.end, spacing12) + } + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(bounded = false), + ) { + config.onCloseClick?.invoke() + }, + ) + SecondaryButtonIconStart( + text = button?.text?.resolveReference().orEmpty(), + iconResId = button?.iconResId ?: R.drawable.ic_exchange_vertical_24, + onClick = button?.onClick ?: {}, + modifier = Modifier.constrainAs(buttonRef) { + start.linkTo(parent.start, spacing12) + end.linkTo(parent.end, spacing12) + bottom.linkTo(parent.bottom, spacing12) + width = Dimension.fillToConstraints + visibility = if (button == null) { + Visibility.Gone + } else { + Visibility.Visible + } + }, + ) + } +} + +//region preview +@Preview +@Composable +private fun NotificationWithBackgroundPreview( + @PreviewParameter(NotificationWithBackgroundPreviewProvider::class) config: NotificationConfig, +) { + TangemTheme { + NotificationWithBackground(config = config) + } +} + +private class NotificationWithBackgroundPreviewProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf( + NotificationConfig( + title = resourceReference(id = R.string.main_swap_promotion_title), + subtitle = resourceReference(id = R.string.main_swap_promotion_message), + iconResId = R.drawable.ic_swap_promo_34, + backgroundResId = R.drawable.img_swap_promo_banner_background, + ), + NotificationConfig( + title = resourceReference(id = R.string.token_swap_promotion_title), + subtitle = stringReference( + "Swap multiple currencies between any chains you wish. Swap multiple " + + "currencies between any chains you wish. Swap multiple " + + "currencies between any chains you wish. Commission free period " + + "till Dec 31.", + ), + iconResId = R.drawable.ic_swap_promo_34, + backgroundResId = R.drawable.img_swap_promo_banner_background, + buttonsState = NotificationConfig.ButtonsState.SecondaryButtonConfig( + text = resourceReference(id = R.string.token_swap_promotion_button), + onClick = {}, + ), + ), + ) +} +//endregion \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_swap_promo_34.xml b/core/ui/src/main/res/drawable/ic_swap_promo_34.xml new file mode 100644 index 0000000000..3c279910c8 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_swap_promo_34.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/core/ui/src/main/res/drawable/img_swap_promo_banner_background.webp b/core/ui/src/main/res/drawable/img_swap_promo_banner_background.webp new file mode 100644 index 0000000000000000000000000000000000000000..1e952cd6f75c5d7d25ad418bbf5dc427ebbd5f86 GIT binary patch literal 12392 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 Z*e;_)pz6qSe5LFduL2cHmK6Z-e*iH`Ae{gJ literal 0 HcmV?d00001 diff --git a/data/settings/src/main/java/com/tangem/data/settings/DefaultSwapPromoRepository.kt b/data/settings/src/main/java/com/tangem/data/settings/DefaultSwapPromoRepository.kt new file mode 100644 index 0000000000..5b4611572e --- /dev/null +++ b/data/settings/src/main/java/com/tangem/data/settings/DefaultSwapPromoRepository.kt @@ -0,0 +1,54 @@ +package com.tangem.data.settings + +import com.tangem.datasource.local.preferences.AppPreferencesStore +import com.tangem.datasource.local.preferences.PreferencesKeys.IS_TOKEN_SWAP_PROMO_SHOW_KEY +import com.tangem.datasource.local.preferences.PreferencesKeys.IS_WALLET_SWAP_PROMO_SHOW_KEY +import com.tangem.datasource.local.preferences.utils.get +import com.tangem.datasource.local.preferences.utils.store +import com.tangem.domain.settings.repositories.SwapPromoRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map +import java.util.Calendar + +/** + * Repository for showing swap promo notification. + */ +class DefaultSwapPromoRepository( + private val appPreferencesStore: AppPreferencesStore, +) : SwapPromoRepository { + override fun isReadyToShowWallet(): Flow { + return appPreferencesStore.get(IS_WALLET_SWAP_PROMO_SHOW_KEY, true) + .map { it && checkPromoPeriod() } + } + + override fun isReadyToShowToken(): Flow { + return appPreferencesStore.get(IS_TOKEN_SWAP_PROMO_SHOW_KEY, true) + .map { it && checkPromoPeriod() } + } + + override suspend fun setNeverToShowWallet() { + appPreferencesStore.store( + key = IS_WALLET_SWAP_PROMO_SHOW_KEY, + value = false, + ) + } + + override suspend fun setNeverToShowToken() { + appPreferencesStore.store( + key = IS_TOKEN_SWAP_PROMO_SHOW_KEY, + value = false, + ) + } + + private fun checkPromoPeriod(): Boolean { + val currentDate = Calendar.getInstance() + return currentDate.get(Calendar.DATE) in START_DATE_KEY..END_DATE_KEY && + currentDate.get(Calendar.MONTH) == MONTH_KEY + } + + companion object { + private const val START_DATE_KEY = 15 + private const val END_DATE_KEY = 31 + private const val MONTH_KEY = 11 // December + } +} \ No newline at end of file diff --git a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt index ba83b09d4d..43d5796d15 100644 --- a/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt +++ b/data/settings/src/main/java/com/tangem/data/settings/di/SettingsDataModule.kt @@ -2,10 +2,12 @@ package com.tangem.data.settings.di import com.tangem.data.settings.DefaultAppRatingRepository import com.tangem.data.settings.DefaultSettingsRepository +import com.tangem.data.settings.DefaultSwapPromoRepository import com.tangem.data.source.preferences.PreferencesDataSource import com.tangem.datasource.local.preferences.AppPreferencesStore import com.tangem.domain.settings.repositories.AppRatingRepository import com.tangem.domain.settings.repositories.SettingsRepository +import com.tangem.domain.settings.repositories.SwapPromoRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider import dagger.Module import dagger.Provides @@ -36,4 +38,10 @@ internal object SettingsDataModule { fun provideAppRatingRepository(appPreferencesStore: AppPreferencesStore): AppRatingRepository { return DefaultAppRatingRepository(appPreferencesStore = appPreferencesStore) } + + @Provides + @Singleton + fun provideSwapPromoRepository(appPreferencesStore: AppPreferencesStore): SwapPromoRepository { + return DefaultSwapPromoRepository(appPreferencesStore = appPreferencesStore) + } } \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoTokenUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoTokenUseCase.kt new file mode 100644 index 0000000000..0c75a4f52a --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoTokenUseCase.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.settings + +import com.tangem.domain.settings.repositories.SwapPromoRepository +import kotlinx.coroutines.flow.Flow + +class ShouldShowSwapPromoTokenUseCase(private val swapPromoRepository: SwapPromoRepository) { + + operator fun invoke(): Flow = swapPromoRepository.isReadyToShowToken() + + suspend fun neverToShow() = swapPromoRepository.setNeverToShowToken() +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoWalletUseCase.kt b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoWalletUseCase.kt new file mode 100644 index 0000000000..573a5ea94b --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/ShouldShowSwapPromoWalletUseCase.kt @@ -0,0 +1,11 @@ +package com.tangem.domain.settings + +import com.tangem.domain.settings.repositories.SwapPromoRepository +import kotlinx.coroutines.flow.Flow + +class ShouldShowSwapPromoWalletUseCase(private val swapPromoRepository: SwapPromoRepository) { + + operator fun invoke(): Flow = swapPromoRepository.isReadyToShowWallet() + + suspend fun neverToShow() = swapPromoRepository.setNeverToShowWallet() +} \ No newline at end of file diff --git a/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SwapPromoRepository.kt b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SwapPromoRepository.kt new file mode 100644 index 0000000000..95d31f65d8 --- /dev/null +++ b/domain/settings/src/main/java/com/tangem/domain/settings/repositories/SwapPromoRepository.kt @@ -0,0 +1,13 @@ +package com.tangem.domain.settings.repositories + +import kotlinx.coroutines.flow.Flow + +interface SwapPromoRepository { + fun isReadyToShowWallet(): Flow + + fun isReadyToShowToken(): Flow + + suspend fun setNeverToShowWallet() + + suspend fun setNeverToShowToken() +} \ No newline at end of file