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:
parent
c5a3f72b99
commit
480b1b28e5
6 changed files with 53 additions and 13 deletions
|
@ -470,7 +470,8 @@ class HomeFragment :
|
||||||
when (decision) {
|
when (decision) {
|
||||||
is PlaylistDecision.New -> {
|
is PlaylistDecision.New -> {
|
||||||
logD("Creating new playlist")
|
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 -> {
|
is PlaylistDecision.Import -> {
|
||||||
logD("Importing playlist")
|
logD("Importing playlist")
|
||||||
|
|
|
@ -34,6 +34,7 @@ import org.oxycblt.auxio.music.external.ExternalPlaylistManager
|
||||||
import org.oxycblt.auxio.util.Event
|
import org.oxycblt.auxio.util.Event
|
||||||
import org.oxycblt.auxio.util.MutableEvent
|
import org.oxycblt.auxio.util.MutableEvent
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
import org.oxycblt.auxio.util.logE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [ViewModel] providing data specific to the music loading process.
|
* 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 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 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) {
|
if (name != null) {
|
||||||
logD("Creating $name with ${songs.size} songs]")
|
logD("Creating $name with ${songs.size} songs]")
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
musicRepository.createPlaylist(name, songs)
|
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 {
|
} else {
|
||||||
logD("Launching creation dialog for ${songs.size} songs")
|
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) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val importedPlaylist = externalPlaylistManager.import(uri)
|
val importedPlaylist = externalPlaylistManager.import(uri)
|
||||||
if (importedPlaylist == null) {
|
if (importedPlaylist == null) {
|
||||||
|
logE("Could not import playlist")
|
||||||
_playlistMessage.put(PlaylistMessage.ImportFailed)
|
_playlistMessage.put(PlaylistMessage.ImportFailed)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
@ -150,6 +164,7 @@ constructor(
|
||||||
val songs = importedPlaylist.paths.mapNotNull(deviceLibrary::findSongByPath)
|
val songs = importedPlaylist.paths.mapNotNull(deviceLibrary::findSongByPath)
|
||||||
|
|
||||||
if (songs.isEmpty()) {
|
if (songs.isEmpty()) {
|
||||||
|
logE("No songs found")
|
||||||
_playlistMessage.put(PlaylistMessage.ImportFailed)
|
_playlistMessage.put(PlaylistMessage.ImportFailed)
|
||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
@ -160,7 +175,7 @@ constructor(
|
||||||
_playlistMessage.put(PlaylistMessage.ImportSuccess)
|
_playlistMessage.put(PlaylistMessage.ImportSuccess)
|
||||||
} else {
|
} else {
|
||||||
// TODO: Have to properly propagate the "Playlist Created" message
|
// TODO: Have to properly propagate the "Playlist Created" message
|
||||||
createPlaylist(importedPlaylist.name, songs)
|
createPlaylist(importedPlaylist.name, songs, PlaylistDecision.New.Reason.IMPORT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -321,8 +336,15 @@ sealed interface PlaylistDecision {
|
||||||
* Navigate to a dialog that allows a user to pick a name for a new [Playlist].
|
* 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 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.
|
* Navigate to a file picker to import a playlist from.
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.oxycblt.auxio.R
|
||||||
import org.oxycblt.auxio.databinding.DialogMusicChoicesBinding
|
import org.oxycblt.auxio.databinding.DialogMusicChoicesBinding
|
||||||
import org.oxycblt.auxio.list.ClickableListListener
|
import org.oxycblt.auxio.list.ClickableListListener
|
||||||
import org.oxycblt.auxio.music.MusicViewModel
|
import org.oxycblt.auxio.music.MusicViewModel
|
||||||
|
import org.oxycblt.auxio.music.PlaylistDecision
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
import org.oxycblt.auxio.ui.ViewBindingMaterialDialogFragment
|
||||||
import org.oxycblt.auxio.util.collectImmediately
|
import org.oxycblt.auxio.util.collectImmediately
|
||||||
|
@ -98,7 +99,8 @@ class AddToPlaylistDialog :
|
||||||
val songs = pickerModel.currentSongsToAdd.value ?: return
|
val songs = pickerModel.currentSongsToAdd.value ?: return
|
||||||
findNavController()
|
findNavController()
|
||||||
.navigateSafe(
|
.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>?) {
|
private fun updatePendingSongs(songs: List<Song>?) {
|
||||||
|
|
|
@ -60,7 +60,7 @@ class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBi
|
||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
}
|
}
|
||||||
// TODO: Navigate to playlist if there are songs in it
|
// TODO: Navigate to playlist if there are songs in it
|
||||||
musicModel.createPlaylist(name, pendingPlaylist.songs)
|
musicModel.createPlaylist(name, pendingPlaylist.songs, pendingPlaylist.reason)
|
||||||
findNavController().apply {
|
findNavController().apply {
|
||||||
navigateUp()
|
navigateUp()
|
||||||
// Do an additional navigation away from the playlist addition dialog, if
|
// Do an additional navigation away from the playlist addition dialog, if
|
||||||
|
@ -82,7 +82,7 @@ class NewPlaylistDialog : ViewBindingMaterialDialogFragment<DialogPlaylistNameBi
|
||||||
|
|
||||||
// --- VIEWMODEL SETUP ---
|
// --- VIEWMODEL SETUP ---
|
||||||
musicModel.playlistDecision.consume()
|
musicModel.playlistDecision.consume()
|
||||||
pickerModel.setPendingPlaylist(requireContext(), args.songUids)
|
pickerModel.setPendingPlaylist(requireContext(), args.songUids, args.reason)
|
||||||
collectImmediately(pickerModel.currentPendingPlaylist, ::updatePendingPlaylist)
|
collectImmediately(pickerModel.currentPendingPlaylist, ::updatePendingPlaylist)
|
||||||
collectImmediately(pickerModel.chosenName, ::updateChosenName)
|
collectImmediately(pickerModel.chosenName, ::updateChosenName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.oxycblt.auxio.list.sort.Sort
|
||||||
import org.oxycblt.auxio.music.Music
|
import org.oxycblt.auxio.music.Music
|
||||||
import org.oxycblt.auxio.music.MusicRepository
|
import org.oxycblt.auxio.music.MusicRepository
|
||||||
import org.oxycblt.auxio.music.Playlist
|
import org.oxycblt.auxio.music.Playlist
|
||||||
|
import org.oxycblt.auxio.music.PlaylistDecision
|
||||||
import org.oxycblt.auxio.music.Song
|
import org.oxycblt.auxio.music.Song
|
||||||
import org.oxycblt.auxio.music.external.ExportConfig
|
import org.oxycblt.auxio.music.external.ExportConfig
|
||||||
import org.oxycblt.auxio.util.logD
|
import org.oxycblt.auxio.util.logD
|
||||||
|
@ -96,7 +97,8 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
|
||||||
_currentPendingPlaylist.value?.let { pendingPlaylist ->
|
_currentPendingPlaylist.value?.let { pendingPlaylist ->
|
||||||
PendingPlaylist(
|
PendingPlaylist(
|
||||||
pendingPlaylist.preferredName,
|
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}")
|
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 context [Context] required to generate a playlist name.
|
||||||
* @param songUids The [Music.UID]s of songs to be present in the playlist.
|
* @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")
|
logD("Opening ${songUids.size} songs to create a playlist from")
|
||||||
val userLibrary = musicRepository.userLibrary ?: return
|
val userLibrary = musicRepository.userLibrary ?: return
|
||||||
val songs =
|
val songs =
|
||||||
|
@ -168,7 +175,7 @@ class PlaylistPickerViewModel @Inject constructor(private val musicRepository: M
|
||||||
|
|
||||||
_currentPendingPlaylist.value =
|
_currentPendingPlaylist.value =
|
||||||
if (possibleName != null && songs != null) {
|
if (possibleName != null && songs != null) {
|
||||||
PendingPlaylist(possibleName, songs)
|
PendingPlaylist(possibleName, songs, reason)
|
||||||
} else {
|
} else {
|
||||||
logW("Given song UIDs to create were invalid")
|
logW("Given song UIDs to create were invalid")
|
||||||
null
|
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 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 songs The [Song]s to be contained in the [PendingPlaylist]
|
||||||
|
* @param reason The reason the playlist is being created.
|
||||||
* @author Alexander Capehart (OxygenCobalt)
|
* @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.
|
* Represents the (processed) user input from the playlist naming dialogs.
|
||||||
|
|
|
@ -413,6 +413,9 @@
|
||||||
<argument
|
<argument
|
||||||
android:name="songUids"
|
android:name="songUids"
|
||||||
app:argType="org.oxycblt.auxio.music.Music$UID[]" />
|
app:argType="org.oxycblt.auxio.music.Music$UID[]" />
|
||||||
|
<argument
|
||||||
|
android:name="reason"
|
||||||
|
app:argType="org.oxycblt.auxio.music.PlaylistDecision$New$Reason" />
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
||||||
<dialog
|
<dialog
|
||||||
|
|
Loading…
Reference in a new issue