diff --git a/AnkiDroid/src/androidTest/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt b/AnkiDroid/src/androidTest/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt deleted file mode 100644 index c148563b8f8b..000000000000 --- a/AnkiDroid/src/androidTest/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2020 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.reviewer - -import android.view.KeyEvent -import androidx.test.ext.junit.runners.AndroidJUnit4 -import com.ichi2.anki.cardviewer.Gesture -import com.ichi2.anki.cardviewer.ViewerCommand -import com.ichi2.anki.tests.InstrumentedTest -import com.ichi2.anki.testutil.MockReviewerUi -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.hasSize -import org.junit.Test -import org.junit.runner.RunWith - -@RunWith(AndroidJUnit4::class) -class PeripheralKeymapTest : InstrumentedTest() { - @Test - fun testNumpadAction() { - // #7736 Ensures that a numpad key is passed through (mostly testing num lock) - val processed: MutableList = ArrayList() - - val peripheralKeymap = - PeripheralKeymap(MockReviewerUi.displayingAnswer()) { e: ViewerCommand, _: Gesture? -> processed.add(e) } - peripheralKeymap.setup() - - peripheralKeymap.onKeyDown( - KeyEvent.KEYCODE_NUMPAD_1, - getNumpadEvent(KeyEvent.KEYCODE_NUMPAD_1), - ) - peripheralKeymap.onKeyUp( - KeyEvent.KEYCODE_NUMPAD_1, - getNumpadEvent(KeyEvent.KEYCODE_NUMPAD_1), - ) - assertThat>(processed, hasSize(1)) - assertThat( - processed[0], - equalTo(ViewerCommand.FLIP_OR_ANSWER_EASE1), - ) - } - - private fun getNumpadEvent(keycode: Int): KeyEvent = KeyEvent(0, 0, KeyEvent.ACTION_UP, keycode, 0, KeyEvent.META_NUM_LOCK_ON) -} diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/UsageAnalytics.kt b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/UsageAnalytics.kt index 8c90f87da734..25d85a6006ed 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/analytics/UsageAnalytics.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/analytics/UsageAnalytics.kt @@ -567,6 +567,21 @@ object UsageAnalytics { "binding_USER_ACTION_7", "binding_USER_ACTION_8", "binding_USER_ACTION_9", + // ******************************** Controls - Previewer ******************************* + "previewer_NEXT", + "previewer_BACK", + "previewer_MARK", + "previewer_EDIT", + "previewer_REPLAY_AUDIO", + "previewer_BACKSIDE_ONLY", + "previewer_TOGGLE_FLAG_RED", + "previewer_TOGGLE_FLAG_ORANGE", + "previewer_TOGGLE_FLAG_GREEN", + "previewer_TOGGLE_FLAG_BLUE", + "previewer_TOGGLE_FLAG_PINK", + "previewer_TOGGLE_FLAG_TURQUOISE", + "previewer_TOGGLE_FLAG_PURPLE", + "previewer_UNSET_FLAG", // ******************************** Accessibility ****************************************** "cardZoom", "imageZoom", diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/PeripheralKeymap.kt b/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/PeripheralKeymap.kt deleted file mode 100644 index f3564a98bc2b..000000000000 --- a/AnkiDroid/src/main/java/com/ichi2/anki/reviewer/PeripheralKeymap.kt +++ /dev/null @@ -1,108 +0,0 @@ -/* - Copyright (c) 2020 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.reviewer - -import android.content.SharedPreferences -import android.view.KeyEvent -import com.ichi2.anki.AnkiDroidApp -import com.ichi2.anki.cardviewer.ViewerCommand -import com.ichi2.anki.preferences.sharedPrefs -import com.ichi2.anki.reviewer.Binding.Companion.possibleKeyBindings -import com.ichi2.anki.reviewer.CardSide.Companion.fromAnswer - -/** Accepts peripheral input, mapping via various keybinding strategies, - * and converting them to commands for the Reviewer. */ -class PeripheralKeymap( - reviewerUi: ReviewerUi, - commandProcessor: ViewerCommand.CommandProcessor, -) { - private val keyMap: KeyMap = KeyMap(commandProcessor, reviewerUi) - private var hasSetup = false - - fun setup() { - val preferences = AnkiDroidApp.instance.sharedPrefs() - setup(preferences) - } - - fun setup(preferences: SharedPreferences) { - for (command in ViewerCommand.entries) { - add(command, preferences) - } - hasSetup = true - } - - private fun add( - command: ViewerCommand, - preferences: SharedPreferences, - ) { - val bindings = command.getBindings(preferences) - for (b in bindings) { - if (!b.isKey) { - continue - } - keyMap[b] = command - } - } - - fun onKeyDown( - keyCode: Int, - event: KeyEvent, - ): Boolean = - if (!hasSetup || event.repeatCount > 0) { - false - } else { - keyMap.onKeyDown(keyCode, event) - } - - @Suppress("UNUSED_PARAMETER") - fun onKeyUp( - keyCode: Int, - event: KeyEvent?, - ): Boolean = false - - class KeyMap( - private val processor: ViewerCommand.CommandProcessor, - private val reviewerUI: ReviewerUi, - ) { - val bindingMap = HashMap() - - @Suppress("UNUSED_PARAMETER") - fun onKeyDown( - keyCode: Int, - event: KeyEvent?, - ): Boolean { - var ret = false - val bindings = possibleKeyBindings(event!!) - val side = fromAnswer(reviewerUI.isDisplayingAnswer) - for (b in bindings) { - val binding = ReviewerBinding(b, side) - val command = bindingMap[binding] ?: continue - ret = ret or processor.executeCommand(command, fromGesture = null) - } - return ret - } - - operator fun set( - key: MappableBinding, - value: ViewerCommand, - ) { - bindingMap[key] = value - } - - operator fun get(key: MappableBinding): ViewerCommand? = bindingMap[key] - } -} diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/analytics/PreferencesAnalyticsTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/analytics/PreferencesAnalyticsTest.kt index 3154cd924731..d90438335dbf 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/analytics/PreferencesAnalyticsTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/analytics/PreferencesAnalyticsTest.kt @@ -75,6 +75,8 @@ class PreferencesAnalyticsTest : RobolectricTest() { "widgetVibrate", // Blink light "widgetBlink", + // Special views + "controlsTabLayout", // potential personal data "syncAccount", "syncBaseUrl", diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferenceTestUtils.kt b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferenceTestUtils.kt index 9a8766d989e3..64d1e3b121bb 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferenceTestUtils.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferenceTestUtils.kt @@ -113,11 +113,19 @@ object PreferenceTestUtils { @XmlRes xml: Int, ): List = getAttrFromXml(context, xml, "key").map { attrValueToString(it, context) } - fun getAllPreferenceKeys(context: Context): Set = - getAllPreferencesFragments(context) - .filterIsInstance() - .map { it.preferenceResource } - .flatMapTo(hashSetOf()) { getKeysFromXml(context, it) } + fun getAllPreferenceKeys(context: Context): Set { + val controlPreferencesKeys = + ControlPreferenceScreen.entries.flatMap { + getKeysFromXml(context, it.xmlRes) + } + val staticPreferencesKeys = + getAllPreferencesFragments(context) + .filterIsInstance() + .map { it.preferenceResource } + .flatMapTo(hashSetOf()) { getKeysFromXml(context, it) } + + return staticPreferencesKeys + controlPreferencesKeys + } fun getAllCustomButtonKeys(context: Context): Set { val keys = getKeysFromXml(context, R.xml.preferences_custom_buttons).toMutableSet() diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt deleted file mode 100644 index 8e610325b37e..000000000000 --- a/AnkiDroid/src/test/java/com/ichi2/anki/reviewer/PeripheralKeymapTest.kt +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2020 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.reviewer - -import android.view.KeyEvent -import com.github.ivanshafran.sharedpreferencesmock.SPMockBuilder -import com.ichi2.anki.cardviewer.ViewerCommand -import org.hamcrest.MatcherAssert.assertThat -import org.hamcrest.Matchers.equalTo -import org.hamcrest.Matchers.hasSize -import org.junit.Test -import org.mockito.Mockito.mock -import org.mockito.kotlin.whenever - -class PeripheralKeymapTest { - @Test - fun flagAndAnswerDoNotConflict() { - val processed: MutableList = ArrayList() - - val peripheralKeymap = PeripheralKeymap(MockReviewerUi()) { e: ViewerCommand, _ -> processed.add(e) } - peripheralKeymap.setup(SPMockBuilder().createSharedPreferences()) - val event = mock(KeyEvent::class.java) - whenever(event.unicodeChar).thenReturn(0) - whenever(event.isCtrlPressed).thenReturn(true) - whenever(event.getUnicodeChar(0)).thenReturn(49) - whenever(event.keyCode).thenReturn(KeyEvent.KEYCODE_1) - - assertThat(event.unicodeChar.toChar(), equalTo('\u0000')) - assertThat(event.getUnicodeChar(0).toChar(), equalTo('1')) - peripheralKeymap.onKeyDown(KeyEvent.KEYCODE_1, event) - - assertThat>(processed, hasSize(1)) - assertThat(processed[0], equalTo(ViewerCommand.TOGGLE_FLAG_RED)) - } - - private class MockReviewerUi : ReviewerUi { - override val isDisplayingAnswer: Boolean - get() = false - } -}