Updated on 2026-08-14

This commit is contained in:
Tangem 2024-05-20 13:57:30 +02:00
parent 68e5d9d174
commit 947ad15975
13 changed files with 117 additions and 10 deletions

View file

@ -6,6 +6,8 @@ import com.tangem.domain.exchange.RampStateManager
import com.tangem.domain.tokens.GetPolkadotCheckHasImmortalUseCase
import com.tangem.domain.tokens.GetPolkadotCheckHasResetUseCase
import com.tangem.domain.tokens.repository.PolkadotAccountHealthCheckRepository
import com.tangem.feature.tester.ActivityClassWrapper
import com.tangem.tap.MainActivity
import com.tangem.tap.domain.sdk.TangemSdkManager
import com.tangem.tap.domain.scanCard.repository.DefaultScanCardRepository
import com.tangem.tap.network.exchangeServices.DefaultRampManager
@ -65,4 +67,10 @@ internal object ActivityModule {
): GetPolkadotCheckHasImmortalUseCase {
return GetPolkadotCheckHasImmortalUseCase(polkadotAccountHealthCheckRepository)
}
@Provides
@Singleton
fun provideActivityClassWrapper(): ActivityClassWrapper {
return ActivityClassWrapper(MainActivity::class.java)
}
}

View file

@ -0,0 +1,9 @@
package com.tangem.features.tester.api
/**
* Interface for app restarter
*/
interface AppRestarter {
fun restart()
}

View file

@ -0,0 +1,12 @@
package com.tangem.feature.tester
import android.app.Activity
/**
* Wraps the main activity class to avoid type erasure issues during injection.
*
* @property clazz activity class
*/
class ActivityClassWrapper(
val clazz: Class<out Activity>,
)

View file

@ -0,0 +1,27 @@
package com.tangem.feature.tester.apprestarter
import android.app.Activity
import android.content.Context
import android.content.Intent
import com.tangem.feature.tester.ActivityClassWrapper
import com.tangem.features.tester.api.AppRestarter
/**
* Entity that kills the process and restarts the main activity
* @property context Activity context
*/
internal class DefaultAppRestarter(
private val context: Context,
private val activityClassWrapper: ActivityClassWrapper,
) : AppRestarter {
override fun restart() {
if (context !is Activity) return
context.finish()
context.startActivity(
Intent(context, activityClassWrapper.clazz).apply { flags = Intent.FLAG_ACTIVITY_CLEAR_TOP },
)
Runtime.getRuntime().exit(0)
}
}

View file

@ -0,0 +1,26 @@
package com.tangem.feature.tester.di
import android.content.Context
import com.tangem.feature.tester.ActivityClassWrapper
import com.tangem.feature.tester.apprestarter.DefaultAppRestarter
import com.tangem.features.tester.api.AppRestarter
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
@Module
@InstallIn(ActivityComponent::class)
internal object RestarterModule {
@Provides
@ActivityScoped
fun provideAppRestarter(
@ActivityContext context: Context,
activityClassWrapper: ActivityClassWrapper,
): AppRestarter {
return DefaultAppRestarter(context, activityClassWrapper)
}
}

View file

@ -18,6 +18,7 @@ import com.tangem.feature.tester.presentation.menu.state.TesterMenuContentState
import com.tangem.feature.tester.presentation.menu.ui.TesterMenuScreen
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
import com.tangem.feature.tester.presentation.navigation.TesterScreen
import com.tangem.features.tester.api.AppRestarter
import com.tangem.features.tester.api.TesterRouter
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
@ -33,6 +34,9 @@ internal class TesterActivity : ComposeActivity() {
@Inject
lateinit var testerRouter: TesterRouter
@Inject
lateinit var appRestarter: AppRestarter
private val innerTesterRouter: InnerTesterRouter
get() = requireNotNull(testerRouter as? InnerTesterRouter) {
"TesterRouter must be InnerTesterRouter for tester feature"
@ -66,7 +70,7 @@ internal class TesterActivity : ComposeActivity() {
composable(route = TesterScreen.FEATURE_TOGGLES.name) {
val viewModel = hiltViewModel<FeatureTogglesViewModel>().apply {
setupNavigation(innerTesterRouter)
setupInteractions(innerTesterRouter, appRestarter)
}
FeatureTogglesScreen(state = viewModel.uiState)

View file

@ -3,15 +3,16 @@ package com.tangem.feature.tester.presentation.actions
import com.tangem.domain.apptheme.model.AppThemeMode
internal data class TesterActionsContentState(
val onBackClick: () -> Unit,
val hideAllCurrenciesConfig: HideAllCurrenciesConfig,
val toggleAppThemeConfig: ToggleAppThemeConfig,
val onBackClick: () -> Unit,
val onApplyChangesClick: () -> Unit,
)
internal sealed class HideAllCurrenciesConfig {
data class Clickable(val onClick: () -> Unit) : HideAllCurrenciesConfig()
object Progress : HideAllCurrenciesConfig()
data object Progress : HideAllCurrenciesConfig()
}
internal data class ToggleAppThemeConfig(

View file

@ -78,9 +78,10 @@ private fun TesterActionsScreenSample(modifier: Modifier = Modifier) {
) {
TesterActionsScreen(
state = TesterActionsContentState(
onBackClick = {},
hideAllCurrenciesConfig = HideAllCurrenciesConfig.Clickable {},
toggleAppThemeConfig = ToggleAppThemeConfig(AppThemeMode.DEFAULT) {},
onBackClick = {},
onApplyChangesClick = {},
),
)
}

View file

@ -31,9 +31,10 @@ internal class TesterActionsViewModel @Inject constructor(
private val initialState: TesterActionsContentState
get() = TesterActionsContentState(
onBackClick = { /* no-op */ },
hideAllCurrenciesConfig = HideAllCurrenciesConfig.Clickable(this::hideAllCurrencies),
toggleAppThemeConfig = ToggleAppThemeConfig(AppThemeMode.DEFAULT, this::toggleAppTheme),
onBackClick = { /* no-op */ },
onApplyChangesClick = { /* no-op */ },
)
init {

View file

@ -8,9 +8,11 @@ import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatur
* @property featureToggles feature toggles list
* @property onBackClick the lambda to be invoked when back button is pressed
* @property onToggleValueChange the lambda to be invoked when switch button is pressed
* @property onApplyChangesClick the lambda to be invoked when apply changes button is pressed
*/
internal data class FeatureTogglesContentState(
val featureToggles: List<TesterFeatureToggle>,
val onBackClick: () -> Unit,
val onToggleValueChange: (String, Boolean) -> Unit,
val onBackClick: () -> Unit,
val onApplyChangesClick: () -> Unit,
)

View file

@ -19,6 +19,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.PrimaryButton
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
@ -51,6 +52,14 @@ internal fun FeatureTogglesScreen(state: FeatureTogglesContentState) {
onCheckedChange = { isChange -> state.onToggleValueChange(featureToggle.name, isChange) },
)
}
item {
PrimaryButton(
text = stringResource(id = R.string.apply_changes),
onClick = state.onApplyChangesClick,
modifier = Modifier.fillMaxWidth()
.padding(TangemTheme.dimens.spacing16),
)
}
}
}
@ -95,6 +104,7 @@ private fun PreviewFeatureTogglesScreen() {
),
onToggleValueChange = { _, _ -> },
onBackClick = {},
onApplyChangesClick = {},
),
)
}

View file

@ -10,6 +10,7 @@ import com.tangem.core.featuretoggle.manager.MutableFeatureTogglesManager
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
import com.tangem.features.tester.api.AppRestarter
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
@ -38,16 +39,20 @@ internal class FeatureTogglesViewModel @Inject constructor(
"Feature toggle manager must be mutable (debug build type)"
}
/** Setup navigation state property by router [router] */
fun setupNavigation(router: InnerTesterRouter) {
uiState = uiState.copy(onBackClick = router::back)
/** Setup navigation state property by router [router] and provides app restart method by [appRestarter] */
fun setupInteractions(router: InnerTesterRouter, appRestarter: AppRestarter) {
uiState = uiState.copy(
onBackClick = router::back,
onApplyChangesClick = appRestarter::restart,
)
}
private fun initState(): FeatureTogglesContentState {
return FeatureTogglesContentState(
featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(),
onBackClick = {},
onToggleValueChange = ::onToggleValueChange,
onBackClick = {},
onApplyChangesClick = {},
)
}

View file

@ -2,6 +2,7 @@
<resources>
<string name="tester_menu" translatable="false">Tester menu</string>
<string name="feature_toggles" translatable="false">Feature toggles</string>
<string name="apply_changes" translatable="false">Apply changes</string>
<string name="stand_toggles" translatable="false">Stand toggles</string>
<string name="tester_actions" translatable="false">Tester actions</string>
<string name="hide_all_currencies" translatable="false">Hide all currencies</string>