summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt8
-rw-r--r--packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt15
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt31
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt126
-rw-r--r--packages/SystemUI/res/layout/edit_widgets.xml32
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt44
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt31
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetPickerActivity.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt4
11 files changed, 245 insertions, 57 deletions
diff --git a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
index e369773f37f1..914e5f2c17bf 100644
--- a/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/disabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -47,6 +47,14 @@ object ComposeFacade : BaseComposeFacade {
throwComposeUnavailableError()
}
+ override fun setCommunalEditWidgetActivityContent(
+ activity: ComponentActivity,
+ viewModel: BaseCommunalViewModel,
+ onOpenWidgetPicker: () -> Unit,
+ ) {
+ throwComposeUnavailableError()
+ }
+
override fun createFooterActionsView(
context: Context,
viewModel: FooterActionsViewModel,
diff --git a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
index 7aba4308053b..59bd95bd9027 100644
--- a/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
+++ b/packages/SystemUI/compose/facade/enabled/src/com/android/systemui/compose/ComposeFacade.kt
@@ -62,6 +62,21 @@ object ComposeFacade : BaseComposeFacade {
activity.setContent { PlatformTheme { PeopleScreen(viewModel, onResult) } }
}
+ override fun setCommunalEditWidgetActivityContent(
+ activity: ComponentActivity,
+ viewModel: BaseCommunalViewModel,
+ onOpenWidgetPicker: () -> Unit,
+ ) {
+ activity.setContent {
+ PlatformTheme {
+ CommunalHub(
+ viewModel = viewModel,
+ onOpenWidgetPicker = onOpenWidgetPicker,
+ )
+ }
+ }
+ }
+
override fun createFooterActionsView(
context: Context,
viewModel: FooterActionsViewModel,
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 4891a680e2e1..6161cc12d2ac 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
@@ -34,6 +34,7 @@ import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Close
+import androidx.compose.material.icons.filled.Edit
import androidx.compose.material3.Card
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -60,6 +61,7 @@ import com.android.systemui.res.R
fun CommunalHub(
modifier: Modifier = Modifier,
viewModel: BaseCommunalViewModel,
+ onOpenWidgetPicker: (() -> Unit)? = null,
) {
val communalContent by viewModel.communalContent.collectAsState(initial = emptyList())
Box(
@@ -81,7 +83,7 @@ fun CommunalHub(
modifier = Modifier.fillMaxHeight().width(Dimensions.CardWidth),
model = communalContent[index],
viewModel = viewModel,
- deleteOnClick = viewModel::onDeleteWidget,
+ deleteOnClick = if (viewModel.isEditMode) viewModel::onDeleteWidget else null,
size =
SizeF(
Dimensions.CardWidth.value,
@@ -90,8 +92,14 @@ fun CommunalHub(
)
}
}
- IconButton(onClick = viewModel::onOpenWidgetEditor) {
- Icon(Icons.Default.Add, stringResource(R.string.button_to_open_widget_editor))
+ if (viewModel.isEditMode && onOpenWidgetPicker != null) {
+ IconButton(onClick = onOpenWidgetPicker) {
+ Icon(Icons.Default.Add, stringResource(R.string.hub_mode_add_widget_button_text))
+ }
+ } else {
+ IconButton(onClick = viewModel::onOpenWidgetEditor) {
+ Icon(Icons.Default.Edit, stringResource(R.string.button_to_open_widget_editor))
+ }
}
// This spacer covers the edge of the LazyHorizontalGrid and prevents it from receiving
@@ -111,7 +119,7 @@ private fun CommunalContent(
model: CommunalContentModel,
viewModel: BaseCommunalViewModel,
size: SizeF,
- deleteOnClick: (id: Int) -> Unit,
+ deleteOnClick: ((id: Int) -> Unit)?,
modifier: Modifier = Modifier,
) {
when (model) {
@@ -126,19 +134,22 @@ private fun CommunalContent(
private fun WidgetContent(
model: CommunalContentModel.Widget,
size: SizeF,
- deleteOnClick: (id: Int) -> Unit,
+ deleteOnClick: ((id: Int) -> Unit)?,
modifier: Modifier = Modifier,
) {
// TODO(b/309009246): update background color
Box(
modifier = modifier.fillMaxSize().background(Color.White),
) {
- IconButton(onClick = { deleteOnClick(model.appWidgetId) }) {
- Icon(
- Icons.Default.Close,
- LocalContext.current.getString(R.string.button_to_remove_widget)
- )
+ if (deleteOnClick != null) {
+ IconButton(onClick = { deleteOnClick(model.appWidgetId) }) {
+ Icon(
+ Icons.Default.Close,
+ LocalContext.current.getString(R.string.button_to_remove_widget)
+ )
+ }
}
+
AndroidView(
modifier = modifier,
factory = { context ->
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
new file mode 100644
index 000000000000..ce7db80db7da
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/view/viewmodel/CommunalEditModeViewModelTest.kt
@@ -0,0 +1,126 @@
+/*
+ * 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.systemui.communal.view.viewmodel
+
+import android.app.smartspace.SmartspaceTarget
+import android.provider.Settings
+import android.widget.RemoteViews
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.data.repository.FakeCommunalMediaRepository
+import com.android.systemui.communal.data.repository.FakeCommunalRepository
+import com.android.systemui.communal.data.repository.FakeCommunalTutorialRepository
+import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
+import com.android.systemui.communal.domain.interactor.CommunalInteractorFactory
+import com.android.systemui.communal.domain.model.CommunalContentModel
+import com.android.systemui.communal.shared.model.CommunalWidgetContentModel
+import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.smartspace.data.repository.FakeSmartspaceRepository
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class CommunalEditModeViewModelTest : SysuiTestCase() {
+ @Mock private lateinit var mediaHost: MediaHost
+
+ private lateinit var testScope: TestScope
+
+ private lateinit var keyguardRepository: FakeKeyguardRepository
+ private lateinit var communalRepository: FakeCommunalRepository
+ private lateinit var tutorialRepository: FakeCommunalTutorialRepository
+ private lateinit var widgetRepository: FakeCommunalWidgetRepository
+ private lateinit var smartspaceRepository: FakeSmartspaceRepository
+ private lateinit var mediaRepository: FakeCommunalMediaRepository
+
+ private lateinit var underTest: CommunalEditModeViewModel
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ testScope = TestScope()
+
+ val withDeps = CommunalInteractorFactory.create()
+ keyguardRepository = withDeps.keyguardRepository
+ communalRepository = withDeps.communalRepository
+ tutorialRepository = withDeps.tutorialRepository
+ widgetRepository = withDeps.widgetRepository
+ smartspaceRepository = withDeps.smartspaceRepository
+ mediaRepository = withDeps.mediaRepository
+
+ underTest =
+ CommunalEditModeViewModel(
+ withDeps.communalInteractor,
+ mediaHost,
+ )
+ }
+
+ @Test
+ fun communalContent_onlyWidgetsAreShownInEditMode() =
+ testScope.runTest {
+ tutorialRepository.setTutorialSettingState(Settings.Secure.HUB_MODE_TUTORIAL_COMPLETED)
+
+ // Widgets available.
+ val widgets =
+ listOf(
+ CommunalWidgetContentModel(
+ appWidgetId = 0,
+ priority = 30,
+ providerInfo = mock(),
+ ),
+ CommunalWidgetContentModel(
+ appWidgetId = 1,
+ priority = 20,
+ providerInfo = mock(),
+ ),
+ )
+ widgetRepository.setCommunalWidgets(widgets)
+
+ // Smartspace available.
+ val target = Mockito.mock(SmartspaceTarget::class.java)
+ whenever(target.smartspaceTargetId).thenReturn("target")
+ whenever(target.featureType).thenReturn(SmartspaceTarget.FEATURE_TIMER)
+ whenever(target.remoteViews).thenReturn(Mockito.mock(RemoteViews::class.java))
+ smartspaceRepository.setLockscreenSmartspaceTargets(listOf(target))
+
+ // Media playing.
+ mediaRepository.mediaPlaying.value = true
+
+ val communalContent by collectLastValue(underTest.communalContent)
+
+ // Only Widgets are shown.
+ assertThat(communalContent?.size).isEqualTo(2)
+ assertThat(communalContent?.get(0))
+ .isInstanceOf(CommunalContentModel.Widget::class.java)
+ assertThat(communalContent?.get(1))
+ .isInstanceOf(CommunalContentModel.Widget::class.java)
+ }
+}
diff --git a/packages/SystemUI/res/layout/edit_widgets.xml b/packages/SystemUI/res/layout/edit_widgets.xml
deleted file mode 100644
index 182e651aa66d..000000000000
--- a/packages/SystemUI/res/layout/edit_widgets.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<!--
- ~ 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.
- -->
-
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/edit_widgets"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <Button
- style="@android:Widget.DeviceDefault.Button.Colored"
- android:id="@+id/add_widget"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:textSize="28sp"
- android:text="@string/hub_mode_add_widget_button_text"/>
-
-</FrameLayout>
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
index 10e9ee855be0..98f3594801f3 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/BaseCommunalViewModel.kt
@@ -37,6 +37,9 @@ abstract class BaseCommunalViewModel(
/** A list of all the communal content to be displayed in the communal hub. */
abstract val communalContent: Flow<List<CommunalContentModel>>
+ /** Whether in edit mode for the communal hub. */
+ open val isEditMode = false
+
/** Called as the UI requests deleting a widget. */
open fun onDeleteWidget(id: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
new file mode 100644
index 000000000000..14d9b2ca80f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/ui/viewmodel/CommunalEditModeViewModel.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.systemui.communal.ui.viewmodel
+
+import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.communal.domain.model.CommunalContentModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.media.controls.ui.MediaHost
+import com.android.systemui.media.dagger.MediaModule
+import javax.inject.Inject
+import javax.inject.Named
+import kotlinx.coroutines.flow.Flow
+
+/** The view model for communal hub in edit mode. */
+@SysUISingleton
+class CommunalEditModeViewModel
+@Inject
+constructor(
+ private val communalInteractor: CommunalInteractor,
+ @Named(MediaModule.COMMUNAL_HUB) mediaHost: MediaHost,
+) : BaseCommunalViewModel(communalInteractor, mediaHost) {
+
+ override val isEditMode = true
+
+ // Only widgets are editable.
+ override val communalContent: Flow<List<CommunalContentModel>> =
+ communalInteractor.widgetContent
+
+ override fun onDeleteWidget(id: Int) = communalInteractor.deleteWidget(id)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
index 78e85db9ea05..7b94fc182fe2 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/EditWidgetsActivity.kt
@@ -20,17 +20,21 @@ import android.appwidget.AppWidgetProviderInfo
import android.content.Intent
import android.os.Bundle
import android.util.Log
-import android.view.View
import androidx.activity.ComponentActivity
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import com.android.systemui.communal.domain.interactor.CommunalInteractor
-import com.android.systemui.res.R
+import com.android.systemui.communal.ui.viewmodel.CommunalEditModeViewModel
+import com.android.systemui.compose.ComposeFacade.setCommunalEditWidgetActivityContent
import javax.inject.Inject
/** An Activity for editing the widgets that appear in hub mode. */
-class EditWidgetsActivity @Inject constructor(private val communalInteractor: CommunalInteractor) :
- ComponentActivity() {
+class EditWidgetsActivity
+@Inject
+constructor(
+ private val communalViewModel: CommunalEditModeViewModel,
+ private val communalInteractor: CommunalInteractor,
+) : ComponentActivity() {
companion object {
/**
* Intent extra name for the {@link AppWidgetProviderInfo} of a widget to add to hub mode.
@@ -59,20 +63,19 @@ class EditWidgetsActivity @Inject constructor(private val communalInteractor: Co
"Failed to receive result from widget picker, code=${result.resultCode}"
)
}
- this@EditWidgetsActivity.finish()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setShowWhenLocked(true)
- setContentView(R.layout.edit_widgets)
-
- val addWidgetsButton = findViewById<View>(R.id.add_widget)
- addWidgetsButton?.setOnClickListener({
- addWidgetActivityLauncher.launch(
- Intent(applicationContext, WidgetPickerActivity::class.java)
- )
- })
+ setCommunalEditWidgetActivityContent(
+ activity = this,
+ viewModel = communalViewModel,
+ onOpenWidgetPicker = {
+ addWidgetActivityLauncher.launch(
+ Intent(applicationContext, WidgetPickerActivity::class.java)
+ )
+ },
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetPickerActivity.kt b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetPickerActivity.kt
index 3e6dbd5a7115..a2765486bf2d 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetPickerActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/widgets/WidgetPickerActivity.kt
@@ -43,7 +43,6 @@ constructor(
super.onCreate(savedInstanceState)
setContentView(R.layout.widget_picker)
- setShowWhenLocked(true)
loadWidgets()
}
diff --git a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
index 38c120da614b..65d44957222a 100644
--- a/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
+++ b/packages/SystemUI/src/com/android/systemui/compose/BaseComposeFacade.kt
@@ -58,6 +58,13 @@ interface BaseComposeFacade {
onResult: (PeopleViewModel.Result) -> Unit,
)
+ /** Bind the content of [activity] to [viewModel]. */
+ fun setCommunalEditWidgetActivityContent(
+ activity: ComponentActivity,
+ viewModel: BaseCommunalViewModel,
+ onOpenWidgetPicker: () -> Unit,
+ )
+
/** Create a [View] to represent [viewModel] on screen. */
fun createFooterActionsView(
context: Context,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index d3744d55c55d..4068e408f0bd 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -167,6 +167,10 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
_isKeyguardOccluded.value = isOccluded
}
+ fun setKeyguardUnlocked(isUnlocked: Boolean) {
+ _isKeyguardUnlocked.value = isUnlocked
+ }
+
override fun setIsDozing(isDozing: Boolean) {
_isDozing.value = isDozing
}