Updated on 2026-08-14

This commit is contained in:
Tangem 2023-09-08 15:18:27 +03:00
parent c1964170e2
commit a4a63d34e5
21 changed files with 119 additions and 62 deletions

View file

@ -27,7 +27,6 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.common.LogConfig
import com.tangem.domain.wallets.legacy.WalletManagersRepository
import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
import com.tangem.features.wallet.featuretoggles.WalletFeatureToggles
import com.tangem.tap.common.analytics.AnalyticsFactory
@ -150,8 +149,8 @@ class TapApplication : Application(), ImageLoaderFactory {
@Inject
lateinit var walletConnectSessionsRepository: WalletConnectSessionsRepository
@Inject
lateinit var learn2earnInteractor: Learn2earnInteractor
// @Inject
// lateinit var learn2earnInteractor: Learn2earnInteractor
@Inject
lateinit var tokenDetailsFeatureToggles: TokenDetailsFeatureToggles
@ -232,7 +231,7 @@ class TapApplication : Application(), ImageLoaderFactory {
// [REDACTED_JIRA]
runBlocking {
featureTogglesManager.init()
learn2earnInteractor.init()
// learn2earnInteractor.init()
}
initTopUpController()

View file

@ -2,10 +2,13 @@ package com.tangem.tap.common.redux.global
import com.tangem.domain.redux.domainStore
import com.tangem.domain.redux.global.DomainGlobalAction
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.onboarding.OnboardingManager
import com.tangem.tap.preferencesStorage
import com.tangem.tap.proxy.AppStateHolder
import com.tangem.tap.store
import com.tangem.utils.extensions.replaceBy
import org.rekotlin.Action
@ -82,9 +85,12 @@ fun globalReducer(action: Action, state: AppState, appStateHolder: AppStateHolde
}
is GlobalAction.SetIfCardVerifiedOnline ->
globalState.copy(cardVerifiedOnline = action.verified)
is GlobalAction.FetchUserCountry.Success -> globalState.copy(
userCountryCode = action.countryCode,
)
is GlobalAction.FetchUserCountry.Success -> {
store.dispatchOnMain(HomeAction.UpdateCountryCode(action.countryCode))
globalState.copy(
userCountryCode = action.countryCode,
)
}
is GlobalAction.UpdateUserWalletsListManager -> {
appStateHolder.userWalletsListManager = action.manager
globalState.copy(

View file

@ -12,18 +12,15 @@ import androidx.compose.ui.platform.ComposeView
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsControllerCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.lifecycleScope
import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.res.TangemTheme
import com.tangem.feature.learn2earn.presentation.Learn2earnViewModel
import com.tangem.tap.common.analytics.events.IntroductionProcess
import com.tangem.tap.features.home.compose.StoriesScreen
import com.tangem.tap.features.home.redux.HomeAction
import com.tangem.tap.features.home.redux.HomeState
import com.tangem.tap.features.home.redux.Stories
import com.tangem.tap.features.tokens.legacy.redux.TokensAction
import com.tangem.tap.store
import dagger.hilt.android.AndroidEntryPoint
@ -35,7 +32,7 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
private var homeState: MutableState<HomeState> = mutableStateOf(store.state.homeState)
private val learn2earnViewModel by activityViewModels<Learn2earnViewModel>()
// private val learn2earnViewModel by activityViewModels<Learn2earnViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@ -45,10 +42,10 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
// sync adding story before screen creation
if (learn2earnViewModel.uiState.storyScreenState.isVisible) {
store.dispatch(HomeAction.InsertStory(position = 0, Stories.OneInchPromo))
homeState.value = store.state.homeState
}
// if (learn2earnViewModel.uiState.storyScreenState.isVisible) {
// store.dispatch(HomeAction.InsertStory(position = 0, Stories.OneInchPromo))
// homeState.value = store.state.homeState
// }
return ComposeView(inflater.context).apply {
setContent {
TangemTheme {
@ -93,7 +90,7 @@ class HomeFragment : Fragment(), StoreSubscriber<HomeState> {
private fun ScreenContent() {
StoriesScreen(
homeState = homeState,
onLearn2earnClick = learn2earnViewModel.uiState.storyScreenState.onClick,
onLearn2earnClick = {}, // learn2earnViewModel.uiState.storyScreenState.onClick,
onScanButtonClick = {
Analytics.send(IntroductionProcess.ButtonScanCard())
lifecycleScope.launch {

View file

@ -178,11 +178,19 @@ private fun StoriesScreenContent(config: StoriesScreenContentConfig, modifier: M
)
when (config.currentStory) {
Stories.OneInchPromo -> Learn2earnStoriesScreen(config.onLearn2earnClick)
Stories.TangemIntro -> FirstStoriesContent(isPaused, currentStoryDuration) {
Stories.TangemIntro -> FirstStoriesContent(
isPaused = isPaused,
duration = currentStoryDuration,
isNewWalletAvailable = config.currentStory.isNewWalletAvailable,
) {
hideContent = it
}
Stories.RevolutionaryWallet -> StoriesRevolutionaryWallet(currentStoryDuration)
Stories.UltraSecureBackup -> StoriesUltraSecureBackup(isPaused, currentStoryDuration)
is Stories.UltraSecureBackup -> StoriesUltraSecureBackup(
isPaused = isPaused,
stepDuration = currentStoryDuration,
isNewWalletAvailable = config.currentStory.isNewWalletAvailable,
)
Stories.Currencies -> StoriesCurrencies(isPaused, currentStoryDuration)
Stories.Web3 -> StoriesWeb3(isPaused, currentStoryDuration)
Stories.WalletForEveryone -> StoriesWalletForEveryone(currentStoryDuration)

View file

@ -2,13 +2,12 @@ package com.tangem.tap.features.home.compose.content
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.*
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -56,7 +55,7 @@ fun StoriesRevolutionaryWallet(stepDuration: Int) {
}
@Composable
fun StoriesUltraSecureBackup(isPaused: Boolean, stepDuration: Int) {
fun StoriesUltraSecureBackup(isPaused: Boolean, stepDuration: Int, isNewWalletAvailable: MutableState<Boolean>) {
val subtitleText = buildAnnotatedString {
append(stringResource(id = R.string.story_backup_description_1))
append(" ")
@ -75,7 +74,11 @@ fun StoriesUltraSecureBackup(isPaused: Boolean, stepDuration: Int) {
)
},
bottomContent = {
FloatingCardsContent(isPaused, stepDuration)
FloatingCardsContent(
isPaused = isPaused,
stepDuration = stepDuration,
isNewWalletAvailable = isNewWalletAvailable,
)
},
)
}
@ -230,7 +233,13 @@ private fun RevolutionaryWalletPreview() {
@Preview
@Composable
private fun UltraSecureBackupPreview() {
StoriesUltraSecureBackup(false, 6000)
StoriesUltraSecureBackup(
false,
6000,
remember {
mutableStateOf(true)
},
)
}
@Preview

View file

@ -32,7 +32,12 @@ import com.tangem.wallet.R
@Suppress("LongMethod", "ComplexMethod", "MagicNumber")
@Composable
fun FirstStoriesContent(isPaused: Boolean, duration: Int, onHideContent: (Boolean) -> Unit) {
fun FirstStoriesContent(
isPaused: Boolean,
duration: Int,
isNewWalletAvailable: MutableState<Boolean>,
onHideContent: (Boolean) -> Unit,
) {
val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current)
val screenState = remember { mutableStateOf(StartingScreenState.INIT) }
@ -115,13 +120,18 @@ fun FirstStoriesContent(isPaused: Boolean, duration: Int, onHideContent: (Boolea
.weight(1.2f)
.wrapContentSize(),
) {
val painter = if (isNewWalletAvailable.value) {
painterResource(id = R.drawable.img_meet_tangem2)
} else {
painterResource(id = R.drawable.img_meet_tangem)
}
StoriesBottomImageAnimation(
totalDuration = duration,
firstStepDuration = 400,
) { modifier ->
Image(
modifier = modifier.fillMaxWidth(),
painter = painterResource(id = R.drawable.img_meet_tangem),
painter = painter,
contentDescription = "Tangem Wallet card",
)
}
@ -178,5 +188,11 @@ private fun MutableState<StartingScreenState>.isMeetTangemDisplaying(): Boolean
@Preview
@Composable
private fun FirstStoriesPreview() {
FirstStoriesContent(false, 8000) {}
FirstStoriesContent(
false,
8000,
remember {
mutableStateOf(false)
},
) {}
}

View file

@ -4,6 +4,7 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
@ -21,9 +22,13 @@ import com.tangem.wallet.R
[REDACTED_AUTHOR]
*/
@Composable
fun FloatingCardsContent(isPaused: Boolean, stepDuration: Int) {
fun FloatingCardsContent(isPaused: Boolean, stepDuration: Int, isNewWalletAvailable: MutableState<Boolean>) {
val bottomInsetsPx = WindowInsets.navigationBars.getBottom(LocalDensity.current)
val imageBitmap = asImageBitmap(R.drawable.img_card_placeholder_wallet_2)
val imageBitmap = if (isNewWalletAvailable.value) {
asImageBitmap(R.drawable.img_card_placeholder_wallet_2)
} else {
asImageBitmap(R.drawable.card_placeholder_wallet)
}
val cards = listOf(
FloatingCard.first(),
FloatingCard.second(),

View file

@ -29,5 +29,7 @@ sealed class HomeAction : Action {
data class ScanInProgress(val scanInProgress: Boolean) : HomeAction()
data class GoToShop(val userCountryCode: String?) : HomeAction()
data class UpdateCountryCode(val userCountryCode: String) : HomeAction()
data class ChangeScanCardButtonState(val state: IndeterminateProgressButton) : HomeAction()
}

View file

@ -7,10 +7,10 @@ object HomeReducer {
fun reduce(action: Action, state: AppState): HomeState = internalReduce(action, state)
}
private fun internalReduce(action: Action, state: AppState): HomeState {
if (action !is HomeAction) return state.homeState
private fun internalReduce(action: Action, appState: AppState): HomeState {
if (action !is HomeAction) return appState.homeState
var state = state.homeState
var state = appState.homeState
when (action) {
is HomeAction.InsertStory -> {
state = state.copy(
@ -25,6 +25,9 @@ private fun internalReduce(action: Action, state: AppState): HomeState {
is HomeAction.ChangeScanCardButtonState -> {
state = state.copy(btnScanState = action.state)
}
is HomeAction.UpdateCountryCode -> {
state.onCountryCodeUpdate(state, action.userCountryCode)
}
else -> {}
}

View file

@ -1,9 +1,12 @@
package com.tangem.tap.features.home.redux
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import com.tangem.tap.common.entities.IndeterminateProgressButton
import com.tangem.tap.features.send.redux.states.ButtonState
import com.tangem.tap.features.wallet.redux.ProgressState
import org.rekotlin.StateType
import java.util.Locale
data class HomeState(
val scanInProgress: Boolean = false,
@ -19,7 +22,16 @@ data class HomeState(
fun stepOf(story: Stories): Int = stories.indexOf(story)
fun onCountryCodeUpdate(homeState: HomeState, countryCode: String) {
val isNewWalletAvailable = !(countryCode == RUSSIA_COUNTRY_CODE || countryCode == BELARUS_COUNTRY_CODE)
homeState.stories.forEach {
it.isNewWalletAvailable.value = isNewWalletAvailable
}
}
companion object {
private const val RUSSIA_COUNTRY_CODE = "ru"
private const val BELARUS_COUNTRY_CODE = "by"
fun initDefaultStories(): List<Stories> = listOf(
Stories.TangemIntro,
Stories.RevolutionaryWallet,
@ -28,12 +40,18 @@ data class HomeState(
Stories.Web3,
Stories.WalletForEveryone,
)
fun isNewWalletAvailableInit(): Boolean {
val locale = Locale.getDefault().language
return !(locale == RUSSIA_COUNTRY_CODE || locale == BELARUS_COUNTRY_CODE)
}
}
}
sealed class Stories(
val isDarkBackground: Boolean,
val duration: Int,
val isNewWalletAvailable: MutableState<Boolean> = mutableStateOf(HomeState.isNewWalletAvailableInit()),
) {
object OneInchPromo : Stories(true, duration = 8000)
object TangemIntro : Stories(true, duration = 8000)

View file

@ -8,9 +8,7 @@ import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.flowWithLifecycle
@ -26,16 +24,12 @@ import com.tangem.core.analytics.Analytics
import com.tangem.core.navigation.AppScreen
import com.tangem.core.navigation.NavigationAction
import com.tangem.core.ui.fragments.setStatusBarColor
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.utils.OneTouchClickListener
import com.tangem.datasource.connection.NetworkConnectionManager
import com.tangem.feature.learn2earn.presentation.Learn2earnViewModel
import com.tangem.feature.learn2earn.presentation.ui.Learn2earnMainPageScreen
import com.tangem.feature.swap.api.SwapFeatureToggleManager
import com.tangem.feature.swap.domain.SwapInteractor
import com.tangem.tap.MainActivity
import com.tangem.tap.common.analytics.events.Portfolio
import com.tangem.tap.common.extensions.beginDelayedTransition
import com.tangem.tap.common.extensions.show
import com.tangem.tap.common.recyclerView.SpaceItemDecoration
import com.tangem.tap.common.redux.global.GlobalAction
@ -79,7 +73,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
private var walletView: WalletView = MultiWalletView()
private val learn2earnViewModel by activityViewModels<Learn2earnViewModel>()
// private val learn2earnViewModel by activityViewModels<Learn2earnViewModel>()
private val viewModel by viewModels<WalletViewModel>()
private val totalBalanceWatcher = modelWatcher {
@ -109,7 +103,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.slide_right)
exitTransition = inflater.inflateTransition(R.transition.fade)
learn2earnViewModel.onMainScreenCreated()
// learn2earnViewModel.onMainScreenCreated()
}
override fun onStart() {
@ -212,27 +206,27 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
if (state.canSaveUserWallets) R.drawable.ic_wallet_24 else R.drawable.ic_tap_card_24,
)
showLearn2earnView()
// showLearn2earnView()
}
private fun showLearn2earnView() {
val isShowing = learn2earnViewModel.uiState.mainScreenState.isVisible
if (!isShowing) return
binding.composeLearnToEarnContainer.show(true) { binding.llWarnings.beginDelayedTransition() }
binding.composeLearnToEarnContainer.apply {
setViewCompositionStrategy(
strategy = ViewCompositionStrategy.DisposeOnLifecycleDestroyed(
lifecycle = this@WalletFragment.lifecycle,
),
)
setContent {
TangemTheme {
Learn2earnMainPageScreen(learn2earnViewModel.uiState)
}
}
}
}
// private fun showLearn2earnView() {
// val isShowing = learn2earnViewModel.uiState.mainScreenState.isVisible
// if (!isShowing) return
//
// binding.composeLearnToEarnContainer.show(true) { binding.llWarnings.beginDelayedTransition() }
// binding.composeLearnToEarnContainer.apply {
// setViewCompositionStrategy(
// strategy = ViewCompositionStrategy.DisposeOnLifecycleDestroyed(
// lifecycle = [REDACTED_EMAIL],
// ),
// )
// setContent {
// TangemTheme {
// Learn2earnMainPageScreen(learn2earnViewModel.uiState)
// }
// }
// }
// }
private fun setupPullToRefreshLayout(state: WalletState) {
setupErrorPullToRefreshState(state)
@ -272,7 +266,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
private fun refreshWalletData() {
Analytics.send(Portfolio.Refreshed())
store.dispatch(WalletAction.LoadData.Refresh)
learn2earnViewModel.onMainScreenRefreshed()
// learn2earnViewModel.onMainScreenRefreshed()
}
private fun showWarningsIfPresent(warnings: List<WarningMessage>) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 222 KiB

After

Width:  |  Height:  |  Size: 266 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 484 KiB

After

Width:  |  Height:  |  Size: 512 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 KiB

View file

Before

Width:  |  Height:  |  Size: 818 KiB

After

Width:  |  Height:  |  Size: 818 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 KiB