Skip to content

Commit b825f75

Browse files
BrayanDSOlukstbit
authored andcommitted
feat(study screen): scroll to card with the Browser command
1 parent 9b75f4b commit b825f75

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import android.content.Context
2020
import android.content.Intent
2121
import com.ichi2.anki.AnkiDroidApp
2222
import com.ichi2.anki.CardBrowser
23+
import com.ichi2.anki.libanki.CardId
2324
import com.ichi2.anki.libanki.DeckId
2425
import com.ichi2.anki.utils.Destination
2526

@@ -35,4 +36,24 @@ sealed interface BrowserDestination : Destination {
3536
return Intent(context, CardBrowser::class.java)
3637
}
3738
}
39+
40+
/**
41+
* Opens the [CardBrowser] with the specified deck selected,
42+
* and automatically scrolls to [cardId] if the card is present on the deck.
43+
*/
44+
data class ToCard(
45+
val deckId: DeckId,
46+
val cardId: CardId,
47+
) : BrowserDestination {
48+
override fun toIntent(context: Context): Intent {
49+
AnkiDroidApp.instance.sharedPrefsLastDeckIdRepository.lastDeckId = deckId
50+
return Intent(context, CardBrowser::class.java).apply {
51+
putExtra(EXTRA_CARD_ID_KEY, cardId)
52+
}
53+
}
54+
55+
companion object {
56+
const val EXTRA_CARD_ID_KEY = "cardId"
57+
}
58+
}
3859
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,7 @@ class CardBrowserFragment :
465465
activityViewModel.flowOfToggleSelectionState.launchCollectionInLifecycleScope(::onToggleSelectionStateUpdated)
466466
viewModel.flowOfSearchForDecks.launchCollectionInLifecycleScope(::onSearchForDecks)
467467
activityViewModel.flowOfDeckSelection.launchCollectionInLifecycleScope(::onDeckChanged)
468+
activityViewModel.flowOfScrollRequest.launchCollectionInLifecycleScope(::autoScrollTo)
468469
}
469470

470471
private fun setupFragmentResultListeners() {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ package com.ichi2.anki.browser
1818

1919
import android.content.Intent
2020
import androidx.annotation.CheckResult
21+
import com.ichi2.anki.common.utils.ext.getLongExtra
22+
import com.ichi2.anki.libanki.CardId
2123

2224
/** How the [com.ichi2.anki.CardBrowser] can be launched */
2325
sealed interface CardBrowserLaunchOptions {
@@ -34,6 +36,10 @@ sealed interface CardBrowserLaunchOptions {
3436
data class SystemContextMenu(
3537
val search: CharSequence,
3638
) : CardBrowserLaunchOptions
39+
40+
data class ScrollToCard(
41+
val cardId: CardId,
42+
) : CardBrowserLaunchOptions
3743
}
3844

3945
@CheckResult
@@ -48,6 +54,10 @@ fun Intent.toCardBrowserLaunchOptions(): CardBrowserLaunchOptions? {
4854
return CardBrowserLaunchOptions.SearchQueryJs(it, getBooleanExtra("all_decks", false))
4955
}
5056

57+
getLongExtra(BrowserDestination.ToCard.EXTRA_CARD_ID_KEY)?.let { cardId ->
58+
return CardBrowserLaunchOptions.ScrollToCard(cardId)
59+
}
60+
5161
// Maybe we were called from ACTION_PROCESS_TEXT
5262
if (Intent.ACTION_PROCESS_TEXT == action) {
5363
val search = getCharSequenceExtra(Intent.EXTRA_PROCESS_TEXT)

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ class CardBrowserViewModel(
168168
// card that was clicked (not marked)
169169
var currentCardId: CardId = 0
170170

171+
var cardIdToBeScrolledTo: CardId? = null
172+
private set
173+
174+
val flowOfScrollRequest = MutableSharedFlow<RowSelection>()
175+
171176
private val sortTypeFlow = MutableStateFlow(SortType.NO_SORTING)
172177
val order get() = sortTypeFlow.value
173178

@@ -402,6 +407,9 @@ class CardBrowserViewModel(
402407
is CardBrowserLaunchOptions.DeepLink -> {
403408
flowOfSearchTerms.value = options.search
404409
}
410+
is CardBrowserLaunchOptions.ScrollToCard -> {
411+
cardIdToBeScrolledTo = options.cardId
412+
}
405413
null -> {}
406414
}
407415

@@ -1175,6 +1183,7 @@ class CardBrowserViewModel(
11751183
* @see com.ichi2.anki.searchForRows
11761184
*/
11771185
@NeedsTest("Invalid searches are handled. For instance: 'and'")
1186+
@NeedsTest("card id is scrolled")
11781187
fun launchSearchForCards(cardOrNoteIdsToSelect: List<CardOrNoteId> = emptyList()) {
11791188
if (!initCompleted) return
11801189

@@ -1204,6 +1213,20 @@ class CardBrowserViewModel(
12041213
flowOfSearchState.emit(SearchState.Completed)
12051214
selectUnvalidatedRowIds(cardOrNoteIdsToSelect)
12061215
}
1216+
1217+
viewModelScope.launch {
1218+
searchJob?.join()
1219+
cardIdToBeScrolledTo?.let { targetId ->
1220+
val rowId =
1221+
if (cardsOrNotes == CARDS) {
1222+
CardOrNoteId(targetId)
1223+
} else {
1224+
val nid = withCol { getCard(targetId) }.nid
1225+
CardOrNoteId(nid)
1226+
}
1227+
flowOfScrollRequest.emit(RowSelection(rowId, topOffset = 0))
1228+
}
1229+
}
12071230
}
12081231
}
12091232

AnkiDroid/src/main/java/com/ichi2/anki/ui/windows/reviewer/ReviewerViewModel.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,8 @@ class ReviewerViewModel(
291291

292292
private suspend fun emitBrowseDestination() {
293293
val deckId = withCol { decks.getCurrentId() }
294-
val destination = BrowserDestination.ToDeck(deckId)
294+
val cardId = currentCard.await().id
295+
val destination = BrowserDestination.ToCard(deckId, cardId)
295296
Timber.i("Launching 'browse options' for deck %d", deckId)
296297
destinationFlow.emit(destination)
297298
}

0 commit comments

Comments
 (0)