From feaf4b95cd613d17c96cb1cd4171c005dda120ae Mon Sep 17 00:00:00 2001 From: SanjaySargam Date: Mon, 25 Nov 2024 21:58:35 +0530 Subject: [PATCH] fix: correct logical grouping in shortcut condtion Grouped the numeric key check with the modifier key check to ensure the condition is true only when both a modifier key and a numeric key are pressed --- .../main/java/com/ichi2/anki/AnkiActivity.kt | 7 +++- .../com/ichi2/anki/android/input/Shortcut.kt | 7 ++++ .../test/java/com/ichi2/anki/ShortcutTest.kt | 41 +++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/ShortcutTest.kt 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..f952d0b9ecae --- /dev/null +++ b/AnkiDroid/src/test/java/com/ichi2/anki/ShortcutTest.kt @@ -0,0 +1,41 @@ +/* + * 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 androidx.test.ext.junit.runners.AndroidJUnit4 +import com.ichi2.anki.android.input.Shortcut +import com.ichi2.testutils.JvmTest +import org.junit.runner.RunWith +import org.mockito.kotlin.mock +import kotlin.test.Test +import kotlin.test.assertFalse + +// TODO: This shouldn't need a JvmTest, but it caused CI to fail with an OutOfMemoryError +// CreateDeckDialogTest > searchDecksIconVisibilityDeckCreationTest FAILED +// java.lang.OutOfMemoryError: Java heap space +@RunWith(AndroidJUnit4::class) +class ShortcutTest : JvmTest() { + val keyEventWithNoModifiers: KeyEvent = mock { } + + @Test + fun `single number is not a shortcut hint`() { + assertFalse( + Shortcut.isPotentialShortcutCombination(keyEventWithNoModifiers, KeyEvent.KEYCODE_NUMPAD_1) + ) + } +}