mirror of
https://github.com/bitwarden/android.git
synced 2025-12-15 16:40:20 -06:00
[PM-21750] Only show dynamic colors option on Android 12+ (#5507)
This commit is contained in:
parent
e193661f5f
commit
f9914e5b46
@ -27,6 +27,7 @@ import com.bitwarden.ui.platform.base.util.EventsEffect
|
||||
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
|
||||
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
|
||||
import com.bitwarden.ui.platform.components.model.CardStyle
|
||||
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
|
||||
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.platform.resource.BitwardenDrawable
|
||||
@ -34,7 +35,6 @@ import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
|
||||
import com.x8bit.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
|
||||
import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
|
||||
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
|
||||
import com.x8bit.bitwarden.ui.platform.util.displayLabel
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
@ -111,20 +111,22 @@ fun AppearanceScreen(
|
||||
.fillMaxWidth(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(height = 8.dp))
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.dynamic_colors),
|
||||
supportingText = stringResource(id = R.string.dynamic_colors_description),
|
||||
isChecked = state.isDynamicColorsEnabled,
|
||||
onCheckedChange = remember(viewModel) {
|
||||
{ viewModel.trySendAction(AppearanceAction.DynamicColorsToggle(it)) }
|
||||
},
|
||||
cardStyle = CardStyle.Full,
|
||||
modifier = Modifier
|
||||
.testTag("DynamicColorsSwitch")
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(height = 8.dp))
|
||||
if (state.isDynamicColorsSupported) {
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.dynamic_colors),
|
||||
supportingText = stringResource(id = R.string.dynamic_colors_description),
|
||||
isChecked = state.isDynamicColorsEnabled,
|
||||
onCheckedChange = remember(viewModel) {
|
||||
{ viewModel.trySendAction(AppearanceAction.DynamicColorsToggle(it)) }
|
||||
},
|
||||
cardStyle = CardStyle.Full,
|
||||
modifier = Modifier
|
||||
.testTag("DynamicColorsSwitch")
|
||||
.fillMaxWidth()
|
||||
.standardHorizontalMargin(),
|
||||
)
|
||||
Spacer(modifier = Modifier.height(height = 8.dp))
|
||||
}
|
||||
BitwardenSwitch(
|
||||
label = stringResource(id = R.string.show_website_icons),
|
||||
supportingText = stringResource(id = R.string.show_website_icons_description),
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.settings.appearance
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Parcelable
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.ui.platform.base.BaseViewModel
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
@ -31,6 +33,7 @@ class AppearanceViewModel @Inject constructor(
|
||||
showWebsiteIcons = !settingsRepository.isIconLoadingDisabled,
|
||||
theme = settingsRepository.appTheme,
|
||||
isDynamicColorsEnabled = settingsRepository.isDynamicColorsEnabled,
|
||||
isDynamicColorsSupported = isBuildVersionAtLeast(Build.VERSION_CODES.S),
|
||||
dialogState = null,
|
||||
),
|
||||
) {
|
||||
@ -42,11 +45,13 @@ class AppearanceViewModel @Inject constructor(
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
|
||||
settingsRepository
|
||||
.isDynamicColorsEnabledFlow
|
||||
.map { AppearanceAction.Internal.DynamicColorsStateUpdateReceive(it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
if (state.isDynamicColorsSupported) {
|
||||
settingsRepository
|
||||
.isDynamicColorsEnabledFlow
|
||||
.map { AppearanceAction.Internal.DynamicColorsStateUpdateReceive(it) }
|
||||
.onEach(::sendAction)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
}
|
||||
|
||||
override fun handleAction(action: AppearanceAction): Unit = when (action) {
|
||||
@ -139,6 +144,7 @@ data class AppearanceState(
|
||||
val language: AppLanguage,
|
||||
val showWebsiteIcons: Boolean,
|
||||
val theme: AppTheme,
|
||||
val isDynamicColorsSupported: Boolean,
|
||||
val isDynamicColorsEnabled: Boolean,
|
||||
val dialogState: DialogState?,
|
||||
) : Parcelable {
|
||||
|
||||
@ -11,15 +11,19 @@ import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import com.bitwarden.core.data.repository.util.bufferedMutableSharedFlow
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.bitwarden.ui.util.assertNoDialogExists
|
||||
import com.x8bit.bitwarden.ui.platform.base.BitwardenComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.unmockkStatic
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.junit.After
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -36,6 +40,8 @@ class AppearanceScreenTest : BitwardenComposeTest() {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mockkStatic(::isBuildVersionAtLeast)
|
||||
every { isBuildVersionAtLeast(any()) } returns true
|
||||
setContent {
|
||||
AppearanceScreen(
|
||||
onNavigateBack = { haveCalledNavigateBack = true },
|
||||
@ -44,6 +50,11 @@ class AppearanceScreenTest : BitwardenComposeTest() {
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
unmockkStatic(::isBuildVersionAtLeast)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on back click should send BackClick`() {
|
||||
composeTestRule.onNodeWithContentDescription("Back").performClick()
|
||||
@ -167,6 +178,19 @@ class AppearanceScreenTest : BitwardenComposeTest() {
|
||||
assertTrue(haveCalledNavigateBack)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `dynamic colors should be displayed based on state`() {
|
||||
composeTestRule.onNodeWithText("Dynamic colors")
|
||||
.performScrollTo()
|
||||
.assertIsDisplayed()
|
||||
|
||||
mutableStateFlow.update {
|
||||
it.copy(isDynamicColorsSupported = false)
|
||||
}
|
||||
composeTestRule.onNodeWithText("Dynamic colors")
|
||||
.assertIsNotDisplayed()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on DynamicColorsToggle should send DynamicColorsToggle`() {
|
||||
composeTestRule.onNodeWithText("Dynamic colors")
|
||||
@ -203,5 +227,6 @@ private val DEFAULT_STATE = AppearanceState(
|
||||
showWebsiteIcons = false,
|
||||
theme = AppTheme.DEFAULT,
|
||||
isDynamicColorsEnabled = false,
|
||||
isDynamicColorsSupported = true,
|
||||
dialogState = null,
|
||||
)
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
package com.x8bit.bitwarden.ui.platform.feature.settings.appearance
|
||||
|
||||
import android.os.Build
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import app.cash.turbine.test
|
||||
import com.bitwarden.core.util.isBuildVersionAtLeast
|
||||
import com.bitwarden.ui.platform.base.BaseViewModelTest
|
||||
import com.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme
|
||||
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
|
||||
@ -9,12 +11,16 @@ import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLang
|
||||
import io.mockk.every
|
||||
import io.mockk.just
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import io.mockk.runs
|
||||
import io.mockk.unmockkStatic
|
||||
import io.mockk.verify
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class AppearanceViewModelTest : BaseViewModelTest() {
|
||||
@ -33,6 +39,17 @@ class AppearanceViewModelTest : BaseViewModelTest() {
|
||||
every { isDynamicColorsEnabledFlow } returns mutableIsDynamicColorsEnabledFlow
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockkStatic(::isBuildVersionAtLeast)
|
||||
every { isBuildVersionAtLeast(any()) } returns true
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
fun tearDown() {
|
||||
unmockkStatic(::isBuildVersionAtLeast)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial state should be correct when not set`() {
|
||||
val viewModel = createViewModel(state = null)
|
||||
@ -46,6 +63,20 @@ class AppearanceViewModelTest : BaseViewModelTest() {
|
||||
assertEquals(state, viewModel.stateFlow.value)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `initial state should be correct when build version is below 31`() {
|
||||
every { isBuildVersionAtLeast(Build.VERSION_CODES.S) } returns false
|
||||
val viewModel = createViewModel(state = null)
|
||||
assertEquals(
|
||||
DEFAULT_STATE.copy(isDynamicColorsSupported = false),
|
||||
viewModel.stateFlow.value,
|
||||
)
|
||||
|
||||
verify(exactly = 0) {
|
||||
mockSettingsRepository.isDynamicColorsEnabledFlow
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `on BackClick should emit NavigateBack`() = runTest {
|
||||
val viewModel = createViewModel()
|
||||
@ -210,6 +241,7 @@ class AppearanceViewModelTest : BaseViewModelTest() {
|
||||
language = AppLanguage.DEFAULT,
|
||||
showWebsiteIcons = true,
|
||||
theme = AppTheme.DEFAULT,
|
||||
isDynamicColorsSupported = true,
|
||||
isDynamicColorsEnabled = false,
|
||||
dialogState = null,
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user