Skip to content

Commit

Permalink
refactor: extract 'anki.android.input' from compat
Browse files Browse the repository at this point in the history
After the minSdk 24 bump, these classes no longer belong
in compat

Note: these changes were not performed in the minSdk 24 bump
as they dominated the diff
  • Loading branch information
mikehardy committed Nov 11, 2024
1 parent 58e6a9d commit eb9dd97
Show file tree
Hide file tree
Showing 12 changed files with 169 additions and 137 deletions.
9 changes: 4 additions & 5 deletions AnkiDroid/src/main/java/com/ichi2/anki/AnkiActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ 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.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.anki.android.input.shortcut
import com.ichi2.anki.dialogs.AsyncDialogFragment
import com.ichi2.anki.dialogs.DialogHandler
import com.ichi2.anki.dialogs.SimpleMessageDialog
Expand All @@ -64,13 +67,9 @@ import com.ichi2.anki.snackbar.showSnackbar
import com.ichi2.anki.workarounds.AppLoadedFromBackupWorkaround.showedActivityFailedScreen
import com.ichi2.async.CollectionLoader
import com.ichi2.compat.CompatHelper.Companion.registerReceiverCompat
import com.ichi2.compat.CompatV24
import com.ichi2.compat.CompatV24.ShortcutGroup
import com.ichi2.compat.ShortcutGroupProvider
import com.ichi2.compat.customtabs.CustomTabActivityHelper
import com.ichi2.compat.customtabs.CustomTabsFallback
import com.ichi2.compat.customtabs.CustomTabsHelper
import com.ichi2.compat.shortcut
import com.ichi2.libanki.Collection
import com.ichi2.themes.Themes
import com.ichi2.utils.AdaptionUtil
Expand Down Expand Up @@ -704,7 +703,7 @@ open class AnkiActivity : AppCompatActivity, SimpleMessageDialogListener, Shortc
}

override val shortcuts
get(): CompatV24.ShortcutGroup? = null
get(): ShortcutGroup? = null

companion object {
const val DIALOG_FRAGMENT_TAG = "dialog"
Expand Down
4 changes: 2 additions & 2 deletions AnkiDroid/src/main/java/com/ichi2/anki/AnkiFragment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import androidx.annotation.StringRes
import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.async.CollectionLoader
import com.ichi2.compat.CompatV24
import com.ichi2.libanki.Collection
import com.ichi2.themes.Themes
import com.ichi2.utils.increaseHorizontalPaddingOfOverflowMenuIcons
Expand Down Expand Up @@ -226,5 +226,5 @@ open class AnkiFragment(@LayoutRes layout: Int) : Fragment(layout), AnkiActivity
/**
* Lists of shortcuts for this fragment, and the IdRes of the name of this shortcut group.
*/
open val shortcuts: CompatV24.ShortcutGroup? = null
open val shortcuts: ShortcutGroup? = null
}
6 changes: 3 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/CardBrowser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ import com.google.android.material.snackbar.Snackbar
import com.ichi2.anim.ActivityTransitionAnimation.Direction
import com.ichi2.anki.CollectionManager.TR
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.shortcut
import com.ichi2.anki.browser.CardBrowserColumn
import com.ichi2.anki.browser.CardBrowserColumn.Companion.COLUMN1_KEYS
import com.ichi2.anki.browser.CardBrowserColumn.Companion.COLUMN2_KEYS
Expand Down Expand Up @@ -112,8 +114,6 @@ import com.ichi2.anki.utils.roundedTimeSpanUnformatted
import com.ichi2.anki.widgets.DeckDropDownAdapter.SubtitleListener
import com.ichi2.annotations.NeedsTest
import com.ichi2.async.renderBrowserQA
import com.ichi2.compat.CompatV24
import com.ichi2.compat.shortcut
import com.ichi2.libanki.Card
import com.ichi2.libanki.CardId
import com.ichi2.libanki.ChangeManager
Expand Down Expand Up @@ -2372,7 +2372,7 @@ open class CardBrowser :
}

override val shortcuts
get() = CompatV24.ShortcutGroup(
get() = ShortcutGroup(
listOf(
shortcut("Ctrl+Shift+A", R.string.edit_tags_dialog),
shortcut("Ctrl+A", R.string.card_browser_select_all),
Expand Down
6 changes: 3 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/CardTemplateEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.shortcut
import com.ichi2.anki.dialogs.ConfirmationDialog
import com.ichi2.anki.dialogs.DeckSelectionDialog
import com.ichi2.anki.dialogs.DeckSelectionDialog.DeckSelectionListener
Expand All @@ -71,8 +73,6 @@ import com.ichi2.anki.utils.ext.isImageOcclusion
import com.ichi2.anki.utils.postDelayed
import com.ichi2.annotations.NeedsTest
import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat
import com.ichi2.compat.CompatV24
import com.ichi2.compat.shortcut
import com.ichi2.libanki.Collection
import com.ichi2.libanki.Note
import com.ichi2.libanki.NoteId
Expand Down Expand Up @@ -431,7 +431,7 @@ open class CardTemplateEditor : AnkiActivity(), DeckSelectionListener {
}

override val shortcuts
get() = CompatV24.ShortcutGroup(
get() = ShortcutGroup(
listOf(
shortcut("Ctrl+P", R.string.card_editor_preview_card),
shortcut("Ctrl+1", R.string.edit_front_template),
Expand Down
6 changes: 3 additions & 3 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ import com.ichi2.anki.InitialActivity.StartupFailure.WEBVIEW_FAILED
import com.ichi2.anki.IntentHandler.Companion.intentToReviewDeckFromShorcuts
import com.ichi2.anki.StudyOptionsFragment.StudyOptionsListener
import com.ichi2.anki.analytics.UsageAnalytics
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.shortcut
import com.ichi2.anki.deckpicker.BITMAP_BYTES_PER_PIXEL
import com.ichi2.anki.deckpicker.BackgroundImage
import com.ichi2.anki.dialogs.AsyncDialogFragment
Expand Down Expand Up @@ -155,8 +157,6 @@ import com.ichi2.annotations.NeedsTest
import com.ichi2.async.deleteMedia
import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat
import com.ichi2.compat.CompatHelper.Companion.sdkVersion
import com.ichi2.compat.CompatV24
import com.ichi2.compat.shortcut
import com.ichi2.libanki.ChangeManager
import com.ichi2.libanki.Consts
import com.ichi2.libanki.DeckId
Expand Down Expand Up @@ -2420,7 +2420,7 @@ open class DeckPicker :
}

override val shortcuts
get() = CompatV24.ShortcutGroup(
get() = ShortcutGroup(
listOf(
shortcut("A", R.string.menu_add_note),
shortcut("B", R.string.card_browser_context_menu),
Expand Down
8 changes: 4 additions & 4 deletions AnkiDroid/src/main/java/com/ichi2/anki/NoteEditor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ import com.ichi2.anim.ActivityTransitionAnimation
import com.ichi2.anki.CollectionManager.TR
import com.ichi2.anki.CollectionManager.withCol
import com.ichi2.anki.OnContextAndLongClickListener.Companion.setOnContextAndLongClickListener
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.anki.android.input.shortcut
import com.ichi2.anki.bottomsheet.ImageOcclusionBottomSheetFragment
import com.ichi2.anki.dialogs.ConfirmationDialog
import com.ichi2.anki.dialogs.DeckSelectionDialog.DeckSelectionListener
Expand Down Expand Up @@ -130,10 +133,7 @@ import com.ichi2.anki.utils.ext.sharedPrefs
import com.ichi2.anki.widgets.DeckDropDownAdapter.SubtitleListener
import com.ichi2.annotations.NeedsTest
import com.ichi2.compat.CompatHelper.Companion.getSerializableCompat
import com.ichi2.compat.CompatV24
import com.ichi2.compat.ShortcutGroupProvider
import com.ichi2.compat.setTooltipTextCompat
import com.ichi2.compat.shortcut
import com.ichi2.imagecropper.ImageCropper
import com.ichi2.imagecropper.ImageCropper.Companion.CROP_IMAGE_RESULT
import com.ichi2.imagecropper.ImageCropperLauncher
Expand Down Expand Up @@ -2352,7 +2352,7 @@ class NoteEditor : AnkiFragment(R.layout.note_editor), DeckSelectionListener, Su
}

override val shortcuts
get() = CompatV24.ShortcutGroup(
get() = ShortcutGroup(
listOf(
shortcut("Ctrl+ENTER", R.string.save),
shortcut("Ctrl+D", R.string.select_deck),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import android.view.KeyEvent
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.fragment.app.commit
import com.ichi2.compat.CompatV24
import com.ichi2.compat.ShortcutGroupProvider
import com.ichi2.anki.android.input.ShortcutGroup
import com.ichi2.anki.android.input.ShortcutGroupProvider
import com.ichi2.utils.getInstanceFromClassName
import timber.log.Timber
import kotlin.reflect.KClass
Expand Down Expand Up @@ -99,7 +99,7 @@ open class SingleFragmentActivity : AnkiActivity() {
}
}

override val shortcuts: CompatV24.ShortcutGroup?
override val shortcuts: ShortcutGroup?
get() = (fragment as? ShortcutGroupProvider)?.shortcuts
}

Expand Down
91 changes: 91 additions & 0 deletions AnkiDroid/src/main/java/com/ichi2/anki/android/input/Shortcut.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright (c) 2024 Sanjay Sargam <[email protected]>
* Copyright (c) 2024 David Allison <[email protected]>
*
* 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 <http://www.gnu.org/licenses/>.
*/

package com.ichi2.anki.android.input

import android.view.KeyEvent
import android.view.KeyboardShortcutInfo
import androidx.annotation.StringRes
import com.ichi2.anki.AnkiActivityProvider
import com.ichi2.anki.CollectionManager.TR
import net.ankiweb.rsdroid.Translations

/**
* Data class representing a keyboard shortcut.
*
* @param shortcut The string representation of the keyboard shortcut (e.g., "Ctrl+Alt+S").
* @param label The string resource for the shortcut label.
*/
data class Shortcut(val shortcut: String, val label: String) {

/**
* Converts the shortcut string into a KeyboardShortcutInfo object.
*
* @return A KeyboardShortcutInfo object representing the keyboard shortcut.
*/
fun toShortcutInfo(): KeyboardShortcutInfo {
val parts = shortcut.split("+")
val key = parts.last()
val keycode: Int = getKey(key)
val modifierFlags: Int = parts.dropLast(1).sumOf { getModifier(it) }

return KeyboardShortcutInfo(label, keycode, modifierFlags)
}

/**
* Maps a modifier string to its corresponding KeyEvent meta flag.
*
* @param modifier The modifier string (e.g., "Ctrl", "Alt", "Shift").
* @return The corresponding KeyEvent meta flag.
*/
private fun getModifier(modifier: String): Int {
return when (modifier) {
"Ctrl" -> KeyEvent.META_CTRL_ON
"Alt" -> KeyEvent.META_ALT_ON
"Shift" -> KeyEvent.META_SHIFT_ON

else -> 0
}
}

/**
* Maps a key string to its corresponding keycode.
*
* @param key The key string.
* @return The corresponding keycode, or 0 if the key string is invalid or not recognized.
*/
private fun getKey(key: String): Int {
return when (key) {
"/" -> KeyEvent.KEYCODE_SLASH
"Esc" -> KeyEvent.KEYCODE_ESCAPE
in "0".."9" -> KeyEvent.KEYCODE_0 + (key.toInt() - 0) // Handle number keys
else -> KeyEvent.keyCodeFromString(key)
}
}
}

/**
* Provides a [Shortcut], from the shortcut keys and the resource id of its description.
*/
fun AnkiActivityProvider.shortcut(shortcut: String, @StringRes labelRes: Int) =
Shortcut(shortcut, ankiActivity.getString(labelRes))

/**
* Provides a [Shortcut], from the shortcut keys and the function from anki strings.
*/
fun shortcut(shortcut: String, getTranslation: Translations.() -> String) =
Shortcut(shortcut, getTranslation(TR))
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2024 Sanjay Sargam <[email protected]>
* Copyright (c) 2024 David Allison <[email protected]>
*
* 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 <http://www.gnu.org/licenses/>.
*/

package com.ichi2.anki.android.input

import android.view.KeyboardShortcutGroup
import androidx.annotation.StringRes
import com.ichi2.anki.AnkiActivity

data class ShortcutGroup(val shortcuts: List<Shortcut>, @StringRes val id: Int) {
fun toShortcutGroup(activity: AnkiActivity): KeyboardShortcutGroup {
val shortcuts = shortcuts.map { it.toShortcutInfo() }
val groupLabel = activity.getString(id)
return KeyboardShortcutGroup(groupLabel, shortcuts)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2024 Sanjay Sargam <[email protected]>
* Copyright (c) 2024 David Allison <[email protected]>
*
* 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 <http://www.gnu.org/licenses/>.
*/

package com.ichi2.anki.android.input

interface ShortcutGroupProvider {
/**
* Lists of shortcuts for this fragment, and the IdRes of the name of this shortcut group.
*/
val shortcuts: ShortcutGroup?
}
3 changes: 1 addition & 2 deletions AnkiDroid/src/main/java/com/ichi2/compat/BaseCompat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -258,5 +258,4 @@ open class BaseCompat : Compat {
override val AXIS_GESTURE_PINCH_SCALE_FACTOR: Int = 52
}

// typically we want a typealias here. Unusually we keep CompatV24 around for a refactor
// so this does not yet exist
typealias CompatV24 = BaseCompat
Loading

0 comments on commit eb9dd97

Please sign in to comment.