Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: improve ControlPreference Style #17927

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 55 additions & 71 deletions AnkiDroid/src/main/java/com/ichi2/anki/cardviewer/ViewerCommand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package com.ichi2.anki.cardviewer
import android.content.SharedPreferences
import android.view.KeyEvent
import androidx.core.content.edit
import com.ichi2.anki.R
import com.ichi2.anki.reviewer.Binding.Companion.keyCode
import com.ichi2.anki.reviewer.Binding.Companion.unicode
import com.ichi2.anki.reviewer.Binding.ModifierKeys
Expand All @@ -28,63 +27,59 @@ import com.ichi2.anki.reviewer.CardSide
import com.ichi2.anki.reviewer.MappableBinding
import com.ichi2.anki.reviewer.MappableBinding.Companion.fromPreference
import com.ichi2.anki.reviewer.MappableBinding.Companion.toPreferenceString
import com.ichi2.anki.reviewer.MappableBinding.Screen
import com.ichi2.anki.reviewer.ReviewerBinding

/** Abstraction: Discuss moving many of these to 'Reviewer' */
enum class ViewerCommand(
val resourceId: Int,
) {
SHOW_ANSWER(R.string.show_answer),
FLIP_OR_ANSWER_EASE1(R.string.answer_again),
FLIP_OR_ANSWER_EASE2(R.string.answer_hard),
FLIP_OR_ANSWER_EASE3(R.string.answer_good),
FLIP_OR_ANSWER_EASE4(R.string.answer_easy),
UNDO(R.string.undo),
REDO(R.string.redo),
EDIT(R.string.cardeditor_title_edit_card),
MARK(R.string.menu_mark_note),
BURY_CARD(R.string.menu_bury_card),
SUSPEND_CARD(R.string.menu_suspend_card),
DELETE(R.string.menu_delete_note),
PLAY_MEDIA(R.string.gesture_play),
EXIT(R.string.gesture_abort_learning),
BURY_NOTE(R.string.menu_bury_note),
SUSPEND_NOTE(R.string.menu_suspend_note),
TOGGLE_FLAG_RED(R.string.gesture_flag_red),
TOGGLE_FLAG_ORANGE(R.string.gesture_flag_orange),
TOGGLE_FLAG_GREEN(R.string.gesture_flag_green),
TOGGLE_FLAG_BLUE(R.string.gesture_flag_blue),
TOGGLE_FLAG_PINK(R.string.gesture_flag_pink),
TOGGLE_FLAG_TURQUOISE(R.string.gesture_flag_turquoise),
TOGGLE_FLAG_PURPLE(R.string.gesture_flag_purple),
UNSET_FLAG(R.string.gesture_flag_remove),
PAGE_UP(R.string.gesture_page_up),
PAGE_DOWN(R.string.gesture_page_down),
TAG(R.string.add_tag),
CARD_INFO(R.string.card_info_title),
ABORT_AND_SYNC(R.string.gesture_abort_sync),
RECORD_VOICE(R.string.record_voice),
SAVE_VOICE(R.string.save_voice),
REPLAY_VOICE(R.string.replay_voice),
TOGGLE_WHITEBOARD(R.string.gesture_toggle_whiteboard),
CLEAR_WHITEBOARD(R.string.clear_whiteboard),
CHANGE_WHITEBOARD_PEN_COLOR(R.string.title_whiteboard_editor),
SHOW_HINT(R.string.gesture_show_hint),
SHOW_ALL_HINTS(R.string.gesture_show_all_hints),
ADD_NOTE(R.string.menu_add_note),

// TODO: CollectionManager.TR.actionsSetDueDate()
RESCHEDULE_NOTE(R.string.card_editor_reschedule_card),
TOGGLE_AUTO_ADVANCE(R.string.toggle_auto_advance),
USER_ACTION_1(R.string.user_action_1),
USER_ACTION_2(R.string.user_action_2),
USER_ACTION_3(R.string.user_action_3),
USER_ACTION_4(R.string.user_action_4),
USER_ACTION_5(R.string.user_action_5),
USER_ACTION_6(R.string.user_action_6),
USER_ACTION_7(R.string.user_action_7),
USER_ACTION_8(R.string.user_action_8),
USER_ACTION_9(R.string.user_action_9),
enum class ViewerCommand {
SHOW_ANSWER,
FLIP_OR_ANSWER_EASE1,
FLIP_OR_ANSWER_EASE2,
FLIP_OR_ANSWER_EASE3,
FLIP_OR_ANSWER_EASE4,
UNDO,
REDO,
EDIT,
MARK,
BURY_CARD,
SUSPEND_CARD,
DELETE,
PLAY_MEDIA,
EXIT,
BURY_NOTE,
SUSPEND_NOTE,
TOGGLE_FLAG_RED,
TOGGLE_FLAG_ORANGE,
TOGGLE_FLAG_GREEN,
TOGGLE_FLAG_BLUE,
TOGGLE_FLAG_PINK,
TOGGLE_FLAG_TURQUOISE,
TOGGLE_FLAG_PURPLE,
UNSET_FLAG,
PAGE_UP,
PAGE_DOWN,
TAG,
CARD_INFO,
ABORT_AND_SYNC,
RECORD_VOICE,
SAVE_VOICE,
REPLAY_VOICE,
TOGGLE_WHITEBOARD,
CLEAR_WHITEBOARD,
CHANGE_WHITEBOARD_PEN_COLOR,
SHOW_HINT,
SHOW_ALL_HINTS,
ADD_NOTE,
RESCHEDULE_NOTE,
TOGGLE_AUTO_ADVANCE,
USER_ACTION_1,
USER_ACTION_2,
USER_ACTION_3,
USER_ACTION_4,
USER_ACTION_5,
USER_ACTION_6,
USER_ACTION_7,
USER_ACTION_8,
USER_ACTION_9,
;

companion object {
Expand Down Expand Up @@ -137,17 +132,6 @@ enum class ViewerCommand(
// If we use the serialised format, then this adds additional coupling to the properties.
val defaultValue: List<MappableBinding>
get() {
// all of the default commands are currently for the Reviewer
fun keyCode(
keycode: Int,
side: CardSide,
modifierKeys: ModifierKeys = ModifierKeys.none(),
) = keyCode(keycode, Screen.Reviewer(side), modifierKeys)

fun unicode(
c: Char,
side: CardSide,
) = unicode(c, Screen.Reviewer(side))
return when (this) {
FLIP_OR_ANSWER_EASE1 ->
listOf(
Expand Down Expand Up @@ -256,14 +240,14 @@ enum class ViewerCommand(

private fun keyCode(
keycode: Int,
screen: Screen,
side: CardSide,
keys: ModifierKeys = ModifierKeys.none(),
): MappableBinding = MappableBinding(keyCode(keys, keycode), screen)
): ReviewerBinding = ReviewerBinding(keyCode(keys, keycode), side)

private fun unicode(
c: Char,
screen: Screen,
): MappableBinding = MappableBinding(unicode(c), screen)
side: CardSide,
): ReviewerBinding = ReviewerBinding(unicode(c), side)

fun interface CommandProcessor {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import com.ichi2.anki.reviewer.MappableBinding.Companion.toPreferenceString
import com.ichi2.anki.ui.internationalization.toSentenceCase
import com.ichi2.annotations.NeedsTest
import com.ichi2.preferences.ControlPreference
import com.ichi2.preferences.ReviewerControlPreference

class ControlsSettingsFragment : SettingsFragment() {
override val preferenceResource: Int
Expand All @@ -37,10 +38,16 @@ class ControlsSettingsFragment : SettingsFragment() {
val commands = ViewerCommand.entries.associateBy { it.preferenceKey }
// set defaultValue in the prefs creation.
// if a preference is empty, it has a value like "1/"
allPreferences()
.filterIsInstance<ControlPreference>()
preferenceScreen
.allPreferences()
.filterIsInstance<ReviewerControlPreference>()
.filter { pref -> pref.value == null }
.forEach { pref -> pref.value = commands[pref.key]?.defaultValue?.toPreferenceString() }
.forEach { pref ->
commands[pref.key]
?.defaultValue
?.toPreferenceString()
?.let { pref.value = it }
}

setDynamicTitle()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ class CustomButtonsSettingsFragment : SettingsFragment() {
}

@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun allKeys(): HashSet<String> = allPreferences().mapTo(hashSetOf()) { it.key }
fun allKeys(): HashSet<String> = preferenceScreen.allPreferences().mapTo(hashSetOf()) { it.key }
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import android.content.SharedPreferences
import androidx.annotation.StringRes
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceGroup
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceScreen

fun SharedPreferences.get(key: String): Any? = all[key]

Expand Down Expand Up @@ -61,3 +63,18 @@ inline fun <reified T : Preference> PreferenceFragmentCompat.requirePreference(

/** shorthand method to get the default [SharedPreferences] instance */
fun Context.sharedPrefs(): SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)

fun PreferenceScreen.allPreferences(): List<Preference> {
val allPreferences = mutableListOf<Preference>()
for (i in 0 until preferenceCount) {
val pref = getPreference(i)
if (pref is PreferenceGroup) {
for (j in 0 until pref.preferenceCount) {
allPreferences.add(pref.getPreference(j))
}
} else {
allPreferences.add(pref)
}
}
return allPreferences
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import androidx.annotation.VisibleForTesting
import androidx.annotation.XmlRes
import androidx.core.os.bundleOf
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.PreferenceManager.OnPreferenceTreeClickListener
Expand Down Expand Up @@ -93,7 +92,7 @@ abstract class SettingsFragment :
(preference as? DialogFragmentProvider)?.makeDialogFragment()
?: return super.onDisplayPreferenceDialog(preference)
Timber.d("displaying custom preference: ${dialogFragment::class.simpleName}")
dialogFragment.arguments = bundleOf("key" to preference.key)
dialogFragment.arguments = bundleOf(PREF_DIALOG_KEY to preference.key)
dialogFragment.setTargetFragment(this, 0)
dialogFragment.show(parentFragmentManager, "androidx.preference.PreferenceFragment.DIALOG")
}
Expand All @@ -112,22 +111,9 @@ abstract class SettingsFragment :
.unregisterOnSharedPreferenceChangeListener(this)
}

protected fun allPreferences(): List<Preference> {
val allPreferences = mutableListOf<Preference>()
for (i in 0 until preferenceScreen.preferenceCount) {
val pref = preferenceScreen.getPreference(i)
if (pref is PreferenceCategory) {
for (j in 0 until pref.preferenceCount) {
allPreferences.add(pref.getPreference(j))
}
} else {
allPreferences.add(pref)
}
}
return allPreferences
}

companion object {
const val PREF_DIALOG_KEY = "key"

/**
* Converts a preference value to a numeric number that
* can be reported to analytics, since analytics events only accept
Expand Down
Loading