From e79d75b3d534ada3b00e40e13521fa669e705e59 Mon Sep 17 00:00:00 2001 From: Coco Duan Date: Wed, 14 Feb 2024 21:12:59 +0000 Subject: Show placeholder for disabled widgets When the setting for "Allow any widget in hub mode" is off, show placeholders for widgets that are previously added but don't have the allowed widget category specified. Added the DisabledWidget content model to render widget in a disabled state. Bug: b/324455650 Test: turn on the setting, add some non-keyguard widgets then turn off the setting Test: atest CommunalInteractorTest Flag: ACONFIG com.android.systemui.communal_hub STAGING Change-Id: Ibad25f142b2add2c08451cffcfc4fad84afa0f81 --- .../systemui/communal/ui/compose/CommunalHub.kt | 84 +++++++++++++++-- .../communal/ui/compose/ContentListState.kt | 8 +- .../domain/interactor/CommunalInteractorTest.kt | 102 +++++++++++++++++++++ .../viewmodel/CommunalEditModeViewModelTest.kt | 11 ++- .../view/viewmodel/CommunalViewModelTest.kt | 4 +- packages/SystemUI/res/values/strings.xml | 2 + .../domain/interactor/CommunalInteractor.kt | 28 ++++-- .../communal/domain/model/CommunalContentModel.kt | 50 +++++++--- 8 files changed, 248 insertions(+), 41 deletions(-) diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt index 622a4f04ee0d..42280d1a622b 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt @@ -17,6 +17,7 @@ package com.android.systemui.communal.ui.compose import android.appwidget.AppWidgetHostView +import android.graphics.drawable.Icon import android.os.Bundle import android.util.SizeF import android.widget.FrameLayout @@ -26,6 +27,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -77,6 +79,8 @@ import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.ColorMatrix import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.LayoutCoordinates @@ -85,8 +89,10 @@ import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId @@ -101,6 +107,8 @@ import androidx.compose.ui.window.Popup import androidx.core.view.setPadding import com.android.compose.modifiers.thenIf import com.android.compose.theme.LocalAndroidColorScheme +import com.android.compose.ui.graphics.painter.rememberDrawablePainter +import com.android.internal.R.dimen.system_app_widget_background_radius import com.android.systemui.communal.domain.model.CommunalContentModel import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.ui.compose.Dimensions.CardOutlineWidth @@ -178,7 +186,7 @@ fun CommunalHub( // not display this button. if ( index == null || - communalContent[index].isWidget() || + communalContent[index].isWidgetContent() || communalContent[index] is CommunalContentModel.CtaTileInViewMode ) { isButtonToEditWidgetsShowing = true @@ -330,7 +338,7 @@ private fun BoxScope.CommunalHubLazyGrid( DraggableItem( dragDropState = dragDropState, selected = selected, - enabled = list[index] is CommunalContentModel.Widget, + enabled = list[index].isWidgetContent(), index = index, ) { isDragging -> CommunalContent( @@ -539,9 +547,11 @@ private fun CommunalContent( widgetConfigurator: WidgetConfigurator? = null, ) { when (model) { - is CommunalContentModel.Widget -> + is CommunalContentModel.WidgetContent.Widget -> WidgetContent(viewModel, model, size, selected, widgetConfigurator, modifier) is CommunalContentModel.WidgetPlaceholder -> HighlightedItem(modifier) + is CommunalContentModel.WidgetContent.DisabledWidget -> + DisabledWidgetPlaceholder(model, modifier) is CommunalContentModel.CtaTileInViewMode -> CtaTileInViewModeContent(viewModel, modifier) is CommunalContentModel.CtaTileInEditMode -> CtaTileInEditModeContent(modifier, onOpenWidgetPicker) @@ -672,7 +682,7 @@ private fun CtaTileInEditModeContent( @Composable private fun WidgetContent( viewModel: BaseCommunalViewModel, - model: CommunalContentModel.Widget, + model: CommunalContentModel.WidgetContent.Widget, size: SizeF, selected: Boolean, widgetConfigurator: WidgetConfigurator?, @@ -690,8 +700,9 @@ private fun WidgetContent( .createViewForCommunal(context, model.appWidgetId, model.providerInfo) .apply { updateAppWidgetSize(Bundle.EMPTY, listOf(size)) } // Remove the extra padding applied to AppWidgetHostView to allow widgets to - // occupy the entire box. The added padding is now adjusted to leave only sufficient - // space for displaying the outline around the box when the widget is selected. + // occupy the entire box. The added padding is now adjusted to leave only + // sufficient space for displaying the outline around the box when the widget + // is selected. view.setPadding(paddingInPx) view }, @@ -716,7 +727,7 @@ private fun WidgetContent( @Composable fun WidgetConfigureButton( visible: Boolean, - model: CommunalContentModel.Widget, + model: CommunalContentModel.WidgetContent.Widget, modifier: Modifier = Modifier, widgetConfigurator: WidgetConfigurator, ) { @@ -750,6 +761,38 @@ fun WidgetConfigureButton( } } +@Composable +fun DisabledWidgetPlaceholder( + model: CommunalContentModel.WidgetContent.DisabledWidget, + modifier: Modifier = Modifier, +) { + val context = LocalContext.current + val appInfo = model.appInfo + val icon: Icon = + if (appInfo == null || appInfo.icon == 0) { + Icon.createWithResource(context, android.R.drawable.sym_def_app_icon) + } else { + Icon.createWithResource(appInfo.packageName, appInfo.icon) + } + + Column( + modifier = + modifier.background( + MaterialTheme.colorScheme.surfaceVariant, + RoundedCornerShape(dimensionResource(system_app_widget_background_radius)) + ), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Image( + painter = rememberDrawablePainter(icon.loadDrawable(context)), + contentDescription = stringResource(R.string.icon_description_for_disabled_widget), + modifier = Modifier.size(48.dp), + colorFilter = ColorFilter.colorMatrix(Colors.DisabledColorFilter), + ) + } +} + @Composable private fun SmartspaceContent( model: CommunalContentModel.Smartspace, @@ -851,7 +894,7 @@ private fun firstIndexAtOffset(gridState: LazyGridState, offset: Offset): Int? = /** Returns the key of item if it's editable at the given index. Only widget is editable. */ private fun keyAtIndexIfEditable(list: List, index: Int): String? = - if (index in list.indices && list[index].isWidget()) list[index].key else null + if (index in list.indices && list[index].isWidgetContent()) list[index].key else null data class ContentPaddingInPx(val start: Float, val top: Float) { fun toOffset(): Offset = Offset(start, top) @@ -880,5 +923,30 @@ object Dimensions { val IconSize = 48.dp } +private object Colors { + val DisabledColorFilter by lazy { disabledColorMatrix() } + + /** Returns the disabled image filter. Ported over from [DisableImageView]. */ + private fun disabledColorMatrix(): ColorMatrix { + val brightnessMatrix = ColorMatrix() + val brightnessAmount = 0.5f + val brightnessRgb = (255 * brightnessAmount).toInt().toFloat() + // Brightness: C-new = C-old*(1-amount) + amount + val scale = 1f - brightnessAmount + val mat = brightnessMatrix.values + mat[0] = scale + mat[6] = scale + mat[12] = scale + mat[4] = brightnessRgb + mat[9] = brightnessRgb + mat[14] = brightnessRgb + + return ColorMatrix().apply { + setToSaturation(0F) + timesAssign(brightnessMatrix) + } + } +} + /** The resource id of communal hub accessible from UiAutomator. */ private const val COMMUNAL_HUB_TEST_TAG = "communal_hub" diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt index 9b8c9d0ab616..c5dab3347e5f 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/ContentListState.kt @@ -71,8 +71,8 @@ internal constructor( /** Remove widget from the list and the database. */ fun onRemove(indexToRemove: Int) { - if (list[indexToRemove] is CommunalContentModel.Widget) { - val widget = list[indexToRemove] as CommunalContentModel.Widget + if (list[indexToRemove].isWidgetContent()) { + val widget = list[indexToRemove] as CommunalContentModel.WidgetContent list.apply { removeAt(indexToRemove) } onDeleteWidget(widget.appWidgetId) } @@ -100,7 +100,7 @@ internal constructor( val widgetIdToPriorityMap: Map = list .mapIndexedNotNull { index, item -> - if (item is CommunalContentModel.Widget) { + if (item is CommunalContentModel.WidgetContent) { item.appWidgetId to list.size - index } else { null @@ -115,5 +115,5 @@ internal constructor( } /** Returns true if the item at given index is editable. */ - fun isItemEditable(index: Int) = list[index] is CommunalContentModel.Widget + fun isItemEditable(index: Int) = list[index].isWidgetContent() } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt index cd296524c17c..6e3573b64f9a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalInteractorTest.kt @@ -27,6 +27,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.SysuiTestCase +import com.android.systemui.communal.data.repository.CommunalSettingsRepositoryImpl import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository import com.android.systemui.communal.data.repository.FakeCommunalPrefsRepository import com.android.systemui.communal.data.repository.FakeCommunalRepository @@ -62,6 +63,7 @@ import com.android.systemui.user.data.repository.FakeUserRepository import com.android.systemui.user.data.repository.fakeUserRepository import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.whenever +import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.MutableStateFlow @@ -831,6 +833,95 @@ class CommunalInteractorTest : SysuiTestCase() { } } + @Test + fun widgetContent_containsDisabledWidgets_whenCategoryNotAllowed() = + testScope.runTest { + // Communal available, and tutorial completed. + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) + userRepository.setSelectedUserInfo(mainUser) + + val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + runCurrent() + + // Widgets available. + val widget1 = + createWidgetWithCategory(1, AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN) + val widget2 = + createWidgetWithCategory(2, AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) + val widget3 = + createWidgetWithCategory(3, AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX) + val widgets = listOf(widget1, widget2, widget3) + widgetRepository.setCommunalWidgets(widgets) + + val widgetContent by collectLastValue(underTest.widgetContent) + kosmos.fakeSettings.putIntForUser( + CommunalSettingsRepositoryImpl.GLANCEABLE_HUB_CONTENT_SETTING, + AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD, + mainUser.id + ) + runCurrent() + + // Only the keyguard widget is enabled. + assertThat(widgetContent).hasSize(3) + assertThat(widgetContent!!.get(0)) + .isInstanceOf(CommunalContentModel.WidgetContent.DisabledWidget::class.java) + assertThat(widgetContent!!.get(1)) + .isInstanceOf(CommunalContentModel.WidgetContent.Widget::class.java) + assertThat(widgetContent!!.get(2)) + .isInstanceOf(CommunalContentModel.WidgetContent.DisabledWidget::class.java) + } + + @Test + fun widgetContent_allEnabled_whenCategoryAllowed() = + testScope.runTest { + // Communal available, and tutorial completed. + keyguardRepository.setKeyguardShowing(true) + keyguardRepository.setKeyguardOccluded(false) + tutorialRepository.setTutorialSettingState(HUB_MODE_TUTORIAL_COMPLETED) + userRepository.setSelectedUserInfo(mainUser) + + val userInfos = listOf(MAIN_USER_INFO, USER_INFO_WORK) + userRepository.setUserInfos(userInfos) + userTracker.set( + userInfos = userInfos, + selectedUserIndex = 0, + ) + runCurrent() + + // Widgets available. + val widget1 = + createWidgetWithCategory(1, AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN) + val widget2 = + createWidgetWithCategory(2, AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) + val widget3 = + createWidgetWithCategory(3, AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) + val widgets = listOf(widget1, widget2, widget3) + widgetRepository.setCommunalWidgets(widgets) + + val widgetContent by collectLastValue(underTest.widgetContent) + kosmos.fakeSettings.putIntForUser( + CommunalSettingsRepositoryImpl.GLANCEABLE_HUB_CONTENT_SETTING, + AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD or + AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN, + mainUser.id + ) + runCurrent() + + // All widgets are enabled. + assertThat(widgetContent).hasSize(3) + widgetContent!!.forEach { model -> + assertThat(model) + .isInstanceOf(CommunalContentModel.WidgetContent.Widget::class.java) + } + } + private fun smartspaceTimer(id: String, timestamp: Long = 0L): SmartspaceTarget { val timer = mock(SmartspaceTarget::class.java) whenever(timer.smartspaceTargetId).thenReturn(id) @@ -848,6 +939,17 @@ class CommunalInteractorTest : SysuiTestCase() { whenever(this.providerInfo).thenReturn(providerInfo) } + private fun createWidgetWithCategory( + appWidgetId: Int, + category: Int + ): CommunalWidgetContentModel = + mock { + whenever(this.appWidgetId).thenReturn(appWidgetId) + val providerInfo = mock().apply { widgetCategory = category } + whenever(providerInfo.profile).thenReturn(UserHandle(MAIN_USER_INFO.id)) + whenever(this.providerInfo).thenReturn(providerInfo) + } + private companion object { val MAIN_USER_INFO = UserInfo(0, "primary", UserInfo.FLAG_MAIN) val USER_INFO_WORK = UserInfo(10, "work", UserInfo.FLAG_PROFILE) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt index 5ee88cb92fa0..8e2e94716660 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt @@ -135,9 +135,9 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { // Only Widgets and CTA tile are shown. assertThat(communalContent?.size).isEqualTo(3) assertThat(communalContent?.get(0)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(1)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(2)) .isInstanceOf(CommunalContentModel.CtaTileInEditMode::class.java) } @@ -181,9 +181,9 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { // Widgets and CTA tile are shown. assertThat(communalContent?.size).isEqualTo(3) assertThat(communalContent?.get(0)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(1)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(2)) .isInstanceOf(CommunalContentModel.CtaTileInEditMode::class.java) @@ -192,7 +192,8 @@ class CommunalEditModeViewModelTest : SysuiTestCase() { // Only one widget and CTA tile remain. assertThat(communalContent?.size).isEqualTo(2) val item = communalContent?.get(0) - val appWidgetId = if (item is CommunalContentModel.Widget) item.appWidgetId else null + val appWidgetId = + if (item is CommunalContentModel.WidgetContent) item.appWidgetId else null assertThat(appWidgetId).isEqualTo(widgets.get(1).appWidgetId) assertThat(communalContent?.get(1)) .isInstanceOf(CommunalContentModel.CtaTileInEditMode::class.java) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt index 1e523dd2a9cc..563aad1920f7 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalViewModelTest.kt @@ -184,9 +184,9 @@ class CommunalViewModelTest : SysuiTestCase() { .isInstanceOf(CommunalContentModel.Smartspace::class.java) assertThat(communalContent?.get(1)).isInstanceOf(CommunalContentModel.Umo::class.java) assertThat(communalContent?.get(2)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(3)) - .isInstanceOf(CommunalContentModel.Widget::class.java) + .isInstanceOf(CommunalContentModel.WidgetContent::class.java) assertThat(communalContent?.get(4)) .isInstanceOf(CommunalContentModel.CtaTileInViewMode::class.java) } diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 4263d9402d66..b62855b8b62a 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1114,6 +1114,8 @@ Long press to customize widgets Customize widgets + + App icon for disabled widget Edit widget diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt index 5d525413a919..151e1eeaefc5 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt @@ -24,6 +24,7 @@ import com.android.systemui.communal.data.repository.CommunalPrefsRepository import com.android.systemui.communal.data.repository.CommunalRepository import com.android.systemui.communal.data.repository.CommunalWidgetRepository import com.android.systemui.communal.domain.model.CommunalContentModel +import com.android.systemui.communal.domain.model.CommunalContentModel.WidgetContent import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.shared.model.CommunalContentSize.FULL import com.android.systemui.communal.shared.model.CommunalContentSize.HALF @@ -278,14 +279,25 @@ constructor( } /** A list of widget content to be displayed in the communal hub. */ - val widgetContent: Flow> = - widgetRepository.communalWidgets.map { widgets -> - filterWidgetsByExistingUsers(widgets).map Widget@{ widget -> - return@Widget CommunalContentModel.Widget( - appWidgetId = widget.appWidgetId, - providerInfo = widget.providerInfo, - appWidgetHost = appWidgetHost, - ) + val widgetContent: Flow> = + combine( + widgetRepository.communalWidgets.map { filterWidgetsByExistingUsers(it) }, + communalSettingsInteractor.communalWidgetCategories + ) { widgets, allowedCategories -> + widgets.map { widget -> + if (widget.providerInfo.widgetCategory and allowedCategories != 0) { + // At least one category this widget specified is allowed, so show it + WidgetContent.Widget( + appWidgetId = widget.appWidgetId, + providerInfo = widget.providerInfo, + appWidgetHost = appWidgetHost, + ) + } else { + WidgetContent.DisabledWidget( + appWidgetId = widget.appWidgetId, + providerInfo = widget.providerInfo, + ) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt index ae019a187bae..c64f666ebf10 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt @@ -18,6 +18,7 @@ package com.android.systemui.communal.domain.model import android.appwidget.AppWidgetProviderInfo import android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE +import android.content.pm.ApplicationInfo import android.widget.RemoteViews import com.android.systemui.communal.shared.model.CommunalContentSize import com.android.systemui.communal.widgets.CommunalAppWidgetHost @@ -42,20 +43,37 @@ sealed interface CommunalContentModel { val createdTimestampMillis: Long } - data class Widget( - val appWidgetId: Int, - val providerInfo: AppWidgetProviderInfo, - val appWidgetHost: CommunalAppWidgetHost, - ) : CommunalContentModel { - override val key = KEY.widget(appWidgetId) - // Widget size is always half. - override val size = CommunalContentSize.HALF + sealed interface WidgetContent : CommunalContentModel { + val appWidgetId: Int + val providerInfo: AppWidgetProviderInfo + + data class Widget( + override val appWidgetId: Int, + override val providerInfo: AppWidgetProviderInfo, + val appWidgetHost: CommunalAppWidgetHost, + ) : WidgetContent { + override val key = KEY.widget(appWidgetId) + // Widget size is always half. + override val size = CommunalContentSize.HALF + + /** Whether this widget can be reconfigured after it has already been added. */ + val reconfigurable: Boolean + get() = + (providerInfo.widgetFeatures and WIDGET_FEATURE_RECONFIGURABLE != 0) && + providerInfo.configure != null + } + + data class DisabledWidget( + override val appWidgetId: Int, + override val providerInfo: AppWidgetProviderInfo + ) : WidgetContent { + override val key = KEY.disabledWidget(appWidgetId) + // Widget size is always half. + override val size = CommunalContentSize.HALF - /** Whether this widget can be reconfigured after it has already been added. */ - val reconfigurable: Boolean - get() = - (providerInfo.widgetFeatures and WIDGET_FEATURE_RECONFIGURABLE != 0) && - providerInfo.configure != null + val appInfo: ApplicationInfo? + get() = providerInfo.providerInfo?.applicationInfo + } } /** A placeholder item representing a new widget being added */ @@ -111,6 +129,10 @@ sealed interface CommunalContentModel { return "widget_$id" } + fun disabledWidget(id: Int): String { + return "disabled_widget_$id" + } + fun widgetPlaceholder(): String { return "widget_placeholder_${UUID.randomUUID()}" } @@ -129,5 +151,5 @@ sealed interface CommunalContentModel { } } - fun isWidget() = this is Widget + fun isWidgetContent() = this is WidgetContent } -- cgit v1.2.3-59-g8ed1b