From 2a74854583589549d80add38b721cda028299127 Mon Sep 17 00:00:00 2001 From: hill Date: Wed, 30 Sep 2026 13:53:50 +0200 Subject: [PATCH 1/2] Compact daily deck status, with a setting to hide it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The deck list gave every deck a second line. "N cards ready" and "Nothing scheduled today" repeated the counts beside it, so they are gone; a deck finished today shows a check after its name next to the green tint; only "Learning later today · next at …" keeps a line. AnkiQuest → Study → "Daily status in the deck list" turns it all off. --- .../ichi2/anki/ankiquest/AnkiquestDecks.kt | 7 + .../anki/deckpicker/DeckPickerViewModel.kt | 20 ++- .../com/ichi2/anki/widgets/DeckAdapter.kt | 15 +- .../res/values-de/ankiquest_daily_decks.xml | 2 + .../res/values-es/ankiquest_daily_decks.xml | 2 + .../res/values-fr/ankiquest_daily_decks.xml | 2 + .../res/values-pt/ankiquest_daily_decks.xml | 2 + .../main/res/values/ankiquest_daily_decks.xml | 3 + .../res/xml/preferences_ankiquest_study.xml | 5 + .../analytics/PreferencesAnalyticsTest.kt | 1 + .../anki/ankiquest/AnkiquestDeckStatusTest.kt | 128 ++++++++++++++++++ 11 files changed, 179 insertions(+), 8 deletions(-) create mode 100644 AnkiDroid/src/test/java/com/ichi2/anki/ankiquest/AnkiquestDeckStatusTest.kt diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ankiquest/AnkiquestDecks.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ankiquest/AnkiquestDecks.kt index 9e73eee1d580..ef4307886585 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/ankiquest/AnkiquestDecks.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/ankiquest/AnkiquestDecks.kt @@ -9,6 +9,13 @@ import org.json.JSONObject /** Deck completion uses Anki's daily limits, including subdecks and learning later today. */ internal object AnkiquestDecks { private const val DAY_MS = 86_400_000L + const val DECK_STATUS_KEY = "ankiquestDeckStatus" + + /** Whether the deck list marks decks finished today and learning due later. */ + fun statusInDeckList(): Boolean = + com.ichi2.anki.AnkiDroidApp + .sharedPrefs() + .getBoolean(DECK_STATUS_KEY, true) fun dailyStates( col: Collection, diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt b/AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt index 7537bfa40678..f7e89df4c977 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/deckpicker/DeckPickerViewModel.kt @@ -415,13 +415,19 @@ class DeckPickerViewModel : Pair(sched.deckDueTree(), isEmpty) } dailyDeckStates.value = - withCol { - com.ichi2.anki.ankiquest.AnkiquestDecks.dailyStates( - this, - com.ichi2.anki.common.time.TimeManager.time - .intTimeMS(), - deckDueTree, - ) + if (com.ichi2.anki.ankiquest.AnkiquestDecks + .statusInDeckList() + ) { + withCol { + com.ichi2.anki.ankiquest.AnkiquestDecks.dailyStates( + this, + com.ichi2.anki.common.time.TimeManager.time + .intTimeMS(), + deckDueTree, + ) + } + } else { + emptyMap() } dueTree = deckDueTree diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/widgets/DeckAdapter.kt b/AnkiDroid/src/main/java/com/ichi2/anki/widgets/DeckAdapter.kt index 0b31b2dd202e..dd75ac4916f2 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/widgets/DeckAdapter.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/widgets/DeckAdapter.kt @@ -169,7 +169,20 @@ class DeckAdapter( binding.deckName.text = node.lastDeckNameComponent binding.deckName.setTextColor(if (node.filtered) deckNameDynColor else deckNameDefaultColor) - binding.deckDailyStatus.isVisible = node.dailyState != null + val dailyStatus = node.dailyState?.status + binding.deckDailyStatus.isVisible = dailyStatus == com.ichi2.anki.ankiquest.DailyDeckStatus.LEARNING_LATER + val finished = dailyStatus == com.ichi2.anki.ankiquest.DailyDeckStatus.DONE + binding.deckName.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, if (finished) R.drawable.ic_done else 0, 0) + TextViewCompat.setCompoundDrawableTintList( + binding.deckName, + if (finished) { + android.content.res.ColorStateList + .valueOf(binding.deckName.context.getColor(R.color.aq_deck_green)) + } else { + null + }, + ) + binding.deckName.compoundDrawablePadding = 4.dp.toPx(binding.deckName.context) node.dailyState?.let { daily -> val status = binding.deckDailyStatus status.text = daily.label(status.context) diff --git a/AnkiDroid/src/main/res/values-de/ankiquest_daily_decks.xml b/AnkiDroid/src/main/res/values-de/ankiquest_daily_decks.xml index 7f905068c842..610ec345bdee 100644 --- a/AnkiDroid/src/main/res/values-de/ankiquest_daily_decks.xml +++ b/AnkiDroid/src/main/res/values-de/ankiquest_daily_decks.xml @@ -1,6 +1,8 @@ + Tagesstatus in der Stapelliste + Markiert heute erledigte Stapel und später heute fälliges Lernen Lernen später heute · nächste Wiederholung um %1$s Für heute erledigt Heute nichts geplant diff --git a/AnkiDroid/src/main/res/values-es/ankiquest_daily_decks.xml b/AnkiDroid/src/main/res/values-es/ankiquest_daily_decks.xml index a2bec26a2a71..87e28ef7b97b 100644 --- a/AnkiDroid/src/main/res/values-es/ankiquest_daily_decks.xml +++ b/AnkiDroid/src/main/res/values-es/ankiquest_daily_decks.xml @@ -1,6 +1,8 @@ + Estado diario en la lista de mazos + Marca los mazos terminados hoy y el aprendizaje pendiente para más tarde Aprendizaje pendiente hoy · siguiente a las %1$s Terminado por hoy Nada programado para hoy diff --git a/AnkiDroid/src/main/res/values-fr/ankiquest_daily_decks.xml b/AnkiDroid/src/main/res/values-fr/ankiquest_daily_decks.xml index 997ccf02097d..db463c6d532e 100644 --- a/AnkiDroid/src/main/res/values-fr/ankiquest_daily_decks.xml +++ b/AnkiDroid/src/main/res/values-fr/ankiquest_daily_decks.xml @@ -1,6 +1,8 @@ + État du jour dans la liste des paquets + Signale les paquets terminés aujourd’hui et l’apprentissage prévu plus tard Apprentissage plus tard aujourd’hui · prochaine révision à %1$s Terminé pour aujourd’hui Rien de prévu aujourd’hui diff --git a/AnkiDroid/src/main/res/values-pt/ankiquest_daily_decks.xml b/AnkiDroid/src/main/res/values-pt/ankiquest_daily_decks.xml index bf6b212d3070..78b2ce7d2cab 100644 --- a/AnkiDroid/src/main/res/values-pt/ankiquest_daily_decks.xml +++ b/AnkiDroid/src/main/res/values-pt/ankiquest_daily_decks.xml @@ -1,6 +1,8 @@ + Estado diário na lista de baralhos + Marca os baralhos concluídos hoje e a aprendizagem pendente para mais tarde Aprendizagem mais tarde hoje · próxima revisão às %1$s Concluído por hoje Nada agendado para hoje diff --git a/AnkiDroid/src/main/res/values/ankiquest_daily_decks.xml b/AnkiDroid/src/main/res/values/ankiquest_daily_decks.xml index 78fa89c2d396..b9d6d14db409 100644 --- a/AnkiDroid/src/main/res/values/ankiquest_daily_decks.xml +++ b/AnkiDroid/src/main/res/values/ankiquest_daily_decks.xml @@ -1,6 +1,9 @@ + ankiquestDeckStatus + Daily status in the deck list + Mark decks finished today, and learning due later today Learning later today · next at %1$s Done today Nothing scheduled today diff --git a/AnkiDroid/src/main/res/xml/preferences_ankiquest_study.xml b/AnkiDroid/src/main/res/xml/preferences_ankiquest_study.xml index 7df7c8f5df1f..f5c21e72d90e 100644 --- a/AnkiDroid/src/main/res/xml/preferences_ankiquest_study.xml +++ b/AnkiDroid/src/main/res/xml/preferences_ankiquest_study.xml @@ -14,6 +14,11 @@ android:key="@string/ankiquest_summary_preference_key" android:summary="@string/ankiquest_summary_preference_summary" android:title="@string/ankiquest_summary_preference_title" /> + + deckPicker.awaitInitialDeckHolder(spanish) + val adapter = + (deckPicker.deckPickerBinding.decks.adapter as ConcatAdapter) + .adapters + .filterIsInstance() + .single() + assertEquals(expected, adapter.currentList.any { it.dailyState != null }, "setting on: $enabled") + } + } + } + + private fun bind(states: Map): Map { + val context = ContextThemeWrapper(targetContext, R.style.Theme_Light) + val adapter = + DeckAdapter( + context, + onDeckSelected = {}, + onDeckCountsSelected = {}, + onDeckChildrenToggled = {}, + onDeckContextRequested = {}, + onDeckRightClick = { _, _, _ -> }, + ) + val list = + RecyclerView(context).apply { + layoutManager = LinearLayoutManager(context) + this.adapter = adapter + } + val nodes = + col.sched + .deckDueTree() + .filterAndFlattenDisplay(DeckFilters.create(""), 1) + .map { it.withDailyState(states[it.did]) } + var committed = false + adapter.submit(nodes, hasSubDecks = false) { committed = true } + advanceRobolectricLooperUntil { committed } + list.measure( + View.MeasureSpec.makeMeasureSpec(480, View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(2000, View.MeasureSpec.EXACTLY), + ) + list.layout(0, 0, 480, 2000) + return states.keys.associateWith { deck -> + list.findViewHolderForAdapterPosition(adapter.currentList.indexOfFirst { it.did == deck }) as DeckAdapter.ViewHolder + } + } +} From fdbb60ebccb7eca8aa9fc9239a08e44d5813da25 Mon Sep 17 00:00:00 2001 From: hill Date: Wed, 30 Sep 2026 14:49:42 +0200 Subject: [PATCH 2/2] List the deck status setting in the settings menu test --- .../java/com/ichi2/anki/preferences/AnkiquestSettingsMenuTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/AnkiquestSettingsMenuTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/AnkiquestSettingsMenuTest.kt index 81ff55610f53..54b80b9c7baa 100644 --- a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/AnkiquestSettingsMenuTest.kt +++ b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/AnkiquestSettingsMenuTest.kt @@ -47,6 +47,7 @@ class AnkiquestSettingsMenuTest : RobolectricTest() { R.string.ankiquest_test_key, R.string.ankiquest_open_today_key, R.string.ankiquest_summary_preference_key, + R.string.ankiquest_deck_status_key, R.string.ankiquest_streak_protection_key, R.string.ankiquest_notify_rank_key, R.string.ankiquest_streak_hours_key,