mirror of
https://github.com/Michatec/michas-droid.git
synced 2026-05-30 18:02:43 +02:00
Drop AppCompat
This commit is contained in:
+2
-2
@@ -116,8 +116,8 @@ repositories {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
|
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:' + versions.kotlin
|
||||||
implementation 'androidx.preference:preference:1.1.1'
|
implementation 'androidx.fragment:fragment:1.2.5'
|
||||||
implementation 'com.google.android.material:material:1.1.0'
|
implementation 'androidx.viewpager2:viewpager2:1.0.0'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
|
implementation 'com.squareup.okhttp3:okhttp:4.7.2'
|
||||||
implementation 'io.reactivex.rxjava3:rxjava:3.0.4'
|
implementation 'io.reactivex.rxjava3:rxjava:3.0.4'
|
||||||
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nya.kitsunyan.foxydroid.content
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
import io.reactivex.rxjava3.subjects.PublishSubject
|
import io.reactivex.rxjava3.subjects.PublishSubject
|
||||||
import nya.kitsunyan.foxydroid.R
|
import nya.kitsunyan.foxydroid.R
|
||||||
@@ -17,7 +16,7 @@ object Preferences {
|
|||||||
Key.Theme, Key.UpdateNotify, Key.UpdateUnstable).map { Pair(it.name, it) }.toMap()
|
Key.Theme, Key.UpdateNotify, Key.UpdateUnstable).map { Pair(it.name, it) }.toMap()
|
||||||
|
|
||||||
fun init(context: Context) {
|
fun init(context: Context) {
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context)
|
preferences = context.getSharedPreferences("${context.packageName}_preferences", Context.MODE_PRIVATE)
|
||||||
preferences.registerOnSharedPreferenceChangeListener { _, keyString -> keys[keyString]?.let(subject::onNext) }
|
preferences.registerOnSharedPreferenceChangeListener { _, keyString -> keys[keyString]?.let(subject::onNext) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package nya.kitsunyan.foxydroid.screen
|
package nya.kitsunyan.foxydroid.screen
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.ClipboardManager
|
import android.content.ClipboardManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
@@ -17,8 +18,7 @@ import android.view.ViewGroup
|
|||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import android.widget.Toolbar
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package nya.kitsunyan.foxydroid.screen
|
package nya.kitsunyan.foxydroid.screen
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import nya.kitsunyan.foxydroid.R
|
import nya.kitsunyan.foxydroid.R
|
||||||
|
|||||||
@@ -1,38 +1,56 @@
|
|||||||
package nya.kitsunyan.foxydroid.screen
|
package nya.kitsunyan.foxydroid.screen
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputFilter
|
import android.text.InputFilter
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.view.WindowManager
|
||||||
|
import android.widget.EditText
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.appcompat.widget.Toolbar
|
import android.widget.LinearLayout
|
||||||
import androidx.preference.EditTextPreference
|
import android.widget.ScrollView
|
||||||
import androidx.preference.ListPreference
|
import android.widget.Switch
|
||||||
import androidx.preference.Preference
|
import android.widget.TextView
|
||||||
import androidx.preference.PreferenceCategory
|
import android.widget.Toolbar
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.preference.PreferenceGroup
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.preference.SwitchPreference
|
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
import nya.kitsunyan.foxydroid.R
|
import nya.kitsunyan.foxydroid.R
|
||||||
import nya.kitsunyan.foxydroid.content.Preferences
|
import nya.kitsunyan.foxydroid.content.Preferences
|
||||||
|
import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
||||||
|
|
||||||
class PreferencesFragment: PreferenceFragmentCompat() {
|
class PreferencesFragment: Fragment() {
|
||||||
|
private val preferences = mutableMapOf<Preferences.Key<*>, Preference<*>>()
|
||||||
private var disposable: Disposable? = null
|
private var disposable: Disposable? = null
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
val view = inflater.inflate(R.layout.fragment, container, false)
|
return inflater.inflate(R.layout.fragment, container, false)
|
||||||
val content = view.findViewById<FrameLayout>(R.id.fragment_content)
|
|
||||||
val child = super.onCreateView(LayoutInflater.from(content.context), content, savedInstanceState)
|
|
||||||
content.addView(child, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
|
||||||
return view
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
preferenceScreen = preferenceManager.createPreferenceScreen(requireContext())
|
super.onViewCreated(view, savedInstanceState)
|
||||||
preferenceScreen.addCategory(getString(R.string.updates)).apply {
|
|
||||||
|
val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
|
||||||
|
screenActivity.onFragmentViewCreated(toolbar)
|
||||||
|
toolbar.setTitle(R.string.preferences)
|
||||||
|
|
||||||
|
val content = view.findViewById<FrameLayout>(R.id.fragment_content)
|
||||||
|
val scroll = ScrollView(content.context)
|
||||||
|
scroll.id = R.id.preferences_list
|
||||||
|
scroll.isFillViewport = true
|
||||||
|
content.addView(scroll, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||||
|
val scrollLayout = FrameLayout(content.context)
|
||||||
|
scroll.addView(scrollLayout, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
|
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)) {
|
addEnumeration(Preferences.Key.AutoSync, getString(R.string.sync_repositories_automatically)) {
|
||||||
when (it) {
|
when (it) {
|
||||||
Preferences.AutoSync.Never -> getString(R.string.never)
|
Preferences.AutoSync.Never -> getString(R.string.never)
|
||||||
@@ -45,7 +63,7 @@ class PreferencesFragment: PreferenceFragmentCompat() {
|
|||||||
addSwitch(Preferences.Key.UpdateUnstable, getString(R.string.unstable_updates),
|
addSwitch(Preferences.Key.UpdateUnstable, getString(R.string.unstable_updates),
|
||||||
getString(R.string.unstable_updates_summary))
|
getString(R.string.unstable_updates_summary))
|
||||||
}
|
}
|
||||||
preferenceScreen.addCategory(getString(R.string.proxy)).apply {
|
preferences.addCategory(getString(R.string.proxy)) {
|
||||||
addEnumeration(Preferences.Key.ProxyType, getString(R.string.proxy_type)) {
|
addEnumeration(Preferences.Key.ProxyType, getString(R.string.proxy_type)) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Preferences.ProxyType.Direct -> getString(R.string.no_proxy)
|
is Preferences.ProxyType.Direct -> getString(R.string.no_proxy)
|
||||||
@@ -56,7 +74,7 @@ class PreferencesFragment: PreferenceFragmentCompat() {
|
|||||||
addEditString(Preferences.Key.ProxyHost, getString(R.string.proxy_host))
|
addEditString(Preferences.Key.ProxyHost, getString(R.string.proxy_host))
|
||||||
addEditInt(Preferences.Key.ProxyPort, getString(R.string.proxy_port), 1 .. 65535)
|
addEditInt(Preferences.Key.ProxyPort, getString(R.string.proxy_port), 1 .. 65535)
|
||||||
}
|
}
|
||||||
preferenceScreen.addCategory(getString(R.string.other)).apply {
|
preferences.addCategory(getString(R.string.other)) {
|
||||||
addEnumeration(Preferences.Key.Theme, getString(R.string.theme)) {
|
addEnumeration(Preferences.Key.Theme, getString(R.string.theme)) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is Preferences.Theme.Light -> getString(R.string.light)
|
is Preferences.Theme.Light -> getString(R.string.light)
|
||||||
@@ -66,14 +84,6 @@ class PreferencesFragment: PreferenceFragmentCompat() {
|
|||||||
addSwitch(Preferences.Key.IncompatibleVersions, getString(R.string.incompatible_versions),
|
addSwitch(Preferences.Key.IncompatibleVersions, getString(R.string.incompatible_versions),
|
||||||
getString(R.string.incompatible_versions_summary))
|
getString(R.string.incompatible_versions_summary))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
|
|
||||||
screenActivity.onFragmentViewCreated(toolbar)
|
|
||||||
toolbar.setTitle(R.string.preferences)
|
|
||||||
|
|
||||||
disposable = Preferences.observable.subscribe(this::updatePreference)
|
disposable = Preferences.observable.subscribe(this::updatePreference)
|
||||||
updatePreference(null)
|
updatePreference(null)
|
||||||
@@ -82,75 +92,107 @@ class PreferencesFragment: PreferenceFragmentCompat() {
|
|||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|
||||||
|
preferences.clear()
|
||||||
disposable?.dispose()
|
disposable?.dispose()
|
||||||
disposable = null
|
disposable = null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updatePreference(key: Preferences.Key<*>?) {
|
private fun updatePreference(key: Preferences.Key<*>?) {
|
||||||
|
if (key != null) {
|
||||||
|
preferences[key]?.update()
|
||||||
|
}
|
||||||
if (key == null || key == Preferences.Key.ProxyType) {
|
if (key == null || key == Preferences.Key.ProxyType) {
|
||||||
val enabled = when (Preferences[Preferences.Key.ProxyType]) {
|
val enabled = when (Preferences[Preferences.Key.ProxyType]) {
|
||||||
is Preferences.ProxyType.Direct -> false
|
is Preferences.ProxyType.Direct -> false
|
||||||
is Preferences.ProxyType.Http, is Preferences.ProxyType.Socks -> true
|
is Preferences.ProxyType.Http, is Preferences.ProxyType.Socks -> true
|
||||||
}
|
}
|
||||||
findPreference<Preference>(Preferences.Key.ProxyHost.name)!!.isEnabled = enabled
|
preferences[Preferences.Key.ProxyHost]?.setEnabled(enabled)
|
||||||
findPreference<Preference>(Preferences.Key.ProxyPort.name)!!.isEnabled = enabled
|
preferences[Preferences.Key.ProxyPort]?.setEnabled(enabled)
|
||||||
}
|
}
|
||||||
if (key == Preferences.Key.Theme) {
|
if (key == Preferences.Key.Theme) {
|
||||||
requireActivity().recreate()
|
requireActivity().recreate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PreferenceGroup.addCategory(title: String): PreferenceCategory {
|
private fun LinearLayout.addDivider(full: Boolean): View {
|
||||||
val preference = PreferenceCategory(context)
|
val divider = View(context)
|
||||||
preference.isIconSpaceReserved = false
|
divider.background = context.getDrawableFromAttr(android.R.attr.listDivider)
|
||||||
preference.title = title
|
addView(divider, LinearLayout.LayoutParams.MATCH_PARENT, divider.background.intrinsicHeight)
|
||||||
addPreference(preference)
|
if (!full) {
|
||||||
|
(divider.layoutParams as LinearLayout.LayoutParams).apply {
|
||||||
|
marginStart = divider.resources.sizeScaled(16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return divider
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun LinearLayout.addCategory(title: String, callback: LinearLayout.() -> Unit) {
|
||||||
|
val text = TextView(context)
|
||||||
|
text.typeface = TypefaceExtra.medium
|
||||||
|
text.setTextSizeScaled(14)
|
||||||
|
text.setTextColor(text.context.getColorFromAttr(android.R.attr.colorAccent))
|
||||||
|
text.text = title
|
||||||
|
resources.sizeScaled(16).let { text.setPadding(it, it, it, 0) }
|
||||||
|
addView(text, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||||
|
callback()
|
||||||
|
val divider = addDivider(true)
|
||||||
|
// Negative margin for last divider
|
||||||
|
(layoutParams as ViewGroup.MarginLayoutParams).bottomMargin = -divider.layoutParams.height
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> LinearLayout.addPreference(key: Preferences.Key<T>, title: String,
|
||||||
|
summaryProvider: () -> String, dialogProvider: ((Context) -> AlertDialog)?): Preference<T> {
|
||||||
|
if (childCount > 0 && getChildAt(childCount - 1) !is TextView) {
|
||||||
|
addDivider(false)
|
||||||
|
}
|
||||||
|
val preference = Preference(key, this@PreferencesFragment, this, title, summaryProvider, dialogProvider)
|
||||||
|
preferences[key] = preference
|
||||||
return preference
|
return preference
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PreferenceGroup.addSwitch(key: Preferences.Key<Boolean>, title: String, summary: String?) {
|
private fun LinearLayout.addSwitch(key: Preferences.Key<Boolean>, title: String, summary: String) {
|
||||||
val preference = SwitchPreference(context)
|
val preference = addPreference(key, title, { summary }, null)
|
||||||
preference.isIconSpaceReserved = false
|
preference.check.visibility = View.VISIBLE
|
||||||
preference.title = title
|
preference.view.setOnClickListener { Preferences[key] = !Preferences[key] }
|
||||||
preference.summary = summary
|
preference.setCallback { preference.check.isChecked = Preferences[key] }
|
||||||
preference.key = key.name
|
|
||||||
preference.setDefaultValue(key.default.value)
|
|
||||||
addPreference(preference)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PreferenceGroup.addEditString(key: Preferences.Key<String>, title: String) {
|
private fun <T> LinearLayout.addEdit(key: Preferences.Key<T>, title: String, valueToString: (T) -> String,
|
||||||
val preference = EditTextPreference(context)
|
stringToValue: (String) -> T?, configureEdit: (EditText) -> Unit) {
|
||||||
preference.isIconSpaceReserved = false
|
addPreference(key, title, { valueToString(Preferences[key]) }) {
|
||||||
preference.title = title
|
val scroll = ScrollView(it)
|
||||||
preference.dialogTitle = title
|
scroll.resources.sizeScaled(20).let { scroll.setPadding(it, 0, it, 0) }
|
||||||
preference.summaryProvider = Preference.SummaryProvider<EditTextPreference> { it.text }
|
val edit = EditText(it)
|
||||||
preference.key = key.name
|
configureEdit(edit)
|
||||||
preference.setDefaultValue(key.default.value)
|
edit.id = android.R.id.edit
|
||||||
addPreference(preference)
|
edit.setTextSizeScaled(16)
|
||||||
}
|
edit.resources.sizeScaled(16).let { edit.setPadding(edit.paddingLeft, it, edit.paddingRight, it) }
|
||||||
|
edit.setText(valueToString(Preferences[key]))
|
||||||
private fun PreferenceGroup.addEditInt(key: Preferences.Key<Int>, title: String, range: IntRange?) {
|
edit.hint = edit.text.toString()
|
||||||
val preference = object: EditTextPreference(context) {
|
edit.setSelection(edit.text.length)
|
||||||
override fun persistString(value: String?): Boolean {
|
edit.requestFocus()
|
||||||
val intValue = value.orEmpty().toIntOrNull() ?: key.default.value
|
scroll.addView(edit, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||||
val result = persistInt(intValue)
|
AlertDialog.Builder(it)
|
||||||
if (intValue.toString() != value) {
|
.setTitle(title)
|
||||||
text = intValue.toString()
|
.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)
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSetInitialValue(defaultValue: Any?) {
|
|
||||||
text = getPersistedInt((defaultValue as? Int) ?: key.default.value).toString()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
preference.isIconSpaceReserved = false
|
}
|
||||||
preference.title = title
|
|
||||||
preference.dialogTitle = title
|
private fun LinearLayout.addEditString(key: Preferences.Key<String>, title: String) {
|
||||||
preference.summaryProvider = Preference.SummaryProvider<EditTextPreference> { it.text }
|
addEdit(key, title, { it }, { it }, { })
|
||||||
preference.key = key.name
|
}
|
||||||
preference.setDefaultValue(key.default.value)
|
|
||||||
preference.setOnBindEditTextListener {
|
private fun LinearLayout.addEditInt(key: Preferences.Key<Int>, title: String, range: IntRange?) {
|
||||||
|
addEdit(key, title, { it.toString() }, { it.toIntOrNull() }) {
|
||||||
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
|
it.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL
|
||||||
if (range != null) {
|
if (range != null) {
|
||||||
it.filters = arrayOf(InputFilter { source, start, end, dest, dstart, dend ->
|
it.filters = arrayOf(InputFilter { source, start, end, dest, dstart, dend ->
|
||||||
@@ -160,23 +202,84 @@ class PreferencesFragment: PreferenceFragmentCompat() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addPreference(preference)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun <T: Preferences.Enumeration<T>> PreferenceGroup
|
private fun <T: Preferences.Enumeration<T>> LinearLayout
|
||||||
.addEnumeration(key: Preferences.Key<T>, title: String, valueString: (T) -> String) {
|
.addEnumeration(key: Preferences.Key<T>, title: String, valueToString: (T) -> String) {
|
||||||
val preference = ListPreference(context)
|
addPreference(key, title, { valueToString(Preferences[key]) }) {
|
||||||
preference.isIconSpaceReserved = false
|
val values = key.default.value.values
|
||||||
preference.title = title
|
AlertDialog.Builder(it)
|
||||||
preference.dialogTitle = title
|
.setTitle(title)
|
||||||
preference.summaryProvider = Preference.SummaryProvider<ListPreference> { p ->
|
.setSingleChoiceItems(values.map(valueToString).toTypedArray(),
|
||||||
val index = p.entryValues.indexOfFirst { it == p.value }
|
values.indexOf(Preferences[key])) { dialog, which ->
|
||||||
if (index >= 0) p.entries[index] else valueString(key.default.value)
|
dialog.dismiss()
|
||||||
|
post { Preferences[key] = values[which] }
|
||||||
|
}
|
||||||
|
.setNegativeButton(R.string.cancel, null)
|
||||||
|
.create()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Preference<T>(private val key: Preferences.Key<T>,
|
||||||
|
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<TextView>(R.id.title)!!
|
||||||
|
val summary = view.findViewById<TextView>(R.id.summary)!!
|
||||||
|
val check = view.findViewById<Switch>(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 PreferencesFragment).preferences
|
||||||
|
val key = requireArguments().getString(EXTRA_KEY)!!
|
||||||
|
.let { name -> preferences.keys.find { it.name == name }!! }
|
||||||
|
val preference = preferences[key]!!
|
||||||
|
return preference.createDialog(requireContext())
|
||||||
}
|
}
|
||||||
preference.key = key.name
|
|
||||||
preference.setDefaultValue(key.default.value.valueString)
|
|
||||||
preference.entryValues = key.default.value.values.map { it.valueString }.toTypedArray()
|
|
||||||
preference.entries = key.default.value.values.map(valueString).toTypedArray()
|
|
||||||
addPreference(preference)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,11 +33,9 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
|
import android.widget.Switch
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.core.text.util.LinkifyCompat
|
import androidx.core.text.util.LinkifyCompat
|
||||||
@@ -106,12 +104,12 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
|
|
||||||
private enum class SectionType(val titleResId: Int, val colorAttrResId: Int) {
|
private enum class SectionType(val titleResId: Int, val colorAttrResId: Int) {
|
||||||
ANTI_FEATURES(R.string.anti_features, R.attr.colorError),
|
ANTI_FEATURES(R.string.anti_features, R.attr.colorError),
|
||||||
WHATS_NEW(R.string.whats_new, R.attr.colorAccent),
|
WHATS_NEW(R.string.whats_new, android.R.attr.colorAccent),
|
||||||
LINKS(R.string.links, R.attr.colorAccent),
|
LINKS(R.string.links, android.R.attr.colorAccent),
|
||||||
DONATE(R.string.donate, R.attr.colorAccent),
|
DONATE(R.string.donate, android.R.attr.colorAccent),
|
||||||
PERMISSIONS(R.string.permissions, R.attr.colorAccent),
|
PERMISSIONS(R.string.permissions, android.R.attr.colorAccent),
|
||||||
SCREENSHOTS(R.string.screenshots, R.attr.colorAccent),
|
SCREENSHOTS(R.string.screenshots, android.R.attr.colorAccent),
|
||||||
RELEASES(R.string.releases, R.attr.colorAccent)
|
RELEASES(R.string.releases, android.R.attr.colorAccent)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal enum class ExpandType { NOTHING, DESCRIPTION, WHATS_NEW,
|
internal enum class ExpandType { NOTHING, DESCRIPTION, WHATS_NEW,
|
||||||
@@ -300,10 +298,13 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
val progressIcon: Drawable
|
val progressIcon: Drawable
|
||||||
val defaultIcon: Drawable
|
val defaultIcon: Drawable
|
||||||
|
|
||||||
val actionTintNormal = action.context.getColorFromAttr(R.attr.colorAccent)
|
val actionTintNormal = action.context.getColorFromAttr(android.R.attr.colorAccent)
|
||||||
val actionTintCancel = action.context.getColorFromAttr(R.attr.colorError)
|
val actionTintCancel = action.context.getColorFromAttr(R.attr.colorError)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
if (Android.sdk(22)) {
|
||||||
|
action.setTextColor(action.context.getColorFromAttr(android.R.attr.colorBackground))
|
||||||
|
}
|
||||||
val (progressIcon, defaultIcon) = Utils.getDefaultApplicationIcons(icon.context)
|
val (progressIcon, defaultIcon) = Utils.getDefaultApplicationIcons(icon.context)
|
||||||
this.progressIcon = progressIcon
|
this.progressIcon = progressIcon
|
||||||
this.defaultIcon = defaultIcon
|
this.defaultIcon = defaultIcon
|
||||||
@@ -312,7 +313,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
|
|
||||||
private class SwitchViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
private class SwitchViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||||
val title = itemView.findViewById<TextView>(R.id.title)!!
|
val title = itemView.findViewById<TextView>(R.id.title)!!
|
||||||
val enabled = itemView.findViewById<SwitchCompat>(R.id.enabled)!!
|
val enabled = itemView.findViewById<Switch>(R.id.enabled)!!
|
||||||
|
|
||||||
val statefulViews: Sequence<View>
|
val statefulViews: Sequence<View>
|
||||||
get() = sequenceOf(itemView, title, enabled)
|
get() = sequenceOf(itemView, title, enabled)
|
||||||
@@ -323,7 +324,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
val icon = itemView.findViewById<ImageView>(R.id.icon)!!
|
val icon = itemView.findViewById<ImageView>(R.id.icon)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ExpandViewHolder(context: Context): RecyclerView.ViewHolder(AppCompatTextView(context)) {
|
private class ExpandViewHolder(context: Context): RecyclerView.ViewHolder(TextView(context)) {
|
||||||
val text: TextView
|
val text: TextView
|
||||||
get() = itemView as TextView
|
get() = itemView as TextView
|
||||||
|
|
||||||
@@ -331,8 +332,8 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
itemView as TextView
|
itemView as TextView
|
||||||
itemView.typeface = TypefaceExtra.medium
|
itemView.typeface = TypefaceExtra.medium
|
||||||
itemView.setTextSizeScaled(14)
|
itemView.setTextSizeScaled(14)
|
||||||
itemView.setTextColor(itemView.context.getColorFromAttr(R.attr.colorAccent))
|
itemView.setTextColor(itemView.context.getColorFromAttr(android.R.attr.colorAccent))
|
||||||
itemView.background = itemView.context.getDrawableFromAttr(R.attr.selectableItemBackground)
|
itemView.background = itemView.context.getDrawableFromAttr(android.R.attr.selectableItemBackground)
|
||||||
itemView.gravity = Gravity.CENTER
|
itemView.gravity = Gravity.CENTER
|
||||||
itemView.isAllCaps = true
|
itemView.isAllCaps = true
|
||||||
itemView.layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,
|
itemView.layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,
|
||||||
@@ -340,7 +341,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TextViewHolder(context: Context): RecyclerView.ViewHolder(AppCompatTextView(context)) {
|
private class TextViewHolder(context: Context): RecyclerView.ViewHolder(TextView(context)) {
|
||||||
val text: TextView
|
val text: TextView
|
||||||
get() = itemView as TextView
|
get() = itemView as TextView
|
||||||
|
|
||||||
@@ -423,12 +424,12 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
itemView as FrameLayout
|
itemView as FrameLayout
|
||||||
itemView.foreground = itemView.context.getDrawableFromAttr(R.attr.selectableItemBackground)
|
itemView.foreground = itemView.context.getDrawableFromAttr(android.R.attr.selectableItemBackground)
|
||||||
val backgroundColor = itemView.context.getColorFromAttr(android.R.attr.colorBackground).defaultColor
|
val backgroundColor = itemView.context.getColorFromAttr(android.R.attr.colorBackground).defaultColor
|
||||||
val accentColor = itemView.context.getColorFromAttr(R.attr.colorAccent).defaultColor
|
val accentColor = itemView.context.getColorFromAttr(android.R.attr.colorAccent).defaultColor
|
||||||
val primaryColor = itemView.context.getColorFromAttr(android.R.attr.textColorPrimary).defaultColor
|
val primaryColor = itemView.context.getColorFromAttr(android.R.attr.textColorPrimary).defaultColor
|
||||||
|
|
||||||
image = object: AppCompatImageView(context) {
|
image = object: ImageView(context) {
|
||||||
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
|
||||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||||
setMeasuredDimension(measuredWidth, measuredWidth)
|
setMeasuredDimension(measuredWidth, measuredWidth)
|
||||||
@@ -465,7 +466,7 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
init {
|
init {
|
||||||
status.background = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, null).apply {
|
status.background = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, null).apply {
|
||||||
setStatusActive = { active -> color = itemView.context.getColorFromAttr(if (active)
|
setStatusActive = { active -> color = itemView.context.getColorFromAttr(if (active)
|
||||||
R.attr.colorAccent else android.R.attr.textColorSecondary) }
|
android.R.attr.colorAccent else android.R.attr.textColorSecondary) }
|
||||||
cornerRadius = itemView.resources.sizeScaled(2).toFloat()
|
cornerRadius = itemView.resources.sizeScaled(2).toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -479,14 +480,14 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
itemView.orientation = LinearLayout.VERTICAL
|
itemView.orientation = LinearLayout.VERTICAL
|
||||||
itemView.gravity = Gravity.CENTER
|
itemView.gravity = Gravity.CENTER
|
||||||
itemView.resources.sizeScaled(20).let { itemView.setPadding(it, it, it, it) }
|
itemView.resources.sizeScaled(20).let { itemView.setPadding(it, it, it, it) }
|
||||||
val title = AppCompatTextView(itemView.context)
|
val title = TextView(itemView.context)
|
||||||
title.gravity = Gravity.CENTER
|
title.gravity = Gravity.CENTER
|
||||||
title.typeface = TypefaceExtra.light
|
title.typeface = TypefaceExtra.light
|
||||||
title.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
title.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
||||||
title.setTextSizeScaled(20)
|
title.setTextSizeScaled(20)
|
||||||
title.setText(R.string.application_not_found)
|
title.setText(R.string.application_not_found)
|
||||||
itemView.addView(title, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
itemView.addView(title, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
|
||||||
val packageName = AppCompatTextView(itemView.context)
|
val packageName = TextView(itemView.context)
|
||||||
packageName.gravity = Gravity.CENTER
|
packageName.gravity = Gravity.CENTER
|
||||||
packageName.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
packageName.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
||||||
packageName.setTextSizeScaled(16)
|
packageName.setTextSizeScaled(16)
|
||||||
@@ -974,8 +975,10 @@ class ProductAdapter(private val callbacks: Callbacks, private val columns: Int)
|
|||||||
if (action != null) {
|
if (action != null) {
|
||||||
holder.action.setText(action.titleResId)
|
holder.action.setText(action.titleResId)
|
||||||
}
|
}
|
||||||
holder.action.backgroundTintList = if (action == Action.CANCEL)
|
if (Android.sdk(22)) {
|
||||||
holder.actionTintCancel else holder.actionTintNormal
|
holder.action.backgroundTintList = if (action == Action.CANCEL)
|
||||||
|
holder.actionTintCancel else holder.actionTintNormal
|
||||||
|
}
|
||||||
holder.statusLayout.visibility = if (status != null) View.VISIBLE else View.GONE
|
holder.statusLayout.visibility = if (status != null) View.VISIBLE else View.GONE
|
||||||
if (status != null) {
|
if (status != null) {
|
||||||
when (status) {
|
when (status) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.appcompat.widget.Toolbar
|
import android.widget.Toolbar
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import coil.api.clear
|
import coil.api.clear
|
||||||
import coil.api.load
|
import coil.api.load
|
||||||
@@ -55,7 +54,7 @@ class ProductsAdapter(private val onClick: (ProductItem) -> Unit):
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class EmptyViewHolder(context: Context): RecyclerView.ViewHolder(AppCompatTextView(context)) {
|
private class EmptyViewHolder(context: Context): RecyclerView.ViewHolder(TextView(context)) {
|
||||||
val text: TextView
|
val text: TextView
|
||||||
get() = itemView as TextView
|
get() = itemView as TextView
|
||||||
|
|
||||||
@@ -143,7 +142,7 @@ class ProductsAdapter(private val onClick: (ProductItem) -> Unit):
|
|||||||
resources.sizeScaled(4).let { setPadding(it, 0, it, 0) }
|
resources.sizeScaled(4).let { setPadding(it, 0, it, 0) }
|
||||||
setTextColor(holder.status.context.getColorFromAttr(android.R.attr.colorBackground))
|
setTextColor(holder.status.context.getColorFromAttr(android.R.attr.colorBackground))
|
||||||
background = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, null).apply {
|
background = GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, null).apply {
|
||||||
color = holder.status.context.getColorFromAttr(R.attr.colorAccent)
|
color = holder.status.context.getColorFromAttr(android.R.attr.colorAccent)
|
||||||
cornerRadius = holder.status.resources.sizeScaled(2).toFloat()
|
cornerRadius = holder.status.resources.sizeScaled(2).toFloat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class ProductsFragment(): Fragment(), CursorOwner.Callback {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||||
return RecyclerView(container!!.context).apply {
|
return RecyclerView(requireContext()).apply {
|
||||||
id = android.R.id.list
|
id = android.R.id.list
|
||||||
layoutManager = LinearLayoutManager(context)
|
layoutManager = LinearLayoutManager(context)
|
||||||
isMotionEventSplittingEnabled = false
|
isMotionEventSplittingEnabled = false
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ package nya.kitsunyan.foxydroid.screen
|
|||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Switch
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import nya.kitsunyan.foxydroid.R
|
import nya.kitsunyan.foxydroid.R
|
||||||
import nya.kitsunyan.foxydroid.database.Database
|
import nya.kitsunyan.foxydroid.database.Database
|
||||||
@@ -18,7 +18,7 @@ class RepositoriesAdapter(private val onClick: (Repository) -> Unit,
|
|||||||
|
|
||||||
private class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
private class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
|
||||||
val name = itemView.findViewById<TextView>(R.id.name)!!
|
val name = itemView.findViewById<TextView>(R.id.name)!!
|
||||||
val enabled = itemView.findViewById<SwitchCompat>(R.id.enabled)!!
|
val enabled = itemView.findViewById<Switch>(R.id.enabled)!!
|
||||||
|
|
||||||
var listenSwitch = true
|
var listenSwitch = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import android.view.MenuItem
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.appcompat.widget.Toolbar
|
import android.widget.Toolbar
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import android.widget.FrameLayout
|
|||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.Toolbar
|
import android.widget.Toolbar
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import android.widget.Toolbar
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
import nya.kitsunyan.foxydroid.R
|
import nya.kitsunyan.foxydroid.R
|
||||||
import nya.kitsunyan.foxydroid.content.Cache
|
import nya.kitsunyan.foxydroid.content.Cache
|
||||||
import nya.kitsunyan.foxydroid.content.Preferences
|
import nya.kitsunyan.foxydroid.content.Preferences
|
||||||
@@ -23,7 +23,7 @@ import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
|||||||
import nya.kitsunyan.foxydroid.utility.extension.text.*
|
import nya.kitsunyan.foxydroid.utility.extension.text.*
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
abstract class ScreenActivity: AppCompatActivity() {
|
abstract class ScreenActivity: FragmentActivity() {
|
||||||
companion object {
|
companion object {
|
||||||
private const val STATE_FRAGMENT_STACK = "fragmentStack"
|
private const val STATE_FRAGMENT_STACK = "fragmentStack"
|
||||||
}
|
}
|
||||||
@@ -162,7 +162,7 @@ abstract class ScreenActivity: AppCompatActivity() {
|
|||||||
internal fun onFragmentViewCreated(toolbar: Toolbar?) {
|
internal fun onFragmentViewCreated(toolbar: Toolbar?) {
|
||||||
this.toolbar = toolbar?.let(::WeakReference)
|
this.toolbar = toolbar?.let(::WeakReference)
|
||||||
if (fragmentStack.isNotEmpty() && toolbar != null) {
|
if (fragmentStack.isNotEmpty() && toolbar != null) {
|
||||||
toolbar.navigationIcon = toolbar.context.getDrawableFromAttr(R.attr.homeAsUpIndicator)
|
toolbar.navigationIcon = toolbar.context.getDrawableFromAttr(android.R.attr.homeAsUpIndicator)
|
||||||
toolbar.setNavigationOnClickListener { onBackPressed() }
|
toolbar.setNavigationOnClickListener { onBackPressed() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.appcompat.widget.AppCompatImageView
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.ColorUtils
|
import androidx.core.graphics.ColorUtils
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
@@ -75,7 +74,7 @@ class ScreenshotsFragment(): DialogFragment() {
|
|||||||
format = PixelFormat.TRANSLUCENT
|
format = PixelFormat.TRANSLUCENT
|
||||||
windowAnimations = run {
|
windowAnimations = run {
|
||||||
val typedArray = dialog.context.obtainStyledAttributes(null,
|
val typedArray = dialog.context.obtainStyledAttributes(null,
|
||||||
intArrayOf(android.R.attr.windowAnimationStyle), R.attr.dialogTheme, 0)
|
intArrayOf(android.R.attr.windowAnimationStyle), android.R.attr.dialogTheme, 0)
|
||||||
try {
|
try {
|
||||||
typedArray.getResourceId(0, 0)
|
typedArray.getResourceId(0, 0)
|
||||||
} finally {
|
} finally {
|
||||||
@@ -156,7 +155,7 @@ class ScreenshotsFragment(): DialogFragment() {
|
|||||||
StableRecyclerAdapter<Adapter.ViewType, RecyclerView.ViewHolder>() {
|
StableRecyclerAdapter<Adapter.ViewType, RecyclerView.ViewHolder>() {
|
||||||
enum class ViewType { SCREENSHOT }
|
enum class ViewType { SCREENSHOT }
|
||||||
|
|
||||||
private class ViewHolder(context: Context): RecyclerView.ViewHolder(AppCompatImageView(context)) {
|
private class ViewHolder(context: Context): RecyclerView.ViewHolder(ImageView(context)) {
|
||||||
val image: ImageView
|
val image: ImageView
|
||||||
get() = itemView as ImageView
|
get() = itemView as ImageView
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,12 @@ package nya.kitsunyan.foxydroid.screen
|
|||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.ColorFilter
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.PixelFormat
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -12,17 +18,15 @@ import android.view.animation.AccelerateInterpolator
|
|||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import android.widget.SearchView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
import android.widget.Toolbar
|
||||||
import androidx.appcompat.widget.SearchView
|
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.view.MenuCompat
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentStatePagerAdapter
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager.widget.ViewPager
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import com.google.android.material.tabs.TabLayout
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
import io.reactivex.rxjava3.disposables.Disposable
|
import io.reactivex.rxjava3.disposables.Disposable
|
||||||
@@ -34,6 +38,7 @@ import nya.kitsunyan.foxydroid.service.Connection
|
|||||||
import nya.kitsunyan.foxydroid.service.SyncService
|
import nya.kitsunyan.foxydroid.service.SyncService
|
||||||
import nya.kitsunyan.foxydroid.utility.RxUtils
|
import nya.kitsunyan.foxydroid.utility.RxUtils
|
||||||
import nya.kitsunyan.foxydroid.utility.Utils
|
import nya.kitsunyan.foxydroid.utility.Utils
|
||||||
|
import nya.kitsunyan.foxydroid.utility.extension.android.*
|
||||||
import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
||||||
import nya.kitsunyan.foxydroid.utility.extension.text.*
|
import nya.kitsunyan.foxydroid.utility.extension.text.*
|
||||||
import nya.kitsunyan.foxydroid.widget.EnumRecyclerAdapter
|
import nya.kitsunyan.foxydroid.widget.EnumRecyclerAdapter
|
||||||
@@ -49,7 +54,7 @@ class TabsFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class Layout(view: View) {
|
private class Layout(view: View) {
|
||||||
val tabLayout = view.findViewById<TabLayout>(R.id.tabs)!!
|
val tabs = view.findViewById<LinearLayout>(R.id.tabs)!!
|
||||||
val categoryLayout = view.findViewById<ViewGroup>(R.id.category_layout)!!
|
val categoryLayout = view.findViewById<ViewGroup>(R.id.category_layout)!!
|
||||||
val categoryChange = view.findViewById<View>(R.id.category_change)!!
|
val categoryChange = view.findViewById<View>(R.id.category_change)!!
|
||||||
val categoryName = view.findViewById<TextView>(R.id.category_name)!!
|
val categoryName = view.findViewById<TextView>(R.id.category_name)!!
|
||||||
@@ -57,17 +62,18 @@ class TabsFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var sortOrderMenu: Pair<MenuItem, List<MenuItem>>? = null
|
private var sortOrderMenu: Pair<MenuItem, List<MenuItem>>? = null
|
||||||
|
private var syncRepositoriesMenuItem: MenuItem? = null
|
||||||
private var layout: Layout? = null
|
private var layout: Layout? = null
|
||||||
private var categoriesList: RecyclerView? = null
|
private var categoriesList: RecyclerView? = null
|
||||||
private var viewPager: ViewPager? = null
|
private var viewPager: ViewPager2? = null
|
||||||
|
|
||||||
private var showCategories = false
|
private var showCategories = false
|
||||||
set(value) {
|
set(value) {
|
||||||
if (field != value) {
|
if (field != value) {
|
||||||
field = value
|
field = value
|
||||||
val layout = layout
|
val layout = layout
|
||||||
layout?.tabLayout?.let { (0 until it.tabCount)
|
layout?.tabs?.let { (0 until it.childCount)
|
||||||
.forEach { index -> it.getTabAt(index)!!.view.isEnabled = !value } }
|
.forEach { index -> it.getChildAt(index)!!.isEnabled = !value } }
|
||||||
layout?.categoryIcon?.scaleY = if (value) -1f else 1f
|
layout?.categoryIcon?.scaleY = if (value) -1f else 1f
|
||||||
if ((categoriesList?.parent as? View)?.height ?: 0 > 0) {
|
if ((categoriesList?.parent as? View)?.height ?: 0 > 0) {
|
||||||
animateCategoriesList()
|
animateCategoriesList()
|
||||||
@@ -127,7 +133,9 @@ class TabsFragment: Fragment() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
toolbar.menu.apply {
|
toolbar.menu.apply {
|
||||||
MenuCompat.setGroupDividerEnabled(this, true)
|
if (Android.sdk(28)) {
|
||||||
|
setGroupDividerEnabled(true)
|
||||||
|
}
|
||||||
|
|
||||||
add(0, R.id.toolbar_search, 0, R.string.search)
|
add(0, R.id.toolbar_search, 0, R.string.search)
|
||||||
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_search))
|
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_search))
|
||||||
@@ -138,21 +146,22 @@ class TabsFragment: Fragment() {
|
|||||||
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_sort))
|
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_sort))
|
||||||
.let { menu ->
|
.let { menu ->
|
||||||
menu.item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
menu.item.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_ALWAYS)
|
||||||
val items = ProductItem.Order.values().map { order -> menu
|
val items = ProductItem.Order.values().map { order ->
|
||||||
.add(order.titleResId)
|
menu
|
||||||
.setOnMenuItemClickListener { item ->
|
.add(order.titleResId)
|
||||||
this@TabsFragment.order = order
|
.setOnMenuItemClickListener { item ->
|
||||||
item.isChecked = true
|
this@TabsFragment.order = order
|
||||||
productFragments.forEach { it.setOrder(order) }
|
item.isChecked = true
|
||||||
true
|
productFragments.forEach { it.setOrder(order) }
|
||||||
} }
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
menu.setGroupCheckable(0, true, true)
|
menu.setGroupCheckable(0, true, true)
|
||||||
Pair(menu.item, items)
|
Pair(menu.item, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
add(0, 0, 0, R.string.sync_repositories)
|
syncRepositoriesMenuItem = add(0, 0, 0, R.string.sync_repositories)
|
||||||
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_sync))
|
.setIcon(Utils.getToolbarIcon(toolbar.context, R.drawable.ic_sync))
|
||||||
.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM)
|
|
||||||
.setOnMenuItemClickListener {
|
.setOnMenuItemClickListener {
|
||||||
syncConnection.binder?.sync(SyncService.SyncRequest.MANUAL)
|
syncConnection.binder?.sync(SyncService.SyncRequest.MANUAL)
|
||||||
true
|
true
|
||||||
@@ -179,16 +188,27 @@ class TabsFragment: Fragment() {
|
|||||||
val layout = Layout(view)
|
val layout = Layout(view)
|
||||||
this.layout = layout
|
this.layout = layout
|
||||||
|
|
||||||
ProductsFragment.Source.values().forEach { layout.tabLayout
|
layout.tabs.background = TabsBackgroundDrawable(layout.tabs.context,
|
||||||
.addTab(layout.tabLayout.newTab().setText(it.titleResId)) }
|
layout.tabs.layoutDirection == View.LAYOUT_DIRECTION_RTL)
|
||||||
layout.tabLayout.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener {
|
ProductsFragment.Source.values().forEach {
|
||||||
override fun onTabSelected(tab: TabLayout.Tab) {
|
val tab = TextView(layout.tabs.context)
|
||||||
viewPager!!.currentItem = tab.position
|
val selectedColor = tab.context.getColorFromAttr(android.R.attr.textColorPrimary).defaultColor
|
||||||
|
val normalColor = tab.context.getColorFromAttr(android.R.attr.textColorSecondary).defaultColor
|
||||||
|
tab.gravity = Gravity.CENTER
|
||||||
|
tab.typeface = TypefaceExtra.medium
|
||||||
|
tab.setTextColor(ColorStateList(arrayOf(intArrayOf(android.R.attr.state_selected), intArrayOf()),
|
||||||
|
intArrayOf(selectedColor, normalColor)))
|
||||||
|
tab.setTextSizeScaled(14)
|
||||||
|
tab.isAllCaps = true
|
||||||
|
tab.text = getString(it.titleResId)
|
||||||
|
tab.background = tab.context.getDrawableFromAttr(android.R.attr.selectableItemBackground)
|
||||||
|
tab.setOnClickListener { _ ->
|
||||||
|
setSelectedTab(it)
|
||||||
|
viewPager!!.currentItem = it.ordinal
|
||||||
}
|
}
|
||||||
|
layout.tabs.addView(tab, 0, LinearLayout.LayoutParams.MATCH_PARENT)
|
||||||
override fun onTabUnselected(tab: TabLayout.Tab) = Unit
|
(tab.layoutParams as LinearLayout.LayoutParams).weight = 1f
|
||||||
override fun onTabReselected(tab: TabLayout.Tab) = Unit
|
}
|
||||||
})
|
|
||||||
|
|
||||||
showCategories = savedInstanceState?.getByte(STATE_SHOW_CATEGORIES)?.toInt() ?: 0 != 0
|
showCategories = savedInstanceState?.getByte(STATE_SHOW_CATEGORIES)?.toInt() ?: 0 != 0
|
||||||
categories = savedInstanceState?.getStringArrayList(STATE_CATEGORIES).orEmpty()
|
categories = savedInstanceState?.getStringArrayList(STATE_CATEGORIES).orEmpty()
|
||||||
@@ -201,14 +221,16 @@ class TabsFragment: Fragment() {
|
|||||||
|
|
||||||
val content = view.findViewById<FrameLayout>(R.id.fragment_content)
|
val content = view.findViewById<FrameLayout>(R.id.fragment_content)
|
||||||
|
|
||||||
viewPager = ViewPager(content.context).apply {
|
viewPager = ViewPager2(content.context).apply {
|
||||||
id = R.id.fragment_pager
|
id = R.id.fragment_pager
|
||||||
adapter = object: FragmentStatePagerAdapter(childFragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
|
adapter = object: FragmentStateAdapter(this@TabsFragment) {
|
||||||
override fun getItem(position: Int): Fragment = ProductsFragment(ProductsFragment.Source.values()[position])
|
override fun getItemCount(): Int = ProductsFragment.Source.values().size
|
||||||
override fun getCount(): Int = ProductsFragment.Source.values().size
|
override fun createFragment(position: Int): Fragment = ProductsFragment(ProductsFragment
|
||||||
|
.Source.values()[position])
|
||||||
}
|
}
|
||||||
content.addView(this, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
content.addView(this, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
|
||||||
addOnPageChangeListener(pageChangeListener)
|
registerOnPageChangeCallback(pageChangeCallback)
|
||||||
|
offscreenPageLimit = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
categoriesDisposable = Observable.just(Unit)
|
categoriesDisposable = Observable.just(Unit)
|
||||||
@@ -238,7 +260,7 @@ class TabsFragment: Fragment() {
|
|||||||
updateCategory()
|
updateCategory()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setBackgroundColor(context.getColorFromAttr(R.attr.colorPrimaryDark).defaultColor)
|
setBackgroundColor(context.getColorFromAttr(android.R.attr.colorPrimaryDark).defaultColor)
|
||||||
elevation = resources.sizeScaled(4).toFloat()
|
elevation = resources.sizeScaled(4).toFloat()
|
||||||
content.addView(this, FrameLayout.LayoutParams.MATCH_PARENT, 0)
|
content.addView(this, FrameLayout.LayoutParams.MATCH_PARENT, 0)
|
||||||
visibility = View.GONE
|
visibility = View.GONE
|
||||||
@@ -268,6 +290,7 @@ class TabsFragment: Fragment() {
|
|||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|
||||||
sortOrderMenu = null
|
sortOrderMenu = null
|
||||||
|
syncRepositoriesMenuItem = null
|
||||||
layout = null
|
layout = null
|
||||||
categoriesList = null
|
categoriesList = null
|
||||||
viewPager = null
|
viewPager = null
|
||||||
@@ -294,7 +317,7 @@ class TabsFragment: Fragment() {
|
|||||||
|
|
||||||
if (needSelectUpdates) {
|
if (needSelectUpdates) {
|
||||||
needSelectUpdates = false
|
needSelectUpdates = false
|
||||||
selectUpdates()
|
selectUpdatesInternal(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,11 +331,19 @@ class TabsFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun selectUpdates() {
|
private fun setSelectedTab(source: ProductsFragment.Source) {
|
||||||
if (view == null) {
|
val layout = layout!!
|
||||||
needSelectUpdates = true
|
(0 until layout.tabs.childCount).forEach { layout.tabs.getChildAt(it).isSelected = it == source.ordinal }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun selectUpdates() = selectUpdatesInternal(true)
|
||||||
|
|
||||||
|
private fun selectUpdatesInternal(allowSmooth: Boolean) {
|
||||||
|
if (view != null) {
|
||||||
|
val viewPager = viewPager
|
||||||
|
viewPager?.setCurrentItem(ProductsFragment.Source.UPDATES.ordinal, allowSmooth && viewPager.isLaidOut)
|
||||||
} else {
|
} else {
|
||||||
layout?.tabLayout?.getTabAt(ProductsFragment.Source.UPDATES.ordinal)!!.select()
|
needSelectUpdates = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,7 +400,7 @@ class TabsFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val pageChangeListener = object: ViewPager.OnPageChangeListener {
|
private val pageChangeCallback = object: ViewPager2.OnPageChangeCallback() {
|
||||||
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
|
||||||
val layout = layout!!
|
val layout = layout!!
|
||||||
val fromCategories = ProductsFragment.Source.values()[position].categories
|
val fromCategories = ProductsFragment.Source.values()[position].categories
|
||||||
@@ -380,14 +411,12 @@ class TabsFragment: Fragment() {
|
|||||||
} else {
|
} else {
|
||||||
if (fromCategories) 1f else 0f
|
if (fromCategories) 1f else 0f
|
||||||
}
|
}
|
||||||
if (layout.categoryLayout.childCount != 1) {
|
(layout.tabs.background as TabsBackgroundDrawable)
|
||||||
throw RuntimeException()
|
.update(position + positionOffset, layout.tabs.childCount)
|
||||||
}
|
assert(layout.categoryLayout.childCount == 1)
|
||||||
val child = layout.categoryLayout.getChildAt(0)
|
val child = layout.categoryLayout.getChildAt(0)
|
||||||
val height = child.layoutParams.height
|
val height = child.layoutParams.height
|
||||||
if (height <= 0) {
|
assert(height > 0)
|
||||||
throw RuntimeException()
|
|
||||||
}
|
|
||||||
val currentHeight = (offset * height).roundToInt()
|
val currentHeight = (offset * height).roundToInt()
|
||||||
if (layout.categoryLayout.layoutParams.height != currentHeight) {
|
if (layout.categoryLayout.layoutParams.height != currentHeight) {
|
||||||
layout.categoryLayout.layoutParams.height = currentHeight
|
layout.categoryLayout.layoutParams.height = currentHeight
|
||||||
@@ -396,27 +425,63 @@ class TabsFragment: Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageSelected(position: Int) {
|
override fun onPageSelected(position: Int) {
|
||||||
val layout = layout!!
|
|
||||||
val source = ProductsFragment.Source.values()[position]
|
val source = ProductsFragment.Source.values()[position]
|
||||||
updateUpdateNotificationBlocker(source)
|
updateUpdateNotificationBlocker(source)
|
||||||
sortOrderMenu!!.first.isVisible = source.order
|
sortOrderMenu!!.first.isVisible = source.order
|
||||||
layout.tabLayout.selectTab(layout.tabLayout.getTabAt(source.ordinal))
|
syncRepositoriesMenuItem!!.setShowAsActionFlags(if (!source.order ||
|
||||||
|
resources.configuration.screenWidthDp >= 480) MenuItem.SHOW_AS_ACTION_ALWAYS else 0)
|
||||||
|
setSelectedTab(source)
|
||||||
if (showCategories && !source.categories) {
|
if (showCategories && !source.categories) {
|
||||||
showCategories = false
|
showCategories = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPageScrollStateChanged(state: Int) {
|
override fun onPageScrollStateChanged(state: Int) {
|
||||||
layout!!.categoryChange.isEnabled = state != ViewPager.SCROLL_STATE_DRAGGING &&
|
layout!!.categoryChange.isEnabled = state != ViewPager2.SCROLL_STATE_DRAGGING &&
|
||||||
ProductsFragment.Source.values()[viewPager!!.currentItem].categories
|
ProductsFragment.Source.values()[viewPager!!.currentItem].categories
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class TabsBackgroundDrawable(context: Context, private val rtl: Boolean): Drawable() {
|
||||||
|
private val height = context.resources.sizeScaled(2)
|
||||||
|
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||||
|
color = context.getColorFromAttr(android.R.attr.colorAccent).defaultColor
|
||||||
|
}
|
||||||
|
|
||||||
|
private var position = 0f
|
||||||
|
private var total = 0
|
||||||
|
|
||||||
|
fun update(position: Float, total: Int) {
|
||||||
|
this.position = position
|
||||||
|
this.total = total
|
||||||
|
invalidateSelf()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(canvas: Canvas) {
|
||||||
|
if (total > 0) {
|
||||||
|
val bounds = bounds
|
||||||
|
val width = bounds.width() / total.toFloat()
|
||||||
|
val x = width * position
|
||||||
|
if (rtl) {
|
||||||
|
canvas.drawRect(bounds.right - width - x, (bounds.bottom - height).toFloat(),
|
||||||
|
bounds.right - x, bounds.bottom.toFloat(), paint)
|
||||||
|
} else {
|
||||||
|
canvas.drawRect(bounds.left + x, (bounds.bottom - height).toFloat(),
|
||||||
|
bounds.left + x + width, bounds.bottom.toFloat(), paint)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setAlpha(alpha: Int) = Unit
|
||||||
|
override fun setColorFilter(colorFilter: ColorFilter?) = Unit
|
||||||
|
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
|
||||||
|
}
|
||||||
|
|
||||||
private class CategoriesAdapter(private val categories: () -> List<String>, private val onClick: (String) -> Unit):
|
private class CategoriesAdapter(private val categories: () -> List<String>, private val onClick: (String) -> Unit):
|
||||||
EnumRecyclerAdapter<CategoriesAdapter.ViewType, RecyclerView.ViewHolder>() {
|
EnumRecyclerAdapter<CategoriesAdapter.ViewType, RecyclerView.ViewHolder>() {
|
||||||
enum class ViewType { CATEGORY }
|
enum class ViewType { CATEGORY }
|
||||||
|
|
||||||
private class CategoryViewHolder(context: Context): RecyclerView.ViewHolder(AppCompatTextView(context)) {
|
private class CategoryViewHolder(context: Context): RecyclerView.ViewHolder(TextView(context)) {
|
||||||
val title: TextView
|
val title: TextView
|
||||||
get() = itemView as TextView
|
get() = itemView as TextView
|
||||||
|
|
||||||
@@ -426,7 +491,7 @@ class TabsFragment: Fragment() {
|
|||||||
itemView.resources.sizeScaled(16).let { itemView.setPadding(it, 0, it, 0) }
|
itemView.resources.sizeScaled(16).let { itemView.setPadding(it, 0, it, 0) }
|
||||||
itemView.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
itemView.setTextColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
|
||||||
itemView.setTextSizeScaled(16)
|
itemView.setTextSizeScaled(16)
|
||||||
itemView.background = context.getDrawableFromAttr(R.attr.selectableItemBackground)
|
itemView.background = context.getDrawableFromAttr(android.R.attr.selectableItemBackground)
|
||||||
itemView.layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,
|
itemView.layoutParams = RecyclerView.LayoutParams(RecyclerView.LayoutParams.MATCH_PARENT,
|
||||||
itemView.resources.sizeScaled(48))
|
itemView.resources.sizeScaled(48))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package nya.kitsunyan.foxydroid.service
|
|||||||
import android.app.Service
|
import android.app.Service
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import nya.kitsunyan.foxydroid.utility.extension.android.Android
|
import nya.kitsunyan.foxydroid.utility.extension.android.*
|
||||||
|
|
||||||
abstract class ConnectionService<T: IBinder>: Service() {
|
abstract class ConnectionService<T: IBinder>: Service() {
|
||||||
abstract override fun onBind(intent: Intent): T
|
abstract override fun onBind(intent: Intent): T
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.rxjava3.core.Observable
|
import io.reactivex.rxjava3.core.Observable
|
||||||
@@ -188,7 +188,7 @@ class DownloadService: ConnectionService<DownloadService.Binder>() {
|
|||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_warning)
|
.setSmallIcon(android.R.drawable.stat_sys_warning)
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.setContentIntent(PendingIntent.getBroadcast(this, 0, Intent(this, Receiver::class.java)
|
.setContentIntent(PendingIntent.getBroadcast(this, 0, Intent(this, Receiver::class.java)
|
||||||
.setAction("$ACTION_OPEN.${task.packageName}"), PendingIntent.FLAG_UPDATE_CURRENT))
|
.setAction("$ACTION_OPEN.${task.packageName}"), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
.apply {
|
.apply {
|
||||||
@@ -223,7 +223,7 @@ class DownloadService: ConnectionService<DownloadService.Binder>() {
|
|||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
.setSmallIcon(android.R.drawable.stat_sys_download_done)
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.setContentIntent(PendingIntent.getBroadcast(this, 0, Intent(this, Receiver::class.java)
|
.setContentIntent(PendingIntent.getBroadcast(this, 0, Intent(this, Receiver::class.java)
|
||||||
.setAction("$ACTION_INSTALL.${task.packageName}")
|
.setAction("$ACTION_INSTALL.${task.packageName}")
|
||||||
.putExtra(EXTRA_CACHE_FILE_NAME, task.release.cacheFileName), PendingIntent.FLAG_UPDATE_CURRENT))
|
.putExtra(EXTRA_CACHE_FILE_NAME, task.release.cacheFileName), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
@@ -286,7 +286,7 @@ class DownloadService: ConnectionService<DownloadService.Binder>() {
|
|||||||
.Builder(this, Common.NOTIFICATION_CHANNEL_DOWNLOADING)
|
.Builder(this, Common.NOTIFICATION_CHANNEL_DOWNLOADING)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_download)
|
.setSmallIcon(android.R.drawable.stat_sys_download)
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.addAction(0, getString(R.string.cancel), PendingIntent.getService(this, 0,
|
.addAction(0, getString(R.string.cancel), PendingIntent.getService(this, 0,
|
||||||
Intent(this, this::class.java).setAction(ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)) }
|
Intent(this, this::class.java).setAction(ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)) }
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import android.content.Intent
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.text.SpannableStringBuilder
|
import android.text.SpannableStringBuilder
|
||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import android.view.ContextThemeWrapper
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||||
@@ -200,7 +200,7 @@ class SyncService: ConnectionService<SyncService.Binder>() {
|
|||||||
.Builder(this, Common.NOTIFICATION_CHANNEL_SYNCING)
|
.Builder(this, Common.NOTIFICATION_CHANNEL_SYNCING)
|
||||||
.setSmallIcon(android.R.drawable.stat_sys_warning)
|
.setSmallIcon(android.R.drawable.stat_sys_warning)
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.setContentTitle(getString(R.string.error_syncing_format, repository.name))
|
.setContentTitle(getString(R.string.error_syncing_format, repository.name))
|
||||||
.setContentText(getString(when (exception) {
|
.setContentText(getString(when (exception) {
|
||||||
is RepositoryUpdater.UpdateException -> when (exception.errorType) {
|
is RepositoryUpdater.UpdateException -> when (exception.errorType) {
|
||||||
@@ -218,7 +218,7 @@ class SyncService: ConnectionService<SyncService.Binder>() {
|
|||||||
.Builder(this, Common.NOTIFICATION_CHANNEL_SYNCING)
|
.Builder(this, Common.NOTIFICATION_CHANNEL_SYNCING)
|
||||||
.setSmallIcon(R.drawable.ic_sync)
|
.setSmallIcon(R.drawable.ic_sync)
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.addAction(0, getString(R.string.cancel), PendingIntent.getService(this, 0,
|
.addAction(0, getString(R.string.cancel), PendingIntent.getService(this, 0,
|
||||||
Intent(this, this::class.java).setAction(ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)) }
|
Intent(this, this::class.java).setAction(ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)) }
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ class SyncService: ConnectionService<SyncService.Binder>() {
|
|||||||
.setContentText(resources.getQuantityString(R.plurals.new_updates_description_format,
|
.setContentText(resources.getQuantityString(R.plurals.new_updates_description_format,
|
||||||
productItems.size, productItems.size))
|
productItems.size, productItems.size))
|
||||||
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
.setColor(ContextThemeWrapper(this, R.style.Theme_Main_Light)
|
||||||
.getColorFromAttr(R.attr.colorAccent).defaultColor)
|
.getColorFromAttr(android.R.attr.colorAccent).defaultColor)
|
||||||
.setContentIntent(PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java)
|
.setContentIntent(PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java)
|
||||||
.setAction(MainActivity.ACTION_UPDATES), PendingIntent.FLAG_UPDATE_CURRENT))
|
.setAction(MainActivity.ACTION_UPDATES), PendingIntent.FLAG_UPDATE_CURRENT))
|
||||||
.setStyle(NotificationCompat.InboxStyle().applyHack {
|
.setStyle(NotificationCompat.InboxStyle().applyHack {
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ object Utils {
|
|||||||
|
|
||||||
fun getDefaultApplicationIcons(context: Context): Pair<Drawable, Drawable> {
|
fun getDefaultApplicationIcons(context: Context): Pair<Drawable, Drawable> {
|
||||||
val progressIcon: Drawable = createDefaultApplicationIcon(context, android.R.attr.textColorSecondary)
|
val progressIcon: Drawable = createDefaultApplicationIcon(context, android.R.attr.textColorSecondary)
|
||||||
val defaultIcon: Drawable = createDefaultApplicationIcon(context, R.attr.colorAccent)
|
val defaultIcon: Drawable = createDefaultApplicationIcon(context, android.R.attr.colorAccent)
|
||||||
return Pair(progressIcon, defaultIcon)
|
return Pair(progressIcon, defaultIcon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.graphics.Canvas
|
|||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
import nya.kitsunyan.foxydroid.utility.extension.resources.*
|
||||||
@@ -23,7 +24,7 @@ class RecyclerFastScroller(private val recyclerView: RecyclerView) {
|
|||||||
|
|
||||||
private val thumbDrawable = recyclerView.context.getDrawableFromAttr(android.R.attr.fastScrollThumbDrawable)
|
private val thumbDrawable = recyclerView.context.getDrawableFromAttr(android.R.attr.fastScrollThumbDrawable)
|
||||||
private val trackDrawable = recyclerView.context.getDrawableFromAttr(android.R.attr.fastScrollTrackDrawable)
|
private val trackDrawable = recyclerView.context.getDrawableFromAttr(android.R.attr.fastScrollTrackDrawable)
|
||||||
private val minTrackSize = recyclerView.resources.sizeScaled(32)
|
private val minTrackSize = recyclerView.resources.sizeScaled(16)
|
||||||
|
|
||||||
private data class FastScrolling(val startAtThumbOffset: Float?, val startY: Float, val currentY: Float)
|
private data class FastScrolling(val startAtThumbOffset: Float?, val startY: Float, val currentY: Float)
|
||||||
|
|
||||||
@@ -134,6 +135,7 @@ class RecyclerFastScroller(private val recyclerView: RecyclerView) {
|
|||||||
val atThumbVertical = if (rtl) event.x <= trackWidth else event.x >= recyclerView.width - trackWidth
|
val atThumbVertical = if (rtl) event.x <= trackWidth else event.x >= recyclerView.width - trackWidth
|
||||||
atThumbVertical && run {
|
atThumbVertical && run {
|
||||||
withScroll { itemHeight, thumbHeight, range ->
|
withScroll { itemHeight, thumbHeight, range ->
|
||||||
|
(recyclerView.parent as? ViewGroup)?.requestDisallowInterceptTouchEvent(true)
|
||||||
val offset = currentOffset(itemHeight, range)
|
val offset = currentOffset(itemHeight, range)
|
||||||
val thumbY = ((recyclerView.height - thumbHeight) * offset).roundToInt()
|
val thumbY = ((recyclerView.height - thumbHeight) * offset).roundToInt()
|
||||||
val atThumb = event.y >= thumbY && event.y <= thumbY + thumbHeight
|
val atThumb = event.y >= thumbY && event.y <= thumbY + thumbHeight
|
||||||
@@ -153,6 +155,7 @@ class RecyclerFastScroller(private val recyclerView: RecyclerView) {
|
|||||||
}
|
}
|
||||||
val cancel = event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
|
val cancel = event.action == MotionEvent.ACTION_UP || event.action == MotionEvent.ACTION_CANCEL
|
||||||
if (!success || cancel) {
|
if (!success || cancel) {
|
||||||
|
(recyclerView.parent as? ViewGroup)?.requestDisallowInterceptTouchEvent(false)
|
||||||
updateState(scrolling, null)
|
updateState(scrolling, null)
|
||||||
recyclerView.invalidate()
|
recyclerView.invalidate()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package nya.kitsunyan.foxydroid.widget
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.widget.Toolbar
|
||||||
|
|
||||||
|
class Toolbar: Toolbar {
|
||||||
|
constructor(context: Context): super(context)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?): super(context, attrs)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)
|
||||||
|
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int,
|
||||||
|
defStyleRes: Int): super(context, attrs, defStyleAttr, defStyleRes)
|
||||||
|
|
||||||
|
private var initalized = false
|
||||||
|
private var layoutDirectionChanged: Int? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
initalized = true
|
||||||
|
val layoutDirection = layoutDirectionChanged
|
||||||
|
layoutDirectionChanged = null
|
||||||
|
if (layoutDirection != null) {
|
||||||
|
onRtlPropertiesChanged(layoutDirection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onRtlPropertiesChanged(layoutDirection: Int) {
|
||||||
|
if (initalized) {
|
||||||
|
super.onRtlPropertiesChanged(layoutDirection)
|
||||||
|
} else {
|
||||||
|
layoutDirectionChanged = layoutDirection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -55,7 +55,8 @@
|
|||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/ic_arrow_down"
|
android:src="@drawable/ic_arrow_down"
|
||||||
android:tint="?android:attr/textColorSecondary"
|
android:tint="?android:attr/textColorSecondary"
|
||||||
android:background="?attr/actionBarItemBackground"
|
android:tintMode="src_in"
|
||||||
|
android:background="?android:attr/actionBarItemBackground"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
@@ -91,7 +92,7 @@
|
|||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="16dp"
|
android:paddingBottom="16dp"
|
||||||
android:gravity="top"
|
android:gravity="top"
|
||||||
android:typeface="monospace"
|
android:fontFamily="monospace"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:inputType="textNoSuggestions|textMultiLine"
|
android:inputType="textNoSuggestions|textMultiLine"
|
||||||
tools:ignore="Autofill,LabelFor" />
|
tools:ignore="Autofill,LabelFor" />
|
||||||
@@ -208,7 +209,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
style="@style/Widget.AppCompat.Button.Borderless.Colored"
|
style="@android:style/Widget.Material.Button.Borderless.Colored"
|
||||||
android:text="@string/skip" />
|
android:text="@string/skip" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,28 +1,30 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<nya.kitsunyan.foxydroid.widget.FragmentLinearLayout
|
<nya.kitsunyan.foxydroid.widget.FragmentLinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:theme="?attr/actionBarTheme">
|
android:orientation="vertical"
|
||||||
|
android:theme="?android:attr/actionBarTheme"
|
||||||
|
android:background="?android:attr/colorPrimary"
|
||||||
|
android:elevation="4dp">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<nya.kitsunyan.foxydroid.widget.Toolbar
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:popupTheme="@style/Theme.Toolbar.Popup" />
|
android:popupTheme="@style/Theme.Toolbar.Popup" />
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/toolbar_extra"
|
android:id="@+id/toolbar_extra"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" />
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/fragment_content"
|
android:id="@+id/fragment_content"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:scaleType="centerInside"
|
android:scaleType="centerInside"
|
||||||
android:tint="?android:attr/textColorSecondary"
|
android:tint="?android:attr/textColorSecondary"
|
||||||
|
android:tintMode="src_in"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:singleLine="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/summary"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/check"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="-16dp"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_gravity="bottom"
|
android:layout_gravity="bottom"
|
||||||
style="@style/Widget.AppCompat.Button.Colored" />
|
style="@android:style/Widget.Material.Button" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginBottom="2dp"
|
android:layout_marginBottom="2dp"
|
||||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal" />
|
style="@android:style/Widget.Material.ProgressBar.Horizontal" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
android:paddingStart="14dp"
|
android:paddingStart="14dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/icon"
|
android:id="@+id/icon"
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
android:layout_height="54dp"
|
android:layout_height="54dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:singleLine="true" />
|
android:singleLine="true" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<Switch
|
||||||
android:id="@+id/enabled"
|
android:id="@+id/enabled"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
@@ -25,6 +25,7 @@
|
|||||||
android:scaleType="center"
|
android:scaleType="center"
|
||||||
android:src="@drawable/ic_arrow_down"
|
android:src="@drawable/ic_arrow_down"
|
||||||
android:tint="?android:attr/textColorPrimary"
|
android:tint="?android:attr/textColorPrimary"
|
||||||
|
android:tintMode="src_in"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
android:layout_height="48dp"
|
android:layout_height="48dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:background="?attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title"
|
android:id="@+id/title"
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
android:singleLine="true" />
|
android:singleLine="true" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.SwitchCompat
|
<Switch
|
||||||
android:id="@+id/enabled"
|
android:id="@+id/enabled"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabLayout
|
<LinearLayout
|
||||||
android:id="@+id/tabs"
|
android:id="@+id/tabs"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="48dp"
|
||||||
app:tabGravity="fill"
|
android:orientation="horizontal" />
|
||||||
app:tabMaxWidth="0dp" />
|
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/category_layout"
|
android:id="@+id/category_layout"
|
||||||
@@ -27,7 +25,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingStart="12dp"
|
android:paddingStart="12dp"
|
||||||
android:paddingEnd="12dp"
|
android:paddingEnd="12dp"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
tools:ignore="UselessParent">
|
tools:ignore="UselessParent">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
|
||||||
|
<attr name="colorError" format="color" />
|
||||||
|
|
||||||
|
</resources>
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
<item type="id" name="divider_configuration" />
|
<item type="id" name="divider_configuration" />
|
||||||
<item type="id" name="fragment_pager" />
|
<item type="id" name="fragment_pager" />
|
||||||
<item type="id" name="main_content" />
|
<item type="id" name="main_content" />
|
||||||
|
<item type="id" name="preferences_list" />
|
||||||
<item type="id" name="toolbar_search" />
|
<item type="id" name="toolbar_search" />
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
<?xml version='1.0' encoding='utf-8'?>
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Theme.Main.Light" parent="Theme.AppCompat.Light.DarkActionBar">
|
<style name="Theme.Main.Light" parent="@android:style/Theme.Material.Light.DarkActionBar">
|
||||||
<item name="windowActionBar">false</item>
|
<item name="android:windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
<item name="android:colorBackground">#fffafafa</item>
|
<item name="android:colorBackground">#fffafafa</item>
|
||||||
<item name="colorPrimary">@color/primary_light</item>
|
<item name="android:colorPrimary">@color/primary_light</item>
|
||||||
<item name="colorPrimaryDark">@color/primary_dark_light</item>
|
<item name="android:colorPrimaryDark">@color/primary_dark_light</item>
|
||||||
<item name="colorAccent">@color/accent_light</item>
|
<item name="android:colorAccent">@color/accent_light</item>
|
||||||
<item name="colorControlActivated">@color/accent_default_light</item>
|
<item name="android:colorControlActivated">@color/accent_default_light</item>
|
||||||
<item name="colorError">@color/error_light</item>
|
<item name="colorError">@color/error_light</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Main.Dark" parent="Theme.AppCompat">
|
<style name="Theme.Main.Dark" parent="@android:style/Theme.Material">
|
||||||
<item name="windowActionBar">false</item>
|
<item name="android:windowActionBar">false</item>
|
||||||
<item name="windowNoTitle">true</item>
|
<item name="android:windowNoTitle">true</item>
|
||||||
<item name="android:colorBackground">#ff111111</item>
|
<item name="android:colorBackground">#ff111111</item>
|
||||||
<item name="colorPrimary">@color/primary_dark</item>
|
<item name="android:colorPrimary">@color/primary_dark</item>
|
||||||
<item name="colorPrimaryDark">@color/primary_dark_dark</item>
|
<item name="android:colorPrimaryDark">@color/primary_dark_dark</item>
|
||||||
<item name="colorAccent">@color/accent_dark</item>
|
<item name="android:colorAccent">@color/accent_dark</item>
|
||||||
<item name="colorControlActivated">@color/accent_default_dark</item>
|
<item name="android:colorControlActivated">@color/accent_default_dark</item>
|
||||||
<item name="colorError">@color/error_dark</item>
|
<item name="colorError">@color/error_dark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="Theme.Toolbar.Popup" parent="Theme.Main.Dark">
|
<style name="Theme.Toolbar.Popup" parent="Theme.Main.Dark">
|
||||||
<item name="android:colorBackground">?attr/colorPrimaryDark</item>
|
<item name="android:colorBackground">?android:attr/colorPrimaryDark</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user