ui: add edge-to-edge toggle
Add a toggle for edge-to-edge mode. Normally we would want to enable edge-to-edge by default (in fact, we still do). However, some phones (once again, samsung) don't provide Auxio with actual window insets. As a result, we need to add a toggle so that it can be disabled on busted devices. Did you know that even when Auxio has it's edge-to-edge functionality busted, Samsung Music works just fine? Very interesting. Resolves #149.
This commit is contained in:
parent
bd683ca09a
commit
c929357d76
6 changed files with 61 additions and 20 deletions
|
@ -32,6 +32,8 @@ import org.oxycblt.auxio.music.IndexerService
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.playback.system.PlaybackService
|
import org.oxycblt.auxio.playback.system.PlaybackService
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
|
import org.oxycblt.auxio.ui.accent.Accent
|
||||||
|
import org.oxycblt.auxio.util.getColorSafe
|
||||||
import org.oxycblt.auxio.util.isNight
|
import org.oxycblt.auxio.util.isNight
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||||
|
@ -54,11 +56,13 @@ class MainActivity : AppCompatActivity() {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
setupTheme()
|
val settingsManager = SettingsManager.getInstance()
|
||||||
|
|
||||||
|
setupTheme(settingsManager.theme, settingsManager.accent, settingsManager.useBlackTheme)
|
||||||
|
|
||||||
val binding = ActivityMainBinding.inflate(layoutInflater)
|
val binding = ActivityMainBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
applyEdgeToEdgeWindow(binding.root)
|
setupEdgeToEdge(binding.root, settingsManager.edgeToEdge)
|
||||||
|
|
||||||
logD("Activity created")
|
logD("Activity created")
|
||||||
}
|
}
|
||||||
|
@ -87,9 +91,12 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a [Uri] from an intent as long as:
|
||||||
|
* - The intent is ACTION_VIEW
|
||||||
|
* - The intent has not already been used.
|
||||||
|
*/
|
||||||
private fun retrieveViewUri(intent: Intent?): Uri? {
|
private fun retrieveViewUri(intent: Intent?): Uri? {
|
||||||
// If this intent is a valid view intent that has not been used already, give it
|
|
||||||
// to PlaybackViewModel to be used later.
|
|
||||||
if (intent != null) {
|
if (intent != null) {
|
||||||
val action = intent.action
|
val action = intent.action
|
||||||
val isConsumed = intent.getBooleanExtra(KEY_INTENT_USED, false)
|
val isConsumed = intent.getBooleanExtra(KEY_INTENT_USED, false)
|
||||||
|
@ -104,22 +111,18 @@ class MainActivity : AppCompatActivity() {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupTheme() {
|
private fun setupTheme(theme: Int, accent: Accent, useBlackTheme: Boolean) {
|
||||||
val settingsManager = SettingsManager.getInstance()
|
|
||||||
|
|
||||||
// Disable theme customization above Android 12, as it's far enough in as a version to
|
// Disable theme customization above Android 12, as it's far enough in as a version to
|
||||||
// the point where most phones should have an automatic option for light/dark theming.
|
// the point where most phones should have an automatic option for light/dark theming.
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||||
AppCompatDelegate.setDefaultNightMode(settingsManager.theme)
|
AppCompatDelegate.setDefaultNightMode(theme)
|
||||||
} else {
|
} else {
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
}
|
}
|
||||||
|
|
||||||
val accent = settingsManager.accent
|
|
||||||
|
|
||||||
// The black theme has a completely separate set of styles since style attributes cannot
|
// The black theme has a completely separate set of styles since style attributes cannot
|
||||||
// be modified at runtime.
|
// be modified at runtime.
|
||||||
if (isNight && settingsManager.useBlackTheme) {
|
if (isNight && useBlackTheme) {
|
||||||
logD("Applying black theme [accent $accent]")
|
logD("Applying black theme [accent $accent]")
|
||||||
setTheme(accent.blackTheme)
|
setTheme(accent.blackTheme)
|
||||||
} else {
|
} else {
|
||||||
|
@ -128,8 +131,21 @@ class MainActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun applyEdgeToEdgeWindow(contentView: View) {
|
private fun setupEdgeToEdge(contentView: View, enabled: Boolean) {
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
val fitsSystemWindows = !enabled
|
||||||
|
WindowCompat.setDecorFitsSystemWindows(window, fitsSystemWindows)
|
||||||
|
if (fitsSystemWindows) {
|
||||||
|
// Auxio's theme is normally set up to anticipate edge to edge mode being
|
||||||
|
// enabled. In the case that it is not, we have to update the values during
|
||||||
|
// runtime.
|
||||||
|
val controller = WindowCompat.getInsetsController(window, window.decorView)
|
||||||
|
val black = getColorSafe(android.R.color.black)
|
||||||
|
|
||||||
|
window.statusBarColor = black
|
||||||
|
controller.isAppearanceLightStatusBars = false
|
||||||
|
window.navigationBarColor = black
|
||||||
|
controller.isAppearanceLightNavigationBars = false
|
||||||
|
}
|
||||||
|
|
||||||
contentView.setOnApplyWindowInsetsListener { view, insets ->
|
contentView.setOnApplyWindowInsetsListener { view, insets ->
|
||||||
val bars = insets.systemBarInsetsCompat
|
val bars = insets.systemBarInsetsCompat
|
||||||
|
|
|
@ -122,6 +122,15 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
SettingsManager.KEY_ACCENT -> {
|
||||||
|
onPreferenceClickListener =
|
||||||
|
Preference.OnPreferenceClickListener {
|
||||||
|
AccentDialog().show(childFragmentManager, AccentDialog.TAG)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
summary = context.getString(settingsManager.accent.name)
|
||||||
|
}
|
||||||
SettingsManager.KEY_BLACK_THEME -> {
|
SettingsManager.KEY_BLACK_THEME -> {
|
||||||
onPreferenceClickListener =
|
onPreferenceClickListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceClickListener {
|
||||||
|
@ -132,14 +141,12 @@ class SettingsListFragment : PreferenceFragmentCompat() {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SettingsManager.KEY_ACCENT -> {
|
SettingsManager.KEY_EDGE_TO_EDGE -> {
|
||||||
onPreferenceClickListener =
|
onPreferenceChangeListener =
|
||||||
Preference.OnPreferenceClickListener {
|
Preference.OnPreferenceChangeListener { _, _ ->
|
||||||
AccentDialog().show(childFragmentManager, AccentDialog.TAG)
|
requireActivity().recreate()
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
summary = context.getString(settingsManager.accent.name)
|
|
||||||
}
|
}
|
||||||
SettingsManager.KEY_LIB_TABS -> {
|
SettingsManager.KEY_LIB_TABS -> {
|
||||||
onPreferenceClickListener =
|
onPreferenceClickListener =
|
||||||
|
|
|
@ -62,6 +62,10 @@ class SettingsManager private constructor(context: Context) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether edge-to-edge is enabled. */
|
||||||
|
val edgeToEdge: Boolean
|
||||||
|
get() = inner.getBoolean(KEY_EDGE_TO_EDGE, true)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to display the RepeatMode or the shuffle status on the notification. False if repeat,
|
* Whether to display the RepeatMode or the shuffle status on the notification. False if repeat,
|
||||||
* true if shuffle.
|
* true if shuffle.
|
||||||
|
@ -304,6 +308,7 @@ class SettingsManager private constructor(context: Context) :
|
||||||
const val KEY_THEME = "KEY_THEME2"
|
const val KEY_THEME = "KEY_THEME2"
|
||||||
const val KEY_BLACK_THEME = "KEY_BLACK_THEME"
|
const val KEY_BLACK_THEME = "KEY_BLACK_THEME"
|
||||||
const val KEY_ACCENT = "auxio_accent2"
|
const val KEY_ACCENT = "auxio_accent2"
|
||||||
|
const val KEY_EDGE_TO_EDGE = "auxio_edge"
|
||||||
|
|
||||||
const val KEY_LIB_TABS = "auxio_lib_tabs"
|
const val KEY_LIB_TABS = "auxio_lib_tabs"
|
||||||
const val KEY_SHOW_COVERS = "KEY_SHOW_COVERS"
|
const val KEY_SHOW_COVERS = "KEY_SHOW_COVERS"
|
||||||
|
|
|
@ -173,7 +173,10 @@ fun Fragment.launch(
|
||||||
* bit of a dumb hack with [combine], as when we have to combine flows, we often just want to call
|
* bit of a dumb hack with [combine], as when we have to combine flows, we often just want to call
|
||||||
* the same block with both functions, and not do any transformations.
|
* the same block with both functions, and not do any transformations.
|
||||||
*/
|
*/
|
||||||
suspend fun <T1, T2> Flow<T1>.collectWith(other: Flow<T2>, block: suspend (T1, T2) -> Unit) {
|
suspend inline fun <T1, T2> Flow<T1>.collectWith(
|
||||||
|
other: Flow<T2>,
|
||||||
|
crossinline block: (T1, T2) -> Unit
|
||||||
|
) {
|
||||||
combine(this, other) { a, b -> a to b }.collect { block(it.first, it.second) }
|
combine(this, other) { a, b -> a to b }.collect { block(it.first, it.second) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,8 @@
|
||||||
<string name="set_accent">Color scheme</string>
|
<string name="set_accent">Color scheme</string>
|
||||||
<string name="set_black_mode">Black theme</string>
|
<string name="set_black_mode">Black theme</string>
|
||||||
<string name="set_black_mode_desc">Use a pure-black dark theme</string>
|
<string name="set_black_mode_desc">Use a pure-black dark theme</string>
|
||||||
|
<string name="set_edge_to_edge">Edge-to-edge</string>
|
||||||
|
<string name="set_edge_to_edge_desc">May not work on all devices</string>
|
||||||
|
|
||||||
<string name="set_display">Display</string>
|
<string name="set_display">Display</string>
|
||||||
<string name="set_lib_tabs">Library tabs</string>
|
<string name="set_lib_tabs">Library tabs</string>
|
||||||
|
|
|
@ -27,6 +27,14 @@
|
||||||
app:summary="@string/set_black_mode_desc"
|
app:summary="@string/set_black_mode_desc"
|
||||||
app:title="@string/set_black_mode" />
|
app:title="@string/set_black_mode" />
|
||||||
|
|
||||||
|
<org.oxycblt.auxio.settings.pref.M3SwitchPreference
|
||||||
|
app:allowDividerBelow="false"
|
||||||
|
app:defaultValue="true"
|
||||||
|
app:iconSpaceReserved="false"
|
||||||
|
app:key="auxio_edge"
|
||||||
|
app:summary="@string/set_edge_to_edge_desc"
|
||||||
|
app:title="@string/set_edge_to_edge" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|
Loading…
Reference in a new issue