Store and restore ThemeChooserPreference state

pull/299/head
Koitharu 3 years ago
parent d05e777b2c
commit 5ce2bc92d6
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -17,6 +17,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.shelf.domain.ShelfSection import org.koitharu.kotatsu.shelf.domain.ShelfSection
import org.koitharu.kotatsu.utils.ext.connectivityManager import org.koitharu.kotatsu.utils.ext.connectivityManager
import org.koitharu.kotatsu.utils.ext.filterToSet
import org.koitharu.kotatsu.utils.ext.getEnumValue import org.koitharu.kotatsu.utils.ext.getEnumValue
import org.koitharu.kotatsu.utils.ext.observe import org.koitharu.kotatsu.utils.ext.observe
import org.koitharu.kotatsu.utils.ext.putEnumValue import org.koitharu.kotatsu.utils.ext.putEnumValue
@ -183,7 +184,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
} }
var hiddenSources: Set<String> var hiddenSources: Set<String>
get() = prefs.getStringSet(KEY_SOURCES_HIDDEN, null) ?: emptySet() get() = prefs.getStringSet(KEY_SOURCES_HIDDEN, null)?.filterToSet { name ->
remoteSources.any { it.name == name }
}.orEmpty()
set(value) = prefs.edit { putStringSet(KEY_SOURCES_HIDDEN, value) } set(value) = prefs.edit { putStringSet(KEY_SOURCES_HIDDEN, value) }
val isSourcesSelected: Boolean val isSourcesSelected: Boolean

@ -3,12 +3,17 @@ package org.koitharu.kotatsu.settings.utils
import android.content.Context import android.content.Context
import android.content.res.TypedArray import android.content.res.TypedArray
import android.os.Build import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewTreeObserver
import android.widget.HorizontalScrollView
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.customview.view.AbsSavedState
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder import androidx.preference.PreferenceViewHolder
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
@ -24,10 +29,12 @@ class ThemeChooserPreference @JvmOverloads constructor(
private val entries = ColorScheme.getAvailableList() private val entries = ColorScheme.getAvailableList()
private var currentValue: ColorScheme = ColorScheme.default private var currentValue: ColorScheme = ColorScheme.default
private val lastScrollPosition = intArrayOf(-1)
private val itemClickListener = View.OnClickListener { private val itemClickListener = View.OnClickListener {
val tag = it.tag as? ColorScheme ?: return@OnClickListener val tag = it.tag as? ColorScheme ?: return@OnClickListener
setValueInternal(tag.name, true) setValueInternal(tag.name, true)
} }
private var scrollPersistListener: ScrollPersistListener? = null
var value: String var value: String
get() = currentValue.name get() = currentValue.name
@ -36,7 +43,9 @@ class ThemeChooserPreference @JvmOverloads constructor(
override fun onBindViewHolder(holder: PreferenceViewHolder) { override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder) super.onBindViewHolder(holder)
val layout = holder.findViewById(R.id.linear) as? LinearLayout ?: return val layout = holder.findViewById(R.id.linear) as? LinearLayout ?: return
val scrollView = holder.findViewById(R.id.scrollView) as? HorizontalScrollView ?: return
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
scrollView.suppressLayout(true)
layout.suppressLayout(true) layout.suppressLayout(true)
} }
layout.removeAllViews() layout.removeAllViews()
@ -52,8 +61,19 @@ class ThemeChooserPreference @JvmOverloads constructor(
item.card.setOnClickListener(itemClickListener) item.card.setOnClickListener(itemClickListener)
layout.addView(item.root) layout.addView(item.root)
} }
if (lastScrollPosition[0] >= 0) {
val scroller = Scroller(scrollView, lastScrollPosition[0])
scroller.run()
scrollView.post(scroller)
}
scrollView.viewTreeObserver.run {
scrollPersistListener?.let { removeOnScrollChangedListener(it) }
scrollPersistListener = ScrollPersistListener(scrollView, lastScrollPosition)
addOnScrollChangedListener(scrollPersistListener)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
layout.suppressLayout(false) layout.suppressLayout(false)
scrollView.suppressLayout(false)
} }
} }
@ -71,6 +91,24 @@ class ThemeChooserPreference @JvmOverloads constructor(
return a.getInt(index, 0) return a.getInt(index, 0)
} }
override fun onSaveInstanceState(): Parcelable? {
val superState = super.onSaveInstanceState() ?: return null
return SavedState(
superState = superState,
scrollPosition = lastScrollPosition[0],
)
}
override fun onRestoreInstanceState(state: Parcelable?) {
if (state !is SavedState) {
super.onRestoreInstanceState(state)
return
}
super.onRestoreInstanceState(state.superState)
lastScrollPosition[0] = state.scrollPosition
// notifyChanged()
}
private fun setValueInternal(enumName: String, notifyChanged: Boolean) { private fun setValueInternal(enumName: String, notifyChanged: Boolean) {
val newValue = ColorScheme.safeValueOf(enumName) ?: return val newValue = ColorScheme.safeValueOf(enumName) ?: return
if (newValue != currentValue) { if (newValue != currentValue) {
@ -81,4 +119,55 @@ class ThemeChooserPreference @JvmOverloads constructor(
} }
} }
} }
private class SavedState : AbsSavedState {
val scrollPosition: Int
constructor(
superState: Parcelable,
scrollPosition: Int
) : super(superState) {
this.scrollPosition = scrollPosition
}
constructor(source: Parcel, classLoader: ClassLoader?) : super(source, classLoader) {
scrollPosition = source.readInt()
}
override fun writeToParcel(out: Parcel, flags: Int) {
super.writeToParcel(out, flags)
out.writeInt(scrollPosition)
}
companion object {
@Suppress("unused")
@JvmField
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
override fun createFromParcel(`in`: Parcel) = SavedState(`in`, SavedState::class.java.classLoader)
override fun newArray(size: Int): Array<SavedState?> = arrayOfNulls(size)
}
}
}
private class ScrollPersistListener(
private val scrollView: HorizontalScrollView,
private val lastScrollPosition: IntArray,
) : ViewTreeObserver.OnScrollChangedListener {
override fun onScrollChanged() {
lastScrollPosition[0] = scrollView.scrollX
}
}
private class Scroller(
private val scrollView: HorizontalScrollView,
private val position: Int,
) : Runnable {
override fun run() {
scrollView.scrollTo(position, 0)
}
}
} }

@ -1,7 +1,7 @@
package org.koitharu.kotatsu.utils.ext package org.koitharu.kotatsu.utils.ext
import androidx.collection.ArraySet import androidx.collection.ArraySet
import java.util.* import java.util.Collections
fun <T> MutableList<T>.move(sourceIndex: Int, targetIndex: Int) { fun <T> MutableList<T>.move(sourceIndex: Int, targetIndex: Int) {
if (sourceIndex <= targetIndex) { if (sourceIndex <= targetIndex) {
@ -11,14 +11,12 @@ fun <T> MutableList<T>.move(sourceIndex: Int, targetIndex: Int) {
} }
} }
@Suppress("FunctionName")
inline fun <T> MutableSet(size: Int, init: (index: Int) -> T): MutableSet<T> { inline fun <T> MutableSet(size: Int, init: (index: Int) -> T): MutableSet<T> {
val set = ArraySet<T>(size) val set = ArraySet<T>(size)
repeat(size) { index -> set.add(init(index)) } repeat(size) { index -> set.add(init(index)) }
return set return set
} }
@Suppress("FunctionName")
inline fun <T> Set(size: Int, init: (index: Int) -> T): Set<T> = when (size) { inline fun <T> Set(size: Int, init: (index: Int) -> T): Set<T> = when (size) {
0 -> emptySet() 0 -> emptySet()
1 -> Collections.singleton(init(0)) 1 -> Collections.singleton(init(0))
@ -39,3 +37,7 @@ fun <K, V> Map<K, V>.findKeyByValue(value: V): K? {
} }
return null return null
} }
inline fun <T> Collection<T>.filterToSet(predicate: (T) -> Boolean): Set<T> {
return filterTo(ArraySet(size), predicate)
}

@ -55,6 +55,7 @@
</LinearLayout> </LinearLayout>
<HorizontalScrollView <HorizontalScrollView
android:id="@+id/scrollView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"

Loading…
Cancel
Save