mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Implement various queue functions
This commit is contained in:
parent
ea243975ad
commit
7a869d9f47
5 changed files with 202 additions and 41 deletions
|
|
@ -209,6 +209,12 @@ class MusicService
|
||||||
player.moveMediaItem(index, if (direction == MoveDirection.UP) index - 1 else index + 1)
|
player.moveMediaItem(index, if (direction == MoveDirection.UP) index - 1 else index + 1)
|
||||||
updateQueueSize()
|
updateQueueSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun playNext(song: BaseItem) {
|
||||||
|
val mediaItem = convert(song)
|
||||||
|
onMain { player.addMediaItem(state.value.currentIndex + 1, mediaItem) }
|
||||||
|
updateQueueSize()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
|
@ -49,20 +50,23 @@ import com.github.damontecres.wholphin.services.MediaReportService
|
||||||
import com.github.damontecres.wholphin.services.MusicService
|
import com.github.damontecres.wholphin.services.MusicService
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
import com.github.damontecres.wholphin.services.UserPreferencesService
|
import com.github.damontecres.wholphin.services.UserPreferencesService
|
||||||
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
|
||||||
import com.github.damontecres.wholphin.ui.components.DialogParams
|
import com.github.damontecres.wholphin.ui.components.DialogParams
|
||||||
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||||
import com.github.damontecres.wholphin.ui.components.GenreText
|
import com.github.damontecres.wholphin.ui.components.GenreText
|
||||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||||
|
import com.github.damontecres.wholphin.ui.components.Optional
|
||||||
import com.github.damontecres.wholphin.ui.components.OverviewText
|
import com.github.damontecres.wholphin.ui.components.OverviewText
|
||||||
import com.github.damontecres.wholphin.ui.components.QuickDetails
|
import com.github.damontecres.wholphin.ui.components.QuickDetails
|
||||||
|
import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
|
||||||
|
import com.github.damontecres.wholphin.ui.detail.PlaylistDialog
|
||||||
|
import com.github.damontecres.wholphin.ui.detail.PlaylistLoadingState
|
||||||
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
import dagger.assisted.AssistedFactory
|
import dagger.assisted.AssistedFactory
|
||||||
|
|
@ -80,8 +84,7 @@ import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
import org.jellyfin.sdk.model.api.ImageType
|
import org.jellyfin.sdk.model.api.ImageType
|
||||||
import org.jellyfin.sdk.model.api.ItemSortBy
|
import org.jellyfin.sdk.model.api.MediaType
|
||||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
|
|
@ -121,22 +124,7 @@ class AlbumViewModel
|
||||||
.content
|
.content
|
||||||
.let { BaseItem(it, false) }
|
.let { BaseItem(it, false) }
|
||||||
}
|
}
|
||||||
val songsDeferred =
|
val songsDeferred = async { getPagerForAlbum(api, itemId) }
|
||||||
async {
|
|
||||||
val request =
|
|
||||||
GetItemsRequest(
|
|
||||||
parentId = itemId,
|
|
||||||
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
|
||||||
fields = DefaultItemFields,
|
|
||||||
sortBy =
|
|
||||||
listOf(
|
|
||||||
ItemSortBy.PARENT_INDEX_NUMBER,
|
|
||||||
ItemSortBy.INDEX_NUMBER,
|
|
||||||
ItemSortBy.SORT_NAME,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope).init()
|
|
||||||
}
|
|
||||||
val album = itemDeferred.await()
|
val album = itemDeferred.await()
|
||||||
val songs = songsDeferred.await()
|
val songs = songsDeferred.await()
|
||||||
val imageUrl = imageUrlService.getItemImageUrl(album, ImageType.PRIMARY)
|
val imageUrl = imageUrlService.getItemImageUrl(album, ImageType.PRIMARY)
|
||||||
|
|
@ -194,18 +182,22 @@ class AlbumViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun playNext(song: BaseItem) {
|
||||||
|
viewModelScope.launchDefault {
|
||||||
|
musicService.playNext(song)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addToQueue(
|
fun addToQueue(
|
||||||
itemId: UUID,
|
item: BaseItem,
|
||||||
index: Int,
|
index: Int,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
val songs = state.value.songs as ApiRequestPager<*>
|
val songs = state.value.songs as ApiRequestPager<*>
|
||||||
if (itemId == this@AlbumViewModel.itemId) {
|
if (item.id == this@AlbumViewModel.itemId) {
|
||||||
musicService.addAllToQueue(songs, 0)
|
musicService.addAllToQueue(songs, 0)
|
||||||
} else {
|
} else if (item.type == BaseItemKind.AUDIO) {
|
||||||
songs.getBlocking(index)?.let {
|
musicService.addToQueue(item)
|
||||||
musicService.addToQueue(it)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -238,21 +230,28 @@ fun AlbumDetailsPage(
|
||||||
hiltViewModel<AlbumViewModel, AlbumViewModel.Factory>(
|
hiltViewModel<AlbumViewModel, AlbumViewModel.Factory>(
|
||||||
creationCallback = { it.create(itemId) },
|
creationCallback = { it.create(itemId) },
|
||||||
),
|
),
|
||||||
|
playlistViewModel: AddPlaylistViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
val currentMusic by viewModel.currentMusic.collectAsState()
|
val currentMusic by viewModel.currentMusic.collectAsState()
|
||||||
|
|
||||||
|
var showPlaylistDialog by remember { mutableStateOf<Optional<UUID>>(Optional.absent()) }
|
||||||
|
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||||
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||||
val moreDialogActions =
|
val moreDialogActions =
|
||||||
remember {
|
remember {
|
||||||
MusicMoreDialogActions(
|
MusicMoreDialogActions(
|
||||||
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
||||||
onClickPlay = { index, _ -> viewModel.play(false, index) },
|
onClickPlay = { index, _ -> viewModel.play(false, index) },
|
||||||
onClickAddToQueue = { index, itemId -> viewModel.addToQueue(itemId, index) },
|
onClickPlayNext = { _, song -> viewModel.playNext(song) },
|
||||||
|
onClickAddToQueue = { index, item -> viewModel.addToQueue(item, index) },
|
||||||
onClickFavorite = { itemId, favorite -> viewModel.setFavorite(itemId, favorite) },
|
onClickFavorite = { itemId, favorite -> viewModel.setFavorite(itemId, favorite) },
|
||||||
onClickAddPlaylist = {},
|
onClickAddPlaylist = { itemId ->
|
||||||
|
playlistViewModel.loadPlaylists(MediaType.AUDIO)
|
||||||
|
showPlaylistDialog.makePresent(itemId)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -377,6 +376,23 @@ fun AlbumDetailsPage(
|
||||||
waitToLoad = params.fromLongClick,
|
waitToLoad = params.fromLongClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
showPlaylistDialog.compose { itemId ->
|
||||||
|
PlaylistDialog(
|
||||||
|
title = stringResource(R.string.add_to_playlist),
|
||||||
|
state = playlistState,
|
||||||
|
onDismissRequest = { showPlaylistDialog.makeAbsent() },
|
||||||
|
onClick = {
|
||||||
|
playlistViewModel.addToPlaylist(it.id, itemId)
|
||||||
|
showPlaylistDialog.makeAbsent()
|
||||||
|
},
|
||||||
|
createEnabled = true,
|
||||||
|
onCreatePlaylist = {
|
||||||
|
playlistViewModel.createPlaylistAndAddItem(it, itemId)
|
||||||
|
showPlaylistDialog.makeAbsent()
|
||||||
|
},
|
||||||
|
elevation = 3.dp,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
|
@ -59,14 +60,19 @@ import com.github.damontecres.wholphin.ui.components.DialogPopup
|
||||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||||
import com.github.damontecres.wholphin.ui.components.GenreText
|
import com.github.damontecres.wholphin.ui.components.GenreText
|
||||||
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
import com.github.damontecres.wholphin.ui.components.LoadingPage
|
||||||
|
import com.github.damontecres.wholphin.ui.components.Optional
|
||||||
import com.github.damontecres.wholphin.ui.components.OverviewText
|
import com.github.damontecres.wholphin.ui.components.OverviewText
|
||||||
import com.github.damontecres.wholphin.ui.components.QuickDetails
|
import com.github.damontecres.wholphin.ui.components.QuickDetails
|
||||||
|
import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
|
||||||
|
import com.github.damontecres.wholphin.ui.detail.PlaylistDialog
|
||||||
|
import com.github.damontecres.wholphin.ui.detail.PlaylistLoadingState
|
||||||
import com.github.damontecres.wholphin.ui.launchDefault
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.toBaseItems
|
import com.github.damontecres.wholphin.ui.toBaseItems
|
||||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
|
import com.github.damontecres.wholphin.util.BlockingList
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
import com.github.damontecres.wholphin.util.LoadingState
|
import com.github.damontecres.wholphin.util.LoadingState
|
||||||
|
|
@ -86,6 +92,7 @@ import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
import org.jellyfin.sdk.model.api.ImageType
|
import org.jellyfin.sdk.model.api.ImageType
|
||||||
import org.jellyfin.sdk.model.api.ItemSortBy
|
import org.jellyfin.sdk.model.api.ItemSortBy
|
||||||
|
import org.jellyfin.sdk.model.api.MediaType
|
||||||
import org.jellyfin.sdk.model.api.SortOrder
|
import org.jellyfin.sdk.model.api.SortOrder
|
||||||
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
@ -205,7 +212,7 @@ class ArtistViewModel
|
||||||
_state.update { it.copy(artist = artist) }
|
_state.update { it.copy(artist = artist) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun play(shuffled: Boolean) {
|
fun playArtist(shuffled: Boolean) {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
Timber.v("Playing artist %s", itemId)
|
Timber.v("Playing artist %s", itemId)
|
||||||
val request =
|
val request =
|
||||||
|
|
@ -247,9 +254,58 @@ class ArtistViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun playSong(song: BaseItem) {
|
fun play(item: BaseItem) {
|
||||||
|
viewModelScope.launchIO {
|
||||||
|
Timber.v("Playing %s %s", item.type, item.id)
|
||||||
|
when (item.type) {
|
||||||
|
BaseItemKind.AUDIO -> {
|
||||||
|
musicService.setQueue(listOf(item), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseItemKind.MUSIC_ALBUM -> {
|
||||||
|
val pager = getPagerForAlbum(api, item.id)
|
||||||
|
musicService.setQueue(pager, 0, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseItemKind.MUSIC_ARTIST -> {
|
||||||
|
val pager = getPagerForArtist(api, item.id)
|
||||||
|
musicService.setQueue(pager, 0, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun playNext(song: BaseItem) {
|
||||||
viewModelScope.launchDefault {
|
viewModelScope.launchDefault {
|
||||||
musicService.setQueue(listOf(song), false)
|
musicService.playNext(song)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addToQueue(
|
||||||
|
item: BaseItem,
|
||||||
|
index: Int,
|
||||||
|
) {
|
||||||
|
viewModelScope.launchIO {
|
||||||
|
Timber.v("addToQueue %s %s", item.type, item.id)
|
||||||
|
when (item.type) {
|
||||||
|
BaseItemKind.AUDIO -> {
|
||||||
|
musicService.addAllToQueue(BlockingList.of(listOf(item)), 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseItemKind.MUSIC_ALBUM -> {
|
||||||
|
val pager = getPagerForAlbum(api, itemId)
|
||||||
|
musicService.addAllToQueue(pager, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseItemKind.MUSIC_ARTIST -> {
|
||||||
|
val pager = getPagerForArtist(api, item.id)
|
||||||
|
musicService.addAllToQueue(pager, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -275,21 +331,28 @@ fun ArtistDetailsPage(
|
||||||
hiltViewModel<ArtistViewModel, ArtistViewModel.Factory>(
|
hiltViewModel<ArtistViewModel, ArtistViewModel.Factory>(
|
||||||
creationCallback = { it.create(itemId) },
|
creationCallback = { it.create(itemId) },
|
||||||
),
|
),
|
||||||
|
playlistViewModel: AddPlaylistViewModel = hiltViewModel(),
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val state by viewModel.state.collectAsState()
|
val state by viewModel.state.collectAsState()
|
||||||
val currentMusic by viewModel.currentMusic.collectAsState()
|
val currentMusic by viewModel.currentMusic.collectAsState()
|
||||||
|
|
||||||
|
var showPlaylistDialog by remember { mutableStateOf<Optional<UUID>>(Optional.absent()) }
|
||||||
|
val playlistState by playlistViewModel.playlistState.observeAsState(PlaylistLoadingState.Pending)
|
||||||
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
var moreDialog by remember { mutableStateOf<DialogParams?>(null) }
|
||||||
val moreDialogActions =
|
val moreDialogActions =
|
||||||
remember {
|
remember {
|
||||||
MusicMoreDialogActions(
|
MusicMoreDialogActions(
|
||||||
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
onNavigate = { viewModel.navigationManager.navigateTo(it) },
|
||||||
onClickPlay = { index, song -> TODO() },
|
onClickPlay = { index, item -> viewModel.play(item) },
|
||||||
onClickAddToQueue = { index, itemId -> viewModel.addToQueue(itemId, index) },
|
onClickPlayNext = { _, item -> viewModel.playNext(item) },
|
||||||
|
onClickAddToQueue = { index, item -> viewModel.addToQueue(item, index) },
|
||||||
onClickFavorite = { itemId, favorite -> viewModel.setFavorite(itemId, favorite) },
|
onClickFavorite = { itemId, favorite -> viewModel.setFavorite(itemId, favorite) },
|
||||||
onClickAddPlaylist = {},
|
onClickAddPlaylist = { itemId ->
|
||||||
|
playlistViewModel.loadPlaylists(MediaType.AUDIO)
|
||||||
|
showPlaylistDialog.makePresent(itemId)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,7 +403,7 @@ fun ArtistDetailsPage(
|
||||||
actions =
|
actions =
|
||||||
remember {
|
remember {
|
||||||
MusicButtonActions(
|
MusicButtonActions(
|
||||||
onClickPlay = { viewModel.play(it) },
|
onClickPlay = { viewModel.playArtist(it) },
|
||||||
onClickInstantMix = viewModel::startInstantMix,
|
onClickInstantMix = viewModel::startInstantMix,
|
||||||
onClickFavorite = {
|
onClickFavorite = {
|
||||||
viewModel.setFavorite(
|
viewModel.setFavorite(
|
||||||
|
|
@ -385,7 +448,7 @@ fun ArtistDetailsPage(
|
||||||
itemsIndexed(state.topSongs) { index, song ->
|
itemsIndexed(state.topSongs) { index, song ->
|
||||||
SongListItem(
|
SongListItem(
|
||||||
song = song,
|
song = song,
|
||||||
onClick = { song?.let { viewModel.playSong(it) } },
|
onClick = { song?.let { viewModel.play(it) } },
|
||||||
onLongClick = {
|
onLongClick = {
|
||||||
if (song != null) {
|
if (song != null) {
|
||||||
moreDialog =
|
moreDialog =
|
||||||
|
|
@ -444,6 +507,23 @@ fun ArtistDetailsPage(
|
||||||
waitToLoad = params.fromLongClick,
|
waitToLoad = params.fromLongClick,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
showPlaylistDialog.compose { itemId ->
|
||||||
|
PlaylistDialog(
|
||||||
|
title = stringResource(R.string.add_to_playlist),
|
||||||
|
state = playlistState,
|
||||||
|
onDismissRequest = { showPlaylistDialog.makeAbsent() },
|
||||||
|
onClick = {
|
||||||
|
playlistViewModel.addToPlaylist(it.id, itemId)
|
||||||
|
showPlaylistDialog.makeAbsent()
|
||||||
|
},
|
||||||
|
createEnabled = true,
|
||||||
|
onCreatePlaylist = {
|
||||||
|
playlistViewModel.createPlaylistAndAddItem(it, itemId)
|
||||||
|
showPlaylistDialog.makeAbsent()
|
||||||
|
},
|
||||||
|
elevation = 3.dp,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
|
|
@ -6,17 +6,26 @@ import androidx.compose.material.icons.filled.Add
|
||||||
import androidx.compose.material.icons.filled.ArrowForward
|
import androidx.compose.material.icons.filled.ArrowForward
|
||||||
import androidx.compose.material.icons.filled.PlayArrow
|
import androidx.compose.material.icons.filled.PlayArrow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
|
import com.github.damontecres.wholphin.ui.DefaultItemFields
|
||||||
import com.github.damontecres.wholphin.ui.components.DialogItem
|
import com.github.damontecres.wholphin.ui.components.DialogItem
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import org.jellyfin.sdk.model.UUID
|
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||||
|
import com.github.damontecres.wholphin.util.GetItemsRequestHandler
|
||||||
|
import org.jellyfin.sdk.api.client.ApiClient
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
|
import org.jellyfin.sdk.model.api.ItemSortBy
|
||||||
|
import org.jellyfin.sdk.model.api.request.GetItemsRequest
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
data class MusicMoreDialogActions(
|
data class MusicMoreDialogActions(
|
||||||
val onNavigate: (Destination) -> Unit,
|
val onNavigate: (Destination) -> Unit,
|
||||||
val onClickPlay: (Int, UUID) -> Unit,
|
val onClickPlay: (Int, BaseItem) -> Unit,
|
||||||
val onClickAddToQueue: (Int, UUID) -> Unit,
|
val onClickPlayNext: (Int, BaseItem) -> Unit,
|
||||||
|
val onClickAddToQueue: (Int, BaseItem) -> Unit,
|
||||||
val onClickFavorite: (UUID, Boolean) -> Unit,
|
val onClickFavorite: (UUID, Boolean) -> Unit,
|
||||||
val onClickAddPlaylist: (UUID) -> Unit,
|
val onClickAddPlaylist: (UUID) -> Unit,
|
||||||
val onClickGoToAlbum: (UUID) -> Unit = {
|
val onClickGoToAlbum: (UUID) -> Unit = {
|
||||||
|
|
@ -40,7 +49,16 @@ fun buildMoreDialogForMusic(
|
||||||
Icons.Default.PlayArrow,
|
Icons.Default.PlayArrow,
|
||||||
iconColor = Color.Green.copy(alpha = .8f),
|
iconColor = Color.Green.copy(alpha = .8f),
|
||||||
) {
|
) {
|
||||||
actions.onClickPlay(index, item.id)
|
actions.onClickPlay(index, item)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
add(
|
||||||
|
DialogItem(
|
||||||
|
context.getString(R.string.play_next),
|
||||||
|
Icons.Default.PlayArrow,
|
||||||
|
iconColor = Color.Green.copy(alpha = .8f),
|
||||||
|
) {
|
||||||
|
actions.onClickPlayNext(index, item)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
|
|
@ -48,7 +66,7 @@ fun buildMoreDialogForMusic(
|
||||||
context.getString(R.string.add_to_queue),
|
context.getString(R.string.add_to_queue),
|
||||||
Icons.Default.Add,
|
Icons.Default.Add,
|
||||||
) {
|
) {
|
||||||
actions.onClickAddToQueue(index, item.id)
|
actions.onClickAddToQueue(index, item)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
add(
|
add(
|
||||||
|
|
@ -93,3 +111,43 @@ fun buildMoreDialogForMusic(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun ViewModel.getPagerForAlbum(
|
||||||
|
api: ApiClient,
|
||||||
|
albumId: UUID,
|
||||||
|
): ApiRequestPager<GetItemsRequest> {
|
||||||
|
val request =
|
||||||
|
GetItemsRequest(
|
||||||
|
parentId = albumId,
|
||||||
|
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
||||||
|
fields = DefaultItemFields,
|
||||||
|
sortBy =
|
||||||
|
listOf(
|
||||||
|
ItemSortBy.PARENT_INDEX_NUMBER,
|
||||||
|
ItemSortBy.INDEX_NUMBER,
|
||||||
|
ItemSortBy.SORT_NAME,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope).init()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun ViewModel.getPagerForArtist(
|
||||||
|
api: ApiClient,
|
||||||
|
artistId: UUID,
|
||||||
|
): ApiRequestPager<GetItemsRequest> {
|
||||||
|
val request =
|
||||||
|
GetItemsRequest(
|
||||||
|
parentId = artistId,
|
||||||
|
recursive = true,
|
||||||
|
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
||||||
|
fields = DefaultItemFields,
|
||||||
|
// TODO better sort
|
||||||
|
sortBy =
|
||||||
|
listOf(
|
||||||
|
ItemSortBy.PARENT_INDEX_NUMBER,
|
||||||
|
ItemSortBy.INDEX_NUMBER,
|
||||||
|
ItemSortBy.SORT_NAME,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
return ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope).init()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -727,5 +727,6 @@
|
||||||
<string name="album_artist">Album artist</string>
|
<string name="album_artist">Album artist</string>
|
||||||
<string name="album">Album</string>
|
<string name="album">Album</string>
|
||||||
<string name="popular_songs">Popular songs</string>
|
<string name="popular_songs">Popular songs</string>
|
||||||
|
<string name="play_next">Play next</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue