@@ -25,7 +25,6 @@ import androidx.lifecycle.viewModelScope
2525import anki.card_rendering.EmptyCardsReport
2626import anki.collection.OpChanges
2727import anki.decks.SetDeckCollapsedRequest
28- import anki.i18n.GeneratedTranslations
2928import anki.sync.SyncStatusResponse
3029import com.ichi2.anki.CollectionManager
3130import com.ichi2.anki.CollectionManager.TR
@@ -203,11 +202,7 @@ class DeckPickerViewModel :
203202 // to match and avoid unnecessary scrolls in `renderPage()`.
204203 focusedDeck = Consts .DEFAULT_DECK_ID
205204
206- events.emit(
207- UiEvent .DeckDeleted (
208- DeckDeletionResult (deckName = deckName, cardsDeleted = changes.count),
209- ),
210- )
205+ events.emit(UiEvent .DeckDeleted (deckName = deckName, cardsDeleted = changes.count))
211206 }
212207
213208 /* *
@@ -245,7 +240,7 @@ class DeckPickerViewModel :
245240 }
246241 }
247242 val result = undoableOp { removeCardsAndOrphanedNotes(toDelete) }
248- events.emit(UiEvent .EmptyCardsDeleted (EmptyCardsResult ( cardsDeleted = result.count) ))
243+ events.emit(UiEvent .EmptyCardsDeleted (cardsDeleted = result.count))
249244 }
250245
251246 // TODO: move withProgress to the ViewModel, so we don't return 'Job'
@@ -447,11 +442,9 @@ class DeckPickerViewModel :
447442 }
448443 events.emit(
449444 UiEvent .CreateShortcut (
450- ShortcutData (
451- deckId = deckId,
452- shortLabel = shortLabel,
453- longLabel = longLabel,
454- ),
445+ deckId = deckId,
446+ shortLabel = shortLabel,
447+ longLabel = longLabel,
455448 ),
456449 )
457450 }
@@ -608,46 +601,8 @@ class DeckPickerViewModel :
608601 }
609602}
610603
611- /* * Result of [DeckPickerViewModel.deleteDeck] */
612- data class DeckDeletionResult (
613- val deckName : String ,
614- val cardsDeleted : Int ,
615- ) {
616- /* *
617- * @see GeneratedTranslations.browsingCardsDeletedWithDeckname
618- */
619- // TODO: Somewhat questionable meaning: {count} cards deleted from {deck_name}.
620- @CheckResult
621- fun toHumanReadableString () =
622- TR .browsingCardsDeletedWithDeckname(
623- count = cardsDeleted,
624- deckName = deckName,
625- )
626- }
627-
628- /* * Result of [DeckPickerViewModel.deleteEmptyCards] */
629- data class EmptyCardsResult (
630- val cardsDeleted : Int ,
631- ) {
632- /* *
633- * @see GeneratedTranslations.emptyCardsDeletedCount */
634- @CheckResult
635- fun toHumanReadableString () = TR .emptyCardsDeletedCount(cardsDeleted)
636- }
637-
638604fun DeckNode.onlyHasDefaultDeck () = children.singleOrNull()?.did == DEFAULT_DECK_ID
639605
640- /* *
641- * Data for creating a deck shortcut
642- * @param shortLabel the basename of the deck (e.g., "Verbs" for "Language::English::Verbs")
643- * @param longLabel the full deck name (e.g., "Language::English::Verbs")
644- */
645- data class ShortcutData (
646- val deckId : DeckId ,
647- val shortLabel : String ,
648- val longLabel : String ,
649- )
650-
651606enum class SyncIconState {
652607 Normal ,
653608 PendingChanges ,
@@ -656,18 +611,36 @@ enum class SyncIconState {
656611}
657612
658613/* *
659- * One-shot UI events emitted by [DeckPickerViewModel].
660- *
661- * @see com.ichi2.anki.ui.UiEventHost
614+ * One-shot UI events emitted by [DeckPickerViewModel] over a single channel and
615+ * collected by [DeckPicker]. Use for navigation, snackbars, dialogs, errors —
616+ * not for ongoing state (use a `StateFlow` for that).
662617 */
663618sealed interface UiEvent {
619+ /* * A deck (and possibly child decks) was deleted. @see DeckPickerViewModel.deleteDeck */
664620 data class DeckDeleted (
665- val result : DeckDeletionResult ,
666- ) : UiEvent
621+ val deckName : String ,
622+ val cardsDeleted : Int ,
623+ ) : UiEvent {
624+ /* *
625+ * @see anki.i18n.GeneratedTranslations.browsingCardsDeletedWithDeckname
626+ */
627+ // TODO: Somewhat questionable meaning: {count} cards deleted from {deck_name}.
628+ @CheckResult
629+ fun toHumanReadableString () =
630+ TR .browsingCardsDeletedWithDeckname(
631+ count = cardsDeleted,
632+ deckName = deckName,
633+ )
634+ }
667635
636+ /* * Empty cards were removed. @see DeckPickerViewModel.deleteEmptyCards */
668637 data class EmptyCardsDeleted (
669- val result : EmptyCardsResult ,
670- ) : UiEvent
638+ val cardsDeleted : Int ,
639+ ) : UiEvent {
640+ /* * @see anki.i18n.GeneratedTranslations.emptyCardsDeletedCount */
641+ @CheckResult
642+ fun toHumanReadableString () = TR .emptyCardsDeletedCount(cardsDeleted)
643+ }
671644
672645 data class Navigate (
673646 val destination : Destination ,
@@ -681,8 +654,15 @@ sealed interface UiEvent {
681654 val deckId : DeckId ,
682655 ) : UiEvent
683656
657+ /* *
658+ * Request to create a launcher shortcut for a deck.
659+ * @param shortLabel the basename of the deck (e.g., "Verbs" for "Language::English::Verbs")
660+ * @param longLabel the full deck name (e.g., "Language::English::Verbs")
661+ */
684662 data class CreateShortcut (
685- val data : ShortcutData ,
663+ val deckId : DeckId ,
664+ val shortLabel : String ,
665+ val longLabel : String ,
686666 ) : UiEvent
687667
688668 data class DisableShortcuts (
0 commit comments