From f77e2a6c560e9c3fbba07f13279def716e1ac44f Mon Sep 17 00:00:00 2001
From: Brayan Oliveira <69634269+brayandso@users.noreply.github.com>
Date: Fri, 6 Dec 2024 15:56:54 -0300
Subject: [PATCH] refactor: remove PreferencesActivity
and upgrade the SearchPreference library, which was what made the removal possible
---
AnkiDroid/src/main/AndroidManifest.xml | 9 ----
.../main/java/com/ichi2/anki/DeckPicker.kt | 4 +-
.../ichi2/anki/NavigationDrawerActivity.kt | 4 +-
.../ichi2/anki/preferences/HeaderFragment.kt | 41 +++++++++++--------
.../com/ichi2/anki/preferences/Preferences.kt | 23 +----------
.../anki/ActivityStartupUnderBackupTest.kt | 2 -
.../ichi2/anki/preferences/PreferencesTest.kt | 19 ++++-----
.../anki/preferences/SettingsSearchBarTest.kt | 11 ++---
.../java/com/ichi2/testutils/ActivityList.kt | 2 -
gradle/libs.versions.toml | 4 +-
10 files changed, 45 insertions(+), 74 deletions(-)
diff --git a/AnkiDroid/src/main/AndroidManifest.xml b/AnkiDroid/src/main/AndroidManifest.xml
index ba8d6f6cc241..c77b5ecf0e5c 100644
--- a/AnkiDroid/src/main/AndroidManifest.xml
+++ b/AnkiDroid/src/main/AndroidManifest.xml
@@ -345,15 +345,6 @@
android:name=".multimedia.MultimediaActivity"
android:configChanges="orientation|screenSize"
android:exported="false" />
-
-
-
-
-
(R.string.search_preference_key)
- .searchConfiguration
- .setFragmentContainerViewId((view.parent as? ViewGroup)?.id ?: R.id.settings_container)
+ requirePreference(R.string.search_preference_key).searchConfiguration
+ .setOnSearchListener { searchPreferenceFragment ->
+ parentFragmentManager.commit {
+ val containerId = (view.parent as? ViewGroup)?.id ?: R.id.settings_container
+ replace(containerId, searchPreferenceFragment)
+ addToBackStack(null)
+ }
+ }
}
companion object {
- fun configureSearchBar(activity: AppCompatActivity, searchConfiguration: SearchConfiguration) {
- val setDuePreferenceTitle = TR.actionsSetDueDate().toSentenceCase(activity, R.string.sentence_set_due_date)
+ fun configureSearchBar(context: Context, searchConfiguration: SearchConfiguration) {
+ val setDuePreferenceTitle = TR.actionsSetDueDate().toSentenceCase(context, R.string.sentence_set_due_date)
with(searchConfiguration) {
- setActivity(activity)
setBreadcrumbsEnabled(true)
setFuzzySearchEnabled(false)
setHistoryEnabled(true)
@@ -105,20 +112,20 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
index(R.xml.preferences_reviewing)
index(R.xml.preferences_sync)
index(R.xml.preferences_custom_sync_server)
- .addBreadcrumb(R.string.pref_cat_sync)
+ .addBreadcrumb(context.getString(R.string.pref_cat_sync))
index(R.xml.preferences_notifications)
index(R.xml.preferences_appearance)
index(R.xml.preferences_custom_buttons)
- .addBreadcrumb(R.string.pref_cat_appearance)
+ .addBreadcrumb(context.getString(R.string.pref_cat_appearance))
index(R.xml.preferences_controls)
index(R.xml.preferences_accessibility)
index(R.xml.preferences_backup_limits)
- ignorePreference(activity.getString(R.string.pref_backups_help_key))
+ ignorePreference(context.getString(R.string.pref_backups_help_key))
indexItem()
- .withKey(activity.getString(R.string.reschedule_command_key))
+ .withKey(context.getString(R.string.reschedule_command_key))
.withTitle(setDuePreferenceTitle)
.withResId(R.xml.preferences_controls)
- .addBreadcrumb(activity.getString(R.string.pref_cat_controls))
+ .addBreadcrumb(context.getString(R.string.pref_cat_controls))
.addBreadcrumb(setDuePreferenceTitle)
}
@@ -126,11 +133,11 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
// so they should be searchable based on the same conditions
/** From [HeaderFragment.onCreatePreferences] */
- if (DevOptionsFragment.isEnabled(activity)) {
+ if (DevOptionsFragment.isEnabled(context)) {
searchConfiguration.index(R.xml.preferences_dev_options)
/** From [DevOptionsFragment.initSubscreen] */
if (BuildConfig.DEBUG) {
- searchConfiguration.ignorePreference(activity.getString(R.string.dev_options_enabled_by_user_key))
+ searchConfiguration.ignorePreference(context.getString(R.string.dev_options_enabled_by_user_key))
}
}
@@ -141,16 +148,16 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
/** From [NotificationsSettingsFragment.initSubscreen] */
if (AdaptionUtil.isXiaomiRestrictedLearningDevice) {
- searchConfiguration.ignorePreference(activity.getString(R.string.pref_notifications_vibrate_key))
- searchConfiguration.ignorePreference(activity.getString(R.string.pref_notifications_blink_key))
+ searchConfiguration.ignorePreference(context.getString(R.string.pref_notifications_vibrate_key))
+ searchConfiguration.ignorePreference(context.getString(R.string.pref_notifications_blink_key))
}
/** From [AdvancedSettingsFragment.removeUnnecessaryAdvancedPrefs] */
if (!CompatHelper.hasScrollKeys()) {
- searchConfiguration.ignorePreference(activity.getString(R.string.double_scrolling_gap_key))
+ searchConfiguration.ignorePreference(context.getString(R.string.double_scrolling_gap_key))
}
- searchConfiguration.ignorePreference(activity.getString(R.string.user_actions_controls_category_key))
+ searchConfiguration.ignorePreference(context.getString(R.string.user_actions_controls_category_key))
}
/**
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt
index 24d1fe420fb8..0ef318279dc8 100644
--- a/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt
@@ -30,7 +30,6 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
-import com.bytehamster.lib.preferencesearch.SearchConfiguration
import com.bytehamster.lib.preferencesearch.SearchPreferenceResult
import com.bytehamster.lib.preferencesearch.SearchPreferenceResultListener
import com.google.android.material.appbar.AppBarLayout
@@ -113,7 +112,7 @@ class PreferencesFragment :
override fun onSearchResultClicked(result: SearchPreferenceResult) {
val fragment = getFragmentFromXmlRes(result.resourceFile) ?: return
- parentFragmentManager.popBackStack() // clear the search fragment from the backstack
+ childFragmentManager.popBackStack() // clear the search fragment from the backstack
childFragmentManager.commit {
replace(R.id.settings_container, fragment, fragment.javaClass.name)
addToBackStack(fragment.javaClass.name)
@@ -154,29 +153,11 @@ class PreferencesFragment :
replace(R.id.settings_container, initialFragment, initialFragment::class.java.name)
}
}
-}
-
-/**
- * Host activity for [PreferencesFragment].
- *
- * Only necessary because [SearchConfiguration] demands an activity that implements
- * [SearchPreferenceResultListener].
- */
-class PreferencesActivity : SingleFragmentActivity(), SearchPreferenceResultListener {
- override fun onSearchResultClicked(result: SearchPreferenceResult) {
- val fragment = supportFragmentManager.findFragmentByTag(FRAGMENT_TAG)
- if (fragment is SearchPreferenceResultListener) {
- fragment.onSearchResultClicked(result)
- }
- }
companion object {
fun getIntent(context: Context, initialFragment: KClass? = null): Intent {
val arguments = bundleOf(INITIAL_FRAGMENT_EXTRA to initialFragment?.jvmName)
- return Intent(context, PreferencesActivity::class.java).apply {
- putExtra(FRAGMENT_NAME_EXTRA, PreferencesFragment::class.jvmName)
- putExtra(FRAGMENT_ARGS_EXTRA, arguments)
- }
+ return SingleFragmentActivity.getIntent(context, PreferencesFragment::class, arguments)
}
}
}
diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt
index 0d06d84828ad..3f006ab64c4a 100644
--- a/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt
+++ b/AnkiDroid/src/test/java/com/ichi2/anki/ActivityStartupUnderBackupTest.kt
@@ -18,7 +18,6 @@ package com.ichi2.anki
import android.app.Activity
import android.os.Looper.getMainLooper
import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity
-import com.ichi2.anki.preferences.PreferencesActivity
import com.ichi2.testutils.ActivityList
import com.ichi2.testutils.ActivityList.ActivityLaunchParam
import com.ichi2.testutils.EmptyApplication
@@ -51,7 +50,6 @@ class ActivityStartupUnderBackupTest : RobolectricTest() {
fun before() {
notYetHandled(IntentHandler::class.java.simpleName, "Not working (or implemented) - inherits from Activity")
notYetHandled(IntentHandler2::class.java.simpleName, "Not working (or implemented) - inherits from Activity")
- notYetHandled(PreferencesActivity::class.java.simpleName, "Not working (or implemented) - inherits from AppCompatPreferenceActivity")
notYetHandled(FilteredDeckOptions::class.java.simpleName, "Not working (or implemented) - inherits from AppCompatPreferenceActivity")
notYetHandled(SingleFragmentActivity::class.java.simpleName, "Implemented, but the test fails because the activity throws if a specific intent extra isn't set")
notYetHandled(InstantNoteEditorActivity::class.java.simpleName, "Single instance activity so should be used")
diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt
index 2879e1b4ea0a..0ec6b99137cb 100644
--- a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt
+++ b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/PreferencesTest.kt
@@ -15,25 +15,24 @@
*/
package com.ichi2.anki.preferences
-import android.content.Context
-import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.commitNow
import androidx.test.core.app.ActivityScenario
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.ichi2.anki.R
import com.ichi2.anki.RobolectricTest
+import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.anki.preferences.HeaderFragment.Companion.getHeaderKeyForFragment
import com.ichi2.anki.preferences.PreferenceTestUtils.getAttrFromXml
import com.ichi2.libanki.exception.ConfirmModSchemaException
import com.ichi2.preferences.HeaderPreference
-import com.ichi2.testutils.getJavaMethodAsAccessible
import com.ichi2.utils.getInstanceFromClassName
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.robolectric.Robolectric
import org.robolectric.annotation.Config
import kotlin.reflect.jvm.jvmName
import kotlin.test.assertEquals
@@ -41,18 +40,14 @@ import kotlin.test.assertTrue
@RunWith(AndroidJUnit4::class)
class PreferencesTest : RobolectricTest() {
- private lateinit var preferences: PreferencesActivity
+ private lateinit var preferences: SingleFragmentActivity
@Before
override fun setUp() {
super.setUp()
- preferences = PreferencesActivity()
- val attachBaseContext = getJavaMethodAsAccessible(
- AppCompatActivity::class.java,
- "attachBaseContext",
- Context::class.java
- )
- attachBaseContext.invoke(preferences, targetContext)
+ val intent = PreferencesFragment.getIntent(targetContext)
+ preferences = Robolectric.buildActivity(SingleFragmentActivity::class.java, intent)
+ .create().start().resume().get()
}
@Test
@@ -79,7 +74,7 @@ class PreferencesTest : RobolectricTest() {
/** checks if any of the Preferences fragments throws while being created */
@Test
fun fragmentsDoNotThrowOnCreation() {
- val activityScenario = ActivityScenario.launch(PreferencesActivity.getIntent(targetContext))
+ val activityScenario = ActivityScenario.launch(PreferencesFragment.getIntent(targetContext))
activityScenario.onActivity { activity ->
PreferenceTestUtils.getAllPreferencesFragments(activity).forEach {
diff --git a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/SettingsSearchBarTest.kt b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/SettingsSearchBarTest.kt
index cbe54c7efed7..f094add5ffe0 100644
--- a/AnkiDroid/src/test/java/com/ichi2/anki/preferences/SettingsSearchBarTest.kt
+++ b/AnkiDroid/src/test/java/com/ichi2/anki/preferences/SettingsSearchBarTest.kt
@@ -19,6 +19,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.bytehamster.lib.preferencesearch.PreferenceItem
import com.bytehamster.lib.preferencesearch.SearchConfiguration
import com.ichi2.anki.RobolectricTest
+import com.ichi2.anki.SingleFragmentActivity
import com.ichi2.testutils.getJavaFieldAsAccessible
import org.hamcrest.MatcherAssert.assertThat
import org.hamcrest.Matchers.equalTo
@@ -35,11 +36,11 @@ class SettingsSearchBarTest : RobolectricTest() {
fun `All indexed XML resIDs lead to the correct fragments on getFragmentFromXmlRes`() {
// TODO try mocking the activity
val preferencesActivity = getPreferencesActivity()
- val searchConfig = SearchConfiguration(preferencesActivity)
+ val searchConfig = SearchConfiguration()
HeaderFragment.configureSearchBar(preferencesActivity, searchConfig)
// Use reflection to access some private fields
- val filesToIndexField = getJavaFieldAsAccessible(SearchConfiguration::class.java, "filesToIndex")
+ val filesToIndexField = getJavaFieldAsAccessible(SearchConfiguration::class.java, "files")
val searchItemResIdField = getJavaFieldAsAccessible(SearchConfiguration.SearchIndexItem::class.java, "resId")
val preferencesToIndexField = getJavaFieldAsAccessible(SearchConfiguration::class.java, "preferencesToIndex")
val prefItemResIdField = getJavaFieldAsAccessible(PreferenceItem::class.java, "resId")
@@ -73,9 +74,9 @@ class SettingsSearchBarTest : RobolectricTest() {
}
}
- private fun getPreferencesActivity(): PreferencesActivity {
- val intent = PreferencesActivity.getIntent(targetContext)
- return Robolectric.buildActivity(PreferencesActivity::class.java, intent)
+ private fun getPreferencesActivity(): SingleFragmentActivity {
+ val intent = PreferencesFragment.getIntent(targetContext)
+ return Robolectric.buildActivity(SingleFragmentActivity::class.java, intent)
.create().start().resume().get()
}
}
diff --git a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt
index 48da2b582864..5acd45213832 100644
--- a/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt
+++ b/AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt
@@ -41,7 +41,6 @@ import com.ichi2.anki.StudyOptionsActivity
import com.ichi2.anki.instantnoteeditor.InstantNoteEditorActivity
import com.ichi2.anki.multimedia.MultimediaActivity
import com.ichi2.anki.notetype.ManageNotetypes
-import com.ichi2.anki.preferences.PreferencesActivity
import com.ichi2.anki.previewer.CardViewerActivity
import com.ichi2.anki.services.ReminderService.Companion.getReviewDeckIntent
import com.ichi2.anki.ui.windows.managespace.ManageSpaceActivity
@@ -74,7 +73,6 @@ object ActivityList {
// Likely has unhandled intents
get(Reviewer::class.java),
get(MyAccount::class.java),
- get(PreferencesActivity::class.java),
get(FilteredDeckOptions::class.java),
get(DrawingActivity::class.java),
// Info has unhandled intents
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 789571f63b29..81c5eb0ca8fc 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -95,7 +95,7 @@ okhttp = "4.12.0"
protobufKotlinLite = "4.29.0"
# ../AnkiDroid/robolectricDownload.gradle may need changes - read instructions in that file
robolectric = "4.14.1"
-searchpreference = "2.5.1"
+searchpreference = "3.0.2"
seismic = "1.0.3"
sharedPreferencesMock = "1.2.4"
slackKeeper = "0.16.1"
@@ -158,7 +158,7 @@ android-lint-api = { module = "com.android.tools.lint:lint-api", version.ref = "
android-lint = { module = "com.android.tools.lint:lint", version.ref = "lint" }
android-lint-tests = { module = "com.android.tools.lint:lint-tests", version.ref = "lint" }
protobuf-kotlin-lite = { module = "com.google.protobuf:protobuf-kotlin-lite", version.ref = "protobufKotlinLite" }
-search-preference = { module = "com.github.ByteHamster:SearchPreference", version.ref = "searchpreference" }
+search-preference = { module = "com.github.BrayanDSO:SearchPreference", version.ref = "searchpreference" }
seismic = { module = "com.squareup:seismic", version.ref = "seismic" }
slf4j-timber = { module = "com.arcao:slf4j-timber", version.ref = "slf4jTimber" }
jakewharton-timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" }