Splitting Light and Dark Theme setting

Soi you can stop complaining now
This commit is contained in:
Jays2Kings 2021-07-03 03:28:24 -04:00
parent 49e0d561b2
commit bed52c7b86
5 changed files with 139 additions and 59 deletions

View File

@ -19,7 +19,8 @@ class SettingsGeneralController : SettingsController() {
private val isUpdaterEnabled = BuildConfig.INCLUDE_UPDATER
var lastThemeX: Int? = null
var lastThemeXLight: Int? = null
var lastThemeXDark: Int? = null
var themePreference: ThemePreference? = null
override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
titleRes = R.string.general
@ -90,12 +91,13 @@ class SettingsGeneralController : SettingsController() {
}
preferenceCategory {
titleRes = R.string.display
titleRes = R.string.app_theme
themePreference = themePreference {
key = "theme_preference"
titleRes = R.string.app_theme
lastScrollPostion = lastThemeX
lastScrollPostionLight = lastThemeXLight
lastScrollPostionDark = lastThemeXDark
summary = if (preferences.nightMode()
.get() == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
) {
@ -124,7 +126,8 @@ class SettingsGeneralController : SettingsController() {
activity?.recreate()
} else {
preferences.nightMode().set(context.appDelegateNightMode())
themePreference?.fastAdapter?.notifyDataSetChanged()
themePreference?.fastAdapterLight?.notifyDataSetChanged()
themePreference?.fastAdapterDark?.notifyDataSetChanged()
}
true
}
@ -270,13 +273,16 @@ class SettingsGeneralController : SettingsController() {
}
override fun onSaveViewState(view: View, outState: Bundle) {
outState.putInt(::lastThemeX.name, themePreference?.lastScrollPostion ?: 0)
outState.putInt(::lastThemeXLight.name, themePreference?.lastScrollPostionLight ?: 0)
outState.putInt(::lastThemeXDark.name, themePreference?.lastScrollPostionDark ?: 0)
super.onSaveInstanceState(outState)
}
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
super.onRestoreViewState(view, savedViewState)
lastThemeX = savedViewState.getInt(::lastThemeX.name)
themePreference?.lastScrollPostion = lastThemeX
lastThemeXLight = savedViewState.getInt(::lastThemeXLight.name)
lastThemeXDark = savedViewState.getInt(::lastThemeXDark.name)
themePreference?.lastScrollPostionLight = lastThemeXLight
themePreference?.lastScrollPostionDark = lastThemeXDark
}
}

View File

@ -27,88 +27,128 @@ import eu.kanade.tachiyomi.util.system.appDelegateNightMode
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.isInNightMode
import uy.kohesive.injekt.injectLazy
import kotlin.math.max
class ThemePreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Preference(context, attrs) {
var fastAdapter: FastAdapter<ThemeItem>
private val itemAdapter = ItemAdapter<ThemeItem>()
private var selectExtension: SelectExtension<ThemeItem>
var fastAdapterLight: FastAdapter<ThemeItem>
var fastAdapterDark: FastAdapter<ThemeItem>
private val itemAdapterLight = ItemAdapter<ThemeItem>()
private val itemAdapterDark = ItemAdapter<ThemeItem>()
private var selectExtensionLight: SelectExtension<ThemeItem>
private var selectExtensionDark: SelectExtension<ThemeItem>
private val preferences: PreferencesHelper by injectLazy()
var activity: Activity? = null
var lastScrollPostion: Int? = null
var lastScrollPostionLight: Int? = null
var lastScrollPostionDark: Int? = null
lateinit var binding: ThemesPreferenceBinding
val manager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
private val managerLight = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
private val managerDark = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
init {
layoutResource = R.layout.themes_preference
fastAdapter = FastAdapter.with(itemAdapter)
fastAdapter.setHasStableIds(true)
selectExtension = fastAdapter.getSelectExtension().apply {
isSelectable = true
multiSelect = true
selectionListener = object : ISelectionListener<ThemeItem> {
override fun onSelectionChanged(item: ThemeItem, selected: Boolean) {
if (item.theme.nightMode == AppCompatDelegate.MODE_NIGHT_YES) {
preferences.darkTheme().set(item.theme)
} else {
preferences.lightTheme().set(item.theme)
}
if (!selected) {
preferences.nightMode().set(item.theme.nightMode)
} else if (preferences.nightMode()
.get() != AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
) {
preferences.nightMode().set(item.theme.nightMode)
}
if ((
preferences.nightMode().get() == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM &&
item.theme.nightMode != context.appDelegateNightMode()
) ||
(!selected && item.theme.nightMode == context.appDelegateNightMode())
) {
fastAdapter.notifyDataSetChanged()
} else {
activity?.recreate()
}
fastAdapterLight = FastAdapter.with(itemAdapterLight)
fastAdapterDark = FastAdapter.with(itemAdapterDark)
fastAdapterLight.setHasStableIds(true)
fastAdapterDark.setHasStableIds(true)
selectExtensionLight = fastAdapterLight.getSelectExtension().setThemeListener()
selectExtensionDark = fastAdapterDark.getSelectExtension().setThemeListener()
val enumConstants = Themes.values()
itemAdapterLight.set(enumConstants.filter { it.nightMode == AppCompatDelegate.MODE_NIGHT_NO }.map(::ThemeItem))
itemAdapterDark.set(enumConstants.filter { it.nightMode == AppCompatDelegate.MODE_NIGHT_YES }.map(::ThemeItem))
isSelectable = false
}
private fun SelectExtension<ThemeItem>.setThemeListener(): SelectExtension<ThemeItem> {
isSelectable = true
multiSelect = true
selectionListener = object : ISelectionListener<ThemeItem> {
override fun onSelectionChanged(item: ThemeItem, selected: Boolean) {
if (item.theme.nightMode == AppCompatDelegate.MODE_NIGHT_YES) {
preferences.darkTheme().set(item.theme)
} else {
preferences.lightTheme().set(item.theme)
}
if (!selected) {
preferences.nightMode().set(item.theme.nightMode)
} else if (preferences.nightMode()
.get() != AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
) {
preferences.nightMode().set(item.theme.nightMode)
}
if ((
preferences.nightMode().get() == AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM &&
item.theme.nightMode != context.appDelegateNightMode()
) ||
(!selected && item.theme.nightMode == context.appDelegateNightMode())
) {
fastAdapterLight.notifyDataSetChanged()
fastAdapterDark.notifyDataSetChanged()
} else {
activity?.recreate()
}
}
}
val enumConstants = Themes.values()
itemAdapter.set(enumConstants.map(::ThemeItem))
isSelectable = false
return this
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
binding = ThemesPreferenceBinding.bind(holder.itemView)
binding.themePrefTitle.text = title
binding.themeRecycler.setHasFixedSize(true)
binding.themeRecycler.layoutManager = manager
binding.themeRecycler.layoutManager = managerLight
binding.themeRecycler.adapter = fastAdapter
binding.themeRecycler.adapter = fastAdapterLight
binding.themeRecycler.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
lastScrollPostion =
lastScrollPostionLight =
recyclerView.computeHorizontalScrollOffset()
}
})
if (lastScrollPostion != null) {
val lX = lastScrollPostion!!
binding.themeRecyclerDark.setHasFixedSize(true)
binding.themeRecyclerDark.layoutManager = managerDark
binding.themeRecyclerDark.adapter = fastAdapterDark
binding.themeRecyclerDark.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy)
lastScrollPostionDark =
recyclerView.computeHorizontalScrollOffset()
}
})
if (lastScrollPostionLight != null) {
val lX = lastScrollPostionLight!!
(binding.themeRecycler.layoutManager as LinearLayoutManager).apply {
scrollToPositionWithOffset(
lX / 110.dpToPx,
-lX % 110.dpToPx
)
}
lastScrollPostion = binding.themeRecycler.computeHorizontalScrollOffset()
lastScrollPostionLight = binding.themeRecycler.computeHorizontalScrollOffset()
} else {
binding.themeRecycler.scrollToPosition(
selectExtension.selections.firstOrNull() ?: 0
max((selectExtensionLight.selections.firstOrNull() ?: 0) - 1, 0)
)
}
if (lastScrollPostionDark != null) {
val lX = lastScrollPostionDark!!
(binding.themeRecyclerDark.layoutManager as LinearLayoutManager).apply {
scrollToPositionWithOffset(
lX / 110.dpToPx,
-lX % 110.dpToPx
)
}
lastScrollPostionDark = binding.themeRecyclerDark.computeHorizontalScrollOffset()
} else {
binding.themeRecyclerDark.scrollToPosition(
max((selectExtensionDark.selections.firstOrNull() ?: 0) - 1, 0)
)
}
}

View File

@ -49,7 +49,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/theme_app_bar_preview"
android:background="?attr/colorSecondary"
android:elevation="2dp"
android:elevation="1dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

View File

@ -5,18 +5,18 @@
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.textview.MaterialTextView
android:id="@+id/theme_pref_title"
android:id="@+id/light_theme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/theme_recycler"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textAppearance="@style/TextAppearance.AppCompat.Menu"
android:text="@string/app_theme"/>
android:text="@string/light_theme"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/theme_recycler"
@ -26,10 +26,42 @@
android:paddingStart="4dp"
android:paddingEnd="0dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@id/theme_pref_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/light_theme"
app:layout_constraintBottom_toTopOf="@id/dark_theme"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:itemCount="2"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:orientation="horizontal"
android:clipToPadding="false"/>
<com.google.android.material.textview.MaterialTextView
android:id="@+id/dark_theme"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@id/theme_recycler"
app:layout_constraintBottom_toTopOf="@id/theme_recycler_dark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:textAppearance="@style/TextAppearance.AppCompat.Menu"
android:text="@string/dark_theme"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/theme_recycler_dark"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:listitem="@layout/theme_item"
android:paddingStart="4dp"
android:paddingEnd="0dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@id/dark_theme"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:orientation="horizontal"
tools:itemCount="2"
android:clipToPadding="false"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -602,6 +602,8 @@
<!-- General settings -->
<string name="app_theme">App theme</string>
<string name="light_theme">Light theme</string>
<string name="dark_theme">Dark theme</string>
<string name="light_blue">Light Blue</string>
<string name="dark">Dark</string>
<string name="amoled_black">AMOLED Black</string>