diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt index 1d777302b2db..60bac9b2f499 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt @@ -52,6 +52,7 @@ import com.ichi2.anim.ActivityTransitionAnimation.Direction import com.ichi2.anim.ActivityTransitionAnimation.Direction.DEFAULT import com.ichi2.anim.ActivityTransitionAnimation.Direction.NONE import com.ichi2.anki.analytics.UsageAnalytics +import com.ichi2.anki.android.input.Shortcut import com.ichi2.anki.android.input.ShortcutGroup import com.ichi2.anki.android.input.ShortcutGroupProvider import com.ichi2.anki.android.input.shortcut @@ -690,8 +691,10 @@ open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener, Shortc val done = super.onKeyUp(keyCode, event) - // Show snackbar only if the current activity have shortcuts, a modifier key is pressed and the keyCode is an unmapped alphabet key - if (!done && shortcuts != null && (event.isCtrlPressed || event.isAltPressed || event.isMetaPressed) && (keyCode in KeyEvent.KEYCODE_A..KeyEvent.KEYCODE_Z) || (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_9)) { + if (done || shortcuts == null) return false + + // Show snackbar only if the current activity have shortcuts, a modifier key is pressed and the keyCode is an unmapped alphabet or num key + if (Shortcut.isPotentialShortcutCombination(event, keyCode)) { showSnackbar(R.string.show_shortcuts_message, Snackbar.LENGTH_SHORT) return true } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/android/input/Shortcut.kt b/AnkiDroid/src/main/java/com/ichi2/anki/android/input/Shortcut.kt index b31254a1df19..7148fe9227e1 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/android/input/Shortcut.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/android/input/Shortcut.kt @@ -19,6 +19,7 @@ package com.ichi2.anki.android.input import android.view.KeyEvent import android.view.KeyboardShortcutInfo +import androidx.annotation.CheckResult import androidx.annotation.StringRes import com.ichi2.anki.AnkiActivityProvider import com.ichi2.anki.CollectionManager.TR @@ -76,6 +77,12 @@ data class Shortcut(val shortcut: String, val label: String) { else -> KeyEvent.keyCodeFromString(key) } } + + companion object { + @CheckResult + fun isPotentialShortcutCombination(event: KeyEvent, keyCode: Int): Boolean = + (event.isCtrlPressed || event.isAltPressed || event.isMetaPressed) && ((keyCode in KeyEvent.KEYCODE_A..KeyEvent.KEYCODE_Z) || (keyCode in KeyEvent.KEYCODE_NUMPAD_0..KeyEvent.KEYCODE_NUMPAD_9)) + } } /** diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ShortcutTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ShortcutTest.kt new file mode 100644 index 000000000000..0725470e5344 --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ShortcutTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 David Allison + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation; either version 3 of the License, or (at your option) any later + * version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +package com.ichi2.anki + +import android.view.KeyEvent +import com.ichi2.anki.android.input.Shortcut +import org.mockito.kotlin.mock +import kotlin.test.Test +import kotlin.test.assertFalse + +class ShortcutTest { + val keyEventWithNoModifiers: KeyEvent = mock { } + + @Test + fun `single number is not a shortcut hint`() { + assertFalse( + Shortcut.isPotentialShortcutCombination(keyEventWithNoModifiers, KeyEvent.KEYCODE_NUMPAD_1) + ) + } +}