Home messages business logic, wallet info removed from status bar and general refactoring
This commit is contained in:
parent
2f12bea435
commit
d6d500eaed
|
@ -29,5 +29,7 @@ interface PreferenceProvider {
|
|||
|
||||
fun observe(key: PreferenceKey): Flow<String?>
|
||||
|
||||
suspend fun remove(key: PreferenceKey)
|
||||
|
||||
suspend fun clearPreferences(): Boolean
|
||||
}
|
||||
|
|
|
@ -22,6 +22,6 @@ data class NullableBooleanPreferenceDefault(
|
|||
preferenceProvider: PreferenceProvider,
|
||||
newValue: Boolean?
|
||||
) {
|
||||
preferenceProvider.putString(key, newValue.toString())
|
||||
preferenceProvider.putString(key, newValue?.toString())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
package co.electriccoin.zcash.preference.model.entry
|
||||
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import java.time.Instant
|
||||
|
||||
class TimestampPreferenceDefault(override val key: PreferenceKey): PreferenceDefault<Instant?> {
|
||||
override suspend fun getValue(preferenceProvider: PreferenceProvider) =
|
||||
preferenceProvider.getLong(key)?.let { Instant.ofEpochMilli(it) }
|
||||
|
||||
override suspend fun putValue(
|
||||
preferenceProvider: PreferenceProvider,
|
||||
newValue: Instant?
|
||||
) = preferenceProvider.putLong(key, newValue?.toEpochMilli())
|
||||
}
|
|
@ -22,6 +22,10 @@ class MockPreferenceProvider(
|
|||
// For the mock implementation, does not support observability of changes
|
||||
override fun observe(key: PreferenceKey): Flow<String?> = flow { emit(getString(key)) }
|
||||
|
||||
override suspend fun remove(key: PreferenceKey) {
|
||||
map.remove(key.key)
|
||||
}
|
||||
|
||||
override suspend fun clearPreferences(): Boolean {
|
||||
map.clear()
|
||||
return true
|
||||
|
|
|
@ -140,6 +140,17 @@ class AndroidPreferenceProvider private constructor(
|
|||
}.flowOn(dispatcher)
|
||||
.map { getString(key) }
|
||||
|
||||
@SuppressLint("ApplySharedPref")
|
||||
override suspend fun remove(key: PreferenceKey) {
|
||||
withContext(dispatcher) {
|
||||
val editor = sharedPreferences.edit()
|
||||
|
||||
editor.remove(key.key)
|
||||
|
||||
editor.commit()
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
suspend fun newStandard(
|
||||
context: Context,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package co.electriccoin.zcash.ui.design.component
|
||||
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||
|
@ -36,8 +35,8 @@ fun ZashiCircularProgressIndicator(
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun ZashiCircularProgressIndicator(
|
||||
@IntRange(from = 0, to = 100) progressPercent: Int,
|
||||
fun ZashiCircularProgressIndicatorByPercent(
|
||||
progressPercent: Float,
|
||||
modifier: Modifier = Modifier,
|
||||
colors: ZashiCircularProgressIndicatorColors =
|
||||
LocalZashiCircularProgressIndicatorColors.current
|
||||
|
|
|
@ -28,8 +28,7 @@ val DarkZashiColorsInternal =
|
|||
textError = ErrorRed.`300`,
|
||||
textLink = HyperBlue.`300`,
|
||||
textLight = Shark.`50`,
|
||||
textLightSupport = Shark.`200`,
|
||||
textOpposite = Base.Bone
|
||||
textLightSupport = Shark.`200`
|
||||
),
|
||||
Btns =
|
||||
Btns(
|
||||
|
|
|
@ -28,8 +28,7 @@ val LightZashiColorsInternal =
|
|||
textError = ErrorRed.`500`,
|
||||
textLink = HyperBlue.`500`,
|
||||
textLight = Gray.`25`,
|
||||
textLightSupport = Gray.`200`,
|
||||
textOpposite = Base.Bone
|
||||
textLightSupport = Gray.`200`
|
||||
),
|
||||
Btns =
|
||||
Btns(
|
||||
|
|
|
@ -145,7 +145,7 @@ internal object Indigo {
|
|||
val `950` = Color(0xFF1F235B)
|
||||
}
|
||||
|
||||
object Purple {
|
||||
internal object Purple {
|
||||
val `25` = Color(0xFFFAFAFF)
|
||||
val `50` = Color(0xFFF4F3FF)
|
||||
val `100` = Color(0xFFEBE9FE)
|
||||
|
|
|
@ -56,8 +56,7 @@ data class Text(
|
|||
val textError: Color,
|
||||
val textLink: Color,
|
||||
val textLight: Color,
|
||||
val textLightSupport: Color,
|
||||
val textOpposite: Color
|
||||
val textLightSupport: Color
|
||||
)
|
||||
|
||||
@Immutable
|
||||
|
|
|
@ -3,7 +3,6 @@ package co.electriccoin.zcash.ui.integration.test.screen.scan.view
|
|||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.integration.test.common.getPermissionNegativeButtonUiObject
|
||||
import co.electriccoin.zcash.ui.integration.test.common.getPermissionPositiveButtonUiObject
|
||||
|
@ -60,7 +59,6 @@ class ScanViewTestSetup(
|
|||
onScanStateChange = {
|
||||
scanState.set(it)
|
||||
},
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
validationResult = ScanValidationState.VALID
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package co.electriccoin.zcash.ui.screen.about.view
|
|||
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||
|
@ -28,7 +27,6 @@ class AboutViewTestSetup(
|
|||
configInfo = configInfo,
|
||||
onPrivacyPolicy = {},
|
||||
snackbarHostState = SnackbarHostState(),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
versionInfo = versionInfo,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ package co.electriccoin.zcash.ui.screen.exportdata.view
|
|||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
@ -46,7 +45,6 @@ class ExportPrivateDataViewTestSetup(
|
|||
onConfirm = {
|
||||
onConfirmCount.incrementAndGet()
|
||||
},
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package co.electriccoin.zcash.ui.screen.scan.view
|
|||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.scan.model.ScanScreenState
|
||||
import co.electriccoin.zcash.ui.screen.scan.model.ScanValidationState
|
||||
|
@ -30,7 +29,7 @@ class ScanViewBasicTestSetup(
|
|||
@Suppress("TestFunctionName")
|
||||
fun DefaultContent() {
|
||||
Scan(
|
||||
validationResult = ScanValidationState.VALID,
|
||||
snackbarHostState = SnackbarHostState(),
|
||||
onBack = {
|
||||
onBackCount.incrementAndGet()
|
||||
},
|
||||
|
@ -40,8 +39,7 @@ class ScanViewBasicTestSetup(
|
|||
onScanStateChange = {
|
||||
scanState.set(it)
|
||||
},
|
||||
snackbarHostState = SnackbarHostState(),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
validationResult = ScanValidationState.VALID,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package co.electriccoin.zcash.ui.screen.settings
|
|||
|
||||
import androidx.compose.ui.test.junit4.ComposeContentTestRule
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.listitem.ZashiListItemState
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
@ -149,7 +148,6 @@ class SettingsViewTestSetup(
|
|||
),
|
||||
)
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ import co.electriccoin.zcash.ui.common.datasource.ProposalDataSource
|
|||
import co.electriccoin.zcash.ui.common.datasource.ProposalDataSourceImpl
|
||||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSourceImpl
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSourceImpl
|
||||
import co.electriccoin.zcash.ui.common.datasource.ZashiSpendingKeyDataSource
|
||||
import co.electriccoin.zcash.ui.common.datasource.ZashiSpendingKeyDataSourceImpl
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
|
@ -18,4 +20,5 @@ val dataSourceModule =
|
|||
singleOf(::ZashiSpendingKeyDataSourceImpl) bind ZashiSpendingKeyDataSource::class
|
||||
singleOf(::ProposalDataSourceImpl) bind ProposalDataSource::class
|
||||
singleOf(::RestoreTimestampDataSourceImpl) bind RestoreTimestampDataSource::class
|
||||
singleOf(::WalletBackupDataSourceImpl) bind WalletBackupDataSource::class
|
||||
}
|
||||
|
|
|
@ -12,8 +12,18 @@ import co.electriccoin.zcash.ui.common.provider.RestoreTimestampStorageProvider
|
|||
import co.electriccoin.zcash.ui.common.provider.RestoreTimestampStorageProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.SelectedAccountUUIDProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.SelectedAccountUUIDProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeCountStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeCountStorageProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeTimestampStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeTimestampStorageProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupFlagStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupFlagStorageProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeCountStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeCountStorageProviderImpl
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeTimestampStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeTimestampStorageProviderImpl
|
||||
import org.koin.core.module.dsl.factoryOf
|
||||
import org.koin.core.module.dsl.singleOf
|
||||
import org.koin.dsl.bind
|
||||
|
@ -30,4 +40,13 @@ val providerModule =
|
|||
singleOf(::SynchronizerProviderImpl) bind SynchronizerProvider::class
|
||||
singleOf(::ApplicationStateProviderImpl) bind ApplicationStateProvider::class
|
||||
factoryOf(::RestoreTimestampStorageProviderImpl) bind RestoreTimestampStorageProvider::class
|
||||
factoryOf(::ShieldFundsRemindMeCountStorageProviderImpl) bind
|
||||
ShieldFundsRemindMeCountStorageProvider::class
|
||||
factoryOf(::ShieldFundsRemindMeTimestampStorageProviderImpl) bind
|
||||
ShieldFundsRemindMeTimestampStorageProvider::class
|
||||
factoryOf(::WalletBackupRemindMeCountStorageProviderImpl) bind
|
||||
WalletBackupRemindMeCountStorageProvider::class
|
||||
factoryOf(::WalletBackupRemindMeTimestampStorageProviderImpl) bind
|
||||
WalletBackupRemindMeTimestampStorageProvider::class
|
||||
factoryOf(::WalletBackupFlagStorageProviderImpl) bind WalletBackupFlagStorageProvider::class
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import co.electriccoin.zcash.ui.common.usecase.GetCurrentFilteredTransactionsUse
|
|||
import co.electriccoin.zcash.ui.common.usecase.GetCurrentTransactionsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetExchangeRateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetFlexaStatusUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetHomeMessageUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetKeystoneStatusUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetMetadataUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetPersistableWalletUseCase
|
||||
|
@ -37,7 +38,6 @@ import co.electriccoin.zcash.ui.common.usecase.GetTransactionMetadataUseCase
|
|||
import co.electriccoin.zcash.ui.common.usecase.GetTransparentAddressUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletAccountsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletStateInformationUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetZashiAccountUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetZashiSpendingKeyUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.IsCoinbaseAvailableUseCase
|
||||
|
@ -46,7 +46,7 @@ import co.electriccoin.zcash.ui.common.usecase.IsRestoreSuccessDialogVisibleUseC
|
|||
import co.electriccoin.zcash.ui.common.usecase.MarkTxMemoAsReadUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToAddressBookUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToCoinbaseUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToSeedRecoveryUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToTaxExportUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ObserveAddressBookContactsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ObserveClearSendUseCase
|
||||
|
@ -62,6 +62,7 @@ import co.electriccoin.zcash.ui.common.usecase.ObserveSynchronizerUseCase
|
|||
import co.electriccoin.zcash.ui.common.usecase.ObserveTransactionSubmitStateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ObserveZashiAccountUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.OnAddressScannedUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.OnUserSavedWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.OnZip321ScannedUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ParseKeystonePCZTUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ParseKeystoneSignInRequestUseCase
|
||||
|
@ -69,6 +70,7 @@ import co.electriccoin.zcash.ui.common.usecase.ParseKeystoneUrToZashiAccountsUse
|
|||
import co.electriccoin.zcash.ui.common.usecase.PersistEndpointUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.PrefillSendUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.RefreshFastestServersUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.RemindWalletBackupLaterUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.RescanBlockchainUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ResetInMemoryDataUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.ResetSharedPrefsDataUseCase
|
||||
|
@ -122,7 +124,6 @@ val useCaseModule =
|
|||
factoryOf(::ShareImageUseCase)
|
||||
factoryOf(::Zip321BuildUriUseCase)
|
||||
factoryOf(::Zip321ParseUriValidationUseCase)
|
||||
factoryOf(::GetWalletStateInformationUseCase)
|
||||
factoryOf(::IsCoinbaseAvailableUseCase)
|
||||
factoryOf(::GetZashiSpendingKeyUseCase)
|
||||
factoryOf(::ObservePersistableWalletUseCase)
|
||||
|
@ -184,8 +185,11 @@ val useCaseModule =
|
|||
factoryOf(::IsRestoreSuccessDialogVisibleUseCase)
|
||||
factoryOf(::ValidateSeedUseCase)
|
||||
factoryOf(::RestoreWalletUseCase)
|
||||
factoryOf(::NavigateToSeedRecoveryUseCase)
|
||||
factoryOf(::NavigateToWalletBackupUseCase)
|
||||
factoryOf(::GetKeystoneStatusUseCase)
|
||||
factoryOf(::GetCoinbaseStatusUseCase)
|
||||
factoryOf(::GetFlexaStatusUseCase)
|
||||
factoryOf(::GetHomeMessageUseCase)
|
||||
factoryOf(::OnUserSavedWalletBackupUseCase)
|
||||
factoryOf(::RemindWalletBackupLaterUseCase)
|
||||
}
|
||||
|
|
|
@ -12,10 +12,14 @@ import co.electriccoin.zcash.ui.screen.balances.BalanceViewModel
|
|||
import co.electriccoin.zcash.ui.screen.chooseserver.ChooseServerViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.AddContactViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.UpdateContactViewModel
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptInViewModel
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.settings.ExchangeRateSettingsViewModel
|
||||
import co.electriccoin.zcash.ui.screen.feedback.viewmodel.FeedbackViewModel
|
||||
import co.electriccoin.zcash.ui.screen.flexa.FlexaViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupDetailViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceInfoViewModel
|
||||
import co.electriccoin.zcash.ui.screen.integrations.IntegrationsViewModel
|
||||
import co.electriccoin.zcash.ui.screen.qrcode.viewmodel.QrCodeViewModel
|
||||
import co.electriccoin.zcash.ui.screen.receive.viewmodel.ReceiveViewModel
|
||||
|
@ -24,13 +28,13 @@ import co.electriccoin.zcash.ui.screen.restore.date.RestoreBDDateViewModel
|
|||
import co.electriccoin.zcash.ui.screen.restore.estimation.RestoreBDEstimationViewModel
|
||||
import co.electriccoin.zcash.ui.screen.restore.height.RestoreBDHeightViewModel
|
||||
import co.electriccoin.zcash.ui.screen.restore.seed.RestoreSeedViewModel
|
||||
import co.electriccoin.zcash.ui.screen.restoresuccess.viewmodel.RestoreSuccessViewModel
|
||||
import co.electriccoin.zcash.ui.screen.restoresuccess.RestoreSuccessViewModel
|
||||
import co.electriccoin.zcash.ui.screen.reviewtransaction.ReviewTransactionViewModel
|
||||
import co.electriccoin.zcash.ui.screen.scan.Scan
|
||||
import co.electriccoin.zcash.ui.screen.scan.viewmodel.ScanViewModel
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.viewmodel.ScanKeystonePCZTViewModel
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.viewmodel.ScanKeystoneSignInRequestViewModel
|
||||
import co.electriccoin.zcash.ui.screen.seed.SeedRecoveryViewModel
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackupViewModel
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.SelectKeystoneAccount
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.viewmodel.SelectKeystoneAccountViewModel
|
||||
import co.electriccoin.zcash.ui.screen.send.SendViewModel
|
||||
|
@ -96,7 +100,7 @@ val viewModelModule =
|
|||
viewModelOf(::IntegrationsViewModel)
|
||||
viewModelOf(::FlexaViewModel)
|
||||
viewModelOf(::SendViewModel)
|
||||
viewModelOf(::SeedRecoveryViewModel)
|
||||
viewModelOf(::WalletBackupViewModel)
|
||||
viewModelOf(::FeedbackViewModel)
|
||||
viewModelOf(::SignKeystoneTransactionViewModel)
|
||||
viewModelOf(::AccountListViewModel)
|
||||
|
@ -144,4 +148,8 @@ val viewModelModule =
|
|||
viewModelOf(::RestoreBDDateViewModel)
|
||||
viewModelOf(::RestoreBDEstimationViewModel)
|
||||
viewModelOf(::TransparentBalanceInfoViewModel)
|
||||
viewModelOf(::WalletBackupInfoViewModel)
|
||||
viewModelOf(::ExchangeRateOptInViewModel)
|
||||
viewModelOf(::ExchangeRateSettingsViewModel)
|
||||
viewModelOf(::WalletBackupDetailViewModel)
|
||||
}
|
||||
|
|
|
@ -67,19 +67,19 @@ import co.electriccoin.zcash.ui.screen.exportdata.WrapExportPrivateData
|
|||
import co.electriccoin.zcash.ui.screen.feedback.WrapFeedback
|
||||
import co.electriccoin.zcash.ui.screen.flexa.FlexaViewModel
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidHome
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidSeedBackupInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidWalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidWalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidWalletSyncingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.AndroidWalletUpdatingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.AndroidWalletBackupInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.AndroidWalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.AndroidWalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.AndroidWalletSyncingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.AndroidWalletUpdatingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.Home
|
||||
import co.electriccoin.zcash.ui.screen.home.SeedBackupInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.WalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.WalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.WalletSyncingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.WalletUpdatingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.balance.AndroidTransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.SeedBackupInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.AndroidTransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.integrations.AndroidDialogIntegrations
|
||||
import co.electriccoin.zcash.ui.screen.integrations.AndroidIntegrations
|
||||
import co.electriccoin.zcash.ui.screen.integrations.DialogIntegrations
|
||||
|
@ -99,10 +99,10 @@ import co.electriccoin.zcash.ui.screen.scankeystone.ScanKeystonePCZTRequest
|
|||
import co.electriccoin.zcash.ui.screen.scankeystone.ScanKeystoneSignInRequest
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.WrapScanKeystonePCZTRequest
|
||||
import co.electriccoin.zcash.ui.screen.scankeystone.WrapScanKeystoneSignInRequest
|
||||
import co.electriccoin.zcash.ui.screen.seed.AndroidSeedRecovery
|
||||
import co.electriccoin.zcash.ui.screen.seed.SeedRecovery
|
||||
import co.electriccoin.zcash.ui.screen.seed.backup.AndroidSeedBackup
|
||||
import co.electriccoin.zcash.ui.screen.seed.backup.SeedBackup
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.AndroidWalletBackup
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackup
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.AndroidWalletBackupDetail
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupDetail
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.AndroidSelectKeystoneAccount
|
||||
import co.electriccoin.zcash.ui.screen.selectkeystoneaccount.SelectKeystoneAccount
|
||||
import co.electriccoin.zcash.ui.screen.send.Send
|
||||
|
@ -227,8 +227,8 @@ internal fun MainActivity.Navigation() {
|
|||
composable(CHOOSE_SERVER) {
|
||||
WrapChooseServer()
|
||||
}
|
||||
composable<SeedRecovery> {
|
||||
AndroidSeedRecovery()
|
||||
composable<WalletBackup> {
|
||||
AndroidWalletBackup(it.toRoute())
|
||||
}
|
||||
composable(SUPPORT) {
|
||||
// Pop back stack won't be right if we deep link into support
|
||||
|
@ -410,8 +410,8 @@ internal fun MainActivity.Navigation() {
|
|||
) {
|
||||
AndroidSeedInfo()
|
||||
}
|
||||
composable<SeedBackup> {
|
||||
AndroidSeedBackup(it.toRoute())
|
||||
composable<WalletBackupDetail> {
|
||||
AndroidWalletBackupDetail(it.toRoute())
|
||||
}
|
||||
dialog<SeedBackupInfo>(
|
||||
dialogProperties =
|
||||
|
@ -420,7 +420,7 @@ internal fun MainActivity.Navigation() {
|
|||
dismissOnClickOutside = false
|
||||
)
|
||||
) {
|
||||
AndroidSeedBackupInfo()
|
||||
AndroidWalletBackupInfo()
|
||||
}
|
||||
dialog<TransparentBalanceInfo>(
|
||||
dialogProperties =
|
||||
|
|
|
@ -8,12 +8,10 @@ import co.electriccoin.zcash.preference.model.entry.BooleanPreferenceDefault
|
|||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.NavigationTargets.SETTINGS
|
||||
import co.electriccoin.zcash.ui.common.model.KeystoneAccount
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletAccount
|
||||
import co.electriccoin.zcash.ui.common.model.ZashiAccount
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSelectedWalletAccountUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletAccountsUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletStateInformationUseCase
|
||||
import co.electriccoin.zcash.ui.design.R
|
||||
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
@ -33,7 +31,6 @@ import kotlinx.coroutines.launch
|
|||
class ZashiTopAppBarViewModel(
|
||||
getWalletAccountUseCase: GetWalletAccountsUseCase,
|
||||
getSelectedWalletAccount: GetSelectedWalletAccountUseCase,
|
||||
getWalletStateInformation: GetWalletStateInformationUseCase,
|
||||
private val standardPreferenceProvider: StandardPreferenceProvider,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
) : ViewModel() {
|
||||
|
@ -43,24 +40,21 @@ class ZashiTopAppBarViewModel(
|
|||
combine(
|
||||
getSelectedWalletAccount.observe().filterNotNull(),
|
||||
isHideBalances,
|
||||
getWalletStateInformation.observe()
|
||||
) { currentAccount, isHideBalances, walletState ->
|
||||
createState(currentAccount, isHideBalances, walletState)
|
||||
) { currentAccount, isHideBalances ->
|
||||
createState(currentAccount, isHideBalances)
|
||||
}.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue =
|
||||
createState(
|
||||
currentAccount = getWalletAccountUseCase.observe().value?.firstOrNull { it.isSelected },
|
||||
isHideBalances = isHideBalances.value,
|
||||
topAppBarSubTitleState = getWalletStateInformation.observe().value
|
||||
isHideBalances = isHideBalances.value
|
||||
)
|
||||
)
|
||||
|
||||
private fun createState(
|
||||
currentAccount: WalletAccount?,
|
||||
isHideBalances: Boolean?,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState
|
||||
isHideBalances: Boolean?
|
||||
) = ZashiMainTopAppBarState(
|
||||
accountSwitchState =
|
||||
AccountSwitchState(
|
||||
|
@ -88,19 +82,7 @@ class ZashiTopAppBarViewModel(
|
|||
icon = R.drawable.ic_app_bar_settings,
|
||||
onClick = ::onSettingsClicked,
|
||||
contentDescription = stringRes(co.electriccoin.zcash.ui.R.string.settings_menu_content_description)
|
||||
),
|
||||
subtitle =
|
||||
when (topAppBarSubTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected ->
|
||||
stringRes(
|
||||
co.electriccoin.zcash.ui.R.string.disconnected_label_new,
|
||||
)
|
||||
TopAppBarSubTitleState.Restoring ->
|
||||
stringRes(
|
||||
co.electriccoin.zcash.ui.R.string.restoring_wallet_label_new,
|
||||
)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
private fun onAccountTypeClicked() = navigationRouter.forward(AccountList)
|
||||
|
|
|
@ -15,14 +15,12 @@ import androidx.compose.foundation.layout.size
|
|||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.common.appbar.ZashiMainTopAppBarState.AccountType
|
||||
import co.electriccoin.zcash.ui.design.R
|
||||
|
@ -32,10 +30,6 @@ import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
|
|||
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.theme.typography.ZashiTypography
|
||||
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 ZashiTopAppBarWithAccountSelection(
|
||||
|
@ -61,16 +55,6 @@ fun ZashiTopAppBarWithAccountSelection(
|
|||
AccountSwitch(state.accountSwitchState)
|
||||
},
|
||||
)
|
||||
|
||||
if (state.subtitle != null) {
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.BottomCenter),
|
||||
text = state.subtitle.getValue().uppercase(),
|
||||
style = ZashiTypography.textXs,
|
||||
fontWeight = FontWeight.Normal,
|
||||
color = ZashiColors.Text.textQuaternary
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,13 +112,9 @@ private fun AccountSwitch(state: AccountSwitchState) {
|
|||
data class ZashiMainTopAppBarState(
|
||||
val accountSwitchState: AccountSwitchState,
|
||||
val balanceVisibilityButton: IconButtonState,
|
||||
val settingsButton: IconButtonState,
|
||||
val subtitle: StringResource?
|
||||
val settingsButton: IconButtonState
|
||||
) {
|
||||
enum class AccountType {
|
||||
ZASHI,
|
||||
KEYSTONE
|
||||
}
|
||||
enum class AccountType { ZASHI, KEYSTONE }
|
||||
}
|
||||
|
||||
data class AccountSwitchState(
|
||||
|
@ -155,8 +135,7 @@ private fun ZashiMainTopAppBarPreview() =
|
|||
onAccountTypeClick = {}
|
||||
),
|
||||
balanceVisibilityButton = IconButtonState(R.drawable.ic_app_bar_balances_hide) {},
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {},
|
||||
subtitle = null
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -174,8 +153,7 @@ private fun KeystoneMainTopAppBarPreview() =
|
|||
onAccountTypeClick = {},
|
||||
),
|
||||
balanceVisibilityButton = IconButtonState(R.drawable.ic_app_bar_balances_hide) {},
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {},
|
||||
subtitle = null
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -193,8 +171,7 @@ private fun MainTopAppBarWithSubtitlePreview() =
|
|||
onAccountTypeClick = {},
|
||||
),
|
||||
balanceVisibilityButton = IconButtonState(R.drawable.ic_app_bar_balances_hide) {},
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {},
|
||||
subtitle = stringRes("Subtitle")
|
||||
settingsButton = IconButtonState(R.drawable.ic_app_bar_settings) {}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ fun ZashiTopAppbar(
|
|||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = title?.getValue(),
|
||||
subtitle = state?.subtitle?.getValue(),
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(
|
||||
onBack = onBack,
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package co.electriccoin.zcash.ui.common.datasource
|
||||
|
||||
import cash.z.ecc.android.sdk.model.AccountUuid
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeCountStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.ShieldFundsRemindMeTimestampStorageProvider
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.days
|
||||
|
||||
interface ShieldFundsRemindMeDataSource {
|
||||
suspend fun observe(forAccount: AccountUuid): Flow<ShieldFundsAvailability>
|
||||
}
|
||||
|
||||
class ShieldFundsRemindMeDataSourceImpl(
|
||||
private val shieldFundsRemindMeCountStorageProvider: ShieldFundsRemindMeCountStorageProvider,
|
||||
private val shieldFundsRemindMeTimestampStorageProvider: ShieldFundsRemindMeTimestampStorageProvider
|
||||
): ShieldFundsRemindMeDataSource {
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<ShieldFundsAvailability> = combine(
|
||||
shieldFundsRemindMeCountStorageProvider.observe(forAccount),
|
||||
shieldFundsRemindMeTimestampStorageProvider.observe(forAccount)
|
||||
) { count, timestamp ->
|
||||
when {
|
||||
timestamp == null -> ShieldFundsAvailability.Available(1.days)
|
||||
count == 1 -> ShieldFundsAvailability.Available(2.days)
|
||||
count == 2 -> ShieldFundsAvailability.Available(3.days)
|
||||
else -> ShieldFundsAvailability.Unavailable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface ShieldFundsAvailability {
|
||||
data class Available(val nextLockoutDuration: Duration) : ShieldFundsAvailability
|
||||
data object Unavailable : ShieldFundsAvailability
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package co.electriccoin.zcash.ui.common.datasource
|
||||
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupFlagStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeCountStorageProvider
|
||||
import co.electriccoin.zcash.ui.common.provider.WalletBackupRemindMeTimestampStorageProvider
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import java.time.Instant
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface WalletBackupDataSource {
|
||||
fun observe(): Flow<WalletBackupAvailability>
|
||||
|
||||
suspend fun onUserSavedWalletBackup()
|
||||
|
||||
suspend fun remindMeLater()
|
||||
}
|
||||
|
||||
class WalletBackupDataSourceImpl(
|
||||
private val walletBackupFlagStorageProvider: WalletBackupFlagStorageProvider,
|
||||
private val walletBackupRemindMeCountStorageProvider: WalletBackupRemindMeCountStorageProvider,
|
||||
private val walletBackupRemindMeTimestampStorageProvider: WalletBackupRemindMeTimestampStorageProvider
|
||||
) : WalletBackupDataSource {
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override fun observe(): Flow<WalletBackupAvailability> = combine(
|
||||
walletBackupFlagStorageProvider.observe(),
|
||||
walletBackupRemindMeCountStorageProvider.observe(),
|
||||
walletBackupRemindMeTimestampStorageProvider.observe()
|
||||
) { isBackedUp, count, timestamp ->
|
||||
Triple(isBackedUp, count, timestamp)
|
||||
}.flatMapLatest { (isBackedUp, count, timestamp) ->
|
||||
when {
|
||||
isBackedUp -> flowOf(WalletBackupAvailability.Unavailable)
|
||||
timestamp == null -> flowOf(WalletBackupAvailability.Available(WalletBackupLockoutDuration.ONE_DAY))
|
||||
count == 1 -> calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = WalletBackupLockoutDuration.ONE_DAY,
|
||||
nextLockoutDuration = WalletBackupLockoutDuration.TWO_DAYS
|
||||
)
|
||||
|
||||
else -> calculateNext(
|
||||
lastTimestamp = timestamp,
|
||||
lastLockoutDuration = if (count == 2) {
|
||||
WalletBackupLockoutDuration.TWO_DAYS
|
||||
} else {
|
||||
WalletBackupLockoutDuration.THREE_DAYS
|
||||
},
|
||||
nextLockoutDuration = WalletBackupLockoutDuration.THREE_DAYS
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onUserSavedWalletBackup() {
|
||||
walletBackupFlagStorageProvider.store(true)
|
||||
}
|
||||
|
||||
override suspend fun remindMeLater() {
|
||||
val count = walletBackupRemindMeCountStorageProvider.get()
|
||||
val timestamp = Instant.now()
|
||||
walletBackupRemindMeCountStorageProvider.store(count + 1)
|
||||
walletBackupRemindMeTimestampStorageProvider.store(timestamp)
|
||||
}
|
||||
|
||||
private fun calculateNext(
|
||||
lastTimestamp: Instant,
|
||||
lastLockoutDuration: WalletBackupLockoutDuration,
|
||||
nextLockoutDuration: WalletBackupLockoutDuration
|
||||
): Flow<WalletBackupAvailability> {
|
||||
val nextAvailableTimestamp = lastTimestamp.plusMillis(lastLockoutDuration.duration.inWholeMilliseconds)
|
||||
val now = Instant.now()
|
||||
return if (nextAvailableTimestamp > now) {
|
||||
flow {
|
||||
val remaining = nextAvailableTimestamp.toEpochMilli() - now.toEpochMilli()
|
||||
emit(WalletBackupAvailability.Unavailable)
|
||||
delay(remaining)
|
||||
emit(WalletBackupAvailability.Available(nextLockoutDuration))
|
||||
}
|
||||
} else {
|
||||
flowOf(WalletBackupAvailability.Available(nextLockoutDuration))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface WalletBackupAvailability {
|
||||
data class Available(val lockoutDuration: WalletBackupLockoutDuration) : WalletBackupAvailability
|
||||
data object Unavailable : WalletBackupAvailability
|
||||
}
|
||||
|
||||
enum class WalletBackupLockoutDuration(val duration: Duration) {
|
||||
ONE_DAY(10.seconds),
|
||||
TWO_DAYS(20.seconds),
|
||||
THREE_DAYS(30.seconds)
|
||||
}
|
|
@ -19,16 +19,3 @@ data class WalletSnapshot(
|
|||
val progress: PercentDecimal,
|
||||
val synchronizerError: SynchronizerError?
|
||||
)
|
||||
|
||||
// TODO [#1370]: WalletSnapshot.canSpend() calculation limitation
|
||||
// TODO [#1370]: https://github.com/Electric-Coin-Company/zashi-android/issues/1370
|
||||
// Note this check is not entirely correct - it does not calculate the resulting fee using the new Proposal API. It's
|
||||
// fine for now, but it's subject to improvement later once we figure out how to handle it in such cases.
|
||||
fun WalletSnapshot.canSpend(amount: Zatoshi): Boolean = spendableBalance() >= amount
|
||||
|
||||
fun WalletSnapshot.totalBalance() = orchardBalance.total + (saplingBalance?.total ?: Zatoshi(0)) + transparentBalance
|
||||
|
||||
// Note that considering both to be spendable is subject to change.
|
||||
// The user experience could be confusing, and in the future we might prefer to ask users
|
||||
// to transfer their balance to the latest balance type to make it spendable.
|
||||
fun WalletSnapshot.spendableBalance() = orchardBalance.available + (saplingBalance?.available ?: Zatoshi(0))
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.PreferenceHolder
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.BooleanPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
interface BooleanStorageProvider {
|
||||
suspend fun get(): Boolean
|
||||
|
||||
suspend fun store(flag: Boolean)
|
||||
|
||||
fun observe(): Flow<Boolean>
|
||||
|
||||
suspend fun clear()
|
||||
}
|
||||
|
||||
abstract class BaseBooleanStorageProvider(key: PreferenceKey) : BooleanStorageProvider {
|
||||
protected abstract val preferenceHolder: PreferenceHolder
|
||||
|
||||
private val default = BooleanPreferenceDefault(key = key, defaultValue = DEFAULT)
|
||||
|
||||
private suspend fun getPreferenceProvider(): PreferenceProvider = preferenceHolder()
|
||||
|
||||
override suspend fun get(): Boolean = default.getValue(getPreferenceProvider())
|
||||
|
||||
override suspend fun store(flag: Boolean) = default.putValue(getPreferenceProvider(), flag)
|
||||
|
||||
override fun observe(): Flow<Boolean> = flow { emitAll(default.observe(getPreferenceProvider())) }
|
||||
|
||||
override suspend fun clear() = default.putValue(getPreferenceProvider(), DEFAULT)
|
||||
}
|
||||
|
||||
private const val DEFAULT = false
|
|
@ -0,0 +1,37 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.PreferenceHolder
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
interface IntStorageProvider {
|
||||
suspend fun get(): Int
|
||||
|
||||
suspend fun store(amount: Int)
|
||||
|
||||
fun observe(): Flow<Int>
|
||||
|
||||
suspend fun clear()
|
||||
}
|
||||
|
||||
abstract class BaseIntStorageProvider(key: PreferenceKey) : IntStorageProvider {
|
||||
protected abstract val preferenceHolder: PreferenceHolder
|
||||
|
||||
private val default = IntegerPreferenceDefault(key = key, defaultValue = DEFAULT)
|
||||
|
||||
private suspend fun getPreferenceProvider(): PreferenceProvider = preferenceHolder()
|
||||
|
||||
override suspend fun get(): Int = default.getValue(getPreferenceProvider())
|
||||
|
||||
override suspend fun store(amount: Int) = default.putValue(getPreferenceProvider(), amount)
|
||||
|
||||
override fun observe(): Flow<Int> = flow { emitAll(default.observe(getPreferenceProvider())) }
|
||||
|
||||
override suspend fun clear() = default.putValue(getPreferenceProvider(), DEFAULT)
|
||||
}
|
||||
|
||||
private const val DEFAULT = 0
|
|
@ -1,45 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import java.time.Instant
|
||||
|
||||
interface RestoreTimestampStorageProvider {
|
||||
suspend fun get(): Instant?
|
||||
|
||||
suspend fun store(key: Instant)
|
||||
|
||||
suspend fun clear()
|
||||
}
|
||||
interface RestoreTimestampStorageProvider : TimestampStorageProvider
|
||||
|
||||
class RestoreTimestampStorageProviderImpl(
|
||||
private val encryptedPreferenceProvider: EncryptedPreferenceProvider
|
||||
) : RestoreTimestampStorageProvider {
|
||||
private val default = RestoreTimestampPreferenceDefault()
|
||||
|
||||
override suspend fun get(): Instant? = default.getValue(encryptedPreferenceProvider())
|
||||
|
||||
override suspend fun store(key: Instant) {
|
||||
default.putValue(encryptedPreferenceProvider(), key)
|
||||
}
|
||||
|
||||
override suspend fun clear() {
|
||||
default.putValue(encryptedPreferenceProvider(), null)
|
||||
}
|
||||
}
|
||||
|
||||
private class RestoreTimestampPreferenceDefault : PreferenceDefault<Instant?> {
|
||||
override val key: PreferenceKey = PreferenceKey("restore_timestamp")
|
||||
|
||||
override suspend fun getValue(preferenceProvider: PreferenceProvider) =
|
||||
preferenceProvider.getLong(key)?.let {
|
||||
Instant.ofEpochMilli(it)
|
||||
}
|
||||
|
||||
override suspend fun putValue(
|
||||
preferenceProvider: PreferenceProvider,
|
||||
newValue: Instant?
|
||||
) = preferenceProvider.putLong(key, newValue?.toEpochMilli())
|
||||
}
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseTimestampStorageProvider(PreferenceKey("restore_timestamp")), RestoreTimestampStorageProvider
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import cash.z.ecc.android.sdk.model.AccountUuid
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.IntegerPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
interface ShieldFundsRemindMeCountStorageProvider {
|
||||
suspend fun get(forAccount: AccountUuid): Int
|
||||
|
||||
suspend fun store(forAccount: AccountUuid, amount: Int)
|
||||
|
||||
suspend fun observe(forAccount: AccountUuid): Flow<Int>
|
||||
}
|
||||
|
||||
class ShieldFundsRemindMeCountStorageProviderImpl(
|
||||
private val encryptedPreferenceProvider: EncryptedPreferenceProvider
|
||||
) : ShieldFundsRemindMeCountStorageProvider {
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun getDefault(forAccount: AccountUuid): IntegerPreferenceDefault {
|
||||
val key = PreferenceKey("shield_funds_remind_me_count_${forAccount.value.toHexString()}")
|
||||
return IntegerPreferenceDefault(key = key, defaultValue = 0)
|
||||
}
|
||||
|
||||
override suspend fun get(forAccount: AccountUuid): Int {
|
||||
return getDefault(forAccount).getValue(encryptedPreferenceProvider())
|
||||
}
|
||||
|
||||
override suspend fun store(forAccount: AccountUuid, amount: Int) {
|
||||
getDefault(forAccount).putValue(encryptedPreferenceProvider(), amount)
|
||||
}
|
||||
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Int> {
|
||||
return getDefault(forAccount).observe(encryptedPreferenceProvider())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import cash.z.ecc.android.sdk.model.AccountUuid
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.TimestampPreferenceDefault
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.time.Instant
|
||||
|
||||
interface ShieldFundsRemindMeTimestampStorageProvider {
|
||||
suspend fun get(forAccount: AccountUuid): Instant?
|
||||
|
||||
suspend fun store(forAccount: AccountUuid, timestamp: Instant)
|
||||
|
||||
suspend fun observe(forAccount: AccountUuid): Flow<Instant?>
|
||||
}
|
||||
|
||||
class ShieldFundsRemindMeTimestampStorageProviderImpl(
|
||||
private val encryptedPreferenceProvider: EncryptedPreferenceProvider
|
||||
) : ShieldFundsRemindMeTimestampStorageProvider {
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun getDefault(forAccount: AccountUuid): TimestampPreferenceDefault {
|
||||
val key = PreferenceKey("shield_funds_remind_me_timestamp_${forAccount.value.toHexString()}")
|
||||
return TimestampPreferenceDefault(key = key)
|
||||
}
|
||||
|
||||
override suspend fun get(forAccount: AccountUuid): Instant? {
|
||||
return getDefault(forAccount).getValue(encryptedPreferenceProvider())
|
||||
}
|
||||
|
||||
override suspend fun store(forAccount: AccountUuid, timestamp: Instant) {
|
||||
getDefault(forAccount).putValue(encryptedPreferenceProvider(), timestamp)
|
||||
}
|
||||
|
||||
override suspend fun observe(forAccount: AccountUuid): Flow<Instant?> {
|
||||
return getDefault(forAccount).observe(encryptedPreferenceProvider())
|
||||
}
|
||||
}
|
|
@ -53,7 +53,7 @@ class SynchronizerProviderImpl(
|
|||
}.flowOn(Dispatchers.IO)
|
||||
.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.WhileSubscribed(Duration.ZERO, Duration.ZERO),
|
||||
started = SharingStarted.Lazily,
|
||||
initialValue = null
|
||||
)
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.PreferenceHolder
|
||||
import co.electriccoin.zcash.preference.api.PreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
import co.electriccoin.zcash.preference.model.entry.TimestampPreferenceDefault
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import java.time.Instant
|
||||
|
||||
interface TimestampStorageProvider {
|
||||
suspend fun get(): Instant?
|
||||
|
||||
suspend fun store(timestamp: Instant)
|
||||
|
||||
fun observe(): Flow<Instant?>
|
||||
|
||||
suspend fun clear()
|
||||
}
|
||||
|
||||
abstract class BaseTimestampStorageProvider(key: PreferenceKey) : TimestampStorageProvider {
|
||||
protected abstract val preferenceHolder: PreferenceHolder
|
||||
|
||||
private val default = TimestampPreferenceDefault(key)
|
||||
|
||||
private suspend fun getPreferenceProvider(): PreferenceProvider = preferenceHolder()
|
||||
|
||||
override suspend fun get(): Instant? = default.getValue(getPreferenceProvider())
|
||||
|
||||
override suspend fun store(timestamp: Instant) = default.putValue(getPreferenceProvider(), timestamp)
|
||||
|
||||
override fun observe(): Flow<Instant?> = flow { emitAll(default.observe(getPreferenceProvider())) }
|
||||
|
||||
override suspend fun clear() = default.putValue(getPreferenceProvider(), null)
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
|
||||
interface WalletBackupFlagStorageProvider : BooleanStorageProvider
|
||||
|
||||
class WalletBackupFlagStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseBooleanStorageProvider(key = PreferenceKey("wallet_backup_flag")),
|
||||
WalletBackupFlagStorageProvider
|
|
@ -0,0 +1,11 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
|
||||
interface WalletBackupRemindMeCountStorageProvider : IntStorageProvider
|
||||
|
||||
class WalletBackupRemindMeCountStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseIntStorageProvider(key = PreferenceKey("wallet_backup_remind_me_count")),
|
||||
WalletBackupRemindMeCountStorageProvider
|
|
@ -0,0 +1,11 @@
|
|||
package co.electriccoin.zcash.ui.common.provider
|
||||
|
||||
import co.electriccoin.zcash.preference.EncryptedPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.PreferenceKey
|
||||
|
||||
interface WalletBackupRemindMeTimestampStorageProvider : TimestampStorageProvider
|
||||
|
||||
class WalletBackupRemindMeTimestampStorageProviderImpl(
|
||||
override val preferenceHolder: EncryptedPreferenceProvider
|
||||
) : BaseTimestampStorageProvider(key = PreferenceKey("wallet_backup_remind_me_timestamp")),
|
||||
WalletBackupRemindMeTimestampStorageProvider
|
|
@ -5,13 +5,11 @@ import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
|||
import co.electriccoin.zcash.preference.StandardPreferenceProvider
|
||||
import co.electriccoin.zcash.preference.model.entry.NullableBooleanPreferenceDefault
|
||||
import co.electriccoin.zcash.spackle.Twig
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.provider.SynchronizerProvider
|
||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||
import co.electriccoin.zcash.ui.common.wallet.RefreshLock
|
||||
import co.electriccoin.zcash.ui.common.wallet.StaleLock
|
||||
import co.electriccoin.zcash.ui.preference.StandardPreferenceKeys
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
|
@ -37,26 +35,19 @@ import kotlin.time.Duration.Companion.minutes
|
|||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
interface ExchangeRateRepository {
|
||||
val isExchangeRateUsdOptedIn: StateFlow<Boolean?>
|
||||
|
||||
val state: StateFlow<ExchangeRateState>
|
||||
|
||||
fun optInExchangeRateUsd(optIn: Boolean)
|
||||
|
||||
fun dismissOptInExchangeRateUsd()
|
||||
|
||||
fun refreshExchangeRateUsd()
|
||||
}
|
||||
|
||||
class ExchangeRateRepositoryImpl(
|
||||
private val synchronizerProvider: SynchronizerProvider,
|
||||
private val standardPreferenceProvider: StandardPreferenceProvider,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
) : ExchangeRateRepository {
|
||||
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
override val isExchangeRateUsdOptedIn: StateFlow<Boolean?> =
|
||||
nullableBooleanStateFlow(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN)
|
||||
private val isExchangeRateUsdOptedIn = nullableBooleanStateFlow(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
private val exchangeRateUsdInternal =
|
||||
|
@ -167,17 +158,13 @@ class ExchangeRateRepositoryImpl(
|
|||
}
|
||||
|
||||
false -> ExchangeRateState.OptedOut
|
||||
null ->
|
||||
ExchangeRateState.OptIn(
|
||||
onDismissClick = ::dismissWidgetOptInExchangeRateUsd,
|
||||
onPrimaryClick = ::showOptInExchangeRateUsd
|
||||
)
|
||||
null -> ExchangeRateState.OptIn
|
||||
}
|
||||
|
||||
return lastExchangeRateUsdValue
|
||||
}
|
||||
|
||||
override fun refreshExchangeRateUsd() {
|
||||
private fun refreshExchangeRateUsd() {
|
||||
refreshExchangeRateUsdInternal()
|
||||
}
|
||||
|
||||
|
@ -192,20 +179,8 @@ class ExchangeRateRepositoryImpl(
|
|||
|
||||
override fun optInExchangeRateUsd(optIn: Boolean) {
|
||||
setNullableBooleanPreference(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN, optIn)
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
override fun dismissOptInExchangeRateUsd() {
|
||||
setNullableBooleanPreference(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN, false)
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
private fun dismissWidgetOptInExchangeRateUsd() {
|
||||
setNullableBooleanPreference(StandardPreferenceKeys.EXCHANGE_RATE_OPTED_IN, false)
|
||||
}
|
||||
|
||||
private fun showOptInExchangeRateUsd() = navigationRouter.forward(ExchangeRateOptIn)
|
||||
|
||||
private fun nullableBooleanStateFlow(default: NullableBooleanPreferenceDefault): StateFlow<Boolean?> =
|
||||
flow {
|
||||
emitAll(default.observe(standardPreferenceProvider()))
|
||||
|
@ -217,7 +192,7 @@ class ExchangeRateRepositoryImpl(
|
|||
|
||||
private fun setNullableBooleanPreference(
|
||||
default: NullableBooleanPreferenceDefault,
|
||||
newState: Boolean
|
||||
newState: Boolean?
|
||||
) {
|
||||
scope.launch {
|
||||
default.putValue(standardPreferenceProvider(), newState)
|
||||
|
|
|
@ -20,7 +20,6 @@ import co.electriccoin.zcash.ui.common.datasource.AccountDataSource
|
|||
import co.electriccoin.zcash.ui.common.datasource.RestoreTimestampDataSource
|
||||
import co.electriccoin.zcash.ui.common.model.FastestServersState
|
||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletAccount
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||
|
@ -81,11 +80,6 @@ interface WalletRepository {
|
|||
*/
|
||||
val walletRestoringState: StateFlow<WalletRestoringState>
|
||||
|
||||
/**
|
||||
* A flow of the wallet current state information that should be displayed in screens top app bar.
|
||||
*/
|
||||
val walletStateInformation: StateFlow<TopAppBarSubTitleState>
|
||||
|
||||
fun persistWallet(persistableWallet: PersistableWallet)
|
||||
|
||||
fun persistOnboardingState(onboardingState: OnboardingState)
|
||||
|
@ -228,29 +222,6 @@ class WalletRepositoryImpl(
|
|||
initialValue = WalletRestoringState.NONE
|
||||
)
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
override val walletStateInformation: StateFlow<TopAppBarSubTitleState> =
|
||||
synchronizer
|
||||
.filterNotNull()
|
||||
.flatMapLatest { synchronizer ->
|
||||
combine(
|
||||
synchronizer.status,
|
||||
walletRestoringState
|
||||
) { status: Synchronizer.Status?, walletRestoringState: WalletRestoringState ->
|
||||
if (Synchronizer.Status.DISCONNECTED == status) {
|
||||
TopAppBarSubTitleState.Disconnected
|
||||
} else if (WalletRestoringState.RESTORING == walletRestoringState) {
|
||||
TopAppBarSubTitleState.Restoring
|
||||
} else {
|
||||
TopAppBarSubTitleState.None
|
||||
}
|
||||
}
|
||||
}.stateIn(
|
||||
scope = scope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = TopAppBarSubTitleState.None
|
||||
)
|
||||
|
||||
/**
|
||||
* Persists a wallet asynchronously. Clients observe [secretState] to see the side effects.
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import cash.z.ecc.android.sdk.Synchronizer
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupAvailability
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSource
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.repository.ExchangeRateRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.WalletRepository
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.SynchronizerError
|
||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||
import co.electriccoin.zcash.ui.util.Quadruple
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class GetHomeMessageUseCase(
|
||||
private val walletRepository: WalletRepository,
|
||||
private val walletBackupDataSource: WalletBackupDataSource,
|
||||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
) {
|
||||
@OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)
|
||||
fun observe() = combine(
|
||||
walletRepository.currentWalletSnapshot.filterNotNull(),
|
||||
walletRepository.walletRestoringState,
|
||||
walletBackupDataSource.observe(),
|
||||
exchangeRateRepository.state.map { it == ExchangeRateState.OptIn }.distinctUntilChanged(),
|
||||
) { walletSnapshot, walletStateInformation, backup, isCCAvailable ->
|
||||
Quadruple(walletSnapshot, walletStateInformation, backup, isCCAvailable)
|
||||
}.flatMapLatest { (walletSnapshot, walletStateInformation, backup, isCCAvailable) ->
|
||||
when {
|
||||
walletSnapshot.synchronizerError != null -> {
|
||||
flowOf(HomeMessageData.Error(walletSnapshot.synchronizerError))
|
||||
}
|
||||
|
||||
walletSnapshot.status == Synchronizer.Status.DISCONNECTED -> {
|
||||
flowOf(HomeMessageData.Disconnected)
|
||||
}
|
||||
|
||||
walletSnapshot.status in listOf(
|
||||
Synchronizer.Status.INITIALIZING,
|
||||
Synchronizer.Status.SYNCING,
|
||||
Synchronizer.Status.STOPPED
|
||||
) -> {
|
||||
flow {
|
||||
val progress = walletSnapshot.progress.decimal * 100f
|
||||
val result = when {
|
||||
walletStateInformation == WalletRestoringState.RESTORING -> {
|
||||
HomeMessageData.Restoring(
|
||||
progress = progress,
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
HomeMessageData.Syncing(progress = progress)
|
||||
}
|
||||
}
|
||||
emit(result)
|
||||
}
|
||||
}
|
||||
backup is WalletBackupAvailability.Available -> flowOf(HomeMessageData.Backup)
|
||||
|
||||
isCCAvailable -> flowOf(HomeMessageData.EnableCurrencyConversion)
|
||||
|
||||
else -> flowOf(null)
|
||||
}
|
||||
}.debounce(.5.seconds)
|
||||
}
|
||||
|
||||
sealed interface HomeMessageData {
|
||||
data object EnableCurrencyConversion : HomeMessageData
|
||||
data class TransparentBalance(val zatoshi: Zatoshi) : HomeMessageData
|
||||
data object Backup : HomeMessageData
|
||||
data object Disconnected : HomeMessageData
|
||||
data class Error(val synchronizerError: SynchronizerError) : HomeMessageData
|
||||
data class Restoring(val progress: Float) : HomeMessageData
|
||||
data class Syncing(val progress: Float) : HomeMessageData
|
||||
data object Updating : HomeMessageData
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.common.repository.WalletRepository
|
||||
|
||||
class GetWalletStateInformationUseCase(
|
||||
private val walletRepository: WalletRepository
|
||||
) {
|
||||
fun observe() = walletRepository.walletStateInformation
|
||||
}
|
|
@ -7,13 +7,13 @@ import co.electriccoin.zcash.ui.common.repository.BiometricRequest
|
|||
import co.electriccoin.zcash.ui.common.repository.BiometricsCancelledException
|
||||
import co.electriccoin.zcash.ui.common.repository.BiometricsFailureException
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.seed.SeedRecovery
|
||||
import co.electriccoin.zcash.ui.screen.walletbackup.WalletBackup
|
||||
|
||||
class NavigateToSeedRecoveryUseCase(
|
||||
class NavigateToWalletBackupUseCase(
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val biometricRepository: BiometricRepository
|
||||
) {
|
||||
suspend operator fun invoke() {
|
||||
suspend operator fun invoke(isOpenedFromSeedBackupInfo: Boolean) {
|
||||
try {
|
||||
biometricRepository.requestBiometrics(
|
||||
BiometricRequest(
|
||||
|
@ -24,7 +24,7 @@ class NavigateToSeedRecoveryUseCase(
|
|||
)
|
||||
)
|
||||
)
|
||||
navigationRouter.forward(SeedRecovery)
|
||||
navigationRouter.forward(WalletBackup(isOpenedFromSeedBackupInfo = isOpenedFromSeedBackupInfo))
|
||||
} catch (_: BiometricsFailureException) {
|
||||
// do nothing
|
||||
} catch (_: BiometricsCancelledException) {
|
|
@ -0,0 +1,14 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSource
|
||||
|
||||
class OnUserSavedWalletBackupUseCase(
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val walletBackupDataSource: WalletBackupDataSource
|
||||
) {
|
||||
suspend operator fun invoke() {
|
||||
walletBackupDataSource.remindMeLater()
|
||||
navigationRouter.backToRoot()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package co.electriccoin.zcash.ui.common.usecase
|
||||
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.datasource.WalletBackupDataSource
|
||||
|
||||
class RemindWalletBackupLaterUseCase(
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val walletBackupDataSource: WalletBackupDataSource
|
||||
) {
|
||||
suspend operator fun invoke() {
|
||||
walletBackupDataSource.remindMeLater()
|
||||
navigationRouter.backToRoot()
|
||||
}
|
||||
}
|
|
@ -3,7 +3,6 @@ package co.electriccoin.zcash.ui.common.viewmodel
|
|||
import android.app.Application
|
||||
import androidx.lifecycle.AndroidViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import cash.z.ecc.android.sdk.Synchronizer
|
||||
import cash.z.ecc.android.sdk.WalletCoordinator
|
||||
import cash.z.ecc.android.sdk.WalletInitMode
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
|
@ -13,12 +12,10 @@ import cash.z.ecc.android.sdk.model.ZcashNetwork
|
|||
import cash.z.ecc.sdk.type.fromResources
|
||||
import co.electriccoin.zcash.preference.StandardPreferenceProvider
|
||||
import co.electriccoin.zcash.spackle.Twig
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.model.OnboardingState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.model.WalletSnapshot
|
||||
import co.electriccoin.zcash.ui.common.provider.GetDefaultServersProvider
|
||||
import co.electriccoin.zcash.ui.common.repository.ExchangeRateRepository
|
||||
import co.electriccoin.zcash.ui.common.repository.WalletRepository
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSynchronizerUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.IsFlexaAvailableUseCase
|
||||
|
@ -44,39 +41,19 @@ class WalletViewModel(
|
|||
application: Application,
|
||||
private val walletCoordinator: WalletCoordinator,
|
||||
private val walletRepository: WalletRepository,
|
||||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val standardPreferenceProvider: StandardPreferenceProvider,
|
||||
private val getAvailableServers: GetDefaultServersProvider,
|
||||
private val resetInMemoryData: ResetInMemoryDataUseCase,
|
||||
private val resetSharedPrefsData: ResetSharedPrefsDataUseCase,
|
||||
private val isFlexaAvailable: IsFlexaAvailableUseCase,
|
||||
private val getSynchronizer: GetSynchronizerUseCase,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
) : AndroidViewModel(application) {
|
||||
val synchronizer = walletRepository.synchronizer
|
||||
|
||||
val walletStateInformation = walletRepository.walletStateInformation
|
||||
|
||||
val secretState: StateFlow<SecretState> = walletRepository.secretState
|
||||
|
||||
val currentWalletSnapshot: StateFlow<WalletSnapshot?> = walletRepository.currentWalletSnapshot
|
||||
|
||||
val isExchangeRateUsdOptedIn = exchangeRateRepository.isExchangeRateUsdOptedIn
|
||||
|
||||
val exchangeRateUsd = exchangeRateRepository.state
|
||||
|
||||
fun optInExchangeRateUsd(optIn: Boolean) {
|
||||
exchangeRateRepository.optInExchangeRateUsd(optIn)
|
||||
}
|
||||
|
||||
fun dismissOptInExchangeRateUsd() {
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
fun onSkipClick() {
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
fun persistNewWalletAndRestoringState(state: WalletRestoringState) {
|
||||
val application = getApplication<Application>()
|
||||
|
||||
|
@ -259,5 +236,3 @@ sealed class SynchronizerError {
|
|||
override fun getStackTrace(limit: Int?): String? = null
|
||||
}
|
||||
}
|
||||
|
||||
fun Synchronizer.Status.isSynced() = this == Synchronizer.Status.SYNCED
|
||||
|
|
|
@ -13,10 +13,7 @@ sealed interface ExchangeRateState {
|
|||
val onRefresh: () -> Unit,
|
||||
) : ExchangeRateState
|
||||
|
||||
data class OptIn(
|
||||
val onDismissClick: () -> Unit = {},
|
||||
val onPrimaryClick: () -> Unit = {}
|
||||
) : ExchangeRateState
|
||||
data object OptIn : ExchangeRateState
|
||||
|
||||
data object OptedOut : ExchangeRateState
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ object ZashiMainTopAppBarStateFixture {
|
|||
) = ZashiMainTopAppBarState(
|
||||
accountSwitchState = accountSwitchState,
|
||||
balanceVisibilityButton = balanceVisibilityButton,
|
||||
settingsButton = settingsButton,
|
||||
subtitle = null
|
||||
settingsButton = settingsButton
|
||||
)
|
||||
}
|
||||
|
|
|
@ -16,4 +16,8 @@ data class PersistableWalletPreferenceDefault(
|
|||
preferenceProvider: PreferenceProvider,
|
||||
newValue: PersistableWallet?
|
||||
) = preferenceProvider.putString(key, newValue?.toJson()?.toString())
|
||||
|
||||
suspend fun remove(preferenceProvider: PreferenceProvider) {
|
||||
preferenceProvider.remove(key)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,10 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.configuration.api.ConfigurationProvider
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalActivity
|
||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.screen.about.util.WebBrowserUtil
|
||||
import co.electriccoin.zcash.ui.screen.about.view.About
|
||||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||
|
@ -26,9 +23,6 @@ import org.koin.compose.koinInject
|
|||
@Composable
|
||||
internal fun WrapAbout(goBack: () -> Unit) {
|
||||
val activity = LocalActivity.current
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
|
||||
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
|
||||
|
||||
BackHandler {
|
||||
goBack()
|
||||
|
@ -49,7 +43,6 @@ internal fun WrapAbout(goBack: () -> Unit) {
|
|||
|
||||
About(
|
||||
onBack = goBack,
|
||||
versionInfo = versionInfo,
|
||||
configInfo = configInfo,
|
||||
onPrivacyPolicy = {
|
||||
openPrivacyPolicyInWebBrowser(
|
||||
|
@ -59,7 +52,7 @@ internal fun WrapAbout(goBack: () -> Unit) {
|
|||
)
|
||||
},
|
||||
snackbarHostState = snackbarHostState,
|
||||
topAppBarSubTitleState = walletState,
|
||||
versionInfo = versionInfo,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiTopAppBarBackNavigation
|
||||
|
@ -48,13 +47,11 @@ import co.electriccoin.zcash.ui.fixture.VersionInfoFixture
|
|||
import co.electriccoin.zcash.ui.screen.support.model.ConfigInfo
|
||||
|
||||
@Composable
|
||||
@Suppress("LongParameterList")
|
||||
fun About(
|
||||
onBack: () -> Unit,
|
||||
configInfo: ConfigInfo,
|
||||
onPrivacyPolicy: () -> Unit,
|
||||
snackbarHostState: SnackbarHostState,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
versionInfo: VersionInfo,
|
||||
) {
|
||||
Scaffold(
|
||||
|
@ -63,7 +60,6 @@ fun About(
|
|||
onBack = onBack,
|
||||
versionInfo = versionInfo,
|
||||
configInfo = configInfo,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
|
@ -85,16 +81,9 @@ fun About(
|
|||
private fun AboutTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
versionInfo: VersionInfo,
|
||||
configInfo: ConfigInfo,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
configInfo: ConfigInfo
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
title = stringResource(id = R.string.about_title),
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(onBack = onBack)
|
||||
|
@ -198,7 +187,6 @@ private fun AboutPreview() =
|
|||
configInfo = ConfigInfoFixture.new(),
|
||||
onPrivacyPolicy = {},
|
||||
snackbarHostState = SnackbarHostState(),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
versionInfo = VersionInfoFixture.new(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.screen.addressbook.view.AddressBookView
|
||||
import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.AddressBookViewModel
|
||||
import co.electriccoin.zcash.ui.screen.addressbook.viewmodel.SelectRecipientViewModel
|
||||
|
@ -23,9 +21,7 @@ internal fun WrapAddressBook(args: AddressBookArgs) {
|
|||
|
||||
@Composable
|
||||
private fun WrapAddressBook() {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<AddressBookViewModel>()
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
BackHandler {
|
||||
|
@ -34,15 +30,12 @@ private fun WrapAddressBook() {
|
|||
|
||||
AddressBookView(
|
||||
state = state,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun WrapSelectRecipient() {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<SelectRecipientViewModel>()
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
BackHandler {
|
||||
|
@ -51,7 +44,6 @@ private fun WrapSelectRecipient() {
|
|||
|
||||
AddressBookView(
|
||||
state = state,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||
|
@ -67,14 +66,12 @@ import co.electriccoin.zcash.ui.screen.addressbook.model.AddressBookState
|
|||
|
||||
@Composable
|
||||
fun AddressBookView(
|
||||
state: AddressBookState,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState
|
||||
state: AddressBookState
|
||||
) {
|
||||
BlankBgScaffold(
|
||||
topBar = {
|
||||
AddressBookTopAppBar(
|
||||
onBack = state.onBack,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
state = state
|
||||
)
|
||||
}
|
||||
|
@ -322,17 +319,10 @@ private fun AddContactButton(
|
|||
@Composable
|
||||
private fun AddressBookTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState,
|
||||
state: AddressBookState,
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = state.title.getValue(),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
modifier = Modifier.testTag(AddressBookTag.TOP_APP_BAR),
|
||||
showTitleLogo = true,
|
||||
navigationAction = {
|
||||
|
@ -382,7 +372,6 @@ private fun AddressBookDataPreview() {
|
|||
),
|
||||
title = stringRes("Address book")
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -447,7 +436,6 @@ private fun SelectRecipientDataPreview() {
|
|||
),
|
||||
title = stringRes("Select Recipient")
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -472,7 +460,6 @@ private fun LoadingPreview() {
|
|||
),
|
||||
title = stringRes("Select Recipient")
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +484,6 @@ private fun EmptyAddressBookPreview() {
|
|||
),
|
||||
title = stringRes("Address Book")
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -535,7 +521,6 @@ private fun EmptySelectRecipientPreview() {
|
|||
),
|
||||
title = stringRes("Select Recipient")
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@ import androidx.compose.ui.unit.dp
|
|||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
|
@ -47,13 +46,11 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
@Composable
|
||||
fun AdvancedSettings(
|
||||
state: AdvancedSettingsState,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
) {
|
||||
BlankBgScaffold(
|
||||
topBar = {
|
||||
AdvancedSettingsTopAppBar(
|
||||
onBack = state.onBack,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
}
|
||||
) { paddingValues ->
|
||||
|
@ -114,17 +111,10 @@ private fun Info() {
|
|||
|
||||
@Composable
|
||||
private fun AdvancedSettingsTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = stringResource(id = R.string.advanced_settings_title),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
modifier = Modifier.testTag(AdvancedSettingsTag.ADVANCED_SETTINGS_TOP_APP_BAR),
|
||||
showTitleLogo = true,
|
||||
navigationAction = {
|
||||
|
@ -170,6 +160,5 @@ private fun AdvancedSettingsPreview() =
|
|||
onClick = {}
|
||||
)
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -8,12 +8,12 @@ import co.electriccoin.zcash.ui.NavigationTargets
|
|||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.WalletRestoringState
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetWalletRestoringStateUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToSeedRecoveryUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToTaxExportUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.listitem.ZashiListItemState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.settings.ExchangeRateSettings
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
@ -26,7 +26,7 @@ class AdvancedSettingsViewModel(
|
|||
getWalletRestoringState: GetWalletRestoringStateUseCase,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val navigateToTaxExport: NavigateToTaxExportUseCase,
|
||||
private val navigateToSeedRecovery: NavigateToSeedRecoveryUseCase
|
||||
private val navigateToSeedRecovery: NavigateToWalletBackupUseCase
|
||||
) : ViewModel() {
|
||||
val state: StateFlow<AdvancedSettingsState> =
|
||||
getWalletRestoringState
|
||||
|
@ -89,7 +89,7 @@ class AdvancedSettingsViewModel(
|
|||
|
||||
private fun onChooseServerClick() = navigationRouter.forward(NavigationTargets.CHOOSE_SERVER)
|
||||
|
||||
private fun onCurrencyConversionClick() = navigationRouter.forward(ExchangeRateOptIn)
|
||||
private fun onCurrencyConversionClick() = navigationRouter.forward(ExchangeRateSettings)
|
||||
|
||||
private fun onTaxExportClick() =
|
||||
viewModelScope.launch {
|
||||
|
@ -98,6 +98,6 @@ class AdvancedSettingsViewModel(
|
|||
|
||||
private fun onSeedRecoveryClick() =
|
||||
viewModelScope.launch {
|
||||
navigateToSeedRecovery()
|
||||
navigateToSeedRecovery(isOpenedFromSeedBackupInfo = false)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ package co.electriccoin.zcash.ui.screen.advancedsettings
|
|||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
|
@ -15,9 +13,7 @@ internal fun WrapAdvancedSettings(
|
|||
goDeleteWallet: () -> Unit,
|
||||
goExportPrivateData: () -> Unit,
|
||||
) {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<AdvancedSettingsViewModel>()
|
||||
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
|
||||
val originalState = viewModel.state.collectAsStateWithLifecycle().value
|
||||
val state =
|
||||
originalState.copy(
|
||||
|
@ -38,6 +34,5 @@ internal fun WrapAdvancedSettings(
|
|||
|
||||
AdvancedSettings(
|
||||
state = state,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -6,17 +6,13 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalNavController
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
internal fun WrapChooseServer() {
|
||||
val navController = LocalNavController.current
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<ChooseServerViewModel>()
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
BackHandler {
|
||||
|
@ -32,6 +28,5 @@ internal fun WrapChooseServer() {
|
|||
navController.popBackStack()
|
||||
}
|
||||
},
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -46,7 +46,6 @@ import androidx.compose.ui.text.input.KeyboardType
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.R.drawable
|
||||
import co.electriccoin.zcash.ui.design.component.AlertDialogState
|
||||
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
||||
|
@ -78,7 +77,6 @@ import co.electriccoin.zcash.ui.design.util.stringRes
|
|||
@Composable
|
||||
fun ChooseServerView(
|
||||
state: ChooseServerState?,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
onBack: () -> Unit,
|
||||
) {
|
||||
if (state == null) {
|
||||
|
@ -91,7 +89,6 @@ fun ChooseServerView(
|
|||
topBar = {
|
||||
ChooseServerTopAppBar(
|
||||
onBack = onBack,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
},
|
||||
bottomBar = {
|
||||
|
@ -208,17 +205,10 @@ fun ChooseServerBottomBar(saveButtonState: ButtonState) {
|
|||
|
||||
@Composable
|
||||
private fun ChooseServerTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = stringResource(id = R.string.choose_server_title),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
modifier = Modifier.testTag(CHOOSE_SERVER_TOP_APP_BAR),
|
||||
showTitleLogo = true,
|
||||
navigationAction = {
|
||||
|
@ -535,7 +525,6 @@ private fun ChooseServerPreview(
|
|||
dialogState = dialogState
|
||||
),
|
||||
onBack = {},
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.view.ContactView
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.AddContactViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
@ -15,9 +13,7 @@ import org.koin.core.parameter.parametersOf
|
|||
|
||||
@Composable
|
||||
internal fun WrapAddContact(address: String?) {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<AddContactViewModel> { parametersOf(address) }
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
BackHandler {
|
||||
|
@ -27,7 +23,6 @@ internal fun WrapAddContact(address: String?) {
|
|||
state?.let {
|
||||
ContactView(
|
||||
state = it,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@ import androidx.activity.compose.BackHandler
|
|||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.screen.contact.view.ContactView
|
||||
import co.electriccoin.zcash.ui.screen.contact.viewmodel.UpdateContactViewModel
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
@ -15,9 +13,7 @@ import org.koin.core.parameter.parametersOf
|
|||
|
||||
@Composable
|
||||
internal fun WrapUpdateContact(contactAddress: String) {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<UpdateContactViewModel> { parametersOf(contactAddress) }
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
BackHandler {
|
||||
|
@ -27,7 +23,6 @@ internal fun WrapUpdateContact(contactAddress: String) {
|
|||
state?.let {
|
||||
ContactView(
|
||||
state = it,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.BlankBgScaffold
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||
|
@ -37,12 +36,11 @@ import co.electriccoin.zcash.ui.screen.contact.model.ContactState
|
|||
|
||||
@Composable
|
||||
fun ContactView(
|
||||
state: ContactState,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState
|
||||
state: ContactState
|
||||
) {
|
||||
BlankBgScaffold(
|
||||
topBar = {
|
||||
ContactTopAppBar(onBack = state.onBack, subTitleState = topAppBarSubTitleState, state = state)
|
||||
ContactTopAppBar(onBack = state.onBack, state = state)
|
||||
}
|
||||
) { paddingValues ->
|
||||
if (state.isLoading) {
|
||||
|
@ -129,17 +127,10 @@ private fun ContactViewInternal(
|
|||
@Composable
|
||||
private fun ContactTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState,
|
||||
state: ContactState
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = state.title.getValue(),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
modifier = Modifier.testTag(ContactTag.TOP_APP_BAR),
|
||||
showTitleLogo = true,
|
||||
navigationAction = {
|
||||
|
@ -169,7 +160,6 @@ private fun DataPreview() {
|
|||
text = stringRes("Negative"),
|
||||
)
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +185,6 @@ private fun LoadingPreview() {
|
|||
text = stringRes("Add New Contact"),
|
||||
)
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.MainActivity
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.screen.deletewallet.view.DeleteWallet
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -22,15 +21,11 @@ internal fun MainActivity.WrapDeleteWallet(
|
|||
onConfirm: () -> Unit,
|
||||
) {
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
|
||||
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
|
||||
|
||||
WrapDeleteWallet(
|
||||
activity = this,
|
||||
goBack = goBack,
|
||||
topAppBarSubTitleState = walletState,
|
||||
walletViewModel = walletViewModel,
|
||||
onConfirm = onConfirm
|
||||
onConfirm = onConfirm,
|
||||
walletViewModel = walletViewModel
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -39,7 +34,6 @@ internal fun WrapDeleteWallet(
|
|||
activity: Activity,
|
||||
goBack: () -> Unit,
|
||||
onConfirm: () -> Unit,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
walletViewModel: WalletViewModel,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
@ -69,6 +63,5 @@ internal fun WrapDeleteWallet(
|
|||
}
|
||||
)
|
||||
},
|
||||
topAppBarSubTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.MINIMAL_WEIGHT
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
||||
|
@ -43,7 +42,6 @@ private fun ExportPrivateDataPreview() =
|
|||
snackbarHostState = SnackbarHostState(),
|
||||
onBack = {},
|
||||
onConfirm = {},
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -52,13 +50,11 @@ fun DeleteWallet(
|
|||
snackbarHostState: SnackbarHostState,
|
||||
onBack: () -> Unit,
|
||||
onConfirm: () -> Unit,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
DeleteWalletDataTopAppBar(
|
||||
onBack = onBack,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
|
@ -76,17 +72,10 @@ fun DeleteWallet(
|
|||
|
||||
@Composable
|
||||
private fun DeleteWalletDataTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = stringResource(R.string.delete_wallet_title),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(
|
||||
onBack = onBack
|
||||
|
|
|
@ -1,26 +1,18 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.optin
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.Composable
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalActivity
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
fun AndroidExchangeRateOptIn() {
|
||||
val activity = LocalActivity.current
|
||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||
|
||||
BackHandler {
|
||||
walletViewModel.dismissOptInExchangeRateUsd()
|
||||
}
|
||||
|
||||
ExchangeRateOptIn(
|
||||
onEnableClick = { walletViewModel.optInExchangeRateUsd(true) },
|
||||
onDismiss = { walletViewModel.dismissOptInExchangeRateUsd() },
|
||||
onSkipClick = { walletViewModel.onSkipClick() }
|
||||
)
|
||||
val viewModel = koinViewModel<ExchangeRateOptInViewModel>()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
BackHandler { state.onBack() }
|
||||
ExchangeRateOptInView(state = state)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.optin
|
||||
|
||||
data class ExchangeRateOptInState(
|
||||
val onEnableClick: () -> Unit,
|
||||
val onBack: () -> Unit,
|
||||
val onSkipClick: () -> Unit,
|
||||
)
|
|
@ -29,13 +29,9 @@ import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
|||
import co.electriccoin.zcash.ui.screen.exchangerate.BaseExchangeRateOptIn
|
||||
|
||||
@Composable
|
||||
fun ExchangeRateOptIn(
|
||||
onEnableClick: () -> Unit,
|
||||
onSkipClick: () -> Unit,
|
||||
onDismiss: () -> Unit,
|
||||
) {
|
||||
fun ExchangeRateOptInView(state: ExchangeRateOptInState) {
|
||||
BaseExchangeRateOptIn(
|
||||
onDismiss = onDismiss,
|
||||
onDismiss = state.onBack,
|
||||
content = {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
|
@ -61,7 +57,7 @@ fun ExchangeRateOptIn(
|
|||
footer = {
|
||||
ZashiTextButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onSkipClick,
|
||||
onClick = state.onSkipClick,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.exchange_rate_opt_in_skip),
|
||||
|
@ -72,7 +68,7 @@ fun ExchangeRateOptIn(
|
|||
ZashiButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = stringResource(R.string.exchange_rate_opt_in_enable),
|
||||
onClick = onEnableClick,
|
||||
onClick = state.onEnableClick,
|
||||
colors = ZashiButtonDefaults.primaryColors()
|
||||
)
|
||||
}
|
||||
|
@ -118,6 +114,12 @@ private fun InfoItem(
|
|||
private fun CurrencyConversionOptInPreview() =
|
||||
ZcashTheme {
|
||||
BlankSurface {
|
||||
ExchangeRateOptIn(onEnableClick = {}, onDismiss = {}, onSkipClick = {})
|
||||
ExchangeRateOptInView(
|
||||
state = ExchangeRateOptInState(
|
||||
onEnableClick = {},
|
||||
onBack = {},
|
||||
onSkipClick = {},
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.optin
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.repository.ExchangeRateRepository
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
class ExchangeRateOptInViewModel(
|
||||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val navigationRouter: NavigationRouter
|
||||
): ViewModel() {
|
||||
val state: StateFlow<ExchangeRateOptInState> = MutableStateFlow(
|
||||
ExchangeRateOptInState(
|
||||
onBack = ::dismissOptInExchangeRateUsd,
|
||||
onEnableClick = ::optInExchangeRateUsd,
|
||||
onSkipClick = ::onSkipClick
|
||||
)
|
||||
)
|
||||
|
||||
private fun onSkipClick() {
|
||||
exchangeRateRepository.optInExchangeRateUsd(false)
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
private fun optInExchangeRateUsd() {
|
||||
exchangeRateRepository.optInExchangeRateUsd(true)
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
private fun dismissOptInExchangeRateUsd() {
|
||||
navigationRouter.back()
|
||||
}
|
||||
}
|
|
@ -1,30 +1,18 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.settings
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.activity.viewModels
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalActivity
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalNavController
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
fun AndroidExchangeRateSettings() {
|
||||
val activity = LocalActivity.current
|
||||
val navController = LocalNavController.current
|
||||
val walletViewModel by activity.viewModels<WalletViewModel>()
|
||||
val isOptedIn = walletViewModel.isExchangeRateUsdOptedIn.collectAsStateWithLifecycle().value ?: false
|
||||
|
||||
BackHandler {
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
ExchangeRateSettings(
|
||||
isOptedIn = isOptedIn,
|
||||
onSaveClick = { walletViewModel.optInExchangeRateUsd(it) },
|
||||
onDismiss = { navController.popBackStack() }
|
||||
)
|
||||
val viewModel = koinViewModel<ExchangeRateSettingsViewModel>()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
BackHandler { state.onDismiss() }
|
||||
ExchangeRateSettingsView(state = state)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.settings
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
data class ExchangeRateSettingsState(
|
||||
val isOptedIn: Boolean,
|
||||
val onSaveClick: (optIn: Boolean) -> Unit,
|
||||
val onDismiss: () -> Unit,
|
||||
)
|
|
@ -37,21 +37,17 @@ import co.electriccoin.zcash.ui.screen.exchangerate.BaseExchangeRateOptIn
|
|||
import co.electriccoin.zcash.ui.screen.exchangerate.SecondaryCard
|
||||
|
||||
@Composable
|
||||
fun ExchangeRateSettings(
|
||||
isOptedIn: Boolean,
|
||||
onDismiss: () -> Unit,
|
||||
onSaveClick: (Boolean) -> Unit
|
||||
) {
|
||||
var isOptInSelected by remember(isOptedIn) { mutableStateOf(isOptedIn) }
|
||||
fun ExchangeRateSettingsView(state: ExchangeRateSettingsState) {
|
||||
var isOptInSelected by remember(state.isOptedIn) { mutableStateOf(state.isOptedIn) }
|
||||
|
||||
val isButtonDisabled by remember {
|
||||
derivedStateOf {
|
||||
(isOptedIn && isOptInSelected) || (!isOptedIn && !isOptInSelected)
|
||||
(state.isOptedIn && isOptInSelected) || (!state.isOptedIn && !isOptInSelected)
|
||||
}
|
||||
}
|
||||
|
||||
BaseExchangeRateOptIn(
|
||||
onDismiss = onDismiss,
|
||||
onDismiss = state.onDismiss,
|
||||
content = {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
|
@ -82,7 +78,7 @@ fun ExchangeRateSettings(
|
|||
ZashiButton(
|
||||
text = stringResource(R.string.exchange_rate_opt_in_save),
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = { onSaveClick(isOptInSelected) },
|
||||
onClick = { state.onSaveClick(isOptInSelected) },
|
||||
enabled = !isButtonDisabled,
|
||||
colors = ZashiButtonDefaults.primaryColors()
|
||||
)
|
||||
|
@ -187,6 +183,12 @@ private val Unchecked: Int
|
|||
private fun SettingsExchangeRateOptInPreview() =
|
||||
ZcashTheme {
|
||||
BlankSurface {
|
||||
ExchangeRateSettings(isOptedIn = true, onDismiss = {}, onSaveClick = {})
|
||||
ExchangeRateSettingsView(
|
||||
state = ExchangeRateSettingsState(
|
||||
isOptedIn = true,
|
||||
onSaveClick = {},
|
||||
onDismiss = {}
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.settings
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.repository.ExchangeRateRepository
|
||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
|
||||
class ExchangeRateSettingsViewModel(
|
||||
private val exchangeRateRepository: ExchangeRateRepository,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
) : ViewModel() {
|
||||
|
||||
val state = exchangeRateRepository.state
|
||||
.map {
|
||||
createState(it)
|
||||
}
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(ANDROID_STATE_FLOW_TIMEOUT),
|
||||
initialValue = createState(exchangeRateRepository.state.value)
|
||||
)
|
||||
|
||||
private fun createState(it: ExchangeRateState) =
|
||||
ExchangeRateSettingsState(
|
||||
isOptedIn = it is ExchangeRateState.OptIn,
|
||||
onSaveClick = ::onOptInExchangeRateUsdClick,
|
||||
onDismiss = ::onBack
|
||||
)
|
||||
|
||||
private fun onBack() {
|
||||
navigationRouter.back()
|
||||
}
|
||||
|
||||
private fun onOptInExchangeRateUsdClick(optInt: Boolean) {
|
||||
exchangeRateRepository.optInExchangeRateUsd(optIn = optInt)
|
||||
navigationRouter.back()
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
package co.electriccoin.zcash.ui.screen.exchangerate.widget
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.wallet.ExchangeRateState
|
||||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
||||
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.screen.exchangerate.SecondaryCard
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
fun StyledExchangeOptIn(
|
||||
state: ExchangeRateState.OptIn,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
SecondaryCard(
|
||||
modifier = modifier,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.padding(start = 20.dp, bottom = 20.dp)
|
||||
) {
|
||||
Row {
|
||||
Image(
|
||||
modifier = Modifier.padding(top = 20.dp),
|
||||
painter = painterResource(Icon),
|
||||
contentDescription = null
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Column(
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(22.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.exchange_rate_opt_in_title),
|
||||
color = ZashiColors.Text.textTertiary,
|
||||
fontSize = 14.sp,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(2.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.exchange_rate_opt_in_subtitle),
|
||||
color = ZashiColors.Text.textPrimary,
|
||||
fontSize = 16.sp,
|
||||
style = ZcashTheme.extendedTypography.restoringTopAppBarStyle,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(
|
||||
modifier = Modifier.padding(top = 4.dp, end = 8.dp),
|
||||
onClick = state.onDismissClick,
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(R.drawable.ic_exchange_rate_unavailable_dialog_close),
|
||||
contentDescription = null,
|
||||
tint = ZashiColors.HintTooltips.defaultFg
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
ZashiButton(
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(end = 20.dp),
|
||||
onClick = state.onPrimaryClick,
|
||||
colors = ZashiButtonDefaults.tertiaryColors(),
|
||||
text = stringResource(R.string.exchange_rate_opt_in_primary_btn),
|
||||
) { scope ->
|
||||
Text(
|
||||
text = stringResource(R.string.exchange_rate_opt_in_primary_btn),
|
||||
style =
|
||||
ZcashTheme.typography.primary.titleSmall
|
||||
.copy(fontWeight = FontWeight.SemiBold),
|
||||
fontSize = 14.sp
|
||||
)
|
||||
scope.Loading()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val Icon: Int
|
||||
@DrawableRes
|
||||
@Composable
|
||||
get() =
|
||||
if (isSystemInDarkTheme()) {
|
||||
R.drawable.ic_exchange_rate_opt_in
|
||||
} else {
|
||||
R.drawable.ic_exchange_rate_opt_in_light
|
||||
}
|
||||
|
||||
@Suppress("UnusedPrivateMember")
|
||||
@Composable
|
||||
@PreviewScreens
|
||||
private fun ExchangeRateOptInPreview() =
|
||||
ZcashTheme {
|
||||
BlankSurface {
|
||||
StyledExchangeOptIn(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = ExchangeRateState.OptIn(onDismissClick = {})
|
||||
)
|
||||
}
|
||||
}
|
|
@ -14,7 +14,6 @@ import cash.z.ecc.sdk.type.fromResources
|
|||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalActivity
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.common.model.VersionInfo
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.design.component.CircularScreenProgressIndicator
|
||||
|
@ -34,13 +33,10 @@ internal fun WrapExportPrivateData(
|
|||
|
||||
val synchronizer = walletViewModel.synchronizer.collectAsStateWithLifecycle().value
|
||||
|
||||
val walletState = walletViewModel.walletStateInformation.collectAsStateWithLifecycle().value
|
||||
|
||||
WrapExportPrivateData(
|
||||
goBack = goBack,
|
||||
onShare = onConfirm,
|
||||
synchronizer = synchronizer,
|
||||
topAppBarSubTitleState = walletState,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -49,7 +45,6 @@ internal fun WrapExportPrivateData(
|
|||
goBack: () -> Unit,
|
||||
onShare: () -> Unit,
|
||||
synchronizer: Synchronizer?,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
) {
|
||||
val activity = LocalActivity.current
|
||||
|
||||
|
@ -85,7 +80,6 @@ internal fun WrapExportPrivateData(
|
|||
}
|
||||
}
|
||||
},
|
||||
topAppBarSubTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import androidx.compose.ui.platform.testTag
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButton
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCheckbox
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiSmallTopAppBar
|
||||
|
@ -38,13 +37,11 @@ fun ExportPrivateData(
|
|||
onBack: () -> Unit,
|
||||
onAgree: (Boolean) -> Unit,
|
||||
onConfirm: () -> Unit,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
ExportPrivateDataTopAppBar(
|
||||
onBack = onBack,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
|
@ -63,17 +60,10 @@ fun ExportPrivateData(
|
|||
|
||||
@Composable
|
||||
private fun ExportPrivateDataTopAppBar(
|
||||
onBack: () -> Unit,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
onBack: () -> Unit
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = stringResource(R.string.export_data_title),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(onBack = onBack)
|
||||
},
|
||||
|
@ -137,6 +127,5 @@ private fun ExportPrivateDataPreview() =
|
|||
onBack = {},
|
||||
onAgree = {},
|
||||
onConfirm = {},
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,9 +7,7 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.electriccoin.zcash.di.koinActivityViewModel
|
||||
import co.electriccoin.zcash.ui.common.compose.LocalNavController
|
||||
import co.electriccoin.zcash.ui.common.viewmodel.WalletViewModel
|
||||
import co.electriccoin.zcash.ui.design.component.AppAlertDialog
|
||||
import co.electriccoin.zcash.ui.screen.feedback.view.FeedbackView
|
||||
import co.electriccoin.zcash.ui.screen.feedback.viewmodel.FeedbackViewModel
|
||||
|
@ -18,33 +16,15 @@ import org.koin.androidx.compose.koinViewModel
|
|||
@Composable
|
||||
internal fun WrapFeedback() {
|
||||
val navController = LocalNavController.current
|
||||
val walletViewModel = koinActivityViewModel<WalletViewModel>()
|
||||
val viewModel = koinViewModel<FeedbackViewModel>()
|
||||
|
||||
val walletState by walletViewModel.walletStateInformation.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val dialogState by viewModel.dialogState.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
viewModel.onBackNavigationCommand.collect {
|
||||
navController.popBackStack()
|
||||
}
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
state?.onBack?.invoke()
|
||||
}
|
||||
|
||||
state?.let {
|
||||
FeedbackView(
|
||||
state = it,
|
||||
topAppBarSubTitleState = walletState
|
||||
)
|
||||
}
|
||||
|
||||
dialogState?.let {
|
||||
AppAlertDialog(
|
||||
state = it
|
||||
)
|
||||
}
|
||||
BackHandler(enabled = state != null) { state?.onBack?.invoke() }
|
||||
state?.let { FeedbackView(state = it) }
|
||||
dialogState?.let { AppAlertDialog(state = it) }
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.TextFieldState
|
||||
|
@ -56,13 +55,11 @@ import co.electriccoin.zcash.ui.screen.feedback.model.FeedbackState
|
|||
@Composable
|
||||
fun FeedbackView(
|
||||
state: FeedbackState,
|
||||
topAppBarSubTitleState: TopAppBarSubTitleState,
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
SupportTopAppBar(
|
||||
state = state,
|
||||
subTitleState = topAppBarSubTitleState,
|
||||
)
|
||||
},
|
||||
) { paddingValues ->
|
||||
|
@ -75,16 +72,9 @@ fun FeedbackView(
|
|||
|
||||
@Composable
|
||||
private fun SupportTopAppBar(
|
||||
state: FeedbackState,
|
||||
subTitleState: TopAppBarSubTitleState
|
||||
state: FeedbackState
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
title = stringResource(id = R.string.support_header),
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(onBack = state.onBack)
|
||||
|
@ -258,7 +248,6 @@ private fun Preview() =
|
|||
onSelected = {}
|
||||
)
|
||||
),
|
||||
topAppBarSubTitleState = TopAppBarSubTitleState.None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,13 +11,14 @@ import co.electriccoin.zcash.ui.screen.balances.BalanceViewModel
|
|||
import co.electriccoin.zcash.ui.screen.restoresuccess.WrapRestoreSuccess
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetViewModel
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@Composable
|
||||
internal fun AndroidHome() {
|
||||
val topAppBarViewModel = koinActivityViewModel<ZashiTopAppBarViewModel>()
|
||||
val balanceViewModel = koinActivityViewModel<BalanceViewModel>()
|
||||
val homeViewModel = koinActivityViewModel<HomeViewModel>()
|
||||
val transactionHistoryWidgetViewModel = koinActivityViewModel<TransactionHistoryWidgetViewModel>()
|
||||
val balanceViewModel = koinViewModel<BalanceViewModel>()
|
||||
val homeViewModel = koinViewModel<HomeViewModel>()
|
||||
val transactionHistoryWidgetViewModel = koinViewModel<TransactionHistoryWidgetViewModel>()
|
||||
val restoreDialogState by homeViewModel.restoreDialogState.collectAsStateWithLifecycle()
|
||||
val appBarState by topAppBarViewModel.state.collectAsStateWithLifecycle()
|
||||
val balanceState by balanceViewModel.state.collectAsStateWithLifecycle()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.CubicBezierEasing
|
||||
|
@ -35,6 +35,22 @@ import androidx.compose.ui.unit.Dp
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.zIndex
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.currency.EnableCurrencyConversionMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.currency.EnableCurrencyConversionMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingMessageState
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlin.time.Duration
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
@ -112,10 +128,10 @@ fun HomeMessage(
|
|||
contentPadding = contentPadding
|
||||
)
|
||||
|
||||
is TransparentBalanceDetectedMessageState ->
|
||||
TransparentBalanceDetectedMessage(
|
||||
is TransparentBalanceMessageState ->
|
||||
TransparentBalanceMessage(
|
||||
innerModifier = innerModifier,
|
||||
state = normalizedState as TransparentBalanceDetectedMessageState,
|
||||
state = normalizedState as TransparentBalanceMessageState,
|
||||
contentPadding = contentPadding
|
||||
)
|
||||
|
||||
|
@ -203,7 +219,7 @@ fun HomeMessage(
|
|||
}
|
||||
}
|
||||
|
||||
sealed interface HomeMessageState
|
||||
interface HomeMessageState
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
@Composable
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
@ -24,8 +24,6 @@ import co.electriccoin.zcash.ui.design.component.LocalZashiCircularProgressIndic
|
|||
import co.electriccoin.zcash.ui.design.component.VerticalSpacer
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiButtonDefaults
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicatorDefaults
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.Purple
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiDarkColors
|
||||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiLightColors
|
||||
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||
|
@ -47,11 +45,11 @@ fun HomeMessageWrapper(
|
|||
innerModifier = innerModifier,
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides ZashiColors.Text.textOpposite,
|
||||
LocalContentColor provides ZashiLightColors.Utility.Purple.utilityPurple50,
|
||||
LocalZashiCircularProgressIndicatorColors provides
|
||||
ZashiCircularProgressIndicatorDefaults.colors(
|
||||
progressColor = ZashiColors.Text.textOpposite,
|
||||
trackColor = Purple.`400`
|
||||
progressColor = ZashiLightColors.Utility.Purple.utilityPurple50,
|
||||
trackColor = ZashiLightColors.Utility.Purple.utilityPurple400
|
||||
)
|
||||
) {
|
||||
start()
|
||||
|
@ -63,7 +61,7 @@ fun HomeMessageWrapper(
|
|||
CompositionLocalProvider(
|
||||
LocalTextStyle provides
|
||||
ZashiTypography.textSm.copy(
|
||||
color = ZashiColors.Text.textOpposite,
|
||||
color = ZashiLightColors.Utility.Purple.utilityPurple50,
|
||||
fontWeight = FontWeight.Medium
|
||||
),
|
||||
) {
|
||||
|
@ -73,7 +71,7 @@ fun HomeMessageWrapper(
|
|||
CompositionLocalProvider(
|
||||
LocalTextStyle provides
|
||||
ZashiTypography.textXs.copy(
|
||||
color = Purple.`200`,
|
||||
color = ZashiLightColors.Utility.Purple.utilityPurple200,
|
||||
fontWeight = FontWeight.Medium
|
||||
),
|
||||
) {
|
||||
|
@ -106,10 +104,11 @@ private fun Container(
|
|||
Modifier
|
||||
.background(
|
||||
Brush.verticalGradient(
|
||||
0f to Purple.`500`,
|
||||
1f to Purple.`900`,
|
||||
0f to ZashiLightColors.Utility.Purple.utilityPurple500,
|
||||
1f to ZashiLightColors.Utility.Purple.utilityPurple900,
|
||||
)
|
||||
).clickable(onClick = onClick)
|
||||
)
|
||||
.clickable(onClick = onClick)
|
||||
.padding(contentPadding),
|
||||
) {
|
||||
Row(
|
|
@ -1,7 +1,6 @@
|
|||
package co.electriccoin.zcash.ui.screen.home
|
||||
|
||||
import co.electriccoin.zcash.ui.design.component.BigIconButtonState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.HomeMessageState
|
||||
|
||||
data class HomeState(
|
||||
val firstButton: BigIconButtonState,
|
||||
|
@ -11,6 +10,6 @@ data class HomeState(
|
|||
val message: HomeMessageState?
|
||||
)
|
||||
|
||||
data class HomeRestoreDialogState(
|
||||
data class HomeRestoreSuccessDialogState(
|
||||
val onClick: () -> Unit
|
||||
)
|
||||
|
|
|
@ -32,8 +32,7 @@ import co.electriccoin.zcash.ui.fixture.BalanceStateFixture
|
|||
import co.electriccoin.zcash.ui.fixture.ZashiMainTopAppBarStateFixture
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceState
|
||||
import co.electriccoin.zcash.ui.screen.balances.BalanceWidget
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.HomeMessage
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetState
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.TransactionHistoryWidgetStateFixture
|
||||
import co.electriccoin.zcash.ui.screen.transactionhistory.widget.createTransactionHistoryWidgets
|
||||
|
|
|
@ -2,7 +2,6 @@ package co.electriccoin.zcash.ui.screen.home
|
|||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.sdk.ANDROID_STATE_FLOW_TIMEOUT
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.NavigationTargets
|
||||
|
@ -11,115 +10,61 @@ import co.electriccoin.zcash.ui.common.model.DistributionDimension
|
|||
import co.electriccoin.zcash.ui.common.model.KeystoneAccount
|
||||
import co.electriccoin.zcash.ui.common.model.WalletAccount
|
||||
import co.electriccoin.zcash.ui.common.provider.GetVersionInfoProvider
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetHomeMessageUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.GetSelectedWalletAccountUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.HomeMessageData
|
||||
import co.electriccoin.zcash.ui.common.usecase.IsRestoreSuccessDialogVisibleUseCase
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToCoinbaseUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.BigIconButtonState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.exchangerate.optin.ExchangeRateOptIn
|
||||
import co.electriccoin.zcash.ui.screen.home.balance.TransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.EnableCurrencyConversionMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.TransparentBalanceDetectedMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletBackupMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletDisconnectedMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletRestoringMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletSyncingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.messages.WalletUpdatingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.SeedBackupInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.currency.EnableCurrencyConversionMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.disconnected.WalletDisconnectedMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.error.WalletErrorMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.restoring.WalletRestoringInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.syncing.WalletSyncingInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.transparentbalance.TransparentBalanceInfo
|
||||
import co.electriccoin.zcash.ui.screen.home.updating.WalletUpdatingInfo
|
||||
import co.electriccoin.zcash.ui.screen.integrations.DialogIntegrations
|
||||
import co.electriccoin.zcash.ui.screen.receive.Receive
|
||||
import co.electriccoin.zcash.ui.screen.receive.model.ReceiveAddressType
|
||||
import co.electriccoin.zcash.ui.screen.scan.Scan
|
||||
import co.electriccoin.zcash.ui.screen.scan.ScanFlow
|
||||
import co.electriccoin.zcash.ui.screen.seed.backup.SeedBackup
|
||||
import co.electriccoin.zcash.ui.screen.home.backup.WalletBackupDetail
|
||||
import co.electriccoin.zcash.ui.screen.send.Send
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.WhileSubscribed
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class HomeViewModel(
|
||||
getHomeMessage: GetHomeMessageUseCase,
|
||||
getVersionInfoProvider: GetVersionInfoProvider,
|
||||
getSelectedWalletAccountUseCase: GetSelectedWalletAccountUseCase,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val isRestoreSuccessDialogVisible: IsRestoreSuccessDialogVisibleUseCase,
|
||||
private val navigateToCoinbase: NavigateToCoinbaseUseCase
|
||||
private val navigateToCoinbase: NavigateToCoinbaseUseCase,
|
||||
) : ViewModel() {
|
||||
@Suppress("MagicNumber")
|
||||
private val messageState =
|
||||
flow {
|
||||
val states =
|
||||
listOf(
|
||||
WalletErrorMessageState(
|
||||
onClick = {}
|
||||
),
|
||||
WalletDisconnectedMessageState(onClick = {
|
||||
navigationRouter.forward(WalletDisconnectedInfo)
|
||||
}),
|
||||
WalletRestoringMessageState(progress = 0, onClick = {
|
||||
navigationRouter.forward(WalletRestoringInfo)
|
||||
}),
|
||||
WalletRestoringMessageState(progress = 100, onClick = {
|
||||
navigationRouter.forward(WalletRestoringInfo)
|
||||
}),
|
||||
WalletSyncingMessageState(progress = 0, onClick = {
|
||||
navigationRouter.forward(WalletSyncingInfo)
|
||||
}),
|
||||
WalletSyncingMessageState(progress = 100, onClick = {
|
||||
navigationRouter.forward(WalletSyncingInfo)
|
||||
}),
|
||||
WalletUpdatingMessageState(onClick = {
|
||||
navigationRouter.forward(WalletUpdatingInfo)
|
||||
}),
|
||||
WalletBackupMessageState(
|
||||
onClick = {
|
||||
navigationRouter.forward(SeedBackupInfo)
|
||||
},
|
||||
onButtonClick = {
|
||||
navigationRouter.forward(SeedBackup(false))
|
||||
}
|
||||
),
|
||||
TransparentBalanceDetectedMessageState(
|
||||
subtitle = stringRes(zatoshi = Zatoshi(1000)),
|
||||
onClick = {
|
||||
navigationRouter.forward(TransparentBalanceInfo)
|
||||
},
|
||||
onButtonClick = {
|
||||
// navigationRouter.forward(TransparentBalanceInfo)
|
||||
},
|
||||
),
|
||||
EnableCurrencyConversionMessageState(
|
||||
onClick = {
|
||||
navigationRouter.forward(ExchangeRateOptIn)
|
||||
},
|
||||
onButtonClick = {
|
||||
navigationRouter.forward(ExchangeRateOptIn)
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
var index = 0
|
||||
|
||||
while (true) {
|
||||
emit(states[index])
|
||||
delay(3.seconds)
|
||||
if (index == states.lastIndex) {
|
||||
emit(null)
|
||||
delay(10.seconds)
|
||||
index = 0
|
||||
} else {
|
||||
index += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
private val messageState = getHomeMessage
|
||||
.observe()
|
||||
.map { createMessageState(it) }
|
||||
.stateIn(
|
||||
scope = viewModelScope,
|
||||
started = SharingStarted.WhileSubscribed(),
|
||||
initialValue = null
|
||||
)
|
||||
|
||||
private val isRestoreDialogVisible: Flow<Boolean?> =
|
||||
isRestoreSuccessDialogVisible
|
||||
|
@ -130,10 +75,10 @@ class HomeViewModel(
|
|||
initialValue = null
|
||||
)
|
||||
|
||||
val restoreDialogState: StateFlow<HomeRestoreDialogState?> =
|
||||
val restoreDialogState: StateFlow<HomeRestoreSuccessDialogState?> =
|
||||
isRestoreDialogVisible
|
||||
.map { isVisible ->
|
||||
HomeRestoreDialogState(
|
||||
HomeRestoreSuccessDialogState(
|
||||
onClick = ::onRestoreDialogSeenClick
|
||||
).takeIf { isVisible == true }
|
||||
}.stateIn(
|
||||
|
@ -203,6 +148,48 @@ class HomeViewModel(
|
|||
message = messageState
|
||||
)
|
||||
|
||||
private fun createMessageState(it: HomeMessageData?) = when (it) {
|
||||
is HomeMessageData.Backup -> WalletBackupMessageState(
|
||||
onClick = ::onWalletBackupMessageClick,
|
||||
onButtonClick = ::onWalletBackupMessageButtonClick,
|
||||
)
|
||||
|
||||
HomeMessageData.Disconnected -> WalletDisconnectedMessageState(
|
||||
onClick = ::onWalletDisconnectedMessageClick
|
||||
)
|
||||
|
||||
HomeMessageData.EnableCurrencyConversion -> EnableCurrencyConversionMessageState(
|
||||
onClick = ::onEnableCurrencyConversionClick,
|
||||
onButtonClick = ::onEnableCurrencyConversionClick
|
||||
)
|
||||
|
||||
is HomeMessageData.Error -> WalletErrorMessageState(
|
||||
onClick = { onWalletErrorMessageClick(it) }
|
||||
)
|
||||
|
||||
is HomeMessageData.Restoring -> WalletRestoringMessageState(
|
||||
progress = it.progress,
|
||||
onClick = ::onWalletRestoringMessageClick
|
||||
)
|
||||
|
||||
is HomeMessageData.Syncing -> WalletSyncingMessageState(
|
||||
progress = it.progress,
|
||||
onClick = ::onWalletSyncingMessageClick
|
||||
)
|
||||
|
||||
is HomeMessageData.TransparentBalance -> TransparentBalanceMessageState(
|
||||
subtitle = stringRes(zatoshi = it.zatoshi),
|
||||
onClick = ::onTransparentBalanceMessageClick,
|
||||
onButtonClick = ::onTransparentBalanceMessageButtonClick,
|
||||
)
|
||||
|
||||
HomeMessageData.Updating -> WalletUpdatingMessageState(
|
||||
onClick = ::onWalletUpdatingMessageClick
|
||||
)
|
||||
|
||||
null -> null
|
||||
}
|
||||
|
||||
private fun onRestoreDialogSeenClick() =
|
||||
viewModelScope.launch {
|
||||
isRestoreSuccessDialogVisible.setSeen()
|
||||
|
@ -232,4 +219,61 @@ class HomeViewModel(
|
|||
private fun onRequestClick() {
|
||||
navigationRouter.forward("${NavigationTargets.REQUEST}/${ReceiveAddressType.Unified.ordinal}")
|
||||
}
|
||||
|
||||
private fun onWalletUpdatingMessageClick() {
|
||||
navigationRouter.forward(WalletUpdatingInfo)
|
||||
}
|
||||
|
||||
private fun onWalletSyncingMessageClick() {
|
||||
navigationRouter.forward(WalletSyncingInfo)
|
||||
}
|
||||
|
||||
private fun onWalletRestoringMessageClick() {
|
||||
navigationRouter.forward(WalletRestoringInfo)
|
||||
}
|
||||
|
||||
private fun onEnableCurrencyConversionClick() {
|
||||
navigationRouter.forward(ExchangeRateOptIn)
|
||||
}
|
||||
|
||||
private fun onWalletDisconnectedMessageClick() {
|
||||
navigationRouter.forward(WalletDisconnectedInfo)
|
||||
}
|
||||
|
||||
private fun onWalletBackupMessageClick() {
|
||||
navigationRouter.forward(SeedBackupInfo)
|
||||
}
|
||||
|
||||
private fun onWalletBackupMessageButtonClick() {
|
||||
navigationRouter.forward(WalletBackupDetail(false))
|
||||
}
|
||||
|
||||
private fun onTransparentBalanceMessageClick() {
|
||||
navigationRouter.forward(TransparentBalanceInfo)
|
||||
}
|
||||
|
||||
private fun onTransparentBalanceMessageButtonClick(): Nothing {
|
||||
TODO()
|
||||
}
|
||||
|
||||
private fun onWalletErrorMessageClick(homeMessageData: HomeMessageData.Error): Nothing {
|
||||
// statusText =
|
||||
// context.getString(
|
||||
// R.string.balances_status_error_simple,
|
||||
// context.getString(R.string.app_name)
|
||||
// )
|
||||
// statusAction =
|
||||
// StatusAction.Error(
|
||||
// details =
|
||||
// context.getString(
|
||||
// R.string.balances_status_error_dialog_cause,
|
||||
// walletSnapshot.synchronizerError.getCauseMessage()
|
||||
// ?: context.getString(R.string.balances_status_error_dialog_cause_unknown),
|
||||
// walletSnapshot.synchronizerError.getStackTrace(limit = STACKTRACE_LIMIT)
|
||||
// ?: context.getString(R.string.balances_status_error_dialog_stacktrace_unknown)
|
||||
// ),
|
||||
// fullStackTrace = walletSnapshot.synchronizerError.getStackTrace(limit = null)
|
||||
// )
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
import org.koin.core.parameter.parametersOf
|
||||
|
||||
@Composable
|
||||
fun AndroidWalletBackupDetail(args: WalletBackupDetail) {
|
||||
val viewModel = koinViewModel<WalletBackupDetailViewModel> { parametersOf(args) }
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
BackHandler { state.onBack() }
|
||||
WalletBackupDetailView(state = state)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class WalletBackupDetail(
|
||||
val isOpenedFromSeedBackupInfo: Boolean
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.androidx.compose.koinViewModel
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AndroidWalletBackupInfo() {
|
||||
val viewModel = koinViewModel<WalletBackupInfoViewModel>()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
WalletBackupInfoView(state = state)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object SeedBackupInfo
|
|
@ -0,0 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
data class WalletBackupDetailState(
|
||||
val onBack: () -> Unit,
|
||||
val onNextClick: () -> Unit,
|
||||
val onInfoClick: () -> Unit,
|
||||
)
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.seed.backup
|
||||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
|
@ -20,7 +20,6 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.model.TopAppBarSubTitleState
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.HorizontalSpacer
|
||||
import co.electriccoin.zcash.ui.design.component.IconButtonState
|
||||
|
@ -38,12 +37,11 @@ import co.electriccoin.zcash.ui.design.util.scaffoldPadding
|
|||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
|
||||
@Composable
|
||||
fun SeedBackupView(
|
||||
state: SeedBackupState,
|
||||
appBarState: TopAppBarSubTitleState,
|
||||
fun WalletBackupDetailView(
|
||||
state: WalletBackupDetailState,
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = { AppBar(state = state, subTitleState = appBarState) }
|
||||
topBar = { AppBar(state = state) }
|
||||
) { paddingValues ->
|
||||
Content(
|
||||
modifier = Modifier.scaffoldPadding(paddingValues),
|
||||
|
@ -54,18 +52,11 @@ fun SeedBackupView(
|
|||
|
||||
@Composable
|
||||
private fun AppBar(
|
||||
state: SeedBackupState,
|
||||
subTitleState: TopAppBarSubTitleState,
|
||||
state: WalletBackupDetailState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
ZashiSmallTopAppBar(
|
||||
title = stringResource(R.string.wallet_backup_title),
|
||||
subtitle =
|
||||
when (subTitleState) {
|
||||
TopAppBarSubTitleState.Disconnected -> stringResource(id = R.string.disconnected_label)
|
||||
TopAppBarSubTitleState.Restoring -> stringResource(id = R.string.restoring_wallet_label)
|
||||
TopAppBarSubTitleState.None -> null
|
||||
},
|
||||
modifier = modifier,
|
||||
navigationAction = {
|
||||
ZashiTopAppBarBackNavigation(onBack = state.onBack)
|
||||
|
@ -85,7 +76,7 @@ private fun AppBar(
|
|||
|
||||
@Composable
|
||||
private fun Content(
|
||||
state: SeedBackupState,
|
||||
state: WalletBackupDetailState,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
|
@ -202,10 +193,9 @@ private fun Item(
|
|||
@PreviewScreens
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
SeedBackupView(
|
||||
appBarState = TopAppBarSubTitleState.None,
|
||||
WalletBackupDetailView(
|
||||
state =
|
||||
SeedBackupState(
|
||||
WalletBackupDetailState(
|
||||
onBack = {},
|
||||
onNextClick = {},
|
||||
onInfoClick = {}
|
|
@ -0,0 +1,43 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.common.usecase.NavigateToWalletBackupUseCase
|
||||
import co.electriccoin.zcash.ui.screen.restore.info.SeedInfo
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class WalletBackupDetailViewModel(
|
||||
private val args: WalletBackupDetail,
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val navigateToWalletBackup: NavigateToWalletBackupUseCase
|
||||
) : ViewModel() {
|
||||
val state = MutableStateFlow(
|
||||
WalletBackupDetailState(
|
||||
onBack = ::onBack,
|
||||
onNextClick = ::onNextClick,
|
||||
onInfoClick = ::onInfoClick
|
||||
)
|
||||
).asStateFlow()
|
||||
|
||||
private fun onNextClick() =
|
||||
viewModelScope.launch {
|
||||
navigateToWalletBackup(true)
|
||||
}
|
||||
|
||||
private fun onInfoClick() {
|
||||
navigationRouter.forward(SeedInfo)
|
||||
}
|
||||
|
||||
private fun onBack() {
|
||||
if (args.isOpenedFromSeedBackupInfo) {
|
||||
navigationRouter.replace(SeedBackupInfo)
|
||||
} else {
|
||||
navigationRouter.back()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.ModalBottomSheetState
|
||||
|
||||
data class WalletBackupInfoState(
|
||||
override val onBack: () -> Unit,
|
||||
val primaryButton: ButtonState,
|
||||
val secondaryButton: ButtonState
|
||||
) : ModalBottomSheetState
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home
|
||||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
|
@ -13,7 +13,6 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.component.Spacer
|
||||
|
@ -27,30 +26,16 @@ import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
|||
import co.electriccoin.zcash.ui.design.theme.colors.ZashiColors
|
||||
import co.electriccoin.zcash.ui.design.theme.typography.ZashiTypography
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.seed.backup.SeedBackup
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun AndroidSeedBackupInfo() {
|
||||
val navigationRouter = koinInject<NavigationRouter>()
|
||||
Content(
|
||||
onBack = { navigationRouter.back() },
|
||||
onPositiveClick = { navigationRouter.replace(SeedBackup(true)) }
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun Content(
|
||||
onBack: () -> Unit,
|
||||
onPositiveClick: () -> Unit,
|
||||
fun WalletBackupInfoView(
|
||||
state: WalletBackupInfoState?,
|
||||
sheetState: SheetState = rememberScreenModalBottomSheetState(),
|
||||
) {
|
||||
ZashiScreenModalBottomSheet(
|
||||
sheetState = sheetState,
|
||||
onDismissRequest = onBack
|
||||
state = state
|
||||
) {
|
||||
Column(
|
||||
modifier =
|
||||
|
@ -101,21 +86,13 @@ private fun Content(
|
|||
Spacer(32.dp)
|
||||
ZashiButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_remind_me_later),
|
||||
onClick = onBack
|
||||
),
|
||||
state = it.secondaryButton,
|
||||
colors = ZashiButtonDefaults.secondaryColors()
|
||||
)
|
||||
Spacer(4.dp)
|
||||
ZashiButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state =
|
||||
ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = onPositiveClick
|
||||
)
|
||||
state = it.primaryButton
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -126,11 +103,17 @@ private fun Content(
|
|||
@Composable
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
Content(
|
||||
onBack = {},
|
||||
onPositiveClick = {}
|
||||
WalletBackupInfoView(
|
||||
WalletBackupInfoState(
|
||||
onBack = {},
|
||||
secondaryButton = ButtonState(
|
||||
text = stringRes(R.string.general_remind_me_later),
|
||||
onClick = {}
|
||||
),
|
||||
primaryButton = ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = {}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Serializable
|
||||
object SeedBackupInfo
|
|
@ -0,0 +1,39 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import co.electriccoin.zcash.ui.NavigationRouter
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.common.usecase.RemindWalletBackupLaterUseCase
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class WalletBackupInfoViewModel(
|
||||
private val navigationRouter: NavigationRouter,
|
||||
private val remindWalletBackupLater: RemindWalletBackupLaterUseCase
|
||||
) : ViewModel() {
|
||||
val state: StateFlow<WalletBackupInfoState?> = MutableStateFlow(
|
||||
WalletBackupInfoState(
|
||||
onBack = ::onBack,
|
||||
secondaryButton = ButtonState(
|
||||
text = stringRes(R.string.general_remind_me_later),
|
||||
onClick = ::onRemindMeLaterClick
|
||||
),
|
||||
primaryButton = ButtonState(
|
||||
text = stringRes(R.string.general_ok),
|
||||
onClick = ::onPrimaryClick
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private fun onPrimaryClick() {
|
||||
navigationRouter.replace(WalletBackupDetail(true))
|
||||
}
|
||||
|
||||
private fun onRemindMeLaterClick() = viewModelScope.launch { remindWalletBackupLater() }
|
||||
|
||||
private fun onBack() = navigationRouter.back()
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.backup
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
|
@ -7,7 +7,6 @@ import androidx.compose.material3.LocalContentColor
|
|||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -20,6 +19,8 @@ import co.electriccoin.zcash.ui.design.component.ZashiButton
|
|||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -34,7 +35,6 @@ fun WalletBackupMessage(
|
|||
onClick = state.onClick,
|
||||
start = {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Top),
|
||||
painter = painterResource(R.drawable.ic_warning_triangle),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(LocalContentColor.current)
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.currency
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
|
@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.height
|
|||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -19,6 +18,8 @@ import co.electriccoin.zcash.ui.design.component.ZashiButton
|
|||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.design.util.stringRes
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -33,7 +34,6 @@ fun EnableCurrencyConversionMessage(
|
|||
onClick = state.onClick,
|
||||
start = {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Top),
|
||||
painter = painterResource(R.drawable.ic_message_currency_conversion),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(LocalContentColor.current)
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home
|
||||
package co.electriccoin.zcash.ui.screen.home.disconnected
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
|
@ -1,11 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.disconnected
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -15,6 +14,8 @@ import co.electriccoin.zcash.ui.R
|
|||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -29,7 +30,6 @@ fun WalletDisconnectedMessage(
|
|||
onClick = state.onClick,
|
||||
start = {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Top),
|
||||
painter = painterResource(R.drawable.ic_message_disconnected),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(LocalContentColor.current)
|
|
@ -1,11 +1,10 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.error
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.material3.LocalContentColor
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.res.painterResource
|
||||
|
@ -15,6 +14,8 @@ import co.electriccoin.zcash.ui.R
|
|||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -29,7 +30,6 @@ fun WalletErrorMessage(
|
|||
onClick = state.onClick,
|
||||
start = {
|
||||
Image(
|
||||
modifier = Modifier.align(Alignment.Top),
|
||||
painter = painterResource(R.drawable.ic_warning_triangle),
|
||||
contentDescription = null,
|
||||
colorFilter = ColorFilter.tint(LocalContentColor.current)
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home
|
||||
package co.electriccoin.zcash.ui.screen.home.restoring
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@ -1,7 +1,6 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.restoring
|
||||
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.animation.core.animateIntAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
@ -13,9 +12,11 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicator
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicatorByPercent
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -29,7 +30,7 @@ fun WalletRestoringMessage(
|
|||
contentPadding = contentPadding,
|
||||
onClick = state.onClick,
|
||||
start = {
|
||||
ZashiCircularProgressIndicator(
|
||||
ZashiCircularProgressIndicatorByPercent(
|
||||
modifier = Modifier.size(20.dp),
|
||||
progressPercent = state.progress,
|
||||
)
|
||||
|
@ -49,7 +50,7 @@ fun WalletRestoringMessage(
|
|||
}
|
||||
|
||||
class WalletRestoringMessageState(
|
||||
@IntRange(from = 0, to = 100) val progress: Int,
|
||||
val progress: Float,
|
||||
val onClick: () -> Unit
|
||||
) : HomeMessageState
|
||||
|
||||
|
@ -57,7 +58,7 @@ class WalletRestoringMessageState(
|
|||
@Composable
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
val progress by animateIntAsState(50, label = "progress", animationSpec = tween(10000))
|
||||
val progress by animateFloatAsState(50f, label = "progress", animationSpec = tween(10000))
|
||||
|
||||
BlankSurface {
|
||||
WalletRestoringMessage(
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home
|
||||
package co.electriccoin.zcash.ui.screen.home.syncing
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
@ -1,7 +1,6 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.messages
|
||||
package co.electriccoin.zcash.ui.screen.home.syncing
|
||||
|
||||
import androidx.annotation.IntRange
|
||||
import androidx.compose.animation.core.animateIntAsState
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
@ -13,9 +12,11 @@ import androidx.compose.ui.res.stringResource
|
|||
import androidx.compose.ui.unit.dp
|
||||
import co.electriccoin.zcash.ui.R
|
||||
import co.electriccoin.zcash.ui.design.component.BlankSurface
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicator
|
||||
import co.electriccoin.zcash.ui.design.component.ZashiCircularProgressIndicatorByPercent
|
||||
import co.electriccoin.zcash.ui.design.newcomponent.PreviewScreens
|
||||
import co.electriccoin.zcash.ui.design.theme.ZcashTheme
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageState
|
||||
import co.electriccoin.zcash.ui.screen.home.HomeMessageWrapper
|
||||
|
||||
@Suppress("ModifierNaming")
|
||||
@Composable
|
||||
|
@ -29,7 +30,7 @@ fun WalletSyncingMessage(
|
|||
contentPadding = contentPadding,
|
||||
onClick = state.onClick,
|
||||
start = {
|
||||
ZashiCircularProgressIndicator(
|
||||
ZashiCircularProgressIndicatorByPercent(
|
||||
modifier = Modifier.size(20.dp),
|
||||
progressPercent = state.progress,
|
||||
)
|
||||
|
@ -49,7 +50,7 @@ fun WalletSyncingMessage(
|
|||
}
|
||||
|
||||
class WalletSyncingMessageState(
|
||||
@IntRange(from = 0, to = 100) val progress: Int,
|
||||
val progress: Float,
|
||||
val onClick: () -> Unit
|
||||
) : HomeMessageState
|
||||
|
||||
|
@ -57,7 +58,7 @@ class WalletSyncingMessageState(
|
|||
@Composable
|
||||
private fun Preview() =
|
||||
ZcashTheme {
|
||||
val progress by animateIntAsState(50, label = "progress", animationSpec = tween(10000))
|
||||
val progress by animateFloatAsState(50f, label = "progress", animationSpec = tween(10000))
|
||||
|
||||
BlankSurface {
|
||||
WalletSyncingMessage(
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.balance
|
||||
package co.electriccoin.zcash.ui.screen.home.transparentbalance
|
||||
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.runtime.Composable
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.balance
|
||||
package co.electriccoin.zcash.ui.screen.home.transparentbalance
|
||||
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import co.electriccoin.zcash.ui.design.component.ButtonState
|
|
@ -1,4 +1,4 @@
|
|||
package co.electriccoin.zcash.ui.screen.home.balance
|
||||
package co.electriccoin.zcash.ui.screen.home.transparentbalance
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue