diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt index 0ba062dcc3d4..832c951cee91 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AbstractFlashcardViewer.kt @@ -708,7 +708,7 @@ abstract class AbstractFlashcardViewer : return super.onKeyUp(keyCode, event) } - public override val currentCardId: CardId? get() = currentCard?.id + open val currentCardId: CardId? get() = currentCard?.id private fun processHardwareButtonScroll( keyCode: Int, diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt index a51ad64536e6..d0bfa9850abe 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/AnkiDroidJsAPI.kt @@ -18,7 +18,6 @@ package com.ichi2.anki import android.content.Context -import android.content.Intent import androidx.lifecycle.lifecycleScope import anki.scheduler.CardAnswer.Rating import com.github.zafarkhaja.semver.Version @@ -36,6 +35,8 @@ import com.ichi2.anki.CollectionManager.withCol import com.ichi2.anki.browser.search.SearchString import com.ichi2.anki.cardviewer.ViewerCommand import com.ichi2.anki.common.annotations.NeedsTest +import com.ichi2.anki.common.destinations.BrowserDestination +import com.ichi2.anki.common.destinations.navigate import com.ichi2.anki.common.utils.android.showThemedToast import com.ichi2.anki.common.utils.ext.stringIterable import com.ichi2.anki.libanki.Card @@ -380,12 +381,7 @@ open class AnkiDroidJsAPI( "ttsStop" -> convertToByteArray(apiContract, talker.stop()) "searchCard" -> { - val intent = - Intent(context, CardBrowser::class.java).apply { - putExtra("currentCard", currentCard.id) - putExtra("search_query", apiParams) - } - activity.startActivity(intent) + with(activity) { navigate(BrowserDestination.Search(query = apiParams, allDecks = false)) } convertToByteArray(apiContract, true) } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt b/AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt index 091656426894..6973f3e08884 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/IntentHandler.kt @@ -16,6 +16,8 @@ import androidx.core.content.IntentCompat import androidx.work.WorkManager import com.ichi2.anki.common.annotations.NeedsTest import com.ichi2.anki.common.coroutines.applicationScope +import com.ichi2.anki.common.destinations.BrowserDestination +import com.ichi2.anki.common.destinations.navigate import com.ichi2.anki.common.preferences.sharedPrefs import com.ichi2.anki.common.storage.CollectionHelper import com.ichi2.anki.common.storage.StorageDecision @@ -154,13 +156,15 @@ class IntentHandler : AbstractIntentHandler() { */ private fun handleBrowserIntent(intent: Intent) { Timber.i("Handling intent to open the Card Browser") - val browserIntent = - Intent(this, CardBrowser::class.java).apply { - action = Intent.ACTION_VIEW - data = intent.data + val search = intent.data?.getQueryParameter("search") + val destination = + if (search != null) { + BrowserDestination.Search(query = search, allDecks = false) + } else { + BrowserDestination.Open } // 'back' should close this activity. - startActivity(browserIntent) + navigate(destination) finish() } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/NavigationDrawerActivity.kt b/AnkiDroid/src/main/java/com/ichi2/anki/NavigationDrawerActivity.kt index e18f8a9ad10e..c95a80f27800 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/NavigationDrawerActivity.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/NavigationDrawerActivity.kt @@ -37,13 +37,15 @@ import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.IntentHandler.Companion.grantedStoragePermissions import com.ichi2.anki.NoteEditorFragment.Companion.NoteEditorCaller import com.ichi2.anki.common.android.animationEnabled +import com.ichi2.anki.common.destinations.BrowserDestination +import com.ichi2.anki.common.destinations.DeferredNavigation import com.ichi2.anki.common.destinations.PreferencesDestination import com.ichi2.anki.common.destinations.StatisticsDestination import com.ichi2.anki.common.destinations.navigate +import com.ichi2.anki.common.destinations.toIntent import com.ichi2.anki.common.preferences.sharedPrefs import com.ichi2.anki.common.utils.android.HandlerUtils import com.ichi2.anki.dialogs.help.HelpDialog -import com.ichi2.anki.libanki.CardId import com.ichi2.anki.utils.ext.showDialogFragment import com.ichi2.anki.workarounds.FullDraggableContainerFix import com.ichi2.utils.IntentUtil @@ -384,11 +386,7 @@ abstract class NavigationDrawerActivity( } protected fun openCardBrowser() { - val intent = Intent(this@NavigationDrawerActivity, CardBrowser::class.java) - if (currentCardId != null) { - intent.putExtra("currentCard", currentCardId) - } - startActivity(intent) + navigate(BrowserDestination.Open) } /** @@ -406,10 +404,6 @@ abstract class NavigationDrawerActivity( preferencesLauncher.navigate(PreferencesDestination.Root) } - // Override this to specify a specific card id - protected open val currentCardId: CardId? - get() = null - /** * Hides the navigation drawer indicator (hamburger icon) and any back arrows * from the toolbar. Used when bottom navigation is active. @@ -523,7 +517,7 @@ abstract class NavigationDrawerActivity( .build() // CardBrowser Shortcut - val intentCardBrowser = Intent(context, CardBrowser::class.java) + val intentCardBrowser = with(DeferredNavigation) { BrowserDestination.Open.toIntent() } intentCardBrowser.action = Intent.ACTION_VIEW intentCardBrowser.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK val cardBrowserShortcut = diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserDestination.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserDestination.kt index 466f04fb9655..70efdbacf537 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserDestination.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/BrowserDestination.kt @@ -10,6 +10,7 @@ import com.ichi2.anki.common.destinations.BrowserDestination /** Builds the [Intent] that launches [CardBrowser] for this destination. */ fun BrowserDestination.toIntent(context: Context): Intent = when (this) { + is BrowserDestination.Open -> Intent(context, CardBrowser::class.java) is BrowserDestination.ToDeck -> Intent(context, CardBrowser::class.java).apply { putExtra(CardBrowserViewModel.EXTRA_DECK_ID, deckId) diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/EmptyCardsDialogFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/EmptyCardsDialogFragment.kt index df2559c21604..a6f60f2599ba 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/EmptyCardsDialogFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/dialogs/EmptyCardsDialogFragment.kt @@ -5,8 +5,6 @@ package com.ichi2.anki.dialogs import android.app.Activity import android.app.Dialog -import android.content.Context -import android.content.Intent import android.content.res.Configuration import android.content.res.Configuration.ORIENTATION_LANDSCAPE import android.graphics.Insets @@ -36,7 +34,8 @@ import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.DeckPicker import com.ichi2.anki.R import com.ichi2.anki.analytics.AnalyticsDialogFragment -import com.ichi2.anki.browser.CardBrowserViewModel +import com.ichi2.anki.common.destinations.BrowserDestination +import com.ichi2.anki.common.destinations.navigate import com.ichi2.anki.databinding.DialogEmptyCardsBinding import com.ichi2.anki.dialogs.EmptyCardsUiState.EmptyCardsSearchFailure import com.ichi2.anki.dialogs.EmptyCardsUiState.EmptyCardsSearchResult @@ -165,7 +164,7 @@ class EmptyCardsDialogFragment : AnalyticsDialogFragment() { AnkiNidTag.parseFromReport(spannableReport).forEach { tag -> // make nid clickable spannableReport.setSpan( - BrowserSearchByNidSpan(requireContext(), tag.nid), + BrowserSearchByNidSpan(requireActivity(), tag.nid), tag.matchedNid.range.first, tag.matchedNid.range.last + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE, @@ -236,14 +235,11 @@ class EmptyCardsDialogFragment : AnalyticsDialogFragment() { * @see CardBrowser */ private class BrowserSearchByNidSpan( - val context: Context, + val activity: Activity, val nid: NoteId, ) : ClickableSpan() { override fun onClick(widget: View) { - val browserSearchIntent = Intent(context, CardBrowser::class.java) - browserSearchIntent.putExtra(CardBrowserViewModel.EXTRA_SEARCH_QUERY, "nid:$nid") - browserSearchIntent.putExtra(CardBrowserViewModel.EXTRA_ALL_DECKS, true) - context.startActivity(browserSearchIntent) + with(activity) { navigate(BrowserDestination.Search(query = "nid:$nid", allDecks = true)) } } } diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/filtered/FilteredDeckOptionsFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/filtered/FilteredDeckOptionsFragment.kt index 4be6d9eccb56..70f65d2ef619 100644 --- a/AnkiDroid/src/main/java/com/ichi2/anki/filtered/FilteredDeckOptionsFragment.kt +++ b/AnkiDroid/src/main/java/com/ichi2/anki/filtered/FilteredDeckOptionsFragment.kt @@ -25,10 +25,10 @@ import androidx.lifecycle.repeatOnLifecycle import com.google.android.material.materialswitch.MaterialSwitch import com.google.android.material.textfield.TextInputEditText import com.google.android.material.textfield.TextInputLayout -import com.ichi2.anki.CardBrowser import com.ichi2.anki.CollectionManager.TR import com.ichi2.anki.R -import com.ichi2.anki.browser.CardBrowserViewModel +import com.ichi2.anki.common.destinations.BrowserDestination +import com.ichi2.anki.common.destinations.navigate import com.ichi2.anki.databinding.FragmentFilteredDeckOptionsBinding import com.ichi2.anki.dialogs.DiscardChangesDialog import com.ichi2.anki.libanki.DeckId @@ -138,9 +138,7 @@ class FilteredDeckOptionsFragment : Fragment(R.layout.fragment_filtered_deck_opt return@collect } if (state.browserQuery != null) { - val browserSearchIntent = Intent(context, CardBrowser::class.java) - browserSearchIntent.putExtra(CardBrowserViewModel.EXTRA_SEARCH_QUERY, state.browserQuery) - startActivity(browserSearchIntent) + navigate(BrowserDestination.Search(query = state.browserQuery, allDecks = false)) viewModel.clearSearchInBrowser() } } diff --git a/anki-common/src/main/kotlin/com/ichi2/anki/common/destinations/BrowserDestination.kt b/anki-common/src/main/kotlin/com/ichi2/anki/common/destinations/BrowserDestination.kt index db309116a33a..7e7a41ac2f81 100644 --- a/anki-common/src/main/kotlin/com/ichi2/anki/common/destinations/BrowserDestination.kt +++ b/anki-common/src/main/kotlin/com/ichi2/anki/common/destinations/BrowserDestination.kt @@ -6,8 +6,10 @@ import com.ichi2.anki.libanki.CardId import com.ichi2.anki.libanki.DeckId /** Opens the Card Browser. */ -// TODO: A number of destination are undefined - grep for CardBrowser::class (#20558) sealed class BrowserDestination : Destination() { + /** Opens the Card Browser on the selected deck. */ + data object Open : BrowserDestination() + /** Opens the Card Browser scoped to [deckId]. */ data class ToDeck( val deckId: DeckId,