music: display correct message on new playlist

The context of the "New Playlist" dialog can differ depending on the
action performed, such as adding to a playlist or importing a playlist.
We need to make sure we're still showing the right message once this
is done.
This commit is contained in:
Alexander Capehart 2023-12-24 11:32:47 -07:00
parent c5a3f72b99
commit 480b1b28e5
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
6 changed files with 53 additions and 13 deletions

View file

@ -470,7 +470,8 @@ class HomeFragment :
when (decision) {
is PlaylistDecision.New -> {
logD("Creating new playlist")
HomeFragmentDirections.newPlaylist(decision.songs.map { it.uid }.toTypedArray())
HomeFragmentDirections.newPlaylist(
decision.songs.map { it.uid }.toTypedArray(), decision.reason)
}
is PlaylistDecision.Import -> {
logD("Importing playlist")

View file

@ -34,6 +34,7 @@ import org.oxycblt.auxio.music.external.ExternalPlaylistManager
import org.oxycblt.auxio.util.Event
import org.oxycblt.auxio.util.MutableEvent
import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE
/**
* A [ViewModel] providing data specific to the music loading process.
@ -114,17 +115,29 @@ constructor(
*
* @param name The name of the new [Playlist]. If null, the user will be prompted for one.
* @param songs The [Song]s to be contained in the new playlist.
* @param reason The reason why a new playlist is being created. For all intensive purposes, you
* do not need to specify this.
*/
fun createPlaylist(name: String? = null, songs: List<Song> = listOf()) {
fun createPlaylist(
name: String? = null,
songs: List<Song> = listOf(),
reason: PlaylistDecision.New.Reason = PlaylistDecision.New.Reason.NEW
) {
if (name != null) {
logD("Creating $name with ${songs.size} songs]")
viewModelScope.launch(Dispatchers.IO) {
musicRepository.createPlaylist(name, songs)
_playlistMessage.put(PlaylistMessage.NewPlaylistSuccess)
val message =
when (reason) {
PlaylistDecision.New.Reason.NEW -> PlaylistMessage.NewPlaylistSuccess
PlaylistDecision.New.Reason.ADD -> PlaylistMessage.AddSuccess
PlaylistDecision.New.Reason.IMPORT -> PlaylistMessage.ImportSuccess
}
_playlistMessage.put(message)
}
} else {
logD("Launching creation dialog for ${songs.size} songs")
_playlistDecision.put(PlaylistDecision.New(songs))
_playlistDecision.put(PlaylistDecision.New(songs, reason))
}
}
@ -142,6 +155,7 @@ constructor(
viewModelScope.launch(Dispatchers.IO) {
val importedPlaylist = externalPlaylistManager.import(uri)
if (importedPlaylist == null) {
logE("Could not import playlist")
_playlistMessage.put(PlaylistMessage.ImportFailed)
return@launch
}
@ -150,6 +164,7 @@ constructor(
val songs = importedPlaylist.paths.mapNotNull(deviceLibrary::findSongByPath)
if (songs.isEmpty()) {
logE("No songs found")
_playlistMessage.put(PlaylistMessage.ImportFailed)
return@launch
}
@ -160,7 +175,7 @@ constructor(
_playlistMessage.put(PlaylistMessage.ImportSuccess)
} else {
// TODO: Have to properly propagate the "Playlist Created" message
createPlaylist(importedPlaylist.name, songs)
createPlaylist(importedPlaylist.name, songs, PlaylistDecision.New.Reason.IMPORT)
}
}
} else {
@ -321,8 +336,15 @@ sealed interface PlaylistDecision {
* Navigate to a dialog that allows a user to pick a name for a new [Playlist].
*
* @param songs The [Song]s to contain in the new [Playlist].
* @param context The context in which this decision is being fulfilled.
*/
data class New(val songs: List<Song>) : PlaylistDecision
data class New(val songs: List<Song>, val reason: Reason) : PlaylistDecision {
enum class Reason {
NEW,
ADD,
IMPORT
}
}
/**
* Navigate to a file picker to import a playlist from.

View file

@ -32,6 +32,7 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.databinding.DialogMusicChoicesBinding
import org.oxycblt.auxio.list.ClickableListListener
import org.oxycblt.auxio.music.MusicViewModel
import org.oxycblt.auxio.music.PlaylistDecision
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
import org.oxycblt.auxio.util.collectImmediately
@ -98,7 +99,8 @@ class AddToPlaylistDialog :
val songs = pickerModel.currentSongsToAdd.value ?: return
findNavController()
.navigateSafe(
AddToPlaylistDialogDirections.newPlaylist(songs.map { it.uid }.toTypedArray()))
AddToPlaylistDialogDirections.newPlaylist(
songs.map { it.uid }.toTypedArray(), PlaylistDecision.New.Reason.ADD))
}
private fun updatePendingSongs(songs: List<Song>?) {

View file

@ -60,7 +60,7 @@ class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBi
else -> throw IllegalStateException()
}
// TODO: Navigate to playlist if there are songs in it
musicModel.createPlaylist(name, pendingPlaylist.songs)
musicModel.createPlaylist(name, pendingPlaylist.songs, pendingPlaylist.reason)
findNavController().apply {
navigateUp()
// Do an additional navigation away from the playlist addition dialog, if
@ -82,7 +82,7 @@ class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBi
// --- VIEWMODEL SETUP ---
musicModel.playlistDecision.consume()
pickerModel.setPendingPlaylist(requireContext(), args.songUids)
pickerModel.setPendingPlaylist(requireContext(), args.songUids, args.reason)
collectImmediately(pickerModel.currentPendingPlaylist, ::updatePendingPlaylist)
collectImmediately(pickerModel.chosenName, ::updateChosenName)
}

View file

@ -30,6 +30,7 @@ import org.oxycblt.auxio.list.sort.Sort
import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.music.MusicRepository
import org.oxycblt.auxio.music.Playlist
import org.oxycblt.auxio.music.PlaylistDecision
import org.oxycblt.auxio.music.Song
import org.oxycblt.auxio.music.external.ExportConfig
import org.oxycblt.auxio.util.logD
@ -96,7 +97,8 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
_currentPendingPlaylist.value?.let { pendingPlaylist ->
PendingPlaylist(
pendingPlaylist.preferredName,
pendingPlaylist.songs.mapNotNull { deviceLibrary.findSong(it.uid) })
pendingPlaylist.songs.mapNotNull { deviceLibrary.findSong(it.uid) },
pendingPlaylist.reason)
}
logD("Updated pending playlist: ${_currentPendingPlaylist.value?.preferredName}")
@ -143,8 +145,13 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
*
* @param context [Context] required to generate a playlist name.
* @param songUids The [Music.UID]s of songs to be present in the playlist.
* @param reason The reason the playlist is being created.
*/
fun setPendingPlaylist(context: Context, songUids: Array<Music.UID>) {
fun setPendingPlaylist(
context: Context,
songUids: Array<Music.UID>,
reason: PlaylistDecision.New.Reason
) {
logD("Opening ${songUids.size} songs to create a playlist from")
val userLibrary = musicRepository.userLibrary ?: return
val songs =
@ -168,7 +175,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
_currentPendingPlaylist.value =
if (possibleName != null && songs != null) {
PendingPlaylist(possibleName, songs)
PendingPlaylist(possibleName, songs, reason)
} else {
logW("Given song UIDs to create were invalid")
null
@ -295,9 +302,14 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
*
* @param preferredName The name to be used by default if no other name is chosen.
* @param songs The [Song]s to be contained in the [PendingPlaylist]
* @param reason The reason the playlist is being created.
* @author Alexander Capehart (OxygenCobalt)
*/
data class PendingPlaylist(val preferredName: String, val songs: List<Song>)
data class PendingPlaylist(
val preferredName: String,
val songs: List<Song>,
val reason: PlaylistDecision.New.Reason
)
/**
* Represents the (processed) user input from the playlist naming dialogs.

View file

@ -413,6 +413,9 @@
<argument
android:name="songUids"
app:argType="org.oxycblt.auxio.music.Music$UID[]" />
<argument
android:name="reason"
app:argType="org.oxycblt.auxio.music.PlaylistDecision$New$Reason" />
</dialog>
<dialog