Change playlist import UI flow
This commit is contained in:
parent
5b47484a40
commit
ba9ae5c705
2 changed files with 38 additions and 39 deletions
|
@ -296,9 +296,6 @@ interface Database {
|
||||||
@Query("SELECT * FROM Song WHERE title LIKE :query OR artistsText LIKE :query")
|
@Query("SELECT * FROM Song WHERE title LIKE :query OR artistsText LIKE :query")
|
||||||
fun search(query: String): Flow<List<DetailedSong>>
|
fun search(query: String): Flow<List<DetailedSong>>
|
||||||
|
|
||||||
@Query("SELECT EXISTS(SELECT 1 FROM Playlist WHERE browseId = :browseId)")
|
|
||||||
fun isImportedPlaylist(browseId: String): Flow<Boolean>
|
|
||||||
|
|
||||||
@Transaction
|
@Transaction
|
||||||
@Query("SELECT Song.* FROM Event JOIN Song ON Song.id = songId GROUP BY songId ORDER BY SUM(CAST(playTime AS REAL) / (((:now - timestamp) / 86400000) + 1)) DESC LIMIT 1")
|
@Query("SELECT Song.* FROM Event JOIN Song ON Song.id = songId GROUP BY songId ORDER BY SUM(CAST(playTime AS REAL) / (((:now - timestamp) / 86400000) + 1)) DESC LIMIT 1")
|
||||||
@RewriteQueriesToDropUnusedColumns
|
@RewriteQueriesToDropUnusedColumns
|
||||||
|
|
|
@ -14,7 +14,9 @@ import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.saveable.autoSaver
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
@ -25,6 +27,7 @@ import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.models.Playlist
|
import it.vfsfitvnm.vimusic.models.Playlist
|
||||||
import it.vfsfitvnm.vimusic.models.SongPlaylistMap
|
import it.vfsfitvnm.vimusic.models.SongPlaylistMap
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.savers.InnertubePlaylistOrAlbumPageSaver
|
import it.vfsfitvnm.vimusic.savers.InnertubePlaylistOrAlbumPageSaver
|
||||||
import it.vfsfitvnm.vimusic.savers.nullableSaver
|
import it.vfsfitvnm.vimusic.savers.nullableSaver
|
||||||
import it.vfsfitvnm.vimusic.transaction
|
import it.vfsfitvnm.vimusic.transaction
|
||||||
|
@ -37,6 +40,7 @@ import it.vfsfitvnm.vimusic.ui.components.themed.HeaderPlaceholder
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.LayoutWithAdaptiveThumbnail
|
import it.vfsfitvnm.vimusic.ui.components.themed.LayoutWithAdaptiveThumbnail
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.NonQueuedMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.SecondaryTextButton
|
import it.vfsfitvnm.vimusic.ui.components.themed.SecondaryTextButton
|
||||||
|
import it.vfsfitvnm.vimusic.ui.components.themed.TextFieldDialog
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.adaptiveThumbnailContent
|
import it.vfsfitvnm.vimusic.ui.components.themed.adaptiveThumbnailContent
|
||||||
import it.vfsfitvnm.vimusic.ui.items.SongItem
|
import it.vfsfitvnm.vimusic.ui.items.SongItem
|
||||||
import it.vfsfitvnm.vimusic.ui.items.SongItemPlaceholder
|
import it.vfsfitvnm.vimusic.ui.items.SongItemPlaceholder
|
||||||
|
@ -54,7 +58,6 @@ import it.vfsfitvnm.youtubemusic.Innertube
|
||||||
import it.vfsfitvnm.youtubemusic.models.bodies.BrowseBody
|
import it.vfsfitvnm.youtubemusic.models.bodies.BrowseBody
|
||||||
import it.vfsfitvnm.youtubemusic.requests.playlistPage
|
import it.vfsfitvnm.youtubemusic.requests.playlistPage
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@ExperimentalFoundationApi
|
@ExperimentalFoundationApi
|
||||||
|
@ -79,19 +82,39 @@ fun PlaylistSongList(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val isImported by produceSaveableState(
|
|
||||||
initialValue = null,
|
|
||||||
stateSaver = autoSaver<Boolean?>(),
|
|
||||||
) {
|
|
||||||
Database
|
|
||||||
.isImportedPlaylist(browseId)
|
|
||||||
.flowOn(Dispatchers.IO)
|
|
||||||
.collect { value = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
val songThumbnailSizeDp = Dimensions.thumbnails.song
|
val songThumbnailSizeDp = Dimensions.thumbnails.song
|
||||||
val songThumbnailSizePx = songThumbnailSizeDp.px
|
val songThumbnailSizePx = songThumbnailSizeDp.px
|
||||||
|
|
||||||
|
var isImportingPlaylist by rememberSaveable {
|
||||||
|
mutableStateOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isImportingPlaylist) {
|
||||||
|
TextFieldDialog(
|
||||||
|
hintText = "Enter the playlist name",
|
||||||
|
initialTextInput = playlistPage?.title ?: "",
|
||||||
|
onDismiss = { isImportingPlaylist = false },
|
||||||
|
onDone = { text ->
|
||||||
|
query {
|
||||||
|
transaction {
|
||||||
|
val playlistId = Database.insert(Playlist(name = text, browseId = browseId))
|
||||||
|
|
||||||
|
playlistPage?.songsPage?.items
|
||||||
|
?.map(Innertube.SongItem::asMediaItem)
|
||||||
|
?.onEach(Database::insert)
|
||||||
|
?.mapIndexed { index, mediaItem ->
|
||||||
|
SongPlaylistMap(
|
||||||
|
songId = mediaItem.mediaId,
|
||||||
|
playlistId = playlistId,
|
||||||
|
position = index
|
||||||
|
)
|
||||||
|
}?.let(Database::insertSongPlaylistMaps)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val headerContent: @Composable () -> Unit = {
|
val headerContent: @Composable () -> Unit = {
|
||||||
if (playlistPage == null) {
|
if (playlistPage == null) {
|
||||||
HeaderPlaceholder(
|
HeaderPlaceholder(
|
||||||
|
@ -116,30 +139,9 @@ fun PlaylistSongList(
|
||||||
)
|
)
|
||||||
|
|
||||||
HeaderIconButton(
|
HeaderIconButton(
|
||||||
icon = if (isImported == true) R.drawable.bookmark else R.drawable.bookmark_outline,
|
icon = R.drawable.add,
|
||||||
color = colorPalette.accent,
|
color = colorPalette.text,
|
||||||
onClick = {
|
onClick = { isImportingPlaylist = true }
|
||||||
transaction {
|
|
||||||
val playlistId =
|
|
||||||
Database.insert(
|
|
||||||
Playlist(
|
|
||||||
name = playlistPage?.title ?: "Unknown",
|
|
||||||
browseId = browseId
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
playlistPage?.songsPage?.items
|
|
||||||
?.map(Innertube.SongItem::asMediaItem)
|
|
||||||
?.onEach(Database::insert)
|
|
||||||
?.mapIndexed { index, mediaItem ->
|
|
||||||
SongPlaylistMap(
|
|
||||||
songId = mediaItem.mediaId,
|
|
||||||
playlistId = playlistId,
|
|
||||||
position = index
|
|
||||||
)
|
|
||||||
}?.let(Database::insertSongPlaylistMaps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
HeaderIconButton(
|
HeaderIconButton(
|
||||||
|
|
Loading…
Reference in a new issue