diff --git a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsNavFragmentX.kt b/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsNavFragmentX.kt deleted file mode 100644 index ddb8eab9..00000000 --- a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsNavFragmentX.kt +++ /dev/null @@ -1,362 +0,0 @@ -package com.machiav3lli.fdroid.ui.fragments - -import android.app.Dialog -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Bundle -import android.text.InputFilter -import android.text.InputType -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager -import android.widget.LinearLayout -import androidx.appcompat.app.AlertDialog -import androidx.core.net.toUri -import androidx.core.widget.NestedScrollView -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.Fragment -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope -import com.google.android.material.circularreveal.CircularRevealFrameLayout -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.switchmaterial.SwitchMaterial -import com.google.android.material.textfield.TextInputEditText -import com.google.android.material.textview.MaterialTextView -import com.machiav3lli.fdroid.R -import com.machiav3lli.fdroid.content.Preferences -import com.machiav3lli.fdroid.databinding.FragmentPrefsBinding -import com.machiav3lli.fdroid.databinding.PreferenceItemBinding -import com.machiav3lli.fdroid.utility.Utils -import com.machiav3lli.fdroid.utility.extension.resources.TypefaceExtra -import com.machiav3lli.fdroid.utility.extension.resources.getColorFromAttr -import com.machiav3lli.fdroid.utility.extension.resources.inflate -import com.machiav3lli.fdroid.utility.extension.resources.setTextSizeScaled -import com.machiav3lli.fdroid.utility.extension.resources.sizeScaled -import com.topjohnwu.superuser.Shell -import kotlinx.coroutines.launch - -abstract class PrefsNavFragmentX : Fragment() { - private lateinit var binding: FragmentPrefsBinding - private var preferenceBinding: PreferenceItemBinding? = null - private val preferences = mutableMapOf, Preference<*>>() - - override fun onResume() { - super.onResume() - preferences.forEach { (_, preference) -> preference.update() } - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle?, - ): View { - super.onCreate(savedInstanceState) - binding = FragmentPrefsBinding.inflate(inflater, container, false) - binding.lifecycleOwner = this - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - preferenceBinding = PreferenceItemBinding.inflate(layoutInflater) - - val content = binding.fragmentContent - val scroll = NestedScrollView(content.context) - scroll.id = R.id.preferences_list - scroll.isFillViewport = true - content.addView( - scroll, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.MATCH_PARENT - ) - val scrollLayout = CircularRevealFrameLayout(content.context) - scroll.addView( - scrollLayout, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - - setupPrefs(scrollLayout) - - lifecycleScope.launch { - Preferences.subject - .flowWithLifecycle(lifecycle, Lifecycle.State.STARTED) - .collect { updatePreference(it) } - } - updatePreference(null) - } - - abstract fun setupPrefs(scrollLayout: CircularRevealFrameLayout) - - private fun openURI(url: Uri) { - startActivity(Intent(Intent.ACTION_VIEW, url)) - } - - override fun onDestroyView() { - super.onDestroyView() - preferences.clear() - preferenceBinding = null - } - - private fun updatePreference(key: Preferences.Key<*>?) { - if (key != null) { - preferences[key]?.update() - } - if (key == null || key == Preferences.Key.ProxyType) { - val enabled = when (Preferences[Preferences.Key.ProxyType]) { - is Preferences.ProxyType.Direct -> false - is Preferences.ProxyType.Http, is Preferences.ProxyType.Socks -> true - } - preferences[Preferences.Key.ProxyHost]?.setEnabled(enabled) - preferences[Preferences.Key.ProxyPort]?.setEnabled(enabled) - } - if (key == null || key == Preferences.Key.RootPermission) { - preferences[Preferences.Key.RootPermission]?.setEnabled( - Shell.getCachedShell()?.isRoot - ?: Shell.getShell().isRoot - ) - preferences[Preferences.Key.RootSessionInstaller]?.setEnabled(Utils.rootInstallerEnabled) - } - if (key == Preferences.Key.Theme) { - requireActivity().recreate() - } - } - - protected fun LinearLayout.addText(title: String, summary: String, url: String) { - val text = MaterialTextView(context) - val subText = MaterialTextView(context) - text.text = title - subText.text = summary - text.setTextSizeScaled(16) - subText.setTextSizeScaled(14) - resources.sizeScaled(16).let { - text.setPadding(it, it, 5, 5) - subText.setPadding(it, 5, 5, 25) - } - addView( - text, - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - addView( - subText, - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - text.setOnClickListener { openURI(url.toUri()) } - subText.setOnClickListener { openURI(url.toUri()) } - } - - protected inline fun LinearLayout.addCategory( - title: String, - callback: LinearLayout.() -> Unit, - ) { - val text = MaterialTextView(context) - text.typeface = TypefaceExtra.medium - text.setTextSizeScaled(14) - text.setTextColor(text.context.getColorFromAttr(R.attr.colorPrimary)) - text.text = title - resources.sizeScaled(16).let { text.setPadding(it, it, it, 0) } - addView( - text, - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ) - callback() - } - - protected fun LinearLayout.addPreference( - key: Preferences.Key, title: String, - summaryProvider: () -> String, dialogProvider: ((Context) -> AlertDialog)?, - ): Preference { - val preference = - Preference(key, this@PrefsNavFragmentX, this, title, summaryProvider, dialogProvider) - preferences[key] = preference - return preference - } - - protected fun LinearLayout.addSwitch( - key: Preferences.Key, - title: String, - summary: String, - ) { - val preference = addPreference(key, title, { summary }, null) - preference.check.visibility = View.VISIBLE - preference.view.setOnClickListener { Preferences[key] = !Preferences[key] } - preference.setCallback { preference.check.isChecked = Preferences[key] } - } - - protected fun LinearLayout.addEdit( - key: Preferences.Key, title: String, valueToString: (T) -> String, - stringToValue: (String) -> T?, configureEdit: (TextInputEditText) -> Unit, - ) { - addPreference(key, title, { valueToString(Preferences[key]) }) { it -> - val scroll = NestedScrollView(it) - scroll.resources.sizeScaled(20).let { scroll.setPadding(it, 0, it, 0) } - val edit = TextInputEditText(it) - configureEdit(edit) - edit.id = android.R.id.edit - edit.resources.sizeScaled(16) - .let { edit.setPadding(edit.paddingLeft, it, edit.paddingRight, it) } - edit.setText(valueToString(Preferences[key])) - edit.hint = edit.text.toString() - edit.text?.let { editable -> edit.setSelection(editable.length) } - edit.requestFocus() - scroll.addView( - edit, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - MaterialAlertDialogBuilder(it) - .setTitle(title) - .setView(scroll) - .setPositiveButton(R.string.ok) { _, _ -> - val value = stringToValue(edit.text.toString()) ?: key.default.value - post { Preferences[key] = value } - } - .setNegativeButton(R.string.cancel, null) - .create() - .apply { - window!!.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE) - } - } - } - - protected fun LinearLayout.addEditString(key: Preferences.Key, title: String) { - addEdit(key, title, { it }, { it }, { }) - } - - protected fun LinearLayout.addEditInt( - key: Preferences.Key, - title: String, - range: IntRange?, - ) { - addEdit(key, title, { it.toString() }, { it.toIntOrNull() }) { - it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL - if (range != null) it.filters = - arrayOf(InputFilter { source, start, end, dest, dstart, dend -> - val value = (dest.substring(0, dstart) + source.substring(start, end) + - dest.substring(dend, dest.length)).toIntOrNull() - if (value != null && value in range) null else "" - }) - } - } - - protected fun > LinearLayout.addEnumeration( - key: Preferences.Key, - title: String, - valueToString: (T) -> String, - ) { - addPreference(key, title, { valueToString(Preferences[key]) }) { - val values = key.default.value.values - MaterialAlertDialogBuilder(it) - .setTitle(title) - .setSingleChoiceItems( - values.map(valueToString).toTypedArray(), - values.indexOf(Preferences[key]) - ) { dialog, which -> - dialog.dismiss() - post { Preferences[key] = values[which] } - } - .setNegativeButton(R.string.cancel, null) - .create() - } - } - - protected fun LinearLayout.addList( - key: Preferences.Key, - title: String, - values: List, - valueToString: (T) -> String, - ) { - addPreference(key, title, { valueToString(Preferences[key]) }) { - MaterialAlertDialogBuilder(it) - .setTitle(title) - .setSingleChoiceItems( - values.map(valueToString).toTypedArray(), - values.indexOf(Preferences[key]) - ) { dialog, which -> - dialog.dismiss() - post { Preferences[key] = values[which] } - } - .setNegativeButton(R.string.cancel, null) - .create() - } - } - - protected class Preference( - private val key: Preferences.Key, - fragment: Fragment, - parent: ViewGroup, - titleText: String, - private val summaryProvider: () -> String, - private val dialogProvider: ((Context) -> AlertDialog)?, - ) { - val view = parent.inflate(R.layout.preference_item) - val title = view.findViewById(R.id.title)!! - val summary = view.findViewById(R.id.summary)!! - val check = view.findViewById(R.id.check)!! - - private var callback: (() -> Unit)? = null - - init { - title.text = titleText - parent.addView(view) - if (dialogProvider != null) { - view.setOnClickListener { - PreferenceDialog(key.name) - .show( - fragment.childFragmentManager, - "${PreferenceDialog::class.java.name}.${key.name}" - ) - } - } - update() - } - - fun setCallback(callback: () -> Unit) { - this.callback = callback - update() - } - - fun setEnabled(enabled: Boolean) { - view.isEnabled = enabled - title.isEnabled = enabled - summary.isEnabled = enabled - check.isEnabled = enabled - } - - fun update() { - summary.text = summaryProvider() - summary.visibility = if (summary.text.isNotEmpty()) View.VISIBLE else View.GONE - callback?.invoke() - } - - fun createDialog(context: Context): AlertDialog { - return dialogProvider!!(context) - } - } - - class PreferenceDialog() : DialogFragment() { - companion object { - private const val EXTRA_KEY = "key" - } - - constructor(key: String) : this() { - arguments = Bundle().apply { - putString(EXTRA_KEY, key) - } - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val preferences = (parentFragment as PrefsNavFragmentX).preferences - val key = requireArguments().getString(EXTRA_KEY)!! - .let { name -> preferences.keys.find { it.name == name }!! } - val preference = preferences[key]!! - return preference.createDialog(requireContext()) - } - } -} diff --git a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsOtherFragment.kt b/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsOtherFragment.kt deleted file mode 100644 index cfbf378c..00000000 --- a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsOtherFragment.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.machiav3lli.fdroid.ui.fragments - -import android.view.ViewGroup -import android.widget.LinearLayout -import com.google.android.material.circularreveal.CircularRevealFrameLayout -import com.machiav3lli.fdroid.BuildConfig -import com.machiav3lli.fdroid.R -import com.machiav3lli.fdroid.content.Preferences - -class PrefsOtherFragment : PrefsNavFragmentX() { - - override fun setupPrefs(scrollLayout: CircularRevealFrameLayout) { - val preferences = LinearLayout(scrollLayout.context) - preferences.orientation = LinearLayout.VERTICAL - scrollLayout.addView( - preferences, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - - preferences.addCategory(getString(R.string.proxy)) { - addEnumeration(Preferences.Key.ProxyType, getString(R.string.proxy_type)) { - when (it) { - is Preferences.ProxyType.Direct -> getString(R.string.no_proxy) - is Preferences.ProxyType.Http -> getString(R.string.http_proxy) - is Preferences.ProxyType.Socks -> getString(R.string.socks_proxy) - } - } - addEditString(Preferences.Key.ProxyHost, getString(R.string.proxy_host)) - addEditInt(Preferences.Key.ProxyPort, getString(R.string.proxy_port), 1..65535) - } - preferences.addCategory(getString(R.string.credits)) { - addText( - title = "Based on Foxy-Droid", - summary = "FoxyDroid", - url = "https://github.com/kitsunyan/foxy-droid/" - ) - addText( - title = getString(R.string.application_name), - summary = "v ${BuildConfig.VERSION_NAME}", - url = "https://github.com/NeoApplications/Neo-Store/" - ) - } - } -} diff --git a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUpdatesFragment.kt b/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUpdatesFragment.kt deleted file mode 100644 index 1bc2ce29..00000000 --- a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUpdatesFragment.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.machiav3lli.fdroid.ui.fragments - -import android.view.ViewGroup -import android.widget.LinearLayout -import com.google.android.material.circularreveal.CircularRevealFrameLayout -import com.machiav3lli.fdroid.R -import com.machiav3lli.fdroid.content.Preferences - -class PrefsUpdatesFragment : PrefsNavFragmentX() { - - override fun setupPrefs(scrollLayout: CircularRevealFrameLayout) { - val preferences = LinearLayout(scrollLayout.context) - preferences.orientation = LinearLayout.VERTICAL - scrollLayout.addView( - preferences, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - - preferences.addCategory(getString(R.string.updates)) { - addEnumeration( - Preferences.Key.AutoSync, - getString(R.string.sync_repositories_automatically) - ) { - when (it) { - Preferences.AutoSync.Never -> getString(R.string.never) - Preferences.AutoSync.Wifi -> getString(R.string.only_on_wifi) - Preferences.AutoSync.WifiBattery -> getString(R.string.only_on_wifi_and_battery) - Preferences.AutoSync.Always -> getString(R.string.always) - } - } - addEditInt( - Preferences.Key.ImagesCacheRetention, - getString(R.string.images_cache_retention), - 1..365 - ) - addEditInt( - Preferences.Key.ReleasesCacheRetention, - getString(R.string.releases_cache_retention), - 0..365 - ) - addEditInt( - Preferences.Key.AutoSyncInterval, - getString(R.string.auto_sync_interval), - 1..1440 - ) - addSwitch( - Preferences.Key.InstallAfterSync, getString(R.string.install_after_sync), - getString(R.string.install_after_sync_summary) - ) - addSwitch( - Preferences.Key.UpdateNotify, getString(R.string.notify_about_updates), - getString(R.string.notify_about_updates_summary) - ) - addSwitch( - Preferences.Key.UpdateUnstable, getString(R.string.unstable_updates), - getString(R.string.unstable_updates_summary) - ) - addSwitch( - Preferences.Key.IncompatibleVersions, getString(R.string.incompatible_versions), - getString(R.string.incompatible_versions_summary) - ) - } - preferences.addCategory(getString(R.string.install_types)) { - addSwitch( - Preferences.Key.RootPermission, getString(R.string.root_permission), - getString(R.string.root_permission_description) - ) - addSwitch( - Preferences.Key.RootSessionInstaller, getString(R.string.root_session_installer), - getString(R.string.root_session_installer_description) - ) - } - } -} diff --git a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUserFragment.kt b/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUserFragment.kt deleted file mode 100644 index 2e5105d3..00000000 --- a/src/main/kotlin/com/machiav3lli/fdroid/ui/fragments/PrefsUserFragment.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.machiav3lli.fdroid.ui.fragments - -import android.view.ViewGroup -import android.widget.LinearLayout -import com.google.android.material.circularreveal.CircularRevealFrameLayout -import com.machiav3lli.fdroid.R -import com.machiav3lli.fdroid.content.Preferences -import com.machiav3lli.fdroid.utility.Utils.getLocaleOfCode -import com.machiav3lli.fdroid.utility.Utils.languagesList -import com.machiav3lli.fdroid.utility.Utils.translateLocale - -class PrefsUserFragment : PrefsNavFragmentX() { - - override fun setupPrefs(scrollLayout: CircularRevealFrameLayout) { - val preferences = LinearLayout(scrollLayout.context) - preferences.orientation = LinearLayout.VERTICAL - scrollLayout.addView( - preferences, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - - preferences.addCategory(requireContext().getString(R.string.prefs_personalization)) { - addList( - Preferences.Key.Language, - context.getString(R.string.prefs_language_title), - languagesList - ) { translateLocale(context.getLocaleOfCode(it)) } - addEnumeration(Preferences.Key.Theme, getString(R.string.theme)) { - when (it) { - is Preferences.Theme.System -> getString(R.string.system) - is Preferences.Theme.SystemBlack -> getString(R.string.system) + " " + getString( - R.string.amoled - ) - is Preferences.Theme.Dynamic -> getString(R.string.dynamic) - is Preferences.Theme.Light -> getString(R.string.light) - is Preferences.Theme.Dark -> getString(R.string.dark) - is Preferences.Theme.Black -> getString(R.string.amoled) - } - } - addEnumeration(Preferences.Key.DefaultTab, getString(R.string.default_tab)) { - when (it) { - is Preferences.DefaultTab.Explore -> getString(R.string.explore) - is Preferences.DefaultTab.Latest -> getString(R.string.latest) - is Preferences.DefaultTab.Installed -> getString(R.string.installed) - } - } - addSwitch( - Preferences.Key.ShowScreenshots, getString(R.string.show_screenshots), - getString(R.string.show_screenshots_description) - ) - addEditInt(Preferences.Key.UpdatedApps, getString(R.string.prefs_updated_apps), 1..200) - addEditInt(Preferences.Key.NewApps, getString(R.string.prefs_new_apps), 1..50) - } - } -} diff --git a/src/main/res/layout/fragment_prefs.xml b/src/main/res/layout/fragment_prefs.xml deleted file mode 100644 index e02b68da..00000000 --- a/src/main/res/layout/fragment_prefs.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/src/main/res/layout/preference_item.xml b/src/main/res/layout/preference_item.xml deleted file mode 100644 index 6c1a580a..00000000 --- a/src/main/res/layout/preference_item.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file