summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Josh <jmokut@google.com> 2024-11-18 10:44:09 +0000
committer Josh <jmokut@google.com> 2024-11-19 10:12:28 +0000
commit75e4420cd29f8f6140739ecde6b15772cc0cfdc7 (patch)
treef07deb58f724e30878eceb3384377058f7123129
parent293f2dbfc23bfdc50f33ba33134e25789485ab85 (diff)
Capturing user's selected custom key combination for shortcuts
When user presses a key combination we capture it, and display on the UI. Test: ShortcutCustomizationViewModelTest Flag: com.android.systemui.keyboard_shortcut_helper_shortcut_customizer Bug: 373631227 Change-Id: Iac6718b5377108849e915ea8121be7a8da44c890
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt87
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt61
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt132
6 files changed, 277 insertions, 24 deletions
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 53ab686ff0d7..b479c8abb530 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3818,6 +3818,10 @@
assigning a new custom key combination to a shortcut in shortcut helper. The helper is a
component that shows the user which keyboard shortcuts they can use. [CHAR LIMIT=NONE] -->
<string name="shortcut_helper_customize_dialog_error_message">Key combination already in use. Try another key.</string>
+ <!-- Plus sign, used in keyboard shortcut helper to combine keys for shortcut. E.g. Ctrl + A
+ The helper is a component that shows the user which keyboard shortcuts they can use.
+ [CHAR LIMIT=NONE] -->
+ <string name="shortcut_helper_plus_symbol">+</string>
<!-- Keyboard touchpad tutorial scheduler-->
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
index e44bfe30a8bb..2cb822eb0609 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/ShortcutCustomizationDialogStarter.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyboard.shortcut.ui
import android.app.Dialog
+import android.view.WindowManager.LayoutParams.PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
@@ -33,6 +34,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialogFactory
import com.android.systemui.statusbar.phone.create
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
+import kotlinx.coroutines.awaitCancellation
class ShortcutCustomizationDialogStarter
@AssistedInject
@@ -48,7 +50,7 @@ constructor(
viewModel.shortcutCustomizationUiState.collect { uiState ->
if (
uiState is ShortcutCustomizationUiState.AddShortcutDialog &&
- !uiState.isDialogShowing
+ !uiState.isDialogShowing
) {
dialog = createAddShortcutDialog().also { it.show() }
viewModel.onAddShortcutDialogShown()
@@ -57,6 +59,7 @@ constructor(
dialog = null
}
}
+ awaitCancellation()
}
fun onShortcutCustomizationRequested(requestInfo: ShortcutCustomizationRequestInfo) {
@@ -66,14 +69,21 @@ constructor(
private fun createAddShortcutDialog(): Dialog {
return dialogFactory.create(dialogDelegate = ShortcutCustomizationDialogDelegate()) { dialog
->
- val uiState by viewModel.shortcutCustomizationUiState.collectAsStateWithLifecycle()
+ val uiState by
+ viewModel.shortcutCustomizationUiState.collectAsStateWithLifecycle(
+ initialValue = ShortcutCustomizationUiState.Inactive
+ )
AssignNewShortcutDialog(
uiState = uiState,
modifier = Modifier.width(364.dp).wrapContentHeight().padding(vertical = 24.dp),
onKeyPress = { viewModel.onKeyPressed(it) },
onCancel = { dialog.dismiss() },
)
- dialog.setOnDismissListener { viewModel.onAddShortcutDialogDismissed() }
+ dialog.setOnDismissListener { viewModel.onDialogDismissed() }
+
+ // By default, apps cannot intercept action key. The system always handles it. This
+ // flag is needed to enable customisation dialog window to intercept action key
+ dialog.window?.addPrivateFlags(PRIVATE_FLAG_ALLOW_ACTION_KEY_EVENTS)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
index 43f0f200ab23..955470f426ab 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/composable/ShortcutCustomizer.kt
@@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
@@ -45,12 +46,13 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.KeyEvent
-import androidx.compose.ui.input.key.onPreviewKeyEvent
+import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
+import com.android.compose.ui.graphics.painter.rememberDrawablePainter
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
import com.android.systemui.res.R
@@ -81,6 +83,7 @@ fun AssignNewShortcutDialog(
SelectedKeyCombinationContainer(
shouldShowErrorMessage = uiState.shouldShowErrorMessage,
onKeyPress = onKeyPress,
+ pressedKeys = uiState.pressedKeys,
)
KeyCombinationAlreadyInUseErrorMessage(uiState.shouldShowErrorMessage)
DialogButtons(onCancel, isValidKeyCombination = uiState.isValidKeyCombination)
@@ -137,10 +140,9 @@ fun KeyCombinationAlreadyInUseErrorMessage(shouldShowErrorMessage: Boolean) {
@Composable
fun SelectedKeyCombinationContainer(
- keyCombination: String =
- stringResource(R.string.shortcut_helper_add_shortcut_dialog_placeholder),
shouldShowErrorMessage: Boolean,
onKeyPress: (KeyEvent) -> Boolean,
+ pressedKeys: List<ShortcutKey>,
) {
val interactionSource = remember { MutableInteractionSource() }
val isFocused by interactionSource.collectIsFocusedAsState()
@@ -157,22 +159,18 @@ fun SelectedKeyCombinationContainer(
Modifier.padding(all = 16.dp)
.sizeIn(minWidth = 332.dp, minHeight = 56.dp)
.border(width = 2.dp, color = outlineColor, shape = RoundedCornerShape(50.dp))
- .onPreviewKeyEvent { onKeyPress(it) },
+ .onKeyEvent { onKeyPress(it) },
interactionSource = interactionSource,
) {
Row(
modifier = Modifier.padding(start = 24.dp, top = 16.dp, end = 16.dp, bottom = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
- Text(
- text = keyCombination,
- style = MaterialTheme.typography.headlineSmall,
- fontSize = 16.sp,
- lineHeight = 24.sp,
- fontWeight = FontWeight.W500,
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- modifier = Modifier.width(252.dp),
- )
+ if (pressedKeys.isEmpty()) {
+ PressKeyPrompt()
+ } else {
+ PressedKeysTextContainer(pressedKeys)
+ }
Spacer(modifier = Modifier.weight(1f))
if (shouldShowErrorMessage) {
Icon(
@@ -187,6 +185,67 @@ fun SelectedKeyCombinationContainer(
}
@Composable
+private fun RowScope.PressedKeysTextContainer(pressedKeys: List<ShortcutKey>) {
+ pressedKeys.forEachIndexed { keyIndex, key ->
+ if (keyIndex > 0) {
+ ShortcutKeySeparator()
+ }
+ if (key is ShortcutKey.Text) {
+ ShortcutTextKey(key)
+ } else if (key is ShortcutKey.Icon) {
+ ShortcutIconKey(key)
+ }
+ }
+}
+
+@Composable
+private fun ShortcutKeySeparator() {
+ Text(
+ text = stringResource(id = R.string.shortcut_helper_plus_symbol),
+ style = MaterialTheme.typography.titleSmall,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+}
+
+@Composable
+private fun RowScope.ShortcutIconKey(key: ShortcutKey.Icon) {
+ Icon(
+ painter =
+ when (key) {
+ is ShortcutKey.Icon.ResIdIcon -> painterResource(key.drawableResId)
+ is ShortcutKey.Icon.DrawableIcon -> rememberDrawablePainter(drawable = key.drawable)
+ },
+ contentDescription = null,
+ modifier = Modifier.align(Alignment.CenterVertically).height(24.dp),
+ tint = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+}
+
+@Composable
+private fun PressKeyPrompt() {
+ Text(
+ text = stringResource(id = R.string.shortcut_helper_add_shortcut_dialog_placeholder),
+ style = MaterialTheme.typography.titleSmall,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+}
+
+@Composable
+private fun ShortcutTextKey(key: ShortcutKey.Text) {
+ Text(
+ text = key.value,
+ style = MaterialTheme.typography.titleSmall,
+ fontSize = 16.sp,
+ lineHeight = 24.sp,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+}
+
+@Composable
private fun Title(title: String, modifier: Modifier = Modifier) {
Text(
text = title,
@@ -203,8 +262,6 @@ private fun Description(modifier: Modifier = Modifier) {
Text(
text = stringResource(id = R.string.shortcut_helper_customize_mode_sub_title),
style = MaterialTheme.typography.bodyMedium,
- fontSize = 14.sp,
- lineHeight = 20.sp,
modifier = modifier.wrapContentSize(Alignment.Center),
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt
index e9f2a3b8e5b3..0080afb7160d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/model/ShortcutCustomizationUiState.kt
@@ -25,6 +25,7 @@ sealed interface ShortcutCustomizationUiState {
val isValidKeyCombination: Boolean,
val defaultCustomShortcutModifierKey: ShortcutKey.Icon.ResIdIcon,
val isDialogShowing: Boolean,
+ val pressedKeys: List<ShortcutKey> = emptyList(),
) : ShortcutCustomizationUiState
data object Inactive : ShortcutCustomizationUiState
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
index e86da5d25b22..9a46ae25cbcb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModel.kt
@@ -17,14 +17,22 @@
package com.android.systemui.keyboard.shortcut.ui.viewmodel
import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEvent
+import androidx.compose.ui.input.key.KeyEventType
+import androidx.compose.ui.input.key.isMetaPressed
+import androidx.compose.ui.input.key.key
+import androidx.compose.ui.input.key.nativeKeyCode
+import androidx.compose.ui.input.key.type
import com.android.systemui.keyboard.shortcut.domain.interactor.ShortcutCustomizationInteractor
+import com.android.systemui.keyboard.shortcut.shared.model.KeyCombination
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
class ShortcutCustomizationViewModel
@@ -35,7 +43,21 @@ constructor(private val shortcutCustomizationInteractor: ShortcutCustomizationIn
private val _shortcutCustomizationUiState =
MutableStateFlow<ShortcutCustomizationUiState>(ShortcutCustomizationUiState.Inactive)
- val shortcutCustomizationUiState = _shortcutCustomizationUiState.asStateFlow()
+ val shortcutCustomizationUiState =
+ shortcutCustomizationInteractor.pressedKeys
+ .map { keys ->
+ // Note that Action Key is excluded as it's already displayed on the UI
+ keys.filter {
+ it != shortcutCustomizationInteractor.getDefaultCustomShortcutModifierKey()
+ }
+ }
+ .combine(_shortcutCustomizationUiState) { keys, uiState ->
+ if (uiState is ShortcutCustomizationUiState.AddShortcutDialog) {
+ uiState.copy(pressedKeys = keys)
+ } else {
+ uiState
+ }
+ }
fun onShortcutCustomizationRequested(requestInfo: ShortcutCustomizationRequestInfo) {
when (requestInfo) {
@@ -48,6 +70,7 @@ constructor(private val shortcutCustomizationInteractor: ShortcutCustomizationIn
defaultCustomShortcutModifierKey =
shortcutCustomizationInteractor.getDefaultCustomShortcutModifierKey(),
isDialogShowing = false,
+ pressedKeys = emptyList(),
)
_shortcutBeingCustomized.value = requestInfo
}
@@ -62,18 +85,48 @@ constructor(private val shortcutCustomizationInteractor: ShortcutCustomizationIn
}
}
- fun onAddShortcutDialogDismissed() {
+ fun onDialogDismissed() {
_shortcutBeingCustomized.value = null
_shortcutCustomizationUiState.value = ShortcutCustomizationUiState.Inactive
+ shortcutCustomizationInteractor.updateUserSelectedKeyCombination(null)
}
fun onKeyPressed(keyEvent: KeyEvent): Boolean {
- // TODO Not yet implemented b/373638584
+ if ((keyEvent.isMetaPressed && keyEvent.type == KeyEventType.KeyDown)) {
+ updatePressedKeys(keyEvent)
+ return true
+ }
return false
}
+ private fun updatePressedKeys(keyEvent: KeyEvent) {
+ val isModifier = SUPPORTED_MODIFIERS.contains(keyEvent.key)
+ val keyCombination =
+ KeyCombination(
+ modifiers = keyEvent.nativeKeyEvent.modifiers,
+ keyCode = if (!isModifier) keyEvent.key.nativeKeyCode else null,
+ )
+ shortcutCustomizationInteractor.updateUserSelectedKeyCombination(keyCombination)
+ }
+
@AssistedFactory
interface Factory {
fun create(): ShortcutCustomizationViewModel
}
+
+ companion object {
+ private val SUPPORTED_MODIFIERS =
+ listOf(
+ Key.MetaLeft,
+ Key.MetaRight,
+ Key.CtrlRight,
+ Key.CtrlLeft,
+ Key.AltLeft,
+ Key.AltRight,
+ Key.ShiftLeft,
+ Key.ShiftRight,
+ Key.Function,
+ Key.Symbol,
+ )
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
index a9b6dd16cd95..ef2597f7f96c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/shortcut/ui/viewmodel/ShortcutCustomizationViewModelTest.kt
@@ -16,6 +16,15 @@
package com.android.systemui.keyboard.shortcut.ui.viewmodel
+import android.content.Context
+import android.content.Context.INPUT_SERVICE
+import android.hardware.input.fakeInputManager
+import android.os.SystemClock
+import android.view.KeyEvent.ACTION_DOWN
+import android.view.KeyEvent.KEYCODE_A
+import android.view.KeyEvent.META_CTRL_ON
+import android.view.KeyEvent.META_META_ON
+import androidx.compose.ui.input.key.KeyEvent
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -24,24 +33,43 @@ import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCategoryType
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutCustomizationRequestInfo
import com.android.systemui.keyboard.shortcut.shared.model.ShortcutKey
import com.android.systemui.keyboard.shortcut.shortcutCustomizationViewModelFactory
+import com.android.systemui.keyboard.shortcut.shortcutHelperTestHelper
import com.android.systemui.keyboard.shortcut.ui.model.ShortcutCustomizationUiState
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
+import com.android.systemui.settings.FakeUserTracker
+import com.android.systemui.settings.userTracker
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runTest
+import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
@SmallTest
@RunWith(AndroidJUnit4::class)
class ShortcutCustomizationViewModelTest : SysuiTestCase() {
- private val kosmos = Kosmos().also { it.testCase = this }
+ private val mockUserContext: Context = mock()
+ private val kosmos =
+ Kosmos().also {
+ it.testCase = this
+ it.userTracker = FakeUserTracker(onCreateCurrentUserContext = { mockUserContext })
+ }
private val testScope = kosmos.testScope
+ private val inputManager = kosmos.fakeInputManager.inputManager
+ private val helper = kosmos.shortcutHelperTestHelper
private val viewModel = kosmos.shortcutCustomizationViewModelFactory.create()
+ @Before
+ fun setup() {
+ helper.showFromActivity()
+ whenever(mockUserContext.getSystemService(INPUT_SERVICE)).thenReturn(inputManager)
+ }
+
@Test
fun uiState_inactiveByDefault() {
testScope.runTest {
@@ -79,11 +107,111 @@ class ShortcutCustomizationViewModelTest : SysuiTestCase() {
val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
viewModel.onAddShortcutDialogShown()
- viewModel.onAddShortcutDialogDismissed()
+ viewModel.onDialogDismissed()
assertThat(uiState).isEqualTo(ShortcutCustomizationUiState.Inactive)
}
}
+ @Test
+ fun uiState_pressedKeys_emptyByDefault() {
+ testScope.runTest {
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ assertThat((uiState as ShortcutCustomizationUiState.AddShortcutDialog).pressedKeys)
+ .isEmpty()
+ }
+ }
+
+ @Test
+ fun onKeyPressed_handlesKeyEvents_whereActionKeyIsAlsoPressed() {
+ testScope.runTest {
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ val isHandled = viewModel.onKeyPressed(keyDownEventWithActionKeyPressed)
+
+ assertThat(isHandled).isTrue()
+ }
+ }
+
+ @Test
+ fun onKeyPressed_doesNotHandleKeyEvents_whenActionKeyIsNotAlsoPressed() {
+ testScope.runTest {
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ val isHandled = viewModel.onKeyPressed(keyDownEventWithoutActionKeyPressed)
+
+ assertThat(isHandled).isFalse()
+ }
+ }
+
+ @Test
+ fun onKeyPressed_convertsKeyEventsAndUpdatesUiStatesPressedKey() {
+ testScope.runTest {
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ viewModel.onKeyPressed(keyDownEventWithActionKeyPressed)
+ viewModel.onKeyPressed(keyUpEventWithActionKeyPressed)
+
+ // Note that Action Key is excluded as it's already displayed on the UI
+ assertThat((uiState as ShortcutCustomizationUiState.AddShortcutDialog).pressedKeys)
+ .containsExactly(ShortcutKey.Text("Ctrl"), ShortcutKey.Text("A"))
+ }
+ }
+
+ @Test
+ fun uiState_pressedKeys_resetsToEmptyListAfterDialogIsDismissedAndReopened() {
+ testScope.runTest {
+ val uiState by collectLastValue(viewModel.shortcutCustomizationUiState)
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ viewModel.onKeyPressed(keyDownEventWithActionKeyPressed)
+ viewModel.onKeyPressed(keyUpEventWithActionKeyPressed)
+
+ // Note that Action Key is excluded as it's already displayed on the UI
+ assertThat((uiState as ShortcutCustomizationUiState.AddShortcutDialog).pressedKeys)
+ .containsExactly(ShortcutKey.Text("Ctrl"), ShortcutKey.Text("A"))
+
+ // Close the dialog and show it again
+ viewModel.onDialogDismissed()
+ viewModel.onShortcutCustomizationRequested(standardAddShortcutRequest)
+ assertThat((uiState as ShortcutCustomizationUiState.AddShortcutDialog).pressedKeys)
+ .isEmpty()
+ }
+ }
+
+ private val keyDownEventWithoutActionKeyPressed =
+ KeyEvent(
+ android.view.KeyEvent(
+ /* downTime = */ SystemClock.uptimeMillis(),
+ /* eventTime = */ SystemClock.uptimeMillis(),
+ /* action = */ ACTION_DOWN,
+ /* code = */ KEYCODE_A,
+ /* repeat = */ 0,
+ /* metaState = */ META_CTRL_ON,
+ )
+ )
+
+ private val keyDownEventWithActionKeyPressed =
+ KeyEvent(
+ android.view.KeyEvent(
+ /* downTime = */ SystemClock.uptimeMillis(),
+ /* eventTime = */ SystemClock.uptimeMillis(),
+ /* action = */ ACTION_DOWN,
+ /* code = */ KEYCODE_A,
+ /* repeat = */ 0,
+ /* metaState = */ META_CTRL_ON or META_META_ON,
+ )
+ )
+
+ private val keyUpEventWithActionKeyPressed =
+ KeyEvent(
+ android.view.KeyEvent(
+ /* downTime = */ SystemClock.uptimeMillis(),
+ /* eventTime = */ SystemClock.uptimeMillis(),
+ /* action = */ ACTION_DOWN,
+ /* code = */ KEYCODE_A,
+ /* repeat = */ 0,
+ /* metaState = */ 0,
+ )
+ )
+
private val standardAddShortcutRequest =
ShortcutCustomizationRequestInfo.Add(
label = "Standard shortcut",