-
Notifications
You must be signed in to change notification settings - Fork 927
[PM-26909] Implement screen capture toggle authenticator #6033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ import com.bitwarden.ui.platform.base.util.cardStyle | |
| import com.bitwarden.ui.platform.base.util.mirrorIfRtl | ||
| import com.bitwarden.ui.platform.base.util.standardHorizontalMargin | ||
| import com.bitwarden.ui.platform.components.appbar.BitwardenMediumTopAppBar | ||
| import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog | ||
| import com.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton | ||
| import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText | ||
| import com.bitwarden.ui.platform.components.model.CardStyle | ||
|
|
@@ -157,6 +158,13 @@ fun SettingsScreen( | |
| ) | ||
| } | ||
| }, | ||
| onScreenCaptureChange = remember(viewModel) { | ||
| { | ||
| viewModel.trySendAction( | ||
| SettingsAction.SecurityClick.AllowScreenCaptureToggle(it), | ||
| ) | ||
| } | ||
| }, | ||
| ) | ||
| Spacer(modifier = Modifier.height(16.dp)) | ||
| VaultSettings( | ||
|
|
@@ -256,27 +264,44 @@ private fun SecuritySettings( | |
| state: SettingsState, | ||
| biometricsManager: BiometricsManager = LocalBiometricsManager.current, | ||
| onBiometricToggle: (Boolean) -> Unit, | ||
| onScreenCaptureChange: (Boolean) -> Unit, | ||
| ) { | ||
| if (!biometricsManager.isBiometricsSupported) return | ||
| Spacer(modifier = Modifier.height(height = 12.dp)) | ||
| BitwardenListHeaderText( | ||
| modifier = Modifier | ||
| .standardHorizontalMargin() | ||
| .padding(horizontal = 16.dp), | ||
| label = stringResource(id = BitwardenString.security), | ||
| ) | ||
|
|
||
| Spacer(modifier = Modifier.height(8.dp)) | ||
| UnlockWithBiometricsRow( | ||
| val hasBiometrics = biometricsManager.isBiometricsSupported | ||
| if (hasBiometrics) { | ||
| UnlockWithBiometricsRow( | ||
| modifier = Modifier | ||
| .testTag("UnlockWithBiometricsSwitch") | ||
| .fillMaxWidth() | ||
| .standardHorizontalMargin(), | ||
| isChecked = state.isUnlockWithBiometricsEnabled, | ||
| onBiometricToggle = { onBiometricToggle(it) }, | ||
| biometricsManager = biometricsManager, | ||
| ) | ||
| } | ||
|
|
||
| ScreenCaptureRow( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're missing the 8dp spacer before this item
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless the intention is to make this a single card?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is missing |
||
| currentValue = state.allowScreenCapture, | ||
| cardStyle = if (hasBiometrics) { | ||
| CardStyle.Bottom | ||
| } else { | ||
| CardStyle.Full | ||
| }, | ||
| onValueChange = onScreenCaptureChange, | ||
| modifier = Modifier | ||
| .testTag("UnlockWithBiometricsSwitch") | ||
| .fillMaxWidth() | ||
| .testTag(tag = "AllowScreenCaptureSwitch") | ||
| .standardHorizontalMargin(), | ||
| isChecked = state.isUnlockWithBiometricsEnabled, | ||
| onBiometricToggle = { onBiometricToggle(it) }, | ||
| biometricsManager = biometricsManager, | ||
| ) | ||
| } | ||
|
|
||
| //endregion | ||
|
|
||
| //region Data settings | ||
|
|
@@ -421,7 +446,7 @@ private fun UnlockWithBiometricsRow( | |
| var showBiometricsPrompt by rememberSaveable { mutableStateOf(false) } | ||
| BitwardenSwitch( | ||
| modifier = modifier, | ||
| cardStyle = CardStyle.Full, | ||
| cardStyle = CardStyle.Top(), | ||
| label = stringResource(BitwardenString.unlock_with_biometrics), | ||
| isChecked = isChecked || showBiometricsPrompt, | ||
| onCheckedChange = { toggled -> | ||
|
|
@@ -443,6 +468,47 @@ private fun UnlockWithBiometricsRow( | |
| ) | ||
| } | ||
|
|
||
| @Composable | ||
| private fun ScreenCaptureRow( | ||
| currentValue: Boolean, | ||
| cardStyle: CardStyle, | ||
| onValueChange: (Boolean) -> Unit, | ||
| modifier: Modifier = Modifier, | ||
| ) { | ||
| var shouldShowScreenCaptureConfirmDialog by remember { mutableStateOf(false) } | ||
|
|
||
| BitwardenSwitch( | ||
| label = stringResource(id = BitwardenString.allow_screen_capture), | ||
| isChecked = currentValue, | ||
| onCheckedChange = { | ||
| if (currentValue) { | ||
| onValueChange(false) | ||
| } else { | ||
| shouldShowScreenCaptureConfirmDialog = true | ||
| } | ||
| }, | ||
| cardStyle = cardStyle, | ||
| modifier = modifier, | ||
| ) | ||
|
|
||
| if (shouldShowScreenCaptureConfirmDialog) { | ||
| BitwardenTwoButtonDialog( | ||
| title = stringResource(BitwardenString.allow_screen_capture), | ||
| message = stringResource( | ||
| id = BitwardenString.are_you_sure_you_want_to_enable_screen_capture, | ||
| ), | ||
| confirmButtonText = stringResource(BitwardenString.yes), | ||
| dismissButtonText = stringResource(id = BitwardenString.cancel), | ||
| onConfirmClick = { | ||
| onValueChange(true) | ||
| shouldShowScreenCaptureConfirmDialog = false | ||
| }, | ||
| onDismissClick = { shouldShowScreenCaptureConfirmDialog = false }, | ||
| onDismissRequest = { shouldShowScreenCaptureConfirmDialog = false }, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| //endregion Data settings | ||
|
|
||
| //region Appearance settings | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,6 +58,7 @@ class SettingsViewModel @Inject constructor( | |
| accountSyncState = authenticatorBridgeManager.accountSyncStateFlow.value, | ||
| defaultSaveOption = settingsRepository.defaultSaveOption, | ||
| sharedAccountsState = authenticatorRepository.sharedCodesStateFlow.value, | ||
| isScreenCaptureAllowed = settingsRepository.isScreenCaptureAllowed, | ||
| ), | ||
| ) { | ||
|
|
||
|
|
@@ -126,6 +127,10 @@ class SettingsViewModel @Inject constructor( | |
| is SettingsAction.SecurityClick.UnlockWithBiometricToggle -> { | ||
| handleBiometricsSetupClick(action) | ||
| } | ||
|
|
||
| is SettingsAction.SecurityClick.AllowScreenCaptureToggle -> { | ||
| handleAllowScreenCaptureToggle(action) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for that! ๐ |
||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -173,6 +178,13 @@ class SettingsViewModel @Inject constructor( | |
| } | ||
| } | ||
|
|
||
| private fun handleAllowScreenCaptureToggle( | ||
| action: SettingsAction.SecurityClick.AllowScreenCaptureToggle, | ||
| ) { | ||
| settingsRepository.isScreenCaptureAllowed = action.enabled | ||
| mutableStateFlow.update { it.copy(allowScreenCapture = action.enabled) } | ||
| } | ||
|
|
||
| private fun handleVaultClick(action: SettingsAction.DataClick) { | ||
| when (action) { | ||
| SettingsAction.DataClick.ExportClick -> handleExportClick() | ||
|
|
@@ -319,6 +331,7 @@ class SettingsViewModel @Inject constructor( | |
| isSubmitCrashLogsEnabled: Boolean, | ||
| accountSyncState: AccountSyncState, | ||
| sharedAccountsState: SharedVerificationCodesState, | ||
| isScreenCaptureAllowed: Boolean, | ||
| ): SettingsState { | ||
| val currentYear = Year.now(clock) | ||
| val copyrightInfo = "ยฉ Bitwarden Inc. 2015-$currentYear".asText() | ||
|
|
@@ -343,6 +356,7 @@ class SettingsViewModel @Inject constructor( | |
| defaultSaveOption = defaultSaveOption, | ||
| showSyncWithBitwarden = shouldShowSyncWithBitwarden, | ||
| showDefaultSaveOptionRow = shouldShowDefaultSaveOption, | ||
| allowScreenCapture = isScreenCaptureAllowed, | ||
| ) | ||
| } | ||
| } | ||
|
|
@@ -362,6 +376,7 @@ data class SettingsState( | |
| val dialog: Dialog?, | ||
| val version: Text, | ||
| val copyrightInfo: Text, | ||
| val allowScreenCapture: Boolean, | ||
| ) : Parcelable { | ||
|
|
||
| /** | ||
|
|
@@ -460,13 +475,18 @@ sealed class SettingsAction( | |
| } | ||
|
|
||
| /** | ||
| * Indicates the user clicked the Unlock with biometrics button. | ||
| * Models actions for the Security section of settings. | ||
| */ | ||
| sealed class SecurityClick : SettingsAction() { | ||
| /** | ||
| * Indicates the user clicked unlock with biometrics toggle. | ||
| */ | ||
| data class UnlockWithBiometricToggle(val enabled: Boolean) : SecurityClick() | ||
|
|
||
| /** | ||
| * Indicates the user clicked allow screen capture toggle. | ||
| */ | ||
| data class AllowScreenCaptureToggle(val enabled: Boolean) : SecurityClick() | ||
| } | ||
|
|
||
| /** | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this change intentional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, I moved
isScreenCaptureAllowedStateFlowto be right after theisScreenCaptureAllowed.There was
previouslySyncedBitwardenAccountIdsbetween them, very minor but made me not see it immediately