Updated on 2026-08-14
This commit is contained in:
parent
a98ecb4182
commit
6417281c76
11 changed files with 165 additions and 116 deletions
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.tangem.feature.tester.presentation.common.components.appbar
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
|
||||||
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
|
import com.tangem.feature.tester.impl.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun TopBarWithRefresh(state: TopBarWithRefreshUM) {
|
||||||
|
AppBarWithBackButtonAndIcon(
|
||||||
|
onBackClick = state.onBackClick,
|
||||||
|
text = stringResourceSafe(state.titleResId),
|
||||||
|
iconRes = R.drawable.ic_refresh_24.takeIf { state.refreshButton.isVisible },
|
||||||
|
onIconClick = state.refreshButton.onRefreshClick,
|
||||||
|
backgroundColor = TangemTheme.colors.background.primary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.tangem.feature.tester.presentation.common.components.appbar
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
|
internal data class TopBarWithRefreshUM(
|
||||||
|
@StringRes val titleResId: Int,
|
||||||
|
val onBackClick: () -> Unit,
|
||||||
|
val refreshButton: RefreshButton,
|
||||||
|
) {
|
||||||
|
|
||||||
|
data class RefreshButton(val isVisible: Boolean, val onRefreshClick: () -> Unit)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.tangem.feature.tester.presentation.common.components.notification
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.tangem.core.ui.components.notifications.Notification
|
||||||
|
import com.tangem.core.ui.components.notifications.NotificationConfig
|
||||||
|
import com.tangem.core.ui.extensions.TextReference
|
||||||
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
|
import com.tangem.feature.tester.impl.R
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun CustomSetupNotification(subtitle: TextReference, modifier: Modifier = Modifier) {
|
||||||
|
Notification(
|
||||||
|
config = NotificationConfig(
|
||||||
|
subtitle = subtitle,
|
||||||
|
iconResId = R.drawable.ic_alert_triangle_20,
|
||||||
|
title = resourceReference(id = R.string.custom_setup_warning_title),
|
||||||
|
),
|
||||||
|
modifier = modifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
@ -114,7 +114,7 @@ private fun TogglesNotification(appVersion: String, isVisible: Boolean, modifier
|
||||||
wrappedList(appVersion),
|
wrappedList(appVersion),
|
||||||
),
|
),
|
||||||
iconResId = R.drawable.ic_alert_triangle_20,
|
iconResId = R.drawable.ic_alert_triangle_20,
|
||||||
title = resourceReference(id = R.string.feature_toggles_custom_setup_warning_title),
|
title = resourceReference(id = R.string.custom_setup_warning_title),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,22 @@
|
||||||
package com.tangem.feature.tester.presentation.featuretoggles.state
|
package com.tangem.feature.tester.presentation.featuretoggles.state
|
||||||
|
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefreshUM
|
||||||
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Content state of feature toggles screen
|
* Content state of feature toggles screen
|
||||||
*
|
*
|
||||||
* @property topBarState top bar state
|
* @property topBar top bar state
|
||||||
* @property appVersion app version
|
* @property appVersion app version
|
||||||
* @property featureToggles feature toggles list
|
* @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 onToggleValueChange the lambda to be invoked when switch button is pressed
|
||||||
* @property onRestartAppClick the lambda to be invoked when restart app button is pressed
|
* @property onRestartAppClick the lambda to be invoked when restart app button is pressed
|
||||||
*/
|
*/
|
||||||
internal data class FeatureTogglesContentState(
|
internal data class FeatureTogglesContentState(
|
||||||
val topBarState: TopBarState,
|
val topBar: TopBarWithRefreshUM,
|
||||||
val appVersion: String,
|
val appVersion: String,
|
||||||
val featureToggles: ImmutableList<TesterFeatureToggle>,
|
val featureToggles: ImmutableList<TesterFeatureToggle>,
|
||||||
val onBackClick: () -> Unit,
|
|
||||||
val onToggleValueChange: (String, Boolean) -> Unit,
|
val onToggleValueChange: (String, Boolean) -> Unit,
|
||||||
val onRestartAppClick: () -> Unit,
|
val onRestartAppClick: () -> Unit,
|
||||||
) {
|
)
|
||||||
|
|
||||||
/** Top bar state */
|
|
||||||
sealed interface TopBarState {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Config setup
|
|
||||||
*
|
|
||||||
* @property onBackClick the lambda to be invoked when back button is pressed
|
|
||||||
*/
|
|
||||||
data object ConfigSetup : TopBarState
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Custom setup
|
|
||||||
*
|
|
||||||
* @property onRecoverClick the lambda to be invoked when recover button is pressed
|
|
||||||
*/
|
|
||||||
data class CustomSetup(val onRecoverClick: () -> Unit) : TopBarState
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -15,15 +15,15 @@ import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.tangem.core.ui.components.PrimaryButton
|
import com.tangem.core.ui.components.PrimaryButton
|
||||||
import com.tangem.core.ui.components.TangemSwitch
|
import com.tangem.core.ui.components.TangemSwitch
|
||||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButtonAndIcon
|
|
||||||
import com.tangem.core.ui.components.notifications.Notification
|
|
||||||
import com.tangem.core.ui.components.notifications.NotificationConfig
|
|
||||||
import com.tangem.core.ui.extensions.resourceReference
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||||
import com.tangem.core.ui.extensions.wrappedList
|
import com.tangem.core.ui.extensions.wrappedList
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
import com.tangem.feature.tester.impl.R
|
import com.tangem.feature.tester.impl.R
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefresh
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefreshUM
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.notification.CustomSetupNotification
|
||||||
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
||||||
import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState
|
import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -41,12 +41,15 @@ internal fun FeatureTogglesScreen(state: FeatureTogglesContentState) {
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.background(TangemTheme.colors.background.secondary),
|
.background(TangemTheme.colors.background.secondary),
|
||||||
) {
|
) {
|
||||||
stickyHeader { TopAppBar(state = state.topBarState, onBackClick = state.onBackClick) }
|
stickyHeader { TopBarWithRefresh(state = state.topBar) }
|
||||||
|
|
||||||
if (state.topBarState is FeatureTogglesContentState.TopBarState.CustomSetup) {
|
if (state.topBar.refreshButton.isVisible) {
|
||||||
item(key = "warning_notification", contentType = "warning_notification") {
|
item(key = "warning_notification", contentType = "warning_notification") {
|
||||||
WarningNotification(
|
CustomSetupNotification(
|
||||||
appVersion = state.appVersion,
|
subtitle = resourceReference(
|
||||||
|
id = R.string.feature_toggles_custom_setup_warning_description,
|
||||||
|
wrappedList(state.appVersion),
|
||||||
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.animateItem()
|
.animateItem()
|
||||||
.padding(horizontal = 16.dp)
|
.padding(horizontal = 16.dp)
|
||||||
|
|
@ -78,39 +81,6 @@ internal fun FeatureTogglesScreen(state: FeatureTogglesContentState) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun TopAppBar(state: FeatureTogglesContentState.TopBarState, onBackClick: () -> Unit) {
|
|
||||||
AppBarWithBackButtonAndIcon(
|
|
||||||
onBackClick = onBackClick,
|
|
||||||
text = stringResourceSafe(id = R.string.feature_toggles),
|
|
||||||
iconRes = if (state is FeatureTogglesContentState.TopBarState.CustomSetup) {
|
|
||||||
R.drawable.ic_refresh_24
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
},
|
|
||||||
onIconClick = if (state is FeatureTogglesContentState.TopBarState.CustomSetup) {
|
|
||||||
state.onRecoverClick
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun WarningNotification(appVersion: String, modifier: Modifier = Modifier) {
|
|
||||||
Notification(
|
|
||||||
config = NotificationConfig(
|
|
||||||
subtitle = resourceReference(
|
|
||||||
id = R.string.feature_toggles_custom_setup_warning_description,
|
|
||||||
wrappedList(appVersion),
|
|
||||||
),
|
|
||||||
iconResId = R.drawable.ic_alert_triangle_20,
|
|
||||||
title = resourceReference(id = R.string.feature_toggles_custom_setup_warning_title),
|
|
||||||
),
|
|
||||||
modifier = modifier,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun FeatureToggleItem(toggle: TesterFeatureToggle, onCheckedChange: (Boolean) -> Unit) {
|
private fun FeatureToggleItem(toggle: TesterFeatureToggle, onCheckedChange: (Boolean) -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
|
|
@ -145,17 +115,19 @@ private fun PreviewFeatureTogglesScreen() {
|
||||||
|
|
||||||
FeatureTogglesScreen(
|
FeatureTogglesScreen(
|
||||||
state = FeatureTogglesContentState(
|
state = FeatureTogglesContentState(
|
||||||
topBarState = if (isCustomSetup) {
|
topBar = TopBarWithRefreshUM(
|
||||||
FeatureTogglesContentState.TopBarState.CustomSetup(onRecoverClick = { isCustomSetup = false })
|
titleResId = R.string.feature_toggles,
|
||||||
} else {
|
onBackClick = {},
|
||||||
FeatureTogglesContentState.TopBarState.ConfigSetup
|
refreshButton = TopBarWithRefreshUM.RefreshButton(
|
||||||
},
|
isVisible = isCustomSetup,
|
||||||
|
onRefreshClick = { isCustomSetup = false },
|
||||||
|
),
|
||||||
|
),
|
||||||
appVersion = "5.15",
|
appVersion = "5.15",
|
||||||
featureToggles = persistentListOf(
|
featureToggles = persistentListOf(
|
||||||
TesterFeatureToggle(name = "FEATURE_TOGGLE_1", isEnabled = true),
|
TesterFeatureToggle(name = "FEATURE_TOGGLE_1", isEnabled = true),
|
||||||
TesterFeatureToggle(name = "FEATURE_TOGGLE_2", isEnabled = false),
|
TesterFeatureToggle(name = "FEATURE_TOGGLE_2", isEnabled = false),
|
||||||
),
|
),
|
||||||
onBackClick = {},
|
|
||||||
onToggleValueChange = { _, _ -> isCustomSetup = true },
|
onToggleValueChange = { _, _ -> isCustomSetup = true },
|
||||||
onRestartAppClick = {},
|
onRestartAppClick = {},
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@ import androidx.lifecycle.viewModelScope
|
||||||
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
import com.tangem.core.configtoggle.feature.FeatureTogglesManager
|
||||||
import com.tangem.core.configtoggle.feature.MutableFeatureTogglesManager
|
import com.tangem.core.configtoggle.feature.MutableFeatureTogglesManager
|
||||||
import com.tangem.core.navigation.finisher.AppFinisher
|
import com.tangem.core.navigation.finisher.AppFinisher
|
||||||
|
import com.tangem.feature.tester.impl.R
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefreshUM
|
||||||
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
import com.tangem.feature.tester.presentation.featuretoggles.models.TesterFeatureToggle
|
||||||
import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState
|
import com.tangem.feature.tester.presentation.featuretoggles.state.FeatureTogglesContentState
|
||||||
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
||||||
|
|
@ -45,22 +47,40 @@ internal class FeatureTogglesViewModel @Inject constructor(
|
||||||
/** Setup navigation state property by router [router] and provides app restart method by [appFinisher] */
|
/** Setup navigation state property by router [router] and provides app restart method by [appFinisher] */
|
||||||
fun setupInteractions(router: InnerTesterRouter, appFinisher: AppFinisher) {
|
fun setupInteractions(router: InnerTesterRouter, appFinisher: AppFinisher) {
|
||||||
uiState = uiState.copy(
|
uiState = uiState.copy(
|
||||||
onBackClick = router::back,
|
topBar = uiState.topBar.copy(onBackClick = router::back),
|
||||||
onRestartAppClick = appFinisher::restart,
|
onRestartAppClick = appFinisher::restart,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initState(): FeatureTogglesContentState {
|
private fun initState(): FeatureTogglesContentState {
|
||||||
return FeatureTogglesContentState(
|
return FeatureTogglesContentState(
|
||||||
topBarState = getConfigSetupState(),
|
topBar = getConfigSetupState(isPrimarySetup = true),
|
||||||
appVersion = appVersionProvider.versionName,
|
appVersion = appVersionProvider.versionName,
|
||||||
featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(),
|
featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(),
|
||||||
onToggleValueChange = ::onToggleValueChange,
|
onToggleValueChange = ::onToggleValueChange,
|
||||||
onBackClick = {},
|
|
||||||
onRestartAppClick = {},
|
onRestartAppClick = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getConfigSetupState(isPrimarySetup: Boolean): TopBarWithRefreshUM {
|
||||||
|
val isMatchLocalConfig = mutableFeatureTogglesManager.isMatchLocalConfig()
|
||||||
|
|
||||||
|
return if (isPrimarySetup) {
|
||||||
|
TopBarWithRefreshUM(
|
||||||
|
titleResId = R.string.feature_toggles,
|
||||||
|
onBackClick = {},
|
||||||
|
refreshButton = TopBarWithRefreshUM.RefreshButton(
|
||||||
|
isVisible = false,
|
||||||
|
onRefreshClick = ::onRefreshClick,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
uiState.topBar.copy(
|
||||||
|
refreshButton = uiState.topBar.refreshButton.copy(isVisible = isMatchLocalConfig),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onToggleValueChange(name: String, isEnabled: Boolean) {
|
private fun onToggleValueChange(name: String, isEnabled: Boolean) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
mutableFeatureTogglesManager.changeToggle(name = name, isEnabled = isEnabled)
|
mutableFeatureTogglesManager.changeToggle(name = name, isEnabled = isEnabled)
|
||||||
|
|
@ -70,25 +90,17 @@ internal class FeatureTogglesViewModel @Inject constructor(
|
||||||
// delay for smoothly update animations
|
// delay for smoothly update animations
|
||||||
delay(timeMillis = 300)
|
delay(timeMillis = 300)
|
||||||
|
|
||||||
uiState = uiState.copy(topBarState = getConfigSetupState())
|
uiState = uiState.copy(topBar = getConfigSetupState(isPrimarySetup = false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getConfigSetupState(): FeatureTogglesContentState.TopBarState {
|
private fun onRefreshClick() {
|
||||||
return if (mutableFeatureTogglesManager.isMatchLocalConfig()) {
|
viewModelScope.launch {
|
||||||
FeatureTogglesContentState.TopBarState.ConfigSetup
|
mutableFeatureTogglesManager.recoverLocalConfig()
|
||||||
} else {
|
|
||||||
FeatureTogglesContentState.TopBarState.CustomSetup(
|
|
||||||
onRecoverClick = {
|
|
||||||
viewModelScope.launch {
|
|
||||||
mutableFeatureTogglesManager.recoverLocalConfig()
|
|
||||||
|
|
||||||
uiState = uiState.copy(
|
uiState = uiState.copy(
|
||||||
topBarState = getConfigSetupState(),
|
topBar = getConfigSetupState(isPrimarySetup = false),
|
||||||
featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(),
|
featureToggles = mutableFeatureTogglesManager.getTesterFeatureToggles(),
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ package com.tangem.feature.tester.presentation.providers.entity
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import com.tangem.blockchain.common.network.providers.ProviderType
|
import com.tangem.blockchain.common.network.providers.ProviderType
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefreshUM
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
internal data class BlockchainProvidersUM(
|
internal data class BlockchainProvidersUM(
|
||||||
val onBackClick: () -> Unit,
|
val topBar: TopBarWithRefreshUM,
|
||||||
val blockchainProviders: ImmutableList<ProvidersUM>,
|
val blockchainProviders: ImmutableList<ProvidersUM>,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.util.fastForEachIndexed
|
import androidx.compose.ui.util.fastForEachIndexed
|
||||||
import com.tangem.core.ui.components.SpacerH8
|
|
||||||
import com.tangem.core.ui.components.appbar.AppBarWithBackButton
|
|
||||||
import com.tangem.core.ui.components.rows.RowText
|
import com.tangem.core.ui.components.rows.RowText
|
||||||
import com.tangem.core.ui.extensions.getActiveIconRes
|
import com.tangem.core.ui.extensions.getActiveIconRes
|
||||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.feature.tester.impl.R
|
import com.tangem.feature.tester.impl.R
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefresh
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.notification.CustomSetupNotification
|
||||||
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM
|
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM
|
||||||
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProviderUM
|
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProviderUM
|
||||||
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProvidersUM
|
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProvidersUM
|
||||||
|
|
@ -50,12 +50,20 @@ internal fun BlockchainProvidersScreen(state: BlockchainProvidersUM) {
|
||||||
.background(TangemTheme.colors.background.primary),
|
.background(TangemTheme.colors.background.primary),
|
||||||
) {
|
) {
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
stickyHeader {
|
stickyHeader { TopBarWithRefresh(state = state.topBar) }
|
||||||
AppBarWithBackButton(
|
|
||||||
onBackClick = state.onBackClick,
|
if (state.topBar.refreshButton.isVisible) {
|
||||||
text = stringResourceSafe(id = R.string.blockchain_providers),
|
item(key = "notification", contentType = "notification") {
|
||||||
containerColor = TangemTheme.colors.background.primary,
|
CustomSetupNotification(
|
||||||
)
|
subtitle = resourceReference(
|
||||||
|
id = R.string.blockchain_providers_custom_setup_warning_description,
|
||||||
|
),
|
||||||
|
modifier = Modifier
|
||||||
|
.animateItem()
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
|
.padding(bottom = 8.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
items(
|
items(
|
||||||
|
|
@ -74,8 +82,8 @@ private fun BlockchainProvidersItem(state: ProvidersUM) {
|
||||||
|
|
||||||
ExpandableBlockchainRow(
|
ExpandableBlockchainRow(
|
||||||
state = state,
|
state = state,
|
||||||
modifier = Modifier.clickable { isExpanded = !isExpanded },
|
|
||||||
content = { Providers(state = state, isExpanded = isExpanded) },
|
content = { Providers(state = state, isExpanded = isExpanded) },
|
||||||
|
onExpandStateChange = { isExpanded = !isExpanded },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,25 +91,23 @@ private fun BlockchainProvidersItem(state: ProvidersUM) {
|
||||||
private fun ExpandableBlockchainRow(
|
private fun ExpandableBlockchainRow(
|
||||||
state: ProvidersUM,
|
state: ProvidersUM,
|
||||||
content: @Composable () -> Unit,
|
content: @Composable () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
onExpandStateChange: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column {
|
||||||
modifier = modifier
|
BlockchainRow(state = state, onExpandStateChange = onExpandStateChange)
|
||||||
.fillMaxWidth()
|
|
||||||
.padding(horizontal = 16.dp),
|
|
||||||
) {
|
|
||||||
BlockchainRow(state)
|
|
||||||
|
|
||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BlockchainRow(state: ProvidersUM) {
|
private fun BlockchainRow(state: ProvidersUM, onExpandStateChange: () -> Unit) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
.clickable { onExpandStateChange() }
|
||||||
|
.padding(horizontal = 16.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(vertical = 16.dp),
|
.padding(vertical = 12.dp),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
|
|
@ -145,11 +151,15 @@ private fun BlockchainRow(state: ProvidersUM) {
|
||||||
private fun Providers(state: ProvidersUM, isExpanded: Boolean) {
|
private fun Providers(state: ProvidersUM, isExpanded: Boolean) {
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = isExpanded,
|
visible = isExpanded,
|
||||||
|
modifier = Modifier.padding(horizontal = 16.dp),
|
||||||
enter = fadeIn() + expandVertically(),
|
enter = fadeIn() + expandVertically(),
|
||||||
exit = fadeOut() + shrinkVertically(),
|
exit = fadeOut() + shrinkVertically(),
|
||||||
label = "providers_visibility",
|
label = "providers_visibility",
|
||||||
) {
|
) {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
Column(
|
||||||
|
modifier = Modifier.padding(vertical = 8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
) {
|
||||||
state.providers.fastForEachIndexed { index, provider ->
|
state.providers.fastForEachIndexed { index, provider ->
|
||||||
key("${provider.name}_$index") {
|
key("${provider.name}_$index") {
|
||||||
ProviderItem(
|
ProviderItem(
|
||||||
|
|
@ -157,8 +167,6 @@ private fun Providers(state: ProvidersUM, isExpanded: Boolean) {
|
||||||
state = provider,
|
state = provider,
|
||||||
onDrop = { prev, new -> state.onDrop(state.blockchainId, prev, new) },
|
onDrop = { prev, new -> state.onDrop(state.blockchainId, prev, new) },
|
||||||
)
|
)
|
||||||
|
|
||||||
if (index == state.providers.lastIndex) SpacerH8()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import com.tangem.blockchain.common.Blockchain
|
||||||
import com.tangem.blockchain.common.network.providers.ProviderType
|
import com.tangem.blockchain.common.network.providers.ProviderType
|
||||||
import com.tangem.blockchainsdk.providers.BlockchainProvidersTypesManager
|
import com.tangem.blockchainsdk.providers.BlockchainProvidersTypesManager
|
||||||
import com.tangem.blockchainsdk.providers.MutableBlockchainProvidersTypesManager
|
import com.tangem.blockchainsdk.providers.MutableBlockchainProvidersTypesManager
|
||||||
|
import com.tangem.feature.tester.impl.R
|
||||||
|
import com.tangem.feature.tester.presentation.common.components.appbar.TopBarWithRefreshUM
|
||||||
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
import com.tangem.feature.tester.presentation.navigation.InnerTesterRouter
|
||||||
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM
|
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM
|
||||||
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProviderUM
|
import com.tangem.feature.tester.presentation.providers.entity.BlockchainProvidersUM.ProviderUM
|
||||||
|
|
@ -26,7 +28,14 @@ internal class BlockchainProvidersViewModel @Inject constructor(
|
||||||
val state: StateFlow<BlockchainProvidersUM> get() = _state.asStateFlow()
|
val state: StateFlow<BlockchainProvidersUM> get() = _state.asStateFlow()
|
||||||
|
|
||||||
private val _state = MutableStateFlow(
|
private val _state = MutableStateFlow(
|
||||||
value = BlockchainProvidersUM(onBackClick = {}, blockchainProviders = persistentListOf()),
|
value = BlockchainProvidersUM(
|
||||||
|
topBar = TopBarWithRefreshUM(
|
||||||
|
titleResId = R.string.blockchain_providers,
|
||||||
|
onBackClick = {},
|
||||||
|
refreshButton = TopBarWithRefreshUM.RefreshButton(isVisible = false, onRefreshClick = ::onRefreshClick),
|
||||||
|
),
|
||||||
|
blockchainProviders = persistentListOf(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
private val manager = blockchainProvidersTypesManager as MutableBlockchainProvidersTypesManager
|
private val manager = blockchainProvidersTypesManager as MutableBlockchainProvidersTypesManager
|
||||||
|
|
@ -37,15 +46,24 @@ internal class BlockchainProvidersViewModel @Inject constructor(
|
||||||
|
|
||||||
fun setupNavigation(router: InnerTesterRouter) {
|
fun setupNavigation(router: InnerTesterRouter) {
|
||||||
_state.update { state ->
|
_state.update { state ->
|
||||||
state.copy(onBackClick = router::back)
|
state.copy(
|
||||||
|
topBar = state.topBar.copy(onBackClick = router::back),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun subscribeOnBlockchainProviderTypesUpdates() {
|
private fun subscribeOnBlockchainProviderTypesUpdates() {
|
||||||
manager.get()
|
manager.get()
|
||||||
.onEach { blockchainProviderTypes ->
|
.onEach { blockchainProviderTypes ->
|
||||||
|
val isChanged = !manager.isMatchWithMerged()
|
||||||
|
|
||||||
_state.update { state ->
|
_state.update { state ->
|
||||||
state.copy(blockchainProviders = blockchainProviderTypes.toProvidersUM())
|
state.copy(
|
||||||
|
topBar = state.topBar.copy(
|
||||||
|
refreshButton = state.topBar.refreshButton.copy(isVisible = isChanged),
|
||||||
|
),
|
||||||
|
blockchainProviders = blockchainProviderTypes.toProvidersUM(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
|
|
@ -67,6 +85,12 @@ internal class BlockchainProvidersViewModel @Inject constructor(
|
||||||
.toImmutableList()
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onRefreshClick() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
manager.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun onDrop(id: String, prev: Int, current: Int) {
|
private fun onDrop(id: String, prev: Int, current: Int) {
|
||||||
val providers = _state.value
|
val providers = _state.value
|
||||||
.blockchainProviders.first { it.blockchainId == id }
|
.blockchainProviders.first { it.blockchainId == id }
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="tester_menu" translatable="false">Tester menu</string>
|
<string name="tester_menu" translatable="false">Tester menu</string>
|
||||||
<string name="feature_toggles" translatable="false">Feature toggles</string>
|
<string name="feature_toggles" translatable="false">Feature toggles</string>
|
||||||
<string name="feature_toggles_custom_setup_warning_title" translatable="false">Custom setup</string>
|
<string name="custom_setup_warning_title" translatable="false">Custom setup</string>
|
||||||
<string name="feature_toggles_custom_setup_warning_description" translatable="false">Toggles differs from v%s config</string>
|
<string name="feature_toggles_custom_setup_warning_description" translatable="false">Toggles differs from v%s config</string>
|
||||||
|
<string name="blockchain_providers_custom_setup_warning_description" translatable="false">Providers differs from release config</string>
|
||||||
<string name="restart_app" translatable="false">Restart app</string>
|
<string name="restart_app" translatable="false">Restart app</string>
|
||||||
<string name="environment_toggles" translatable="false">Environment toggles</string>
|
<string name="environment_toggles" translatable="false">Environment toggles</string>
|
||||||
<string name="tester_actions" translatable="false">Tester actions</string>
|
<string name="tester_actions" translatable="false">Tester actions</string>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue