Skip to content

Commit

Permalink
Merge pull request #63 from mattcarter11/singelton-sync-and-chip-loader
Browse files Browse the repository at this point in the history
Fixes #53 
Fixes #13 (I think)
  • Loading branch information
mikooomich authored Nov 1, 2024
2 parents 627f99d + be50fd6 commit 24269a5
Show file tree
Hide file tree
Showing 37 changed files with 3,145 additions and 1,312 deletions.
1,259 changes: 1,259 additions & 0 deletions app/schemas/com.dd3boh.outertune.db.InternalDatabase/16.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ val SongFilterKey = stringPreferencesKey("songFilter")
val ArtistFilterKey = stringPreferencesKey("artistFilter")
val ArtistViewTypeKey = stringPreferencesKey("artistViewType")
val AlbumFilterKey = stringPreferencesKey("albumFilter")
val PlaylistFilterKey = stringPreferencesKey("playlistFilter")
val AlbumViewTypeKey = stringPreferencesKey("albumViewType")
val PlaylistViewTypeKey = stringPreferencesKey("playlistViewType")
val LibraryFilterKey = stringPreferencesKey("libraryFilter")
Expand Down Expand Up @@ -179,11 +180,15 @@ enum class SongFilter {
}

enum class ArtistFilter {
LIBRARY, LIKED
LIBRARY, LIKED, DOWNLOADED
}

enum class AlbumFilter {
LIBRARY, LIKED
LIBRARY, LIKED, DOWNLOADED
}

enum class PlaylistFilter {
LIBRARY, DOWNLOADED
}

enum class LibraryFilter {
Expand Down
880 changes: 7 additions & 873 deletions app/src/main/java/com/dd3boh/outertune/db/DatabaseDao.kt

Large diffs are not rendered by default.

10 changes: 9 additions & 1 deletion app/src/main/java/com/dd3boh/outertune/db/MusicDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class MusicDatabase(
SortedSongAlbumMap::class,
PlaylistSongMapPreview::class
],
version = 15,
version = 16,
exportSchema = true,
autoMigrations = [
AutoMigration(from = 2, to = 3),
Expand All @@ -106,6 +106,7 @@ class MusicDatabase(
AutoMigration(from = 11, to = 12, spec = Migration11To12::class),
AutoMigration(from = 12, to = 13, spec = Migration12To13::class), // Migration from InnerTune
AutoMigration(from = 13, to = 14), // Initial queue as database
AutoMigration(from = 15, to = 16), // Add dateDownload to songs
]
)
@TypeConverters(Converters::class)
Expand All @@ -120,6 +121,7 @@ abstract class InternalDatabase : RoomDatabase() {
delegate = Room.databaseBuilder(context, InternalDatabase::class.java, DB_NAME)
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_14_15)
.addMigrations(MIGRATION_15_16)
.build()
)
}
Expand Down Expand Up @@ -313,6 +315,12 @@ val MIGRATION_14_15 = object : Migration(14, 15) {
}
}

val MIGRATION_15_16 = object : Migration(15, 16) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("ALTER TABLE song ADD COLUMN dateDownload Integer NULL DEFAULT NULL")
}
}

@DeleteColumn.Entries(
DeleteColumn(tableName = "song", columnName = "isTrash"),
DeleteColumn(tableName = "playlist", columnName = "author"),
Expand Down
185 changes: 185 additions & 0 deletions app/src/main/java/com/dd3boh/outertune/db/daos/AlbumsDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
package com.dd3boh.outertune.db.daos

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction
import androidx.room.Update
import androidx.room.Upsert
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery
import com.dd3boh.outertune.constants.AlbumFilter
import com.dd3boh.outertune.constants.AlbumSortType
import com.dd3boh.outertune.db.entities.Album
import com.dd3boh.outertune.db.entities.AlbumArtistMap
import com.dd3boh.outertune.db.entities.AlbumEntity
import com.dd3boh.outertune.db.entities.AlbumWithSongs
import com.dd3boh.outertune.db.entities.ArtistEntity
import com.dd3boh.outertune.db.entities.Song
import com.dd3boh.outertune.db.entities.SongAlbumMap
import com.dd3boh.outertune.extensions.reversed
import com.zionhuang.innertube.models.AlbumItem
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map

/*
* Logic related to albums entities and their mapping
*/

@Dao
interface AlbumsDao : ArtistsDao {

// region Gets
@Query("""
SELECT album.*, count(song.dateDownload) downloadCount
FROM album
LEFT JOIN song ON song.albumId = album.id
WHERE album.id = :id
GROUP BY album.id
""")
fun album(id: String): Flow<Album?>

@Query("""
SELECT album.*, count(song.dateDownload) downloadCount
FROM album
LEFT JOIN song ON song.albumId = album.id
WHERE album.title LIKE '%' || :query || '%' AND song.inLibrary IS NOT NULL
GROUP BY album.id
LIMIT :previewSize
""")
fun searchAlbums(query: String, previewSize: Int = Int.MAX_VALUE): Flow<List<Album>>

@Query("""
SELECT album.*, count(song.dateDownload) downloadCount
FROM album
LEFT JOIN song ON song.albumId = album.id
WHERE album.id = :albumId
GROUP BY album.id
""")
fun albumWithSongs(albumId: String): Flow<AlbumWithSongs?>

@Query("SELECT song.* FROM song JOIN song_album_map ON song.id = song_album_map.songId WHERE song_album_map.albumId = :albumId")
fun albumSongs(albumId: String): Flow<List<Song>>

@Query("""
SELECT album.*, count(song.dateDownload) downloadCount
FROM album
JOIN song ON album.id = song.albumId
JOIN event ON song.id = event.songId
WHERE event.timestamp > :fromTimeStamp
GROUP BY album.id
ORDER BY SUM(event.playTime) DESC
LIMIT :limit;
""")
fun mostPlayedAlbums(fromTimeStamp: Long, limit: Int = 6): Flow<List<Album>>

@RawQuery(observedEntities = [AlbumEntity::class])
fun _getAlbum(query: SupportSQLiteQuery): Flow<List<Album>>

fun albums(filter: AlbumFilter, sortType: AlbumSortType, descending: Boolean): Flow<List<Album>> {
val orderBy = when (sortType) {
AlbumSortType.CREATE_DATE -> "album.rowId ASC"
AlbumSortType.NAME -> "album.title COLLATE NOCASE ASC"
AlbumSortType.ARTIST -> """ORDER BY (
SELECT LOWER(GROUP_CONCAT(name, ''))
FROM artist
WHERE id IN (SELECT artistId FROM album_artist_map WHERE albumId = album.id)
ORDER BY name
) COLLATE NOCASE ASC"""
AlbumSortType.YEAR -> "album.year ASC"
AlbumSortType.SONG_COUNT -> "album.songCount ASC"
AlbumSortType.LENGTH -> "album.duration ASC"
AlbumSortType.PLAY_TIME -> "SUM(song.totalPlayTime) ASC"
}

val where = when (filter) {
AlbumFilter.DOWNLOADED -> "song.dateDownload IS NOT NULL"
AlbumFilter.LIBRARY -> "song.inLibrary IS NOT NULL"
AlbumFilter.LIKED -> "album.bookmarkedAt IS NOT NULL"
}

val query = SimpleSQLiteQuery("""
SELECT album.*, count(song.dateDownload) downloadCount
FROM album
LEFT JOIN song ON song.albumId = album.id
WHERE $where
GROUP BY album.id
ORDER BY $orderBy
""")

return _getAlbum(query).map { it.reversed(descending) }
}

fun albumsInLibraryAsc() = albums(AlbumFilter.LIBRARY, AlbumSortType.CREATE_DATE, false)
fun albumsLikedAsc() = albums(AlbumFilter.LIKED, AlbumSortType.CREATE_DATE, false)
// endregion

// region Inserts
@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(album: AlbumEntity): Long

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(map: SongAlbumMap)

@Insert(onConflict = OnConflictStrategy.IGNORE)
fun insert(map: AlbumArtistMap)

@Transaction
fun insert(albumItem: AlbumItem) {
if (insert(AlbumEntity(
id = albumItem.browseId,
playlistId = albumItem.playlistId,
title = albumItem.title,
year = albumItem.year,
thumbnailUrl = albumItem.thumbnail,
songCount = 0,
duration = 0
)) == -1L
) return
albumItem.artists
?.map { artist ->
ArtistEntity(
id = artist.id ?: artistByName(artist.name)?.id ?: ArtistEntity.generateArtistId(),
name = artist.name
)
}
?.onEach(::insert)
?.mapIndexed { index, artist ->
AlbumArtistMap(
albumId = albumItem.browseId,
artistId = artist.id,
order = index
)
}
?.forEach(::insert)
}
// endregion

// region Updates
@Update
fun update(album: AlbumEntity)

@Upsert
fun upsert(map: SongAlbumMap)

@Transaction
@Query("UPDATE album_artist_map SET artistId = :newId WHERE artistId = :oldId")
fun updateAlbumArtistMap(oldId: String, newId: String)

@Transaction
@Query("DELETE FROM song_artist_map WHERE songId = :songID")
fun unlinkSongArtists(songID: String)
// endregion

// region Deletes
@Delete
fun delete(album: AlbumEntity)

@Transaction
@Query("DELETE FROM album WHERE isLocal = 1")
fun nukeLocalAlbums()
// endregion
}
Loading

0 comments on commit 24269a5

Please sign in to comment.