Heavily improve dialogs
Both improve and use dialogs - The AlertDialog style now properly colors dialogs with the primary coler - The accent & blacklist dialogs are now based on AlertDialog for their buttons, reducing layout complexity
This commit is contained in:
parent
53ec1aa8a5
commit
4d92df7896
8 changed files with 72 additions and 122 deletions
|
@ -4,6 +4,9 @@ import android.net.Uri
|
||||||
|
|
||||||
// --- MUSIC MODELS ---
|
// --- MUSIC MODELS ---
|
||||||
|
|
||||||
|
// TODO: Implement some kind of hash system, removing the need to redundant names but alsow without the volitility of id
|
||||||
|
// They need to be completely unique, however, and from whatever information I have about them.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base data object for all music.
|
* The base data object for all music.
|
||||||
* @property id The ID that is assigned to this object
|
* @property id The ID that is assigned to this object
|
||||||
|
@ -51,7 +54,7 @@ data class Song(
|
||||||
val album: Album get() = requireNotNull(mAlbum)
|
val album: Album get() = requireNotNull(mAlbum)
|
||||||
|
|
||||||
val seconds = duration / 1000
|
val seconds = duration / 1000
|
||||||
val formattedDuration: String = seconds.toDuration()
|
val formattedDuration = seconds.toDuration()
|
||||||
|
|
||||||
fun linkAlbum(album: Album) {
|
fun linkAlbum(album: Album) {
|
||||||
if (mAlbum == null) {
|
if (mAlbum == null) {
|
||||||
|
|
|
@ -4,13 +4,13 @@ import android.os.Bundle
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import org.oxycblt.auxio.databinding.DialogAccentBinding
|
import org.oxycblt.auxio.databinding.DialogAccentBinding
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.settings.SettingsManager
|
import org.oxycblt.auxio.settings.SettingsManager
|
||||||
import org.oxycblt.auxio.settings.ui.LifecycleDialog
|
import org.oxycblt.auxio.settings.ui.LifecycleDialog
|
||||||
import org.oxycblt.auxio.ui.ACCENTS
|
import org.oxycblt.auxio.ui.ACCENTS
|
||||||
import org.oxycblt.auxio.ui.Accent
|
import org.oxycblt.auxio.ui.Accent
|
||||||
import org.oxycblt.auxio.ui.inflater
|
|
||||||
import org.oxycblt.auxio.ui.toColor
|
import org.oxycblt.auxio.ui.toColor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,25 +38,11 @@ class AccentDialog : LifecycleDialog() {
|
||||||
adapter = AccentAdapter(pendingAccent) { accent ->
|
adapter = AccentAdapter(pendingAccent) { accent ->
|
||||||
pendingAccent = accent
|
pendingAccent = accent
|
||||||
|
|
||||||
updateAccent(binding)
|
updateAccent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.accentConfirm.setOnClickListener {
|
updateAccent()
|
||||||
if (pendingAccent != Accent.get()) {
|
|
||||||
settingsManager.accent = pendingAccent
|
|
||||||
|
|
||||||
requireActivity().recreate()
|
|
||||||
}
|
|
||||||
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.accentCancel.setOnClickListener {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
|
|
||||||
updateAccent(binding)
|
|
||||||
|
|
||||||
logD("Dialog created.")
|
logD("Dialog created.")
|
||||||
|
|
||||||
|
@ -69,11 +55,28 @@ class AccentDialog : LifecycleDialog() {
|
||||||
outState.putInt(KEY_PENDING_ACCENT, ACCENTS.indexOf(pendingAccent))
|
outState.putInt(KEY_PENDING_ACCENT, ACCENTS.indexOf(pendingAccent))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateAccent(binding: DialogAccentBinding) {
|
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
||||||
|
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
if (pendingAccent != Accent.get()) {
|
||||||
|
settingsManager.accent = pendingAccent
|
||||||
|
|
||||||
|
requireActivity().recreate()
|
||||||
|
}
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Negative button just dismisses, no need for a listener.
|
||||||
|
builder.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateAccent() {
|
||||||
val accentColor = pendingAccent.color.toColor(requireContext())
|
val accentColor = pendingAccent.color.toColor(requireContext())
|
||||||
|
|
||||||
binding.accentCancel.setTextColor(accentColor)
|
(requireDialog() as AlertDialog).apply {
|
||||||
binding.accentConfirm.setTextColor(accentColor)
|
getButton(AlertDialog.BUTTON_POSITIVE)?.setTextColor(accentColor)
|
||||||
|
getButton(AlertDialog.BUTTON_NEGATIVE)?.setTextColor(accentColor)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
|
@ -10,6 +10,7 @@ import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.fragment.app.viewModels
|
import androidx.fragment.app.viewModels
|
||||||
|
@ -19,9 +20,7 @@ import org.oxycblt.auxio.databinding.DialogBlacklistBinding
|
||||||
import org.oxycblt.auxio.logD
|
import org.oxycblt.auxio.logD
|
||||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||||
import org.oxycblt.auxio.settings.ui.LifecycleDialog
|
import org.oxycblt.auxio.settings.ui.LifecycleDialog
|
||||||
import org.oxycblt.auxio.ui.Accent
|
|
||||||
import org.oxycblt.auxio.ui.createToast
|
import org.oxycblt.auxio.ui.createToast
|
||||||
import org.oxycblt.auxio.ui.toColor
|
|
||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -42,43 +41,30 @@ class BlacklistDialog : LifecycleDialog() {
|
||||||
): View {
|
): View {
|
||||||
val binding = DialogBlacklistBinding.inflate(inflater)
|
val binding = DialogBlacklistBinding.inflate(inflater)
|
||||||
|
|
||||||
val launcher = registerForActivityResult(
|
|
||||||
ActivityResultContracts.OpenDocumentTree(), ::addDocTreePath
|
|
||||||
)
|
|
||||||
|
|
||||||
val accent = Accent.get().color.toColor(requireContext())
|
|
||||||
|
|
||||||
val adapter = BlacklistEntryAdapter { path ->
|
val adapter = BlacklistEntryAdapter { path ->
|
||||||
blacklistModel.removePath(path)
|
blacklistModel.removePath(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val launcher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.OpenDocumentTree(), ::addDocTreePath
|
||||||
|
)
|
||||||
|
|
||||||
// --- UI SETUP ---
|
// --- UI SETUP ---
|
||||||
|
|
||||||
binding.blacklistRecycler.adapter = adapter
|
binding.blacklistRecycler.adapter = adapter
|
||||||
|
|
||||||
// Dialogs don't know how to into theming, so I have to manually set the accent color
|
// Now that the dialog exists, we get the view manually when the dialog is shown
|
||||||
// to each of the buttons since the overall fragment theme is Neutral.
|
// and override its click-listener so that the dialog does not auto-dismiss when we
|
||||||
binding.blacklistAdd.apply {
|
// click the "Add"/"Save" buttons. This prevents the dialog from disappearing in the former
|
||||||
setTextColor(accent)
|
// and the app from crashing in the latter.
|
||||||
|
val dialog = requireDialog() as AlertDialog
|
||||||
|
|
||||||
setOnClickListener {
|
dialog.setOnShowListener {
|
||||||
// showFileDialog()
|
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)?.setOnClickListener {
|
||||||
launcher.launch(null)
|
launcher.launch(null)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
binding.blacklistCancel.apply {
|
dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.setOnClickListener {
|
||||||
setTextColor(accent)
|
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.blacklistConfirm.apply {
|
|
||||||
setTextColor(accent)
|
|
||||||
|
|
||||||
setOnClickListener {
|
|
||||||
if (blacklistModel.isModified()) {
|
if (blacklistModel.isModified()) {
|
||||||
saveAndRestart()
|
saveAndRestart()
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,6 +93,13 @@ class BlacklistDialog : LifecycleDialog() {
|
||||||
blacklistModel.loadDatabasePaths()
|
blacklistModel.loadDatabasePaths()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onConfigDialog(builder: AlertDialog.Builder) {
|
||||||
|
// Dont set the click listener here, we do some custom black magic in onCreateView instead.
|
||||||
|
builder.setNeutralButton(R.string.label_add, null)
|
||||||
|
builder.setPositiveButton(R.string.label_save, null)
|
||||||
|
builder.setNegativeButton(android.R.string.cancel, null)
|
||||||
|
}
|
||||||
|
|
||||||
private fun addDocTreePath(uri: Uri?) {
|
private fun addDocTreePath(uri: Uri?) {
|
||||||
uri ?: return
|
uri ?: return
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,19 @@ import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import org.oxycblt.auxio.R
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [DialogFragment] that replicates the Fragment lifecycle in regards to [AlertDialog], which
|
* A wrapper around [DialogFragment] that allows the usage of the standard Auxio lifecycle
|
||||||
* doesn't seem to set the view from onCreateView correctly.
|
* override [onCreateView] and [onDestroyView], but with a proper dialog being created.
|
||||||
*/
|
*/
|
||||||
abstract class LifecycleDialog : DialogFragment() {
|
abstract class LifecycleDialog : DialogFragment() {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
return MaterialAlertDialogBuilder(requireActivity(), theme).create()
|
val builder = AlertDialog.Builder(requireActivity(), R.style.Theme_CustomDialog)
|
||||||
|
|
||||||
|
onConfigDialog(builder)
|
||||||
|
|
||||||
|
return builder.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
@ -21,4 +25,6 @@ abstract class LifecycleDialog : DialogFragment() {
|
||||||
|
|
||||||
(requireDialog() as AlertDialog).setView(view)
|
(requireDialog() as AlertDialog).setView(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected open fun onConfigDialog(builder: AlertDialog.Builder) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,28 +36,5 @@
|
||||||
tools:itemCount="18"
|
tools:itemCount="18"
|
||||||
tools:listitem="@layout/item_accent" />
|
tools:listitem="@layout/item_accent" />
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="end"
|
|
||||||
android:padding="@dimen/padding_small">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/accent_cancel"
|
|
||||||
style="@style/Widget.Button.Dialog"
|
|
||||||
android:layout_marginEnd="@dimen/margin_small"
|
|
||||||
android:text="@android:string/cancel"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/accent_confirm" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/accent_confirm"
|
|
||||||
style="@style/Widget.Button.Dialog"
|
|
||||||
android:text="@android:string/ok"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/accent_cancel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/accent_cancel" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
|
@ -44,37 +44,5 @@
|
||||||
android:textAppearance="?android:attr/textAppearanceLarge"
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
android:textColor="?android:attr/textColorSecondary" />
|
android:textColor="?android:attr/textColorSecondary" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="bottom"
|
|
||||||
android:padding="@dimen/padding_small">
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/blacklist_cancel"
|
|
||||||
style="@style/Widget.Button.Dialog"
|
|
||||||
android:layout_marginEnd="@dimen/padding_small"
|
|
||||||
android:text="@android:string/cancel"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/blacklist_confirm"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/blacklist_add" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/blacklist_confirm"
|
|
||||||
style="@style/Widget.Button.Dialog"
|
|
||||||
android:text="@string/label_save"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/blacklist_cancel"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@+id/blacklist_cancel" />
|
|
||||||
|
|
||||||
<Button
|
|
||||||
android:id="@+id/blacklist_add"
|
|
||||||
style="@style/Widget.Button.Dialog"
|
|
||||||
android:text="@string/label_add"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</layout>
|
</layout>
|
|
@ -104,6 +104,7 @@
|
||||||
<string name="error_load_failed">Laden die Musik fehlgeschlagen</string>
|
<string name="error_load_failed">Laden die Musik fehlgeschlagen</string>
|
||||||
<string name="error_no_perms">Auxio braucht Berechtigung, zu lesen deine Musikbibliothek</string>
|
<string name="error_no_perms">Auxio braucht Berechtigung, zu lesen deine Musikbibliothek</string>
|
||||||
<string name="error_no_browser">Link könnte nicht geöffnet werden</string>
|
<string name="error_no_browser">Link könnte nicht geöffnet werden</string>
|
||||||
|
<string name="error_bad_dir">Das Verzeichnis ist nicht gestützt</string>
|
||||||
|
|
||||||
<!-- Hint Namespace | EditText Hints -->
|
<!-- Hint Namespace | EditText Hints -->
|
||||||
<string name="hint_search_library">Durchsuche deine Musikbibliothek…</string>
|
<string name="hint_search_library">Durchsuche deine Musikbibliothek…</string>
|
||||||
|
|
|
@ -79,11 +79,10 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Custom Dialog EntryNames -->
|
<!-- Custom Dialog EntryNames -->
|
||||||
<style name="Theme.CustomDialog" parent="Theme.MaterialComponents.DayNight.Dialog">
|
<style name="Theme.CustomDialog" parent="ThemeOverlay.AppCompat.Dialog.Alert">
|
||||||
<item name="colorBackgroundFloating">@color/background</item>
|
|
||||||
<item name="android:windowTitleStyle">@style/TextAppearance.Dialog.Title</item>
|
<item name="android:windowTitleStyle">@style/TextAppearance.Dialog.Title</item>
|
||||||
<item name="colorPrimary">@color/control_color</item>
|
<item name="colorBackgroundFloating">@color/background</item>
|
||||||
<item name="colorSecondary">@color/control_color</item>
|
<item name="buttonBarButtonStyle">@style/Widget.Button.Dialog</item>
|
||||||
<item name="dialogCornerRadius">0dp</item>
|
<item name="dialogCornerRadius">0dp</item>
|
||||||
<item name="colorControlHighlight">@color/selection_color</item>
|
<item name="colorControlHighlight">@color/selection_color</item>
|
||||||
</style>
|
</style>
|
||||||
|
@ -93,6 +92,17 @@
|
||||||
<item name="android:fontFamily">@font/inter_exbold</item>
|
<item name="android:fontFamily">@font/inter_exbold</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Style for dialog buttons -->
|
||||||
|
<style name="Widget.Button.Dialog" parent="Widget.AppCompat.Button.ButtonBar.AlertDialog">
|
||||||
|
<item name="android:layout_height">@dimen/height_dialog_button</item>
|
||||||
|
<item name="android:layout_width">wrap_content</item>
|
||||||
|
<item name="android:paddingStart">@dimen/padding_mid_small</item>
|
||||||
|
<item name="android:paddingEnd">@dimen/padding_mid_small</item>
|
||||||
|
<item name="android:minWidth">@dimen/width_dialog_button_min</item>
|
||||||
|
<item name="android:textColor">?attr/colorPrimary</item>
|
||||||
|
<item name="android:fontFamily">@font/inter_semibold</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<!-- Style for the general item background -->
|
<!-- Style for the general item background -->
|
||||||
<style name="ItemSurroundings">
|
<style name="ItemSurroundings">
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
|
@ -217,15 +227,4 @@
|
||||||
<item name="android:scaleType">fitCenter</item>
|
<item name="android:scaleType">fitCenter</item>
|
||||||
<item name="android:padding">@dimen/padding_medium</item>
|
<item name="android:padding">@dimen/padding_medium</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- Style for dialog buttons -->
|
|
||||||
<style name="Widget.Button.Dialog" parent="Widget.AppCompat.Button">
|
|
||||||
<item name="android:layout_height">@dimen/height_dialog_button</item>
|
|
||||||
<item name="android:layout_width">wrap_content</item>
|
|
||||||
<item name="android:paddingStart">@dimen/padding_mid_small</item>
|
|
||||||
<item name="android:paddingEnd">@dimen/padding_mid_small</item>
|
|
||||||
<item name="android:minWidth">@dimen/width_dialog_button_min</item>
|
|
||||||
<item name="android:background">@drawable/ui_ripple</item>
|
|
||||||
<item name="android:fontFamily">@font/inter_semibold</item>
|
|
||||||
</style>
|
|
||||||
</resources>
|
</resources>
|
Loading…
Reference in a new issue