Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 0 additions & 9 deletions AnkiDroid/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -345,15 +345,6 @@
android:name=".multimedia.MultimediaActivity"
android:configChanges="orientation|screenSize"
android:exported="false" />
<activity
android:name="com.ichi2.anki.preferences.PreferencesActivity"
android:exported="false"
android:configChanges="screenSize"
>
<intent-filter>
<category android:name="android.intent.category.MONKEY" />
</intent-filter>
</activity>
<activity
android:name=".FilteredDeckOptions"
android:label="@string/deckpreferences_title"
Expand Down
4 changes: 2 additions & 2 deletions AnkiDroid/src/main/java/com/ichi2/anki/DeckPicker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ import com.ichi2.anki.pages.AnkiPackageImporterFragment
import com.ichi2.anki.pages.CongratsPage
import com.ichi2.anki.pages.CongratsPage.Companion.onDeckCompleted
import com.ichi2.anki.preferences.AdvancedSettingsFragment
import com.ichi2.anki.preferences.PreferencesActivity
import com.ichi2.anki.preferences.PreferencesFragment
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.receiver.SdCardReceiver
import com.ichi2.anki.servicelayer.ScopedStorageService
Expand Down Expand Up @@ -787,7 +787,7 @@ open class DeckPicker :
convertDpToPixel(32F, this@DeckPicker).toInt()
)
positiveButton(R.string.open_settings) {
val settingsIntent = PreferencesActivity.getIntent(this@DeckPicker, AdvancedSettingsFragment::class)
val settingsIntent = PreferencesFragment.getIntent(this@DeckPicker, AdvancedSettingsFragment::class)
requestPathUpdateLauncher.launch(settingsIntent)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import com.google.android.material.color.MaterialColors
import com.google.android.material.navigation.NavigationView
import com.ichi2.anki.NoteEditor.Companion.NoteEditorCaller
import com.ichi2.anki.dialogs.help.HelpDialog
import com.ichi2.anki.preferences.PreferencesActivity
import com.ichi2.anki.preferences.PreferencesFragment
import com.ichi2.anki.preferences.sharedPrefs
import com.ichi2.anki.utils.ext.showDialogFragment
import com.ichi2.anki.workarounds.FullDraggableContainerFix
Expand Down Expand Up @@ -361,7 +361,7 @@ abstract class NavigationDrawerActivity :
* Opens AnkiDroid's Settings Screen.
*/
protected fun openSettings() {
val intent = PreferencesActivity.getIntent(this)
val intent = PreferencesFragment.getIntent(this)
preferencesLauncher.launch(intent)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
*/
package com.ichi2.anki.preferences

import android.content.Context
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.fragment.app.commit
import androidx.fragment.app.replace
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.bytehamster.lib.preferencesearch.SearchConfiguration
Expand Down Expand Up @@ -57,7 +59,7 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
.isVisible = DevOptionsFragment.isEnabled(requireContext())

configureSearchBar(
requireActivity() as AppCompatActivity,
requireContext(),
requirePreference<SearchPreference>(R.string.search_preference_key).searchConfiguration
)

Expand All @@ -68,6 +70,7 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
}

parentFragmentManager.addOnBackStackChangedListener {
if (!isAdded) return@addOnBackStackChangedListener
val fragment = parentFragmentManager.findFragmentById(R.id.settings_container)
?: return@addOnBackStackChangedListener

Expand All @@ -87,16 +90,20 @@ class HeaderFragment : PreferenceFragmentCompat(), TitleProvider {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// use the same fragment container to search in case there is a navigation container
requirePreference<SearchPreference>(R.string.search_preference_key)
.searchConfiguration
.setFragmentContainerViewId((view.parent as? ViewGroup)?.id ?: R.id.settings_container)
requirePreference<SearchPreference>(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)
Expand All @@ -105,32 +112,32 @@ 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)
}

// Some preferences and categories are only shown conditionally,
// 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))
}
}

Expand All @@ -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))
}

/**
Expand Down
23 changes: 2 additions & 21 deletions AnkiDroid/src/main/java/com/ichi2/anki/preferences/Preferences.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -150,29 +149,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<out SettingsFragment>? = 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)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

package com.ichi2.anki.ui.internationalization

import android.app.Activity
import android.content.Context
import android.content.res.Resources
import androidx.annotation.StringRes
import androidx.fragment.app.Fragment

Expand All @@ -29,16 +30,15 @@ import androidx.fragment.app.Fragment
* "Toggle Suspend".toSentenceCase(R.string.sentence_toggle_suspend) // "Toggle suspend"
* ```
*/
fun String.toSentenceCase(activity: Activity, @StringRes resId: Int): String {
val resString = activity.getString(resId)
fun String.toSentenceCase(resources: Resources, @StringRes resId: Int): String {
val resString = resources.getString(resId)
// lowercase both for the comparison: sentence case doesn't mean all words are lowercase
if (this.lowercase() == resString.lowercase()) return resString
return this
}

fun String.toSentenceCase(fragment: Fragment, @StringRes resId: Int): String {
val resString = fragment.getString(resId)
// lowercase both for the comparison: sentence case doesn't mean all words are lowercase
if (this.lowercase() == resString.lowercase()) return resString
return this
}
fun String.toSentenceCase(context: Context, @StringRes resId: Int): String =
toSentenceCase(context.resources, resId)

fun String.toSentenceCase(fragment: Fragment, @StringRes resId: Int): String =
toSentenceCase(fragment.resources, resId)
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,44 +15,39 @@
*/
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.getInstanceFromClassName
import com.ichi2.testutils.getJavaMethodAsAccessible
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
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
Expand All @@ -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>(PreferencesActivity.getIntent(targetContext))
val activityScenario = ActivityScenario.launch<SingleFragmentActivity>(PreferencesFragment.getIntent(targetContext))

activityScenario.onActivity { activity ->
PreferenceTestUtils.getAllPreferencesFragments(activity).forEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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")
Expand Down Expand Up @@ -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()
}
}
2 changes: 0 additions & 2 deletions AnkiDroid/src/test/java/com/ichi2/testutils/ActivityList.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Loading
Loading