diff --git a/app/build.gradle b/app/build.gradle index 26e946794..0497e42f6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -97,8 +97,8 @@ dependencies { // Dialogs implementation 'com.afollestad.material-dialogs:core:3.3.0' - // Edge-To-Edge - implementation 'de.halfbit:edge-to-edge:0.10' + // Edge-To-Edge insets + implementation "dev.chrisbanes:insetter-ktx:0.3.1" // --- DEV --- diff --git a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt index cdeac30b2..c3f52cfc9 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainActivity.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainActivity.kt @@ -1,21 +1,34 @@ package org.oxycblt.auxio -import android.content.Context import android.content.Intent -import android.util.AttributeSet +import android.graphics.Color +import android.os.Build +import android.os.Bundle +import android.util.Log import android.view.View +import android.view.WindowInsets import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import androidx.databinding.DataBindingUtil +import dev.chrisbanes.insetter.applySystemWindowInsetsToMargin +import org.oxycblt.auxio.databinding.ActivityMainBinding import org.oxycblt.auxio.playback.PlaybackService import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.ui.accent +import org.oxycblt.auxio.ui.handleTransparentSystemBars // FIXME: Fix bug where fast navigation will break the animations and // lead to nothing being displayed [Possibly Un-fixable] // TODO: Landscape UI layouts // FIXME: Compat issue with Versions 5 that leads to progress bar looking off -class MainActivity : AppCompatActivity(R.layout.activity_main) { - override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? { +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val binding = DataBindingUtil.setContentView( + this, R.layout.activity_main + ) + val settingsManager = SettingsManager.init(applicationContext) AppCompatDelegate.setDefaultNightMode( @@ -27,7 +40,41 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) { // Apply the theme setTheme(accent.second) - return super.onCreateView(name, context, attrs) + // If enabled and possible, go through a stupidly long & complicated process + // just to get edge-to-edge to work. + // TODO: Make the navigation bar fully transparent + if (settingsManager.getEdgeToEdge() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { + window?.apply { + statusBarColor = Color.TRANSPARENT + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + Log.d(this::class.simpleName, "Doing R+ edge-to-edge.") + + setDecorFitsSystemWindows(false) + + binding.root.setOnApplyWindowInsetsListener { v, insets -> + WindowInsets.Builder() + .setInsets( + WindowInsets.Type.systemBars(), + insets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars()) + ) + .build() + } + } else { + Log.d(this::class.simpleName, "Doing deprec edge-to-edge.") + binding.root.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or + View.SYSTEM_UI_FLAG_LAYOUT_STABLE + } + + navigationBarColor = Color.TRANSPARENT + + handleTransparentSystemBars(resources.configuration) + + // I barely know how insets work so here's another third party library + // that I think does things + binding.root.applySystemWindowInsetsToMargin(top = false, bottom = false) + } + } } override fun onStart() { @@ -41,8 +88,4 @@ class MainActivity : AppCompatActivity(R.layout.activity_main) { fun doThemeRecreate(newTheme: Int) { AppCompatDelegate.setDefaultNightMode(newTheme) } - - fun doAccentRecreate() { - recreate() - } } diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/NoLeakThumbView.kt b/app/src/main/java/org/oxycblt/auxio/recycler/NoLeakThumbView.kt index 7d35af33f..f57771849 100644 --- a/app/src/main/java/org/oxycblt/auxio/recycler/NoLeakThumbView.kt +++ b/app/src/main/java/org/oxycblt/auxio/recycler/NoLeakThumbView.kt @@ -59,6 +59,9 @@ class NoLeakThumbView @JvmOverloads constructor( textView = thumbView.findViewById(R.id.fast_scroller_thumb_text) iconView = thumbView.findViewById(R.id.fast_scroller_thumb_icon) + isActivated = false + isVisible = false + applyStyle() thumbAnimation = SpringAnimation(thumbView, DynamicAnimation.TRANSLATION_Y).apply { @@ -87,10 +90,12 @@ class NoLeakThumbView @JvmOverloads constructor( ) ) { isActivated = false + isVisible = true return@setOnTouchListener true } isActivated = isPointerOnItem(fastScrollerView, event.y.toInt()) + isVisible = true true } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt index 55a982919..0ca1b7fb9 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt @@ -29,8 +29,7 @@ class SettingsListFragment : PreferenceFragmentCompat() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - view.apply { - } + // --- PREFERENCE ITEM SETUP --- val themePref = findPreference(SettingsManager.Keys.KEY_THEME)?.apply { setIcon( @@ -53,6 +52,8 @@ class SettingsListFragment : PreferenceFragmentCompat() { summary = getDetailedAccentSummary(requireActivity(), accent) } + // --- VIEWMODEL SETUP --- + settingsModel.theme.observe(viewLifecycleOwner) { if (it != null) { themePref?.setIcon( @@ -75,12 +76,20 @@ class SettingsListFragment : PreferenceFragmentCompat() { if (it != null) { accentPref?.summary = getDetailedAccentSummary(requireActivity(), it) - (requireActivity() as MainActivity).doAccentRecreate() + requireActivity().recreate() settingsModel.doneWithAccentUpdate() } } + settingsModel.edge.observe(viewLifecycleOwner) { + if (it != null) { + requireActivity().recreate() + + settingsModel.doneWithEdgeUpdate() + } + } + Log.d(this::class.simpleName, "Fragment created.") } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt index 87bef980c..7809b730c 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsManager.kt @@ -65,6 +65,10 @@ class SettingsManager private constructor(context: Context) : } } + fun getEdgeToEdge(): Boolean { + return sharedPrefs.getBoolean(Keys.KEY_EDGE_TO_EDGE, false) + } + fun setLibrarySortMode(sortMode: SortMode) { sharedPrefs.edit() .putInt(Keys.KEY_LIBRARY_SORT_MODE, sortMode.toInt()) @@ -80,10 +84,6 @@ class SettingsManager private constructor(context: Context) : ) ?: SortMode.ALPHA_DOWN } - fun getEdgeToEdge(): Boolean { - return sharedPrefs.getBoolean(Keys.KEY_EDGE_TO_EDGE, false) - } - // --- OVERRIDES --- override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { @@ -93,6 +93,12 @@ class SettingsManager private constructor(context: Context) : it.onThemeUpdate(getTheme()) } } + + Keys.KEY_EDGE_TO_EDGE -> { + callbacks.forEach { + it.onEdgeToEdgeUpdate(getEdgeToEdge()) + } + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsViewModel.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsViewModel.kt index dc8567a8a..6d1bb65b8 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsViewModel.kt @@ -11,6 +11,9 @@ class SettingsViewModel : ViewModel(), SettingsManager.Callback { private val mAccent = MutableLiveData?>() val accent: LiveData?> get() = mAccent + private val mEdge = MutableLiveData() + val edge: LiveData = mEdge + private val settingsManager = SettingsManager.getInstance() init { @@ -25,18 +28,22 @@ class SettingsViewModel : ViewModel(), SettingsManager.Callback { mAccent.value = null } - override fun onThemeUpdate(newTheme: Int) { - super.onThemeUpdate(newTheme) + fun doneWithEdgeUpdate() { + mEdge.value = null + } + override fun onThemeUpdate(newTheme: Int) { mTheme.value = newTheme } override fun onAccentUpdate(newAccent: Pair) { - super.onAccentUpdate(newAccent) - mAccent.value = newAccent } + override fun onEdgeToEdgeUpdate(isEdgeToEdge: Boolean) { + mEdge.value = isEdgeToEdge + } + override fun onCleared() { super.onCleared() diff --git a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt index 69ecff340..a71b9192e 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/InterfaceUtils.kt @@ -2,14 +2,20 @@ package org.oxycblt.auxio.ui import android.content.Context import android.content.res.ColorStateList +import android.content.res.Configuration +import android.os.Build import android.text.SpannableString import android.text.Spanned import android.text.style.ForegroundColorSpan import android.view.MenuItem +import android.view.View +import android.view.Window +import android.view.WindowInsetsController import android.widget.ImageButton import android.widget.Toast import androidx.annotation.ColorInt import androidx.annotation.MenuRes +import androidx.annotation.RequiresApi import androidx.appcompat.widget.PopupMenu import androidx.core.text.HtmlCompat import org.oxycblt.auxio.R @@ -66,6 +72,38 @@ fun Spanned.render(): Spanned { ) } +/** + * Handle transparent system bars on light mode. Adapted from Music Player GO + * (https://github.com/enricocid/Music-Player-GO) + */ +@RequiresApi(Build.VERSION_CODES.O_MR1) +@Suppress("DEPRECATION") +fun Window.handleTransparentSystemBars(config: Configuration) { + fun isNight() = config.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + insetsController?.let { controller -> + val appearance = WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS or + WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS + + val mask = if (isNight()) 0 else appearance + + controller.setSystemBarsAppearance(appearance, mask) + } + } else { + val flags = decorView.systemUiVisibility + + decorView.systemUiVisibility = + if (isNight()) { + flags and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() and + View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR.inv() + } else { + flags or View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR or + View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR + } + } +} + /** * Show actions for a song item, such as the ones found in [org.oxycblt.auxio.songs.SongsFragment] */ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index ca3d2093a..8e9e45eac 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -1,11 +1,14 @@ - \ No newline at end of file + xmlns:tools="http://schemas.android.com/tools" + tools:context=".MainActivity"> + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index a9ee109ec..5a8261312 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -8,6 +8,7 @@ @drawable/ui_cursor true none + false @style/Widget.CustomPopup @color/control_color @@ -15,9 +16,7 @@ @style/FastScrollTheme ?attr/colorPrimary ?attr/colorPrimary - @style/Theme.Preference - @android:color/transparent @color/background 0dp @color/control_color @@ -88,20 +87,9 @@ 18sp - - - \ No newline at end of file