mirror of
https://github.com/bitwarden/android.git
synced 2026-06-02 18:59:15 -05:00
BIT-2101 BIT-2103: Update export flow for JSON (password protected) (#1188)
This commit is contained in:
committed by
Álison Fernandes
parent
3565054a4c
commit
90ff2897f5
@@ -34,6 +34,7 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.auth.feature.createaccount.PasswordStrengthIndicator
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
|
||||
@@ -164,9 +165,15 @@ fun ExportVaultScreen(
|
||||
) { innerPadding ->
|
||||
ExportVaultScreenContent(
|
||||
state = state,
|
||||
onConfirmFilePasswordInputChanged = remember(viewModel) {
|
||||
{ viewModel.trySendAction(ExportVaultAction.ConfirmFilePasswordInputChange(it)) }
|
||||
},
|
||||
onExportFormatOptionSelected = remember(viewModel) {
|
||||
{ viewModel.trySendAction(ExportVaultAction.ExportFormatOptionSelect(it)) }
|
||||
},
|
||||
onFilePasswordInputChanged = remember(viewModel) {
|
||||
{ viewModel.trySendAction(ExportVaultAction.FilePasswordInputChange(it)) }
|
||||
},
|
||||
onPasswordInputChanged = remember(viewModel) {
|
||||
{ viewModel.trySendAction(ExportVaultAction.PasswordInputChanged(it)) }
|
||||
},
|
||||
@@ -182,7 +189,9 @@ fun ExportVaultScreen(
|
||||
@Suppress("LongMethod")
|
||||
private fun ExportVaultScreenContent(
|
||||
state: ExportVaultState,
|
||||
onConfirmFilePasswordInputChanged: (String) -> Unit,
|
||||
onExportFormatOptionSelected: (ExportVaultFormat) -> Unit,
|
||||
onFilePasswordInputChanged: (String) -> Unit,
|
||||
onPasswordInputChanged: (String) -> Unit,
|
||||
onExportVaultClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -226,6 +235,37 @@ private fun ExportVaultScreenContent(
|
||||
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
if (state.exportFormat == ExportVaultFormat.JSON_ENCRYPTED) {
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.file_password),
|
||||
value = state.filePasswordInput,
|
||||
onValueChange = onFilePasswordInputChanged,
|
||||
hint = stringResource(id = R.string.password_used_to_export),
|
||||
modifier = Modifier
|
||||
.semantics { testTag = "FilePasswordEntry" }
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
|
||||
PasswordStrengthIndicator(
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
state = state.passwordStrengthState,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.confirm_file_password),
|
||||
value = state.confirmFilePasswordInput,
|
||||
onValueChange = onConfirmFilePasswordInputChanged,
|
||||
modifier = Modifier
|
||||
.semantics { testTag = "ConfirmFilePasswordEntry" }
|
||||
.padding(horizontal = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
BitwardenPasswordField(
|
||||
label = stringResource(id = R.string.master_password),
|
||||
value = state.passwordInput,
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.x8bit.bitwarden.data.vault.datasource.network.model.PolicyTypeJson
|
||||
import com.x8bit.bitwarden.data.vault.manager.FileManager
|
||||
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
|
||||
import com.x8bit.bitwarden.data.vault.repository.model.ExportVaultDataResult
|
||||
import com.x8bit.bitwarden.ui.auth.feature.createaccount.PasswordStrengthState
|
||||
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.Text
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
@@ -46,10 +47,13 @@ class ExportVaultViewModel @Inject constructor(
|
||||
) : BaseViewModel<ExportVaultState, ExportVaultEvent, ExportVaultAction>(
|
||||
initialState = savedStateHandle[KEY_STATE]
|
||||
?: ExportVaultState(
|
||||
confirmFilePasswordInput = "",
|
||||
dialogState = null,
|
||||
exportData = null,
|
||||
exportFormat = ExportVaultFormat.JSON,
|
||||
filePasswordInput = "",
|
||||
passwordInput = "",
|
||||
passwordStrengthState = PasswordStrengthState.NONE,
|
||||
policyPreventsExport = policyManager
|
||||
.getActivePolicies(type = PolicyTypeJson.DISABLE_PERSONAL_VAULT_EXPORT)
|
||||
.any(),
|
||||
@@ -66,7 +70,12 @@ class ExportVaultViewModel @Inject constructor(
|
||||
when (action) {
|
||||
ExportVaultAction.CloseButtonClick -> handleCloseButtonClicked()
|
||||
ExportVaultAction.ConfirmExportVaultClicked -> handleConfirmExportVaultClicked()
|
||||
is ExportVaultAction.ConfirmFilePasswordInputChange -> {
|
||||
handleConfirmFilePasswordInputChanged(action)
|
||||
}
|
||||
|
||||
ExportVaultAction.DialogDismiss -> handleDialogDismiss()
|
||||
is ExportVaultAction.FilePasswordInputChange -> handleFilePasswordInputChanged(action)
|
||||
is ExportVaultAction.ExportFormatOptionSelect -> handleExportFormatOptionSelect(action)
|
||||
is ExportVaultAction.PasswordInputChanged -> handlePasswordInputChanged(action)
|
||||
is ExportVaultAction.ExportLocationReceive -> handleExportLocationReceive(action)
|
||||
@@ -118,6 +127,17 @@ class ExportVaultViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with the new confirm file password input.
|
||||
*/
|
||||
private fun handleConfirmFilePasswordInputChanged(
|
||||
action: ExportVaultAction.ConfirmFilePasswordInputChange,
|
||||
) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(confirmFilePasswordInput = action.input)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismiss the dialog.
|
||||
*/
|
||||
@@ -155,6 +175,15 @@ class ExportVaultViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with the new file password input.
|
||||
*/
|
||||
private fun handleFilePasswordInputChanged(action: ExportVaultAction.FilePasswordInputChange) {
|
||||
mutableStateFlow.update {
|
||||
it.copy(filePasswordInput = action.input)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the state with the new password input.
|
||||
*/
|
||||
@@ -267,9 +296,12 @@ class ExportVaultViewModel @Inject constructor(
|
||||
data class ExportVaultState(
|
||||
@IgnoredOnParcel
|
||||
val exportData: String? = null,
|
||||
val confirmFilePasswordInput: String,
|
||||
val dialogState: DialogState?,
|
||||
val exportFormat: ExportVaultFormat,
|
||||
val filePasswordInput: String,
|
||||
val passwordInput: String,
|
||||
val passwordStrengthState: PasswordStrengthState,
|
||||
val policyPreventsExport: Boolean,
|
||||
) : Parcelable {
|
||||
/**
|
||||
@@ -330,6 +362,11 @@ sealed class ExportVaultAction {
|
||||
*/
|
||||
data object ConfirmExportVaultClicked : ExportVaultAction()
|
||||
|
||||
/**
|
||||
* Indicates that the confirm file password input has changed.
|
||||
*/
|
||||
data class ConfirmFilePasswordInputChange(val input: String) : ExportVaultAction()
|
||||
|
||||
/**
|
||||
* Indicates that the dialog has been dismissed.
|
||||
*/
|
||||
@@ -347,6 +384,11 @@ sealed class ExportVaultAction {
|
||||
val fileUri: Uri,
|
||||
) : ExportVaultAction()
|
||||
|
||||
/**
|
||||
* Indicates that the file password input has changed.
|
||||
*/
|
||||
data class FilePasswordInputChange(val input: String) : ExportVaultAction()
|
||||
|
||||
/**
|
||||
* Indicates that the password input has changed.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user