Add falsing for edit mode button
Add a viewmodel for the button. Also, the action to start editing is not
needed anymore as part of TileGrid.
Test: manual, enter edit mode
Test: atest EditModeButtonViewModelTest
Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Fixes: 379311646
Change-Id: I6e7a1c864ed2eba1202cee0473816d11f4df96a3
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index 26c827a..f84865f 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -168,7 +168,6 @@
modifier =
Modifier.fillMaxWidth()
.heightIn(max = QuickSettingsShade.Dimensions.GridMaxHeight),
- viewModel.editModeViewModel::startEditing,
)
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt
new file mode 100644
index 0000000..f2bfd72
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelTest.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2024 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.qs.panels.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.fakeFalsingManager
+import com.android.systemui.kosmos.collectLastValue
+import com.android.systemui.kosmos.runCurrent
+import com.android.systemui.kosmos.runTest
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class EditModeButtonViewModelTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+
+ val underTest = kosmos.editModeButtonViewModelFactory.create()
+
+ @Test
+ fun falsingFalseTap_editModeDoesntStart() =
+ kosmos.runTest {
+ val isEditing by collectLastValue(editModeViewModel.isEditing)
+
+ fakeFalsingManager.setFalseTap(true)
+
+ underTest.onButtonClick()
+ runCurrent()
+
+ assertThat(isEditing).isFalse()
+ }
+
+ @Test
+ fun falsingNotFalseTap_editModeStarted() =
+ kosmos.runTest {
+ val isEditing by collectLastValue(editModeViewModel.isEditing)
+
+ fakeFalsingManager.setFalseTap(false)
+
+ underTest.onButtonClick()
+ runCurrent()
+
+ assertThat(isEditing).isTrue()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt b/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt
index 57e9ade..074b64e 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/classifier/domain/interactor/FalsingInteractor.kt
@@ -23,6 +23,7 @@
import com.android.systemui.classifier.FalsingCollectorActual
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.FalsingManager.Penalty
import javax.inject.Inject
/**
@@ -63,12 +64,13 @@
* Inserts the given [result] into the falsing system, affecting future runs of the classifier
* as if this was a result that had organically happened before.
*/
- fun updateFalseConfidence(
- result: FalsingClassifier.Result,
- ) = collector.updateFalseConfidence(result)
+ fun updateFalseConfidence(result: FalsingClassifier.Result) =
+ collector.updateFalseConfidence(result)
/** Returns `true` if the gesture should be rejected. */
- fun isFalseTouch(
- @Classifier.InteractionType interactionType: Int,
- ): Boolean = manager.isFalseTouch(interactionType)
+ fun isFalseTouch(@Classifier.InteractionType interactionType: Int): Boolean =
+ manager.isFalseTouch(interactionType)
+
+ /** Returns `true` if the tap gesture should be rejected */
+ fun isFalseTap(@Penalty penalty: Int): Boolean = manager.isFalseTap(penalty)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
index 32790be..5167d17 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/composefragment/QSFragmentCompose.kt
@@ -719,7 +719,6 @@
max =
QuickSettingsShade.Dimensions.GridMaxHeight
),
- containerViewModel.editModeViewModel::startEditing,
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt
new file mode 100644
index 0000000..c2764f9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/EditModeButton.kt
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2024 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.qs.panels.ui.compose
+
+import androidx.compose.foundation.shape.CornerSize
+import androidx.compose.foundation.shape.RoundedCornerShape
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Edit
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.LocalContentColor
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.CompositionLocalProvider
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.unit.dp
+import com.android.systemui.lifecycle.rememberViewModel
+import com.android.systemui.qs.panels.ui.viewmodel.EditModeButtonViewModel
+import com.android.systemui.qs.ui.compose.borderOnFocus
+import com.android.systemui.res.R
+
+@Composable
+fun EditModeButton(
+ viewModelFactory: EditModeButtonViewModel.Factory,
+ modifier: Modifier = Modifier,
+) {
+ val viewModel = rememberViewModel(traceName = "EditModeButton") { viewModelFactory.create() }
+ CompositionLocalProvider(
+ value = LocalContentColor provides MaterialTheme.colorScheme.onSurface
+ ) {
+ IconButton(
+ onClick = viewModel::onButtonClick,
+ shape = RoundedCornerShape(CornerSize(28.dp)),
+ modifier =
+ modifier.borderOnFocus(
+ color = MaterialTheme.colorScheme.secondary,
+ cornerSize = CornerSize(24.dp),
+ ),
+ ) {
+ Icon(
+ imageVector = Icons.Default.Edit,
+ contentDescription = stringResource(id = R.string.qs_edit),
+ )
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
index 0d37581..a22eb3a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/GridLayout.kt
@@ -27,12 +27,7 @@
/** A layout of tiles, indicating how they should be composed when showing in QS or in edit mode. */
interface GridLayout {
- @Composable
- fun SceneScope.TileGrid(
- tiles: List<TileViewModel>,
- modifier: Modifier,
- editModeStart: () -> Unit,
- )
+ @Composable fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier)
@Composable
fun EditTileGrid(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
index 32eaba2..b6dbf4d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/PaginatedGridLayout.kt
@@ -30,15 +30,8 @@
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CornerSize
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.Edit
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
-import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
@@ -46,7 +39,6 @@
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInteropFilter
-import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
@@ -57,10 +49,10 @@
import com.android.systemui.qs.panels.dagger.PaginatedBaseLayoutType
import com.android.systemui.qs.panels.ui.compose.Dimensions.FooterHeight
import com.android.systemui.qs.panels.ui.compose.Dimensions.InterPageSpacing
+import com.android.systemui.qs.panels.ui.viewmodel.EditModeButtonViewModel
import com.android.systemui.qs.panels.ui.viewmodel.PaginatedGridViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileViewModel
import com.android.systemui.qs.ui.compose.borderOnFocus
-import com.android.systemui.res.R
import javax.inject.Inject
class PaginatedGridLayout
@@ -70,11 +62,7 @@
@PaginatedBaseLayoutType private val delegateGridLayout: PaginatableGridLayout,
) : GridLayout by delegateGridLayout {
@Composable
- override fun SceneScope.TileGrid(
- tiles: List<TileViewModel>,
- modifier: Modifier,
- editModeStart: () -> Unit,
- ) {
+ override fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) {
val viewModel =
rememberViewModel(traceName = "PaginatedGridLayout-TileGrid") {
viewModelFactory.create()
@@ -131,14 +119,12 @@
) {
val page = pages[it]
- with(delegateGridLayout) {
- TileGrid(tiles = page, modifier = Modifier, editModeStart = {})
- }
+ with(delegateGridLayout) { TileGrid(tiles = page, modifier = Modifier) }
}
FooterBar(
buildNumberViewModelFactory = viewModel.buildNumberViewModelFactory,
pagerState = pagerState,
- editModeStart = editModeStart,
+ editButtonViewModelFactory = viewModel.editModeButtonViewModelFactory,
)
}
}
@@ -153,7 +139,7 @@
private fun FooterBar(
buildNumberViewModelFactory: BuildNumberViewModel.Factory,
pagerState: PagerState,
- editModeStart: () -> Unit,
+ editButtonViewModelFactory: EditModeButtonViewModel.Factory,
) {
// Use requiredHeight so it won't be squished if the view doesn't quite fit. As this is
// expected to be inside a scrollable container, this should not be an issue.
@@ -189,24 +175,7 @@
)
Row(Modifier.weight(1f)) {
Spacer(modifier = Modifier.weight(1f))
- CompositionLocalProvider(
- value = LocalContentColor provides MaterialTheme.colorScheme.onSurface
- ) {
- IconButton(
- onClick = editModeStart,
- shape = RoundedCornerShape(CornerSize(28.dp)),
- modifier =
- Modifier.borderOnFocus(
- color = MaterialTheme.colorScheme.secondary,
- cornerSize = CornerSize(FooterHeight / 2),
- ),
- ) {
- Icon(
- imageVector = Icons.Default.Edit,
- contentDescription = stringResource(id = R.string.qs_edit),
- )
- }
- }
+ EditModeButton(viewModelFactory = editButtonViewModelFactory)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
index 1a5297b..6c1906b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/TileGrid.kt
@@ -24,13 +24,9 @@
import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
@Composable
-fun SceneScope.TileGrid(
- viewModel: TileGridViewModel,
- modifier: Modifier = Modifier,
- editModeStart: () -> Unit,
-) {
+fun SceneScope.TileGrid(viewModel: TileGridViewModel, modifier: Modifier = Modifier) {
val gridLayout by viewModel.gridLayout.collectAsStateWithLifecycle()
val tiles by viewModel.tileViewModels.collectAsStateWithLifecycle(emptyList())
- with(gridLayout) { TileGrid(tiles, modifier, editModeStart) }
+ with(gridLayout) { TileGrid(tiles, modifier) }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
index 29ff171..cb857ae 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/compose/infinitegrid/InfiniteGridLayout.kt
@@ -55,11 +55,7 @@
) : PaginatableGridLayout {
@Composable
- override fun SceneScope.TileGrid(
- tiles: List<TileViewModel>,
- modifier: Modifier,
- editModeStart: () -> Unit,
- ) {
+ override fun SceneScope.TileGrid(tiles: List<TileViewModel>, modifier: Modifier) {
DisposableEffect(tiles) {
val token = Any()
tiles.forEach { it.startListening(token) }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt
new file mode 100644
index 0000000..b033473
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModel.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 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.qs.panels.ui.viewmodel
+
+import com.android.systemui.classifier.domain.interactor.FalsingInteractor
+import com.android.systemui.plugins.FalsingManager
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+
+class EditModeButtonViewModel
+@AssistedInject
+constructor(
+ private val editModeViewModel: EditModeViewModel,
+ private val falsingInteractor: FalsingInteractor,
+) {
+
+ fun onButtonClick() {
+ if (!falsingInteractor.isFalseTap(FalsingManager.LOW_PENALTY)) {
+ editModeViewModel.startEditing()
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): EditModeButtonViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
index b5873be..4a18872 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModel.kt
@@ -38,6 +38,7 @@
paginatedGridInteractor: PaginatedGridInteractor,
inFirstPageViewModel: InFirstPageViewModel,
val buildNumberViewModelFactory: BuildNumberViewModel.Factory,
+ val editModeButtonViewModelFactory: EditModeButtonViewModel.Factory,
private val falsingInteractor: FalsingInteractor,
) : IconTilesViewModel by iconTilesViewModel, ExclusiveActivatable() {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt
new file mode 100644
index 0000000..b8d3ff4
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/EditModeButtonViewModelKosmos.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2024 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.qs.panels.ui.viewmodel
+
+import com.android.systemui.classifier.domain.interactor.falsingInteractor
+import com.android.systemui.kosmos.Kosmos
+
+val Kosmos.editModeButtonViewModelFactory by
+ Kosmos.Fixture {
+ object : EditModeButtonViewModel.Factory {
+ override fun create(): EditModeButtonViewModel {
+ return EditModeButtonViewModel(editModeViewModel, falsingInteractor)
+ }
+ }
+ }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt
index d515ad0..5c71ba2 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/panels/ui/viewmodel/PaginatedGridViewModelKosmos.kt
@@ -29,6 +29,7 @@
paginatedGridInteractor,
inFirstPageViewModel,
buildNumberViewModelFactory,
+ editModeButtonViewModelFactory,
falsingInteractor,
)
}