feat: M3 weighted shuffle v1 — real /api/radio with scoring #21
@@ -6,6 +6,7 @@ import androidx.room.TypeConverters
|
||||
import com.fabledsword.minstrel.cache.db.dao.AudioCacheIndexDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedAlbumDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedArtistDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedHomeIndexDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedLikeDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedMutationDao
|
||||
import com.fabledsword.minstrel.cache.db.dao.CachedPlaylistDao
|
||||
@@ -17,6 +18,7 @@ import com.fabledsword.minstrel.cache.db.dao.SyncMetadataDao
|
||||
import com.fabledsword.minstrel.cache.db.entities.AudioCacheIndexEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedAlbumEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedArtistEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedHomeIndexEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedLikeEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedMutationEntity
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedPlaylistEntity
|
||||
@@ -52,6 +54,7 @@ import com.fabledsword.minstrel.cache.db.entities.SyncMetadataEntity
|
||||
AudioCacheIndexEntity::class,
|
||||
CachedMutationEntity::class,
|
||||
CachedResumeStateEntity::class,
|
||||
CachedHomeIndexEntity::class,
|
||||
],
|
||||
version = 1,
|
||||
exportSchema = true,
|
||||
@@ -69,4 +72,5 @@ abstract class AppDatabase : RoomDatabase() {
|
||||
abstract fun audioCacheIndexDao(): AudioCacheIndexDao
|
||||
abstract fun cachedMutationDao(): CachedMutationDao
|
||||
abstract fun cachedResumeStateDao(): CachedResumeStateDao
|
||||
abstract fun cachedHomeIndexDao(): CachedHomeIndexDao
|
||||
}
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.fabledsword.minstrel.cache.db.dao
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import com.fabledsword.minstrel.cache.db.entities.CachedHomeIndexEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
@Dao
|
||||
interface CachedHomeIndexDao {
|
||||
@Query(
|
||||
"SELECT * FROM cached_home_index " +
|
||||
"WHERE section = :section ORDER BY position ASC",
|
||||
)
|
||||
fun observeBySection(section: String): Flow<List<CachedHomeIndexEntity>>
|
||||
|
||||
@Query(
|
||||
"SELECT * FROM cached_home_index " +
|
||||
"WHERE section = :section ORDER BY position ASC",
|
||||
)
|
||||
suspend fun getBySection(section: String): List<CachedHomeIndexEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||
suspend fun upsertAll(rows: List<CachedHomeIndexEntity>)
|
||||
|
||||
/** Replace-all pattern; sync wipes a section then re-inserts. */
|
||||
@Query("DELETE FROM cached_home_index WHERE section = :section")
|
||||
suspend fun deleteBySection(section: String)
|
||||
|
||||
@Query("DELETE FROM cached_home_index")
|
||||
suspend fun clear()
|
||||
}
|
||||
Vendored
+34
@@ -0,0 +1,34 @@
|
||||
package com.fabledsword.minstrel.cache.db.entities
|
||||
|
||||
import androidx.room.Entity
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
|
||||
/**
|
||||
* Per-item row driving the Home screen sections. Mirrors
|
||||
* `flutter_client/lib/cache/db.dart`'s `CachedHomeIndex` Drift table.
|
||||
*
|
||||
* `section` is one of (matching /api/home keys):
|
||||
* - "recently_added_albums"
|
||||
* - "rediscover_albums"
|
||||
* - "rediscover_artists"
|
||||
* - "most_played_tracks"
|
||||
* - "last_played_artists"
|
||||
*
|
||||
* `entityType` is "album" | "artist" | "track" — dispatches hydration
|
||||
* to the right per-entity endpoint when a tile is rendered.
|
||||
*
|
||||
* The composite PK (section, position) means there's exactly one row
|
||||
* per slot per section; sync replaces in-place by upsert.
|
||||
*/
|
||||
@Entity(
|
||||
tableName = "cached_home_index",
|
||||
primaryKeys = ["section", "position"],
|
||||
)
|
||||
data class CachedHomeIndexEntity(
|
||||
val section: String,
|
||||
val position: Int,
|
||||
val entityType: String,
|
||||
val entityId: String,
|
||||
val fetchedAt: Instant = Clock.System.now(),
|
||||
)
|
||||
Reference in New Issue
Block a user