Skip to content

Commit

Permalink
Add recently played artists and albums to home (#324)
Browse files Browse the repository at this point in the history
* Fetch plays

Also insert self-reported plays in DB

* Add recently played albums to home

* Extract creating Album from DbAlbum

* Show recently played artists on home
  • Loading branch information
chvp authored Nov 20, 2021
1 parent 6b7fe56 commit f66eb87
Show file tree
Hide file tree
Showing 16 changed files with 852 additions and 119 deletions.
583 changes: 583 additions & 0 deletions app/schemas/me.vanpetegem.accentor.data.AccentorDatabase/9.json

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions app/src/main/java/me/vanpetegem/accentor/api/plays/Play.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.vanpetegem.accentor.api.plays

import com.github.kittinunf.fuel.httpGet
import com.github.kittinunf.fuel.httpPost
import java.time.Instant
import me.vanpetegem.accentor.data.authentication.AuthenticationData
Expand All @@ -23,3 +24,30 @@ fun create(server: String, authenticationData: AuthenticationData, trackId: Int,
{ e: Throwable -> Result.Error(Exception("Error creating play", e)) },
)
}

fun index(server: String, authenticationData: AuthenticationData): Result<List<Play>> {
var page = 1
val results = ArrayList<Play>()

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

return doFetch()
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ 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.plays.DbPlay
import me.vanpetegem.accentor.data.plays.PlayDao
import me.vanpetegem.accentor.data.plays.UnreportedPlay
import me.vanpetegem.accentor.data.plays.UnreportedPlayDao
import me.vanpetegem.accentor.data.tracks.DbTrack
Expand All @@ -39,17 +41,19 @@ import me.vanpetegem.accentor.util.RoomTypeConverters
DbAlbumLabel::class,
DbArtist::class,
DbCodecConversion::class,
DbPlay::class,
DbTrack::class,
DbTrackArtist::class,
DbTrackGenre::class,
UnreportedPlay::class,
],
version = 8
version = 9
)
abstract class AccentorDatabase : RoomDatabase() {
abstract fun albumDao(): AlbumDao
abstract fun artistDao(): ArtistDao
abstract fun codecConversionDao(): CodecConversionDao
abstract fun playDao(): PlayDao
abstract fun trackDao(): TrackDao
abstract fun userDao(): UserDao
abstract fun unreportedPlayDao(): UnreportedPlayDao
Expand Down Expand Up @@ -203,6 +207,27 @@ internal object DatabaseModule {
}
}
})
.addMigrations(object : Migration(8, 9) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
try {
database.execSQL(
"""
CREATE TABLE IF NOT EXISTS `plays` (
`id` INTEGER NOT NULL,
`played_at` TEXT NOT NULL,
`track_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
PRIMARY KEY(`id`)
)
"""
)
database.setTransactionSuccessful()
} finally {
database.endTransaction()
}
}
})
.build()
}

Expand All @@ -213,6 +238,8 @@ internal object DatabaseModule {
@Provides
fun provideCodecConversionDao(database: AccentorDatabase): CodecConversionDao = database.codecConversionDao()
@Provides
fun providePlayDao(database: AccentorDatabase): PlayDao = database.playDao()
@Provides
fun provideTrackDao(database: AccentorDatabase): TrackDao = database.trackDao()
@Provides
fun provideUserDao(database: AccentorDatabase): UserDao = database.userDao()
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/java/me/vanpetegem/accentor/data/albums/Album.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,28 @@ data class Album(
order = if (order == 0) this.id - other.id else order
return order
}

companion object {
fun fromDbAlbum(a: DbAlbum, labels: List<AlbumLabel>, artists: List<AlbumArtist>): Album =
Album(
a.id,
a.title,
a.normalizedTitle,
a.release,
a.reviewComment,
a.edition,
a.editionDescription,
a.createdAt,
a.updatedAt,
a.image,
a.image500,
a.image250,
a.image100,
a.imageType,
labels,
artists,
)
}
}

fun compareAlbumEditions(a1: Album, a2: Album): Int {
Expand Down
123 changes: 30 additions & 93 deletions app/src/main/java/me/vanpetegem/accentor/data/albums/AlbumDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.lifecycle.Transformations.switchMap
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import androidx.room.Transaction
import java.time.LocalDate
import java.time.format.DateTimeFormatter
Expand All @@ -17,53 +18,23 @@ abstract class AlbumDao {
open fun getAll(): LiveData<List<Album>> = switchMap(getAllDbAlbums()) { albums ->
switchMap(albumArtistsByAlbumId()) { albumArtists ->
map(albumLabelsByAlbumId()) { albumLabels ->
albums.map { a ->
Album(
a.id,
a.title,
a.normalizedTitle,
a.release,
a.reviewComment,
a.edition,
a.editionDescription,
a.createdAt,
a.updatedAt,
a.image,
a.image500,
a.image250,
a.image100,
a.imageType,
albumLabels.get(a.id, ArrayList()),
albumArtists.get(a.id, ArrayList())
)
}
albums.map { a -> Album.fromDbAlbum(a, albumLabels.get(a.id, ArrayList()), albumArtists.get(a.id, ArrayList())) }
}
}
}

open fun getAllByPlayed(): LiveData<List<Album>> = switchMap(getAllDbAlbumsByPlayed()) { albums ->
switchMap(albumArtistsByAlbumId()) { albumArtists ->
map(albumLabelsByAlbumId()) { albumLabels ->
albums.map { a -> Album.fromDbAlbum(a, albumLabels.get(a.id, ArrayList()), albumArtists.get(a.id, ArrayList())) }
}
}
}

open fun findByIds(ids: List<Int>): LiveData<List<Album>> = switchMap(findDbAlbumsByIds(ids)) { albums ->
switchMap(albumArtistsByAlbumIdWhereAlbumIds(ids)) { albumArtists ->
map(albumLabelsByAlbumIdWhereAlbumIds(ids)) { albumLabels ->
albums.map { a ->
Album(
a.id,
a.title,
a.normalizedTitle,
a.release,
a.reviewComment,
a.edition,
a.editionDescription,
a.createdAt,
a.updatedAt,
a.image,
a.image500,
a.image250,
a.image100,
a.imageType,
albumLabels.get(a.id, ArrayList()),
albumArtists.get(a.id, ArrayList())
)
}
albums.map { a -> Album.fromDbAlbum(a, albumLabels.get(a.id, ArrayList()), albumArtists.get(a.id, ArrayList())) }
}
}
}
Expand All @@ -72,23 +43,10 @@ abstract class AlbumDao {
switchMap(findDbAlbumArtistsById(id)) { albumArtists ->
map(findDbAlbumLabelsById(id)) { albumLabels ->
if (dbAlbum != null) {
Album(
dbAlbum.id,
dbAlbum.title,
dbAlbum.normalizedTitle,
dbAlbum.release,
dbAlbum.reviewComment,
dbAlbum.edition,
dbAlbum.editionDescription,
dbAlbum.createdAt,
dbAlbum.updatedAt,
dbAlbum.image,
dbAlbum.image500,
dbAlbum.image250,
dbAlbum.image100,
dbAlbum.imageType,
Album.fromDbAlbum(
dbAlbum,
albumLabels.map { AlbumLabel(it.labelId, it.catalogueNumber) },
albumArtists.map { AlbumArtist(it.artistId, it.name, it.normalizedName, it.order, it.separator) }
albumArtists.map { AlbumArtist(it.artistId, it.name, it.normalizedName, it.order, it.separator) },
)
} else {
null
Expand All @@ -101,26 +59,7 @@ abstract class AlbumDao {
switchMap(findDbAlbumsByDay(day.format(DateTimeFormatter.ISO_LOCAL_DATE).substring(4))) { albums ->
switchMap(albumArtistsByAlbumId()) { albumArtists ->
map(albumLabelsByAlbumId()) { albumLabels ->
albums.map { a ->
Album(
a.id,
a.title,
a.normalizedTitle,
a.release,
a.reviewComment,
a.edition,
a.editionDescription,
a.createdAt,
a.updatedAt,
a.image,
a.image500,
a.image250,
a.image100,
a.imageType,
albumLabels.get(a.id, ArrayList()),
albumArtists.get(a.id, ArrayList())
)
}
albums.map { a -> Album.fromDbAlbum(a, albumLabels.get(a.id, ArrayList()), albumArtists.get(a.id, ArrayList())) }
}
}
}
Expand All @@ -132,23 +71,10 @@ abstract class AlbumDao {
val albumArtists = getDbAlbumArtistsById(id)
val albumLabels = getDbAlbumLabelsById(id)

return Album(
dbAlbum.id,
dbAlbum.title,
dbAlbum.normalizedTitle,
dbAlbum.release,
dbAlbum.reviewComment,
dbAlbum.edition,
dbAlbum.editionDescription,
dbAlbum.createdAt,
dbAlbum.updatedAt,
dbAlbum.image,
dbAlbum.image500,
dbAlbum.image250,
dbAlbum.image100,
dbAlbum.imageType,
return Album.fromDbAlbum(
dbAlbum,
albumLabels.map { AlbumLabel(it.labelId, it.catalogueNumber) },
albumArtists.map { AlbumArtist(it.artistId, it.name, it.normalizedName, it.order, it.separator) }
albumArtists.map { AlbumArtist(it.artistId, it.name, it.normalizedName, it.order, it.separator) },
)
}

Expand All @@ -169,7 +95,7 @@ abstract class AlbumDao {
edition ASC,
edition_description ASC,
id ASC
"""
"""
)
protected abstract fun findDbAlbumsByDay(day: String): LiveData<List<DbAlbum>>

Expand Down Expand Up @@ -265,6 +191,17 @@ abstract class AlbumDao {
@Query("SELECT * FROM albums ORDER BY normalized_title ASC, release ASC, edition ASC, edition_description ASC, id ASC")
protected abstract fun getAllDbAlbums(): LiveData<List<DbAlbum>>

@RewriteQueriesToDropUnusedColumns
@Query(
"""
SELECT * FROM albums INNER JOIN (
SELECT tracks.album_id as album_id, MAX(plays.played_at) AS played_at FROM
tracks INNER JOIN plays ON tracks.id = plays.track_id GROUP BY tracks.album_id
) p ON p.album_id = albums.id ORDER BY p.played_at DESC
"""
)
protected abstract fun getAllDbAlbumsByPlayed(): LiveData<List<DbAlbum>>

@Query("SELECT * FROM album_artists")
protected abstract fun getAllAlbumArtists(): LiveData<List<DbAlbumArtist>>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import me.vanpetegem.accentor.util.Result
@Reusable
class AlbumRepository @Inject constructor(
private val albumDao: AlbumDao,
private val authenticationRepository: AuthenticationRepository
private val authenticationRepository: AuthenticationRepository,
) {
val allAlbums: LiveData<List<Album>> = albumDao.getAll()
val allAlbumsById: LiveData<SparseArray<Album>> = map(allAlbums) {
Expand All @@ -31,6 +31,7 @@ class AlbumRepository @Inject constructor(
copy.sortWith({ a1, a2 -> a2.createdAt.compareTo(a1.createdAt) })
copy
}
val albumsByPlayed: LiveData<List<Album>> = albumDao.getAllByPlayed()
val randomAlbums: LiveData<List<Album>> = map(allAlbums) {
val copy = it.toMutableList()
copy.shuffle()
Expand Down
16 changes: 16 additions & 0 deletions app/src/main/java/me/vanpetegem/accentor/data/artists/Artist.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,20 @@ data class Artist(
val imageType: String?
) {
fun firstCharacter() = String(intArrayOf(name.codePointAt(0)), 0, 1)

companion object {
fun fromDbArtist(a: DbArtist): Artist = Artist(
a.id,
a.name,
a.normalizedName,
a.reviewComment,
a.createdAt,
a.updatedAt,
a.image,
a.image500,
a.image250,
a.image100,
a.imageType,
)
}
}
Loading

0 comments on commit f66eb87

Please sign in to comment.