diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2bcdbe0de8..7b8485d96e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -177,7 +177,7 @@ dependencies { } implementation(Library.accompanistAppCompatTheme) implementation(Library.accompanistSystemUiController) - implementation(Library.skydovesVeil) + implementation(Library.xmlShimmer) implementation(Library.viewBindingDelegate) implementation(Library.armadillo) implementation(Library.googlePlayServicesWallet) diff --git a/buildSrc/src/main/java/Dependency.kt b/buildSrc/src/main/java/Dependency.kt index 84f6380c8c..f93b728008 100644 --- a/buildSrc/src/main/java/Dependency.kt +++ b/buildSrc/src/main/java/Dependency.kt @@ -34,6 +34,7 @@ object Library { const val appsflyer = "com.appsflyer:af-android-sdk:" + Versions.appsflyer const val armadillo = "at.favre.lib:armadillo:" + Versions.armadillo const val coil = "io.coil-kt:coil:" + Versions.coil + const val composeShimmer = "com.valentinilk.shimmer:compose-shimmer:" + Versions.composeShimmer const val coroutine = "org.jetbrains.kotlinx:kotlinx-coroutines-core:" + Versions.coroutine const val desugarJdkLibs = "com.android.tools:desugar_jdk_libs:" + Versions.desugarJdkLibs const val googlePlayCore = "com.google.android.play:core:" + Versions.googlePlayCore @@ -52,7 +53,6 @@ object Library { const val okHttpLogging = "com.squareup.okhttp3:logging-interceptor:" + Versions.okhttp const val otaliastudiosCameraView = "com.otaliastudios:cameraview:" + Versions.otaliastudiosCameraView const val shopifyBuySdk = "com.shopify.mobilebuysdk:buy3:" + Versions.shopifyBuySdk - const val skydovesVeil = "com.github.skydoves:androidveil:" + Versions.skydovesAndroidVeil const val spongecastleCryptoCore = "com.madgag.spongycastle:core:" + Versions.spongycastleCryptoCore const val reKotlin = "org.rekotlin:rekotlin:" + Versions.rekotlin const val retrofit = "com.squareup.retrofit2:retrofit:" + Versions.retrofit @@ -60,6 +60,7 @@ object Library { const val timber = "com.jakewharton.timber:timber:" + Versions.timber const val viewBindingDelegate = "com.github.kirich1409:viewbindingpropertydelegate-noreflection:" + Versions.viewBindingDelegate + const val xmlShimmer = "com.github.skydoves:androidveil:" + Versions.xmlShimmer const val zendeskChat = "com.zendesk:chat:" + Versions.zendeskChat const val zendeskMessaging = "com.zendesk:messaging:" + Versions.zendeskMessaging const val zxingQrBarcodeScanner = "me.dm7.barcodescanner:zxing:" + Versions.zxingQrBarcodeScanner diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index b52ccb4d7b..54b4716dc7 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -28,6 +28,7 @@ object Versions { const val appsflyer = "6.5.1" const val armadillo = "0.9.0" const val coil = "2.1.0" + const val composeShimmer = "1.0.3" const val coroutine = "1.5.2" const val desugarJdkLibs = "1.1.5" const val firebase = "26.0.0" @@ -46,10 +47,10 @@ object Versions { const val retrofit = "2.8.1" const val retrofitMoshiConverter = "2.6.0" const val shopifyBuySdk = "12.0.0" - const val skydovesAndroidVeil = "1.1.2" const val spongycastleCryptoCore = "1.58.0.0" const val timber = "4.7.1" const val viewBindingDelegate = "1.5.6" + const val xmlShimmer = "1.1.2" const val zendeskChat = "3.3.5" const val zendeskMessaging = "5.2.4" const val zxingQrBarcodeScanner = "1.9.8" diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/AppBar.kt b/core/ui/src/main/java/com/tangem/core/ui/components/AppBar.kt index 6810ba11e8..6b5e3dc55d 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/AppBar.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/AppBar.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.Icon @@ -48,7 +49,8 @@ fun AppBarWithBackButton(text: String? = null, onBackClick: () -> Unit) { Row( modifier = Modifier .background(MaterialTheme.colors.primaryVariant) - .padding(all = dimensionResource(R.dimen.spacing16)), + .padding(all = dimensionResource(R.dimen.spacing16)) + .fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.spacing16)), verticalAlignment = Alignment.CenterVertically, ) { diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt new file mode 100644 index 0000000000..60ce6bf8bc --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Spacers.kt @@ -0,0 +1,19 @@ +package com.tangem.core.ui.components + +import androidx.annotation.DimenRes +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.dimensionResource + +@Composable +fun VerticalSpacer(@DimenRes spaceResId: Int) { + Spacer(modifier = Modifier.height(dimensionResource(id = spaceResId))) +} + +@Composable +fun HorizontalSpacer(@DimenRes spaceResId: Int) { + Spacer(modifier = Modifier.width(dimensionResource(id = spaceResId))) +} \ No newline at end of file diff --git a/core/ui/src/main/java/com/tangem/core/ui/res/IconColor.kt b/core/ui/src/main/java/com/tangem/core/ui/res/IconColor.kt new file mode 100644 index 0000000000..72cc8936bb --- /dev/null +++ b/core/ui/src/main/java/com/tangem/core/ui/res/IconColor.kt @@ -0,0 +1,19 @@ +package com.tangem.core.ui.res + +import androidx.compose.material.Colors +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +enum class IconColorType(val lightColor: Color, val darkColor: Color) { + PRIMARY1(lightColor = Black, darkColor = White), + PRIMARY2(lightColor = White, darkColor = Dark6), + SECONDARY(lightColor = Dark2, darkColor = Dark1), + INFORMATIVE(lightColor = Light5, darkColor = Dark2), + INACTIVE(lightColor = Light4, darkColor = Dark4), + ACCENT(lightColor = Meadow, darkColor = Meadow), + WARNING(lightColor = Amaranth, darkColor = Amaranth), + ATTENTION(lightColor = Tangerine, darkColor = Tangerine) +} + +@Composable +fun Colors.iconColor(type: IconColorType): Color = if (isSystemInDarkTheme) type.darkColor else type.lightColor \ No newline at end of file diff --git a/core/ui/src/main/res/drawable/ic_discount.xml b/core/ui/src/main/res/drawable/ic_discount.xml new file mode 100644 index 0000000000..5045eccd5b --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_discount.xml @@ -0,0 +1,9 @@ + + + diff --git a/core/ui/src/main/res/drawable/ic_tether.xml b/core/ui/src/main/res/drawable/ic_tether.xml new file mode 100644 index 0000000000..e3f94b5dbb --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_tether.xml @@ -0,0 +1,17 @@ + + + + + + + diff --git a/core/ui/src/main/res/values/dimens.xml b/core/ui/src/main/res/values/dimens.xml index cd873bfb37..3863794b73 100644 --- a/core/ui/src/main/res/values/dimens.xml +++ b/core/ui/src/main/res/values/dimens.xml @@ -13,19 +13,37 @@ + 6dp 12dp + 16dp + 11dp + 16dp 24dp + 28dp + 40dp 48dp + 56dp + 84dp + 86dp + 102dp + 164dp 200dp + 2dp + 4dp 8dp + 10dp 12dp 16dp 24dp + 32dp + 44dp + 50dp + 54dp \ No newline at end of file diff --git a/features/referral/presentation/build.gradle.kts b/features/referral/presentation/build.gradle.kts index 4a5dd97a5c..05a5ad278c 100644 --- a/features/referral/presentation/build.gradle.kts +++ b/features/referral/presentation/build.gradle.kts @@ -1,8 +1,6 @@ plugins { id("com.android.library") kotlin("android") - kotlin("kapt") - id("com.google.dagger.hilt.android") } android { @@ -22,11 +20,25 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 isCoreLibraryDesugaringEnabled = false } + + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = Versions.compose + } } dependencies { + /** Core modules */ + implementation(project(":core:ui")) - /** DI */ - implementation(Library.hilt) - kapt(Library.hiltKapt) + /** Compose */ + implementation(Compose.foundation) + implementation(Compose.material) + implementation(Compose.uiTooling) + + /** Other libraries */ + implementation(Library.composeShimmer) } \ No newline at end of file diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt new file mode 100644 index 0000000000..4c592299c1 --- /dev/null +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/models/ReferralStateHolder.kt @@ -0,0 +1,37 @@ +package com.tangem.feature.referral.models + +data class ReferralStateHolder( + val headerState: HeaderState, + val referralInfoState: ReferralInfoState, + val effects: Effects, +) { + + data class HeaderState(val onBackClicked: () -> Unit) + + sealed interface ReferralInfoContentState + + sealed interface ReferralInfoState { + + data class ParticipantContent( + val award: String, + val address: String, + val discount: String, + val onAgreementClicked: () -> Unit, + val onParticipateClicked: () -> Unit, + ) : ReferralInfoState, ReferralInfoContentState + + data class NonParticipantContent( + val award: String, + val discount: String, + val purchasedWalletCount: Int, + val code: String, + val onCopyClicked: () -> Unit, + val onShareClicked: () -> Unit, + val onAgreementClicked: () -> Unit, + ) : ReferralInfoState, ReferralInfoContentState + + object Loading : ReferralInfoState + } + + data class Effects(val showErrorToast: Boolean) +} diff --git a/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt new file mode 100644 index 0000000000..c7894c0bea --- /dev/null +++ b/features/referral/presentation/src/main/java/com/tangem/feature/referral/ui/ReferralScreen.kt @@ -0,0 +1,362 @@ +package com.tangem.feature.referral.ui + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import com.tangem.core.ui.components.AppBarWithBackButton +import com.tangem.core.ui.components.VerticalSpacer +import com.tangem.core.ui.res.ButtonColorType +import com.tangem.core.ui.res.IconColorType +import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TextColorType +import com.tangem.core.ui.res.White +import com.tangem.core.ui.res.buttonColor +import com.tangem.core.ui.res.iconColor +import com.tangem.core.ui.res.textColor +import com.tangem.feature.referral.models.ReferralStateHolder +import com.tangem.feature.referral.models.ReferralStateHolder.ReferralInfoState +import com.tangem.feature.referral.presentation.R +import com.valentinilk.shimmer.shimmer + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_Participant_InLightTheme() { + TangemTheme(isDarkTheme = false) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.ParticipantContent( + award = "10 USDT", + address = "ma80...zk8q2", + discount = "10%", + onAgreementClicked = {}, + onParticipateClicked = {}, + ), + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_Participant_InDarkTheme() { + TangemTheme(isDarkTheme = true) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.ParticipantContent( + award = "10 USDT", + address = "ma80...zk8q2", + discount = "10%", + onAgreementClicked = {}, + onParticipateClicked = {}, + ), + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_NonParticipant_InLightTheme() { + TangemTheme(isDarkTheme = false) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.NonParticipantContent( + award = "10 USDT", + discount = "10%", + purchasedWalletCount = 3, + code = "x4JdK", + onCopyClicked = {}, + onShareClicked = {}, + onAgreementClicked = {}, + ), + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_NonParticipant_InDarkTheme() { + TangemTheme(isDarkTheme = true) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.NonParticipantContent( + award = "10 USDT", + discount = "10%", + purchasedWalletCount = 3, + code = "x4JdK", + onCopyClicked = {}, + onShareClicked = {}, + onAgreementClicked = {}, + ), + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_Loading_InLightTheme() { + TangemTheme(isDarkTheme = false) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.Loading, + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +@Preview(widthDp = 360, showBackground = true) +@Composable +fun Preview_ReferralScreen_Loading_InDarkTheme() { + TangemTheme(isDarkTheme = true) { + ReferralScreen( + stateHolder = ReferralStateHolder( + headerState = ReferralStateHolder.HeaderState(onBackClicked = {}), + referralInfoState = ReferralInfoState.Loading, + effects = ReferralStateHolder.Effects(showErrorToast = false), + ), + ) + } +} + +/** + * Referral program screen for participant and non-participant + * + * @param stateHolder state holder + */ +@Composable +fun ReferralScreen(stateHolder: ReferralStateHolder) { + Column( + modifier = Modifier + .background(color = MaterialTheme.colors.primary) + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Header(stateHolder = stateHolder) + VerticalSpacer(spaceResId = R.dimen.spacing16) + ReferralInfo(stateHolder = stateHolder) + } +} + +@Composable +private fun ColumnScope.Header(stateHolder: ReferralStateHolder) { + AppBar(stateHolder = stateHolder) + Image( + painter = painterResource(R.drawable.ill_businessman_3d), + contentDescription = null, + modifier = Modifier + .padding(horizontal = dimensionResource(id = R.dimen.spacing32)) + .fillMaxWidth() + .height(dimensionResource(R.dimen.size200)), + ) + VerticalSpacer(spaceResId = R.dimen.spacing24) + Text( + text = stringResource(id = R.string.referral_title), + modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.spacing50)), + color = MaterialTheme.colors.textColor(type = TextColorType.PRIMARY1), + textAlign = TextAlign.Center, + maxLines = 2, + style = MaterialTheme.typography.h2, + ) +} + +@Composable +fun ReferralInfo(stateHolder: ReferralStateHolder) { + when (val state = stateHolder.referralInfoState) { + is ReferralInfoState.ParticipantContent, + is ReferralInfoState.NonParticipantContent -> { + Column(verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing32))) { + ConditionForYou(state = state as ReferralStateHolder.ReferralInfoContentState) + ConditionForYourFriend(state = state) + } + } + is ReferralInfoState.Loading -> { + Column(verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing32))) { + LoadingCondition(iconResId = R.drawable.ic_tether) + LoadingCondition(iconResId = R.drawable.ic_discount) + } + } + } +} + +@Composable +private fun AppBar(stateHolder: ReferralStateHolder) { + AppBarWithBackButton( + text = stringResource(R.string.details_referral_title), + onBackClick = stateHolder.headerState.onBackClicked, + ) +} + +@Composable +private fun ConditionForYou(state: ReferralStateHolder.ReferralInfoContentState) { + Condition(iconResId = R.drawable.ic_tether) { + when (state) { + is ReferralInfoState.ParticipantContent -> InfoForYou(award = state.award, address = state.address) + is ReferralInfoState.NonParticipantContent -> InfoForYou(award = state.award) + } + } +} + +@Composable +private fun ConditionForYourFriend(state: ReferralStateHolder.ReferralInfoContentState) { + Condition(iconResId = R.drawable.ic_discount) { + when (state) { + is ReferralInfoState.ParticipantContent -> InfoForYourFriend(discount = state.discount) + is ReferralInfoState.NonParticipantContent -> InfoForYourFriend(discount = state.discount) + } + } +} + +@Composable +private fun LoadingCondition(@DrawableRes iconResId: Int) { + Condition(iconResId = iconResId) { + ShimmerCondition() + } +} + +@Composable +private fun Condition(@DrawableRes iconResId: Int, infoBlock: @Composable () -> Unit) { + Row( + modifier = Modifier.padding(horizontal = dimensionResource(id = R.dimen.spacing16)), + horizontalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing12)), + verticalAlignment = Alignment.Top, + ) { + Box( + modifier = Modifier + .background( + color = MaterialTheme.colors.buttonColor(type = ButtonColorType.SECONDARY), + shape = RoundedCornerShape(dimensionResource(id = R.dimen.radius16)), + ) + .size(dimensionResource(id = R.dimen.size56)), + contentAlignment = Alignment.Center, + ) { + Icon( + painter = painterResource(id = iconResId), + contentDescription = null, + modifier = Modifier.size(dimensionResource(id = R.dimen.size28)), + tint = MaterialTheme.colors.iconColor(type = IconColorType.PRIMARY1), + ) + } + infoBlock() + } +} + +@Composable +private fun InfoForYou(award: String, address: String? = null) { + ConditionInfo(title = stringResource(id = R.string.referral_point_currencies_title)) { + Text( + text = buildAnnotatedString { + append(stringResource(id = R.string.referral_point_currencies_description_prefix)) + withStyle(SpanStyle(color = MaterialTheme.colors.textColor(type = TextColorType.PRIMARY1))) { + append(" $award ") + } + append( + String.format( + stringResource(id = R.string.referral_point_currencies_description_suffix), + if (!address.isNullOrBlank()) address else "", + ), + ) + }, + color = MaterialTheme.colors.textColor(type = TextColorType.TERTIARY), + style = MaterialTheme.typography.body2, + ) + } +} + +@Composable +private fun InfoForYourFriend(discount: String) { + ConditionInfo(title = stringResource(id = R.string.referral_point_discount_title)) { + Text( + text = buildString { + append(stringResource(id = R.string.referral_point_discount_description_prefix)) + append( + String.format( + stringResource(id = R.string.referral_point_discount_description_value), + " $discount", + ), + ) + append(" ") + append(stringResource(id = R.string.referral_point_discount_description_suffix)) + }, + color = MaterialTheme.colors.textColor(type = TextColorType.TERTIARY), + style = MaterialTheme.typography.body2, + ) + } +} + +@Composable +private fun ConditionInfo(title: String, subtitleContent: @Composable () -> Unit) { + Column(verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing2))) { + Text( + text = title, + color = MaterialTheme.colors.textColor(type = TextColorType.PRIMARY1), + style = MaterialTheme.typography.subtitle1, + ) + subtitleContent() + } +} + +@Composable +private fun ShimmerCondition() { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = dimensionResource(id = R.dimen.spacing4)) + .shimmer(), + verticalArrangement = Arrangement.spacedBy(dimensionResource(id = R.dimen.spacing10)), + ) { + Box( + modifier = Modifier + .clip(RoundedCornerShape(dimensionResource(id = R.dimen.radius6))) + .width(dimensionResource(id = R.dimen.size102)) + .height(dimensionResource(id = R.dimen.size16)) + .background(White), + ) + Box( + modifier = Modifier + .clip(RoundedCornerShape(dimensionResource(id = R.dimen.radius6))) + .width(dimensionResource(id = R.dimen.size40)) + .height(dimensionResource(id = R.dimen.size11)) + .background(White), + ) + } +} + diff --git a/features/referral/presentation/src/main/res/values-ru/string.xml b/features/referral/presentation/src/main/res/values-ru/string.xml new file mode 100644 index 0000000000..27e42e7c03 --- /dev/null +++ b/features/referral/presentation/src/main/res/values-ru/string.xml @@ -0,0 +1,20 @@ + + + Реферальная программа + Приведи друга в Tangem + Вы + Получите + за каждый кошелек, который купит ваш друг на ваш адрес в сети Tron %@ + Ваш друг + Получит + %@ скидку + при покупке карточки на сайте tangem.com + Нажимая на эту кнопку вы принимаете + условия участия + в реферальной программе + Участвовать + Вы приняли + Ваш персональный код + %d кошельков + Ваши друзья купили + \ No newline at end of file diff --git a/features/referral/presentation/src/main/res/values/string.xml b/features/referral/presentation/src/main/res/values/string.xml new file mode 100644 index 0000000000..7042ed2411 --- /dev/null +++ b/features/referral/presentation/src/main/res/values/string.xml @@ -0,0 +1,20 @@ + + + Referral program + Refer your friends to Tangem + You + Will get + for each wallet bought by your friend on your Tron network address %s + Your friend + Will get a + %s discount + when buying a card on tangem.com + By tapping this button you accept + terms and conditions + of the referral program + Participate + You\'ve accepted + Your personal code + %d wallets + Your friends bought + \ No newline at end of file