diff --git a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt index f7b293a06..e63c630ac 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/SongDetailDialog.kt @@ -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() { +class SongDetailDialog : ViewBindingMaterialDialogFragment() { 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. diff --git a/app/src/main/java/org/oxycblt/auxio/detail/picker/ShowArtistDialog.kt b/app/src/main/java/org/oxycblt/auxio/detail/picker/ShowArtistDialog.kt index a98dfb162..2e7ef1ba1 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/picker/ShowArtistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/picker/ShowArtistDialog.kt @@ -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(), ClickableListListener { + ViewBindingMaterialDialogFragment(), ClickableListListener { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt index c7dadd8d2..fd6b36ae7 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/tabs/TabCustomizeDialog.kt @@ -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(), EditClickListListener { + ViewBindingMaterialDialogFragment(), EditClickListListener { private val tabAdapter = TabAdapter(this) private var touchHelper: ItemTouchHelper? = null @Inject lateinit var homeSettings: HomeSettings diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt new file mode 100644 index 000000000..5129857dc --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuDialogFragment.kt @@ -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 . + */ + +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() { + 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) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/list/menu/MenuOptionAdapter.kt b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuOptionAdapter.kt new file mode 100644 index 000000000..a9e23f11e --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/list/menu/MenuOptionAdapter.kt @@ -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 . + */ + +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(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() { + override fun areItemsTheSame(oldItem: MenuItem, newItem: MenuItem) = + oldItem == newItem + + override fun areContentsTheSame(oldItem: MenuItem, newItem: MenuItem) = + oldItem.title == newItem.title + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/list/recycler/DialogRecyclerView.kt b/app/src/main/java/org/oxycblt/auxio/list/recycler/DialogRecyclerView.kt index 9fc255ce1..90a5786f6 100644 --- a/app/src/main/java/org/oxycblt/auxio/list/recycler/DialogRecyclerView.kt +++ b/app/src/main/java/org/oxycblt/auxio/list/recycler/DialogRecyclerView.kt @@ -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. diff --git a/app/src/main/java/org/oxycblt/auxio/music/fs/MusicDirsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/fs/MusicDirsDialog.kt index 4ecea1336..bca211f9a 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/fs/MusicDirsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/fs/MusicDirsDialog.kt @@ -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(), DirectoryAdapter.Listener { + ViewBindingMaterialDialogFragment(), DirectoryAdapter.Listener { private val dirAdapter = DirectoryAdapter(this) private var openDocumentTreeLauncher: ActivityResultLauncher? = null private var storageManager: StorageManager? = null diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt index 3496ea059..d74b9ba53 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt @@ -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() { +class SeparatorsDialog : ViewBindingMaterialDialogFragment() { @Inject lateinit var musicSettings: MusicSettings override fun onCreateBinding(inflater: LayoutInflater) = diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/AddToPlaylistDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/AddToPlaylistDialog.kt index d22f9a5e9..00175dc2a 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/AddToPlaylistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/AddToPlaylistDialog.kt @@ -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(), + ViewBindingMaterialDialogFragment(), ClickableListListener, NewPlaylistFooterAdapter.Listener { private val musicModel: MusicViewModel by activityViewModels() diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/DeletePlaylistDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/DeletePlaylistDialog.kt index 15d347199..fbe599750 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/DeletePlaylistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/DeletePlaylistDialog.kt @@ -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() { +class DeletePlaylistDialog : ViewBindingMaterialDialogFragment() { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/NewPlaylistDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/NewPlaylistDialog.kt index d0c4a03cc..b21925781 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/NewPlaylistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/NewPlaylistDialog.kt @@ -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() { +class NewPlaylistDialog : ViewBindingMaterialDialogFragment() { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/music/picker/RenamePlaylistDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/picker/RenamePlaylistDialog.kt index 20ed39bd5..024396525 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/picker/RenamePlaylistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/picker/RenamePlaylistDialog.kt @@ -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() { +class RenamePlaylistDialog : ViewBindingMaterialDialogFragment() { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt index e42e6ff61..1c7f025ef 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromArtistDialog.kt @@ -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(), ClickableListListener { + ViewBindingMaterialDialogFragment(), ClickableListListener { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt index 6811e3510..e47f87968 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/picker/PlayFromGenreDialog.kt @@ -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(), ClickableListListener { + ViewBindingMaterialDialogFragment(), ClickableListListener { 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 diff --git a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt index dcd7db42e..6cc1cea54 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/replaygain/PreAmpCustomizeDialog.kt @@ -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() { +class PreAmpCustomizeDialog : ViewBindingMaterialDialogFragment() { @Inject lateinit var playbackSettings: PlaybackSettings override fun onCreateBinding(inflater: LayoutInflater) = DialogPreAmpBinding.inflate(inflater) diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingBottomSheetDialogFragment.kt b/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingBottomSheetDialogFragment.kt new file mode 100644 index 000000000..2072d62e7 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingBottomSheetDialogFragment.kt @@ -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 . + */ + +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 : + 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") + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingDialogFragment.kt b/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingMaterialDialogFragment.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/ui/ViewBindingDialogFragment.kt rename to app/src/main/java/org/oxycblt/auxio/ui/ViewBindingMaterialDialogFragment.kt index 1615cbfd3..f12fe1b2e 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingDialogFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/ViewBindingMaterialDialogFragment.kt @@ -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 : DialogFragment() { +abstract class ViewBindingMaterialDialogFragment : DialogFragment() { private var _binding: VB? = null /** diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt index a09e0f0d5..c5ce7a5cc 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentCustomizeDialog.kt @@ -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(), ClickableListListener { + ViewBindingMaterialDialogFragment(), ClickableListListener { private var accentAdapter = AccentAdapter(this) @Inject lateinit var uiSettings: UISettings diff --git a/app/src/main/res/layout/dialog_menu.xml b/app/src/main/res/layout/dialog_menu.xml new file mode 100644 index 000000000..72534ff15 --- /dev/null +++ b/app/src/main/res/layout/dialog_menu.xml @@ -0,0 +1,24 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_menu_option.xml b/app/src/main/res/layout/item_menu_option.xml new file mode 100644 index 000000000..6064a7025 --- /dev/null +++ b/app/src/main/res/layout/item_menu_option.xml @@ -0,0 +1,12 @@ + + \ No newline at end of file diff --git a/app/src/main/res/navigation/main.xml b/app/src/main/res/navigation/main.xml index b1694965c..9d0736663 100644 --- a/app/src/main/res/navigation/main.xml +++ b/app/src/main/res/navigation/main.xml @@ -30,6 +30,9 @@ + @@ -297,6 +300,12 @@ app:argType="org.oxycblt.auxio.music.Music$UID" /> + + @style/Theme.Auxio.Dialog @style/Widget.Auxio.Slider @style/Widget.Auxio.LinearProgressIndicator + @style/Widget.Auxio.BottomSheet + @style/Widget.Auxio.BottomSheet.Dialog @style/TextAppearance.Auxio.DisplayLarge @style/TextAppearance.Auxio.DisplayMedium diff --git a/app/src/main/res/values/styles_ui.xml b/app/src/main/res/values/styles_ui.xml index 5ee16b401..105b4aab5 100644 --- a/app/src/main/res/values/styles_ui.xml +++ b/app/src/main/res/values/styles_ui.xml @@ -31,6 +31,28 @@ @dimen/size_corners_medium + + + + + +