Settings code cleanup (#1644)

* Settings code cleanup

* Auto formatting using Ktlint

---------

Co-authored-by: Honza <rychnovsky.honza@gmail.com>
This commit is contained in:
Milan 2024-10-23 15:08:02 +02:00 committed by GitHub
parent 5410cc26c2
commit 9d634a2da8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 382 additions and 251 deletions

View File

@ -0,0 +1,51 @@
package co.electriccoin.zcash.ui.design.component
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.design.R
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.util.StringResource
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.stringRes
@Composable
fun ZashiVersion(
version: StringResource,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier
) {
Image(
modifier = Modifier.align(CenterHorizontally),
painter =
painterResource(id = R.drawable.img_zashi_version),
contentDescription = version.getValue()
)
Spacer(modifier = Modifier.height(16.dp))
Text(
modifier = Modifier.align(CenterHorizontally),
text = version.getValue(),
color = ZashiColors.Text.textTertiary
)
}
}
@PreviewScreens
@Composable
private fun ZashiVersionPreview() =
ZcashTheme {
BlankSurface {
ZashiVersion(version = stringRes("Version"))
}
}

View File

@ -10,6 +10,7 @@ import co.electriccoin.zcash.ui.screen.settings.model.SettingsState
import co.electriccoin.zcash.ui.screen.settings.model.SettingsTroubleshootingState import co.electriccoin.zcash.ui.screen.settings.model.SettingsTroubleshootingState
import co.electriccoin.zcash.ui.screen.settings.model.TroubleshootingItemState import co.electriccoin.zcash.ui.screen.settings.model.TroubleshootingItemState
import co.electriccoin.zcash.ui.screen.settings.view.Settings import co.electriccoin.zcash.ui.screen.settings.view.Settings
import kotlinx.collections.immutable.persistentListOf
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
class SettingsViewTestSetup( class SettingsViewTestSetup(
@ -107,26 +108,46 @@ class SettingsViewTestSetup(
SettingsState( SettingsState(
isLoading = false, isLoading = false,
version = stringRes("app_version"), version = stringRes("app_version"),
settingsTroubleshootingState = settingsTroubleshootingState, debugMenu = settingsTroubleshootingState,
onBack = { onBack = {
onBackCount.incrementAndGet() onBackCount.incrementAndGet()
}, },
onSendUsFeedbackClick = { items =
onFeedbackCount.incrementAndGet() persistentListOf(
}, ZashiSettingsListItemState(
onAdvancedSettingsClick = { text = stringRes(R.string.settings_address_book),
onAdvancedSettingsCount.incrementAndGet() icon = R.drawable.ic_settings_address_book,
}, onClick = {
onAboutUsClick = { onAddressBookCount.incrementAndGet()
onAboutCount.incrementAndGet() },
}, ),
onAddressBookClick = { ZashiSettingsListItemState(
onAddressBookCount.incrementAndGet() text = stringRes(R.string.settings_integrations),
}, icon = R.drawable.ic_settings_integrations,
integrations = titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase),
ZashiSettingsListItemState( onClick = { },
stringRes("Integrations"), ),
R.drawable.ic_settings_integrations, ZashiSettingsListItemState(
text = stringRes(R.string.settings_advanced_settings),
icon = R.drawable.ic_advanced_settings,
onClick = {
onAdvancedSettingsCount.incrementAndGet()
},
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_about_us),
icon = R.drawable.ic_settings_info,
onClick = {
onAboutCount.incrementAndGet()
},
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_feedback),
icon = R.drawable.ic_settings_feedback,
onClick = {
onFeedbackCount.incrementAndGet()
},
),
) )
), ),
topAppBarSubTitleState = TopAppBarSubTitleState.None, topAppBarSubTitleState = TopAppBarSubTitleState.None,

View File

@ -55,7 +55,6 @@ val viewModelModule =
AddressBookViewModel( AddressBookViewModel(
args = args, args = args,
observeAddressBookContacts = get(), observeAddressBookContacts = get(),
getVersionInfo = get(),
observeContactPicked = get(), observeContactPicked = get(),
) )
} }

View File

@ -6,7 +6,6 @@ import co.electriccoin.zcash.ui.design.util.StringResource
data class AddressBookState( data class AddressBookState(
val contacts: List<AddressBookContactState>, val contacts: List<AddressBookContactState>,
val isLoading: Boolean, val isLoading: Boolean,
val version: StringResource,
val onBack: () -> Unit, val onBack: () -> Unit,
val scanButton: ButtonState, val scanButton: ButtonState,
val manualButton: ButtonState val manualButton: ButtonState

View File

@ -146,7 +146,6 @@ private fun PopupContentPreview() =
AddressBookState( AddressBookState(
onBack = {}, onBack = {},
isLoading = false, isLoading = false,
version = stringRes("Version"),
contacts = emptyList(), contacts = emptyList(),
scanButton = scanButton =
ButtonState( ButtonState(

View File

@ -55,7 +55,6 @@ import co.electriccoin.zcash.ui.screen.addressbook.AddressBookTag
import co.electriccoin.zcash.ui.screen.addressbook.model.AddressBookContactState import co.electriccoin.zcash.ui.screen.addressbook.model.AddressBookContactState
import co.electriccoin.zcash.ui.screen.addressbook.model.AddressBookState import co.electriccoin.zcash.ui.screen.addressbook.model.AddressBookState
@Suppress("LongMethod")
@Composable @Composable
fun AddressBookView( fun AddressBookView(
state: AddressBookState, state: AddressBookState,
@ -307,7 +306,6 @@ private fun DataPreview() {
state = state =
AddressBookState( AddressBookState(
isLoading = false, isLoading = false,
version = stringRes("Version 1.2"),
onBack = {}, onBack = {},
contacts = contacts =
(1..10).map { (1..10).map {
@ -341,7 +339,6 @@ private fun LoadingPreview() {
state = state =
AddressBookState( AddressBookState(
isLoading = true, isLoading = true,
version = stringRes("Version 1.2"),
onBack = {}, onBack = {},
contacts = emptyList(), contacts = emptyList(),
scanButton = scanButton =
@ -366,7 +363,6 @@ private fun EmptyPreview() {
state = state =
AddressBookState( AddressBookState(
isLoading = false, isLoading = false,
version = stringRes("Version 1.2"),
onBack = {}, onBack = {},
contacts = emptyList(), contacts = emptyList(),
scanButton = scanButton =

View File

@ -5,7 +5,6 @@ import androidx.lifecycle.viewModelScope
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.AddressBookContact import co.electriccoin.zcash.ui.common.model.AddressBookContact
import co.electriccoin.zcash.ui.common.provider.GetVersionInfoProvider
import co.electriccoin.zcash.ui.common.usecase.ObserveAddressBookContactsUseCase import co.electriccoin.zcash.ui.common.usecase.ObserveAddressBookContactsUseCase
import co.electriccoin.zcash.ui.common.usecase.ObserveContactPickedUseCase import co.electriccoin.zcash.ui.common.usecase.ObserveContactPickedUseCase
import co.electriccoin.zcash.ui.design.component.ButtonState import co.electriccoin.zcash.ui.design.component.ButtonState
@ -31,12 +30,9 @@ import kotlin.time.Duration.Companion.seconds
class AddressBookViewModel( class AddressBookViewModel(
observeAddressBookContacts: ObserveAddressBookContactsUseCase, observeAddressBookContacts: ObserveAddressBookContactsUseCase,
getVersionInfo: GetVersionInfoProvider,
private val args: AddressBookArgs, private val args: AddressBookArgs,
private val observeContactPicked: ObserveContactPickedUseCase private val observeContactPicked: ObserveContactPickedUseCase
) : ViewModel() { ) : ViewModel() {
private val versionInfo = getVersionInfo()
val state = val state =
observeAddressBookContacts() observeAddressBookContacts()
.map { contacts -> createState(contacts = contacts) } .map { contacts -> createState(contacts = contacts) }
@ -53,7 +49,6 @@ class AddressBookViewModel(
private fun createState(contacts: List<AddressBookContact>?) = private fun createState(contacts: List<AddressBookContact>?) =
AddressBookState( AddressBookState(
version = stringRes(R.string.address_book_version, versionInfo.versionName),
isLoading = contacts == null, isLoading = contacts == null,
contacts = contacts =
contacts?.map { contact -> contacts?.map { contact ->

View File

@ -1,10 +0,0 @@
package co.electriccoin.zcash.ui.screen.advancedsettings
data class AdvancedSettingsState(
val onBack: () -> Unit,
val onRecoveryPhraseClick: () -> Unit,
val onExportPrivateDataClick: () -> Unit,
val onChooseServerClick: () -> Unit,
val onCurrencyConversionClick: () -> Unit,
val onDeleteZashiClick: () -> Unit,
)

View File

@ -11,6 +11,7 @@ import co.electriccoin.zcash.ui.common.compose.LocalNavController
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
import co.electriccoin.zcash.ui.screen.advancedsettings.view.AdvancedSettings import co.electriccoin.zcash.ui.screen.advancedsettings.view.AdvancedSettings
import co.electriccoin.zcash.ui.screen.advancedsettings.viewmodel.AdvancedSettingsViewModel import co.electriccoin.zcash.ui.screen.advancedsettings.viewmodel.AdvancedSettingsViewModel
import kotlinx.collections.immutable.toImmutableList
import org.koin.androidx.compose.koinViewModel import org.koin.androidx.compose.koinViewModel
@Suppress("LongParameterList") @Suppress("LongParameterList")
@ -24,11 +25,18 @@ internal fun WrapAdvancedSettings(
val walletViewModel = koinActivityViewModel<WalletViewModel>() val walletViewModel = koinActivityViewModel<WalletViewModel>()
val viewModel = koinViewModel<AdvancedSettingsViewModel>() val viewModel = koinViewModel<AdvancedSettingsViewModel>()
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
val originalState = viewModel.state.collectAsStateWithLifecycle().value
val state = val state =
viewModel.state.collectAsStateWithLifecycle().value.copy( originalState.copy(
onDeleteZashiClick = goDeleteWallet, deleteButton = originalState.deleteButton.copy(onClick = goDeleteWallet),
onExportPrivateDataClick = goExportPrivateData, items =
onRecoveryPhraseClick = goSeedRecovery originalState.items.mapIndexed { index, item ->
when (index) {
0 -> item.copy(onClick = goSeedRecovery)
1 -> item.copy(onClick = goExportPrivateData)
else -> item
}
}.toImmutableList()
) )
BackHandler { BackHandler {

View File

@ -0,0 +1,11 @@
package co.electriccoin.zcash.ui.screen.advancedsettings.model
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import kotlinx.collections.immutable.ImmutableList
data class AdvancedSettingsState(
val onBack: () -> Unit,
val items: ImmutableList<ZashiSettingsListItemState>,
val deleteButton: ButtonState,
)

View File

@ -22,26 +22,29 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEachIndexed
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ZashiButton import co.electriccoin.zcash.ui.design.component.ZashiButton
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
import co.electriccoin.zcash.ui.design.component.ZashiHorizontalDivider import co.electriccoin.zcash.ui.design.component.ZashiHorizontalDivider
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItem import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItem
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
import co.electriccoin.zcash.ui.design.util.orDark import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsState
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsTag import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsTag
import co.electriccoin.zcash.ui.screen.advancedsettings.model.AdvancedSettingsState
import kotlinx.collections.immutable.persistentListOf
// TODO [#1271]: Add AdvancedSettingsView Tests // TODO [#1271]: Add AdvancedSettingsView Tests
// TODO [#1271]: https://github.com/Electric-Coin-Company/zashi-android/issues/1271 // TODO [#1271]: https://github.com/Electric-Coin-Company/zashi-android/issues/1271
@Suppress("LongMethod")
@Composable @Composable
fun AdvancedSettings( fun AdvancedSettings(
state: AdvancedSettingsState, state: AdvancedSettingsState,
@ -67,66 +70,49 @@ fun AdvancedSettings(
end = 4.dp end = 4.dp
), ),
) { ) {
ZashiSettingsListItem( state.items.fastForEachIndexed { index, item ->
text = stringResource(id = R.string.advanced_settings_recovery), ZashiSettingsListItem(state = item)
icon = R.drawable.ic_advanced_settings_recovery, if (index != state.items.lastIndex) {
onClick = state.onRecoveryPhraseClick ZashiHorizontalDivider()
) }
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.advanced_settings_export),
icon = R.drawable.ic_advanced_settings_export,
onClick = state.onExportPrivateDataClick
)
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.advanced_settings_choose_server),
icon =
R.drawable.ic_advanced_settings_choose_server orDark
R.drawable.ic_advanced_settings_choose_server,
onClick = state.onChooseServerClick
)
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.advanced_settings_currency_conversion),
icon =
R.drawable.ic_advanced_settings_currency_conversion orDark
R.drawable.ic_advanced_settings_currency_conversion,
onClick = state.onCurrencyConversionClick
)
Spacer(modifier = Modifier.height(24.dp))
Spacer(modifier = Modifier.weight(1f))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = R.drawable.ic_advanced_settings_info),
contentDescription = "",
colorFilter = ColorFilter.tint(ZashiColors.Text.textTertiary)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = stringResource(id = R.string.advanced_settings_info),
fontSize = 12.sp,
color = ZashiColors.Text.textTertiary,
)
} }
Spacer(modifier = Modifier.height(ZashiDimensions.Spacing.spacingXl))
Spacer(modifier = Modifier.weight(1f))
Info()
Spacer(modifier = Modifier.height(20.dp)) Spacer(modifier = Modifier.height(20.dp))
ZashiButton( ZashiButton(
modifier = modifier =
Modifier Modifier
.padding(horizontal = 20.dp) .padding(horizontal = 20.dp)
.fillMaxWidth(), .fillMaxWidth(),
text = stringResource(R.string.advanced_settings_delete_button),
colors = ZashiButtonDefaults.destructive1Colors(), colors = ZashiButtonDefaults.destructive1Colors(),
onClick = state.onDeleteZashiClick state = state.deleteButton
) )
} }
} }
} }
@Composable
private fun Info() {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = R.drawable.ic_advanced_settings_info),
contentDescription = "",
colorFilter = ColorFilter.tint(ZashiColors.Text.textTertiary)
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = stringResource(id = R.string.advanced_settings_info),
fontSize = 12.sp,
color = ZashiColors.Text.textTertiary,
)
}
}
@Composable @Composable
private fun AdvancedSettingsTopAppBar( private fun AdvancedSettingsTopAppBar(
onBack: () -> Unit, onBack: () -> Unit,
@ -148,7 +134,6 @@ private fun AdvancedSettingsTopAppBar(
) )
} }
@Suppress("UnusedPrivateMember")
@PreviewScreens @PreviewScreens
@Composable @Composable
private fun AdvancedSettingsPreview() = private fun AdvancedSettingsPreview() =
@ -157,11 +142,34 @@ private fun AdvancedSettingsPreview() =
state = state =
AdvancedSettingsState( AdvancedSettingsState(
onBack = {}, onBack = {},
onRecoveryPhraseClick = {}, items =
onExportPrivateDataClick = {}, persistentListOf(
onChooseServerClick = {}, ZashiSettingsListItemState(
onCurrencyConversionClick = {}, text = stringRes(R.string.advanced_settings_recovery),
onDeleteZashiClick = {}, icon = R.drawable.ic_advanced_settings_recovery,
onClick = {}
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_export),
icon = R.drawable.ic_advanced_settings_export,
onClick = {}
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_choose_server),
icon = R.drawable.ic_advanced_settings_choose_server,
onClick = {}
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_currency_conversion),
icon = R.drawable.ic_advanced_settings_currency_conversion,
onClick = {}
)
),
deleteButton =
ButtonState(
text = stringRes(R.string.advanced_settings_delete_button),
onClick = {}
)
), ),
topAppBarSubTitleState = TopAppBarSubTitleState.None, topAppBarSubTitleState = TopAppBarSubTitleState.None,
) )

View File

@ -3,7 +3,12 @@ package co.electriccoin.zcash.ui.screen.advancedsettings.viewmodel
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import co.electriccoin.zcash.ui.NavigationTargets import co.electriccoin.zcash.ui.NavigationTargets
import co.electriccoin.zcash.ui.screen.advancedsettings.AdvancedSettingsState import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.design.component.ButtonState
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.advancedsettings.model.AdvancedSettingsState
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@ -14,11 +19,36 @@ class AdvancedSettingsViewModel : ViewModel() {
MutableStateFlow( MutableStateFlow(
AdvancedSettingsState( AdvancedSettingsState(
onBack = ::onBack, onBack = ::onBack,
onRecoveryPhraseClick = {}, items =
onExportPrivateDataClick = {}, persistentListOf(
onChooseServerClick = ::onChooseServerClick, ZashiSettingsListItemState(
onCurrencyConversionClick = ::onCurrencyConversionClick, text = stringRes(R.string.advanced_settings_recovery),
onDeleteZashiClick = {}, icon = R.drawable.ic_advanced_settings_recovery,
onClick = {}
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_export),
icon = R.drawable.ic_advanced_settings_export,
onClick = {}
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_choose_server),
icon =
R.drawable.ic_advanced_settings_choose_server,
onClick = ::onChooseServerClick
),
ZashiSettingsListItemState(
text = stringRes(R.string.advanced_settings_currency_conversion),
icon =
R.drawable.ic_advanced_settings_currency_conversion,
onClick = ::onCurrencyConversionClick
)
),
deleteButton =
ButtonState(
stringRes(R.string.advanced_settings_delete_button),
onClick = {}
)
) )
).asStateFlow() ).asStateFlow()

View File

@ -2,10 +2,11 @@ package co.electriccoin.zcash.ui.screen.integrations.model
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.util.StringResource import co.electriccoin.zcash.ui.design.util.StringResource
import kotlinx.collections.immutable.ImmutableList
data class IntegrationsState( data class IntegrationsState(
val version: StringResource, val version: StringResource,
val coinbase: ZashiSettingsListItemState?,
val disabledInfo: StringResource?, val disabledInfo: StringResource?,
val onBack: () -> Unit, val onBack: () -> Unit,
val items: ImmutableList<ZashiSettingsListItemState>
) )

View File

@ -25,20 +25,23 @@ import androidx.compose.ui.unit.sp
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
import co.electriccoin.zcash.ui.design.component.ZashiHorizontalDivider
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItem import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItem
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.ZashiVersion
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
import co.electriccoin.zcash.ui.design.util.StringResource
import co.electriccoin.zcash.ui.design.util.getValue import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.orDark
import co.electriccoin.zcash.ui.design.util.stringRes import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.integrations.model.IntegrationsState import co.electriccoin.zcash.ui.screen.integrations.model.IntegrationsState
import co.electriccoin.zcash.ui.screen.settings.SettingsTag import co.electriccoin.zcash.ui.screen.settings.SettingsTag
import kotlinx.collections.immutable.persistentListOf
@Suppress("LongMethod")
@Composable @Composable
fun Integrations( fun Integrations(
state: IntegrationsState, state: IntegrationsState,
@ -56,54 +59,53 @@ fun Integrations(
.verticalScroll(rememberScrollState()) .verticalScroll(rememberScrollState())
.padding( .padding(
top = paddingValues.calculateTopPadding(), top = paddingValues.calculateTopPadding(),
bottom = paddingValues.calculateBottomPadding(), bottom = paddingValues.calculateBottomPadding() + ZashiDimensions.Spacing.spacing3xl,
start = 4.dp, start = 4.dp,
end = 4.dp end = 4.dp
), ),
) { ) {
state.coinbase?.let { state.items.forEachIndexed { index, item ->
ZashiSettingsListItem(state = it) ZashiSettingsListItem(state = item)
if (index != state.items.lastIndex) {
ZashiHorizontalDivider()
}
} }
state.disabledInfo?.let { state.disabledInfo?.let {
Spacer(modifier = Modifier.height(28.dp)) Spacer(modifier = Modifier.height(28.dp))
Row( DisabledInfo(it)
modifier = Modifier.fillMaxWidth().padding(horizontal = 20.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
painter = painterResource(id = R.drawable.ic_advanced_settings_info),
contentDescription = "",
colorFilter = ColorFilter.tint(ZashiColors.Utility.WarningYellow.utilityOrange700)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = it.getValue(),
fontSize = 12.sp,
color = ZashiColors.Utility.WarningYellow.utilityOrange700,
)
}
} }
Spacer(modifier = Modifier.height(ZashiDimensions.Spacing.spacingXl))
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingMin)) ZashiVersion(modifier = Modifier.align(CenterHorizontally), version = state.version)
Image(
modifier = Modifier.align(CenterHorizontally),
painter =
painterResource(id = R.drawable.ic_settings_zashi orDark R.drawable.ic_settings_zashi),
contentDescription = ""
)
Spacer(modifier = Modifier.height(16.dp))
Text(
modifier = Modifier.align(CenterHorizontally),
text = state.version.getValue(),
color = ZashiColors.Text.textTertiary
)
Spacer(modifier = Modifier.height(20.dp))
} }
} }
} }
@Composable
private fun DisabledInfo(it: StringResource) {
Row(
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
painter = painterResource(id = R.drawable.ic_advanced_settings_info),
contentDescription = "",
colorFilter = ColorFilter.tint(ZashiColors.Utility.WarningYellow.utilityOrange700)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = it.getValue(),
fontSize = 12.sp,
color = ZashiColors.Utility.WarningYellow.utilityOrange700,
)
}
}
@Composable @Composable
private fun IntegrationsTopAppBar( private fun IntegrationsTopAppBar(
onBack: () -> Unit, onBack: () -> Unit,
@ -125,25 +127,26 @@ private fun IntegrationsTopAppBar(
) )
} }
@Suppress("UnusedPrivateMember")
@PreviewScreens @PreviewScreens
@Composable @Composable
private fun IntegrationSettings() { private fun IntegrationSettings() =
ZcashTheme { ZcashTheme {
Integrations( Integrations(
state = state =
IntegrationsState( IntegrationsState(
version = stringRes("Version 1.2"), version = stringRes("Version 1.2"),
onBack = {}, onBack = {},
coinbase =
ZashiSettingsListItemState(
icon = R.drawable.ic_integrations_coinbase,
text = stringRes("Coinbase"),
subtitle = stringRes("Coinbase subtitle"),
) {},
disabledInfo = stringRes("Disabled info"), disabledInfo = stringRes("Disabled info"),
items =
persistentListOf(
ZashiSettingsListItemState(
icon = R.drawable.ic_integrations_coinbase,
text = stringRes("Coinbase"),
subtitle = stringRes("subtitle"),
onClick = {}
)
)
), ),
topAppBarSubTitleState = TopAppBarSubTitleState.None, topAppBarSubTitleState = TopAppBarSubTitleState.None,
) )
} }
}

View File

@ -14,6 +14,7 @@ import co.electriccoin.zcash.ui.common.usecase.ObserveWalletStateUseCase
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.util.stringRes import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.integrations.model.IntegrationsState import co.electriccoin.zcash.ui.screen.integrations.model.IntegrationsState
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.WhileSubscribed import kotlinx.coroutines.flow.WhileSubscribed
@ -44,21 +45,23 @@ class IntegrationsViewModel(
isEnabled.map { isEnabled -> isEnabled.map { isEnabled ->
IntegrationsState( IntegrationsState(
version = stringRes(R.string.integrations_version, versionInfo.versionName), version = stringRes(R.string.integrations_version, versionInfo.versionName),
coinbase =
ZashiSettingsListItemState(
// Set the wallet currency by app build is more future-proof, although we hide it from the UI
// in the Testnet build
icon = R.drawable.ic_integrations_coinbase,
text = stringRes(R.string.integrations_coinbase, getZcashCurrency.getLocalizedName()),
subtitle =
stringRes(
R.string.integrations_coinbase_subtitle,
getZcashCurrency.getLocalizedName()
),
onClick = ::onBuyWithCoinbaseClicked
).takeIf { isCoinbaseAvailable() },
disabledInfo = stringRes(R.string.integrations_disabled_info).takeIf { isEnabled.not() }, disabledInfo = stringRes(R.string.integrations_disabled_info).takeIf { isEnabled.not() },
onBack = ::onBack, onBack = ::onBack,
items =
listOfNotNull(
ZashiSettingsListItemState(
// Set the wallet currency by app build is more future-proof, although we hide it from
// the UI in the Testnet build
icon = R.drawable.ic_integrations_coinbase,
text = stringRes(R.string.integrations_coinbase, getZcashCurrency.getLocalizedName()),
subtitle =
stringRes(
R.string.integrations_coinbase_subtitle,
getZcashCurrency.getLocalizedName()
),
onClick = ::onBuyWithCoinbaseClicked
).takeIf { isCoinbaseAvailable() }
).toImmutableList()
) )
}.stateIn( }.stateIn(
scope = viewModelScope, scope = viewModelScope,

View File

@ -2,15 +2,12 @@ package co.electriccoin.zcash.ui.screen.settings.model
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.util.StringResource import co.electriccoin.zcash.ui.design.util.StringResource
import kotlinx.collections.immutable.ImmutableList
data class SettingsState( data class SettingsState(
val isLoading: Boolean,
val version: StringResource, val version: StringResource,
val settingsTroubleshootingState: SettingsTroubleshootingState?, val isLoading: Boolean,
val onAddressBookClick: () -> Unit,
val onBack: () -> Unit, val onBack: () -> Unit,
val integrations: ZashiSettingsListItemState, val debugMenu: SettingsTroubleshootingState?,
val onAdvancedSettingsClick: () -> Unit, val items: ImmutableList<ZashiSettingsListItemState>,
val onAboutUsClick: () -> Unit,
val onSendUsFeedbackClick: () -> Unit,
) )

View File

@ -1,6 +1,5 @@
package co.electriccoin.zcash.ui.screen.settings.view package co.electriccoin.zcash.ui.screen.settings.view
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@ -25,7 +24,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterHorizontally
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import co.electriccoin.zcash.ui.R import co.electriccoin.zcash.ui.R
@ -37,18 +35,16 @@ import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItem
import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState import co.electriccoin.zcash.ui.design.component.ZashiSettingsListItemState
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation
import co.electriccoin.zcash.ui.design.component.ZashiVersion
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
import co.electriccoin.zcash.ui.design.theme.ZcashTheme import co.electriccoin.zcash.ui.design.theme.ZcashTheme
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions import co.electriccoin.zcash.ui.design.theme.dimensions.ZashiDimensions
import co.electriccoin.zcash.ui.design.util.getValue
import co.electriccoin.zcash.ui.design.util.stringRes import co.electriccoin.zcash.ui.design.util.stringRes
import co.electriccoin.zcash.ui.screen.settings.SettingsTag import co.electriccoin.zcash.ui.screen.settings.SettingsTag
import co.electriccoin.zcash.ui.screen.settings.model.SettingsState import co.electriccoin.zcash.ui.screen.settings.model.SettingsState
import co.electriccoin.zcash.ui.screen.settings.model.SettingsTroubleshootingState import co.electriccoin.zcash.ui.screen.settings.model.SettingsTroubleshootingState
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
@Suppress("LongMethod")
@Composable @Composable
fun Settings( fun Settings(
state: SettingsState, state: SettingsState,
@ -78,45 +74,15 @@ fun Settings(
end = 4.dp end = 4.dp
), ),
) { ) {
ZashiSettingsListItem( state.items.forEachIndexed { index, item ->
text = stringResource(id = R.string.settings_address_book), ZashiSettingsListItem(state = item)
icon = R.drawable.ic_settings_address_book, if (index != state.items.lastIndex) {
onClick = state.onAddressBookClick ZashiHorizontalDivider()
) }
ZashiHorizontalDivider() }
ZashiSettingsListItem(state = state.integrations) Spacer(modifier = Modifier.height(ZashiDimensions.Spacing.spacingXl))
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.settings_advanced_settings),
icon = R.drawable.ic_advanced_settings,
onClick = state.onAdvancedSettingsClick
)
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.settings_about_us),
icon = R.drawable.ic_settings_info,
onClick = state.onAboutUsClick
)
ZashiHorizontalDivider()
ZashiSettingsListItem(
text = stringResource(id = R.string.settings_feedback),
icon = R.drawable.ic_settings_feedback,
onClick = state.onSendUsFeedbackClick
)
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
Spacer(modifier = Modifier.height(ZcashTheme.dimens.spacingMin)) ZashiVersion(modifier = Modifier.align(CenterHorizontally), version = state.version)
Image(
modifier = Modifier.align(CenterHorizontally),
painter =
painterResource(id = R.drawable.ic_settings_zashi),
contentDescription = ""
)
Spacer(modifier = Modifier.height(16.dp))
Text(
modifier = Modifier.align(CenterHorizontally),
text = state.version.getValue(),
color = ZashiColors.Text.textTertiary
)
} }
} }
} }
@ -142,8 +108,8 @@ private fun SettingsTopAppBar(
ZashiTopAppBarBackNavigation(onBack = onBack) ZashiTopAppBarBackNavigation(onBack = onBack)
}, },
regularActions = { regularActions = {
if (state.settingsTroubleshootingState != null) { if (state.debugMenu != null) {
TroubleshootingMenu(state = state.settingsTroubleshootingState) TroubleshootingMenu(state = state.debugMenu)
} }
}, },
) )
@ -224,7 +190,6 @@ private fun AddIcon(enabled: Boolean) {
} }
} }
@Suppress("UnusedPrivateMember")
@PreviewScreens @PreviewScreens
@Composable @Composable
private fun PreviewSettings() { private fun PreviewSettings() {
@ -234,25 +199,43 @@ private fun PreviewSettings() {
SettingsState( SettingsState(
isLoading = false, isLoading = false,
version = stringRes("Version 1.2"), version = stringRes("Version 1.2"),
settingsTroubleshootingState = null, debugMenu = null,
onBack = {}, onBack = {},
onAdvancedSettingsClick = {}, items =
onAboutUsClick = {}, persistentListOf(
onSendUsFeedbackClick = {}, ZashiSettingsListItemState(
onAddressBookClick = {}, text = stringRes(R.string.settings_address_book),
integrations = icon = R.drawable.ic_settings_address_book,
ZashiSettingsListItemState( onClick = { },
icon = R.drawable.ic_settings_integrations, ),
text = stringRes("Integrations"), ZashiSettingsListItemState(
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase) text = stringRes(R.string.settings_integrations),
) {} icon = R.drawable.ic_settings_integrations,
onClick = { },
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase)
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_advanced_settings),
icon = R.drawable.ic_advanced_settings,
onClick = { },
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_about_us),
icon = R.drawable.ic_settings_info,
onClick = { },
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_feedback),
icon = R.drawable.ic_settings_feedback,
onClick = { },
),
),
), ),
topAppBarSubTitleState = TopAppBarSubTitleState.None, topAppBarSubTitleState = TopAppBarSubTitleState.None,
) )
} }
} }
@Suppress("UnusedPrivateMember")
@PreviewScreens @PreviewScreens
@Composable @Composable
private fun PreviewSettingsLoading() { private fun PreviewSettingsLoading() {
@ -262,18 +245,37 @@ private fun PreviewSettingsLoading() {
SettingsState( SettingsState(
isLoading = true, isLoading = true,
version = stringRes("Version 1.2"), version = stringRes("Version 1.2"),
settingsTroubleshootingState = null, debugMenu = null,
onBack = {}, onBack = {},
onAdvancedSettingsClick = {}, items =
onAboutUsClick = {}, persistentListOf(
onSendUsFeedbackClick = {}, ZashiSettingsListItemState(
onAddressBookClick = {}, text = stringRes(R.string.settings_address_book),
integrations = icon = R.drawable.ic_settings_address_book,
ZashiSettingsListItemState( onClick = { },
icon = R.drawable.ic_settings_integrations, ),
text = stringRes("Integrations"), ZashiSettingsListItemState(
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase) text = stringRes(R.string.settings_integrations),
) {} icon = R.drawable.ic_settings_integrations,
onClick = { },
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase)
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_advanced_settings),
icon = R.drawable.ic_advanced_settings,
onClick = { },
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_about_us),
icon = R.drawable.ic_settings_info,
onClick = { },
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_feedback),
icon = R.drawable.ic_settings_feedback,
onClick = { },
),
),
), ),
topAppBarSubTitleState = TopAppBarSubTitleState.None, topAppBarSubTitleState = TopAppBarSubTitleState.None,
) )

View File

@ -99,20 +99,38 @@ class SettingsViewModel(
combine(isLoading, troubleshootingState) { isLoading, troubleshootingState -> combine(isLoading, troubleshootingState) { isLoading, troubleshootingState ->
SettingsState( SettingsState(
isLoading = isLoading, isLoading = isLoading,
version = stringRes(R.string.settings_version, versionInfo.versionName), debugMenu = troubleshootingState,
settingsTroubleshootingState = troubleshootingState,
onBack = ::onBack, onBack = ::onBack,
integrations = items =
ZashiSettingsListItemState( persistentListOf(
text = stringRes(R.string.settings_integrations), ZashiSettingsListItemState(
icon = R.drawable.ic_settings_integrations, text = stringRes(R.string.settings_address_book),
onClick = ::onIntegrationsClick, icon = R.drawable.ic_settings_address_book,
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase) onClick = ::onAddressBookClick
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_integrations),
icon = R.drawable.ic_settings_integrations,
onClick = ::onIntegrationsClick,
titleIcons = persistentListOf(R.drawable.ic_integrations_coinbase)
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_advanced_settings),
icon = R.drawable.ic_advanced_settings,
onClick = ::onAdvancedSettingsClick
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_about_us),
icon = R.drawable.ic_settings_info,
onClick = ::onAboutUsClick
),
ZashiSettingsListItemState(
text = stringRes(R.string.settings_feedback),
icon = R.drawable.ic_settings_feedback,
onClick = ::onSendUsFeedbackClick
),
), ),
onAdvancedSettingsClick = ::onAdvancedSettingsClick, version = stringRes(R.string.settings_version, versionInfo.versionName)
onAboutUsClick = ::onAboutUsClick,
onSendUsFeedbackClick = ::onSendUsFeedbackClick,
onAddressBookClick = ::onAddressBookClick
) )
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), null) }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT), null)