Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 068d5c3c authored by Catherine Liang's avatar Catherine Liang
Browse files

Grid Picker Selection Animation Fix (1/2)

Fix grid picker selection animation issue, due to comparison issues in
diff util.

Bug: 273336388
Test: Manually verified that grid picker, color picker, and quick
affordance picker selection animation function correctly. Tested with
print statements to verify diff util functions as intended. Updated
field types in grid view model test.

Change-Id: If48da6985ca99e254fbe511f2062a32e946883c9
parent a0966662
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
package com.android.customization.model.grid.ui.binder

import android.widget.ImageView
import com.android.customization.model.grid.ui.viewmodel.GridIconViewModel
import com.android.customization.widget.GridTileDrawable

object GridIconViewBinder {
    fun bind(view: ImageView, viewModel: GridIconViewModel) {
        view.setImageDrawable(
            GridTileDrawable(
                viewModel.columns,
                viewModel.rows,
                viewModel.path,
            )
        )
    }
}
+3 −4
Original line number Diff line number Diff line
@@ -25,11 +25,10 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.customization.model.grid.ui.viewmodel.GridIconViewModel
import com.android.customization.model.grid.ui.viewmodel.GridScreenViewModel
import com.android.customization.picker.common.ui.view.ItemSpacing
import com.android.wallpaper.R
import com.android.wallpaper.picker.common.icon.ui.viewbinder.IconViewBinder
import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
import com.android.wallpaper.picker.option.ui.binder.OptionItemBinder
import kotlinx.coroutines.CoroutineDispatcher
@@ -61,9 +60,9 @@ object GridScreenBinder {
                        selectedColor = view.context.getColor(R.color.text_color_primary),
                        unselectedColor = view.context.getColor(R.color.text_color_secondary),
                    ),
                bindIcon = { foregroundView: View, gridIcon: Icon ->
                bindIcon = { foregroundView: View, gridIcon: GridIconViewModel ->
                    val imageView = foregroundView as? ImageView
                    imageView?.let { IconViewBinder.bind(imageView, gridIcon) }
                    imageView?.let { GridIconViewBinder.bind(imageView, gridIcon) }
                }
            )
        optionView.adapter = adapter
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 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.model.grid.ui.viewmodel

data class GridIconViewModel(
    val columns: Int,
    val rows: Int,
    val path: String,
)
+11 −15
Original line number Diff line number Diff line
@@ -26,12 +26,11 @@ import androidx.lifecycle.viewModelScope
import com.android.customization.model.ResourceConstants
import com.android.customization.model.grid.domain.interactor.GridInteractor
import com.android.customization.model.grid.shared.model.GridOptionItemsModel
import com.android.customization.widget.GridTileDrawable
import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
import com.android.wallpaper.picker.common.text.ui.viewmodel.Text
import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

@@ -43,12 +42,12 @@ class GridScreenViewModel(
    @SuppressLint("StaticFieldLeak") // We're not leaking this context as it is the app context.
    private val applicationContext = context.applicationContext

    val optionItems: Flow<List<OptionItemViewModel<Icon>>> =
    val optionItems: Flow<List<OptionItemViewModel<GridIconViewModel>>> =
        interactor.options.map { model -> toViewModel(model) }

    private fun toViewModel(
        model: GridOptionItemsModel,
    ): List<OptionItemViewModel<Icon>> {
    ): List<OptionItemViewModel<GridIconViewModel>> {
        val iconShapePath =
            applicationContext.resources.getString(
                Resources.getSystem()
@@ -63,17 +62,14 @@ class GridScreenViewModel(
            is GridOptionItemsModel.Loaded ->
                model.options.map { option ->
                    val text = Text.Loaded(option.name)
                    OptionItemViewModel<Icon>(
                        key = flowOf("${option.cols}x${option.rows}"),
                    OptionItemViewModel<GridIconViewModel>(
                        key =
                            MutableStateFlow("${option.cols}x${option.rows}") as StateFlow<String>,
                        payload =
                            Icon.Loaded(
                                drawable =
                                    GridTileDrawable(
                                        option.cols,
                                        option.rows,
                                        iconShapePath,
                                    ),
                                contentDescription = text
                            GridIconViewModel(
                                columns = option.cols,
                                rows = option.rows,
                                path = iconShapePath,
                            ),
                        text = text,
                        isSelected = option.isSelected,
+26 −17
Original line number Diff line number Diff line
@@ -31,9 +31,10 @@ import kotlin.math.max
import kotlin.math.min
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

/** Models UI state for a color picker experience. */
@@ -91,15 +92,19 @@ private constructor(
                                        colorOptionModel.colorOption as ColorSeedOption
                                    val colors =
                                        colorSeedOption.previewInfo.resolveColors(context.resources)
                                    val isSelectedFlow: Flow<Boolean> =
                                        interactor.activeColorOption.map {
                                    val isSelectedFlow: StateFlow<Boolean> =
                                        interactor.activeColorOption
                                            .map {
                                                it?.colorOption?.isEquivalent(
                                                    colorOptionModel.colorOption
                                                )
                                                    ?: colorOptionModel.isSelected
                                            }
                                            .stateIn(viewModelScope)
                                    OptionItemViewModel<ColorOptionIconViewModel>(
                                        key = flowOf(colorOptionModel.key),
                                        key =
                                            MutableStateFlow(colorOptionModel.key)
                                                as StateFlow<String>,
                                        payload =
                                            ColorOptionIconViewModel(
                                                colors[0],
@@ -141,15 +146,19 @@ private constructor(
                                        colorBundle.previewInfo.resolveSecondaryColor(
                                            context.resources
                                        )
                                    val isSelectedFlow: Flow<Boolean> =
                                        interactor.activeColorOption.map {
                                    val isSelectedFlow: StateFlow<Boolean> =
                                        interactor.activeColorOption
                                            .map {
                                                it?.colorOption?.isEquivalent(
                                                    colorOptionModel.colorOption
                                                )
                                                    ?: colorOptionModel.isSelected
                                            }
                                            .stateIn(viewModelScope)
                                    OptionItemViewModel<ColorOptionIconViewModel>(
                                        key = flowOf(colorOptionModel.key),
                                        key =
                                            MutableStateFlow(colorOptionModel.key)
                                                as StateFlow<String>,
                                        payload =
                                            ColorOptionIconViewModel(
                                                primaryColor,
Loading