Use database executors instead of compose coroutines to launch database operations
This commit is contained in:
parent
85f89ec799
commit
2cbb5a4ba4
11 changed files with 88 additions and 107 deletions
|
@ -207,8 +207,19 @@ object Converters {
|
||||||
val Database.internal: RoomDatabase
|
val Database.internal: RoomDatabase
|
||||||
get() = DatabaseInitializer.Instance
|
get() = DatabaseInitializer.Instance
|
||||||
|
|
||||||
fun Database.checkpoint() {
|
fun query(block: () -> Unit) = DatabaseInitializer.Instance.getQueryExecutor().execute(block)
|
||||||
internal.getOpenHelper().writableDatabase.run {
|
|
||||||
|
fun transaction(block: () -> Unit) = with(DatabaseInitializer.Instance) {
|
||||||
|
getTransactionExecutor().execute {
|
||||||
|
runInTransaction(block)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val RoomDatabase.path: String
|
||||||
|
get() = getOpenHelper().writableDatabase.path
|
||||||
|
|
||||||
|
fun RoomDatabase.checkpoint() {
|
||||||
|
getOpenHelper().writableDatabase.run {
|
||||||
query("PRAGMA journal_mode").use { cursor ->
|
query("PRAGMA journal_mode").use { cursor ->
|
||||||
if (cursor.moveToFirst()) {
|
if (cursor.moveToFirst()) {
|
||||||
when (cursor.getString(0).lowercase()) {
|
when (cursor.getString(0).lowercase()) {
|
||||||
|
|
|
@ -41,8 +41,8 @@ import coil.request.ImageRequest
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.MainActivity
|
import it.vfsfitvnm.vimusic.MainActivity
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.internal
|
|
||||||
import it.vfsfitvnm.vimusic.models.QueuedMediaItem
|
import it.vfsfitvnm.vimusic.models.QueuedMediaItem
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.utils.*
|
import it.vfsfitvnm.vimusic.utils.*
|
||||||
import it.vfsfitvnm.youtubemusic.Outcome
|
import it.vfsfitvnm.youtubemusic.Outcome
|
||||||
import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint
|
import it.vfsfitvnm.youtubemusic.models.NavigationEndpoint
|
||||||
|
@ -195,7 +195,7 @@ class PlayerService : Service(), Player.Listener, PlaybackStatsListener.Callback
|
||||||
val mediaItemIndex = player.currentMediaItemIndex
|
val mediaItemIndex = player.currentMediaItemIndex
|
||||||
val mediaItemPosition = player.currentPosition
|
val mediaItemPosition = player.currentPosition
|
||||||
|
|
||||||
Database.internal.getQueryExecutor().execute {
|
query {
|
||||||
Database.clearQueue()
|
Database.clearQueue()
|
||||||
Database.insertQueue(
|
Database.insertQueue(
|
||||||
mediaItems.mapIndexed { index, mediaItem ->
|
mediaItems.mapIndexed { index, mediaItem ->
|
||||||
|
@ -226,7 +226,7 @@ class PlayerService : Service(), Player.Listener, PlaybackStatsListener.Callback
|
||||||
val mediaItem =
|
val mediaItem =
|
||||||
eventTime.timeline.getWindow(eventTime.windowIndex, Timeline.Window()).mediaItem
|
eventTime.timeline.getWindow(eventTime.windowIndex, Timeline.Window()).mediaItem
|
||||||
|
|
||||||
Database.internal.getQueryExecutor().execute {
|
query {
|
||||||
Database.incrementTotalPlayTimeMs(mediaItem.mediaId, playbackStats.totalPlayTimeMs)
|
Database.incrementTotalPlayTimeMs(mediaItem.mediaId, playbackStats.totalPlayTimeMs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -443,7 +443,7 @@ class PlayerService : Service(), Player.Listener, PlaybackStatsListener.Callback
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaItem?.let {
|
mediaItem?.let {
|
||||||
Database.internal.getQueryExecutor().execute {
|
query {
|
||||||
Database.insert(it)
|
Database.insert(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.media3.common.MediaItem
|
import androidx.media3.common.MediaItem
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.route.empty
|
import it.vfsfitvnm.route.empty
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.*
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.internal
|
|
||||||
import it.vfsfitvnm.vimusic.models.Playlist
|
import it.vfsfitvnm.vimusic.models.Playlist
|
||||||
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
||||||
import it.vfsfitvnm.vimusic.models.SongWithInfo
|
import it.vfsfitvnm.vimusic.models.SongWithInfo
|
||||||
|
@ -39,13 +37,11 @@ fun InFavoritesMediaItemMenu(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onDismiss: (() -> Unit)? = null
|
onDismiss: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
NonQueuedMediaItemMenu(
|
NonQueuedMediaItemMenu(
|
||||||
mediaItem = song.asMediaItem,
|
mediaItem = song.asMediaItem,
|
||||||
onDismiss = onDismiss,
|
onDismiss = onDismiss,
|
||||||
onRemoveFromFavorites = {
|
onRemoveFromFavorites = {
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.update(song.song.toggleLike())
|
Database.update(song.song.toggleLike())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -63,8 +59,6 @@ fun InHistoryMediaItemMenu(
|
||||||
val menuState = LocalMenuState.current
|
val menuState = LocalMenuState.current
|
||||||
val binder = LocalPlayerServiceBinder.current
|
val binder = LocalPlayerServiceBinder.current
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
var isDeletingFromDatabase by remember {
|
var isDeletingFromDatabase by remember {
|
||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
@ -77,8 +71,9 @@ fun InHistoryMediaItemMenu(
|
||||||
},
|
},
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
(onDismiss ?: menuState::hide).invoke()
|
(onDismiss ?: menuState::hide).invoke()
|
||||||
|
query {
|
||||||
|
// Not sure we can to this here
|
||||||
binder?.cache?.removeResource(song.song.id)
|
binder?.cache?.removeResource(song.song.id)
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
|
||||||
Database.delete(song.song)
|
Database.delete(song.song)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,14 +99,11 @@ fun InPlaylistMediaItemMenu(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onDismiss: (() -> Unit)? = null
|
onDismiss: (() -> Unit)? = null
|
||||||
) {
|
) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
NonQueuedMediaItemMenu(
|
NonQueuedMediaItemMenu(
|
||||||
mediaItem = song.asMediaItem,
|
mediaItem = song.asMediaItem,
|
||||||
onDismiss = onDismiss,
|
onDismiss = onDismiss,
|
||||||
onRemoveFromPlaylist = {
|
onRemoveFromPlaylist = {
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
transaction {
|
||||||
Database.internal.runInTransaction {
|
|
||||||
Database.delete(
|
Database.delete(
|
||||||
SongInPlaylist(
|
SongInPlaylist(
|
||||||
songId = song.song.id,
|
songId = song.song.id,
|
||||||
|
@ -124,7 +116,6 @@ fun InPlaylistMediaItemMenu(
|
||||||
fromPosition = positionInPlaylist + 1
|
fromPosition = positionInPlaylist + 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
},
|
},
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
)
|
)
|
||||||
|
@ -211,7 +202,6 @@ fun BaseMediaItemMenu(
|
||||||
onGlobalRouteEmitted: (() -> Unit)? = null,
|
onGlobalRouteEmitted: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val albumRoute = rememberPlaylistOrAlbumRoute()
|
val albumRoute = rememberPlaylistOrAlbumRoute()
|
||||||
val artistRoute = rememberArtistRoute()
|
val artistRoute = rememberArtistRoute()
|
||||||
|
@ -224,7 +214,7 @@ fun BaseMediaItemMenu(
|
||||||
onPlaySingle = onPlaySingle,
|
onPlaySingle = onPlaySingle,
|
||||||
onEnqueue = onEnqueue,
|
onEnqueue = onEnqueue,
|
||||||
onAddToPlaylist = { playlist, position ->
|
onAddToPlaylist = { playlist, position ->
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
transaction {
|
||||||
val playlistId = Database.playlist(playlist.id)?.id ?: Database.insert(playlist)
|
val playlistId = Database.playlist(playlist.id)?.id ?: Database.insert(playlist)
|
||||||
|
|
||||||
Database.insert(mediaItem)
|
Database.insert(mediaItem)
|
||||||
|
@ -498,6 +488,7 @@ fun MediaItemMenu(
|
||||||
icon = R.drawable.trash,
|
icon = R.drawable.trash,
|
||||||
text = "Delete",
|
text = "Delete",
|
||||||
onClick = {
|
onClick = {
|
||||||
|
onDismiss()
|
||||||
onDeleteFromDatabase()
|
onDeleteFromDatabase()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package it.vfsfitvnm.vimusic.ui.screens
|
package it.vfsfitvnm.vimusic.ui.screens
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
|
||||||
import androidx.compose.animation.*
|
import androidx.compose.animation.*
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
|
@ -39,6 +38,7 @@ import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
||||||
import it.vfsfitvnm.vimusic.models.Playlist
|
import it.vfsfitvnm.vimusic.models.Playlist
|
||||||
import it.vfsfitvnm.vimusic.models.SearchQuery
|
import it.vfsfitvnm.vimusic.models.SearchQuery
|
||||||
import it.vfsfitvnm.vimusic.models.SongWithInfo
|
import it.vfsfitvnm.vimusic.models.SongWithInfo
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.InFavoritesMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.InFavoritesMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.InHistoryMediaItemMenu
|
||||||
|
@ -50,7 +50,6 @@ import it.vfsfitvnm.vimusic.ui.views.PlaylistPreviewItem
|
||||||
import it.vfsfitvnm.vimusic.ui.views.SongItem
|
import it.vfsfitvnm.vimusic.ui.views.SongItem
|
||||||
import it.vfsfitvnm.vimusic.utils.*
|
import it.vfsfitvnm.vimusic.utils.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
@ExperimentalFoundationApi
|
@ExperimentalFoundationApi
|
||||||
|
@ -60,8 +59,6 @@ fun HomeScreen() {
|
||||||
val colorPalette = LocalColorPalette.current
|
val colorPalette = LocalColorPalette.current
|
||||||
val typography = LocalTypography.current
|
val typography = LocalTypography.current
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val lazyListState = rememberLazyListState()
|
val lazyListState = rememberLazyListState()
|
||||||
|
|
||||||
val intentUriRoute = rememberIntentUriRoute()
|
val intentUriRoute = rememberIntentUriRoute()
|
||||||
|
@ -86,8 +83,6 @@ fun HomeScreen() {
|
||||||
}
|
}
|
||||||
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
|
}.collectAsState(initial = emptyList(), context = Dispatchers.IO)
|
||||||
|
|
||||||
Log.d("HomeScreen", "songCollection: ${songCollection.size}")
|
|
||||||
|
|
||||||
RouteHandler(
|
RouteHandler(
|
||||||
listenToGlobalEmitter = true,
|
listenToGlobalEmitter = true,
|
||||||
transitionSpec = {
|
transitionSpec = {
|
||||||
|
@ -122,7 +117,7 @@ fun HomeScreen() {
|
||||||
onSearch = { query ->
|
onSearch = { query ->
|
||||||
searchResultRoute(query)
|
searchResultRoute(query)
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.insert(SearchQuery(query = query))
|
Database.insert(SearchQuery(query = query))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -173,7 +168,7 @@ fun HomeScreen() {
|
||||||
isCreatingANewPlaylist = false
|
isCreatingANewPlaylist = false
|
||||||
},
|
},
|
||||||
onDone = { text ->
|
onDone = { text ->
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.insert(Playlist(name = text))
|
Database.insert(Playlist(name = text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,9 +23,9 @@ import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.internal
|
|
||||||
import it.vfsfitvnm.vimusic.models.Playlist
|
import it.vfsfitvnm.vimusic.models.Playlist
|
||||||
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
||||||
|
import it.vfsfitvnm.vimusic.transaction
|
||||||
import it.vfsfitvnm.vimusic.ui.components.Error
|
import it.vfsfitvnm.vimusic.ui.components.Error
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.Message
|
import it.vfsfitvnm.vimusic.ui.components.Message
|
||||||
|
@ -40,7 +40,6 @@ import it.vfsfitvnm.youtubemusic.Outcome
|
||||||
import it.vfsfitvnm.youtubemusic.YouTube
|
import it.vfsfitvnm.youtubemusic.YouTube
|
||||||
import it.vfsfitvnm.youtubemusic.toNullable
|
import it.vfsfitvnm.youtubemusic.toNullable
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
|
@ -70,7 +69,6 @@ fun IntentUriScreen(uri: Uri) {
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
val binder = LocalPlayerServiceBinder.current
|
val binder = LocalPlayerServiceBinder.current
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
val shimmer = rememberShimmer(shimmerBounds = ShimmerBounds.Window)
|
val shimmer = rememberShimmer(shimmerBounds = ShimmerBounds.Window)
|
||||||
|
|
||||||
var items by remember(uri) {
|
var items by remember(uri) {
|
||||||
|
@ -102,8 +100,7 @@ fun IntentUriScreen(uri: Uri) {
|
||||||
onDone = { text ->
|
onDone = { text ->
|
||||||
menuState.hide()
|
menuState.hide()
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
transaction {
|
||||||
Database.internal.runInTransaction {
|
|
||||||
val playlistId = Database.insert(Playlist(name = text))
|
val playlistId = Database.insert(Playlist(name = text))
|
||||||
|
|
||||||
items.valueOrNull
|
items.valueOrNull
|
||||||
|
@ -121,7 +118,6 @@ fun IntentUriScreen(uri: Uri) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,7 @@ import androidx.compose.ui.unit.dp
|
||||||
import it.vfsfitvnm.reordering.rememberReorderingState
|
import it.vfsfitvnm.reordering.rememberReorderingState
|
||||||
import it.vfsfitvnm.reordering.verticalDragAfterLongPressToReorder
|
import it.vfsfitvnm.reordering.verticalDragAfterLongPressToReorder
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.*
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.models.PlaylistWithSongs
|
import it.vfsfitvnm.vimusic.models.PlaylistWithSongs
|
||||||
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
||||||
|
@ -39,7 +38,6 @@ import it.vfsfitvnm.vimusic.ui.views.SongItem
|
||||||
import it.vfsfitvnm.vimusic.utils.*
|
import it.vfsfitvnm.vimusic.utils.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
|
|
||||||
|
|
||||||
@ExperimentalAnimationApi
|
@ExperimentalAnimationApi
|
||||||
|
@ -84,8 +82,6 @@ fun LocalPlaylistScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val reorderingState = rememberReorderingState(playlistWithSongs.songs)
|
val reorderingState = rememberReorderingState(playlistWithSongs.songs)
|
||||||
|
|
||||||
var isRenaming by rememberSaveable {
|
var isRenaming by rememberSaveable {
|
||||||
|
@ -100,7 +96,7 @@ fun LocalPlaylistScreen(
|
||||||
isRenaming = false
|
isRenaming = false
|
||||||
},
|
},
|
||||||
onDone = { text ->
|
onDone = { text ->
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.update(playlistWithSongs.playlist.copy(name = text))
|
Database.update(playlistWithSongs.playlist.copy(name = text))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +114,7 @@ fun LocalPlaylistScreen(
|
||||||
isDeleting = false
|
isDeleting = false
|
||||||
},
|
},
|
||||||
onConfirm = {
|
onConfirm = {
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.delete(playlistWithSongs.playlist)
|
Database.delete(playlistWithSongs.playlist)
|
||||||
}
|
}
|
||||||
pop()
|
pop()
|
||||||
|
@ -290,7 +286,7 @@ fun LocalPlaylistScreen(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onDragEnd = { reachedIndex ->
|
onDragEnd = { reachedIndex ->
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
transaction {
|
||||||
if (index > reachedIndex) {
|
if (index > reachedIndex) {
|
||||||
Database.incrementSongPositions(
|
Database.incrementSongPositions(
|
||||||
playlistId = playlistWithSongs.playlist.id,
|
playlistId = playlistWithSongs.playlist.id,
|
||||||
|
|
|
@ -31,9 +31,9 @@ import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
||||||
import it.vfsfitvnm.vimusic.internal
|
|
||||||
import it.vfsfitvnm.vimusic.models.Playlist
|
import it.vfsfitvnm.vimusic.models.Playlist
|
||||||
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
import it.vfsfitvnm.vimusic.models.SongInPlaylist
|
||||||
|
import it.vfsfitvnm.vimusic.transaction
|
||||||
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
import it.vfsfitvnm.vimusic.ui.components.LocalMenuState
|
||||||
import it.vfsfitvnm.vimusic.ui.components.OutcomeItem
|
import it.vfsfitvnm.vimusic.ui.components.OutcomeItem
|
||||||
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
||||||
|
@ -45,7 +45,6 @@ import it.vfsfitvnm.vimusic.utils.*
|
||||||
import it.vfsfitvnm.youtubemusic.Outcome
|
import it.vfsfitvnm.youtubemusic.Outcome
|
||||||
import it.vfsfitvnm.youtubemusic.YouTube
|
import it.vfsfitvnm.youtubemusic.YouTube
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
|
@ -164,8 +163,7 @@ fun PlaylistOrAlbumScreen(
|
||||||
menuState.hide()
|
menuState.hide()
|
||||||
|
|
||||||
playlistOrAlbum.valueOrNull?.let { album ->
|
playlistOrAlbum.valueOrNull?.let { album ->
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
transaction {
|
||||||
Database.internal.runInTransaction {
|
|
||||||
val playlistId =
|
val playlistId =
|
||||||
Database.insert(Playlist(name = album.title ?: "Unknown"))
|
Database.insert(Playlist(name = album.title ?: "Unknown"))
|
||||||
|
|
||||||
|
@ -187,7 +185,6 @@ fun PlaylistOrAlbumScreen(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MenuEntry(
|
MenuEntry(
|
||||||
|
|
|
@ -33,6 +33,7 @@ import androidx.core.net.toUri
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.ui.components.OutcomeItem
|
import it.vfsfitvnm.vimusic.ui.components.OutcomeItem
|
||||||
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
|
import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
|
||||||
|
@ -44,7 +45,6 @@ import it.vfsfitvnm.youtubemusic.YouTube
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,8 +107,6 @@ fun SearchScreen(
|
||||||
val colorPalette = LocalColorPalette.current
|
val colorPalette = LocalColorPalette.current
|
||||||
val typography = LocalTypography.current
|
val typography = LocalTypography.current
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val isOpenableUrl = remember(textFieldValue.text) {
|
val isOpenableUrl = remember(textFieldValue.text) {
|
||||||
Regex("""https://(music|www|m)\.youtube.com/(watch|playlist).*""").matches(textFieldValue.text)
|
Regex("""https://(music|www|m)\.youtube.com/(watch|playlist).*""").matches(textFieldValue.text)
|
||||||
}
|
}
|
||||||
|
@ -280,7 +278,7 @@ fun SearchScreen(
|
||||||
colorFilter = ColorFilter.tint(colorPalette.darkGray),
|
colorFilter = ColorFilter.tint(colorPalette.darkGray),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable {
|
.clickable {
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.delete(searchQuery)
|
Database.delete(searchQuery)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,11 @@ import androidx.compose.foundation.*
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.text.BasicText
|
import androidx.compose.foundation.text.BasicText
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
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.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
|
@ -18,10 +21,8 @@ import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.*
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.checkpoint
|
|
||||||
import it.vfsfitvnm.vimusic.internal
|
|
||||||
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
import it.vfsfitvnm.vimusic.ui.components.TopAppBar
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
|
import it.vfsfitvnm.vimusic.ui.components.themed.ConfirmationDialog
|
||||||
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
|
import it.vfsfitvnm.vimusic.ui.screens.ArtistScreen
|
||||||
|
@ -32,8 +33,6 @@ import it.vfsfitvnm.vimusic.ui.styling.LocalColorPalette
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
|
import it.vfsfitvnm.vimusic.ui.styling.LocalTypography
|
||||||
import it.vfsfitvnm.vimusic.utils.secondary
|
import it.vfsfitvnm.vimusic.utils.secondary
|
||||||
import it.vfsfitvnm.vimusic.utils.semiBold
|
import it.vfsfitvnm.vimusic.utils.semiBold
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.io.FileInputStream
|
import java.io.FileInputStream
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
@ -67,17 +66,15 @@ fun BackupAndRestoreScreen() {
|
||||||
val typography = LocalTypography.current
|
val typography = LocalTypography.current
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
|
||||||
|
|
||||||
val backupLauncher =
|
val backupLauncher =
|
||||||
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/vnd.sqlite3")) { uri ->
|
rememberLauncherForActivityResult(ActivityResultContracts.CreateDocument("application/vnd.sqlite3")) { uri ->
|
||||||
if (uri == null) return@rememberLauncherForActivityResult
|
if (uri == null) return@rememberLauncherForActivityResult
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.checkpoint()
|
Database.internal.checkpoint()
|
||||||
context.applicationContext.contentResolver.openOutputStream(uri)
|
context.applicationContext.contentResolver.openOutputStream(uri)
|
||||||
?.use { outputStream ->
|
?.use { outputStream ->
|
||||||
FileInputStream(Database.internal.getOpenHelper().writableDatabase.path).use { inputStream ->
|
FileInputStream(Database.internal.path).use { inputStream ->
|
||||||
inputStream.copyTo(outputStream)
|
inputStream.copyTo(outputStream)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,10 +85,10 @@ fun BackupAndRestoreScreen() {
|
||||||
rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
rememberLauncherForActivityResult(ActivityResultContracts.OpenDocument()) { uri ->
|
||||||
if (uri == null) return@rememberLauncherForActivityResult
|
if (uri == null) return@rememberLauncherForActivityResult
|
||||||
|
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
Database.internal.close()
|
Database.internal.close()
|
||||||
|
|
||||||
FileOutputStream(Database.internal.getOpenHelper().writableDatabase.path).use { outputStream ->
|
FileOutputStream(Database.internal.path).use { outputStream ->
|
||||||
context.applicationContext.contentResolver.openInputStream(uri)
|
context.applicationContext.contentResolver.openInputStream(uri)
|
||||||
?.use { inputStream ->
|
?.use { inputStream ->
|
||||||
inputStream.copyTo(outputStream)
|
inputStream.copyTo(outputStream)
|
||||||
|
|
|
@ -20,7 +20,6 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.scale
|
import androidx.compose.ui.draw.scale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.media3.common.Player
|
|
||||||
import it.vfsfitvnm.route.Route
|
import it.vfsfitvnm.route.Route
|
||||||
import it.vfsfitvnm.route.RouteHandler
|
import it.vfsfitvnm.route.RouteHandler
|
||||||
import it.vfsfitvnm.route.empty
|
import it.vfsfitvnm.route.empty
|
||||||
|
@ -28,6 +27,7 @@ import it.vfsfitvnm.route.rememberRoute
|
||||||
import it.vfsfitvnm.vimusic.Database
|
import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.models.Song
|
import it.vfsfitvnm.vimusic.models.Song
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.ui.components.BottomSheet
|
import it.vfsfitvnm.vimusic.ui.components.BottomSheet
|
||||||
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
|
import it.vfsfitvnm.vimusic.ui.components.BottomSheetState
|
||||||
import it.vfsfitvnm.vimusic.ui.screens.rememberLyricsRoute
|
import it.vfsfitvnm.vimusic.ui.screens.rememberLyricsRoute
|
||||||
|
@ -55,7 +55,6 @@ fun PlayerBottomSheet(
|
||||||
val colorPalette = LocalColorPalette.current
|
val colorPalette = LocalColorPalette.current
|
||||||
val typography = LocalTypography.current
|
val typography = LocalTypography.current
|
||||||
|
|
||||||
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
val lyricsRoute = rememberLyricsRoute()
|
val lyricsRoute = rememberLyricsRoute()
|
||||||
|
@ -209,7 +208,7 @@ fun PlayerBottomSheet(
|
||||||
}.map { lyrics ->
|
}.map { lyrics ->
|
||||||
lyrics ?: ""
|
lyrics ?: ""
|
||||||
}.map { lyrics ->
|
}.map { lyrics ->
|
||||||
withContext(Dispatchers.IO) {
|
query {
|
||||||
(song ?: mediaItem.let(Database::insert)).let {
|
(song ?: mediaItem.let(Database::insert)).let {
|
||||||
Database.update(it.copy(lyrics = lyrics))
|
Database.update(it.copy(lyrics = lyrics))
|
||||||
}
|
}
|
||||||
|
@ -230,7 +229,7 @@ fun PlayerBottomSheet(
|
||||||
},
|
},
|
||||||
onLyricsUpdate = { lyrics ->
|
onLyricsUpdate = { lyrics ->
|
||||||
val mediaItem = player?.currentMediaItem
|
val mediaItem = player?.currentMediaItem
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
(song ?: mediaItem?.let(Database::insert))?.let {
|
(song ?: mediaItem?.let(Database::insert))?.let {
|
||||||
Database.update(it.copy(lyrics = lyrics))
|
Database.update(it.copy(lyrics = lyrics))
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import it.vfsfitvnm.vimusic.Database
|
||||||
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
import it.vfsfitvnm.vimusic.LocalPlayerServiceBinder
|
||||||
import it.vfsfitvnm.vimusic.R
|
import it.vfsfitvnm.vimusic.R
|
||||||
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
import it.vfsfitvnm.vimusic.enums.ThumbnailRoundness
|
||||||
|
import it.vfsfitvnm.vimusic.query
|
||||||
import it.vfsfitvnm.vimusic.ui.components.*
|
import it.vfsfitvnm.vimusic.ui.components.*
|
||||||
import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu
|
import it.vfsfitvnm.vimusic.ui.components.themed.QueuedMediaItemMenu
|
||||||
import it.vfsfitvnm.vimusic.ui.styling.BlackColorPalette
|
import it.vfsfitvnm.vimusic.ui.styling.BlackColorPalette
|
||||||
|
@ -537,7 +538,7 @@ fun PlayerView(
|
||||||
),
|
),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable {
|
.clickable {
|
||||||
coroutineScope.launch(Dispatchers.IO) {
|
query {
|
||||||
(song ?: playerState.mediaItem?.let(Database::insert))?.let {
|
(song ?: playerState.mediaItem?.let(Database::insert))?.let {
|
||||||
Database.update(it.toggleLike())
|
Database.update(it.toggleLike())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue