Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-28 10:45:08 +03:00
parent 967d5520a1
commit fea0ea5890
11 changed files with 57 additions and 161 deletions

View file

@ -7,7 +7,6 @@ import com.tangem.domain.tokens.*
import com.tangem.domain.tokens.repository.*
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.feature.swap.domain.api.SwapRepository
import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
@ -234,7 +233,6 @@ internal object TokensDomainModule {
networksRepository: NetworksRepository,
stakingRepository: StakingRepository,
stakingFeatureToggles: StakingFeatureToggles,
marketsFeatureToggles: MarketsFeatureToggles,
dispatchers: CoroutineDispatcherProvider,
): GetCryptoCurrencyActionsUseCase {
return GetCryptoCurrencyActionsUseCase(
@ -246,7 +244,6 @@ internal object TokensDomainModule {
networksRepository = networksRepository,
stakingRepository = stakingRepository,
stakingFeatureToggles = stakingFeatureToggles,
marketsFeatureToggles = marketsFeatureToggles,
dispatchers = dispatchers,
)
}

View file

@ -12,7 +12,6 @@ import com.tangem.domain.tokens.repository.NetworksRepository
import com.tangem.domain.tokens.repository.QuotesRepository
import com.tangem.domain.walletmanager.WalletManagersFacade
import com.tangem.domain.wallets.models.UserWallet
import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import com.tangem.utils.isNullOrZero
@ -34,7 +33,6 @@ class GetCryptoCurrencyActionsUseCase(
private val networksRepository: NetworksRepository,
private val stakingRepository: StakingRepository,
private val stakingFeatureToggles: StakingFeatureToggles,
private val marketsFeatureToggles: MarketsFeatureToggles,
private val dispatchers: CoroutineDispatcherProvider,
) {
@ -116,7 +114,7 @@ class GetCryptoCurrencyActionsUseCase(
// markets
// not a custom token
if (marketsFeatureToggles.isFeatureEnabled && cryptoCurrencyStatus.currency.id.rawCurrencyId != null) {
if (cryptoCurrencyStatus.currency.id.rawCurrencyId != null) {
activeList.add(TokenActionsState.ActionState.Analytics(ScenarioUnavailabilityReason.None))
}

View file

@ -1,5 +0,0 @@
package com.tangem.features.markets
interface MarketsFeatureToggles {
val isFeatureEnabled: Boolean
}

View file

@ -1,11 +0,0 @@
package com.tangem.features.markets
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
internal class DefaultMarketsFeatureToggles(
private val featureTogglesManager: FeatureTogglesManager,
) : MarketsFeatureToggles {
override val isFeatureEnabled: Boolean
get() = featureTogglesManager.isFeatureEnabled("MARKETS_ENABLED")
}

View file

@ -1,20 +0,0 @@
package com.tangem.features.markets.di
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
import com.tangem.features.markets.DefaultMarketsFeatureToggles
import com.tangem.features.markets.MarketsFeatureToggles
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object FeatureModule {
@Provides
@Singleton
fun provideFeatureToggles(featureTogglesManager: FeatureTogglesManager): MarketsFeatureToggles =
DefaultMarketsFeatureToggles(featureTogglesManager = featureTogglesManager)
}

View file

@ -20,7 +20,6 @@ import com.tangem.domain.tokens.model.CryptoCurrency
import com.tangem.feature.tokendetails.presentation.router.InnerTokenDetailsRouter
import com.tangem.feature.tokendetails.presentation.tokendetails.ui.TokenDetailsScreen
import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsViewModel
import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.markets.token.block.TokenMarketBlockComponent
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -36,9 +35,6 @@ internal class TokenDetailsFragment : ComposeFragment() {
@Inject
lateinit var tokenDetailsRouter: TokenDetailsRouter
@Inject
internal lateinit var marketsFeatureToggles: MarketsFeatureToggles
@Inject
internal lateinit var coroutineDispatcherProvider: CoroutineDispatcherProvider
@ -61,27 +57,25 @@ internal class TokenDetailsFragment : ComposeFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (marketsFeatureToggles.isFeatureEnabled) {
val cryptoCurrency: CryptoCurrency = arguments
?.getBundle(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY)
?.unbundle(CryptoCurrency.serializer())
?: error("Token Details screen can't be opened without `CryptoCurrency`")
val cryptoCurrency: CryptoCurrency = arguments
?.getBundle(AppRoute.CurrencyDetails.CRYPTO_CURRENCY_KEY)
?.unbundle(CryptoCurrency.serializer())
?: error("Token Details screen can't be opened without `CryptoCurrency`")
val param = cryptoCurrency.toParam() ?: return
val param = cryptoCurrency.toParam() ?: return
val appContext = DefaultAppComponentContext(
componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher),
messageHandler = uiDependencies.eventMessageHandler,
dispatchers = coroutineDispatcherProvider,
hiltComponentBuilder = componentBuilder,
replaceRouter = appRouter.asRouter(),
)
val appContext = DefaultAppComponentContext(
componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher),
messageHandler = uiDependencies.eventMessageHandler,
dispatchers = coroutineDispatcherProvider,
hiltComponentBuilder = componentBuilder,
replaceRouter = appRouter.asRouter(),
)
tokenMarketBlockComponent = tokenMarketBlockComponentFactory.create(
appComponentContext = appContext,
params = param,
)
}
tokenMarketBlockComponent = tokenMarketBlockComponentFactory.create(
appComponentContext = appContext,
params = param,
)
}
private fun CryptoCurrency.toParam(): TokenMarketBlockComponent.Params? {

View file

@ -12,7 +12,6 @@ import com.tangem.core.decompose.di.DecomposeComponent
import com.tangem.core.ui.UiDependencies
import com.tangem.core.ui.screen.ComposeFragment
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.markets.entry.MarketsEntryComponent
import com.tangem.features.wallet.navigation.WalletRouter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
@ -43,13 +42,10 @@ internal class WalletFragment : ComposeFragment() {
@Inject
internal lateinit var componentBuilder: DecomposeComponent.Builder
@Inject
internal lateinit var marketsFeatureToggles: MarketsFeatureToggles
@Inject
internal lateinit var appRouter: AppRouter
private var marketsEntryComponent: MarketsEntryComponent? = null
private lateinit var marketsEntryComponent: MarketsEntryComponent
private val _walletRouter: InnerWalletRouter
get() = requireNotNull(walletRouter as? InnerWalletRouter) {
@ -59,17 +55,15 @@ internal class WalletFragment : ComposeFragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (marketsFeatureToggles.isFeatureEnabled) {
val appContext = DefaultAppComponentContext(
componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher),
messageHandler = uiDependencies.eventMessageHandler,
dispatchers = coroutineDispatcherProvider,
hiltComponentBuilder = componentBuilder,
replaceRouter = appRouter.asRouter(),
)
val appContext = DefaultAppComponentContext(
componentContext = defaultComponentContext(requireActivity().onBackPressedDispatcher),
messageHandler = uiDependencies.eventMessageHandler,
dispatchers = coroutineDispatcherProvider,
hiltComponentBuilder = componentBuilder,
replaceRouter = appRouter.asRouter(),
)
marketsEntryComponent = marketsEntryComponentFactory.create(appContext)
}
marketsEntryComponent = marketsEntryComponentFactory.create(appContext)
}
@Composable

View file

@ -42,7 +42,7 @@ internal class DefaultWalletRouter(
override fun getEntryFragment(): Fragment = WalletFragment.create()
@Composable
override fun Initialize(onFinish: () -> Unit, marketsEntryComponent: MarketsEntryComponent?) {
override fun Initialize(onFinish: () -> Unit, marketsEntryComponent: MarketsEntryComponent) {
this.onFinish = onFinish
NavHost(

View file

@ -24,7 +24,7 @@ internal interface InnerWalletRouter : WalletRouter {
* @param onFinish finish activity callback
*/
@Composable
fun Initialize(onFinish: () -> Unit, marketsEntryComponent: MarketsEntryComponent?)
fun Initialize(onFinish: () -> Unit, marketsEntryComponent: MarketsEntryComponent)
/** Pop back stack */
fun popBackStack()

View file

@ -45,7 +45,6 @@ import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.tangem.core.ui.components.BottomFade
import com.tangem.core.ui.components.atoms.Hand
import com.tangem.core.ui.components.atoms.handComposableComponentHeight
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
@ -65,7 +64,6 @@ import com.tangem.core.ui.res.LocalWindowSize
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.core.ui.test.TestTags
import com.tangem.core.ui.utils.WindowInsetsZero
import com.tangem.core.ui.utils.lineTo
import com.tangem.core.ui.utils.moveTo
import com.tangem.core.ui.utils.toPx
@ -93,7 +91,7 @@ import kotlinx.coroutines.launch
import kotlin.math.roundToInt
@Composable
internal fun WalletScreen(state: WalletScreenState, marketsEntryComponent: MarketsEntryComponent?) {
internal fun WalletScreen(state: WalletScreenState, marketsEntryComponent: MarketsEntryComponent) {
BackHandler(onBack = state.onBackClick)
// It means that screen is still initializing
@ -137,7 +135,7 @@ private fun WalletContent(
walletsListState: LazyListState,
snackbarHostState: SnackbarHostState,
isAutoScroll: State<Boolean>,
marketsEntryComponent: MarketsEntryComponent?,
marketsEntryComponent: MarketsEntryComponent,
alertConfig: WalletAlertState?,
onAutoScrollReset: () -> Unit,
) {
@ -239,82 +237,26 @@ private fun WalletContent(
)
}
if (marketsEntryComponent != null) {
val bottomSheetState = remember { mutableStateOf(BottomSheetState.COLLAPSED) }
val bottomSheetState = remember { mutableStateOf(BottomSheetState.COLLAPSED) }
var headerSize by remember { mutableStateOf(0.dp) }
var headerSize by remember { mutableStateOf(0.dp) }
BaseScaffoldWithMarkets(
state = state,
listState = listState,
selectedWallet = selectedWallet,
snackbarHostState = snackbarHostState,
bottomSheetHeaderHeightProvider = { headerSize },
alertConfig = alertConfig,
onBottomSheetStateChange = { bottomSheetState.value = it },
bottomSheetContent = {
marketsEntryComponent.BottomSheetContent(
bottomSheetState = bottomSheetState,
onHeaderSizeChange = { headerSize = it },
modifier = Modifier,
)
},
content = scaffoldContent,
)
} else {
BaseScaffold(
state = state,
selectedWallet = selectedWallet,
snackbarHostState = snackbarHostState,
content = { scaffoldContent(null) },
)
}
}
@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun BaseScaffold(
state: WalletScreenState,
selectedWallet: WalletState,
snackbarHostState: SnackbarHostState,
content: @Composable () -> Unit,
) {
Scaffold(
topBar = { WalletTopBar(config = state.topBarConfig) },
contentWindowInsets = WindowInsetsZero,
snackbarHost = {
WalletSnackbarHost(
snackbarHostState = snackbarHostState,
event = state.event,
modifier = Modifier.padding(bottom = TangemTheme.dimens.spacing16),
BaseScaffoldWithMarkets(
state = state,
listState = listState,
selectedWallet = selectedWallet,
snackbarHostState = snackbarHostState,
bottomSheetHeaderHeightProvider = { headerSize },
alertConfig = alertConfig,
onBottomSheetStateChange = { bottomSheetState.value = it },
bottomSheetContent = {
marketsEntryComponent.BottomSheetContent(
bottomSheetState = bottomSheetState,
onHeaderSizeChange = { headerSize = it },
modifier = Modifier,
)
},
floatingActionButtonPosition = FabPosition.Center,
containerColor = TangemTheme.colors.background.secondary,
content = {
val pullRefreshState = rememberPullRefreshState(
refreshing = selectedWallet.pullToRefreshConfig.isRefreshing,
onRefresh = {
selectedWallet.pullToRefreshConfig.onRefresh(PullToRefreshConfig.ShowRefreshState())
},
)
Box(
modifier = Modifier
.pullRefresh(pullRefreshState)
.padding(it),
) {
content()
WalletPullToRefreshIndicator(
isRefreshing = selectedWallet.pullToRefreshConfig.isRefreshing,
state = pullRefreshState,
modifier = Modifier.align(Alignment.TopCenter),
)
BottomFade(Modifier.align(Alignment.BottomCenter))
}
},
content = scaffoldContent,
)
}
@ -771,7 +713,16 @@ private fun WalletScreen_Preview(@PreviewParameter(WalletScreenPreviewProvider::
TangemThemePreview {
WalletScreen(
state = data,
marketsEntryComponent = null,
marketsEntryComponent = object : MarketsEntryComponent {
@Composable
override fun BottomSheetContent(
bottomSheetState: State<BottomSheetState>,
onHeaderSizeChange: (Dp) -> Unit,
modifier: Modifier,
) {
Text("Markets Content")
}
},
)
}
}

View file

@ -29,7 +29,6 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
import com.tangem.feature.wallet.presentation.wallet.viewmodels.intents.WalletClickIntents
import com.tangem.features.markets.MarketsFeatureToggles
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
import com.tangem.utils.Provider
@ -68,7 +67,6 @@ internal class WalletViewModel @Inject constructor(
private val walletNameMigrationUseCase: WalletNameMigrationUseCase,
private val refreshMultiCurrencyWalletQuotesUseCase: RefreshMultiCurrencyWalletQuotesUseCase,
private val shouldAskPermissionUseCase: ShouldAskPermissionUseCase,
private val marketsFeatureToggles: MarketsFeatureToggles,
private val walletImageResolver: WalletImageResolver,
private val tokenListStore: MultiWalletTokenListStore,
analyticsEventsHandler: AnalyticsEventHandler,
@ -130,7 +128,7 @@ internal class WalletViewModel @Inject constructor(
viewModelScope.launch {
withContext(dispatchers.io) { delay(timeMillis = 1_800) }
if (marketsFeatureToggles.isFeatureEnabled && shouldShowMarketsTooltipUseCase()) {
if (shouldShowMarketsTooltipUseCase()) {
stateHolder.update {
it.copy(showMarketsOnboarding = true)
}