diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 048e2f771d..7c5c71355a 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -275,7 +275,7 @@ dependencies {
implementation(projects.features.tokenRecieve.api)
implementation(projects.features.tokenRecieve.impl)
implementation(projects.features.yieldSupply.api)
- implementation(projects.features.yieldSupply.api)
+ implementation(projects.features.yieldSupply.impl)
/** AndroidX libraries */
implementation(deps.androidx.core.ktx)
diff --git a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
index 6035f506dc..fb0bfb3588 100644
--- a/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
+++ b/app/src/main/java/com/tangem/tap/routing/utils/ChildFactory.kt
@@ -34,9 +34,11 @@ import com.tangem.features.staking.api.StakingComponent
import com.tangem.features.swap.SwapComponent
import com.tangem.features.swap.v2.api.SendWithSwapComponent
import com.tangem.features.tangempay.components.TangemPayDetailsComponent
+import com.tangem.features.tangempay.components.TangemPayOnboardingComponent
import com.tangem.features.tokendetails.TokenDetailsComponent
import com.tangem.features.wallet.WalletEntryComponent
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent
+import com.tangem.features.yield.supply.api.YieldSupplyPromoComponent
import com.tangem.tap.features.details.ui.appcurrency.api.AppCurrencySelectorComponent
import com.tangem.tap.features.details.ui.appsettings.api.AppSettingsComponent
import com.tangem.tap.features.details.ui.cardsettings.api.CardSettingsComponent
@@ -45,7 +47,6 @@ import com.tangem.tap.features.details.ui.resetcard.api.ResetCardComponent
import com.tangem.tap.features.details.ui.securitymode.api.SecurityModeComponent
import com.tangem.tap.features.welcome.component.WelcomeComponent
import com.tangem.tap.routing.component.RoutingComponent.Child
-import com.tangem.features.tangempay.components.TangemPayOnboardingComponent
import dagger.hilt.android.scopes.ActivityScoped
import javax.inject.Inject
import com.tangem.features.walletconnect.components.WalletConnectEntryComponent as RedesignedWalletConnectComponent
@@ -105,6 +106,7 @@ internal class ChildFactory @Inject constructor(
private val sendEntryPointComponentFactory: SendEntryPointComponent.Factory,
private val tangemPayDetailsComponentFactory: TangemPayDetailsComponent.Factory,
private val tangemPayOnboardingComponentFactory: TangemPayOnboardingComponent.Factory,
+ private val yieldSupplyPromoComponentFactory: YieldSupplyPromoComponent.Factory,
private val hotWalletFeatureToggles: HotWalletFeatureToggles,
) {
@@ -600,6 +602,13 @@ internal class ChildFactory @Inject constructor(
componentFactory = tangemPayOnboardingComponentFactory,
)
}
+ is AppRoute.YieldSupplyPromo -> {
+ createComponentChild(
+ context = context,
+ params = YieldSupplyPromoComponent.Params(route.userWalletId, route.cryptoCurrency),
+ componentFactory = yieldSupplyPromoComponentFactory,
+ )
+ }
}
}
}
\ No newline at end of file
diff --git a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
index 3ca2c4c565..448f369ac0 100644
--- a/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
+++ b/common/routing/src/main/kotlin/com/tangem/common/routing/AppRoute.kt
@@ -382,4 +382,10 @@ sealed class AppRoute(val path: String) : Route {
data class TangemPayOnboarding(
val deeplink: String,
) : AppRoute(path = "/tangem_pay_onboarding/$deeplink")
+
+ @Serializable
+ data class YieldSupplyPromo(
+ val userWalletId: UserWalletId,
+ val cryptoCurrency: CryptoCurrency,
+ ) : AppRoute(path = "/yield_supply_promo/${userWalletId.stringValue}/${cryptoCurrency.symbol}")
}
\ No newline at end of file
diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml
index 0ec41dbaeb..50f599d85a 100644
--- a/core/res/src/main/res/values-ja/strings.xml
+++ b/core/res/src/main/res/values-ja/strings.xml
@@ -1657,7 +1657,7 @@
Aaveは世界中で何百万人もの人々に信頼されています。総貸付額は104億ドルです。
分散型・自己管理型
サービスを使用することにより、プロバイダーに同意したものとみなされます
- 年間%s%の収益
+ 年間%s%%の収益
Aave • 変動金利
Aave
平均%s
diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml
index 4db0f5063e..fb4b2b7a3b 100644
--- a/core/res/src/main/res/values/strings.xml
+++ b/core/res/src/main/res/values/strings.xml
@@ -200,6 +200,7 @@
You have not given access to your camera, please adjust your privacy settings
Cancel
Change
+ Choose account
Choose action
Choose network
Choose token
@@ -1266,6 +1267,14 @@
You receive
Choose token
not available
+ Get card
+ Add to your wallet and pay with your phone anywhere.
+ Apple Pay & Google Pay
+ Use your USDC balance to pay for everyday purchases seamlessly.
+ Everyday purchases
+ Your card details are protected — full control in the app.
+ Built-in security
+ Get your free Crypto Card\nin minutes
This is my wallet
Balances hidden
Balances shown
@@ -1414,14 +1423,6 @@
Unlock
Scan your card to unlock access
Needed unlock
- Get your free Crypto Card\nin minutes
- Built-in security
- Your card details are protected — full control in the app.
- Everyday purchases
- Use your USDC balance to pay for everyday purchases seamlessly.
- Apple Pay & Google Pay
- Add to your wallet and pay with your phone anywhere.
- Get card
Blockchain is unreachable. Try later
Scan card or ring
This wallet has already been activated earlier.\nIf it was not done by you, please contact support.\nTangem never sells wallets along with pre-generated access codes.
@@ -1732,8 +1733,8 @@
How it works?
Aave is trusted by millions worldwide. Total lended value is $10.4B.
Decentralized and self-custodial
- By using service, you agree with provider
- Earn %s% yearly
+ By using service, you agree with provider %1$s and %2$s
+ Earn %s%% yearly
Aave • Variable Interest Rate
Aave
Avg %s
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt b/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt
index 7e95a24776..86dacb20d6 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/label/Label.kt
@@ -2,19 +2,22 @@ package com.tangem.core.ui.components.label
import android.content.res.Configuration
import androidx.compose.animation.AnimatedContent
+import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.height
-import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.*
+import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.R
import com.tangem.core.ui.components.label.entity.LabelStyle
import com.tangem.core.ui.components.label.entity.LabelUM
import com.tangem.core.ui.extensions.TextReference
@@ -48,8 +51,18 @@ fun Label(state: LabelUM, modifier: Modifier = Modifier) {
},
)
+ val iconColor by animateColorAsState(
+ targetValue = when (state.style) {
+ LabelStyle.ACCENT -> TangemTheme.colors.icon.accent
+ LabelStyle.REGULAR -> TangemTheme.colors.icon.informative
+ LabelStyle.WARNING -> TangemTheme.colors.icon.warning
+ },
+ )
+
AnimatedContent(targetState = state.text) { text ->
- Box(
+ Row(
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.spacedBy(4.dp),
modifier = modifier
.padding(horizontal = 4.dp)
.background(
@@ -63,6 +76,15 @@ fun Label(state: LabelUM, modifier: Modifier = Modifier) {
style = TangemTheme.typography.caption1,
color = textColor,
)
+ AnimatedVisibility(state.icon != null) {
+ val wrappedIcon = remember(this) { requireNotNull(state.icon) }
+ Icon(
+ imageVector = ImageVector.vectorResource(wrappedIcon),
+ tint = iconColor,
+ contentDescription = null,
+ modifier = Modifier.size(16.dp),
+ )
+ }
}
}
}
@@ -73,6 +95,7 @@ fun Label(state: LabelUM, modifier: Modifier = Modifier) {
private fun LabelPreview() {
TangemThemePreview {
Column(
+ verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier.padding(16.dp),
) {
Label(
@@ -81,24 +104,39 @@ private fun LabelPreview() {
style = LabelStyle.REGULAR,
),
)
-
- Spacer(modifier = Modifier.height(8.dp))
-
Label(
state = LabelUM(
text = TextReference.Str("Accent Label"),
style = LabelStyle.ACCENT,
),
)
-
- Spacer(modifier = Modifier.height(8.dp))
-
Label(
state = LabelUM(
text = TextReference.Str("Warning Label"),
style = LabelStyle.WARNING,
),
)
+ Label(
+ state = LabelUM(
+ text = TextReference.Str("Regular Label"),
+ style = LabelStyle.REGULAR,
+ icon = R.drawable.ic_information_24,
+ ),
+ )
+ Label(
+ state = LabelUM(
+ text = TextReference.Str("Accent Label"),
+ style = LabelStyle.ACCENT,
+ icon = R.drawable.ic_information_24,
+ ),
+ )
+ Label(
+ state = LabelUM(
+ text = TextReference.Str("Warning Label"),
+ style = LabelStyle.WARNING,
+ icon = R.drawable.ic_information_24,
+ ),
+ )
}
}
}
\ No newline at end of file
diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/label/entity/LabelUM.kt b/core/ui/src/main/java/com/tangem/core/ui/components/label/entity/LabelUM.kt
index 70b134bfe8..1be654c994 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/components/label/entity/LabelUM.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/components/label/entity/LabelUM.kt
@@ -1,10 +1,13 @@
package com.tangem.core.ui.components.label.entity
+import androidx.annotation.DrawableRes
import com.tangem.core.ui.extensions.TextReference
data class LabelUM(
val text: TextReference,
val style: LabelStyle,
+ @DrawableRes val icon: Int? = null,
+ val onIconClick: (() -> Unit)? = null,
)
enum class LabelStyle {
diff --git a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt
index 2e3d83710f..6128a71c4a 100644
--- a/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt
+++ b/core/ui/src/main/java/com/tangem/core/ui/decompose/ComposableBottomSheetComponent.kt
@@ -10,4 +10,13 @@ interface ComposableBottomSheetComponent {
@Composable
fun BottomSheet()
+}
+
+fun getEmptyComposableBottomSheetComponent() = EmptyComposableBottomSheetComponent
+
+object EmptyComposableBottomSheetComponent : ComposableBottomSheetComponent {
+ override fun dismiss() {}
+
+ @Composable
+ override fun BottomSheet() {}
}
\ No newline at end of file
diff --git a/core/ui/src/main/res/drawable/ic_analytics_up_24.xml b/core/ui/src/main/res/drawable/ic_analytics_up_24.xml
new file mode 100644
index 0000000000..be13c86516
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_analytics_up_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_flash_new_24.xml b/core/ui/src/main/res/drawable/ic_flash_new_24.xml
new file mode 100644
index 0000000000..71ad60eda8
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_flash_new_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_repeat_24.xml b/core/ui/src/main/res/drawable/ic_repeat_24.xml
new file mode 100644
index 0000000000..deb5797a0b
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_repeat_24.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/core/ui/src/main/res/drawable/ic_security_check_24.xml b/core/ui/src/main/res/drawable/ic_security_check_24.xml
new file mode 100644
index 0000000000..8a64f5924c
--- /dev/null
+++ b/core/ui/src/main/res/drawable/ic_security_check_24.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyPromoComponent.kt b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyPromoComponent.kt
new file mode 100644
index 0000000000..0516efb037
--- /dev/null
+++ b/features/yield-supply/api/src/main/java/com/tangem/features/yield/supply/api/YieldSupplyPromoComponent.kt
@@ -0,0 +1,16 @@
+package com.tangem.features.yield.supply.api
+
+import com.tangem.core.decompose.factory.ComponentFactory
+import com.tangem.core.ui.decompose.ComposableContentComponent
+import com.tangem.domain.models.currency.CryptoCurrency
+import com.tangem.domain.models.wallet.UserWalletId
+
+interface YieldSupplyPromoComponent : ComposableContentComponent {
+
+ data class Params(
+ val userWalletId: UserWalletId,
+ val currency: CryptoCurrency,
+ )
+
+ interface Factory : ComponentFactory
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/build.gradle.kts b/features/yield-supply/impl/build.gradle.kts
index 14dbb06d31..95021510f8 100644
--- a/features/yield-supply/impl/build.gradle.kts
+++ b/features/yield-supply/impl/build.gradle.kts
@@ -21,6 +21,7 @@ dependencies {
implementation(projects.core.configToggles)
implementation(projects.core.decompose)
implementation(projects.core.ui)
+ implementation(projects.core.navigation)
/** Common */
implementation(projects.common.ui)
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/DefaultYieldSupplyPromoComponent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/DefaultYieldSupplyPromoComponent.kt
new file mode 100644
index 0000000000..7e9414c4a1
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/DefaultYieldSupplyPromoComponent.kt
@@ -0,0 +1,56 @@
+package com.tangem.features.yield.supply.impl.promo
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.Modifier
+import com.arkivanov.decompose.extensions.compose.subscribeAsState
+import com.arkivanov.decompose.router.slot.childSlot
+import com.tangem.core.decompose.context.AppComponentContext
+import com.tangem.core.decompose.model.getOrCreateModel
+import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
+import com.tangem.core.ui.decompose.getEmptyComposableBottomSheetComponent
+import com.tangem.features.yield.supply.api.YieldSupplyPromoComponent
+import com.tangem.features.yield.supply.impl.promo.model.YieldSupplyPromoModel
+import com.tangem.features.yield.supply.impl.promo.ui.YieldSupplyPromoContent
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+internal class DefaultYieldSupplyPromoComponent @AssistedInject constructor(
+ @Assisted private val appComponentContext: AppComponentContext,
+ @Assisted private val params: YieldSupplyPromoComponent.Params,
+) : YieldSupplyPromoComponent, AppComponentContext by appComponentContext {
+
+ private val model: YieldSupplyPromoModel = getOrCreateModel(params = params)
+
+ private val bottomSheetSlot = childSlot(
+ source = model.bottomSheetNavigation,
+ serializer = null,
+ handleBackButton = false,
+ childFactory = { _, _ -> bottomSheetChild() },
+ )
+
+ @Composable
+ override fun Content(modifier: Modifier) {
+ val state = model.uiState
+ val bottomSheet by bottomSheetSlot.subscribeAsState()
+
+ YieldSupplyPromoContent(
+ yieldSupplyPromoUM = state,
+ clickIntents = model,
+ modifier = modifier,
+ )
+
+ bottomSheet.child?.instance?.BottomSheet()
+ }
+
+ private fun bottomSheetChild(): ComposableBottomSheetComponent = getEmptyComposableBottomSheetComponent()
+
+ @AssistedFactory
+ interface Factory : YieldSupplyPromoComponent.Factory {
+ override fun create(
+ context: AppComponentContext,
+ params: YieldSupplyPromoComponent.Params,
+ ): DefaultYieldSupplyPromoComponent
+ }
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/YieldSupplyPromoConfig.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/YieldSupplyPromoConfig.kt
new file mode 100644
index 0000000000..7a87ea9946
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/YieldSupplyPromoConfig.kt
@@ -0,0 +1,6 @@
+package com.tangem.features.yield.supply.impl.promo
+
+internal enum class YieldSupplyPromoConfig {
+ Apy,
+ Action,
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/di/YieldSupplyPromoBindsModule.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/di/YieldSupplyPromoBindsModule.kt
new file mode 100644
index 0000000000..95e0a79cc6
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/di/YieldSupplyPromoBindsModule.kt
@@ -0,0 +1,34 @@
+package com.tangem.features.yield.supply.impl.promo.di
+
+import com.tangem.core.decompose.di.ModelComponent
+import com.tangem.core.decompose.model.Model
+import com.tangem.features.yield.supply.impl.promo.DefaultYieldSupplyPromoComponent
+import com.tangem.features.yield.supply.impl.promo.model.YieldSupplyPromoModel
+import com.tangem.features.yield.supply.api.YieldSupplyPromoComponent
+import dagger.Binds
+import dagger.Module
+import dagger.hilt.InstallIn
+import dagger.hilt.components.SingletonComponent
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Singleton
+
+@Module
+@InstallIn(SingletonComponent::class)
+internal interface YieldSupplyPromoBindsModule {
+ @Binds
+ @Singleton
+ fun provideYieldSupplyPromoComponentFactory(
+ impl: DefaultYieldSupplyPromoComponent.Factory,
+ ): YieldSupplyPromoComponent.Factory
+}
+
+@Module
+@InstallIn(ModelComponent::class)
+internal interface YieldSupplyPromoModelModule {
+
+ @Binds
+ @IntoMap
+ @ClassKey(YieldSupplyPromoModel::class)
+ fun provideYieldSupplyPromoModel(impl: YieldSupplyPromoModel): Model
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/entity/YieldSupplyPromoUM.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/entity/YieldSupplyPromoUM.kt
new file mode 100644
index 0000000000..51eefdad41
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/entity/YieldSupplyPromoUM.kt
@@ -0,0 +1,9 @@
+package com.tangem.features.yield.supply.impl.promo.entity
+
+import com.tangem.core.ui.extensions.TextReference
+
+data class YieldSupplyPromoUM(
+ val tosLink: String,
+ val policyLink: String,
+ val title: TextReference,
+)
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoClickIntents.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoClickIntents.kt
new file mode 100644
index 0000000000..0bf70fa048
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoClickIntents.kt
@@ -0,0 +1,14 @@
+package com.tangem.features.yield.supply.impl.promo.model
+
+internal interface YieldSupplyPromoClickIntents {
+
+ fun onBackClick()
+
+ fun onApyInfoClick()
+
+ fun onHowItWorksClick()
+
+ fun onStartEarningClick()
+
+ fun onUrlClick(url: String)
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt
new file mode 100644
index 0000000000..9dbc5ecdd9
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/model/YieldSupplyPromoModel.kt
@@ -0,0 +1,51 @@
+package com.tangem.features.yield.supply.impl.promo.model
+
+import com.arkivanov.decompose.router.slot.SlotNavigation
+import com.arkivanov.decompose.router.slot.activate
+import com.tangem.common.routing.AppRouter
+import com.tangem.core.decompose.di.ModelScoped
+import com.tangem.core.decompose.model.Model
+import com.tangem.core.navigation.url.UrlOpener
+import com.tangem.core.ui.extensions.resourceReference
+import com.tangem.core.ui.extensions.wrappedList
+import com.tangem.features.yield.supply.impl.R
+import com.tangem.features.yield.supply.impl.promo.YieldSupplyPromoConfig
+import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM
+import com.tangem.utils.coroutines.CoroutineDispatcherProvider
+import javax.inject.Inject
+
+@ModelScoped
+internal class YieldSupplyPromoModel @Inject constructor(
+ override val dispatchers: CoroutineDispatcherProvider,
+ private val urlOpener: UrlOpener,
+ private val appRouter: AppRouter,
+) : Model(), YieldSupplyPromoClickIntents {
+
+ val uiState: YieldSupplyPromoUM = YieldSupplyPromoUM(
+ tosLink = "https://tangem.com/terms-of-service/", // TODO replace with real link
+ policyLink = "https://tangem.com/privacy-policy/", // TODO replace with real link
+ title = resourceReference(R.string.yield_module_promo_screen_title, wrappedList("5.3")),
+ )
+
+ val bottomSheetNavigation: SlotNavigation = SlotNavigation()
+
+ override fun onBackClick() {
+ appRouter.pop()
+ }
+
+ override fun onApyInfoClick() {
+ bottomSheetNavigation.activate(YieldSupplyPromoConfig.Apy)
+ }
+
+ override fun onUrlClick(url: String) {
+ urlOpener.openUrl(url)
+ }
+
+ override fun onHowItWorksClick() {
+ urlOpener.openUrl("https://tangem.com/") // TODO replace with real link
+ }
+
+ override fun onStartEarningClick() {
+ bottomSheetNavigation.activate(YieldSupplyPromoConfig.Action)
+ }
+}
\ No newline at end of file
diff --git a/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt
new file mode 100644
index 0000000000..5839f6fb28
--- /dev/null
+++ b/features/yield-supply/impl/src/main/java/com/tangem/features/yield/supply/impl/promo/ui/YieldSupplyPromoContent.kt
@@ -0,0 +1,239 @@
+package com.tangem.features.yield.supply.impl.promo.ui
+
+import android.content.res.Configuration
+import androidx.annotation.DrawableRes
+import androidx.compose.foundation.background
+import androidx.compose.foundation.clickable
+import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.shape.CircleShape
+import androidx.compose.material3.Icon
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.vector.ImageVector
+import androidx.compose.ui.res.vectorResource
+import androidx.compose.ui.text.LinkAnnotation
+import androidx.compose.ui.text.buildAnnotatedString
+import androidx.compose.ui.text.style.TextAlign
+import androidx.compose.ui.text.withLink
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import com.tangem.core.ui.components.*
+import com.tangem.core.ui.components.label.Label
+import com.tangem.core.ui.components.label.entity.LabelStyle
+import com.tangem.core.ui.components.label.entity.LabelUM
+import com.tangem.core.ui.extensions.*
+import com.tangem.core.ui.res.TangemTheme
+import com.tangem.core.ui.res.TangemThemePreview
+import com.tangem.features.yield.supply.impl.R
+import com.tangem.features.yield.supply.impl.promo.entity.YieldSupplyPromoUM
+import com.tangem.features.yield.supply.impl.promo.model.YieldSupplyPromoClickIntents
+import com.tangem.utils.StringsSigns
+
+@Suppress("MagicNumber")
+@Composable
+internal fun YieldSupplyPromoContent(
+ yieldSupplyPromoUM: YieldSupplyPromoUM,
+ clickIntents: YieldSupplyPromoClickIntents,
+ modifier: Modifier = Modifier,
+) {
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = modifier
+ .background(color = TangemTheme.colors.background.tertiary)
+ .fillMaxWidth()
+ .imePadding()
+ .systemBarsPadding()
+ .padding(horizontal = 16.dp),
+ ) {
+ YieldStatusAppBar(
+ onBackClick = clickIntents::onBackClick,
+ onHowItWorksClick = clickIntents::onHowItWorksClick,
+ )
+ Column(
+ horizontalAlignment = Alignment.CenterHorizontally,
+ modifier = Modifier.padding(horizontal = 20.dp),
+ ) {
+ Icon(
+ imageVector = ImageVector.vectorResource(R.drawable.ic_analytics_up_24),
+ tint = TangemTheme.colors.icon.accent,
+ contentDescription = null,
+ modifier = Modifier
+ .background(TangemTheme.colors.icon.accent.copy(0.1f), CircleShape)
+ .padding(12.dp)
+ .size(32.dp),
+ )
+ SpacerH(20.dp)
+ Text(
+ text = yieldSupplyPromoUM.title.resolveReference(),
+ style = TangemTheme.typography.h2,
+ color = TangemTheme.colors.text.primary1,
+ )
+ SpacerH8()
+ Label(
+ state = LabelUM(
+ text = resourceReference(R.string.yield_module_promo_screen_variable_rate_info),
+ style = LabelStyle.REGULAR,
+ icon = R.drawable.ic_information_24,
+ onIconClick = clickIntents::onApyInfoClick,
+ ),
+ )
+ SpacerH32()
+ PromoItems()
+ }
+ SpacerHMax()
+ YieldSupplyTosText(
+ tosLink = yieldSupplyPromoUM.tosLink,
+ policyLink = yieldSupplyPromoUM.policyLink,
+ onClick = clickIntents::onUrlClick,
+ )
+ PrimaryButton(
+ text = stringResourceSafe(R.string.yield_module_start_earning),
+ onClick = clickIntents::onStartEarningClick,
+ modifier = Modifier.fillMaxWidth(),
+ )
+ SpacerH8()
+ }
+}
+
+@Composable
+private fun YieldStatusAppBar(onBackClick: () -> Unit, onHowItWorksClick: () -> Unit) {
+ Row(
+ modifier = Modifier.padding(vertical = 16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Icon(
+ imageVector = ImageVector.vectorResource(R.drawable.ic_back_24),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.primary1,
+ modifier = Modifier.clickable(onClick = onBackClick),
+ )
+ SpacerWMax()
+ Text(
+ text = stringResourceSafe(R.string.yield_module_promo_screen_how_it_works_button_title),
+ style = TangemTheme.typography.body1,
+ color = TangemTheme.colors.text.primary1,
+ modifier = Modifier.clickable(onClick = onHowItWorksClick),
+ )
+ }
+}
+
+@Composable
+private fun PromoItems() {
+ PromoItem(
+ icon = R.drawable.ic_flash_new_24,
+ title = resourceReference(R.string.yield_module_promo_screen_cash_out_title),
+ subtitle = resourceReference(R.string.yield_module_promo_screen_cash_out_subtitle),
+ )
+ SpacerH24()
+ PromoItem(
+ icon = R.drawable.ic_repeat_24,
+ title = resourceReference(R.string.yield_module_promo_screen_auto_balance_title),
+ subtitle = resourceReference(R.string.yield_module_promo_screen_auto_balance_subtitle),
+ )
+ SpacerH24()
+ PromoItem(
+ icon = R.drawable.ic_security_check_24,
+ title = resourceReference(R.string.yield_module_promo_screen_self_custodial_title),
+ subtitle = resourceReference(R.string.yield_module_promo_screen_self_custodial_subtitle),
+ )
+}
+
+@Composable
+private fun PromoItem(@DrawableRes icon: Int, title: TextReference, subtitle: TextReference) {
+ Row(
+ horizontalArrangement = Arrangement.spacedBy(20.dp),
+ ) {
+ Icon(
+ imageVector = ImageVector.vectorResource(icon),
+ contentDescription = null,
+ tint = TangemTheme.colors.icon.accent,
+ )
+ Column(verticalArrangement = Arrangement.spacedBy(3.dp)) {
+ Text(
+ text = title.resolveReference(),
+ style = TangemTheme.typography.subtitle1,
+ color = TangemTheme.colors.text.primary1,
+ )
+ Text(
+ text = subtitle.resolveReference(),
+ style = TangemTheme.typography.body2,
+ color = TangemTheme.colors.text.secondary,
+ )
+ }
+ }
+}
+
+@Composable
+private fun YieldSupplyTosText(tosLink: String, policyLink: String, onClick: (String) -> Unit) {
+ val tosTitle = stringResourceSafe(R.string.common_terms_of_use)
+ val policyTitle = stringResourceSafe(R.string.common_privacy_policy)
+ val fullString = stringResourceSafe(id = R.string.yield_module_promo_screen_terms_disclaimer, tosTitle, policyTitle)
+ val tosIndex = fullString.indexOf(tosTitle)
+ val policyIndex = fullString.indexOf(policyTitle)
+
+ Text(
+ text = buildAnnotatedString {
+ append(StringsSigns.POINT_SIGN)
+ appendSpace()
+ append(fullString.substring(0, tosIndex))
+ withLink(
+ link = LinkAnnotation.Clickable(
+ tag = "TOS_TAG",
+ linkInteractionListener = { onClick(tosLink) },
+ ),
+ block = {
+ appendColored(
+ text = fullString.substring(tosIndex, tosIndex + tosTitle.length),
+ color = TangemTheme.colors.text.accent,
+ )
+ },
+ )
+ append(fullString.substring(tosIndex + tosTitle.length, policyIndex))
+ withLink(
+ link = LinkAnnotation.Clickable(
+ tag = "POLICY_TAG",
+ linkInteractionListener = { onClick(policyLink) },
+ ),
+ block = {
+ appendColored(
+ text = fullString.substring(policyIndex, policyIndex + policyTitle.length),
+ color = TangemTheme.colors.text.accent,
+ )
+ },
+ )
+ },
+ textAlign = TextAlign.Center,
+ style = TangemTheme.typography.caption2,
+ color = TangemTheme.colors.text.tertiary,
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(16.dp),
+ )
+}
+
+// region Preview
+@Composable
+@Preview(showBackground = true, widthDp = 360, heightDp = 724)
+@Preview(showBackground = true, widthDp = 360, heightDp = 724, uiMode = Configuration.UI_MODE_NIGHT_YES)
+private fun YieldSupplyPromoContent_Preview() {
+ TangemThemePreview {
+ YieldSupplyPromoContent(
+ yieldSupplyPromoUM = YieldSupplyPromoUM(
+ tosLink = "https://tangem.com/terms-of-service/",
+ policyLink = "https://tangem.com/privacy-policy/",
+ title = resourceReference(R.string.yield_module_promo_screen_title, wrappedList("5.3")),
+ ),
+ clickIntents = object : YieldSupplyPromoClickIntents {
+ override fun onBackClick() {}
+ override fun onApyInfoClick() {}
+ override fun onHowItWorksClick() {}
+ override fun onStartEarningClick() {}
+ override fun onUrlClick(url: String) {}
+ },
+ )
+ }
+}
+
+// endregion
\ No newline at end of file