mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 15:50:16 +02:00
Unify logic for albums & artists
This commit is contained in:
parent
7a869d9f47
commit
9fb77854e4
5 changed files with 114 additions and 152 deletions
|
|
@ -35,7 +35,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
|
|
@ -61,10 +60,8 @@ 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.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -82,28 +79,26 @@ import kotlinx.coroutines.launch
|
|||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.api.client.extensions.itemsApi
|
||||
import org.jellyfin.sdk.api.client.extensions.userLibraryApi
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import org.jellyfin.sdk.model.api.ImageType
|
||||
import org.jellyfin.sdk.model.api.MediaType
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
|
||||
@HiltViewModel(assistedFactory = AlbumViewModel.Factory::class)
|
||||
class AlbumViewModel
|
||||
@AssistedInject
|
||||
constructor(
|
||||
private val api: ApiClient,
|
||||
api: ApiClient,
|
||||
musicService: MusicService,
|
||||
navigationManager: NavigationManager,
|
||||
@param:ApplicationContext private val context: Context,
|
||||
val navigationManager: NavigationManager,
|
||||
val serverRepository: ServerRepository,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val backdropService: BackdropService,
|
||||
private val imageUrlService: ImageUrlService,
|
||||
private val musicService: MusicService,
|
||||
@Assisted val itemId: UUID,
|
||||
) : ViewModel() {
|
||||
) : MusicViewModel(api, musicService, navigationManager) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(itemId: UUID): AlbumViewModel
|
||||
|
|
@ -175,39 +170,8 @@ class AlbumViewModel
|
|||
shuffled: Boolean,
|
||||
startIndex: Int = 0,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Playing album %s from %s", itemId, startIndex)
|
||||
val songs = state.value.songs as ApiRequestPager<*>
|
||||
musicService.setQueue(songs, startIndex, shuffled)
|
||||
}
|
||||
}
|
||||
|
||||
fun playNext(song: BaseItem) {
|
||||
viewModelScope.launchDefault {
|
||||
musicService.playNext(song)
|
||||
}
|
||||
}
|
||||
|
||||
fun addToQueue(
|
||||
item: BaseItem,
|
||||
index: Int,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
val songs = state.value.songs as ApiRequestPager<*>
|
||||
if (item.id == this@AlbumViewModel.itemId) {
|
||||
musicService.addAllToQueue(songs, 0)
|
||||
} else if (item.type == BaseItemKind.AUDIO) {
|
||||
musicService.addToQueue(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startInstantMix() {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Starting instant mix for %s", itemId)
|
||||
musicService.startInstantMix(itemId)
|
||||
navigationManager.navigateTo(Destination.NowPlaying)
|
||||
}
|
||||
val songs = state.value.songs as ApiRequestPager<*>
|
||||
play(songs, startIndex, shuffled)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +261,7 @@ fun AlbumDetailsPage(
|
|||
remember {
|
||||
MusicButtonActions(
|
||||
onClickPlay = { viewModel.play(it, 0) },
|
||||
onClickInstantMix = viewModel::startInstantMix,
|
||||
onClickInstantMix = { viewModel.startInstantMix(album.id) },
|
||||
onClickFavorite = {
|
||||
viewModel.setFavorite(
|
||||
album.id,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
|
|
@ -69,10 +68,8 @@ 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.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.toBaseItems
|
||||
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.GetItemsRequestHandler
|
||||
import com.github.damontecres.wholphin.util.LoadingState
|
||||
|
|
@ -95,25 +92,24 @@ 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.request.GetItemsRequest
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
|
||||
@HiltViewModel(assistedFactory = ArtistViewModel.Factory::class)
|
||||
class ArtistViewModel
|
||||
@AssistedInject
|
||||
constructor(
|
||||
private val api: ApiClient,
|
||||
api: ApiClient,
|
||||
musicService: MusicService,
|
||||
navigationManager: NavigationManager,
|
||||
@param:ApplicationContext private val context: Context,
|
||||
val navigationManager: NavigationManager,
|
||||
val serverRepository: ServerRepository,
|
||||
val mediaReportService: MediaReportService,
|
||||
private val favoriteWatchManager: FavoriteWatchManager,
|
||||
private val userPreferencesService: UserPreferencesService,
|
||||
private val backdropService: BackdropService,
|
||||
private val imageUrlService: ImageUrlService,
|
||||
private val musicService: MusicService,
|
||||
@Assisted val itemId: UUID,
|
||||
) : ViewModel() {
|
||||
) : MusicViewModel(api, musicService, navigationManager) {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(itemId: UUID): ArtistViewModel
|
||||
|
|
@ -211,103 +207,6 @@ class ArtistViewModel
|
|||
.let { BaseItem(it, false) }
|
||||
_state.update { it.copy(artist = artist) }
|
||||
}
|
||||
|
||||
fun playArtist(shuffled: Boolean) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Playing artist %s", itemId)
|
||||
val request =
|
||||
GetItemsRequest(
|
||||
parentId = itemId,
|
||||
fields = DefaultItemFields,
|
||||
recursive = true,
|
||||
includeItemTypes = listOf(BaseItemKind.AUDIO),
|
||||
sortBy =
|
||||
listOf(
|
||||
ItemSortBy.PREMIERE_DATE,
|
||||
ItemSortBy.INDEX_NUMBER,
|
||||
),
|
||||
sortOrder = listOf(SortOrder.DESCENDING, SortOrder.ASCENDING),
|
||||
)
|
||||
val pager =
|
||||
ApiRequestPager(api, request, GetItemsRequestHandler, viewModelScope).init()
|
||||
musicService.setQueue(pager, 0, shuffled)
|
||||
}
|
||||
}
|
||||
|
||||
fun addToQueue(
|
||||
itemId: UUID,
|
||||
index: Int,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
if (itemId == this@ArtistViewModel.itemId) {
|
||||
// TODO
|
||||
} else {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startInstantMix() {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Starting instant mix for %s", itemId)
|
||||
musicService.startInstantMix(itemId)
|
||||
navigationManager.navigateTo(Destination.NowPlaying)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
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 -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class ArtistState(
|
||||
|
|
@ -403,8 +302,8 @@ fun ArtistDetailsPage(
|
|||
actions =
|
||||
remember {
|
||||
MusicButtonActions(
|
||||
onClickPlay = { viewModel.playArtist(it) },
|
||||
onClickInstantMix = viewModel::startInstantMix,
|
||||
onClickPlay = { viewModel.play(artist) },
|
||||
onClickInstantMix = { viewModel.startInstantMix(artist.id) },
|
||||
onClickFavorite = {
|
||||
viewModel.setFavorite(
|
||||
artist.id,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,99 @@
|
|||
package com.github.damontecres.wholphin.ui.detail.music
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.services.MusicService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
import com.github.damontecres.wholphin.ui.launchDefault
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.util.ApiRequestPager
|
||||
import com.github.damontecres.wholphin.util.BlockingList
|
||||
import org.jellyfin.sdk.api.client.ApiClient
|
||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||
import timber.log.Timber
|
||||
import java.util.UUID
|
||||
|
||||
abstract class MusicViewModel(
|
||||
internal val api: ApiClient,
|
||||
internal val musicService: MusicService,
|
||||
internal val navigationManager: NavigationManager,
|
||||
) : ViewModel() {
|
||||
fun play(
|
||||
pager: ApiRequestPager<*>,
|
||||
startIndex: Int = 0,
|
||||
shuffled: Boolean = false,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
musicService.setQueue(pager, startIndex, shuffled)
|
||||
}
|
||||
}
|
||||
|
||||
fun play(
|
||||
item: BaseItem,
|
||||
startIndex: Int = 0,
|
||||
shuffled: Boolean = false,
|
||||
) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Playing %s %s", item.type, item.id)
|
||||
when (item.type) {
|
||||
BaseItemKind.AUDIO -> {
|
||||
musicService.setQueue(listOf(item), shuffled)
|
||||
}
|
||||
|
||||
BaseItemKind.MUSIC_ALBUM -> {
|
||||
val pager = getPagerForAlbum(api, item.id)
|
||||
musicService.setQueue(pager, startIndex, shuffled)
|
||||
}
|
||||
|
||||
BaseItemKind.MUSIC_ARTIST -> {
|
||||
val pager = getPagerForArtist(api, item.id)
|
||||
musicService.setQueue(pager, startIndex, shuffled)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun playNext(song: BaseItem) {
|
||||
viewModelScope.launchDefault {
|
||||
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, item.id)
|
||||
musicService.addAllToQueue(pager, 0)
|
||||
}
|
||||
|
||||
BaseItemKind.MUSIC_ARTIST -> {
|
||||
val pager = getPagerForArtist(api, item.id)
|
||||
musicService.addAllToQueue(pager, 0)
|
||||
}
|
||||
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun startInstantMix(itemId: UUID) {
|
||||
viewModelScope.launchIO {
|
||||
Timber.v("Starting instant mix for %s", itemId)
|
||||
musicService.startInstantMix(itemId)
|
||||
navigationManager.navigateTo(Destination.NowPlaying)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ class NowPlayingViewModel
|
|||
val mediaItem =
|
||||
onMain {
|
||||
player.currentMediaItemIndex
|
||||
.takeIf { it >= 0 }
|
||||
.takeIf { it in 0..<player.mediaItemCount }
|
||||
?.let { player.getMediaItemAt(it) }
|
||||
}
|
||||
return mediaItem?.localConfiguration?.tag as? AudioItem
|
||||
|
|
|
|||
|
|
@ -355,7 +355,7 @@ fun NavDrawer(
|
|||
interactionSource = interactionSource,
|
||||
onClick = {
|
||||
viewModel.setIndex(NOW_PLAYING_INDEX)
|
||||
viewModel.navigationManager.navigateToFromDrawer(Destination.NowPlaying)
|
||||
viewModel.navigationManager.navigateTo(Destination.NowPlaying)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue