Updated on 2026-08-14
This commit is contained in:
parent
2c259cb036
commit
4b5adcd08a
8 changed files with 539 additions and 258 deletions
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.details.redux
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.common.CardTypesResolver
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
|
|
@ -27,6 +28,14 @@ sealed class DetailsAction : Action {
|
|||
|
||||
data class PrepareCardSettingsData(val card: CardDTO, val cardTypesResolver: CardTypesResolver) : DetailsAction()
|
||||
object ResetCardSettingsData : DetailsAction()
|
||||
object ScanAndSaveUserWallet : DetailsAction() {
|
||||
|
||||
object Success : DetailsAction()
|
||||
|
||||
data class Error(val error: TextReference?) : DetailsAction()
|
||||
}
|
||||
|
||||
object DismissError : DetailsAction()
|
||||
|
||||
sealed class AccessCodeRecovery : DetailsAction() {
|
||||
object Open : AccessCodeRecovery()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.features.details.redux
|
||||
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.core.TangemError
|
||||
import com.tangem.common.core.TangemSdkError
|
||||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
|
|
@ -9,6 +10,9 @@ import com.tangem.common.flatMap
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
|
|
@ -19,6 +23,7 @@ import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
|||
import com.tangem.domain.wallets.legacy.isLockedSync
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
@ -73,37 +78,8 @@ class DetailsMiddleware {
|
|||
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins))
|
||||
}
|
||||
is DetailsAction.AccessCodeRecovery -> accessCodeRecoveryMiddleware.handle(state, action)
|
||||
DetailsAction.ScanCard -> {
|
||||
scope.launch {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor)
|
||||
.scan(allowsRequestAccessCodeFromRepository = true)
|
||||
.doOnSuccess { scanResponse ->
|
||||
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
|
||||
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
||||
val currentUserWalletId = state.scanResponse
|
||||
?.let { UserWalletIdBuilder.scanResponse(it).build() }
|
||||
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse)
|
||||
.build()
|
||||
val isSameWallet = currentUserWalletId == scannedUserWalletId
|
||||
|
||||
if (isSameWallet) {
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.PrepareCardSettingsData(
|
||||
scanResponse.card,
|
||||
scanResponse.cardTypesResolver,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
store.dispatchDialogShow(
|
||||
AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.error_wrong_wallet_tapped,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
is DetailsAction.ScanCard -> scanCard(state)
|
||||
is DetailsAction.ScanAndSaveUserWallet -> scanAndSaveUserWallet()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -460,4 +436,97 @@ class DetailsMiddleware {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanCard(state: DetailsState) = scope.launch {
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor)
|
||||
.scan(allowsRequestAccessCodeFromRepository = true)
|
||||
.doOnSuccess { scanResponse ->
|
||||
// if we use biometric, scanResponse in GlobalState is null, and crashes NPE on twin cards
|
||||
store.dispatch(GlobalAction.SaveScanResponse(scanResponse))
|
||||
val currentUserWalletId = state.scanResponse
|
||||
?.let { UserWalletIdBuilder.scanResponse(it).build() }
|
||||
val scannedUserWalletId = UserWalletIdBuilder.scanResponse(scanResponse)
|
||||
.build()
|
||||
val isSameWallet = currentUserWalletId == scannedUserWalletId
|
||||
|
||||
if (isSameWallet) {
|
||||
store.dispatchOnMain(
|
||||
DetailsAction.PrepareCardSettingsData(
|
||||
scanResponse.card,
|
||||
scanResponse.cardTypesResolver,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
store.dispatchDialogShow(
|
||||
AppDialog.SimpleOkDialogRes(
|
||||
headerId = R.string.common_warning,
|
||||
messageId = R.string.error_wrong_wallet_tapped,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun scanAndSaveUserWallet() = scope.launch(Dispatchers.IO) {
|
||||
val cardSdkConfigRepository = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository)
|
||||
|
||||
val prevUseBiometricsForAccessCode = cardSdkConfigRepository.isBiometricsRequestPolicy()
|
||||
|
||||
// Update access code policy for access code saving when a card was scanned
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(
|
||||
isBiometricsRequestPolicy = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
store.state.daggerGraphState.get(DaggerGraphState::scanCardProcessor).scan(
|
||||
analyticsEvent = Basic.CardWasScanned(AnalyticsParam.ScannedFrom.MyWallets),
|
||||
onWalletNotCreated = {
|
||||
// No need to rollback policy, continue with the policy set before the card scan
|
||||
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
|
||||
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
},
|
||||
disclaimerWillShow = {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo())
|
||||
},
|
||||
onSuccess = { scanResponse ->
|
||||
saveUserWalletAndPopBackToWalletScreen(scanResponse)
|
||||
.doOnFailure { error ->
|
||||
// Rollback policy if card saving was failed
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
Timber.e(error, "Unable to save user wallet")
|
||||
|
||||
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Error(error.toTextReference()))
|
||||
}
|
||||
},
|
||||
onFailure = { error ->
|
||||
// Rollback policy if card scanning was failed
|
||||
cardSdkConfigRepository.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
Timber.e(error, "Unable to scan card")
|
||||
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Error(error.toTextReference()))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun saveUserWalletAndPopBackToWalletScreen(scanResponse: ScanResponse): CompletionResult<Unit> {
|
||||
val userWallet = UserWalletBuilder(scanResponse).build()
|
||||
?: return CompletionResult.Failure(TangemSdkError.WalletIsNotCreated())
|
||||
|
||||
return userWalletsListManager.save(userWallet)
|
||||
.doOnSuccess {
|
||||
store.dispatchWithMain(DetailsAction.ScanAndSaveUserWallet.Success)
|
||||
store.dispatchWithMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
|
||||
val walletFeatureToggles = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletFeatureToggles)
|
||||
|
||||
if (!walletFeatureToggles.isRedesignedScreenEnabled) {
|
||||
store.onUserWalletSelected(userWallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun TangemError.toTextReference(): TextReference? {
|
||||
if (silent) return null
|
||||
|
||||
return messageResId?.let(::resourceReference) ?: stringReference(customMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ object DetailsReducer {
|
|||
fun reduce(action: Action, state: AppState): DetailsState = internalReduce(action, state)
|
||||
}
|
||||
|
||||
@Suppress("CyclomaticComplexMethod")
|
||||
private fun internalReduce(action: Action, state: AppState): DetailsState {
|
||||
if (action !is DetailsAction) return state.detailsState
|
||||
val detailsState = state.detailsState
|
||||
|
|
@ -45,6 +46,19 @@ private fun internalReduce(action: Action, state: AppState): DetailsState {
|
|||
),
|
||||
)
|
||||
is DetailsAction.AccessCodeRecovery -> handleAccessCodeRecoveryAction(action, detailsState)
|
||||
is DetailsAction.ScanAndSaveUserWallet -> detailsState.copy(
|
||||
isScanningInProgress = true,
|
||||
)
|
||||
is DetailsAction.ScanAndSaveUserWallet.Error -> detailsState.copy(
|
||||
isScanningInProgress = false,
|
||||
error = action.error,
|
||||
)
|
||||
is DetailsAction.ScanAndSaveUserWallet.Success -> detailsState.copy(
|
||||
isScanningInProgress = false,
|
||||
)
|
||||
is DetailsAction.DismissError -> detailsState.copy(
|
||||
error = null,
|
||||
)
|
||||
else -> detailsState
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.features.details.redux
|
||||
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
|
@ -13,6 +14,8 @@ data class DetailsState(
|
|||
val cardSettingsState: CardSettingsState? = null,
|
||||
val privacyPolicyUrl: String? = null,
|
||||
val createBackupAllowed: Boolean = false,
|
||||
val isScanningInProgress: Boolean = false,
|
||||
val error: TextReference? = null,
|
||||
val appSettingsState: AppSettingsState = AppSettingsState(),
|
||||
) : StateType
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.*
|
|||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
|
|
@ -22,9 +23,11 @@ internal fun SettingsScreensScaffold(
|
|||
onBackClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
fab: @Composable (() -> Unit)? = null,
|
||||
@StringRes titleRes: Int? = null,
|
||||
snackbarHostState: SnackbarHostState = remember { SnackbarHostState() },
|
||||
fab: @Composable () -> Unit = {},
|
||||
) {
|
||||
val state = rememberScaffoldState(snackbarHostState = snackbarHostState)
|
||||
val backgroundColor = TangemTheme.colors.background.secondary
|
||||
|
||||
BackHandler(onBack = onBackClick)
|
||||
|
|
@ -33,6 +36,7 @@ internal fun SettingsScreensScaffold(
|
|||
}
|
||||
|
||||
Scaffold(
|
||||
scaffoldState = state,
|
||||
topBar = {
|
||||
EmptyTopBarWithNavigation(
|
||||
onBackClick = onBackClick,
|
||||
|
|
@ -41,27 +45,28 @@ internal fun SettingsScreensScaffold(
|
|||
},
|
||||
modifier = modifier.systemBarsPadding(),
|
||||
backgroundColor = backgroundColor,
|
||||
floatingActionButton = { fab?.invoke() },
|
||||
) { paddings ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(paddings)
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
if (titleRes != null) {
|
||||
Text(
|
||||
text = stringResource(id = titleRes),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing20)
|
||||
.padding(bottom = TangemTheme.dimens.spacing36),
|
||||
style = TangemTheme.typography.h1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
}
|
||||
floatingActionButton = fab,
|
||||
content = { paddings ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(paddings)
|
||||
.fillMaxSize(),
|
||||
) {
|
||||
if (titleRes != null) {
|
||||
Text(
|
||||
text = stringResource(id = titleRes),
|
||||
modifier = Modifier
|
||||
.padding(horizontal = TangemTheme.dimens.spacing20)
|
||||
.padding(bottom = TangemTheme.dimens.spacing36),
|
||||
style = TangemTheme.typography.h1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
}
|
||||
|
||||
content()
|
||||
}
|
||||
}
|
||||
content()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
|
|||
|
|
@ -6,36 +6,44 @@ import androidx.compose.foundation.lazy.LazyRow
|
|||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.SideEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import com.tangem.core.ui.components.SpacerH
|
||||
import com.tangem.core.ui.components.SpacerHMax
|
||||
import com.tangem.core.ui.event.EventEffect
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resolveReference
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.features.details.ui.common.ScreenTitle
|
||||
import com.tangem.tap.features.details.ui.common.SettingsScreensScaffold
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
|
||||
@Composable
|
||||
internal fun DetailsScreen(state: DetailsScreenState, onBackClick: () -> Unit, modifier: Modifier = Modifier) {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
|
||||
SettingsScreensScaffold(
|
||||
modifier = modifier,
|
||||
snackbarHostState = snackbarHostState,
|
||||
content = { Content(state = state) },
|
||||
onBackClick = onBackClick,
|
||||
)
|
||||
|
||||
ShowSnackbarIfNeeded(
|
||||
snackbarHostState = snackbarHostState,
|
||||
messageEvent = state.showSnackbar,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -50,102 +58,124 @@ private fun Content(state: DetailsScreenState, modifier: Modifier = Modifier) {
|
|||
SpacerH(height = TangemTheme.dimens.spacing36)
|
||||
SettingsItems(
|
||||
items = state.elements,
|
||||
onItemsClick = state.onItemsClick,
|
||||
)
|
||||
SpacerHMax()
|
||||
TangemSocialAccounts(
|
||||
links = state.tangemLinks,
|
||||
onSocialNetworkClick = state.onSocialNetworkClick,
|
||||
)
|
||||
SpacerH(height = TangemTheme.dimens.spacing16)
|
||||
SpacerH(height = TangemTheme.dimens.spacing12)
|
||||
TangemAppVersion(
|
||||
appNameRes = state.appNameRes,
|
||||
version = state.tangemVersion,
|
||||
)
|
||||
SpacerH(height = TangemTheme.dimens.spacing24)
|
||||
SpacerH(height = TangemTheme.dimens.spacing16)
|
||||
}
|
||||
ShowSnackbarIfNeeded(state.showErrorSnackbar.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SettingsItems(items: List<SettingsElement>, onItemsClick: (SettingsElement) -> Unit) {
|
||||
private fun SettingsItems(items: List<SettingsItem>) {
|
||||
items.forEach { item ->
|
||||
val onItemClick = remember(item) {
|
||||
{ onItemsClick(item) }
|
||||
}
|
||||
|
||||
if (item == SettingsElement.WalletConnect) {
|
||||
WalletConnectDetailsItem(onItemClick)
|
||||
if (item.isLarge) {
|
||||
LargeDetailsItem(item)
|
||||
} else {
|
||||
DetailsItem(
|
||||
item = item,
|
||||
onItemClick = onItemClick,
|
||||
)
|
||||
DetailsItem(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WalletConnectDetailsItem(onItemClick: () -> Unit) {
|
||||
private fun LargeDetailsItem(item: SettingsItem) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.defaultMinSize(minHeight = 84.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onItemClick),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
.clickable(onClick = item.onClick)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing20)
|
||||
.heightIn(min = TangemTheme.dimens.size84)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing20),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.ic_walletconnect),
|
||||
contentDescription = stringResource(id = R.string.wallet_connect_title),
|
||||
modifier = Modifier.padding(start = 20.dp, end = 20.dp),
|
||||
tint = TangemColorPalette.Azure,
|
||||
)
|
||||
if (item.showProgress) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
color = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = item.iconResId),
|
||||
contentDescription = item.title.resolveReference(),
|
||||
tint = TangemColorPalette.Azure,
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier.defaultMinSize(minHeight = 56.dp),
|
||||
modifier = Modifier.heightIn(min = TangemTheme.dimens.size56),
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
space = TangemTheme.dimens.spacing4,
|
||||
alignment = Alignment.CenterVertically,
|
||||
),
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = R.string.wallet_connect_title),
|
||||
modifier = Modifier.padding(end = 20.dp, bottom = 4.dp),
|
||||
text = item.title.resolveReference(),
|
||||
style = TangemTheme.typography.h3,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
Text(
|
||||
text = stringResource(id = R.string.wallet_connect_subtitle),
|
||||
modifier = Modifier.padding(end = 20.dp, bottom = 4.dp),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
|
||||
if (item.subtitle != null) {
|
||||
Text(
|
||||
text = item.subtitle.resolveReference(),
|
||||
style = TangemTheme.typography.body1,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun DetailsItem(item: SettingsElement, onItemClick: () -> Unit) {
|
||||
private fun DetailsItem(item: SettingsItem) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(56.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onItemClick),
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
.clickable(enabled = !item.showProgress, onClick = item.onClick)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing20)
|
||||
.heightIn(min = TangemTheme.dimens.size56)
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing20),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = item.iconRes),
|
||||
contentDescription = stringResource(id = item.titleRes),
|
||||
modifier = Modifier.padding(start = 20.dp, end = 20.dp),
|
||||
tint = TangemTheme.colors.icon.secondary,
|
||||
)
|
||||
Column(modifier = Modifier.padding(end = 20.dp)) {
|
||||
if (item.showProgress) {
|
||||
CircularProgressIndicator(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
color = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = item.iconResId),
|
||||
contentDescription = item.title.resolveReference(),
|
||||
tint = TangemTheme.colors.icon.secondary,
|
||||
)
|
||||
}
|
||||
|
||||
Column(
|
||||
horizontalAlignment = Alignment.Start,
|
||||
verticalArrangement = Arrangement.SpaceAround,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(id = item.titleRes),
|
||||
modifier = Modifier,
|
||||
text = item.title.resolveReference(),
|
||||
style = TangemTheme.typography.subtitle1,
|
||||
color = TangemTheme.colors.text.primary1,
|
||||
)
|
||||
|
||||
if (item.subtitle != null) {
|
||||
Text(
|
||||
text = item.subtitle.resolveReference(),
|
||||
style = TangemTheme.typography.body2,
|
||||
color = TangemTheme.colors.text.secondary,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -153,50 +183,45 @@ private fun DetailsItem(item: SettingsElement, onItemClick: () -> Unit) {
|
|||
@Composable
|
||||
private fun TangemSocialAccounts(links: List<SocialNetworkLink>, onSocialNetworkClick: (SocialNetworkLink) -> Unit) {
|
||||
LazyRow(
|
||||
modifier = Modifier.padding(start = 8.dp, end = 8.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
contentPadding = PaddingValues(horizontal = TangemTheme.dimens.spacing8),
|
||||
) {
|
||||
items(links) {
|
||||
Icon(
|
||||
painter = painterResource(id = it.network.iconRes),
|
||||
contentDescription = "",
|
||||
val onClick = remember(it) {
|
||||
{ onSocialNetworkClick(it) }
|
||||
}
|
||||
|
||||
IconButton(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.clickable { onSocialNetworkClick(it) },
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing4)
|
||||
.size(TangemTheme.dimens.size32),
|
||||
onClick = onClick,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.size(TangemTheme.dimens.size24),
|
||||
painter = painterResource(id = it.network.iconRes),
|
||||
tint = TangemTheme.colors.icon.informative,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BoxScope.ShowSnackbarIfNeeded(snackbarErrorState: EventError) {
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
SnackbarHost(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.padding(vertical = TangemTheme.dimens.spacing16)
|
||||
.fillMaxWidth(),
|
||||
hostState = snackbarHostState,
|
||||
)
|
||||
val errorTitle = when (snackbarErrorState) {
|
||||
is EventError.DemoReferralNotAvailable -> stringResource(id = R.string.alert_demo_feature_disabled)
|
||||
EventError.Empty -> ""
|
||||
}
|
||||
if (snackbarErrorState != EventError.Empty) {
|
||||
SideEffect {
|
||||
coroutineScope.launch {
|
||||
snackbarHostState.showSnackbar(errorTitle)
|
||||
}
|
||||
when (snackbarErrorState) {
|
||||
is EventError.DemoReferralNotAvailable -> snackbarErrorState.onErrorShow.invoke()
|
||||
else -> {
|
||||
/*no-op*/
|
||||
}
|
||||
}
|
||||
private fun ShowSnackbarIfNeeded(snackbarHostState: SnackbarHostState, messageEvent: StateEvent<TextReference>) {
|
||||
var message: TextReference? by remember { mutableStateOf(value = null) }
|
||||
val resolvedMessage by rememberUpdatedState(newValue = message?.resolveReference())
|
||||
|
||||
LaunchedEffect(resolvedMessage) {
|
||||
resolvedMessage?.let {
|
||||
snackbarHostState.showSnackbar(it)
|
||||
}
|
||||
}
|
||||
|
||||
EventEffect(messageEvent) {
|
||||
message = it
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -210,33 +235,59 @@ private fun TangemAppVersion(appNameRes: Int, version: String, modifier: Modifie
|
|||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 900)
|
||||
@Composable
|
||||
private fun DetailsScreenContentSample() {
|
||||
DetailsScreen(
|
||||
state = DetailsScreenState(
|
||||
elements = SettingsElement.values().toList(),
|
||||
private fun DetailsScreenPreview_Light(
|
||||
@PreviewParameter(DetailsScreenStateProvider::class) param: DetailsScreenState,
|
||||
) {
|
||||
TangemTheme(isDark = false) {
|
||||
DetailsScreen(param, onBackClick = {})
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360, heightDp = 900)
|
||||
@Composable
|
||||
private fun DetailsScreenPreview_Dark(@PreviewParameter(DetailsScreenStateProvider::class) param: DetailsScreenState) {
|
||||
TangemTheme(isDark = true) {
|
||||
DetailsScreen(param, onBackClick = {})
|
||||
}
|
||||
}
|
||||
|
||||
private class DetailsScreenStateProvider : CollectionPreviewParameterProvider<DetailsScreenState>(
|
||||
collection = buildList {
|
||||
DetailsScreenState(
|
||||
elements = buildList {
|
||||
SettingsItem.WalletConnect({}).let(::add)
|
||||
SettingsItem.AddWallet(showProgress = false, {}).let(::add)
|
||||
SettingsItem.LinkMoreCards({}).let(::add)
|
||||
SettingsItem.CardSettings({}).let(::add)
|
||||
SettingsItem.AppSettings({}).let(::add)
|
||||
SettingsItem.Chat({}).let(::add)
|
||||
SettingsItem.SendFeedback({}).let(::add)
|
||||
SettingsItem.ReferralProgram({}).let(::add)
|
||||
SettingsItem.TermsOfService({}).let(::add)
|
||||
}.toImmutableList(),
|
||||
tangemLinks = TangemSocialAccounts.accountsEn,
|
||||
tangemVersion = "Tangem 2.14.12 (343)",
|
||||
onItemsClick = {},
|
||||
showSnackbar = consumedEvent(),
|
||||
onSocialNetworkClick = {},
|
||||
),
|
||||
onBackClick = {},
|
||||
)
|
||||
}
|
||||
).let(::add)
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Composable
|
||||
private fun DetailsScreenContentPreview_Light() {
|
||||
TangemTheme(isDark = false) {
|
||||
DetailsScreenContentSample()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Composable
|
||||
private fun DetailsScreenContentPreview_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
DetailsScreenContentSample()
|
||||
}
|
||||
}
|
||||
DetailsScreenState(
|
||||
elements = buildList {
|
||||
SettingsItem.WalletConnect({}).let(::add)
|
||||
SettingsItem.AddWallet(showProgress = true, {}).let(::add)
|
||||
SettingsItem.CardSettings({}).let(::add)
|
||||
SettingsItem.AppSettings({}).let(::add)
|
||||
SettingsItem.Chat({}).let(::add)
|
||||
SettingsItem.SendFeedback({}).let(::add)
|
||||
SettingsItem.TermsOfService({}).let(::add)
|
||||
}.toImmutableList(),
|
||||
tangemLinks = TangemSocialAccounts.accountsRu,
|
||||
tangemVersion = "Tangem 2.14.12 (343)",
|
||||
showSnackbar = consumedEvent(),
|
||||
onSocialNetworkClick = {},
|
||||
).let(::add)
|
||||
},
|
||||
)
|
||||
// endregion Preview
|
||||
|
|
@ -1,37 +1,118 @@
|
|||
package com.tangem.tap.features.details.ui.details
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringReference
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Immutable
|
||||
internal data class DetailsScreenState(
|
||||
val elements: List<SettingsElement>,
|
||||
val tangemLinks: List<SocialNetworkLink>,
|
||||
val elements: ImmutableList<SettingsItem>,
|
||||
val tangemLinks: ImmutableList<SocialNetworkLink>,
|
||||
val tangemVersion: String,
|
||||
val onItemsClick: (SettingsElement) -> Unit,
|
||||
val showSnackbar: StateEvent<TextReference>,
|
||||
val onSocialNetworkClick: (SocialNetworkLink) -> Unit,
|
||||
val showErrorSnackbar: MutableState<EventError> = mutableStateOf(EventError.Empty),
|
||||
) {
|
||||
val appNameRes: Int = R.string.tangem_app_name
|
||||
}
|
||||
|
||||
@Immutable
|
||||
internal enum class SettingsElement(
|
||||
val iconRes: Int,
|
||||
val titleRes: Int,
|
||||
internal sealed class SettingsItem(
|
||||
@DrawableRes val iconResId: Int,
|
||||
val title: TextReference,
|
||||
val subtitle: TextReference? = null,
|
||||
val isLarge: Boolean = false,
|
||||
) {
|
||||
WalletConnect(R.drawable.ic_walletconnect, R.string.wallet_connect_title),
|
||||
LinkMoreCards(R.drawable.ic_more_cards, R.string.details_row_title_create_backup),
|
||||
ReferralProgram(R.drawable.ic_add_friends, R.string.details_referral_title),
|
||||
CardSettings(R.drawable.ic_card_settings, R.string.card_settings_title),
|
||||
AppSettings(R.drawable.ic_settings, R.string.app_settings_title),
|
||||
Chat(R.drawable.ic_chat, R.string.details_chat),
|
||||
SendFeedback(R.drawable.ic_comment, R.string.details_row_title_send_feedback),
|
||||
TermsOfService(R.drawable.ic_text, R.string.disclaimer_title), // General Terms of Service of the App,
|
||||
PrivacyPolicy(R.drawable.ic_lock_24, R.string.details_row_privacy_policy),
|
||||
TesterMenu(R.drawable.ic_alert_24, R.string.tester_menu),
|
||||
|
||||
abstract val onClick: () -> Unit
|
||||
|
||||
open val showProgress: Boolean = false
|
||||
|
||||
data class WalletConnect(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_walletconnect,
|
||||
title = resourceReference(R.string.wallet_connect_title),
|
||||
subtitle = resourceReference(R.string.wallet_connect_subtitle),
|
||||
isLarge = true,
|
||||
)
|
||||
|
||||
data class AddWallet(
|
||||
override val showProgress: Boolean,
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_plus_24,
|
||||
title = stringReference(value = "Add new wallet"),
|
||||
)
|
||||
|
||||
data class ScanWallet(
|
||||
override val showProgress: Boolean,
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_plus_24,
|
||||
title = stringReference(value = "Scan new wallet"),
|
||||
)
|
||||
|
||||
data class LinkMoreCards(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_more_cards,
|
||||
title = resourceReference(R.string.details_row_title_create_backup),
|
||||
)
|
||||
|
||||
data class CardSettings(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_card_settings,
|
||||
title = resourceReference(R.string.card_settings_title),
|
||||
)
|
||||
|
||||
data class AppSettings(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_settings,
|
||||
title = resourceReference(R.string.app_settings_title),
|
||||
)
|
||||
|
||||
data class Chat(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_chat,
|
||||
title = resourceReference(R.string.details_chat),
|
||||
)
|
||||
|
||||
data class SendFeedback(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_comment,
|
||||
title = resourceReference(R.string.details_row_title_send_feedback),
|
||||
)
|
||||
|
||||
data class ReferralProgram(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_add_friends,
|
||||
title = resourceReference(R.string.details_referral_title),
|
||||
)
|
||||
|
||||
data class TermsOfService(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_text,
|
||||
title = resourceReference(R.string.disclaimer_title),
|
||||
)
|
||||
|
||||
data class TesterMenu(
|
||||
override val onClick: () -> Unit,
|
||||
) : SettingsItem(
|
||||
iconResId = R.drawable.ic_alert_24,
|
||||
title = resourceReference(R.string.tester_menu),
|
||||
)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
|
|
@ -57,7 +138,7 @@ sealed class SocialNetwork(val id: String, val iconRes: Int) {
|
|||
}
|
||||
|
||||
internal object TangemSocialAccounts {
|
||||
val accountsEn: List<SocialNetworkLink> = listOf(
|
||||
val accountsEn: ImmutableList<SocialNetworkLink> = persistentListOf(
|
||||
SocialNetworkLink(SocialNetwork.Telegram, "https://t.me/tangem_chat"),
|
||||
SocialNetworkLink(SocialNetwork.Twitter, "https://twitter.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"),
|
||||
|
|
@ -67,7 +148,7 @@ internal object TangemSocialAccounts {
|
|||
SocialNetworkLink(SocialNetwork.LinkedIn, "https://www.linkedin.com/company/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Discord, "https://discord.gg/7AqTVyqdGS"),
|
||||
)
|
||||
val accountsRu: List<SocialNetworkLink> = listOf(
|
||||
val accountsRu: ImmutableList<SocialNetworkLink> = persistentListOf(
|
||||
SocialNetworkLink(SocialNetwork.Telegram, "https://t.me/tangem_chat_ru"),
|
||||
SocialNetworkLink(SocialNetwork.Twitter, "https://twitter.com/tangem"),
|
||||
SocialNetworkLink(SocialNetwork.Facebook, "https://m.facebook.com/TangemCards/"),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ import androidx.compose.runtime.mutableStateOf
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.event.StateEvent
|
||||
import com.tangem.core.ui.event.consumedEvent
|
||||
import com.tangem.core.ui.event.triggeredEvent
|
||||
import com.tangem.core.ui.extensions.TextReference
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
|
|
@ -21,6 +25,9 @@ import com.tangem.tap.features.wallet.redux.WalletAction
|
|||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.userWalletsListManager
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
|
|
@ -42,82 +49,64 @@ internal class DetailsViewModel(private val store: Store<AppState>) {
|
|||
elements = createSettingsItems(state),
|
||||
tangemLinks = getSocialLinks(),
|
||||
tangemVersion = getTangemAppVersion(),
|
||||
onItemsClick = { handleClickingSettingsItem(it) },
|
||||
onSocialNetworkClick = { handleSocialNetworkClick(it) },
|
||||
showSnackbar = triggerErrorSnackbarIfNeeded(state.error),
|
||||
onSocialNetworkClick = ::handleSocialNetworkClick,
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("ComplexMethod")
|
||||
private fun createSettingsItems(state: DetailsState): List<SettingsElement> {
|
||||
val scanResponse = state.scanResponse ?: return emptyList()
|
||||
private fun createSettingsItems(state: DetailsState): ImmutableList<SettingsItem> {
|
||||
val scanResponse = state.scanResponse ?: return persistentListOf()
|
||||
val cardTypesResolver = scanResponse.cardTypesResolver
|
||||
|
||||
return SettingsElement.values().mapNotNull {
|
||||
when (it) {
|
||||
SettingsElement.WalletConnect -> if (cardTypesResolver.isMultiwalletAllowed()) it else null
|
||||
SettingsElement.SendFeedback -> it
|
||||
SettingsElement.LinkMoreCards -> if (state.createBackupAllowed) it else null
|
||||
SettingsElement.PrivacyPolicy -> if (state.privacyPolicyUrl != null) it else null
|
||||
SettingsElement.AppSettings -> if (state.appSettingsState.isBiometricsAvailable) it else null
|
||||
SettingsElement.ReferralProgram -> if (cardTypesResolver.isTangemWallet()) it else null
|
||||
SettingsElement.TesterMenu -> if (BuildConfig.TESTER_MENU_ENABLED) it else null
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
return buildList {
|
||||
SettingsItem.WalletConnect(::navigateToWalletConnect)
|
||||
.takeIf { cardTypesResolver.isMultiwalletAllowed() }
|
||||
?.let(::add)
|
||||
|
||||
SettingsItem.AddWallet(showProgress = state.isScanningInProgress, ::scanAndSaveUserWallet)
|
||||
.takeIf { state.appSettingsState.saveWallets }
|
||||
?.let(::add)
|
||||
|
||||
SettingsItem.ScanWallet(showProgress = state.isScanningInProgress, ::scanAndSaveUserWallet)
|
||||
.takeUnless { state.appSettingsState.saveWallets }
|
||||
?.let(::add)
|
||||
|
||||
SettingsItem.LinkMoreCards(::linkMoreCards)
|
||||
.takeIf { state.createBackupAllowed }
|
||||
?.let(::add)
|
||||
|
||||
SettingsItem.CardSettings(::navigateToCardSettings)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.AppSettings(::navigateToAppSettings)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.Chat(::navigateToChat)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.SendFeedback(::sendFeedback)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.ReferralProgram(::navigateToReferralProgram)
|
||||
.takeIf { cardTypesResolver.isTangemWallet() }
|
||||
?.let(::add)
|
||||
|
||||
SettingsItem.TermsOfService(::navigateToToS)
|
||||
.let(::add)
|
||||
|
||||
SettingsItem.TesterMenu(::navigateToTesterMenu)
|
||||
.takeIf { BuildConfig.TESTER_MENU_ENABLED }
|
||||
?.let(::add)
|
||||
}.toImmutableList()
|
||||
}
|
||||
|
||||
private fun handleSocialNetworkClick(link: SocialNetworkLink) {
|
||||
Analytics.send(Settings.ButtonSocialNetwork(link.network))
|
||||
store.dispatch(NavigationAction.OpenUrl(link.url))
|
||||
}
|
||||
|
||||
private fun handleClickingSettingsItem(item: SettingsElement) {
|
||||
when (item) {
|
||||
SettingsElement.WalletConnect -> {
|
||||
Analytics.send(Settings.ButtonWalletConnect())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions))
|
||||
}
|
||||
SettingsElement.Chat -> {
|
||||
Analytics.send(Settings.ButtonChat())
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
}
|
||||
SettingsElement.SendFeedback -> {
|
||||
Analytics.send(Settings.ButtonSendFeedback())
|
||||
store.dispatch(GlobalAction.SendEmail(FeedbackEmail()))
|
||||
}
|
||||
SettingsElement.CardSettings -> {
|
||||
Analytics.send(Settings.ButtonCardSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CardSettings))
|
||||
}
|
||||
SettingsElement.AppSettings -> {
|
||||
Analytics.send(Settings.ButtonAppSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.AppSettings))
|
||||
}
|
||||
SettingsElement.LinkMoreCards -> {
|
||||
Analytics.send(Settings.ButtonCreateBackup())
|
||||
store.dispatch(WalletAction.MultiWallet.BackupWallet)
|
||||
}
|
||||
SettingsElement.TermsOfService -> {
|
||||
store.dispatch(DisclaimerAction.Show(AppScreen.Details))
|
||||
}
|
||||
SettingsElement.PrivacyPolicy -> {
|
||||
// TODO: To be available later
|
||||
}
|
||||
SettingsElement.ReferralProgram -> {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.ReferralProgram))
|
||||
}
|
||||
SettingsElement.TesterMenu -> {
|
||||
store.state.daggerGraphState.testerRouter?.startTesterScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSocialLinks(): List<SocialNetworkLink> {
|
||||
val locale = LocaleRegionProvider().getRegion()
|
||||
return if (locale.lowercase() == RUSSIA_COUNTRY_CODE) {
|
||||
TangemSocialAccounts.accountsRu
|
||||
private fun triggerErrorSnackbarIfNeeded(text: TextReference?): StateEvent<TextReference> {
|
||||
return if (text == null) {
|
||||
consumedEvent()
|
||||
} else {
|
||||
TangemSocialAccounts.accountsEn
|
||||
triggeredEvent(text) {
|
||||
store.dispatch(DetailsAction.DismissError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +116,66 @@ internal class DetailsViewModel(private val store: Store<AppState>) {
|
|||
return "$versionName ($versionCode)"
|
||||
}
|
||||
|
||||
private fun navigateToTesterMenu() {
|
||||
store.state.daggerGraphState.testerRouter?.startTesterScreen()
|
||||
}
|
||||
|
||||
private fun navigateToToS() {
|
||||
store.dispatch(DisclaimerAction.Show(AppScreen.Details))
|
||||
}
|
||||
|
||||
private fun navigateToReferralProgram() {
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.ReferralProgram))
|
||||
}
|
||||
|
||||
private fun sendFeedback() {
|
||||
Analytics.send(Settings.ButtonSendFeedback())
|
||||
store.dispatch(GlobalAction.SendEmail(FeedbackEmail()))
|
||||
}
|
||||
|
||||
private fun navigateToChat() {
|
||||
Analytics.send(Settings.ButtonChat())
|
||||
store.dispatch(GlobalAction.OpenChat(SupportInfo()))
|
||||
}
|
||||
|
||||
private fun navigateToAppSettings() {
|
||||
Analytics.send(Settings.ButtonAppSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.AppSettings))
|
||||
}
|
||||
|
||||
private fun navigateToCardSettings() {
|
||||
Analytics.send(Settings.ButtonCardSettings())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.CardSettings))
|
||||
}
|
||||
|
||||
private fun linkMoreCards() {
|
||||
Analytics.send(Settings.ButtonCreateBackup())
|
||||
store.dispatch(WalletAction.MultiWallet.BackupWallet)
|
||||
}
|
||||
|
||||
private fun scanAndSaveUserWallet() {
|
||||
store.dispatch(DetailsAction.ScanAndSaveUserWallet)
|
||||
}
|
||||
|
||||
private fun navigateToWalletConnect() {
|
||||
Analytics.send(Settings.ButtonWalletConnect())
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.WalletConnectSessions))
|
||||
}
|
||||
|
||||
private fun handleSocialNetworkClick(link: SocialNetworkLink) {
|
||||
Analytics.send(Settings.ButtonSocialNetwork(link.network))
|
||||
store.dispatch(NavigationAction.OpenUrl(link.url))
|
||||
}
|
||||
|
||||
private fun getSocialLinks(): ImmutableList<SocialNetworkLink> {
|
||||
val locale = LocaleRegionProvider().getRegion()
|
||||
return if (locale.lowercase() == RUSSIA_COUNTRY_CODE) {
|
||||
TangemSocialAccounts.accountsRu
|
||||
} else {
|
||||
TangemSocialAccounts.accountsEn
|
||||
}
|
||||
}
|
||||
|
||||
private fun bootstrapScreenState() {
|
||||
userWalletsListManager.selectedUserWallet
|
||||
.distinctUntilChanged()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue