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

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

Merge "Better handle icon apply failure and icon theme refresh (1/2)" into main

parents f8946c25 dd8dba7a
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -35,5 +35,11 @@ interface IconStyleRepository {

    val selectedIconStyle: Flow<IconStyle>

    suspend fun setIconStyle(iconStyle: IconStyle)
    /**
     * Sets the selected icon style.
     *
     * @param iconStyle The icon style to set.
     * @return True if the icon style was set successfully and data was updated, false otherwise.
     */
    suspend fun setIconStyle(iconStyle: IconStyle): Boolean
}
+5 −2
Original line number Diff line number Diff line
@@ -184,12 +184,15 @@ constructor(
        }
    }

    override suspend fun setIconStyle(iconStyle: IconStyle) {
    override suspend fun setIconStyle(iconStyle: IconStyle): Boolean {
        themedIconUri.first()?.let {
            val values = ContentValues()
            values.put(COL_ICON_THEMED_VALUE, iconStyle == ThemePickerIconStyle.MONOCHROME)
            val rowsUpdated =
                contentResolver.update(it, values, /* where= */ null, /* selectionArgs= */ null)
            return rowsUpdated > 0
        }
        return false
    }

    companion object {
+2 −1
Original line number Diff line number Diff line
@@ -56,5 +56,6 @@ constructor(

    suspend fun applyShape(shapeKey: String) = shapeRepository.applyShape(shapeKey)

    suspend fun applyIconStyle(iconStyle: IconStyle) = iconStyleRepository.setIconStyle(iconStyle)
    suspend fun applyIconStyle(iconStyle: IconStyle): Boolean =
        iconStyleRepository.setIconStyle(iconStyle)
}
+40 −9
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wallpaper.customization.ui.viewmodel

import android.content.Context
import android.util.Log
import com.android.customization.model.grid.ShapeOptionModel
import com.android.customization.module.logging.ThemesUserEventLogger
import com.android.customization.picker.grid.ui.viewmodel.ShapeIconViewModel
@@ -34,7 +35,10 @@ import dagger.assisted.AssistedInject
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.android.scopes.ViewModelScoped
import java.util.Locale
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -48,6 +52,7 @@ import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout

class AppIconPickerViewModel
@AssistedInject
@@ -115,7 +120,7 @@ constructor(
        }

    //// Style
    private val selectedIconStyle = interactor.selectedIconStyle
    val selectedIconStyle = interactor.selectedIconStyle
    private val overridingIconStyle: MutableStateFlow<IconStyle?> = MutableStateFlow(null)
    val previewingIconStyle =
        combine(selectedIconStyle, overridingIconStyle) { selected, overriding ->
@@ -127,9 +132,9 @@ constructor(
            started = SharingStarted.WhileSubscribed(),
            replay = 1,
        )
    val overridingIconStyleModel =
        combine(overridingIconStyle, iconStylesModels) { overridingIconStyle, iconStylesModels ->
            iconStylesModels.find { it.iconStyle == overridingIconStyle }
    val previewingIconStyleModel =
        combine(previewingIconStyle, iconStylesModels) { previewingIconStyle, iconStylesModels ->
            iconStylesModels.find { it.iconStyle == previewingIconStyle }
        }
    val styleOptions: Flow<List<OptionItemViewModel2<IconStyleModel>>> =
        iconStylesModels.map {
@@ -353,13 +358,34 @@ constructor(
                    }
                    if (styleNeedsUpdate) {
                        coroutineScope {
                            launch { overridingIconStyle?.let { interactor.applyIconStyle(it) } }
                            val waitForUpdate = launch {
                                try {
                                    withTimeout(ICON_UPDATE_TIMEOUT) {
                                        // Drop the first emitted icon style since it is the current
                                        // selection. The next emitted icon style signals an update.
                                        selectedIconStyle.drop(1).take(1).collect {
                                            return@collect
                                        }
                            overridingIconStyle?.let {
                                logger.logThemedIconApplied(it.getIsThemedIcon())
                                    }
                                } catch (e: TimeoutCancellationException) {
                                    Log.w(TAG, "Timed out waiting for icon update", e)
                                }
                            }
                            launch {
                                val success =
                                    overridingIconStyle?.let { interactor.applyIconStyle(it) }
                                if (success == true) {
                                    logger.logThemedIconApplied(
                                        overridingIconStyle.getIsThemedIcon()
                                    )
                                } else {
                                    Log.w(TAG, "Apply unsuccessful, no data was updated")
                                    waitForUpdate.cancel()
                                }
                            }
                            try {
                                waitForUpdate.join()
                            } catch (_: CancellationException) {}
                        }
                    }
                }
@@ -447,4 +473,9 @@ constructor(
    interface Factory {
        fun create(viewModelScope: CoroutineScope): AppIconPickerViewModel
    }

    companion object {
        const val TAG = "AppIconPickerViewModel"
        val ICON_UPDATE_TIMEOUT = 1000.milliseconds
    }
}
+8 −2
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ class FakeIconStyleRepository @Inject constructor() : IconStyleRepository {
    private val _selectedIconStyle = MutableStateFlow<IconStyle>(ThemePickerIconStyle.DEFAULT)
    override val selectedIconStyle = _selectedIconStyle.asStateFlow()

    var shouldApplySuccessfully = true
    var shouldUpdateSuccessfully = true

    override val iconStyleModels: Flow<List<IconStyleModel>> =
        isCustomizationAvailable.map { isThemedIconAvailable ->
            ThemePickerIconStyle.entries
@@ -61,9 +64,12 @@ class FakeIconStyleRepository @Inject constructor() : IconStyleRepository {
        )
    }

    override suspend fun setIconStyle(iconStyle: IconStyle) {
    override suspend fun setIconStyle(iconStyle: IconStyle): Boolean {
        if (shouldApplySuccessfully && shouldUpdateSuccessfully) {
            _selectedIconStyle.value = iconStyle
        }
        return shouldApplySuccessfully
    }

    override suspend fun setThemedIconEnabled(enabled: Boolean) {
        _isThemedIconActivated.value = enabled
Loading