diff options
| author | 2024-02-14 21:12:59 +0000 | |
|---|---|---|
| committer | 2024-02-28 03:34:47 +0000 | |
| commit | e79d75b3d534ada3b00e40e13521fa669e705e59 (patch) | |
| tree | a506d6ad657a7f74bedb5fbfd258170e92483d6e | |
| parent | 5ade91bec6f5e720786eed23c0d2bd42758aedac (diff) | |
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
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, ) { @@ -751,6 +762,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, modifier: Modifier = Modifier, @@ -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<CommunalContentModel>, 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<Int, Int> = 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<CommunalWidgetContentModel> { + whenever(this.appWidgetId).thenReturn(appWidgetId) + val providerInfo = mock<AppWidgetProviderInfo>().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 @@ <string name="popup_on_dismiss_cta_tile_text">Long press to customize widgets</string> <!-- Text for the button to configure widgets after long press. [CHAR LIMIT=50] --> <string name="button_to_configure_widgets_text">Customize widgets</string> + <!-- Description for the App icon of disabled widget. [CHAR LIMIT=NONE] --> + <string name="icon_description_for_disabled_widget">App icon for disabled widget</string> <!-- Label for the button which configures widgets [CHAR LIMIT=NONE] --> <string name="edit_widget">Edit widget</string> <!-- Description for the button that removes a widget on click. [CHAR LIMIT=50] --> 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<List<CommunalContentModel.Widget>> = - widgetRepository.communalWidgets.map { widgets -> - filterWidgetsByExistingUsers(widgets).map Widget@{ widget -> - return@Widget CommunalContentModel.Widget( - appWidgetId = widget.appWidgetId, - providerInfo = widget.providerInfo, - appWidgetHost = appWidgetHost, - ) + val widgetContent: Flow<List<WidgetContent>> = + 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 } |