ui: fix lollipop bugs
Fix more lollipop bugs, as I usually do. Except for the drawing issues I may or may not have produced. Don't really care enough to fix them though.
This commit is contained in:
parent
e12c7cb419
commit
5978e124d2
14 changed files with 85 additions and 93 deletions
|
@ -44,9 +44,6 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
*
|
*
|
||||||
* TODO: Add multi-select
|
* TODO: Add multi-select
|
||||||
*
|
*
|
||||||
* LEFT-OFF: Add RecyclerView styles, queue issue is caused by tiny scroll and then replace op, not
|
|
||||||
* enough to change scroll apparently
|
|
||||||
*
|
|
||||||
* @author OxygenCobalt
|
* @author OxygenCobalt
|
||||||
*/
|
*/
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
|
@ -128,9 +128,6 @@ private constructor(
|
||||||
|
|
||||||
binding.background.isInvisible = true
|
binding.background.isInvisible = true
|
||||||
|
|
||||||
binding.songName.requestLayout()
|
|
||||||
binding.songInfo.requestLayout()
|
|
||||||
|
|
||||||
binding.body.setOnClickListener { listener.onClick(this) }
|
binding.body.setOnClickListener { listener.onClick(this) }
|
||||||
|
|
||||||
// Roll our own drag handlers as the default ones suck
|
// Roll our own drag handlers as the default ones suck
|
||||||
|
|
|
@ -49,12 +49,14 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemList
|
||||||
binding.queueRecycler.apply {
|
binding.queueRecycler.apply {
|
||||||
adapter = queueAdapter
|
adapter = queueAdapter
|
||||||
touchHelper.attachToRecyclerView(this)
|
touchHelper.attachToRecyclerView(this)
|
||||||
|
|
||||||
|
// Sometimes the scroll can change without the listener being updated, so we also
|
||||||
|
// check for relayout events.
|
||||||
|
addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ -> invalidateDivider() }
|
||||||
addOnScrollListener(
|
addOnScrollListener(
|
||||||
object : RecyclerView.OnScrollListener() {
|
object : RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
binding.queueDivider.isInvisible =
|
invalidateDivider()
|
||||||
(layoutManager as LinearLayoutManager)
|
|
||||||
.findFirstCompletelyVisibleItemPosition() < 1
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -78,6 +80,8 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemList
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateQueue(queue: List<Song>, index: Int) {
|
private fun updateQueue(queue: List<Song>, index: Int) {
|
||||||
|
val binding = requireBinding()
|
||||||
|
|
||||||
val replaceQueue = queueModel.replaceQueue
|
val replaceQueue = queueModel.replaceQueue
|
||||||
if (replaceQueue == true) {
|
if (replaceQueue == true) {
|
||||||
logD("Replacing queue")
|
logD("Replacing queue")
|
||||||
|
@ -87,11 +91,14 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemList
|
||||||
queueAdapter.data.submitList(queue)
|
queueAdapter.data.submitList(queue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.queueDivider.isInvisible =
|
||||||
|
(binding.queueRecycler.layoutManager as LinearLayoutManager)
|
||||||
|
.findFirstCompletelyVisibleItemPosition() < 1
|
||||||
|
|
||||||
queueModel.finishReplace()
|
queueModel.finishReplace()
|
||||||
|
|
||||||
val scrollTo = queueModel.scrollTo
|
val scrollTo = queueModel.scrollTo
|
||||||
if (scrollTo != null) {
|
if (scrollTo != null) {
|
||||||
val binding = requireBinding()
|
|
||||||
val lmm = binding.queueRecycler.layoutManager as LinearLayoutManager
|
val lmm = binding.queueRecycler.layoutManager as LinearLayoutManager
|
||||||
val start = lmm.findFirstCompletelyVisibleItemPosition()
|
val start = lmm.findFirstCompletelyVisibleItemPosition()
|
||||||
val end = lmm.findLastCompletelyVisibleItemPosition()
|
val end = lmm.findLastCompletelyVisibleItemPosition()
|
||||||
|
@ -106,4 +113,11 @@ class QueueFragment : ViewBindingFragment<FragmentQueueBinding>(), QueueItemList
|
||||||
|
|
||||||
queueAdapter.updateIndex(index)
|
queueAdapter.updateIndex(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun invalidateDivider() {
|
||||||
|
val binding = requireBinding()
|
||||||
|
binding.queueDivider.isInvisible =
|
||||||
|
(binding.queueRecycler.layoutManager as LinearLayoutManager)
|
||||||
|
.findFirstCompletelyVisibleItemPosition() < 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
package org.oxycblt.auxio.settings
|
package org.oxycblt.auxio.settings
|
||||||
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
@ -154,45 +153,38 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
if (!preference.isVisible) return
|
if (!preference.isVisible) return
|
||||||
|
|
||||||
if (preference is PreferenceCategory) {
|
if (preference is PreferenceCategory) {
|
||||||
for (child in preference.children) {
|
preference.children.forEach(::setupPreference)
|
||||||
setupPreference(child)
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
preference.apply {
|
when (preference.key) {
|
||||||
when (key) {
|
context.getString(R.string.set_key_theme) -> {
|
||||||
context.getString(R.string.set_key_theme) -> {
|
preference.onPreferenceChangeListener =
|
||||||
// Android 12 is the first version I deem to have universal dark and light
|
Preference.OnPreferenceChangeListener { _, value ->
|
||||||
// mode toggles. No need for our setting.
|
AppCompatDelegate.setDefaultNightMode(value as Int)
|
||||||
isVisible = Build.VERSION.SDK_INT < Build.VERSION_CODES.S
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.getString(R.string.set_key_accent) -> {
|
||||||
|
preference.summary = context.getString(settings.accent.name)
|
||||||
|
}
|
||||||
|
context.getString(R.string.set_key_black_theme) -> {
|
||||||
|
preference.onPreferenceChangeListener =
|
||||||
|
Preference.OnPreferenceChangeListener { _, _ ->
|
||||||
|
if (context.isNight) {
|
||||||
|
context.recreate()
|
||||||
|
}
|
||||||
|
|
||||||
onPreferenceChangeListener =
|
true
|
||||||
Preference.OnPreferenceChangeListener { _, value ->
|
}
|
||||||
AppCompatDelegate.setDefaultNightMode(value as Int)
|
}
|
||||||
true
|
context.getString(R.string.set_key_show_covers),
|
||||||
}
|
context.getString(R.string.set_key_quality_covers) -> {
|
||||||
}
|
preference.onPreferenceChangeListener =
|
||||||
context.getString(R.string.set_key_accent) -> {
|
Preference.OnPreferenceChangeListener { _, _ ->
|
||||||
summary = context.getString(settings.accent.name)
|
Coil.imageLoader(context).memoryCache?.clear()
|
||||||
}
|
true
|
||||||
context.getString(R.string.set_key_black_theme) -> {
|
}
|
||||||
onPreferenceChangeListener =
|
|
||||||
Preference.OnPreferenceChangeListener { _, _ ->
|
|
||||||
if (context.isNight) {
|
|
||||||
context.recreate()
|
|
||||||
}
|
|
||||||
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
context.getString(R.string.set_key_show_covers),
|
|
||||||
context.getString(R.string.set_key_quality_covers) -> {
|
|
||||||
onPreferenceChangeListener =
|
|
||||||
Preference.OnPreferenceChangeListener { _, _ ->
|
|
||||||
Coil.imageLoader(context).apply { this.memoryCache?.clear() }
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ package org.oxycblt.auxio.ui
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
import android.graphics.drawable.LayerDrawable
|
import android.graphics.drawable.LayerDrawable
|
||||||
|
import android.os.Build
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
@ -79,8 +80,12 @@ abstract class AuxioSheetBehavior<V : View>(context: Context, attributeSet: Attr
|
||||||
context.getAttrColorCompat(R.attr.colorSurface).defaultColor),
|
context.getAttrColorCompat(R.attr.colorSurface).defaultColor),
|
||||||
sheetBackgroundDrawable))
|
sheetBackgroundDrawable))
|
||||||
|
|
||||||
// Try to disable drop shadows if possible.
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
||||||
disableDropShadowCompat()
|
val transparent =
|
||||||
|
context.getColorCompat(android.R.color.transparent).defaultColor
|
||||||
|
outlineAmbientShadowColor = transparent
|
||||||
|
outlineSpotShadowColor = transparent
|
||||||
|
}
|
||||||
|
|
||||||
setOnApplyWindowInsetsListener(::applyWindowInsets)
|
setOnApplyWindowInsetsListener(::applyWindowInsets)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,11 +55,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
|
|
||||||
override fun onScrolled(dx: Int, dy: Int) {
|
override fun onScrolled(dx: Int, dy: Int) {
|
||||||
super.onScrolled(dx, dy)
|
super.onScrolled(dx, dy)
|
||||||
|
invalidateDividers()
|
||||||
val manager = layoutManager as LinearLayoutManager
|
|
||||||
topDivider.isInvisible = manager.findFirstCompletelyVisibleItemPosition() < 1
|
|
||||||
bottomDivider.isInvisible =
|
|
||||||
manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMeasure(widthSpec: Int, heightSpec: Int) {
|
override fun onMeasure(widthSpec: Int, heightSpec: Int) {
|
||||||
|
@ -88,5 +84,13 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
||||||
super.onLayout(changed, l, t, r, b)
|
super.onLayout(changed, l, t, r, b)
|
||||||
topDivider.layout(l, spacingMedium, r, spacingMedium + topDivider.measuredHeight)
|
topDivider.layout(l, spacingMedium, r, spacingMedium + topDivider.measuredHeight)
|
||||||
bottomDivider.layout(l, measuredHeight - bottomDivider.measuredHeight, r, b)
|
bottomDivider.layout(l, measuredHeight - bottomDivider.measuredHeight, r, b)
|
||||||
|
invalidateDividers()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun invalidateDividers() {
|
||||||
|
val manager = layoutManager as LinearLayoutManager
|
||||||
|
topDivider.isInvisible = manager.findFirstCompletelyVisibleItemPosition() < 1
|
||||||
|
bottomDivider.isInvisible =
|
||||||
|
manager.findLastCompletelyVisibleItemPosition() == (manager.itemCount - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,18 +47,6 @@ import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.oxycblt.auxio.R
|
import org.oxycblt.auxio.R
|
||||||
|
|
||||||
/**
|
|
||||||
* Disables drop shadows on a view programmatically in a version-compatible manner. This only works
|
|
||||||
* on Android 9 and above. Below that version, shadows will remain visible.
|
|
||||||
*/
|
|
||||||
fun View.disableDropShadowCompat() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
||||||
val transparent = context.getColorCompat(android.R.color.transparent).defaultColor
|
|
||||||
outlineAmbientShadowColor = transparent
|
|
||||||
outlineSpotShadowColor = transparent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines if the point given by [x] and [y] falls within this view.
|
* Determines if the point given by [x] and [y] falls within this view.
|
||||||
* @param minTouchTargetSize The minimum touch size, independent of the view's size (Optional)
|
* @param minTouchTargetSize The minimum touch size, independent of the view's size (Optional)
|
||||||
|
|
|
@ -34,8 +34,7 @@ fun Any.logD(obj: Any?) = logD("$obj")
|
||||||
* objects
|
* objects
|
||||||
*/
|
*/
|
||||||
fun Any.logD(msg: String) {
|
fun Any.logD(msg: String) {
|
||||||
if (BuildConfig.DEBUG) {
|
if (BuildConfig.DEBUG && !basedCopyleftNotice()) {
|
||||||
basedCopyleftNotice()
|
|
||||||
Log.d(autoTag, msg)
|
Log.d(autoTag, msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,18 +57,6 @@ fun Any.logEOrThrow(msg: String) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs an error in production while still throwing it in debug mode. This is useful for
|
|
||||||
* non-showstopper bugs that I would still prefer to be caught in debug mode.
|
|
||||||
*/
|
|
||||||
fun Throwable.logTraceOrThrow() {
|
|
||||||
if (BuildConfig.DEBUG) {
|
|
||||||
throw this
|
|
||||||
} else {
|
|
||||||
logE(stackTraceToString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Automatically creates a tag that identifies the object currently logging. */
|
/** Automatically creates a tag that identifies the object currently logging. */
|
||||||
private val Any.autoTag: String
|
private val Any.autoTag: String
|
||||||
get() = "Auxio.${this::class.simpleName ?: "Anonymous Object"}"
|
get() = "Auxio.${this::class.simpleName ?: "Anonymous Object"}"
|
||||||
|
@ -84,31 +71,33 @@ private val Any.autoTag: String
|
||||||
*
|
*
|
||||||
* JUNE 1989 TIANAMEN SQUARE PROTESTS AND MASSACRE 六四事件
|
* JUNE 1989 TIANAMEN SQUARE PROTESTS AND MASSACRE 六四事件
|
||||||
*
|
*
|
||||||
* KASHMIR INDEPENDENCE MOVEMENT
|
* 2022 RUSSIAN INVASION OF UKRAINE Вторжение России на Украину
|
||||||
*
|
*
|
||||||
* WOMEN'S RIGHTS IN THE ISLAMIC REPUBLIC OF IRAN حقوق زنان در ایران
|
* WOMEN'S RIGHTS IN THE ISLAMIC REPUBLIC OF IRAN حقوق زنان در ایران
|
||||||
*
|
*
|
||||||
* FREE TIBET 西藏自由
|
|
||||||
*
|
|
||||||
* 1971 BANGLADESHI GENOCIDE BY PAKISTAN
|
|
||||||
*
|
|
||||||
* 2022 RUSSIAN INVASION OF UKRAINE Вторжение России на Украину
|
|
||||||
*
|
|
||||||
* UYGHUR GENOCIDE/XINJIANG INTERNMENT CAMPS 新疆种族灭绝指控/新疆再教育營
|
* UYGHUR GENOCIDE/XINJIANG INTERNMENT CAMPS 新疆种族灭绝指控/新疆再教育營
|
||||||
*
|
*
|
||||||
* KURDISTAN WORKERS PARTY KÜRDISTAN İŞÇI PARTISI (PKK)
|
* KASHMIR INDEPENDENCE MOVEMENT
|
||||||
*
|
*
|
||||||
* TORTURE AND ASSASSINATION OF JAMAL KHASHOGGI مقتل جمال خاشقجي
|
* FREE TIBET 西藏自由
|
||||||
|
*
|
||||||
|
* 1915-1916 ARMENIAN GENOCIDE Ermeni Kırımı
|
||||||
|
*
|
||||||
|
* 2018 TORTURE AND ASSASSINATION OF JAMAL KHASHOGGI مقتل جمال خاشقجي
|
||||||
*
|
*
|
||||||
* UNITED ARAB EMIRATES ENSLAVED MIGRANT WORKERS
|
* UNITED ARAB EMIRATES ENSLAVED MIGRANT WORKERS
|
||||||
*/
|
*/
|
||||||
@Suppress("KotlinConstantConditions")
|
@Suppress("KotlinConstantConditions")
|
||||||
private fun basedCopyleftNotice() {
|
private fun basedCopyleftNotice(): Boolean {
|
||||||
if (BuildConfig.APPLICATION_ID != "org.oxycblt.auxio" &&
|
if (BuildConfig.APPLICATION_ID != "org.oxycblt.auxio" &&
|
||||||
BuildConfig.APPLICATION_ID != "org.oxycblt.auxio.debug") {
|
BuildConfig.APPLICATION_ID != "org.oxycblt.auxio.debug") {
|
||||||
Log.d(
|
Log.d(
|
||||||
"Auxio Project",
|
"Auxio Project",
|
||||||
"Friendly reminder: Auxio is licensed under the " +
|
"Friendly reminder: Auxio is licensed under the " +
|
||||||
"GPLv3 and all derivative apps must be made open source!")
|
"GPLv3 and all derivative apps must be made open source!")
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Widget.Auxio.RecyclerView.Grid" parent="Widget.Auxio.RecyclerView.Grid.Base">
|
<style name="Widget.Auxio.RecyclerView.Grid" parent="Widget.Auxio.RecyclerView.Grid.Base">
|
||||||
<item name="spanCount">3</item>
|
<item name="spanCount">3</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
4
app/src/main/res/values-v31/settings.xml
Normal file
4
app/src/main/res/values-v31/settings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<bool name="enable_theme_settings">false</bool>
|
||||||
|
</resources>
|
|
@ -1,5 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
<bool name="enable_theme_settings">true</bool>
|
||||||
|
|
||||||
<!-- Note: The old way of naming keys was to prefix them with KEY_. Now it's to prefix them with auxio_. -->
|
<!-- Note: The old way of naming keys was to prefix them with KEY_. Now it's to prefix them with auxio_. -->
|
||||||
<string name="set_key_theme" translatable="false">KEY_THEME2</string>
|
<string name="set_key_theme" translatable="false">KEY_THEME2</string>
|
||||||
<string name="set_key_black_theme" translatable="false">KEY_BLACK_THEME</string>
|
<string name="set_key_black_theme" translatable="false">KEY_BLACK_THEME</string>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Master parent theme -->
|
<!-- Master parent theme -->
|
||||||
<style name="Theme.Auxio" parent="Theme.Material3.DynamicColors.DayNight" />
|
<style name="Theme.Auxio" parent="Theme.Material3.DynamicColors.DayNight" />
|
||||||
<!-- Adds nicer selector attributes not supported on lollipop-->
|
<!-- Adds nicer selector attributes not supported on lollipop -->
|
||||||
<style name="Theme.Auxio.V23" parent="Theme.Auxio" />
|
<style name="Theme.Auxio.V23" parent="Theme.Auxio" />
|
||||||
<!-- Handles edge-to-edge on other styles variants -->
|
<!-- Handles edge-to-edge on other styles variants -->
|
||||||
<style name="Theme.Auxio.V27" parent="Theme.Auxio.V23">
|
<style name="Theme.Auxio.V27" parent="Theme.Auxio.V23">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||||
<!-- SHARED RE-USABLE UI STYLES -->
|
<!-- SHARED RE-USABLE UI STYLES -->
|
||||||
|
|
||||||
<style name="Widget.Auxio.AppBarLayout" parent="Widget.Material3.AppBarLayout">
|
<style name="Widget.Auxio.AppBarLayout" parent="Widget.Material3.AppBarLayout">
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
app:entryIcons="@array/icons_theme"
|
app:entryIcons="@array/icons_theme"
|
||||||
app:entryValues="@array/values_theme"
|
app:entryValues="@array/values_theme"
|
||||||
app:icon="@drawable/ic_light_24"
|
app:icon="@drawable/ic_light_24"
|
||||||
|
app:isPreferenceVisible="@bool/enable_theme_settings"
|
||||||
app:key="@string/set_key_theme"
|
app:key="@string/set_key_theme"
|
||||||
app:title="@string/set_theme" />
|
app:title="@string/set_theme" />
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue