Skip to content

Commit

Permalink
Refactored deck iteration and empty deck check logic
Browse files Browse the repository at this point in the history
  • Loading branch information
devyk100 committed Feb 24, 2025
1 parent dd538c9 commit 2e33db4
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 48 deletions.
59 changes: 12 additions & 47 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2167,20 +2167,14 @@ open class DeckPicker :
openReviewerOrStudyOptions(selectionType)
return
}
when (queryCompletedDeckCustomStudyAction(did)) {
CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED,
CompletedDeckStatus.REGULAR_DECK_NO_MORE_CARDS_TODAY,
CompletedDeckStatus.DYNAMIC_DECK_NO_LIMITS_REACHED,
CompletedDeckStatus.DAILY_STUDY_LIMIT_REACHED,
-> {
onDeckCompleted()
}
CompletedDeckStatus.EMPTY_REGULAR_DECK -> {
// If the deck is empty (& has no children) then show a message saying it's empty
showEmptyDeckSnackbar()
updateUi()
}

if (isDeckAndSubdeckEmpty(did)) {
showEmptyDeckSnackbar()
updateUi()
return
}

onDeckCompleted()
}

/**
Expand Down Expand Up @@ -2668,44 +2662,15 @@ open class DeckPicker :
}

/**
* Returns how a user can 'custom study' a deck with no more pending cards
* Returns if the deck and its subdecks are all empty.
*
* @param did The id of a deck with no pending cards to review
*/
private suspend fun queryCompletedDeckCustomStudyAction(did: DeckId): CompletedDeckStatus =
when {
withCol { sched.hasCardsTodayAfterStudyAheadLimit() } -> CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED
withCol { sched.newDue() || sched.revDue() } -> CompletedDeckStatus.LEARN_AHEAD_LIMIT_REACHED
withCol { decks.isFiltered(did) } -> CompletedDeckStatus.DYNAMIC_DECK_NO_LIMITS_REACHED
run {
val node = getNodeByDid(did)
withCol {
var allChildrenEmpty = true
node.forEach { deckNode ->
allChildrenEmpty = allChildrenEmpty && decks.isEmpty(deckNode.did)
}
allChildrenEmpty
}
} -> CompletedDeckStatus.EMPTY_REGULAR_DECK
else -> CompletedDeckStatus.REGULAR_DECK_NO_MORE_CARDS_TODAY
private suspend fun isDeckAndSubdeckEmpty(did: DeckId): Boolean {
val node = getNodeByDid(did)
return withCol {
node.all { decks.isEmpty(it.did) }
}

/** Status for a deck with no current cards to review */
enum class CompletedDeckStatus {
/** No cards for today, but there would be if the user waited */
LEARN_AHEAD_LIMIT_REACHED,

/** No cards for today, but either the 'new' or 'review' limit was reached */
DAILY_STUDY_LIMIT_REACHED,

/** No cards are available, but the deck was dynamic */
DYNAMIC_DECK_NO_LIMITS_REACHED,

/** The deck contained no cards and had no child decks */
EMPTY_REGULAR_DECK,

/** The user has completed their studying for today, and there are future reviews */
REGULAR_DECK_NO_MORE_CARDS_TODAY,
}

override fun getApkgFileImportResultLauncher(): ActivityResultLauncher<Intent> = apkgFileImportResultLauncher
Expand Down
8 changes: 7 additions & 1 deletion AnkiDroid/src/main/java/com/ichi2/libanki/sched/DeckNode.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ data class DeckNode(
val node: DeckTreeNode,
val fullDeckName: String,
val parent: WeakReference<DeckNode>? = null,
) {
) : Iterable<DeckNode> {
var collapsed = node.collapsed
val revCount = node.reviewCount
val newCount = node.newCount
Expand Down Expand Up @@ -89,6 +89,12 @@ data class DeckNode(
}
}

override fun iterator(): Iterator<DeckNode> =
sequence {
if (node.level > 0) yield(this@DeckNode)
for (child in children) yieldAll(child)
}.iterator()

/** Convert the tree into a flat list, where matching decks and the children/parents
* are included. Decks inside collapsed decks are not considered. */
fun filterAndFlatten(filter: CharSequence?): List<DeckNode> {
Expand Down

0 comments on commit 2e33db4

Please sign in to comment.