+
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
726 changes: 726 additions & 0 deletions app/schemas/me.vanpetegem.accentor.data.AccentorDatabase/12.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package me.vanpetegem.accentor.api.playlist

import com.github.kittinunf.fuel.httpGet
import me.vanpetegem.accentor.api.util.retry
import me.vanpetegem.accentor.data.authentication.AuthenticationData
import me.vanpetegem.accentor.data.playlists.ApiPlaylist
import me.vanpetegem.accentor.util.Result
import me.vanpetegem.accentor.util.responseObject

fun index(server: String, authenticationData: AuthenticationData): Sequence<Result<List<ApiPlaylist>>> {
var page = 1

fun doFetch(): Result<List<ApiPlaylist>>? {
return retry(5) {
"$server/api/playlists".httpGet(listOf(Pair("page", page)))
.set("Accept", "application/json")
.set("X-Secret", authenticationData.secret)
.set("X-Device-Id", authenticationData.deviceId)
.responseObject<List<ApiPlaylist>>().third
.fold(
{ a: List<ApiPlaylist> ->
if (a.isEmpty()) {
null
} else {
page++
Result.Success(a)
}
},
{ e: Throwable -> Result.Error(Exception("Error getting playlists", e)) },
)
}
}

return generateSequence { doFetch() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import me.vanpetegem.accentor.data.artists.ArtistDao
import me.vanpetegem.accentor.data.artists.DbArtist
import me.vanpetegem.accentor.data.codecconversions.CodecConversionDao
import me.vanpetegem.accentor.data.codecconversions.DbCodecConversion
import me.vanpetegem.accentor.data.playlists.DbPlaylist
import me.vanpetegem.accentor.data.playlists.DbPlaylistItem
import me.vanpetegem.accentor.data.playlists.PlaylistDao
import me.vanpetegem.accentor.data.plays.DbPlay
import me.vanpetegem.accentor.data.plays.PlayDao
import me.vanpetegem.accentor.data.plays.UnreportedPlay
Expand All @@ -44,17 +47,20 @@ import me.vanpetegem.accentor.util.RoomTypeConverters
DbArtist::class,
DbCodecConversion::class,
DbPlay::class,
DbPlaylist::class,
DbPlaylistItem::class,
DbTrack::class,
DbTrackArtist::class,
DbTrackGenre::class,
UnreportedPlay::class,
],
version = 11
version = 12
)
abstract class AccentorDatabase : RoomDatabase() {
abstract fun albumDao(): AlbumDao
abstract fun artistDao(): ArtistDao
abstract fun codecConversionDao(): CodecConversionDao
abstract fun playlistDao(): PlaylistDao
abstract fun playDao(): PlayDao
abstract fun trackDao(): TrackDao
abstract fun userDao(): UserDao
Expand Down Expand Up @@ -259,6 +265,42 @@ internal object DatabaseModule {
}
}
})
.addMigrations(object : Migration(11, 12) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS `playlists` (
`id` INTEGER NOT NULL,
`name` TEXT NOT NULL,
`description` TEXT,
`user_id` INTEGER NOT NULL,
`playlist_type` INTEGER NOT NULL,
`created_at` TEXT NOT NULL,
`updated_at` TEXT NOT NULL,
`access` INTEGER NOT NULL,
`fetched_at` TEXT NOT NULL,
PRIMARY KEY(`id`)
)
"""
)
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS `playlist_items` (
`playlist_id` INTEGER NOT NULL,
`item_id` INTEGER NOT NULL,
`order` INTEGER NOT NULL,
PRIMARY KEY(`playlist_id`, `item_id`)
)
"""
)
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
})
.build()
}

Expand All @@ -269,6 +311,8 @@ internal object DatabaseModule {
@Provides
fun provideCodecConversionDao(database: AccentorDatabase): CodecConversionDao = database.codecConversionDao()
@Provides
fun providePlaylistDao(database: AccentorDatabase): PlaylistDao = database.playlistDao()
@Provides
fun providePlayDao(database: AccentorDatabase): PlayDao = database.playDao()
@Provides
fun provideTrackDao(database: AccentorDatabase): TrackDao = database.trackDao()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ abstract class AlbumDao {
}
}

open fun getByIds(ids: List<Int>): List<Album> {
val albums = getDbAlbumsByIds(ids)
val albumsByIds = SparseArray<DbAlbum>()
albums.forEach { albumsByIds.put(it.id, it) }
val albumArtists = getAlbumArtistsByAlbumIdWhereAlbumIds(ids)
val albumLabels = getAlbumLabelsByAlbumIdWhereAlbumIds(ids)
return ids.map { Album.fromDb(albumsByIds.get(it), albumLabels.get(it, ArrayList()), albumArtists.get(it, ArrayList())) }
}

open fun findByIds(ids: List<Int>): LiveData<List<Album>> = switchMap(findDbAlbumsByIds(ids)) { albums ->
switchMap(albumArtistsByAlbumIdWhereAlbumIds(ids)) { albumArtists ->
map(albumLabelsByAlbumIdWhereAlbumIds(ids)) { albumLabels ->
Expand Down Expand Up @@ -88,6 +97,9 @@ abstract class AlbumDao {
@Query("SELECT * FROM albums WHERE id IN (:ids)")
protected abstract fun findDbAlbumsByIds(ids: List<Int>): LiveData<List<DbAlbum>>

@Query("SELECT * FROM albums WHERE id IN (:ids)")
protected abstract fun getDbAlbumsByIds(ids: List<Int>): List<DbAlbum>

@Query(
"""
SELECT * FROM albums WHERE release LIKE '%' || :day || '%'
Expand Down Expand Up @@ -124,7 +136,7 @@ abstract class AlbumDao {
}

protected open fun albumLabelsByAlbumIdWhereAlbumIds(ids: List<Int>): LiveData<SparseArray<MutableList<AlbumLabel>>> =
map(getAllAlbumLabelsWhereAlbumIds(ids)) {
map(findAllAlbumLabelsWhereAlbumIds(ids)) {
val map = SparseArray<MutableList<AlbumLabel>>()
for (al in it) {
val l = map.get(al.albumId, ArrayList())
Expand All @@ -134,6 +146,17 @@ abstract class AlbumDao {
return@map map
}

protected open fun getAlbumLabelsByAlbumIdWhereAlbumIds(ids: List<Int>): SparseArray<MutableList<AlbumLabel>> {
val albumLabels = getAllAlbumLabelsWhereAlbumIds(ids)
val map = SparseArray<MutableList<AlbumLabel>>()
for (al in albumLabels) {
val l = map.get(al.albumId, ArrayList())
l.add(AlbumLabel(al.labelId, al.catalogueNumber))
map.put(al.albumId, l)
}
return map
}

protected open fun albumArtistsByAlbumId(): LiveData<SparseArray<MutableList<AlbumArtist>>> =
map(getAllAlbumArtists()) {
val map = SparseArray<MutableList<AlbumArtist>>()
Expand All @@ -146,7 +169,7 @@ abstract class AlbumDao {
}

protected open fun albumArtistsByAlbumIdWhereAlbumIds(ids: List<Int>): LiveData<SparseArray<MutableList<AlbumArtist>>> =
map(getAllAlbumArtistsWhereAlbumIds(ids)) {
map(findAllAlbumArtistsWhereAlbumIds(ids)) {
val map = SparseArray<MutableList<AlbumArtist>>()
for (aa in it) {
val l = map.get(aa.albumId, ArrayList())
Expand All @@ -156,6 +179,17 @@ abstract class AlbumDao {
return@map map
}

protected open fun getAlbumArtistsByAlbumIdWhereAlbumIds(ids: List<Int>): SparseArray<MutableList<AlbumArtist>> {
val albumArtists = getAllAlbumArtistsWhereAlbumIds(ids)
val map = SparseArray<MutableList<AlbumArtist>>()
for (aa in albumArtists) {
val l = map.get(aa.albumId, ArrayList())
l.add(AlbumArtist(aa.artistId, aa.name, aa.normalizedName, aa.order, aa.separator))
map.put(aa.albumId, l)
}
return map
}

@Transaction
open fun upsertAll(albums: List<Album>) {
albums.forEach { album: Album ->
Expand Down Expand Up @@ -207,13 +241,19 @@ abstract class AlbumDao {
protected abstract fun getAllAlbumArtists(): LiveData<List<DbAlbumArtist>>

@Query("SELECT * FROM album_artists WHERE album_id IN (:ids)")
protected abstract fun getAllAlbumArtistsWhereAlbumIds(ids: List<Int>): LiveData<List<DbAlbumArtist>>
protected abstract fun findAllAlbumArtistsWhereAlbumIds(ids: List<Int>): LiveData<List<DbAlbumArtist>>

@Query("SELECT * FROM album_artists WHERE album_id IN (:ids)")
protected abstract fun getAllAlbumArtistsWhereAlbumIds(ids: List<Int>): List<DbAlbumArtist>

@Query("SELECT * FROM album_labels")
protected abstract fun getAllAlbumLabels(): LiveData<List<DbAlbumLabel>>

@Query("SELECT * FROM album_labels WHERE album_id IN (:ids)")
protected abstract fun getAllAlbumLabelsWhereAlbumIds(ids: List<Int>): LiveData<List<DbAlbumLabel>>
protected abstract fun findAllAlbumLabelsWhereAlbumIds(ids: List<Int>): LiveData<List<DbAlbumLabel>>

@Query("SELECT * FROM album_labels WHERE album_id IN (:ids)")
protected abstract fun getAllAlbumLabelsWhereAlbumIds(ids: List<Int>): List<DbAlbumLabel>

@Insert(onConflict = OnConflictStrategy.REPLACE)
protected abstract fun upsert(album: DbAlbum)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class AlbumRepository @Inject constructor(

fun findById(id: Int): LiveData<Album?> = albumDao.findById(id)
fun getById(id: Int): Album? = albumDao.getAlbumById(id)
fun getByIds(ids: List<Int>): List<Album> = albumDao.getByIds(ids)

fun findByIds(ids: List<Int>): LiveData<List<Album>> = albumDao.findByIds(ids)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package me.vanpetegem.accentor.data.playlists

enum class Access {
SHARED,
PERSONAL,
SECRET,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package me.vanpetegem.accentor.data.playlists

import java.time.Instant

data class ApiPlaylist(
val id: Int,
val name: String,
val description: String?,
val userId: Int,
val playlistType: PlaylistType,
val createdAt: Instant,
val updatedAt: Instant,
val itemIds: List<Int>,
val access: Access,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package me.vanpetegem.accentor.data.playlists

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.Instant

@Entity(tableName = "playlists")
data class DbPlaylist(
@PrimaryKey
@ColumnInfo(name = "id")
val id: Int,
@ColumnInfo(name = "name")
val name: String,
@ColumnInfo(name = "description")
val description: String?,
@ColumnInfo(name = "user_id")
val userId: Int,
@ColumnInfo(name = "playlist_type")
val playlistType: PlaylistType,
@ColumnInfo(name = "created_at")
val createdAt: Instant,
@ColumnInfo(name = "updated_at")
val updatedAt: Instant,
@ColumnInfo(name = "access")
val access: Access,
@ColumnInfo(name = "fetched_at")
val fetchedAt: Instant,
)

@Entity(tableName = "playlist_items", primaryKeys = ["playlist_id", "item_id"])
data class DbPlaylistItem(
@ColumnInfo(name = "playlist_id")
val playlistId: Int,
@ColumnInfo(name = "item_id")
val itemId: Int,
@ColumnInfo(name = "order")
val order: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package me.vanpetegem.accentor.data.playlists

import android.util.SparseArray
import java.time.Instant
import me.vanpetegem.accentor.data.albums.Album
import me.vanpetegem.accentor.data.albums.AlbumRepository
import me.vanpetegem.accentor.data.tracks.Track
import me.vanpetegem.accentor.data.tracks.TrackRepository

data class Playlist(
val id: Int,
val name: String,
val description: String?,
val userId: Int,
val playlistType: PlaylistType,
val createdAt: Instant,
val updatedAt: Instant,
val itemIds: List<Int>,
val access: Access,
val fetchedAt: Instant,
) {
companion object {
fun fromDb(p: DbPlaylist, playlistItems: List<Int>) =
Playlist(
p.id,
p.name,
p.description,
p.userId,
p.playlistType,
p.createdAt,
p.updatedAt,
playlistItems,
p.access,
p.fetchedAt,
)

fun fromApi(p: ApiPlaylist, fetchTime: Instant) =
Playlist(
p.id,
p.name,
p.description,
p.userId,
p.playlistType,
p.createdAt,
p.updatedAt,
p.itemIds,
p.access,
fetchTime,
)
}

fun toTrackAlbumPairs(trackRepository: TrackRepository, albumRepository: AlbumRepository): List<Pair<Track, Album>> {
return when (playlistType) {
PlaylistType.TRACK -> {
val albumMap = SparseArray<Album>()
val tracks = trackRepository.getByIds(itemIds)
tracks.forEach {
if (albumMap.indexOfKey(it.albumId) < 0) {
albumMap.put(it.albumId, albumRepository.getById(it.albumId)!!)
}
}
tracks.map { Pair(it, albumMap.get(it.albumId)) }
}
PlaylistType.ALBUM -> albumRepository.getByIds(itemIds).flatMap { a ->
trackRepository.getByAlbum(a).map { t -> Pair(t, a) }
}
PlaylistType.ARTIST -> {
val albumMap = SparseArray<Album>()
itemIds.flatMap { id ->
val tracks = trackRepository.getByArtistId(id).toMutableList()
tracks.forEach {
if (albumMap.indexOfKey(it.albumId) < 0) {
albumMap.put(it.albumId, albumRepository.getById(it.albumId)!!)
}
}
tracks.sortWith({ t1, t2 -> t1.compareAlphabetically(t2, albumMap) })
tracks.map { Pair(it, albumMap.get(it.albumId)) }
}
}
}
}
}
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载