list: add menu dialog framework
Add a dialog that shows menu information as a bottom sheet instead of as a PopupMenu. This did not take as much finessing of BottomSheetBehavior as the main playback UI framework did, just some style redefinitions.
This commit is contained in:
parent
6dc2892eb9
commit
c1158b1a07
23 changed files with 359 additions and 39 deletions
|
@ -38,18 +38,18 @@ import org.oxycblt.auxio.music.info.Name
|
|||
import org.oxycblt.auxio.music.metadata.AudioProperties
|
||||
import org.oxycblt.auxio.music.resolveNames
|
||||
import org.oxycblt.auxio.playback.formatDurationMs
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.concatLocalized
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [ViewBindingDialogFragment] that shows information about a Song.
|
||||
* A [ViewBindingMaterialDialogFragment] that shows information about a Song.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class SongDetailDialog : ViewBindingDialogFragment<DialogSongDetailBinding>() {
|
||||
class SongDetailDialog : ViewBindingMaterialDialogFragment<DialogSongDetailBinding>() {
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
// Information about what song to display is initially within the navigation arguments
|
||||
// as a UID, as that is the only safe way to parcel an song.
|
||||
|
|
|
@ -33,17 +33,17 @@ import org.oxycblt.auxio.detail.DetailViewModel
|
|||
import org.oxycblt.auxio.list.ClickableListListener
|
||||
import org.oxycblt.auxio.list.adapter.UpdateInstructions
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
|
||||
/**
|
||||
* A picker [ViewBindingDialogFragment] intended for when the [Artist] to show is ambiguous.
|
||||
* A picker [ViewBindingMaterialDialogFragment] intended for when the [Artist] to show is ambiguous.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class ShowArtistDialog :
|
||||
ViewBindingDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Artist> {
|
||||
ViewBindingMaterialDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Artist> {
|
||||
private val detailModel: DetailViewModel by activityViewModels()
|
||||
private val pickerModel: NavigationPickerViewModel by viewModels()
|
||||
// Information about what artists to show choices for is initially within the navigation
|
||||
|
|
|
@ -30,17 +30,18 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.DialogTabsBinding
|
||||
import org.oxycblt.auxio.home.HomeSettings
|
||||
import org.oxycblt.auxio.list.EditClickListListener
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* A [ViewBindingDialogFragment] that allows the user to modify the home [Tab] configuration.
|
||||
* A [ViewBindingMaterialDialogFragment] that allows the user to modify the home [Tab]
|
||||
* configuration.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class TabCustomizeDialog :
|
||||
ViewBindingDialogFragment<DialogTabsBinding>(), EditClickListListener<Tab> {
|
||||
ViewBindingMaterialDialogFragment<DialogTabsBinding>(), EditClickListListener<Tab> {
|
||||
private val tabAdapter = TabAdapter(this)
|
||||
private var touchHelper: ItemTouchHelper? = null
|
||||
@Inject lateinit var homeSettings: HomeSettings
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* MenuDialogFragment.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.list.menu
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuInflater
|
||||
import androidx.appcompat.view.menu.MenuBuilder
|
||||
import androidx.core.view.children
|
||||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogMenuBinding
|
||||
import org.oxycblt.auxio.list.adapter.UpdateInstructions
|
||||
import org.oxycblt.auxio.ui.ViewBindingBottomSheetDialogFragment
|
||||
|
||||
/**
|
||||
* A [ViewBindingBottomSheetDialogFragment] that displays basic music information and
|
||||
* a series of options.
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class MenuDialogFragment : ViewBindingBottomSheetDialogFragment<DialogMenuBinding>() {
|
||||
private val menuAdapter = MenuOptionAdapter()
|
||||
|
||||
override fun onCreateBinding(inflater: LayoutInflater) = DialogMenuBinding.inflate(inflater)
|
||||
|
||||
override fun onBindingCreated(binding: DialogMenuBinding, savedInstanceState: Bundle?) {
|
||||
super.onBindingCreated(binding, savedInstanceState)
|
||||
|
||||
binding.menuRecycler.apply {
|
||||
adapter = menuAdapter
|
||||
itemAnimator = null
|
||||
}
|
||||
|
||||
// Avoid having to use a dummy view and rely on what AndroidX Toolbar uses.
|
||||
@SuppressLint("RestrictedApi") val builder = MenuBuilder(requireContext())
|
||||
MenuInflater(requireContext()).inflate(R.menu.item_song, builder)
|
||||
menuAdapter.update(builder.children.toList(), UpdateInstructions.Diff)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2023 Auxio Project
|
||||
* MenuOptionAdapter.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.list.menu
|
||||
|
||||
import android.view.MenuItem
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import org.oxycblt.auxio.databinding.ItemMenuOptionBinding
|
||||
import org.oxycblt.auxio.list.adapter.FlexibleListAdapter
|
||||
import org.oxycblt.auxio.list.recycler.DialogRecyclerView
|
||||
import org.oxycblt.auxio.util.inflater
|
||||
|
||||
/**
|
||||
* Displays a list of [MenuItem]s as custom list items.
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class MenuOptionAdapter :
|
||||
FlexibleListAdapter<MenuItem, MenuOptionViewHolder>(MenuOptionViewHolder.DIFF_CALLBACK) {
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
|
||||
MenuOptionViewHolder.from(parent)
|
||||
|
||||
override fun onBindViewHolder(holder: MenuOptionViewHolder, position: Int) {
|
||||
holder.bind(getItem(position))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A [DialogRecyclerView.ViewHolder] that displays a list of menu options based on [MenuItem].
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
class MenuOptionViewHolder private constructor(private val binding: ItemMenuOptionBinding) :
|
||||
DialogRecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(item: MenuItem) {
|
||||
binding.title.text = item.title
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param parent The parent to inflate this instance from.
|
||||
* @return A new instance.
|
||||
*/
|
||||
fun from(parent: ViewGroup) =
|
||||
MenuOptionViewHolder(ItemMenuOptionBinding.inflate(parent.context.inflater))
|
||||
|
||||
/** A comparator that can be used with DiffUtil. */
|
||||
val DIFF_CALLBACK =
|
||||
object : DiffUtil.ItemCallback<MenuItem>() {
|
||||
override fun areItemsTheSame(oldItem: MenuItem, newItem: MenuItem) =
|
||||
oldItem == newItem
|
||||
|
||||
override fun areContentsTheSame(oldItem: MenuItem, newItem: MenuItem) =
|
||||
oldItem.title == newItem.title
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import android.content.Context
|
|||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowInsets
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.updatePadding
|
||||
|
@ -31,6 +32,7 @@ import com.google.android.material.divider.MaterialDivider
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.list.recycler.DialogRecyclerView.ViewHolder
|
||||
import org.oxycblt.auxio.util.getDimenPixels
|
||||
import org.oxycblt.auxio.util.systemBarInsetsCompat
|
||||
|
||||
/**
|
||||
* A [RecyclerView] intended for use in Dialogs, adding features such as:
|
||||
|
@ -74,6 +76,13 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
|
|||
invalidateDividers()
|
||||
}
|
||||
|
||||
override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets {
|
||||
// Update the RecyclerView's padding such that the bottom insets are applied
|
||||
// while still preserving bottom padding.
|
||||
updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
|
||||
return insets
|
||||
}
|
||||
|
||||
override fun onScrolled(dx: Int, dy: Int) {
|
||||
super.onScrolled(dx, dy)
|
||||
// Scroll event occurred, need to update the dividers.
|
||||
|
|
|
@ -35,7 +35,7 @@ import org.oxycblt.auxio.BuildConfig
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogMusicDirsBinding
|
||||
import org.oxycblt.auxio.music.MusicSettings
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.getSystemServiceCompat
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
@ -47,7 +47,7 @@ import org.oxycblt.auxio.util.showToast
|
|||
*/
|
||||
@AndroidEntryPoint
|
||||
class MusicDirsDialog :
|
||||
ViewBindingDialogFragment<DialogMusicDirsBinding>(), DirectoryAdapter.Listener {
|
||||
ViewBindingMaterialDialogFragment<DialogMusicDirsBinding>(), DirectoryAdapter.Listener {
|
||||
private val dirAdapter = DirectoryAdapter(this)
|
||||
private var openDocumentTreeLauncher: ActivityResultLauncher<Uri?>? = null
|
||||
private var storageManager: StorageManager? = null
|
||||
|
|
|
@ -29,19 +29,19 @@ import org.oxycblt.auxio.BuildConfig
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogSeparatorsBinding
|
||||
import org.oxycblt.auxio.music.MusicSettings
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.logW
|
||||
|
||||
/**
|
||||
* A [ViewBindingDialogFragment] that allows the user to configure the separator characters used to
|
||||
* split tags with multiple values.
|
||||
* A [ViewBindingMaterialDialogFragment] that allows the user to configure the separator characters
|
||||
* used to split tags with multiple values.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*
|
||||
* TODO: Replace with unsplit names dialog
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class SeparatorsDialog : ViewBindingDialogFragment<DialogSeparatorsBinding>() {
|
||||
class SeparatorsDialog : ViewBindingMaterialDialogFragment<DialogSeparatorsBinding>() {
|
||||
@Inject lateinit var musicSettings: MusicSettings
|
||||
|
||||
override fun onCreateBinding(inflater: LayoutInflater) =
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.oxycblt.auxio.databinding.DialogMusicChoicesBinding
|
|||
import org.oxycblt.auxio.list.ClickableListListener
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Song
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
@ -45,7 +45,7 @@ import org.oxycblt.auxio.util.showToast
|
|||
*/
|
||||
@AndroidEntryPoint
|
||||
class AddToPlaylistDialog :
|
||||
ViewBindingDialogFragment<DialogMusicChoicesBinding>(),
|
||||
ViewBindingMaterialDialogFragment<DialogMusicChoicesBinding>(),
|
||||
ClickableListListener<PlaylistChoice>,
|
||||
NewPlaylistFooterAdapter.Listener {
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
|
|
|
@ -30,19 +30,19 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.DialogDeletePlaylistBinding
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Playlist
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A [ViewBindingDialogFragment] that asks the user to confirm the deletion of a [Playlist].
|
||||
* A [ViewBindingMaterialDialogFragment] that asks the user to confirm the deletion of a [Playlist].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class DeletePlaylistDialog : ViewBindingDialogFragment<DialogDeletePlaylistBinding>() {
|
||||
class DeletePlaylistDialog : ViewBindingMaterialDialogFragment<DialogDeletePlaylistBinding>() {
|
||||
private val pickerModel: PlaylistPickerViewModel by viewModels()
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
// Information about what playlist to name for is initially within the navigation arguments
|
||||
|
|
|
@ -30,7 +30,7 @@ import dagger.hilt.android.AndroidEntryPoint
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogPlaylistNameBinding
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
@ -42,7 +42,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
|
|||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class NewPlaylistDialog : ViewBindingDialogFragment<DialogPlaylistNameBinding>() {
|
||||
class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBinding>() {
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
private val pickerModel: PlaylistPickerViewModel by viewModels()
|
||||
// Information about what playlist to name for is initially within the navigation arguments
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.DialogPlaylistNameBinding
|
||||
import org.oxycblt.auxio.music.MusicViewModel
|
||||
import org.oxycblt.auxio.music.Playlist
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.showToast
|
||||
|
@ -43,7 +43,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull
|
|||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class RenamePlaylistDialog : ViewBindingDialogFragment<DialogPlaylistNameBinding>() {
|
||||
class RenamePlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBinding>() {
|
||||
private val musicModel: MusicViewModel by activityViewModels()
|
||||
private val pickerModel: PlaylistPickerViewModel by viewModels()
|
||||
// Information about what playlist to name for is initially within the navigation arguments
|
||||
|
|
|
@ -33,19 +33,19 @@ import org.oxycblt.auxio.list.ClickableListListener
|
|||
import org.oxycblt.auxio.list.adapter.UpdateInstructions
|
||||
import org.oxycblt.auxio.music.Artist
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A picker [ViewBindingDialogFragment] intended for when [Artist] playback is ambiguous.
|
||||
* A picker [ViewBindingMaterialDialogFragment] intended for when [Artist] playback is ambiguous.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class PlayFromArtistDialog :
|
||||
ViewBindingDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Artist> {
|
||||
ViewBindingMaterialDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Artist> {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
private val pickerModel: PlaybackPickerViewModel by viewModels()
|
||||
// Information about what Song to show choices for is initially within the navigation arguments
|
||||
|
|
|
@ -33,19 +33,19 @@ import org.oxycblt.auxio.list.ClickableListListener
|
|||
import org.oxycblt.auxio.list.adapter.UpdateInstructions
|
||||
import org.oxycblt.auxio.music.Genre
|
||||
import org.oxycblt.auxio.playback.PlaybackViewModel
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.collectImmediately
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A picker [ViewBindingDialogFragment] intended for when [Genre] playback is ambiguous.
|
||||
* A picker [ViewBindingMaterialDialogFragment] intended for when [Genre] playback is ambiguous.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class PlayFromGenreDialog :
|
||||
ViewBindingDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Genre> {
|
||||
ViewBindingMaterialDialogFragment<DialogMusicChoicesBinding>(), ClickableListListener<Genre> {
|
||||
private val playbackModel: PlaybackViewModel by activityViewModels()
|
||||
private val pickerModel: PlaybackPickerViewModel by viewModels()
|
||||
// Information about what Song to show choices for is initially within the navigation arguments
|
||||
|
|
|
@ -28,16 +28,17 @@ import kotlin.math.abs
|
|||
import org.oxycblt.auxio.R
|
||||
import org.oxycblt.auxio.databinding.DialogPreAmpBinding
|
||||
import org.oxycblt.auxio.playback.PlaybackSettings
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.logD
|
||||
|
||||
/**
|
||||
* aa [ViewBindingDialogFragment] that allows user configuration of the current [ReplayGainPreAmp].
|
||||
* aa [ViewBindingMaterialDialogFragment] that allows user configuration of the current
|
||||
* [ReplayGainPreAmp].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class PreAmpCustomizeDialog : ViewBindingDialogFragment<DialogPreAmpBinding>() {
|
||||
class PreAmpCustomizeDialog : ViewBindingMaterialDialogFragment<DialogPreAmpBinding>() {
|
||||
@Inject lateinit var playbackSettings: PlaybackSettings
|
||||
|
||||
override fun onCreateBinding(inflater: LayoutInflater) = DialogPreAmpBinding.inflate(inflater)
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Auxio Project
|
||||
* ViewBindingBottomSheetDialogFragment.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.oxycblt.auxio.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A lifecycle-aware [DialogFragment] that automatically manages the [ViewBinding] lifecycle as a
|
||||
* [BottomSheetDialogFragment].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
abstract class ViewBindingBottomSheetDialogFragment<VB : ViewBinding> :
|
||||
BottomSheetDialogFragment() {
|
||||
private var _binding: VB? = null
|
||||
|
||||
/**
|
||||
* Configure the [AlertDialog.Builder] during [onCreateDialog].
|
||||
*
|
||||
* @param builder The [AlertDialog.Builder] to configure.
|
||||
* @see onCreateDialog
|
||||
*/
|
||||
protected open fun onConfigDialog(builder: AlertDialog.Builder) {}
|
||||
|
||||
/**
|
||||
* Inflate the [ViewBinding] during [onCreateView].
|
||||
*
|
||||
* @param inflater The [LayoutInflater] to inflate the [ViewBinding] with.
|
||||
* @return A new [ViewBinding] instance.
|
||||
* @see onCreateView
|
||||
*/
|
||||
protected abstract fun onCreateBinding(inflater: LayoutInflater): VB
|
||||
|
||||
/**
|
||||
* Configure the newly-inflated [ViewBinding] during [onViewCreated].
|
||||
*
|
||||
* @param binding The [ViewBinding] to configure.
|
||||
* @param savedInstanceState The previously saved state of the UI.
|
||||
* @see onViewCreated
|
||||
*/
|
||||
protected open fun onBindingCreated(binding: VB, savedInstanceState: Bundle?) {}
|
||||
|
||||
/**
|
||||
* Free memory held by the [ViewBinding] during [onDestroyView]
|
||||
*
|
||||
* @param binding The [ViewBinding] to release.
|
||||
* @see onDestroyView
|
||||
*/
|
||||
protected open fun onDestroyBinding(binding: VB) {}
|
||||
|
||||
/** The [ViewBinding], or null if it has not been inflated yet. */
|
||||
protected val binding: VB?
|
||||
get() = _binding
|
||||
|
||||
/**
|
||||
* Get the [ViewBinding] under the assumption that it has been inflated.
|
||||
*
|
||||
* @return The currently-inflated [ViewBinding].
|
||||
* @throws IllegalStateException if the [ViewBinding] is not inflated.
|
||||
*/
|
||||
protected fun requireBinding() =
|
||||
requireNotNull(_binding) {
|
||||
"ViewBinding was available. Fragment should be a valid state " +
|
||||
"right now, but instead it was ${lifecycle.currentState}"
|
||||
}
|
||||
|
||||
final override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
) = onCreateBinding(inflater).also { _binding = it }.root
|
||||
|
||||
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
onBindingCreated(requireBinding(), savedInstanceState)
|
||||
logD("Fragment created")
|
||||
}
|
||||
|
||||
final override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
onDestroyBinding(unlikelyToBeNull(_binding))
|
||||
// Clear binding
|
||||
_binding = null
|
||||
logD("Fragment destroyed")
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Auxio Project
|
||||
* ViewBindingDialogFragment.kt is part of Auxio.
|
||||
* ViewBindingMaterialDialogFragment.kt is part of Auxio.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -32,11 +32,12 @@ import org.oxycblt.auxio.util.logD
|
|||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A lifecycle-aware [DialogFragment] that automatically manages the [ViewBinding] lifecycle.
|
||||
* A lifecycle-aware [DialogFragment] that automatically manages the [ViewBinding] lifecycle as a
|
||||
* material dialog.
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
abstract class ViewBindingDialogFragment<VB : ViewBinding> : DialogFragment() {
|
||||
abstract class ViewBindingMaterialDialogFragment<VB : ViewBinding> : DialogFragment() {
|
||||
private var _binding: VB? = null
|
||||
|
||||
/**
|
|
@ -29,18 +29,18 @@ import org.oxycblt.auxio.R
|
|||
import org.oxycblt.auxio.databinding.DialogAccentBinding
|
||||
import org.oxycblt.auxio.list.ClickableListListener
|
||||
import org.oxycblt.auxio.ui.UISettings
|
||||
import org.oxycblt.auxio.ui.ViewBindingDialogFragment
|
||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||
import org.oxycblt.auxio.util.logD
|
||||
import org.oxycblt.auxio.util.unlikelyToBeNull
|
||||
|
||||
/**
|
||||
* A [ViewBindingDialogFragment] that allows the user to configure the current [Accent].
|
||||
* A [ViewBindingMaterialDialogFragment] that allows the user to configure the current [Accent].
|
||||
*
|
||||
* @author Alexander Capehart (OxygenCobalt)
|
||||
*/
|
||||
@AndroidEntryPoint
|
||||
class AccentCustomizeDialog :
|
||||
ViewBindingDialogFragment<DialogAccentBinding>(), ClickableListListener<Accent> {
|
||||
ViewBindingMaterialDialogFragment<DialogAccentBinding>(), ClickableListListener<Accent> {
|
||||
private var accentAdapter = AccentAdapter(this)
|
||||
@Inject lateinit var uiSettings: UISettings
|
||||
|
||||
|
|
24
app/src/main/res/layout/dialog_menu.xml
Normal file
24
app/src/main/res/layout/dialog_menu.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
style="@style/Widget.Auxio.RecyclerView.Linear"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/spacing_medium"
|
||||
android:paddingHorizontal="@dimen/spacing_medium"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.HeadlineSmall"
|
||||
android:text="TODO: Put info here" />
|
||||
|
||||
<org.oxycblt.auxio.list.recycler.DialogRecyclerView
|
||||
android:id="@+id/menu_recycler"
|
||||
style="@style/Widget.Auxio.RecyclerView.Linear"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:listitem="@layout/item_menu_option" />
|
||||
|
||||
</LinearLayout>
|
12
app/src/main/res/layout/item_menu_option.xml
Normal file
12
app/src/main/res/layout/item_menu_option.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@android:id/title"
|
||||
android:textAppearance="@style/TextAppearance.Auxio.TitleMedium"
|
||||
android:padding="@dimen/spacing_medium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="@drawable/ui_item_ripple"
|
||||
tools:text="Songs" />
|
|
@ -30,6 +30,9 @@
|
|||
<action
|
||||
android:id="@+id/show_genre"
|
||||
app:destination="@id/genre_detail_fragment" />
|
||||
<action
|
||||
android:id="@+id/open_menu"
|
||||
app:destination="@id/menu_dialog" />
|
||||
<action
|
||||
android:id="@+id/show_playlist"
|
||||
app:destination="@id/playlist_detail_fragment" />
|
||||
|
@ -297,6 +300,12 @@
|
|||
app:argType="org.oxycblt.auxio.music.Music$UID" />
|
||||
</dialog>
|
||||
|
||||
<dialog
|
||||
android:id="@+id/menu_dialog"
|
||||
android:name="org.oxycblt.auxio.list.menu.MenuDialogFragment"
|
||||
android:label="menu_dialog"
|
||||
tools:layout="@layout/dialog_menu" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/root_preferences_fragment"
|
||||
android:name="org.oxycblt.auxio.settings.RootPreferenceFragment"
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
<item name="materialAlertDialogTheme">@style/Theme.Auxio.Dialog</item>
|
||||
<item name="sliderStyle">@style/Widget.Auxio.Slider</item>
|
||||
<item name="linearProgressIndicatorStyle">@style/Widget.Auxio.LinearProgressIndicator</item>
|
||||
<item name="bottomSheetStyle">@style/Widget.Auxio.BottomSheet</item>
|
||||
<item name="bottomSheetDialogTheme">@style/Widget.Auxio.BottomSheet.Dialog</item>
|
||||
|
||||
<item name="textAppearanceDisplayLarge">@style/TextAppearance.Auxio.DisplayLarge</item>
|
||||
<item name="textAppearanceDisplayMedium">@style/TextAppearance.Auxio.DisplayMedium</item>
|
||||
|
|
|
@ -31,6 +31,28 @@
|
|||
<item name="trackCornerRadius">@dimen/size_corners_medium</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.BottomSheet" parent="Widget.Material3.BottomSheet">
|
||||
<item name="marginLeftSystemWindowInsets">false</item>
|
||||
<item name="marginRightSystemWindowInsets">false</item>
|
||||
<item name="paddingBottomSystemWindowInsets">false</item>
|
||||
<item name="paddingTopSystemWindowInsets">false</item>
|
||||
<item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.None</item>
|
||||
<item name="shouldRemoveExpandedCorners">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.BottomSheet.Modal" parent="Widget.Material3.BottomSheet.Modal">
|
||||
<item name="marginLeftSystemWindowInsets">false</item>
|
||||
<item name="marginRightSystemWindowInsets">false</item>
|
||||
<item name="paddingBottomSystemWindowInsets">false</item>
|
||||
<item name="paddingTopSystemWindowInsets">false</item>
|
||||
<item name="shapeAppearance">@style/ShapeAppearance.Material3.Corner.None</item>
|
||||
<item name="shouldRemoveExpandedCorners">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.BottomSheet.Dialog" parent="ThemeOverlay.Material3.BottomSheetDialog">
|
||||
<item name="bottomSheetStyle">@style/Widget.Auxio.BottomSheet.Modal</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Auxio.Image.Small" parent="">
|
||||
<item name="android:layout_width">@dimen/size_cover_compact</item>
|
||||
<item name="android:layout_height">@dimen/size_cover_compact</item>
|
||||
|
|
Loading…
Reference in a new issue