Use database executors instead of compose coroutines to launch database operations

This commit is contained in:
vfsfitvnm 2022-06-27 22:07:07 +02:00
parent 85f89ec799
commit 2cbb5a4ba4
11 changed files with 88 additions and 107 deletions

View file

@ -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()) {

View file

@ -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)
} }
} }

View file

@ -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()
} }
) )

View file

@ -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))
} }
} }

View file

@ -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) {
} }
} }
} }
}
) )
} }

View file

@ -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,

View file

@ -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(

View file

@ -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)
} }
} }

View file

@ -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)

View file

@ -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))
} }

View file

@ -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())
} }