[PM-22640] Re-added isScreenCaptureAllowed to the MainViewModel state (#5462)

This commit is contained in:
aj-rosado
2025-07-02 19:18:33 +01:00
committed by GitHub
parent 9940c8cf9e
commit defdf8eb58
4 changed files with 30 additions and 55 deletions

View File

@@ -84,6 +84,7 @@ class MainActivity : AppCompatActivity() {
val navController = rememberBitwardenNavController(name = "MainActivity")
SetupEventsEffect(navController = navController)
val state by mainViewModel.stateFlow.collectAsStateWithLifecycle()
updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed)
LocalManagerProvider(featureFlagsState = state.featureFlagsState) {
ObserveScreenDataEffect(
onDataUpdate = remember(mainViewModel) {
@@ -185,10 +186,6 @@ class MainActivity : AppCompatActivity() {
}
is MainEvent.UpdateAppTheme -> AppCompatDelegate.setDefaultNightMode(event.osTheme)
is MainEvent.ScreenCaptureSettingChange -> {
handleScreenCaptureSettingChange(isScreenCaptureAllowed = event.isAllowed)
}
}
}
}
@@ -217,7 +214,7 @@ class MainActivity : AppCompatActivity() {
recreate()
}
private fun handleScreenCaptureSettingChange(isScreenCaptureAllowed: Boolean) {
private fun updateScreenCapture(isScreenCaptureAllowed: Boolean) {
if (isScreenCaptureAllowed) {
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
} else {

View File

@@ -84,6 +84,7 @@ class MainViewModel @Inject constructor(
) : BaseViewModel<MainState, MainEvent, MainAction>(
initialState = MainState(
theme = settingsRepository.appTheme,
isScreenCaptureAllowed = settingsRepository.isScreenCaptureAllowed,
isErrorReportingDialogEnabled = featureFlagManager.getFeatureFlag(
key = FlagKey.MobileErrorReporting,
),
@@ -264,7 +265,7 @@ class MainViewModel @Inject constructor(
}
private fun handleScreenCaptureUpdate(action: MainAction.Internal.ScreenCaptureUpdate) {
sendEvent(MainEvent.ScreenCaptureSettingChange(isAllowed = action.isScreenCaptureEnabled))
mutableStateFlow.update { it.copy(isScreenCaptureAllowed = action.isScreenCaptureEnabled) }
}
private fun handleAppThemeUpdated(action: MainAction.Internal.ThemeUpdate) {
@@ -492,6 +493,7 @@ class MainViewModel @Inject constructor(
@Parcelize
data class MainState(
val theme: AppTheme,
val isScreenCaptureAllowed: Boolean,
val isDynamicColorsEnabled: Boolean,
private val isErrorReportingDialogEnabled: Boolean,
) : Parcelable {
@@ -637,9 +639,4 @@ sealed class MainEvent {
data class UpdateAppTheme(
val osTheme: Int,
) : MainEvent()
/**
* Event indicating a change in the screen capture setting.
*/
data class ScreenCaptureSettingChange(val isAllowed: Boolean) : MainEvent()
}

View File

@@ -93,7 +93,7 @@ class SettingsDiskSourceImpl(
private val mutableHasSeenGeneratorCoachMarkFlow = bufferedMutableSharedFlow<Boolean?>()
private val mutableScreenCaptureAllowedFlow = bufferedMutableSharedFlow<Boolean?>(replay = 1)
private val mutableScreenCaptureAllowedFlow = bufferedMutableSharedFlow<Boolean?>()
private val mutableVaultRegisteredForExportFlow =
mutableMapOf<String, MutableSharedFlow<Boolean?>>()

View File

@@ -243,9 +243,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -296,9 +294,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -319,9 +315,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
val cipherView = mockk<CipherView>()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -338,9 +332,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
val cipherView = mockk<CipherView>()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -373,9 +365,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.stateEventFlow(backgroundScope) { stateFlow, eventFlow ->
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
eventFlow.awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
eventFlow.awaitItem()
eventFlow.awaitItem()
@@ -398,9 +388,7 @@ class MainViewModelTest : BaseViewModelTest() {
val viewModel = createViewModel()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -608,9 +596,7 @@ class MainViewModelTest : BaseViewModelTest() {
} returns EmailTokenResult.Error(message = null, error = Throwable("Fail!"))
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -644,9 +630,7 @@ class MainViewModelTest : BaseViewModelTest() {
} returns EmailTokenResult.Error(message = expectedMessage, error = null)
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -1021,13 +1005,25 @@ class MainViewModelTest : BaseViewModelTest() {
)
}
@Test
fun `changes in the allowed screen capture value should update the state`() {
val viewModel = createViewModel()
assertEquals(DEFAULT_STATE, viewModel.stateFlow.value)
mutableScreenCaptureAllowedFlow.value = false
assertEquals(
DEFAULT_STATE.copy(isScreenCaptureAllowed = false),
viewModel.stateFlow.value,
)
}
@Test
fun `send NavigateToDebugMenu action when OpenDebugMenu action is sent`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
// We skip the first 2 events because they are the default appTheme and appLanguage
awaitItem()
awaitItem()
@@ -1121,22 +1117,6 @@ class MainViewModelTest : BaseViewModelTest() {
verify { settingsRepository.appLanguage = AppLanguage.SPANISH }
}
@Test
fun `on ScreenCaptureUpdate should trigger the ScreenCaptureSettingChange event`() = runTest {
val viewModel = createViewModel()
viewModel.eventFlow.test {
// We skip the first 3 events because they are the
// default appTheme, appLanguage and ScreenCaptureUpdate
awaitItem()
awaitItem()
awaitItem()
viewModel.trySendAction(MainAction.Internal.ScreenCaptureUpdate(true))
assertEquals(MainEvent.ScreenCaptureSettingChange(true), awaitItem())
}
}
private fun createViewModel(
initialSpecialCircumstance: SpecialCircumstance? = null,
) = MainViewModel(
@@ -1162,6 +1142,7 @@ class MainViewModelTest : BaseViewModelTest() {
private val DEFAULT_STATE: MainState = MainState(
theme = AppTheme.DEFAULT,
isScreenCaptureAllowed = true,
isErrorReportingDialogEnabled = false,
isDynamicColorsEnabled = false,
)