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