Loading src/com/android/customization/model/color/ColorCustomizationManager.java +20 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti private String mCurrentStyle; private WallpaperColors mHomeWallpaperColors; private WallpaperColors mLockWallpaperColors; private SettingsChangedListener mListener; /** Returns the {@link ColorCustomizationManager} instance. */ public static ColorCustomizationManager getInstance(Context context, Loading Loading @@ -116,6 +117,7 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti mProvider = provider; mContentResolver = contentResolver; mExecutorService = executorService; mListener = null; ContentObserver observer = new ContentObserver(/* handler= */ null) { @Override public void onChange(boolean selfChange, Uri uri) { Loading @@ -127,6 +129,9 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti mCurrentOverlays = null; mCurrentStyle = null; mCurrentSource = null; if (mListener != null) { mListener.onSettingsChanged(); } } } }; Loading Loading @@ -314,4 +319,19 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti } return overlayPackages; } /** * Sets a listener that is called when ColorCustomizationManager is updated. */ public void setListener(SettingsChangedListener listener) { mListener = listener; } /** * A listener for listening to when ColorCustomizationManager is updated. */ public interface SettingsChangedListener { /** */ void onSettingsChanged(); } } src/com/android/customization/picker/color/data/repository/ColorPickerRepository2.kt 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.data.repository import com.android.customization.model.color.ColorOption import com.android.customization.picker.color.shared.model.ColorType import kotlinx.coroutines.flow.Flow /** * Abstracts access to application state related to functionality for selecting, picking, or setting * system color. */ interface ColorPickerRepository2 { /** List of wallpaper and preset color options on the device, categorized by Color Type */ val colorOptions: Flow<Map<ColorType, List<ColorOption>>> /** The system selected color option from the generated list of color options */ val selectedColorOption: Flow<ColorOption?> /** Selects a color option with optimistic update */ suspend fun select(colorOption: ColorOption) } src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl2.kt 0 → 100644 +160 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.data.repository import android.util.Log import com.android.customization.model.CustomizationManager import com.android.customization.model.color.ColorCustomizationManager import com.android.customization.model.color.ColorOption import com.android.customization.model.color.ColorOptionImpl import com.android.customization.picker.color.shared.model.ColorType import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.suspendCancellableCoroutine @Singleton class ColorPickerRepositoryImpl2 @Inject constructor( @BackgroundDispatcher private val scope: CoroutineScope, wallpaperColorsRepository: WallpaperColorsRepository, private val colorManager: ColorCustomizationManager, ) : ColorPickerRepository2 { private val homeWallpaperColors: StateFlow<WallpaperColorsModel?> = wallpaperColorsRepository.homeWallpaperColors private val lockWallpaperColors: StateFlow<WallpaperColorsModel?> = wallpaperColorsRepository.lockWallpaperColors override val colorOptions: Flow<Map<ColorType, List<ColorOption>>> = combine(homeWallpaperColors, lockWallpaperColors) { homeColors, lockColors -> homeColors to lockColors } .map { (homeColors, lockColors) -> suspendCancellableCoroutine { continuation -> if ( homeColors is WallpaperColorsModel.Loading || lockColors is WallpaperColorsModel.Loading ) { continuation.resumeWith( Result.success( mapOf( ColorType.WALLPAPER_COLOR to listOf(), ColorType.PRESET_COLOR to listOf(), ) ) ) return@suspendCancellableCoroutine } val homeColorsLoaded = homeColors as WallpaperColorsModel.Loaded val lockColorsLoaded = lockColors as WallpaperColorsModel.Loaded colorManager.setWallpaperColors( homeColorsLoaded.colors, lockColorsLoaded.colors, ) colorManager.fetchOptions( object : CustomizationManager.OptionsFetchedListener<ColorOption> { override fun onOptionsLoaded(options: MutableList<ColorOption>?) { val wallpaperColorOptions: MutableList<ColorOption> = mutableListOf() val presetColorOptions: MutableList<ColorOption> = mutableListOf() options?.forEach { option -> when ((option as ColorOptionImpl).type) { ColorType.WALLPAPER_COLOR -> wallpaperColorOptions.add(option) ColorType.PRESET_COLOR -> presetColorOptions.add(option) } } continuation.resumeWith( Result.success( mapOf( ColorType.WALLPAPER_COLOR to wallpaperColorOptions, ColorType.PRESET_COLOR to presetColorOptions, ) ) ) } override fun onError(throwable: Throwable?) { Log.e(TAG, "Error loading theme bundles", throwable) continuation.resumeWith( Result.failure( throwable ?: Throwable("Error loading theme bundles") ) ) } }, /* reload= */ false, ) } } private val settingsChanged = callbackFlow { trySend(Unit) colorManager.setListener { trySend(Unit) } awaitClose { colorManager.setListener(null) } } override val selectedColorOption = combine(colorOptions, settingsChanged) { options, _ -> options.forEach { (_, optionsByType) -> optionsByType.forEach { if (it.isActive(colorManager)) { return@combine it } } } return@combine null } .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initialValue = null) override suspend fun select(colorOption: ColorOption) { suspendCancellableCoroutine { continuation -> colorManager.apply( colorOption, object : CustomizationManager.Callback { override fun onSuccess() { continuation.resumeWith(Result.success(Unit)) } override fun onError(throwable: Throwable?) { Log.w(TAG, "Apply theme with error", throwable) continuation.resumeWith( Result.failure(throwable ?: Throwable("Error loading theme bundles")) ) } }, ) } } companion object { private const val TAG = "ColorPickerRepositoryImpl" } } src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor2.kt 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.domain.interactor import com.android.customization.model.color.ColorOption import com.android.customization.picker.color.data.repository.ColorPickerRepository2 import javax.inject.Inject import javax.inject.Singleton /** Single entry-point for all application state and business logic related to system color. */ @Singleton class ColorPickerInteractor2 @Inject constructor(private val repository: ColorPickerRepository2) { val selectedColorOption = repository.selectedColorOption /** List of wallpaper and preset color options on the device, categorized by Color Type */ val colorOptions = repository.colorOptions suspend fun select(colorOption: ColorOption) { repository.select(colorOption) } } src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt +4 −4 Original line number Diff line number Diff line Loading @@ -93,11 +93,11 @@ object ColorsFloatingSheetBinder { } launch { viewModel.previewingColorOption.collect { colorModel -> if (colorModel != null) { viewModel.previewingColorOption.collect { colorOption -> if (colorOption != null) { colorUpdateViewModel.previewColors( colorModel.colorOption.seedColor, colorModel.colorOption.style, colorOption.seedColor, colorOption.style, ) } else colorUpdateViewModel.resetPreview() } Loading Loading
src/com/android/customization/model/color/ColorCustomizationManager.java +20 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti private String mCurrentStyle; private WallpaperColors mHomeWallpaperColors; private WallpaperColors mLockWallpaperColors; private SettingsChangedListener mListener; /** Returns the {@link ColorCustomizationManager} instance. */ public static ColorCustomizationManager getInstance(Context context, Loading Loading @@ -116,6 +117,7 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti mProvider = provider; mContentResolver = contentResolver; mExecutorService = executorService; mListener = null; ContentObserver observer = new ContentObserver(/* handler= */ null) { @Override public void onChange(boolean selfChange, Uri uri) { Loading @@ -127,6 +129,9 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti mCurrentOverlays = null; mCurrentStyle = null; mCurrentSource = null; if (mListener != null) { mListener.onSettingsChanged(); } } } }; Loading Loading @@ -314,4 +319,19 @@ public class ColorCustomizationManager implements CustomizationManager<ColorOpti } return overlayPackages; } /** * Sets a listener that is called when ColorCustomizationManager is updated. */ public void setListener(SettingsChangedListener listener) { mListener = listener; } /** * A listener for listening to when ColorCustomizationManager is updated. */ public interface SettingsChangedListener { /** */ void onSettingsChanged(); } }
src/com/android/customization/picker/color/data/repository/ColorPickerRepository2.kt 0 → 100644 +36 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.data.repository import com.android.customization.model.color.ColorOption import com.android.customization.picker.color.shared.model.ColorType import kotlinx.coroutines.flow.Flow /** * Abstracts access to application state related to functionality for selecting, picking, or setting * system color. */ interface ColorPickerRepository2 { /** List of wallpaper and preset color options on the device, categorized by Color Type */ val colorOptions: Flow<Map<ColorType, List<ColorOption>>> /** The system selected color option from the generated list of color options */ val selectedColorOption: Flow<ColorOption?> /** Selects a color option with optimistic update */ suspend fun select(colorOption: ColorOption) }
src/com/android/customization/picker/color/data/repository/ColorPickerRepositoryImpl2.kt 0 → 100644 +160 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.data.repository import android.util.Log import com.android.customization.model.CustomizationManager import com.android.customization.model.color.ColorCustomizationManager import com.android.customization.model.color.ColorOption import com.android.customization.model.color.ColorOptionImpl import com.android.customization.picker.color.shared.model.ColorType import com.android.wallpaper.picker.customization.data.repository.WallpaperColorsRepository import com.android.wallpaper.picker.customization.shared.model.WallpaperColorsModel import com.android.wallpaper.picker.di.modules.BackgroundDispatcher import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.suspendCancellableCoroutine @Singleton class ColorPickerRepositoryImpl2 @Inject constructor( @BackgroundDispatcher private val scope: CoroutineScope, wallpaperColorsRepository: WallpaperColorsRepository, private val colorManager: ColorCustomizationManager, ) : ColorPickerRepository2 { private val homeWallpaperColors: StateFlow<WallpaperColorsModel?> = wallpaperColorsRepository.homeWallpaperColors private val lockWallpaperColors: StateFlow<WallpaperColorsModel?> = wallpaperColorsRepository.lockWallpaperColors override val colorOptions: Flow<Map<ColorType, List<ColorOption>>> = combine(homeWallpaperColors, lockWallpaperColors) { homeColors, lockColors -> homeColors to lockColors } .map { (homeColors, lockColors) -> suspendCancellableCoroutine { continuation -> if ( homeColors is WallpaperColorsModel.Loading || lockColors is WallpaperColorsModel.Loading ) { continuation.resumeWith( Result.success( mapOf( ColorType.WALLPAPER_COLOR to listOf(), ColorType.PRESET_COLOR to listOf(), ) ) ) return@suspendCancellableCoroutine } val homeColorsLoaded = homeColors as WallpaperColorsModel.Loaded val lockColorsLoaded = lockColors as WallpaperColorsModel.Loaded colorManager.setWallpaperColors( homeColorsLoaded.colors, lockColorsLoaded.colors, ) colorManager.fetchOptions( object : CustomizationManager.OptionsFetchedListener<ColorOption> { override fun onOptionsLoaded(options: MutableList<ColorOption>?) { val wallpaperColorOptions: MutableList<ColorOption> = mutableListOf() val presetColorOptions: MutableList<ColorOption> = mutableListOf() options?.forEach { option -> when ((option as ColorOptionImpl).type) { ColorType.WALLPAPER_COLOR -> wallpaperColorOptions.add(option) ColorType.PRESET_COLOR -> presetColorOptions.add(option) } } continuation.resumeWith( Result.success( mapOf( ColorType.WALLPAPER_COLOR to wallpaperColorOptions, ColorType.PRESET_COLOR to presetColorOptions, ) ) ) } override fun onError(throwable: Throwable?) { Log.e(TAG, "Error loading theme bundles", throwable) continuation.resumeWith( Result.failure( throwable ?: Throwable("Error loading theme bundles") ) ) } }, /* reload= */ false, ) } } private val settingsChanged = callbackFlow { trySend(Unit) colorManager.setListener { trySend(Unit) } awaitClose { colorManager.setListener(null) } } override val selectedColorOption = combine(colorOptions, settingsChanged) { options, _ -> options.forEach { (_, optionsByType) -> optionsByType.forEach { if (it.isActive(colorManager)) { return@combine it } } } return@combine null } .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initialValue = null) override suspend fun select(colorOption: ColorOption) { suspendCancellableCoroutine { continuation -> colorManager.apply( colorOption, object : CustomizationManager.Callback { override fun onSuccess() { continuation.resumeWith(Result.success(Unit)) } override fun onError(throwable: Throwable?) { Log.w(TAG, "Apply theme with error", throwable) continuation.resumeWith( Result.failure(throwable ?: Throwable("Error loading theme bundles")) ) } }, ) } } companion object { private const val TAG = "ColorPickerRepositoryImpl" } }
src/com/android/customization/picker/color/domain/interactor/ColorPickerInteractor2.kt 0 → 100644 +35 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.android.customization.picker.color.domain.interactor import com.android.customization.model.color.ColorOption import com.android.customization.picker.color.data.repository.ColorPickerRepository2 import javax.inject.Inject import javax.inject.Singleton /** Single entry-point for all application state and business logic related to system color. */ @Singleton class ColorPickerInteractor2 @Inject constructor(private val repository: ColorPickerRepository2) { val selectedColorOption = repository.selectedColorOption /** List of wallpaper and preset color options on the device, categorized by Color Type */ val colorOptions = repository.colorOptions suspend fun select(colorOption: ColorOption) { repository.select(colorOption) } }
src/com/android/wallpaper/customization/ui/binder/ColorsFloatingSheetBinder.kt +4 −4 Original line number Diff line number Diff line Loading @@ -93,11 +93,11 @@ object ColorsFloatingSheetBinder { } launch { viewModel.previewingColorOption.collect { colorModel -> if (colorModel != null) { viewModel.previewingColorOption.collect { colorOption -> if (colorOption != null) { colorUpdateViewModel.previewColors( colorModel.colorOption.seedColor, colorModel.colorOption.style, colorOption.seedColor, colorOption.style, ) } else colorUpdateViewModel.resetPreview() } Loading