Skip to content

Commit

Permalink
Final changes for YouTube synchronization
Browse files Browse the repository at this point in the history
  • Loading branch information
MaloyBegonia committed Feb 15, 2025
1 parent 21a9053 commit afda980
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 99 deletions.
63 changes: 6 additions & 57 deletions app/schemas/com.maloy.muzza.db.InternalDatabase/13.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 13,
"identityHash": "3eab7e4a1f6aceefcce0dc809aa2ec17",
"identityHash": "cf1917f48fb44c8b82e3aa4a03223b2d",
"entities": [
{
"tableName": "song",
Expand Down Expand Up @@ -90,7 +90,7 @@
},
{
"tableName": "artist",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnailUrl` TEXT, `channelId` TEXT, `lastUpdateTime` INTEGER NOT NULL, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `thumbnailUrl` TEXT, `lastUpdateTime` INTEGER NOT NULL, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
Expand All @@ -110,12 +110,6 @@
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "channelId",
"columnName": "channelId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "lastUpdateTime",
"columnName": "lastUpdateTime",
Expand All @@ -140,20 +134,14 @@
},
{
"tableName": "album",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `playlistId` TEXT, `title` TEXT NOT NULL, `year` INTEGER, `thumbnailUrl` TEXT, `themeColor` INTEGER, `songCount` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `lastUpdateTime` INTEGER NOT NULL, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `title` TEXT NOT NULL, `year` INTEGER, `thumbnailUrl` TEXT, `themeColor` INTEGER, `songCount` INTEGER NOT NULL, `duration` INTEGER NOT NULL, `lastUpdateTime` INTEGER NOT NULL, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "playlistId",
"columnName": "playlistId",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "title",
"columnName": "title",
Expand Down Expand Up @@ -214,7 +202,7 @@
},
{
"tableName": "playlist",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `browseId` TEXT, `isEditable` INTEGER NOT NULL DEFAULT true, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `name` TEXT NOT NULL, `browseId` TEXT, `bookmarkedAt` INTEGER, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
Expand All @@ -234,13 +222,6 @@
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "isEditable",
"columnName": "isEditable",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "true"
},
{
"fieldPath": "bookmarkedAt",
"columnName": "bookmarkedAt",
Expand Down Expand Up @@ -484,7 +465,7 @@
},
{
"tableName": "playlist_song_map",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, `setVideoId` TEXT, FOREIGN KEY(`playlistId`) REFERENCES `playlist`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`songId`) REFERENCES `song`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `playlistId` TEXT NOT NULL, `songId` TEXT NOT NULL, `position` INTEGER NOT NULL, FOREIGN KEY(`playlistId`) REFERENCES `playlist`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`songId`) REFERENCES `song`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
"fields": [
{
"fieldPath": "id",
Expand All @@ -509,12 +490,6 @@
"columnName": "position",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "setVideoId",
"columnName": "setVideoId",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
Expand Down Expand Up @@ -825,32 +800,6 @@
]
}
]
},
{
"tableName": "set_video_id",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`videoId` TEXT NOT NULL, `setVideoId` TEXT, PRIMARY KEY(`videoId`))",
"fields": [
{
"fieldPath": "videoId",
"columnName": "videoId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "setVideoId",
"columnName": "setVideoId",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"autoGenerate": false,
"columnNames": [
"videoId"
]
},
"indices": [],
"foreignKeys": []
}
],
"views": [
Expand All @@ -869,7 +818,7 @@
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3eab7e4a1f6aceefcce0dc809aa2ec17')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'cf1917f48fb44c8b82e3aa4a03223b2d')"
]
}
}
3 changes: 1 addition & 2 deletions app/src/main/java/com/maloy/muzza/db/MusicDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ class MusicDatabase(
FormatEntity::class,
LyricsEntity::class,
Event::class,
RelatedSongMap::class,
SetVideoIdEntity::class
RelatedSongMap::class
],
views = [
SortedSongArtistMap::class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import androidx.compose.runtime.Immutable
import androidx.room.Entity
import androidx.room.PrimaryKey
import org.apache.commons.lang3.RandomStringUtils
import java.time.LocalDateTime

@Suppress("DEPRECATION")
@Immutable
Expand All @@ -12,6 +13,7 @@ data class PlaylistEntity(
@PrimaryKey val id: String = generatePlaylistId(),
val name: String,
val browseId: String? = null,
val bookmarkedAt: LocalDateTime? = null,
) {
companion object {
const val LIKED_PLAYLIST_ID = "LP_LIKED"
Expand Down
23 changes: 14 additions & 9 deletions app/src/main/java/com/maloy/muzza/ui/menu/AddToPlaylistDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -44,10 +43,11 @@ fun AddToPlaylistDialog(
) {
val database = LocalDatabase.current
val coroutineScope = rememberCoroutineScope()
val playlists by remember {

var playlists by remember {
mutableStateOf(emptyList<Playlist>())
}
var showAddPlaylistDialog by rememberSaveable {
var showCreatePlaylistDialog by rememberSaveable {
mutableStateOf(false)
}

Expand All @@ -64,6 +64,12 @@ fun AddToPlaylistDialog(
mutableStateOf(emptyList<String>())
}

LaunchedEffect(Unit) {
database.playlistsByCreateDateAsc().collect {
playlists = it.asReversed()
}
}

if (isVisible) {
ListDialog(
onDismiss = onDismiss
Expand All @@ -73,14 +79,14 @@ fun AddToPlaylistDialog(
title = stringResource(R.string.create_playlist),
thumbnailContent = {
Image(
imageVector = Icons.Rounded.Add,
painter = painterResource(R.drawable.add),
contentDescription = null,
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
modifier = Modifier.size(ListThumbnailSize)
)
},
modifier = Modifier.clickable {
showAddPlaylistDialog = true
showCreatePlaylistDialog = true
}
)
}
Expand Down Expand Up @@ -108,11 +114,11 @@ fun AddToPlaylistDialog(
}
}

if (showAddPlaylistDialog) {
if (showCreatePlaylistDialog) {
TextFieldDialog(
icon = { Icon(painter = painterResource(R.drawable.add), contentDescription = null) },
title = { Text(text = stringResource(R.string.create_playlist)) },
onDismiss = { showAddPlaylistDialog = false },
onDismiss = { showCreatePlaylistDialog = false },
onDone = { playlistName ->
database.query {
insert(
Expand All @@ -125,7 +131,6 @@ fun AddToPlaylistDialog(
)
}

// duplicate songs warning
if (showDuplicateDialog) {
DefaultDialog(
title = { Text(stringResource(R.string.duplicates)) },
Expand Down
13 changes: 1 addition & 12 deletions app/src/main/java/com/maloy/muzza/ui/menu/AlbumMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ fun AlbumMenu(
mutableStateOf(emptyList<Song>())
}

val coroutineScope = rememberCoroutineScope()

LaunchedEffect(Unit) {
database.albumSongs(album.id).collect {
songs = it
Expand Down Expand Up @@ -140,16 +138,7 @@ fun AlbumMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { playlistId ->
album.album.playlistId?.let { addPlaylistId ->
YouTube.addPlaylistToPlaylist(playlistId, addPlaylistId)
}
}
}
songs.map { it.id }
},
onGetSong = { songs.map { it.id } },
onDismiss = {
showChoosePlaylistDialog = false
}
Expand Down
13 changes: 1 addition & 12 deletions app/src/main/java/com/maloy/muzza/ui/menu/YouTubeAlbumMenu.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
Expand Down Expand Up @@ -57,8 +56,6 @@ import com.maloy.muzza.ui.component.GridMenuItem
import com.maloy.muzza.ui.component.ListDialog
import com.maloy.muzza.ui.component.YouTubeListItem
import com.maloy.muzza.utils.reportException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Composable
fun YouTubeAlbumMenu(
Expand All @@ -71,7 +68,6 @@ fun YouTubeAlbumMenu(
val downloadUtil = LocalDownloadUtil.current
val playerConnection = LocalPlayerConnection.current ?: return
val album by database.albumWithSongs(albumItem.id).collectAsState(initial = null)
val coroutineScope = rememberCoroutineScope()

LaunchedEffect(Unit) {
database.album(albumItem.id).collect { album ->
Expand Down Expand Up @@ -114,14 +110,7 @@ fun YouTubeAlbumMenu(

AddToPlaylistDialog(
isVisible = showChoosePlaylistDialog,
onGetSong = { playlist ->
coroutineScope.launch(Dispatchers.IO) {
playlist.playlist.browseId?.let { playlistId ->
album?.album?.playlistId?.let { addPlaylistId ->
YouTube.addPlaylistToPlaylist(playlistId, addPlaylistId)
}
}
}
onGetSong = {
album?.songs?.map { it.id }.orEmpty()
},
onDismiss = { showChoosePlaylistDialog = false }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import com.maloy.muzza.db.MusicDatabase
import com.maloy.muzza.extensions.reversed
import com.maloy.muzza.extensions.toEnum
import com.maloy.muzza.playback.DownloadUtil
import com.maloy.muzza.utils.SyncUtils
import com.maloy.muzza.utils.dataStore
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
Expand All @@ -25,7 +24,6 @@ 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 javax.inject.Inject

@OptIn(ExperimentalCoroutinesApi::class)
Expand All @@ -35,7 +33,6 @@ class AutoPlaylistViewModel @Inject constructor(
database: MusicDatabase,
downloadUtil: DownloadUtil,
savedStateHandle: SavedStateHandle,
private val syncUtils: SyncUtils,
) : ViewModel() {
val playlist = savedStateHandle.get<String>("playlist")!!

Expand Down Expand Up @@ -77,8 +74,4 @@ class AutoPlaylistViewModel @Inject constructor(
else -> MutableStateFlow(emptyList())
}
}.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())

fun syncLikedSongs() {
viewModelScope.launch(Dispatchers.IO) { syncUtils.syncLikedSongs() }
}
}

0 comments on commit afda980

Please sign in to comment.