@@ -70,15 +70,12 @@ import com.ichi2.anki.model.CardStateFilter
7070import com.ichi2.anki.model.CardsOrNotes
7171import com.ichi2.anki.model.CardsOrNotes.CARDS
7272import com.ichi2.anki.model.CardsOrNotes.NOTES
73- import com.ichi2.anki.model.LegacySortType
7473import com.ichi2.anki.model.SelectableDeck
7574import com.ichi2.anki.model.SortType
7675import com.ichi2.anki.observability.ChangeManager
7776import com.ichi2.anki.observability.undoableOp
7877import com.ichi2.anki.pages.CardInfoDestination
7978import com.ichi2.anki.preferences.SharedPreferencesProvider
80- import com.ichi2.anki.settings.Prefs
81- import com.ichi2.anki.settings.PrefsRepository
8279import com.ichi2.anki.utils.ext.currentCardBrowse
8380import com.ichi2.anki.utils.ext.getCardOrNull
8481import com.ichi2.anki.utils.ext.ignoreAccentsInSearch
@@ -94,7 +91,6 @@ import kotlinx.coroutines.flow.SharingStarted
9491import kotlinx.coroutines.flow.StateFlow
9592import kotlinx.coroutines.flow.combine
9693import kotlinx.coroutines.flow.combineTransform
97- import kotlinx.coroutines.flow.filter
9894import kotlinx.coroutines.flow.flattenMerge
9995import kotlinx.coroutines.flow.flowOf
10096import kotlinx.coroutines.flow.launchIn
@@ -117,6 +113,11 @@ import java.util.Collections
117113import kotlin.math.max
118114import kotlin.math.min
119115
116+ /* *
117+ * Whether the current sort is reversed (descending). `true` if reversed.
118+ */
119+ typealias ReverseDirection = Boolean
120+
120121// TODO: move the tag computation to ViewModel
121122
122123/* *
@@ -129,7 +130,6 @@ import kotlin.math.min
129130 * @param isFragmented `true` if a NoteEditor side panel is displayed (x-large displays)
130131 * @param manualInit test-only: defer `initCompleted` until `manualInit()` is called
131132 */
132- @NeedsTest(" reverseDirectionFlow/sortTypeFlow are not updated on .launch { }" )
133133@NeedsTest(" columIndex1/2 config is not not updated on init" )
134134@NeedsTest(" 13442: selected deck is not changed, as this affects the reviewer" )
135135@NeedsTest(" search is called after launch()" )
@@ -143,8 +143,6 @@ class CardBrowserViewModel(
143143 private val manualInit : Boolean = false ,
144144) : ViewModel(),
145145 SharedPreferencesProvider by preferences {
146- private val prefs: PrefsRepository = Prefs
147-
148146 // TODO: abstract so we can use a `Context` and `pref_display_filenames_in_browser_key`
149147 val showMediaFilenames = sharedPrefs().getBoolean(" card_browser_show_media_filenames" , false )
150148
@@ -193,11 +191,12 @@ class CardBrowserViewModel(
193191
194192 val flowOfScrollRequest = MutableSharedFlow <RowSelection >()
195193
196- private val sortTypeFlow = MutableStateFlow (LegacySortType .NO_SORTING )
197- val order get() = sortTypeFlow.value
198-
199- val reverseDirectionFlow = MutableStateFlow (ReverseDirection (orderAsc = false ))
200- val orderAsc get() = reverseDirectionFlow.value.orderAsc
194+ /* *
195+ * Whether the current sort is reversed (descending).
196+ *
197+ * `null` when no sort is applied ([SortType.NoOrdering]).
198+ */
199+ val flowOfReverseDirection: MutableStateFlow <ReverseDirection ?> = MutableStateFlow (null )
201200
202201 /* *
203202 * A map from column backend key to backend column definition
@@ -498,16 +497,6 @@ class CardBrowserViewModel(
498497 launchSearchForCards(cardOrNoteIdsToSelect = ids)
499498 }.launchIn(viewModelScope)
500499
501- reverseDirectionFlow
502- .ignoreValuesFromViewModelLaunch()
503- .onEach { newValue -> withCol { newValue.updateConfig(config) } }
504- .launchIn(viewModelScope)
505-
506- sortTypeFlow
507- .ignoreValuesFromViewModelLaunch()
508- .onEach { sortType -> withCol { sortType.save(config, prefs) } }
509- .launchIn(viewModelScope)
510-
511500 flowOfCardsOrNotes
512501 .onEach { cardsOrNotes ->
513502 Timber .d(" loading columns for %s mode" , cardsOrNotes)
@@ -525,10 +514,8 @@ class CardBrowserViewModel(
525514 val cardsOrNotes = withCol { CardsOrNotes .fromCollection(this @withCol) }
526515 flowOfCardsOrNotes.update { cardsOrNotes }
527516
528- withCol {
529- sortTypeFlow.update { LegacySortType .fromCol(config, cardsOrNotes, prefs) }
530- reverseDirectionFlow.update { ReverseDirection .fromConfig(config) }
531- }
517+ flowOfReverseDirection.update { (SortType .build(cardsOrNotes) as ? SortType .CollectionOrdering )?.reverse }
518+
532519 Timber .i(" initCompleted" )
533520
534521 if (! manualInit) {
@@ -869,41 +856,17 @@ class CardBrowserViewModel(
869856 viewModelScope.launch {
870857 Timber .i(" setting sort type: %s" , sortType)
871858
872- // Temporarily update legacy flows
873- sortTypeFlow.update { sortType.toLegacy() }
874- sortType.toLegacyReverse()?.let { newValue ->
875- reverseDirectionFlow.update { newValue }
876- }
877-
878859 sortType.save(cardsOrNotes)
879860
880- launchSearchForCards()
881- }
882-
883- fun changeCardOrder (which : LegacySortType ) {
884- val changeType =
885- when {
886- which != order -> ChangeCardOrder .OrderChange (which)
887- // if the same element is selected again, reverse the order
888- which != LegacySortType .NO_SORTING -> ChangeCardOrder .DirectionChange
889- else -> null
890- } ? : return
891-
892- Timber .i(" updating order: %s" , changeType)
893-
894- when (changeType) {
895- is ChangeCardOrder .OrderChange -> {
896- sortTypeFlow.update { which }
897- reverseDirectionFlow.update { ReverseDirection (orderAsc = false ) }
898- launchSearchForCards()
899- }
900- ChangeCardOrder .DirectionChange -> {
901- reverseDirectionFlow.update { ReverseDirection (orderAsc = ! orderAsc) }
902- cards.reverse()
903- viewModelScope.launch { flowOfSearchState.emit(SearchState .Completed ) }
861+ flowOfReverseDirection.update {
862+ when (sortType) {
863+ is SortType .NoOrdering -> null
864+ is SortType .CollectionOrdering -> sortType.reverse
865+ }
904866 }
867+
868+ launchSearchForCards()
905869 }
906- }
907870
908871 /* *
909872 * Updates the backend with a new collection of columns
@@ -1116,9 +1079,6 @@ class CardBrowserViewModel(
11161079 return if (searchAdded) SaveSearchResult .SUCCESS else SaveSearchResult .ALREADY_EXISTS
11171080 }
11181081
1119- /* * Ignores any values before [initCompleted] is set */
1120- private fun <T > Flow<T>.ignoreValuesFromViewModelLaunch (): Flow <T > = this .filter { initCompleted }
1121-
11221082 /* *
11231083 * Sets the filter query (legacy): 'is:suspended'
11241084 */
@@ -1316,7 +1276,7 @@ class CardBrowserViewModel(
13161276 ) {
13171277 val searchString = withCol { searchRequestFlow.value.toSearchString().getOrThrow() }
13181278 flowOfSearchState.emit(SearchState .Searching )
1319- val sortOrder = order.toSortOrder ()
1279+ val sortOrder = SortType .buildSortOrder ()
13201280 Timber .d(" performing search: '%s'; order: %s" , searchString, sortOrder)
13211281 val cards = com.ichi2.anki.searchForRows(searchString, sortOrder, cardsOrNotes)
13221282 Timber .d(" Search returned %d card(s)" , cards.size)
@@ -1498,14 +1458,6 @@ class CardBrowserViewModel(
14981458 val count : Int ,
14991459 )
15001460
1501- private sealed interface ChangeCardOrder {
1502- data class OrderChange (
1503- val sortType : LegacySortType ,
1504- ) : ChangeCardOrder
1505-
1506- data object DirectionChange : ChangeCardOrder
1507- }
1508-
15091461 sealed class ChangeMultiSelectMode : Parcelable {
15101462 val resultedInMultiSelect: Boolean get() =
15111463 when (this ) {
0 commit comments