Skip to content

Commit bd949c1

Browse files
committed
feat(card-browser): snackbar on sort type change
Prep for issue 17732 Assisted-by: Claude Ops 4.7
1 parent 8d32bd5 commit bd949c1

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,6 +1009,22 @@ class CardBrowserFragment :
10091009
sortChip?.scaleY = if (reverse == false || reverse == null) 1.0f else -1.0f
10101010
}
10111011

1012+
/** Displays a snackbar: Sort by Card Type · A-Z*/
1013+
fun onSortTypeChanged(notification: SortChangeNotification) {
1014+
val (title, subtitle) =
1015+
when (notification) {
1016+
is SortChangeNotification.NoOrdering ->
1017+
getString(R.string.card_browser_order_no_sorting_title) to null
1018+
is SortChangeNotification.CollectionOrdering -> {
1019+
val subtitleRes = notification.type.humanReadableExplanation(descending = notification.reverse)
1020+
getString(R.string.card_browser_order_snackbar_sort_by, notification.columnLabel) to
1021+
subtitleRes?.let(::getString)
1022+
}
1023+
}
1024+
val text = if (subtitle != null) "$title · $subtitle" else title
1025+
showSnackbar(text, Snackbar.LENGTH_SHORT)
1026+
}
1027+
10121028
activityViewModel.flowOfReverseDirection.launchCollectionInLifecycleScope(::reverseDirectionChanged)
10131029
activityViewModel.flowOfIsTruncated.launchCollectionInLifecycleScope(::onIsTruncatedChanged)
10141030
activityViewModel.flowOfSelectedRows.launchCollectionInLifecycleScope(::onSelectedRowsChanged)
@@ -1028,6 +1044,7 @@ class CardBrowserFragment :
10281044
searchViewModel.submittedSearchFlow.filterNotNull().launchCollectionInLifecycleScope(::onSearchSubmitted)
10291045
searchViewModel.userMessageFlow.filterNotNull().launchCollectionInLifecycleScope(::onUserMessage)
10301046
activityViewModel.searchRequestFlow.launchCollectionInLifecycleScope(::onSearchRequestUpdated)
1047+
activityViewModel.flowOfSortTypeChanged.launchCollectionInLifecycleScope(::onSortTypeChanged)
10311048
}
10321049

10331050
private fun setupFragmentResultListeners() {

AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserViewModel.kt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,9 @@ class CardBrowserViewModel(
198198
*/
199199
val flowOfReverseDirection: MutableStateFlow<ReverseDirection?> = MutableStateFlow(null)
200200

201+
/** Emits each time the user changes the sort order, with data for a snackbar */
202+
val flowOfSortTypeChanged = MutableSharedFlow<SortChangeNotification>()
203+
201204
/**
202205
* A map from column backend key to backend column definition
203206
*
@@ -865,9 +868,31 @@ class CardBrowserViewModel(
865868
}
866869
}
867870

871+
flowOfSortTypeChanged.emit(buildSortChangeNotification(sortType))
872+
868873
launchSearchForCards()
869874
}
870875

876+
private fun buildSortChangeNotification(sortType: SortType): SortChangeNotification =
877+
when (sortType) {
878+
is SortType.NoOrdering -> SortChangeNotification.NoOrdering
879+
is SortType.CollectionOrdering -> {
880+
val columnLabel =
881+
flowOfAllColumns.value[sortType.key.value]?.getLabel(cardsOrNotes)
882+
?: sortType.key.value
883+
val type =
884+
runCatching { CardBrowserColumn.fromColumnKey(sortType.key.value) }
885+
.getOrNull()
886+
?.type(cardsOrNotes)
887+
?: ColumnType.UNSPECIFIED
888+
SortChangeNotification.CollectionOrdering(
889+
columnLabel = columnLabel,
890+
type = type,
891+
reverse = sortType.reverse,
892+
)
893+
}
894+
}
895+
871896
/**
872897
* Updates the backend with a new collection of columns
873898
*
@@ -1643,3 +1668,22 @@ data class ColumnHeading(
16431668
val label: String,
16441669
val ankiColumnKey: String,
16451670
) : Parcelable
1671+
1672+
/**
1673+
* Data needed to show a snackbar when the sort order is changed
1674+
*/
1675+
sealed interface SortChangeNotification {
1676+
/** [SortType.NoOrdering] was selected */
1677+
data object NoOrdering : SortChangeNotification
1678+
1679+
/**
1680+
* @param columnLabel The localized label for the column
1681+
* @param type The data type of the column. Used to explain the sort direction
1682+
* @param reverse Whether the sort is ascending/descending
1683+
*/
1684+
data class CollectionOrdering(
1685+
val columnLabel: String,
1686+
val type: ColumnType,
1687+
val reverse: Boolean,
1688+
) : SortChangeNotification
1689+
}

AnkiDroid/src/main/res/values/07-cardbrowser.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<!-- Sort Order -->
102102
<string name="card_browser_order_no_sorting_title" comment="Title of the 'no sorting' row in the Choose Display Order bottom sheet">No sorting</string>
103103
<string name="card_browser_order_no_sorting_subtitle" comment="Subtitle for the 'no sorting' row noting that no-sort is faster than sorted queries">Faster</string>
104+
<string name="card_browser_order_snackbar_sort_by" comment="Snackbar shown after sort changes. %1$s is the column name (e.g. 'Card Type')">Sort by %1$s</string>
104105

105106
<string name="card_browser_order_subtitle_text_ascending" comment="Sort direction subtitle for text columns when ascending (A before Z)">A–Z</string>
106107
<string name="card_browser_order_subtitle_text_descending" comment="Sort direction subtitle for text columns when descending (Z before A)">Z–A</string>

0 commit comments

Comments
 (0)