Loading src/com/android/customization/picker/settings/data/repository/ColorContrastSectionRepository.kt +6 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.customization.picker.settings.data.repository import android.app.UiModeManager import android.app.UiModeManager.ContrastUtils import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import com.android.wallpaper.system.UiModeManagerWrapper import java.util.concurrent.Executor Loading @@ -35,16 +36,18 @@ constructor( uiModeManager: UiModeManagerWrapper, @BackgroundDispatcher bgDispatcher: CoroutineDispatcher, ) { var contrast: Flow<Float> = callbackFlow { var contrast: Flow<Int> = callbackFlow { val executor: Executor = bgDispatcher.asExecutor() val listener = UiModeManager.ContrastChangeListener { contrast -> // Emit the new contrast value whenever it changes trySend(contrast) trySend(ContrastUtils.toContrastLevel(contrast)) } // Emit the current contrast value immediately uiModeManager.getContrast()?.let { currentContrast -> trySend(currentContrast) } uiModeManager.getContrast()?.let { currentContrast -> trySend(ContrastUtils.toContrastLevel(currentContrast)) } uiModeManager.addContrastChangeListener(executor, listener) Loading src/com/android/customization/picker/settings/domain/interactor/ColorContrastSectionInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -25,5 +25,5 @@ import kotlinx.coroutines.flow.Flow class ColorContrastSectionInteractor @Inject constructor(colorContrastSectionRepository: ColorContrastSectionRepository) { val contrast: Flow<Float> = colorContrastSectionRepository.contrast val contrast: Flow<Int> = colorContrastSectionRepository.contrast } src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionViewModel.kt +20 −24 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.customization.picker.settings.ui.viewmodel import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor Loading @@ -28,62 +32,54 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map class ColorContrastSectionViewModel private constructor( colorContrastSectionInteractor: ColorContrastSectionInteractor, ) : ViewModel() { private constructor(colorContrastSectionInteractor: ColorContrastSectionInteractor) : ViewModel() { val summary: Flow<ColorContrastSectionDataViewModel> = colorContrastSectionInteractor.contrast.map { contrastValue -> when (contrastValue) { ContrastValue.STANDARD.value -> CONTRAST_LEVEL_STANDARD -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_default_title), Icon.Resource( res = R.drawable.ic_contrast_standard, contentDescription = null, ), ) ) ContrastValue.MEDIUM.value -> CONTRAST_LEVEL_MEDIUM -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_medium_title), Icon.Resource( res = R.drawable.ic_contrast_medium, contentDescription = null, ), ) ) ContrastValue.HIGH.value -> CONTRAST_LEVEL_HIGH -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_high_title), Icon.Resource( res = R.drawable.ic_contrast_high, contentDescription = null, ) Icon.Resource(res = R.drawable.ic_contrast_high, contentDescription = null), ) else -> { println("Invalid contrast value: $contrastValue") throw IllegalArgumentException("Invalid contrast value") Log.e(TAG, "Invalid contrast value: $contrastValue") throw IllegalArgumentException("Invalid contrast value: $contrastValue") } } } enum class ContrastValue(val value: Float) { STANDARD(0f), MEDIUM(0.5f), HIGH(1f) } @Singleton class Factory @Inject constructor( private val colorContrastSectionInteractor: ColorContrastSectionInteractor, ) : ViewModelProvider.Factory { constructor(private val colorContrastSectionInteractor: ColorContrastSectionInteractor) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { @Suppress("UNCHECKED_CAST") return ColorContrastSectionViewModel( colorContrastSectionInteractor = colorContrastSectionInteractor, colorContrastSectionInteractor = colorContrastSectionInteractor ) as T } } companion object { private const val TAG = "ColorContrastSectionViewModel" } } tests/robotests/src/com/android/customization/model/picker/settings/data/repository/ColorContrastSectionRepositoryTest.kt +5 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.customization.model.picker.settings.data.repository import android.app.UiModeManager.ContrastUtils import androidx.test.filters.SmallTest import com.android.customization.picker.settings.data.repository.ColorContrastSectionRepository import com.android.wallpaper.testing.FakeUiModeManager Loading Loading @@ -61,8 +62,10 @@ class ColorContrastSectionRepositoryTest { fun contrastFlowEmitsValues() = testScope.runTest { val nextContrastValues = listOf(0.5f, 0.7f, 0.8f) val expectedContrastValues = nextContrastValues.map { ContrastUtils.toContrastLevel(it) } // Set up a flow to collect all contrast values val flowCollector = mutableListOf<Float>() val flowCollector = mutableListOf<Int>() // Start collecting values from the flow, using an unconfined dispatcher to start // collecting from the flow right away (rather than explicitly calling `runCurrent`) // See https://developer.android.com/kotlin/flow/test#continuous-collection Loading @@ -74,6 +77,6 @@ class ColorContrastSectionRepositoryTest { // Ignore the first contrast value from constructing the repository val collectedValues = flowCollector.drop(1) assertThat(collectedValues).containsExactlyElementsIn(nextContrastValues) assertThat(collectedValues).containsExactlyElementsIn(expectedContrastValues) } } tests/robotests/src/com/android/customization/model/picker/settings/domain/interactor/ColorContrastSectionInteractorTest.kt +5 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.customization.model.picker.settings.domain.interactor import android.app.UiModeManager.ContrastUtils import androidx.test.filters.SmallTest import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor import com.android.wallpaper.testing.FakeUiModeManager Loading Loading @@ -47,11 +48,12 @@ class ColorContrastSectionInteractorTest { @Test fun contrastEmitCorrectValuesFromRepository() = runTest { val expectedContrast = 1.5f uiModeManager.setContrast(expectedContrast) val contrastVal = 0.5f val expectedContrastVal = ContrastUtils.toContrastLevel(contrastVal) uiModeManager.setContrast(contrastVal) val result = interactor.contrast.first() assertThat(result).isEqualTo(expectedContrast) assertThat(result).isEqualTo(expectedContrastVal) } } Loading
src/com/android/customization/picker/settings/data/repository/ColorContrastSectionRepository.kt +6 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.customization.picker.settings.data.repository import android.app.UiModeManager import android.app.UiModeManager.ContrastUtils import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import com.android.wallpaper.system.UiModeManagerWrapper import java.util.concurrent.Executor Loading @@ -35,16 +36,18 @@ constructor( uiModeManager: UiModeManagerWrapper, @BackgroundDispatcher bgDispatcher: CoroutineDispatcher, ) { var contrast: Flow<Float> = callbackFlow { var contrast: Flow<Int> = callbackFlow { val executor: Executor = bgDispatcher.asExecutor() val listener = UiModeManager.ContrastChangeListener { contrast -> // Emit the new contrast value whenever it changes trySend(contrast) trySend(ContrastUtils.toContrastLevel(contrast)) } // Emit the current contrast value immediately uiModeManager.getContrast()?.let { currentContrast -> trySend(currentContrast) } uiModeManager.getContrast()?.let { currentContrast -> trySend(ContrastUtils.toContrastLevel(currentContrast)) } uiModeManager.addContrastChangeListener(executor, listener) Loading
src/com/android/customization/picker/settings/domain/interactor/ColorContrastSectionInteractor.kt +1 −1 Original line number Diff line number Diff line Loading @@ -25,5 +25,5 @@ import kotlinx.coroutines.flow.Flow class ColorContrastSectionInteractor @Inject constructor(colorContrastSectionRepository: ColorContrastSectionRepository) { val contrast: Flow<Float> = colorContrastSectionRepository.contrast val contrast: Flow<Int> = colorContrastSectionRepository.contrast }
src/com/android/customization/picker/settings/ui/viewmodel/ColorContrastSectionViewModel.kt +20 −24 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.customization.picker.settings.ui.viewmodel import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_HIGH import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_MEDIUM import android.app.UiModeManager.ContrastUtils.CONTRAST_LEVEL_STANDARD import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor Loading @@ -28,62 +32,54 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map class ColorContrastSectionViewModel private constructor( colorContrastSectionInteractor: ColorContrastSectionInteractor, ) : ViewModel() { private constructor(colorContrastSectionInteractor: ColorContrastSectionInteractor) : ViewModel() { val summary: Flow<ColorContrastSectionDataViewModel> = colorContrastSectionInteractor.contrast.map { contrastValue -> when (contrastValue) { ContrastValue.STANDARD.value -> CONTRAST_LEVEL_STANDARD -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_default_title), Icon.Resource( res = R.drawable.ic_contrast_standard, contentDescription = null, ), ) ) ContrastValue.MEDIUM.value -> CONTRAST_LEVEL_MEDIUM -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_medium_title), Icon.Resource( res = R.drawable.ic_contrast_medium, contentDescription = null, ), ) ) ContrastValue.HIGH.value -> CONTRAST_LEVEL_HIGH -> ColorContrastSectionDataViewModel( Text.Resource(R.string.color_contrast_high_title), Icon.Resource( res = R.drawable.ic_contrast_high, contentDescription = null, ) Icon.Resource(res = R.drawable.ic_contrast_high, contentDescription = null), ) else -> { println("Invalid contrast value: $contrastValue") throw IllegalArgumentException("Invalid contrast value") Log.e(TAG, "Invalid contrast value: $contrastValue") throw IllegalArgumentException("Invalid contrast value: $contrastValue") } } } enum class ContrastValue(val value: Float) { STANDARD(0f), MEDIUM(0.5f), HIGH(1f) } @Singleton class Factory @Inject constructor( private val colorContrastSectionInteractor: ColorContrastSectionInteractor, ) : ViewModelProvider.Factory { constructor(private val colorContrastSectionInteractor: ColorContrastSectionInteractor) : ViewModelProvider.Factory { override fun <T : ViewModel> create(modelClass: Class<T>): T { @Suppress("UNCHECKED_CAST") return ColorContrastSectionViewModel( colorContrastSectionInteractor = colorContrastSectionInteractor, colorContrastSectionInteractor = colorContrastSectionInteractor ) as T } } companion object { private const val TAG = "ColorContrastSectionViewModel" } }
tests/robotests/src/com/android/customization/model/picker/settings/data/repository/ColorContrastSectionRepositoryTest.kt +5 −2 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.customization.model.picker.settings.data.repository import android.app.UiModeManager.ContrastUtils import androidx.test.filters.SmallTest import com.android.customization.picker.settings.data.repository.ColorContrastSectionRepository import com.android.wallpaper.testing.FakeUiModeManager Loading Loading @@ -61,8 +62,10 @@ class ColorContrastSectionRepositoryTest { fun contrastFlowEmitsValues() = testScope.runTest { val nextContrastValues = listOf(0.5f, 0.7f, 0.8f) val expectedContrastValues = nextContrastValues.map { ContrastUtils.toContrastLevel(it) } // Set up a flow to collect all contrast values val flowCollector = mutableListOf<Float>() val flowCollector = mutableListOf<Int>() // Start collecting values from the flow, using an unconfined dispatcher to start // collecting from the flow right away (rather than explicitly calling `runCurrent`) // See https://developer.android.com/kotlin/flow/test#continuous-collection Loading @@ -74,6 +77,6 @@ class ColorContrastSectionRepositoryTest { // Ignore the first contrast value from constructing the repository val collectedValues = flowCollector.drop(1) assertThat(collectedValues).containsExactlyElementsIn(nextContrastValues) assertThat(collectedValues).containsExactlyElementsIn(expectedContrastValues) } }
tests/robotests/src/com/android/customization/model/picker/settings/domain/interactor/ColorContrastSectionInteractorTest.kt +5 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.customization.model.picker.settings.domain.interactor import android.app.UiModeManager.ContrastUtils import androidx.test.filters.SmallTest import com.android.customization.picker.settings.domain.interactor.ColorContrastSectionInteractor import com.android.wallpaper.testing.FakeUiModeManager Loading Loading @@ -47,11 +48,12 @@ class ColorContrastSectionInteractorTest { @Test fun contrastEmitCorrectValuesFromRepository() = runTest { val expectedContrast = 1.5f uiModeManager.setContrast(expectedContrast) val contrastVal = 0.5f val expectedContrastVal = ContrastUtils.toContrastLevel(contrastVal) uiModeManager.setContrast(contrastVal) val result = interactor.contrast.first() assertThat(result).isEqualTo(expectedContrast) assertThat(result).isEqualTo(expectedContrastVal) } }