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

Commit 6328bd56 authored by Catherine Liang's avatar Catherine Liang Committed by Android (Google) Code Review
Browse files

Merge "Add default and minimal icon style options" into main

parents 5ec3c968 ce62a17f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -151,6 +151,14 @@
        [CHAR LIMIT=15] -->
    <string name="app_icons_theme_themed">themed</string>

    <!-- Label for an icon style option that applies no theming to app icons when selected.
        [CHAR LIMIT=15] -->
    <string name="app_icons_style_default">Default</string>

    <!-- Label for an icon style option that applies a monochrome theme to app icons when selected.
        [CHAR LIMIT=15] -->
    <string name="app_icons_style_minimal">Minimal</string>

    <!-- Title of a tab to change the app icon shape [CHAR LIMIT=15] -->
    <string name="app_icons_shape">Shape</string>

+18 −2
Original line number Diff line number Diff line
@@ -12,13 +12,13 @@
 * 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.grid.domain.interactor
package com.android.customization.picker.icon.domain.interactor

import com.android.customization.model.grid.ShapeOptionModel
import com.android.customization.picker.grid.data.repository.ShapeRepository
import com.android.customization.picker.icon.shared.model.IconStyle
import com.android.customization.picker.themedicon.data.repository.ThemedIconRepository
import javax.inject.Inject
import javax.inject.Singleton
@@ -45,6 +45,22 @@ constructor(

    val isThemedIconEnabled: Flow<Boolean> = themedIconRepository.isActivated

    val iconStyles =
        isThemedIconAvailable.map { isThemedIconAvailable ->
            // TODO (b/397782741): introduce different icon styles depending on repository
            var styles = IconStyle.entries.toList()
            if (!isThemedIconAvailable) styles = styles.filter { it != IconStyle.MONOCHROME }
            styles
        }

    val selectedIconStyle =
        isThemedIconEnabled.map {
            when (it) {
                true -> IconStyle.MONOCHROME
                false -> IconStyle.DEFAULT
            }
        }

    suspend fun applyThemedIconEnabled(enabled: Boolean) =
        themedIconRepository.setThemedIconEnabled(enabled)

+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.icon.shared.model

import com.android.themepicker.R

enum class IconStyle(val nameResId: Int) {
    DEFAULT(R.string.app_icons_style_default),
    MONOCHROME(R.string.app_icons_style_minimal),
}
+61 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.wallpaper.customization.ui.binder

import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.AdaptiveIconDrawable
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
@@ -32,6 +33,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.customization.picker.common.ui.view.SingleRowListItemSpacing
import com.android.customization.picker.grid.ui.viewmodel.ShapeIconViewModel
import com.android.customization.picker.icon.shared.model.IconStyle
import com.android.themepicker.R
import com.android.wallpaper.config.BaseFlags
import com.android.wallpaper.customization.ui.util.ThemePickerCustomizationOptionUtil.ThemePickerHomeCustomizationOption.APP_ICONS
@@ -112,7 +114,20 @@ object AppIconFloatingSheetBinder {
            )
        val shapeOptionList =
            view.requireViewById<RecyclerView>(R.id.shape_options).also {
                it.initShapeOptionList(view.context, shapeOptionListAdapter)
                it.initOptionList(view.context, shapeOptionListAdapter)
            }

        val styleOptionListAdapter =
            createStyleOptionItemAdapter(
                context = view.context,
                colorUpdateViewModel = colorUpdateViewModel,
                shouldAnimateColor = isFloatingSheetActive,
                lifecycleOwner = lifecycleOwner,
                backgroundDispatcher = backgroundDispatcher,
            )
        val styleOptionList =
            view.requireViewById<RecyclerView>(R.id.icon_style_options).also {
                it.initOptionList(view.context, styleOptionListAdapter)
            }

        val themedIconsSwitch = view.requireViewById<MaterialSwitch>(R.id.themed_icon_toggle)
@@ -137,6 +152,17 @@ object AppIconFloatingSheetBinder {
                if (isExtendibleThemeManager) {
                    themedIconEntry.isVisible = false

                    launch {
                        viewModel.styleOptions.collect { options ->
                            styleOptionListAdapter.setItems(options) {
                                val indexToFocus =
                                    options.indexOfFirst { it.isSelected.value }.coerceAtLeast(0)
                                (styleOptionList.layoutManager as LinearLayoutManager)
                                    .scrollToPosition(indexToFocus)
                            }
                        }
                    }

                    launch {
                        viewModel.tabs.collect {
                            if (it.size > 1) {
@@ -245,6 +271,39 @@ object AppIconFloatingSheetBinder {
        }
    }

    private fun createStyleOptionItemAdapter(
        context: Context,
        colorUpdateViewModel: ColorUpdateViewModel,
        shouldAnimateColor: () -> Boolean,
        lifecycleOwner: LifecycleOwner,
        backgroundDispatcher: CoroutineDispatcher,
    ): OptionItemAdapter2<IconStyle> {
        val previewIconPackageName = context.resources.getString(R.string.camera_package)
        val appIconDrawable = ShapeIconViewBinder.loadAppIcon(context, previewIconPackageName)
        return OptionItemAdapter2(
            layoutResourceId = R.layout.icon_style_option2,
            lifecycleOwner = lifecycleOwner,
            backgroundDispatcher = backgroundDispatcher,
            bindPayload = { view: View, iconStyle: IconStyle ->
                val imageView = view.findViewById(R.id.foreground) as? ImageView
                val disposableHandle =
                    imageView?.let {
                        ShapeIconViewBinder.bindPreviewIcon(
                            view = it,
                            appIconDrawable = appIconDrawable as? AdaptiveIconDrawable,
                            isThemed = iconStyle == IconStyle.MONOCHROME,
                            colorUpdateViewModel = colorUpdateViewModel,
                            shouldAnimateColor = shouldAnimateColor,
                            lifecycleOwner = lifecycleOwner,
                        )
                    }
                return@OptionItemAdapter2 disposableHandle
            },
            colorUpdateViewModel = WeakReference(colorUpdateViewModel),
            shouldAnimateColor = shouldAnimateColor,
        )
    }

    private fun createShapeOptionItemAdapter(
        colorUpdateViewModel: ColorUpdateViewModel,
        shouldAnimateColor: () -> Boolean,
@@ -264,10 +323,7 @@ object AppIconFloatingSheetBinder {
            shouldAnimateColor = shouldAnimateColor,
        )

    private fun RecyclerView.initShapeOptionList(
        context: Context,
        adapter: OptionItemAdapter2<ShapeIconViewModel>,
    ) {
    private fun RecyclerView.initOptionList(context: Context, adapter: OptionItemAdapter2<*>) {
        apply {
            this.layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
            addItemDecoration(
+2 −2
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ object ShapeIconViewBinder {
    fun bindPreviewIcon(
        view: ImageView,
        appIconDrawable: AdaptiveIconDrawable?,
        shapeIcon: ShapeIconViewModel,
        shapeIcon: ShapeIconViewModel? = null,
        isThemed: Boolean,
        colorUpdateViewModel: ColorUpdateViewModel,
        shouldAnimateColor: () -> Boolean,
@@ -48,7 +48,7 @@ object ShapeIconViewBinder {
        val shapeTileDrawable =
            ShapeTileDrawable(
                context = view.context,
                path = shapeIcon.path,
                path = shapeIcon?.path,
                icon = appIconDrawable,
                isThemed = isThemed,
            )
Loading