Anki-Android
Anki-Android copied to clipboard
[GSoC'24] Card Analysis Widget .
Purpose / Description
This commit introduces the Card Analysis Widget, which displays a deck name along with the number of cards that are new, in learning, and due for review.
Approach
On the same pattern as Deck Picker Widget.
How Has This Been Tested?
https://github.com/user-attachments/assets/38e138d2-6c34-42a2-a675-85f18e683be7
Checklist
Please, go through these checks before submitting the PR.
- [x] You have a descriptive commit message with a short title (first line, max 50 chars).
- [x] You have commented your code, particularly in hard-to-understand areas
- [x] You have performed a self-review of your own code
- [x] UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
- [ ] UI Changes: You have tested your change using the Google Accessibility Scanner
Message to maintainers, this PR contains strings changes.
- Before merging this PR, it is best to run the "Sync Translations" GitHub action, then make and merge a PR from the i18n_sync branch to get translations cleaned out.
- Then merge this PR, and immediately do another translation PR so the huge change made by this PR's key changes are all by themselves.
Read more about updating strings on the wiki,
I get a "You may only select one deck" after selecting the only deck. I'd prefer if you could open the deck selector as soon as configuration is opened. There is really no reason to have the use press "+". Similarly, once the selection is done, you can directly save it. In the worst case, if the user want to change the deck they can reconfigure it
If the deck is deleted, I'd prefer if you could either delete the widget alltogether if it's possible (@david-allison do you agree?) or at least show a message stating something such as "Missing deck. Please reconfigure" and tapping on the widget would open the configuration view instead of opening ankidroid
Deleting the widget: it doesn't seem wise. Renaming a deck would count as a deletion, whereas the user would expect a reconfiguration
I'm fine with not deleting it. But at least, we should not leave it empty
I'm happy, and to be frank, pleasantly surprised, you were able to update so quickly.
A few requests:
- you shouldn't be able to close the list of decks except by selecting a deck. Closing the list, e.g. with "esc" should close the whole configuration.
- Remove the + symbol. It won't be used.
- If the collection is empty instead of "missing deck", reuse the "not initialized" string. And don't open the configuration, as it close automatically.
- Check whether there is a way to have the deck list take more of the screen, given that the part below the deck list is of no interest
To save you time, here are the typing change I created while reviewing and testing your code
Subject: [PATCH] Notify the UI that a sync was done
In this case, I really don't think it's realistic to expect an
OpChange from the backend. The backend already sends informations that
are relevant for the sync process. Given that "sync" does not uses the
processes uses for undoable change (indeed, it should not be
undoable), no OpChange is generated.
It seems reasonable in this place at least to directly notify the
observers.
Given that the observers expect an OpChanges, I create one, and simply
assume everything may be changed. This seems reasonable in case of
sync, and it's sufficiently rare that the cost won't be prohibitive
anyway.
Fixed: #16943
Fixed: #16942
---
Index: AnkiDroid/src/test/java/com/ichi2/anki/widget/deckpicker/DeckNameAndStatsTest.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/widget/deckpicker/DeckNameAndStatsTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/widget/deckpicker/DeckNameAndStatsTest.kt
--- a/AnkiDroid/src/test/java/com/ichi2/anki/widget/deckpicker/DeckNameAndStatsTest.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/test/java/com/ichi2/anki/widget/deckpicker/DeckNameAndStatsTest.kt (date 1725056072761)
@@ -18,7 +18,7 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.ichi2.anki.RobolectricTest
-import com.ichi2.widget.deckpicker.getDeckNameAndStats
+import com.ichi2.widget.deckpicker.getDeckNamesAndStats
import org.junit.Test
import org.junit.runner.RunWith
import kotlin.test.assertEquals
@@ -32,7 +32,7 @@
val deck2Id = addDeck("Deck 2")
val deckIds = listOf(deck1Id, deck2Id)
- val result = getDeckNameAndStats(deckIds)
+ val result = getDeckNamesAndStats(deckIds)
assertEquals(2, result.size)
assertEquals("Deck 1", result[0].name)
@@ -48,7 +48,7 @@
val deckCId = addDeck("Deck C")
val deckIds = listOf(deckCId, deckAId, deckBId)
- val result = getDeckNameAndStats(deckIds)
+ val result = getDeckNamesAndStats(deckIds)
assertEquals(3, result.size)
assertEquals("Deck C", result[0].name)
@@ -65,7 +65,7 @@
val child1Id = addDeck("Deck 1::Child 1")
val deckIds = listOf(deck1Id, child1Id)
- val result = getDeckNameAndStats(deckIds)
+ val result = getDeckNamesAndStats(deckIds)
assertEquals(2, result.size)
assertEquals("Deck 1", result[0].name)
Index: AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetConfig.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetConfig.kt b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetConfig.kt
--- a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetConfig.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetConfig.kt (date 1725056710433)
@@ -104,8 +104,8 @@
initializeUIComponents()
// Show the Deck selection dialog only when there are no decks selected while opening the configuration screen.
- val selectedDeckIds = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)
- if (selectedDeckIds.isEmpty()) {
+ val selectedDeckId = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)
+ if (selectedDeckId == null) {
showDeckSelectionDialog()
}
}
@@ -220,16 +220,14 @@
/** Updates the view according to the saved preference for appWidgetId.*/
fun updateViewWithSavedPreferences() {
- val selectedDeckIds = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)
- if (selectedDeckIds.isNotEmpty()) {
+ val selectedDeckId = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)?: return
lifecycleScope.launch {
val decks = fetchDecks()
- val selectedDecks = decks.filter { it.deckId in selectedDeckIds }
+ val selectedDecks = decks.filter { it.deckId == selectedDeckId }
selectedDecks.forEach { deckAdapter.addDeck(it) }
updateViewVisibility()
updateFabVisibility()
}
- }
}
/** Asynchronously displays the list of deck in the selection dialog. */
@@ -287,9 +285,9 @@
hasUnsavedChanges = false
setUnsavedChanges(false)
- val selectedDeckIds = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)
+ val selectedDeckId = cardAnalysisWidgetPreferences.getSelectedDeckIdFromPreferences(appWidgetId)
val appWidgetManager = AppWidgetManager.getInstance(this)
- CardAnalysisWidget.updateWidget(this, appWidgetManager, appWidgetId, selectedDeckIds)
+ CardAnalysisWidget.updateWidget(this, appWidgetManager, appWidgetId, selectedDeckId)
val resultValue = Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
setResult(RESULT_OK, resultValue)
@@ -310,14 +308,14 @@
}
fun saveSelectedDecksToPreferencesCardAnalysisWidget() {
- val selectedDecks = deckAdapter.deckIds.map { it }
- cardAnalysisWidgetPreferences.saveSelectedDeck(appWidgetId, selectedDecks.map { it.toString() })
+ val selectedDeck = deckAdapter.deckIds.getOrNull(0)
+ cardAnalysisWidgetPreferences.saveSelectedDeck(appWidgetId, selectedDeck)
val updateIntent = Intent(this, CardAnalysisWidget::class.java).apply {
action = AppWidgetManager.ACTION_APPWIDGET_UPDATE
putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, intArrayOf(appWidgetId))
- putExtra("card_analysis_widget_selected_deck_ids", selectedDecks.toList().toLongArray())
+ putExtra("card_analysis_widget_selected_deck_ids", selectedDeck)
}
sendBroadcast(updateIntent)
Index: AnkiDroid/src/test/java/com/ichi2/anki/widget/cardanalysis/CardAnalysisWidgetConfigTest.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/widget/cardanalysis/CardAnalysisWidgetConfigTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/widget/cardanalysis/CardAnalysisWidgetConfigTest.kt
--- a/AnkiDroid/src/test/java/com/ichi2/anki/widget/cardanalysis/CardAnalysisWidgetConfigTest.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/test/java/com/ichi2/anki/widget/cardanalysis/CardAnalysisWidgetConfigTest.kt (date 1725056072761)
@@ -82,7 +82,7 @@
activity.saveSelectedDecksToPreferencesCardAnalysisWidget()
// Verify saved decks
- val selectedDeckIds = widgetPreferences.getSelectedDeckIdFromPreferences(1).toList()
+ val selectedDeckIds = widgetPreferences.getSelectedDeckIdsFromPreferences(1).toList()
assertThat(selectedDeckIds.contains(deck1.deckId), equalTo(true))
}
@@ -96,7 +96,7 @@
fun testLoadSavedPreferences() {
// Save decks to preferences
val deckIds = listOf(1L)
- widgetPreferences.saveSelectedDeck(1, deckIds.map { it.toString() })
+ widgetPreferences.saveSelectedDecks(1, deckIds.map { it.toString() })
// Load preferences
activity.updateViewWithSavedPreferences()
Index: AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt
--- a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidget.kt (date 1725056072761)
@@ -30,9 +30,11 @@
import com.ichi2.anki.Reviewer
import com.ichi2.anki.analytics.UsageAnalytics
import com.ichi2.anki.pages.DeckOptions
+import com.ichi2.libanki.DeckId
import com.ichi2.widget.ACTION_UPDATE_WIDGET
import com.ichi2.widget.AnalyticsWidgetProvider
import com.ichi2.widget.cancelRecurringAlarm
+import com.ichi2.widget.deckpicker.DeckWidgetData
import com.ichi2.widget.deckpicker.getDeckNameAndStats
import com.ichi2.widget.setRecurringAlarm
import kotlinx.coroutines.launch
@@ -68,72 +70,85 @@
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetId: Int,
- deckId: LongArray
+ deckId: DeckId?
) {
val remoteViews = RemoteViews(context.packageName, R.layout.widget_card_analysis)
-
+ if (deckId == null) {
+ showMissingDeck(context, appWidgetManager, appWidgetId, remoteViews)
+ return
+ }
AnkiDroidApp.applicationScope.launch {
- val deckData = getDeckNameAndStats(deckId.toList())
+ val deckData = getDeckNameAndStats(deckId)
- if (deckData.isEmpty()) {
+
+ if (deckData ==null) {
// If the deck was deleted, clear the stored deck ID
- val widgetPreferences = CardAnalysisWidgetPreferences(context)
- val selectedDeck = longArrayOf().map { it.toString() }
- widgetPreferences.saveSelectedDeck(appWidgetId, selectedDeck)
+ CardAnalysisWidgetPreferences(context).saveSelectedDeck(appWidgetId, null)
+ showMissingDeck(context, appWidgetManager, appWidgetId, remoteViews)
+ return@launch
+ }
+ showDeck(context, appWidgetManager, appWidgetId, remoteViews, deckData)
+ }
+ }
+
+ private fun showMissingDeck(context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetId: Int, remoteViews: RemoteViews) {
- // Show empty_widget and set click listener to open configuration
- remoteViews.setViewVisibility(R.id.empty_widget, View.VISIBLE)
- remoteViews.setViewVisibility(R.id.cardAnalysisDataHolder, View.GONE)
- remoteViews.setViewVisibility(R.id.deckNameCardAnalysis, View.GONE)
+ // Show empty_widget and set click listener to open configuration
+ remoteViews.setViewVisibility(R.id.empty_widget, View.VISIBLE)
+ remoteViews.setViewVisibility(R.id.cardAnalysisDataHolder, View.GONE)
+ remoteViews.setViewVisibility(R.id.deckNameCardAnalysis, View.GONE)
- val configIntent = Intent(context, CardAnalysisWidgetConfig::class.java).apply {
- putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
- flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
- }
- val configPendingIntent = PendingIntent.getActivity(
- context,
- appWidgetId,
- configIntent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
- remoteViews.setOnClickPendingIntent(R.id.empty_widget, configPendingIntent)
+ val configIntent = Intent(context, CardAnalysisWidgetConfig::class.java).apply {
+ putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
+ }
+ val configPendingIntent = PendingIntent.getActivity(
+ context,
+ appWidgetId,
+ configIntent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ remoteViews.setOnClickPendingIntent(R.id.empty_widget, configPendingIntent)
- appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
- return@launch
- }
+ appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
+ }
- val deck = deckData[0]
- remoteViews.setTextViewText(R.id.deckNameCardAnalysis, deck.name)
- remoteViews.setTextViewText(R.id.deckNew_card_analysis_widget, deck.newCount.toString())
- remoteViews.setTextViewText(R.id.deckDue_card_analysis_widget, deck.reviewCount.toString())
- remoteViews.setTextViewText(R.id.deckLearn_card_analysis_widget, deck.learnCount.toString())
+ private fun showDeck(context: Context,
+ appWidgetManager: AppWidgetManager,
+ appWidgetId: Int, remoteViews: RemoteViews, deckData: DeckWidgetData) {
+ remoteViews.setTextViewText(R.id.deckNameCardAnalysis, deckData.name)
+ remoteViews.setTextViewText(R.id.deckNew_card_analysis_widget, deckData.newCount.toString())
+ remoteViews.setTextViewText(R.id.deckDue_card_analysis_widget, deckData.reviewCount.toString())
+ remoteViews.setTextViewText(R.id.deckLearn_card_analysis_widget, deckData.learnCount.toString())
- // Hide empty_widget and show the actual widget content
- remoteViews.setViewVisibility(R.id.empty_widget, View.GONE)
- remoteViews.setViewVisibility(R.id.cardAnalysisDataHolder, View.VISIBLE)
- remoteViews.setViewVisibility(R.id.deckNameCardAnalysis, View.VISIBLE)
+ // Hide empty_widget and show the actual widget content
+ remoteViews.setViewVisibility(R.id.empty_widget, View.GONE)
+ remoteViews.setViewVisibility(R.id.cardAnalysisDataHolder, View.VISIBLE)
+ remoteViews.setViewVisibility(R.id.deckNameCardAnalysis, View.VISIBLE)
- val isEmptyDeck = deck.newCount == 0 && deck.reviewCount == 0 && deck.learnCount == 0
+ val isEmptyDeck = deckData.newCount == 0 && deckData.reviewCount == 0 && deckData.learnCount == 0
- val intent = if (!isEmptyDeck) {
- Intent(context, Reviewer::class.java).apply {
- action = Intent.ACTION_VIEW
- putExtra("deckId", deck.deckId)
- }
- } else {
- DeckOptions.getIntent(context, deck.deckId)
- }
- val pendingIntent = PendingIntent.getActivity(
- context,
- deck.deckId.toInt(),
- intent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
- remoteViews.setOnClickPendingIntent(R.id.deckNameCardAnalysis, pendingIntent)
+ val intent = if (!isEmptyDeck) {
+ Intent(context, Reviewer::class.java).apply {
+ action = Intent.ACTION_VIEW
+ putExtra("deckId", deckData.deckId)
+ }
+ } else {
+ DeckOptions.getIntent(context, deckData.deckId)
+ }
+ val pendingIntent = PendingIntent.getActivity(
+ context,
+ deckData.deckId.toInt(),
+ intent,
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ )
+ remoteViews.setOnClickPendingIntent(R.id.deckNameCardAnalysis, pendingIntent)
- appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
- }
+ appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}
+
/**
* Updates the Card Analysis Widgets based on the current state of the application.
@@ -207,7 +222,7 @@
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID && selectedDeckId != -1L) {
Timber.d("Updating widget with ID: $appWidgetId")
// Wrap selectedDeckId into a LongArray
- updateWidget(context, appWidgetManager, appWidgetId, longArrayOf(selectedDeckId))
+ updateWidget(context, appWidgetManager, appWidgetId, selectedDeckId)
Timber.d("Widget update process completed for widget ID: $appWidgetId")
}
}
Index: AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetPreferences.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetPreferences.kt b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetPreferences.kt
--- a/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetPreferences.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/main/java/com/ichi2/widget/cardanalysis/CardAnalysisWidgetPreferences.kt (date 1725056072761)
@@ -18,6 +18,8 @@
import android.content.Context
import androidx.core.content.edit
+import com.ichi2.libanki.DeckId
+import com.ichi2.libanki.Decks.Companion.NOT_FOUND_DECK_ID
class CardAnalysisWidgetPreferences(context: Context) {
@@ -39,21 +41,17 @@
}
}
- fun getSelectedDeckIdFromPreferences(appWidgetId: Int): LongArray {
- val selectedDeckString = cardAnalysisWidgetSharedPreferences.getString(
+ fun getSelectedDeckIdFromPreferences(appWidgetId: Int): DeckId? {
+ val selectedDeckString = cardAnalysisWidgetSharedPreferences.getLong(
getCardAnalysisExtraWidgetKey(appWidgetId),
- ""
+ NOT_FOUND_DECK_ID
)
- return if (!selectedDeckString.isNullOrEmpty()) {
- selectedDeckString.split(",").map { it.toLong() }.toLongArray()
- } else {
- longArrayOf()
- }
+ return selectedDeckString.takeIf { it != NOT_FOUND_DECK_ID }
}
- fun saveSelectedDeck(appWidgetId: Int, selectedDeck: List<String>) {
+ fun saveSelectedDeck(appWidgetId: Int, selectedDeck: DeckId?) {
cardAnalysisWidgetSharedPreferences.edit {
- putString(getCardAnalysisExtraWidgetKey(appWidgetId), selectedDeck.joinToString(","))
+ putLong(getCardAnalysisExtraWidgetKey(appWidgetId), selectedDeck ?: NOT_FOUND_DECK_ID)
}
}
}
Index: AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt b/AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt
--- a/AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt (revision a4a4c1bba2a4efeb201212bc201724b9d7ac6c8d)
+++ b/AnkiDroid/src/main/java/com/ichi2/widget/deckpicker/DeckPickerWidget.kt (date 1725056072761)
@@ -30,6 +30,7 @@
import com.ichi2.anki.Reviewer
import com.ichi2.anki.analytics.UsageAnalytics
import com.ichi2.anki.pages.DeckOptions
+import com.ichi2.libanki.DeckId
import com.ichi2.widget.ACTION_UPDATE_WIDGET
import com.ichi2.widget.AnalyticsWidgetProvider
import com.ichi2.widget.cancelRecurringAlarm
@@ -37,7 +38,6 @@
import kotlinx.coroutines.launch
import timber.log.Timber
-typealias DeckId = Long
typealias AppWidgetId = Int
/**
@@ -49,7 +49,7 @@
* @property learnCount The number of cards in the learning phase.
* @property newCount The number of new cards.
*/
-data class DeckPickerWidgetData(
+data class DeckWidgetData(
val deckId: DeckId,
val name: String,
val reviewCount: Int,
@@ -97,7 +97,7 @@
val remoteViews = RemoteViews(context.packageName, R.layout.widget_deck_picker_large)
AnkiDroidApp.applicationScope.launch {
- val deckData = getDeckNameAndStats(deckIds.toList())
+ val deckData = getDeckNamesAndStats(deckIds.toList())
remoteViews.removeAllViews(R.id.deckCollection)
@@ -277,15 +277,19 @@
* @param deckIds the list of deck IDs to retrieve data for
* @return a list of DeckPickerWidgetData objects containing deck names and statistics
*/
-suspend fun getDeckNameAndStats(deckIds: List<DeckId>): List<DeckPickerWidgetData> {
- val result = mutableListOf<DeckPickerWidgetData>()
+suspend fun getDeckNameAndStats(deckId:DeckId): DeckWidgetData? {
+ return getDeckNamesAndStats(listOf(deckId)).getOrNull(0)
+}
+
+suspend fun getDeckNamesAndStats(deckIds: List<DeckId>): List<DeckWidgetData> {
+ val result = mutableListOf<DeckWidgetData>()
val deckTree = withCol { sched.deckDueTree() }
deckTree.forEach { node ->
if (node.did !in deckIds) return@forEach
result.add(
- DeckPickerWidgetData(
+ DeckWidgetData(
deckId = node.did,
name = node.lastDeckNameComponent,
reviewCount = node.revCount,
To save you time, here are the typing change I created while reviewing and testing your code
Thanks a lot for this, really helped me as my exams are around the corner.
you shouldn't be able to close the list of decks except by selecting a deck. Closing the list, e.g. with "esc" should close the whole configuration. Remove the + symbol. It won't be used.
Is it possible to implement this change in future?. Need some time for my exam. I tried but wasn't able to implement that on back press the config screen should get closed not the deck selection dialog. I did implement the alternate mechanism for now.
@xenonnn4w after checking with David, fine for doing the configuration change in the future
- https://github.com/ankidroid/Anki-Android/actions/runs/10760675211
- https://github.com/ankidroid/Anki-Android/pull/17039
Maintainers: Please Sync Translations to produce a commit with only the automated changes from this PR.
Read more about updating strings on the wiki,
Hi there @xenonnn4w! This is the OpenCollective Notice for PRs merged from 2024-09-01 through 2024-09-30
If you are interested in compensation for this work, the process with details is here:
https://github.com/ankidroid/Anki-Android/wiki/OpenCollective-Payment-Process#how-to-get-paid
[!IMPORTANT] PLEASE NOTE: The process was updated in August 2024. Re-read the Payment Process page if you have not already.
We only post one comment per person per month to avoid spamming you, regardless of the number of PRs merged, but this note applies to all PRs merged for this month
Please understand that our monthly budget is never guaranteed to cover all claims - the cap on payments-per-person may be lower, but we try to make our process as fair and transparent as possible, we just need your understanding.
Thanks!