diff --git a/app/src/main/java/com/zionhuang/music/ui/component/EmptyPlaceholder.kt b/app/src/main/java/com/zionhuang/music/ui/component/EmptyPlaceholder.kt index 39eb78f69..75cb5ae39 100644 --- a/app/src/main/java/com/zionhuang/music/ui/component/EmptyPlaceholder.kt +++ b/app/src/main/java/com/zionhuang/music/ui/component/EmptyPlaceholder.kt @@ -2,7 +2,12 @@ package com.zionhuang.music.ui.component import androidx.annotation.DrawableRes import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -22,7 +27,7 @@ fun EmptyPlaceholder( horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier .fillMaxSize() - .padding(12.dp) + .padding(horizontal = 12.dp, vertical = 24.dp) ) { Image( painter = painterResource(icon), diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryAlbumsScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryAlbumsScreen.kt index 446ae5287..f0f81b5f7 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryAlbumsScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryAlbumsScreen.kt @@ -57,6 +57,7 @@ import com.zionhuang.music.constants.SmallGridThumbnailHeight import com.zionhuang.music.ui.component.AlbumGridItem import com.zionhuang.music.ui.component.AlbumListItem import com.zionhuang.music.ui.component.ChipsRow +import com.zionhuang.music.ui.component.EmptyPlaceholder import com.zionhuang.music.ui.component.LocalMenuState import com.zionhuang.music.ui.component.SortHeader import com.zionhuang.music.ui.menu.AlbumMenu @@ -157,11 +158,13 @@ fun LibraryAlbumsScreen( Spacer(Modifier.weight(1f)) - Text( - text = pluralStringResource(R.plurals.n_album, albums.size, albums.size), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) + albums?.let { albums -> + Text( + text = pluralStringResource(R.plurals.n_album, albums.size, albums.size), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) + } } } @@ -188,40 +191,52 @@ fun LibraryAlbumsScreen( headerContent() } - items( - items = albums, - key = { it.id }, - contentType = { CONTENT_TYPE_ALBUM } - ) { album -> - AlbumListItem( - album = album, - isActive = album.id == mediaMetadata?.album?.id, - isPlaying = isPlaying, - trailingContent = { - IconButton( - onClick = { - menuState.show { - AlbumMenu( - originalAlbum = album, - navController = navController, - onDismiss = menuState::dismiss - ) + albums?.let { albums -> + if (albums.isEmpty()) { + item { + EmptyPlaceholder( + icon = R.drawable.album, + text = stringResource(R.string.library_album_empty), + modifier = Modifier.animateItem() + ) + } + } + + items( + items = albums, + key = { it.id }, + contentType = { CONTENT_TYPE_ALBUM } + ) { album -> + AlbumListItem( + album = album, + isActive = album.id == mediaMetadata?.album?.id, + isPlaying = isPlaying, + trailingContent = { + IconButton( + onClick = { + menuState.show { + AlbumMenu( + originalAlbum = album, + navController = navController, + onDismiss = menuState::dismiss + ) + } } + ) { + Icon( + painter = painterResource(R.drawable.more_vert), + contentDescription = null + ) } - ) { - Icon( - painter = painterResource(R.drawable.more_vert), - contentDescription = null - ) - } - }, - modifier = Modifier - .fillMaxWidth() - .combinedClickable { - navController.navigate("album/${album.id}") - } - .animateItem() - ) + }, + modifier = Modifier + .fillMaxWidth() + .combinedClickable { + navController.navigate("album/${album.id}") + } + .animateItem() + ) + } } } @@ -252,36 +267,48 @@ fun LibraryAlbumsScreen( headerContent() } - items( - items = albums, - key = { it.id }, - contentType = { CONTENT_TYPE_ALBUM } - ) { album -> - AlbumGridItem( - album = album, - isActive = album.id == mediaMetadata?.album?.id, - isPlaying = isPlaying, - coroutineScope = coroutineScope, - fillMaxWidth = true, - modifier = Modifier - .fillMaxWidth() - .combinedClickable( - onClick = { - navController.navigate("album/${album.id}") - }, - onLongClick = { - haptic.performHapticFeedback(HapticFeedbackType.LongPress) - menuState.show { - AlbumMenu( - originalAlbum = album, - navController = navController, - onDismiss = menuState::dismiss - ) - } - } + albums?.let { albums -> + if (albums.isEmpty()) { + item(span = { GridItemSpan(maxLineSpan) }) { + EmptyPlaceholder( + icon = R.drawable.album, + text = stringResource(R.string.library_album_empty), + modifier = Modifier.animateItem() ) - .animateItem() - ) + } + } + + items( + items = albums, + key = { it.id }, + contentType = { CONTENT_TYPE_ALBUM } + ) { album -> + AlbumGridItem( + album = album, + isActive = album.id == mediaMetadata?.album?.id, + isPlaying = isPlaying, + coroutineScope = coroutineScope, + fillMaxWidth = true, + modifier = Modifier + .fillMaxWidth() + .combinedClickable( + onClick = { + navController.navigate("album/${album.id}") + }, + onLongClick = { + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + menuState.show { + AlbumMenu( + originalAlbum = album, + navController = navController, + onDismiss = menuState::dismiss + ) + } + } + ) + .animateItem() + ) + } } } } diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryArtistsScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryArtistsScreen.kt index f49d0700f..10870bddd 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryArtistsScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryArtistsScreen.kt @@ -57,6 +57,7 @@ import com.zionhuang.music.constants.SmallGridThumbnailHeight import com.zionhuang.music.ui.component.ArtistGridItem import com.zionhuang.music.ui.component.ArtistListItem import com.zionhuang.music.ui.component.ChipsRow +import com.zionhuang.music.ui.component.EmptyPlaceholder import com.zionhuang.music.ui.component.LocalMenuState import com.zionhuang.music.ui.component.SortHeader import com.zionhuang.music.ui.menu.ArtistMenu @@ -150,11 +151,13 @@ fun LibraryArtistsScreen( Spacer(Modifier.weight(1f)) - Text( - text = pluralStringResource(R.plurals.n_artist, artists.size, artists.size), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) + artists?.let { artists -> + Text( + text = pluralStringResource(R.plurals.n_artist, artists.size, artists.size), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) + } } } @@ -181,38 +184,50 @@ fun LibraryArtistsScreen( headerContent() } - items( - items = artists, - key = { it.id }, - contentType = { CONTENT_TYPE_ARTIST } - ) { artist -> - ArtistListItem( - artist = artist, - trailingContent = { - IconButton( - onClick = { - menuState.show { - ArtistMenu( - originalArtist = artist, - coroutineScope = coroutineScope, - onDismiss = menuState::dismiss - ) + artists?.let { artists -> + if (artists.isEmpty()) { + item { + EmptyPlaceholder( + icon = R.drawable.artist, + text = stringResource(R.string.library_artist_empty), + modifier = Modifier.animateItem() + ) + } + } + + items( + items = artists, + key = { it.id }, + contentType = { CONTENT_TYPE_ARTIST } + ) { artist -> + ArtistListItem( + artist = artist, + trailingContent = { + IconButton( + onClick = { + menuState.show { + ArtistMenu( + originalArtist = artist, + coroutineScope = coroutineScope, + onDismiss = menuState::dismiss + ) + } } + ) { + Icon( + painter = painterResource(R.drawable.more_vert), + contentDescription = null + ) } - ) { - Icon( - painter = painterResource(R.drawable.more_vert), - contentDescription = null - ) - } - }, - modifier = Modifier - .fillMaxWidth() - .clickable { - navController.navigate("artist/${artist.id}") - } - .animateItem() - ) + }, + modifier = Modifier + .fillMaxWidth() + .clickable { + navController.navigate("artist/${artist.id}") + } + .animateItem() + ) + } } } @@ -243,33 +258,45 @@ fun LibraryArtistsScreen( headerContent() } - items( - items = artists, - key = { it.id }, - contentType = { CONTENT_TYPE_ARTIST } - ) { artist -> - ArtistGridItem( - artist = artist, - fillMaxWidth = true, - modifier = Modifier - .fillMaxWidth() - .combinedClickable( - onClick = { - navController.navigate("artist/${artist.id}") - }, - onLongClick = { - haptic.performHapticFeedback(HapticFeedbackType.LongPress) - menuState.show { - ArtistMenu( - originalArtist = artist, - coroutineScope = coroutineScope, - onDismiss = menuState::dismiss - ) - } - } + artists?.let { artists -> + if (artists.isEmpty()) { + item(span = { GridItemSpan(maxLineSpan) }) { + EmptyPlaceholder( + icon = R.drawable.artist, + text = stringResource(R.string.library_artist_empty), + modifier = Modifier.animateItem() ) - .animateItem() - ) + } + } + + items( + items = artists, + key = { it.id }, + contentType = { CONTENT_TYPE_ARTIST } + ) { artist -> + ArtistGridItem( + artist = artist, + fillMaxWidth = true, + modifier = Modifier + .fillMaxWidth() + .combinedClickable( + onClick = { + navController.navigate("artist/${artist.id}") + }, + onLongClick = { + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + menuState.show { + ArtistMenu( + originalArtist = artist, + coroutineScope = coroutineScope, + onDismiss = menuState::dismiss + ) + } + } + ) + .animateItem() + ) + } } } } diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryPlaylistsScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryPlaylistsScreen.kt index 0f6b1a0c9..cfe3dd3c1 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryPlaylistsScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibraryPlaylistsScreen.kt @@ -56,6 +56,7 @@ import com.zionhuang.music.constants.PlaylistSortTypeKey import com.zionhuang.music.constants.PlaylistViewTypeKey import com.zionhuang.music.constants.SmallGridThumbnailHeight import com.zionhuang.music.db.entities.PlaylistEntity +import com.zionhuang.music.ui.component.EmptyPlaceholder import com.zionhuang.music.ui.component.HideOnScrollFAB import com.zionhuang.music.ui.component.LocalMenuState import com.zionhuang.music.ui.component.PlaylistGridItem @@ -143,11 +144,13 @@ fun LibraryPlaylistsScreen( Spacer(Modifier.weight(1f)) - Text( - text = pluralStringResource(R.plurals.n_playlist, playlists.size, playlists.size), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) + playlists?.let { playlists -> + Text( + text = pluralStringResource(R.plurals.n_playlist, playlists.size, playlists.size), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) + } IconButton( onClick = { @@ -184,38 +187,50 @@ fun LibraryPlaylistsScreen( headerContent() } - items( - items = playlists, - key = { it.id }, - contentType = { CONTENT_TYPE_PLAYLIST } - ) { playlist -> - PlaylistListItem( - playlist = playlist, - trailingContent = { - IconButton( - onClick = { - menuState.show { - PlaylistMenu( - playlist = playlist, - coroutineScope = coroutineScope, - onDismiss = menuState::dismiss - ) + playlists?.let { playlists -> + if (playlists.isEmpty()) { + item { + EmptyPlaceholder( + icon = R.drawable.queue_music, + text = stringResource(R.string.library_playlist_empty), + modifier = Modifier.animateItem() + ) + } + } + + items( + items = playlists, + key = { it.id }, + contentType = { CONTENT_TYPE_PLAYLIST } + ) { playlist -> + PlaylistListItem( + playlist = playlist, + trailingContent = { + IconButton( + onClick = { + menuState.show { + PlaylistMenu( + playlist = playlist, + coroutineScope = coroutineScope, + onDismiss = menuState::dismiss + ) + } } + ) { + Icon( + painter = painterResource(R.drawable.more_vert), + contentDescription = null + ) } - ) { - Icon( - painter = painterResource(R.drawable.more_vert), - contentDescription = null - ) - } - }, - modifier = Modifier - .fillMaxWidth() - .clickable { - navController.navigate("local_playlist/${playlist.id}") - } - .animateItem() - ) + }, + modifier = Modifier + .fillMaxWidth() + .clickable { + navController.navigate("local_playlist/${playlist.id}") + } + .animateItem() + ) + } } } @@ -247,33 +262,45 @@ fun LibraryPlaylistsScreen( headerContent() } - items( - items = playlists, - key = { it.id }, - contentType = { CONTENT_TYPE_PLAYLIST } - ) { playlist -> - PlaylistGridItem( - playlist = playlist, - fillMaxWidth = true, - modifier = Modifier - .fillMaxWidth() - .combinedClickable( - onClick = { - navController.navigate("local_playlist/${playlist.id}") - }, - onLongClick = { - haptic.performHapticFeedback(HapticFeedbackType.LongPress) - menuState.show { - PlaylistMenu( - playlist = playlist, - coroutineScope = coroutineScope, - onDismiss = menuState::dismiss - ) - } - } + playlists?.let { playlists -> + if (playlists.isEmpty()) { + item(span = { GridItemSpan(maxLineSpan) }) { + EmptyPlaceholder( + icon = R.drawable.queue_music, + text = stringResource(R.string.library_playlist_empty), + modifier = Modifier.animateItem() ) - .animateItem() - ) + } + } + + items( + items = playlists, + key = { it.id }, + contentType = { CONTENT_TYPE_PLAYLIST } + ) { playlist -> + PlaylistGridItem( + playlist = playlist, + fillMaxWidth = true, + modifier = Modifier + .fillMaxWidth() + .combinedClickable( + onClick = { + navController.navigate("local_playlist/${playlist.id}") + }, + onLongClick = { + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + menuState.show { + PlaylistMenu( + playlist = playlist, + coroutineScope = coroutineScope, + onDismiss = menuState::dismiss + ) + } + } + ) + .animateItem() + ) + } } } diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibrarySongsScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibrarySongsScreen.kt index 94af16578..6b819573f 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/library/LibrarySongsScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/library/LibrarySongsScreen.kt @@ -45,6 +45,7 @@ import com.zionhuang.music.extensions.toMediaItem import com.zionhuang.music.extensions.togglePlayPause import com.zionhuang.music.playback.queues.ListQueue import com.zionhuang.music.ui.component.ChipsRow +import com.zionhuang.music.ui.component.EmptyPlaceholder import com.zionhuang.music.ui.component.HideOnScrollFAB import com.zionhuang.music.ui.component.LocalMenuState import com.zionhuang.music.ui.component.SongListItem @@ -130,70 +131,84 @@ fun LibrarySongsScreen( Spacer(Modifier.weight(1f)) - Text( - text = pluralStringResource(R.plurals.n_song, songs.size, songs.size), - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.secondary - ) + songs?.let { songs -> + Text( + text = pluralStringResource(R.plurals.n_song, songs.size, songs.size), + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary + ) + } } } - itemsIndexed( - items = songs, - key = { _, item -> item.id }, - contentType = { _, _ -> CONTENT_TYPE_SONG } - ) { index, song -> - SongListItem( - song = song, - isActive = song.id == mediaMetadata?.id, - isPlaying = isPlaying, - trailingContent = { - IconButton( - onClick = { - menuState.show { - SongMenu( - originalSong = song, - navController = navController, - onDismiss = menuState::dismiss - ) + songs?.let { songs -> + if (songs.isEmpty()) { + item { + EmptyPlaceholder( + icon = R.drawable.music_note, + text = stringResource(R.string.library_song_empty), + modifier = Modifier.animateItem() + ) + } + } + + itemsIndexed( + items = songs, + key = { _, item -> item.id }, + contentType = { _, _ -> CONTENT_TYPE_SONG } + ) { index, song -> + SongListItem( + song = song, + isActive = song.id == mediaMetadata?.id, + isPlaying = isPlaying, + trailingContent = { + IconButton( + onClick = { + menuState.show { + SongMenu( + originalSong = song, + navController = navController, + onDismiss = menuState::dismiss + ) + } } + ) { + Icon( + painter = painterResource(R.drawable.more_vert), + contentDescription = null + ) } - ) { - Icon( - painter = painterResource(R.drawable.more_vert), - contentDescription = null - ) - } - }, - modifier = Modifier - .fillMaxWidth() - .combinedClickable { - if (song.id == mediaMetadata?.id) { - playerConnection.player.togglePlayPause() - } else { - playerConnection.playQueue( - ListQueue( - title = context.getString(R.string.queue_all_songs), - items = songs.map { it.toMediaItem() }, - startIndex = index + }, + modifier = Modifier + .fillMaxWidth() + .combinedClickable { + if (song.id == mediaMetadata?.id) { + playerConnection.player.togglePlayPause() + } else { + playerConnection.playQueue( + ListQueue( + title = context.getString(R.string.queue_all_songs), + items = songs.map { it.toMediaItem() }, + startIndex = index + ) ) - ) + } } - } - .animateItem() - ) + .animateItem() + ) + } } } HideOnScrollFAB( - visible = songs.isNotEmpty(), + visible = !songs.isNullOrEmpty(), lazyListState = lazyListState, icon = R.drawable.shuffle, onClick = { playerConnection.playQueue( ListQueue( title = context.getString(R.string.queue_all_songs), - items = songs.shuffled().map { it.toMediaItem() }, + items = songs!!.shuffled().map { it.toMediaItem() }, ) ) } diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/playlist/LocalPlaylistScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/playlist/LocalPlaylistScreen.kt index dee75e83e..01b1a4c83 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/playlist/LocalPlaylistScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/playlist/LocalPlaylistScreen.kt @@ -303,7 +303,8 @@ fun LocalPlaylistScreen( item { EmptyPlaceholder( icon = R.drawable.music_note, - text = stringResource(R.string.playlist_is_empty) + text = stringResource(R.string.playlist_is_empty), + modifier = Modifier.animateItem() ) } } else { diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/search/LocalSearchScreen.kt b/app/src/main/java/com/zionhuang/music/ui/screens/search/LocalSearchScreen.kt index 0d2c5d316..3ed827475 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/search/LocalSearchScreen.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/search/LocalSearchScreen.kt @@ -234,7 +234,8 @@ fun LocalSearchScreen( ) { EmptyPlaceholder( icon = R.drawable.search, - text = stringResource(R.string.no_results_found) + text = stringResource(R.string.no_results_found), + modifier = Modifier.animateItem() ) } } diff --git a/app/src/main/java/com/zionhuang/music/ui/screens/search/OnlineSearchResult.kt b/app/src/main/java/com/zionhuang/music/ui/screens/search/OnlineSearchResult.kt index ffd79fb2f..62809452a 100644 --- a/app/src/main/java/com/zionhuang/music/ui/screens/search/OnlineSearchResult.kt +++ b/app/src/main/java/com/zionhuang/music/ui/screens/search/OnlineSearchResult.kt @@ -182,7 +182,8 @@ fun OnlineSearchResult( item { EmptyPlaceholder( icon = R.drawable.search, - text = stringResource(R.string.no_results_found) + text = stringResource(R.string.no_results_found), + modifier = Modifier.animateItem() ) } } @@ -207,7 +208,8 @@ fun OnlineSearchResult( item { EmptyPlaceholder( icon = R.drawable.search, - text = stringResource(R.string.no_results_found) + text = stringResource(R.string.no_results_found), + modifier = Modifier.animateItem() ) } } diff --git a/app/src/main/java/com/zionhuang/music/viewmodels/LibraryViewModels.kt b/app/src/main/java/com/zionhuang/music/viewmodels/LibraryViewModels.kt index 15fee1187..01c66f494 100644 --- a/app/src/main/java/com/zionhuang/music/viewmodels/LibraryViewModels.kt +++ b/app/src/main/java/com/zionhuang/music/viewmodels/LibraryViewModels.kt @@ -8,7 +8,27 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.media3.exoplayer.offline.Download import com.zionhuang.innertube.YouTube -import com.zionhuang.music.constants.* +import com.zionhuang.music.constants.AlbumFilter +import com.zionhuang.music.constants.AlbumFilterKey +import com.zionhuang.music.constants.AlbumSortDescendingKey +import com.zionhuang.music.constants.AlbumSortType +import com.zionhuang.music.constants.AlbumSortTypeKey +import com.zionhuang.music.constants.ArtistFilter +import com.zionhuang.music.constants.ArtistFilterKey +import com.zionhuang.music.constants.ArtistSongSortDescendingKey +import com.zionhuang.music.constants.ArtistSongSortType +import com.zionhuang.music.constants.ArtistSongSortTypeKey +import com.zionhuang.music.constants.ArtistSortDescendingKey +import com.zionhuang.music.constants.ArtistSortType +import com.zionhuang.music.constants.ArtistSortTypeKey +import com.zionhuang.music.constants.PlaylistSortDescendingKey +import com.zionhuang.music.constants.PlaylistSortType +import com.zionhuang.music.constants.PlaylistSortTypeKey +import com.zionhuang.music.constants.SongFilter +import com.zionhuang.music.constants.SongFilterKey +import com.zionhuang.music.constants.SongSortDescendingKey +import com.zionhuang.music.constants.SongSortType +import com.zionhuang.music.constants.SongSortTypeKey import com.zionhuang.music.db.MusicDatabase import com.zionhuang.music.extensions.reversed import com.zionhuang.music.extensions.toEnum @@ -19,7 +39,12 @@ import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import java.time.Duration import java.time.LocalDateTime @@ -65,7 +90,7 @@ class LibrarySongsViewModel @Inject constructor( } } } - }.stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) + }.stateIn(viewModelScope, SharingStarted.Lazily, null) } @HiltViewModel @@ -88,17 +113,17 @@ class LibraryArtistsViewModel @Inject constructor( ArtistFilter.LIKED -> database.artistsBookmarked(sortType, descending) } } - .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) + .stateIn(viewModelScope, SharingStarted.Lazily, null) init { viewModelScope.launch(Dispatchers.IO) { allArtists.collect { artists -> artists - .map { it.artist } - .filter { + ?.map { it.artist } + ?.filter { it.thumbnailUrl == null || Duration.between(it.lastUpdateTime, LocalDateTime.now()) > Duration.ofDays(10) } - .forEach { artist -> + ?.forEach { artist -> YouTube.artist(artist.id).onSuccess { artistPage -> database.query { update(artist, artistPage) @@ -130,27 +155,29 @@ class LibraryAlbumsViewModel @Inject constructor( AlbumFilter.LIKED -> database.albumsLiked(sortType, descending) } } - .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) + .stateIn(viewModelScope, SharingStarted.Lazily, null) init { viewModelScope.launch(Dispatchers.IO) { allAlbums.collect { albums -> - albums.filter { - it.album.songCount == 0 - }.forEach { album -> - YouTube.album(album.id).onSuccess { albumPage -> - database.query { - update(album.album, albumPage) - } - }.onFailure { - reportException(it) - if (it.message?.contains("NOT_FOUND") == true) { + albums + ?.filter { + it.album.songCount == 0 + } + ?.forEach { album -> + YouTube.album(album.id).onSuccess { albumPage -> database.query { - delete(album.album) + update(album.album, albumPage) + } + }.onFailure { + reportException(it) + if (it.message?.contains("NOT_FOUND") == true) { + database.query { + delete(album.album) + } } } } - } } } } @@ -169,7 +196,7 @@ class LibraryPlaylistsViewModel @Inject constructor( .flatMapLatest { (sortType, descending) -> database.playlists(sortType, descending) } - .stateIn(viewModelScope, SharingStarted.Lazily, emptyList()) + .stateIn(viewModelScope, SharingStarted.Lazily, null) } @HiltViewModel diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c96d500a7..fbc4b902c 100755 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -52,6 +52,12 @@ 收藏 找不到結果 + + 媒體庫的歌曲會顯示在這裡 + 媒體庫的藝人會顯示在這裡 + 媒體庫的專輯會顯示在這裡 + 你的播放清單會顯示在這裡 + 來自你的媒體庫 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index c512c7a79..dc17a6b33 100755 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -52,6 +52,12 @@ Bookmarked No results found + + Library songs will show up here + Library artists will show up here + Library albums will show up here + Your playlists will show up here + From your library