From e01ea25d0b5ecf3371875db98664254d2b195b69 Mon Sep 17 00:00:00 2001 From: Alexander Capehart Date: Fri, 12 May 2023 10:39:56 -0600 Subject: [PATCH] music: add playlist naming flow Add a real playlist naming dialog and UX flow. This is a bit rough at the moment since theres a good amount of nuance here. Should improve as the playlist implementation continues to grow more fleshed out. --- CHANGELOG.md | 1 + .../java/org/oxycblt/auxio/MainFragment.kt | 13 ++- .../auxio/home/FlipFloatingActionButton.kt | 10 +- .../org/oxycblt/auxio/home/HomeFragment.kt | 2 +- .../org/oxycblt/auxio/music/MusicViewModel.kt | 17 ++- .../music/dialog/PlaylistDialogViewModel.kt | 106 ++++++++++++++++++ .../music/dialog/PlaylistNamingDialog.kt | 87 ++++++++++++++ .../{metadata => dialog}/SeparatorsDialog.kt | 15 ++- .../auxio/music/metadata/Separators.kt | 32 ------ .../oxycblt/auxio/music/metadata/TagWorker.kt | 4 + .../dialog/ArtistNavigationPickerDialog.kt | 2 +- ...wModel.kt => NavigationDialogViewModel.kt} | 6 +- .../dialog/ArtistPlaybackPickerDialog.kt | 2 +- .../dialog/GenrePlaybackPickerDialog.kt | 2 +- ...iewModel.kt => PlaybackDialogViewModel.kt} | 4 +- .../res/layout/dialog_playlist_naming.xml | 17 +++ app/src/main/res/navigation/nav_main.xml | 49 +++++--- app/src/main/res/values/strings.xml | 1 + 18 files changed, 302 insertions(+), 68 deletions(-) create mode 100644 app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistDialogViewModel.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistNamingDialog.kt rename app/src/main/java/org/oxycblt/auxio/music/{metadata => dialog}/SeparatorsDialog.kt (92%) delete mode 100644 app/src/main/java/org/oxycblt/auxio/music/metadata/Separators.kt rename app/src/main/java/org/oxycblt/auxio/navigation/dialog/{NavigationPickerViewModel.kt => NavigationDialogViewModel.kt} (96%) rename app/src/main/java/org/oxycblt/auxio/playback/dialog/{PlaybackPickerViewModel.kt => PlaybackDialogViewModel.kt} (95%) create mode 100644 app/src/main/res/layout/dialog_playlist_naming.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index 5581a3903..bbebcf85b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ be parsed as images - Fixed issue where searches would match song file names case-sensitively - Fixed issue where the notification would not respond to changes in the album cover setting +- Fixed issue where short names starting with an article would not be correctly sorted (ex. "the 1") ## 3.0.5 diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 817ef494e..148f665b1 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -40,7 +40,9 @@ import kotlin.math.min import org.oxycblt.auxio.databinding.FragmentMainBinding import org.oxycblt.auxio.list.selection.SelectionViewModel import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicViewModel import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.music.dialog.PendingName import org.oxycblt.auxio.navigation.MainNavigationAction import org.oxycblt.auxio.navigation.NavigationViewModel import org.oxycblt.auxio.playback.PlaybackBottomSheetBehavior @@ -60,8 +62,9 @@ class MainFragment : ViewBindingFragment(), ViewTreeObserver.OnPreDrawListener, NavController.OnDestinationChangedListener { - private val playbackModel: PlaybackViewModel by activityViewModels() private val navModel: NavigationViewModel by activityViewModels() + private val musicModel: MusicViewModel by activityViewModels() + private val playbackModel: PlaybackViewModel by activityViewModels() private val selectionModel: SelectionViewModel by activityViewModels() private val callback = DynamicBackPressedCallback() private var lastInsets: WindowInsets? = null @@ -132,6 +135,7 @@ class MainFragment : collect(navModel.mainNavigationAction.flow, ::handleMainNavigation) collect(navModel.exploreNavigationItem.flow, ::handleExploreNavigation) collect(navModel.exploreArtistNavigationItem.flow, ::handleArtistNavigationPicker) + collect(musicModel.pendingPlaylistNaming.flow, ::handlePlaylistNaming) collectImmediately(playbackModel.song, ::updateSong) collect(playbackModel.artistPickerSong.flow, ::handlePlaybackArtistPicker) collect(playbackModel.genrePickerSong.flow, ::handlePlaybackGenrePicker) @@ -300,6 +304,13 @@ class MainFragment : } } + private fun handlePlaylistNaming(args: PendingName.Args?) { + if (args != null) { + findNavController().navigateSafe(MainFragmentDirections.actionNamePlaylist(args)) + musicModel.pendingPlaylistNaming.consume() + } + } + private fun handlePlaybackArtistPicker(song: Song?) { if (song != null) { navModel.mainNavigateTo( diff --git a/app/src/main/java/org/oxycblt/auxio/home/FlipFloatingActionButton.kt b/app/src/main/java/org/oxycblt/auxio/home/FlipFloatingActionButton.kt index c2b2842a3..2b0cd3d5e 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/FlipFloatingActionButton.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/FlipFloatingActionButton.kt @@ -78,10 +78,14 @@ constructor( // Avoid doing a flip if the given config is already being applied. if (tag == iconRes) return tag = iconRes - flipping = true pendingConfig = PendingConfig(iconRes, contentDescriptionRes, clickListener) - // We will re-show the FAB later, assuming that there was not a prior flip operation. - super.hide(FlipVisibilityListener()) + + // Already hiding for whatever reason, apply the configuration when the FAB is shown again. + if (!isOrWillBeHidden) { + flipping = true + // We will re-show the FAB later, assuming that there was not a prior flip operation. + super.hide(FlipVisibilityListener()) + } } private data class PendingConfig( diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index e042e59b0..9f2514c71 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -321,7 +321,7 @@ class HomeFragment : } } else { binding.homeFab.flipTo(R.drawable.ic_add_24, R.string.desc_new_playlist) { - musicModel.createPlaylist() + musicModel.createPlaylist("New playlist") } } } diff --git a/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt b/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt index 13a7b0fc3..6707a6694 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/MusicViewModel.kt @@ -23,6 +23,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import org.oxycblt.auxio.music.dialog.PendingName +import org.oxycblt.auxio.util.Event +import org.oxycblt.auxio.util.MutableEvent /** * A [ViewModel] providing data specific to the music loading process. @@ -42,6 +45,9 @@ class MusicViewModel @Inject constructor(private val musicRepository: MusicRepos val statistics: StateFlow get() = _statistics + private val _pendingPlaylistNaming = MutableEvent() + val pendingPlaylistNaming: Event = _pendingPlaylistNaming + init { musicRepository.addUpdateListener(this) musicRepository.addIndexingListener(this) @@ -79,12 +85,15 @@ class MusicViewModel @Inject constructor(private val musicRepository: MusicRepos } /** - * Create a new generic playlist. + * Create a new generic playlist. This will prompt the user to edit the name before the creation + * finishes. * - * @param name The name of the new playlist. If null, the user will be prompted for a name. + * @param name The preferred name of the new playlist. */ - fun createPlaylist(name: String? = null) { - musicRepository.createPlaylist(name ?: "New playlist", listOf()) + fun createPlaylist(name: String, songs: List = listOf()) { + // TODO: Default to something like "Playlist 1", "Playlist 2", etc. + // TODO: Attempt to unify playlist creation flow with dialog model + _pendingPlaylistNaming.put(PendingName.Args(name, songs.map { it.uid })) } /** diff --git a/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistDialogViewModel.kt b/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistDialogViewModel.kt new file mode 100644 index 000000000..8542b28e1 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistDialogViewModel.kt @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2023 Auxio Project + * PlaylistDialogViewModel.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.music.dialog + +import android.os.Parcelable +import androidx.lifecycle.ViewModel +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.parcelize.Parcelize +import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.MusicRepository +import org.oxycblt.auxio.music.Song + +/** + * A [ViewModel] managing the state of the playlist editing dialogs. + * @author Alexander Capehart + */ +@HiltViewModel +class PlaylistDialogViewModel @Inject constructor(private val musicRepository: MusicRepository) : + ViewModel(), MusicRepository.UpdateListener { + private val _currentPendingName = MutableStateFlow(null) + val currentPendingName: StateFlow = _currentPendingName + + init { + musicRepository.addUpdateListener(this) + } + + override fun onMusicChanges(changes: MusicRepository.Changes) { + if (!changes.deviceLibrary) return + val deviceLibrary = musicRepository.deviceLibrary ?: return + // Update the pending name to reflect new information in the music library. + _currentPendingName.value = + _currentPendingName.value?.let { pendingName -> + PendingName( + pendingName.name, + pendingName.songs.mapNotNull { deviceLibrary.findSong(it.uid) }) + } + } + + override fun onCleared() { + musicRepository.removeUpdateListener(this) + } + + /** + * Update the current [PendingName] based on the given [PendingName.Args]. + * @param args The [PendingName.Args] to update with. + */ + fun setPendingName(args: PendingName.Args) { + val deviceLibrary = musicRepository.deviceLibrary ?: return + val name = + PendingName(args.preferredName, args.songUids.mapNotNull(deviceLibrary::findSong)) + _currentPendingName.value = name + } + + /** + * Update the current [PendingName] based on new user input. + * @param name The new user-inputted name, directly from the UI. + */ + fun updatePendingName(name: String?) { + // Remove any additional whitespace from the string to be consistent with all other + // music items. + val normalized = (name ?: return).trim() + _currentPendingName.value = + _currentPendingName.value?.run { PendingName(normalized, songs) } + } + + /** + * Confirm the current [PendingName] operation and write it to the database. + */ + fun confirmPendingName() { + val pendingName = _currentPendingName.value ?: return + musicRepository.createPlaylist(pendingName.name, pendingName.songs) + _currentPendingName.value = null + } +} + +/** + * Represents a name operation + */ +data class PendingName(val name: String, val songs: List) { + /** + * A [Parcelable] version of [PendingName], to be used as a dialog argument. + * @param preferredName The name to be used initially by the dialog. + * @param songUids The [Music.UID] of any pending [Song]s that will be put in the playlist. + */ + @Parcelize + data class Args(val preferredName: String, val songUids: List) : Parcelable +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistNamingDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistNamingDialog.kt new file mode 100644 index 000000000..6afaf866e --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/music/dialog/PlaylistNamingDialog.kt @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Auxio Project + * PlaylistNamingDialog.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.music.dialog + +import android.os.Bundle +import android.view.LayoutInflater +import androidx.appcompat.app.AlertDialog +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import androidx.navigation.fragment.navArgs +import dagger.hilt.android.AndroidEntryPoint +import org.oxycblt.auxio.R +import org.oxycblt.auxio.databinding.DialogPlaylistNamingBinding +import org.oxycblt.auxio.ui.ViewBindingDialogFragment +import org.oxycblt.auxio.util.collectImmediately + +/** + * A dialog allowing the name of a new/existing playlist to be edited. + * + * @author Alexander Capehart (OxygenCobalt) + */ +@AndroidEntryPoint +class PlaylistNamingDialog : ViewBindingDialogFragment() { + // activityViewModels is intentional here as the ViewModel will do work that we + // do not want to cancel after this dialog closes. + private val dialogModel: PlaylistDialogViewModel by activityViewModels() + // Information about what playlist to name for is initially within the navigation arguments + // as UIDs, as that is the only safe way to parcel playlist information. + private val args: PlaylistNamingDialogArgs by navArgs() + private var initializedInput = false + + override fun onConfigDialog(builder: AlertDialog.Builder) { + builder + .setTitle(R.string.lbl_new_playlist) + .setPositiveButton(R.string.lbl_ok) { _, _ -> dialogModel.confirmPendingName() } + .setNegativeButton(R.string.lbl_cancel, null) + } + + override fun onCreateBinding(inflater: LayoutInflater) = + DialogPlaylistNamingBinding.inflate(inflater) + + override fun onBindingCreated( + binding: DialogPlaylistNamingBinding, + savedInstanceState: Bundle? + ) { + super.onBindingCreated(binding, savedInstanceState) + + binding.playlistName.addTextChangedListener { + dialogModel.updatePendingName(it?.toString()) + } + + dialogModel.setPendingName(args.pendingName) + collectImmediately(dialogModel.currentPendingName, ::updatePendingName) + } + + private fun updatePendingName(pendingName: PendingName?) { + if (pendingName == null) { + findNavController().navigateUp() + return + } + // Make sure we initialize the TextView with the preferred name if we haven't already. + if (!initializedInput) { + requireBinding().playlistName.setText(pendingName.name) + initializedInput = true + } + // Disable the OK button if the name is invalid (empty or whitespace) + (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)?.isEnabled = + pendingName.name.isNotBlank() + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt b/app/src/main/java/org/oxycblt/auxio/music/dialog/SeparatorsDialog.kt similarity index 92% rename from app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt rename to app/src/main/java/org/oxycblt/auxio/music/dialog/SeparatorsDialog.kt index 2acf872ba..86e1ebbf4 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/SeparatorsDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/dialog/SeparatorsDialog.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.music.metadata +package org.oxycblt.auxio.music.dialog import android.os.Bundle import android.view.LayoutInflater @@ -99,6 +99,19 @@ class SeparatorsDialog : ViewBindingDialogFragment() { return separators } + /** + * Defines the allowed separator characters that can be used to delimit multi-value tags. + * + * @author Alexander Capehart (OxygenCobalt) + */ + private object Separators { + const val COMMA = ',' + const val SEMICOLON = ';' + const val SLASH = '/' + const val PLUS = '+' + const val AND = '&' + } + private companion object { const val KEY_PENDING_SEPARATORS = BuildConfig.APPLICATION_ID + ".key.PENDING_SEPARATORS" } diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/Separators.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/Separators.kt deleted file mode 100644 index cf42234f4..000000000 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/Separators.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023 Auxio Project - * Separators.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.music.metadata - -/** - * Defines the allowed separator characters that can be used to delimit multi-value tags. - * - * @author Alexander Capehart (OxygenCobalt) - */ -object Separators { - const val COMMA = ',' - const val SEMICOLON = ';' - const val SLASH = '/' - const val PLUS = '+' - const val AND = '&' -} diff --git a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt index 53bacbf08..504491033 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/metadata/TagWorker.kt @@ -169,7 +169,9 @@ private class TagWorkerImpl( (textFrames["TCMP"] ?: textFrames["TXXX:compilation"] ?: textFrames["TXXX:itunescompilation"]) ?.let { + // Ignore invalid instances of this tag if (it.size != 1 || it[0] != "1") return@let + // Change the metadata to be a compilation album made by "Various Artists" rawSong.albumArtistNames = rawSong.albumArtistNames.ifEmpty { COMPILATION_ALBUM_ARTISTS } rawSong.releaseTypes = rawSong.releaseTypes.ifEmpty { COMPILATION_RELEASE_TYPES } @@ -262,7 +264,9 @@ private class TagWorkerImpl( // Compilation Flag (comments["compilation"] ?: comments["itunescompilation"])?.let { + // Ignore invalid instances of this tag if (it.size != 1 || it[0] != "1") return@let + // Change the metadata to be a compilation album made by "Various Artists" rawSong.albumArtistNames = rawSong.albumArtistNames.ifEmpty { COMPILATION_ALBUM_ARTISTS } rawSong.releaseTypes = rawSong.releaseTypes.ifEmpty { COMPILATION_RELEASE_TYPES } diff --git a/app/src/main/java/org/oxycblt/auxio/navigation/dialog/ArtistNavigationPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/navigation/dialog/ArtistNavigationPickerDialog.kt index c292f00fe..a3a1647a4 100644 --- a/app/src/main/java/org/oxycblt/auxio/navigation/dialog/ArtistNavigationPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/navigation/dialog/ArtistNavigationPickerDialog.kt @@ -48,7 +48,7 @@ import org.oxycblt.auxio.util.collectImmediately class ArtistNavigationPickerDialog : ViewBindingDialogFragment(), ClickableListListener { private val navigationModel: NavigationViewModel by activityViewModels() - private val pickerModel: NavigationPickerViewModel by viewModels() + private val pickerModel: NavigationDialogViewModel by viewModels() // Information about what artists to show choices for is initially within the navigation // arguments as UIDs, as that is the only safe way to parcel an artist. private val args: ArtistNavigationPickerDialogArgs by navArgs() diff --git a/app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationPickerViewModel.kt b/app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationDialogViewModel.kt similarity index 96% rename from app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationPickerViewModel.kt rename to app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationDialogViewModel.kt index 193d9553a..9e626b53e 100644 --- a/app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationPickerViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/navigation/dialog/NavigationDialogViewModel.kt @@ -1,6 +1,6 @@ /* * Copyright (c) 2023 Auxio Project - * NavigationPickerViewModel.kt is part of Auxio. + * NavigationDialogViewModel.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 @@ -26,12 +26,12 @@ import kotlinx.coroutines.flow.StateFlow import org.oxycblt.auxio.music.* /** - * A [ViewModel] that stores the current information required for [ArtistNavigationPickerDialog]. + * A [ViewModel] that stores the current information required for navigation dialogs * * @author Alexander Capehart (OxygenCobalt) */ @HiltViewModel -class NavigationPickerViewModel @Inject constructor(private val musicRepository: MusicRepository) : +class NavigationDialogViewModel @Inject constructor(private val musicRepository: MusicRepository) : ViewModel(), MusicRepository.UpdateListener { private val _currentArtistChoices = MutableStateFlow(null) /** The current set of [Artist] choices to show in the picker, or null if to show nothing. */ diff --git a/app/src/main/java/org/oxycblt/auxio/playback/dialog/ArtistPlaybackPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/dialog/ArtistPlaybackPickerDialog.kt index 9c74577d7..d1fc49000 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/dialog/ArtistPlaybackPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/dialog/ArtistPlaybackPickerDialog.kt @@ -49,7 +49,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull class ArtistPlaybackPickerDialog : ViewBindingDialogFragment(), ClickableListListener { private val playbackModel: PlaybackViewModel by activityViewModels() - private val pickerModel: PlaybackPickerViewModel by viewModels() + private val pickerModel: PlaybackDialogViewModel by viewModels() // Information about what Song to show choices for is initially within the navigation arguments // as UIDs, as that is the only safe way to parcel a Song. private val args: ArtistPlaybackPickerDialogArgs by navArgs() diff --git a/app/src/main/java/org/oxycblt/auxio/playback/dialog/GenrePlaybackPickerDialog.kt b/app/src/main/java/org/oxycblt/auxio/playback/dialog/GenrePlaybackPickerDialog.kt index 9dbb271f1..d80157002 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/dialog/GenrePlaybackPickerDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/dialog/GenrePlaybackPickerDialog.kt @@ -49,7 +49,7 @@ import org.oxycblt.auxio.util.unlikelyToBeNull class GenrePlaybackPickerDialog : ViewBindingDialogFragment(), ClickableListListener { private val playbackModel: PlaybackViewModel by activityViewModels() - private val pickerModel: PlaybackPickerViewModel by viewModels() + private val pickerModel: PlaybackDialogViewModel by viewModels() // Information about what Song to show choices for is initially within the navigation arguments // as UIDs, as that is the only safe way to parcel a Song. private val args: GenrePlaybackPickerDialogArgs by navArgs() diff --git a/app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackPickerViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackDialogViewModel.kt similarity index 95% rename from app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackPickerViewModel.kt rename to app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackDialogViewModel.kt index fea0d04da..eb97b88f8 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackPickerViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/dialog/PlaybackDialogViewModel.kt @@ -1,6 +1,6 @@ /* * Copyright (c) 2023 Auxio Project - * PlaybackPickerViewModel.kt is part of Auxio. + * PlaybackDialogViewModel.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 @@ -31,7 +31,7 @@ import org.oxycblt.auxio.music.* * @author OxygenCobalt (Alexander Capehart) */ @HiltViewModel -class PlaybackPickerViewModel @Inject constructor(private val musicRepository: MusicRepository) : +class PlaybackDialogViewModel @Inject constructor(private val musicRepository: MusicRepository) : ViewModel(), MusicRepository.UpdateListener { private val _currentPickerSong = MutableStateFlow(null) /** The current set of [Artist] choices to show in the picker, or null if to show nothing. */ diff --git a/app/src/main/res/layout/dialog_playlist_naming.xml b/app/src/main/res/layout/dialog_playlist_naming.xml new file mode 100644 index 000000000..390292f34 --- /dev/null +++ b/app/src/main/res/layout/dialog_playlist_naming.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 7848ff8c7..1be49a828 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -18,26 +18,39 @@ android:id="@+id/action_show_details" app:destination="@id/song_detail_dialog" /> + android:id="@+id/action_name_playlist" + app:destination="@id/playlist_naming_dialog" /> + + android:id="@+id/song_detail_dialog" + android:name="org.oxycblt.auxio.detail.SongDetailDialog" + android:label="song_detail_dialog" + tools:layout="@layout/dialog_song_detail"> + + + + + + + + - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 811c2c573..07d611778 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -78,6 +78,7 @@ Playlist Playlists + New playlist Search