diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt
index 1fe5741aa6f4..8f1bdc4f2e88 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/CardBrowserFragment.kt
@@ -416,6 +416,8 @@ class CardBrowserFragment :
Timber.d("onCreateMenu()")
menuInflater.inflate(R.menu.card_browser, menu)
menu.findItem(R.id.action_search_by_flag).subMenu?.setupFlags()
+ // note: this menu item is available with and without a selection of items
+ menu.findItem(R.id.action_find_replace)?.title = TR.sentenceCase.findAndReplace
if (!useSearchView) {
searchItem = menu.findItem(R.id.action_search)
@@ -562,6 +564,10 @@ class CardBrowserFragment :
showFilteredDeckScreen()
return true
}
+ R.id.action_find_replace -> {
+ showFindAndReplaceDialog()
+ return true
+ }
}
return false
@@ -594,11 +600,8 @@ class CardBrowserFragment :
menu.findItem(R.id.action_reschedule_cards).title = TR.sentenceCase.setDueDate
menu.findItem(R.id.action_grade_now).title = TR.sentenceCase.gradeNow
- val isFindReplaceEnabled = sharedPrefs().getBoolean(getString(R.string.pref_browser_find_replace), false)
- menu.findItem(R.id.action_find_replace).apply {
- isVisible = isFindReplaceEnabled
- title = TR.browsingFindAndReplace().toSentenceCase(R.string.sentence_find_and_replace)
- }
+ // note: this menu item is available with and without a selection of items
+ menu.findItem(R.id.action_find_replace)?.title = TR.sentenceCase.findAndReplace
menu.findItem(R.id.action_undo).setupUndo()
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/browser/FindAndReplaceDialogFragment.kt b/AnkiDroid/src/main/java/com/ichi2/anki/browser/FindAndReplaceDialogFragment.kt
index c951d0fe5a4f..42e9adb11a0e 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/browser/FindAndReplaceDialogFragment.kt
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/browser/FindAndReplaceDialogFragment.kt
@@ -99,6 +99,8 @@ class FindAndReplaceDialogFragment : AnalyticsDialogFragment() {
}
}
+ // TODO maybe get rid of the html tags that come with the backend strings and handle the
+ // sentence case for TR.browsingReplaceWith()
private fun setupLabels() {
binding.labelFind.text =
HtmlCompat.fromHtml(TR.browsingFind(), HtmlCompat.FROM_HTML_MODE_LEGACY)
@@ -218,7 +220,10 @@ class FindAndReplaceDialogFragment : AnalyticsDialogFragment() {
): FindAndReplaceDialogFragment {
val file = IdsFile(context.cacheDir, noteIds, "find-replace")
return FindAndReplaceDialogFragment().apply {
- arguments = bundleOf(ARG_IDS to file)
+ arguments =
+ Bundle().apply {
+ putParcelable(ARG_IDS, file)
+ }
}
}
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt
index aaeea9119c7e..0fc74353b483 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/servicelayer/PreferenceUpgradeService.kt
@@ -137,6 +137,7 @@ object PreferenceUpgradeService {
yield(UpgradeToggleBacksideOnlyControl())
yield(UpgradeThemes())
yield(UpgradeAnswerControls())
+ yield(RemoveDeveloperFindReplace())
}
/** Returns a list of preference upgrade classes which have not been applied */
@@ -900,6 +901,14 @@ object PreferenceUpgradeService {
}
}
}
+
+ internal class RemoveDeveloperFindReplace : PreferenceUpgrade(28) {
+ override fun upgrade(preferences: SharedPreferences) {
+ preferences.edit {
+ remove("browserFindReplace")
+ }
+ }
+ }
}
}
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/ui/internationalization/SentenceCase.kt b/AnkiDroid/src/main/java/com/ichi2/anki/ui/internationalization/SentenceCase.kt
index 5b685bd8638e..cda5f0a6c38d 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/ui/internationalization/SentenceCase.kt
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/ui/internationalization/SentenceCase.kt
@@ -127,6 +127,9 @@ object SentenceCase {
context(_: Fragment)
val toggleSuspend get() = TR.browsingToggleSuspend().toSentenceCase(R.string.sentence_toggle_suspend)
+
+ context(_: Fragment)
+ val findAndReplace get() = TR.browsingFindAndReplace().toSentenceCase(R.string.sentence_find_and_replace)
}
/**
diff --git a/AnkiDroid/src/main/res/layout/fragment_find_replace.xml b/AnkiDroid/src/main/res/layout/fragment_find_replace.xml
index c32f6e6f3957..c40e8675110f 100644
--- a/AnkiDroid/src/main/res/layout/fragment_find_replace.xml
+++ b/AnkiDroid/src/main/res/layout/fragment_find_replace.xml
@@ -22,14 +22,29 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp">
+
+
+
+ app:showAsAction="never"
+ tools:title="Find and replace"
+ />
\ No newline at end of file
diff --git a/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml b/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml
index 616a3e7389b8..dc21cef52ee6 100644
--- a/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml
+++ b/AnkiDroid/src/main/res/menu/card_browser_multiselect.xml
@@ -86,8 +86,9 @@
+ app:showAsAction="never"
+ tools:title="Find and replace"
+ />
- Touch “%2$s” to confirm adding “%1$s”
Existing tag “%1$s” selected
Tag already exists
+ Consider backing up your collection from DeckPicker before using this option!
diff --git a/AnkiDroid/src/main/res/values/preferences.xml b/AnkiDroid/src/main/res/values/preferences.xml
index 0bbcf113199c..8d535ec9fbd0 100644
--- a/AnkiDroid/src/main/res/values/preferences.xml
+++ b/AnkiDroid/src/main/res/values/preferences.xml
@@ -230,7 +230,6 @@
debug_corrupt_fsrs_params
new_congrats_screen
newReviewerOptions
- browserFindReplace
newReviewReminders
devOptionsEnabledByUser
workInProgressDevOptions
diff --git a/AnkiDroid/src/main/res/xml/preferences_developer_options.xml b/AnkiDroid/src/main/res/xml/preferences_developer_options.xml
index 90dbc3a1d432..0e86a57c92fb 100644
--- a/AnkiDroid/src/main/res/xml/preferences_developer_options.xml
+++ b/AnkiDroid/src/main/res/xml/preferences_developer_options.xml
@@ -111,11 +111,6 @@
android:summary="Not compatible with side-by-side editor"
android:key="@string/dev_card_browser_search_view"
android:defaultValue="false"/>
-