mirror of
https://github.com/bitwarden/android.git
synced 2025-12-11 13:57:03 -06:00
[PM-27092] Changing screen capture flow from event based to state based on Authenticator (#6062)
This commit is contained in:
parent
38bdda0a41
commit
be27c76bd3
@ -62,6 +62,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
setupEdgeToEdge(appThemeFlow = mainViewModel.stateFlow.map { it.theme })
|
setupEdgeToEdge(appThemeFlow = mainViewModel.stateFlow.map { it.theme })
|
||||||
setContent {
|
setContent {
|
||||||
val state by mainViewModel.stateFlow.collectAsStateWithLifecycle()
|
val state by mainViewModel.stateFlow.collectAsStateWithLifecycle()
|
||||||
|
updateScreenCapture(isScreenCaptureAllowed = state.isScreenCaptureAllowed)
|
||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
observeViewModelEvents(navController)
|
observeViewModelEvents(navController)
|
||||||
LocalManagerProvider {
|
LocalManagerProvider {
|
||||||
@ -96,10 +97,6 @@ class MainActivity : AppCompatActivity() {
|
|||||||
.eventFlow
|
.eventFlow
|
||||||
.onEach { event ->
|
.onEach { event ->
|
||||||
when (event) {
|
when (event) {
|
||||||
is MainEvent.ScreenCaptureSettingChange -> {
|
|
||||||
handleScreenCaptureSettingChange(event)
|
|
||||||
}
|
|
||||||
|
|
||||||
MainEvent.NavigateToDebugMenu -> navController.navigateToDebugMenuScreen()
|
MainEvent.NavigateToDebugMenu -> navController.navigateToDebugMenuScreen()
|
||||||
is MainEvent.UpdateAppTheme -> {
|
is MainEvent.UpdateAppTheme -> {
|
||||||
AppCompatDelegate.setDefaultNightMode(event.osTheme)
|
AppCompatDelegate.setDefaultNightMode(event.osTheme)
|
||||||
@ -123,8 +120,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
mainViewModel.trySendAction(MainAction.OpenDebugMenu)
|
mainViewModel.trySendAction(MainAction.OpenDebugMenu)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleScreenCaptureSettingChange(event: MainEvent.ScreenCaptureSettingChange) {
|
private fun updateScreenCapture(isScreenCaptureAllowed: Boolean) {
|
||||||
if (event.isAllowed) {
|
if (isScreenCaptureAllowed) {
|
||||||
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
} else {
|
} else {
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
window.addFlags(WindowManager.LayoutParams.FLAG_SECURE)
|
||||||
|
|||||||
@ -26,6 +26,7 @@ class MainViewModel @Inject constructor(
|
|||||||
) : BaseViewModel<MainState, MainEvent, MainAction>(
|
) : BaseViewModel<MainState, MainEvent, MainAction>(
|
||||||
MainState(
|
MainState(
|
||||||
theme = settingsRepository.appTheme,
|
theme = settingsRepository.appTheme,
|
||||||
|
isScreenCaptureAllowed = settingsRepository.isScreenCaptureAllowed,
|
||||||
isDynamicColorsEnabled = settingsRepository.isDynamicColorsEnabled,
|
isDynamicColorsEnabled = settingsRepository.isDynamicColorsEnabled,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
@ -43,9 +44,10 @@ class MainViewModel @Inject constructor(
|
|||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
settingsRepository
|
settingsRepository
|
||||||
.isScreenCaptureAllowedStateFlow
|
.isScreenCaptureAllowedStateFlow
|
||||||
.map { MainEvent.ScreenCaptureSettingChange(it) }
|
.map { MainAction.Internal.ScreenCaptureUpdate(it) }
|
||||||
.onEach(::sendEvent)
|
.onEach(::sendAction)
|
||||||
.launchIn(viewModelScope)
|
.launchIn(viewModelScope)
|
||||||
|
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
configRepository.getServerConfig(forceRefresh = false)
|
configRepository.getServerConfig(forceRefresh = false)
|
||||||
}
|
}
|
||||||
@ -64,6 +66,10 @@ class MainViewModel @Inject constructor(
|
|||||||
when (action) {
|
when (action) {
|
||||||
is MainAction.Internal.DynamicColorUpdate -> handleDynamicColorUpdate(action)
|
is MainAction.Internal.DynamicColorUpdate -> handleDynamicColorUpdate(action)
|
||||||
is MainAction.Internal.ThemeUpdate -> handleThemeUpdated(action)
|
is MainAction.Internal.ThemeUpdate -> handleThemeUpdated(action)
|
||||||
|
|
||||||
|
is MainAction.Internal.ScreenCaptureUpdate -> handleScreenCaptureUpdate(
|
||||||
|
screenCaptureUpdateAction = action,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,6 +100,16 @@ class MainViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleScreenCaptureUpdate(
|
||||||
|
screenCaptureUpdateAction: MainAction.Internal.ScreenCaptureUpdate,
|
||||||
|
) {
|
||||||
|
mutableStateFlow.update {
|
||||||
|
it.copy(
|
||||||
|
isScreenCaptureAllowed = screenCaptureUpdateAction.isScreenCaptureEnabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleIntent(
|
private fun handleIntent(
|
||||||
intent: Intent,
|
intent: Intent,
|
||||||
isFirstIntent: Boolean,
|
isFirstIntent: Boolean,
|
||||||
@ -109,6 +125,7 @@ class MainViewModel @Inject constructor(
|
|||||||
data class MainState(
|
data class MainState(
|
||||||
val theme: AppTheme,
|
val theme: AppTheme,
|
||||||
val isDynamicColorsEnabled: Boolean,
|
val isDynamicColorsEnabled: Boolean,
|
||||||
|
val isScreenCaptureAllowed: Boolean,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,6 +164,13 @@ sealed class MainAction {
|
|||||||
data class ThemeUpdate(
|
data class ThemeUpdate(
|
||||||
val theme: AppTheme,
|
val theme: AppTheme,
|
||||||
) : Internal()
|
) : Internal()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates that the screen capture state has changed.
|
||||||
|
*/
|
||||||
|
data class ScreenCaptureUpdate(
|
||||||
|
val isScreenCaptureEnabled: Boolean,
|
||||||
|
) : Internal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,11 +184,6 @@ sealed class MainEvent {
|
|||||||
*/
|
*/
|
||||||
data object NavigateToDebugMenu : MainEvent()
|
data object NavigateToDebugMenu : MainEvent()
|
||||||
|
|
||||||
/**
|
|
||||||
* Event indicating a change in the screen capture setting.
|
|
||||||
*/
|
|
||||||
data class ScreenCaptureSettingChange(val isAllowed: Boolean) : MainEvent()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the app theme has been updated.
|
* Indicates that the app theme has been updated.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -22,6 +22,7 @@ class MainViewModelTest : BaseViewModelTest() {
|
|||||||
every { appTheme } returns AppTheme.DEFAULT
|
every { appTheme } returns AppTheme.DEFAULT
|
||||||
every { appThemeStateFlow } returns mutableAppThemeFlow
|
every { appThemeStateFlow } returns mutableAppThemeFlow
|
||||||
every { isScreenCaptureAllowedStateFlow } returns mutableScreenCaptureAllowedFlow
|
every { isScreenCaptureAllowedStateFlow } returns mutableScreenCaptureAllowedFlow
|
||||||
|
every { isScreenCaptureAllowed } returns false
|
||||||
every { isDynamicColorsEnabled } returns false
|
every { isDynamicColorsEnabled } returns false
|
||||||
every { isDynamicColorsEnabledFlow } returns mutableIsDynamicColorsEnabledFlow
|
every { isDynamicColorsEnabledFlow } returns mutableIsDynamicColorsEnabledFlow
|
||||||
}
|
}
|
||||||
@ -31,7 +32,7 @@ class MainViewModelTest : BaseViewModelTest() {
|
|||||||
fun `on AppThemeChanged should update state`() = runTest {
|
fun `on AppThemeChanged should update state`() = runTest {
|
||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.stateEventFlow(backgroundScope) { stateFlow, eventFlow ->
|
viewModel.stateEventFlow(backgroundScope) { stateFlow, eventFlow ->
|
||||||
eventFlow.skipItems(count = 2)
|
eventFlow.skipItems(count = 1)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
DEFAULT_STATE,
|
DEFAULT_STATE,
|
||||||
stateFlow.awaitItem(),
|
stateFlow.awaitItem(),
|
||||||
@ -79,12 +80,29 @@ class MainViewModelTest : BaseViewModelTest() {
|
|||||||
val viewModel = createViewModel()
|
val viewModel = createViewModel()
|
||||||
viewModel.eventFlow.test {
|
viewModel.eventFlow.test {
|
||||||
// Ignore the events that are fired off by flows in the ViewModel init
|
// Ignore the events that are fired off by flows in the ViewModel init
|
||||||
skipItems(2)
|
skipItems(1)
|
||||||
viewModel.trySendAction(MainAction.OpenDebugMenu)
|
viewModel.trySendAction(MainAction.OpenDebugMenu)
|
||||||
assertEquals(MainEvent.NavigateToDebugMenu, awaitItem())
|
assertEquals(MainEvent.NavigateToDebugMenu, awaitItem())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `changes in the allowed screen capture value should update the state`() {
|
||||||
|
val viewModel = createViewModel()
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
DEFAULT_STATE.copy(isScreenCaptureAllowed = false),
|
||||||
|
viewModel.stateFlow.value,
|
||||||
|
)
|
||||||
|
|
||||||
|
mutableScreenCaptureAllowedFlow.value = true
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
DEFAULT_STATE.copy(isScreenCaptureAllowed = true),
|
||||||
|
viewModel.stateFlow.value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
private fun createViewModel(): MainViewModel =
|
private fun createViewModel(): MainViewModel =
|
||||||
MainViewModel(
|
MainViewModel(
|
||||||
settingsRepository = settingsRepository,
|
settingsRepository = settingsRepository,
|
||||||
@ -95,4 +113,5 @@ class MainViewModelTest : BaseViewModelTest() {
|
|||||||
private val DEFAULT_STATE = MainState(
|
private val DEFAULT_STATE = MainState(
|
||||||
theme = AppTheme.DEFAULT,
|
theme = AppTheme.DEFAULT,
|
||||||
isDynamicColorsEnabled = false,
|
isDynamicColorsEnabled = false,
|
||||||
|
isScreenCaptureAllowed = false,
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user