feat: M3 weighted shuffle v1 — real /api/radio with scoring #21

Merged
bvandeusen merged 262 commits from dev into main 2026-04-27 11:00:29 -04:00
Showing only changes of commit 587baf4a79 - Show all commits
@@ -0,0 +1,22 @@
package com.fabledsword.minstrel.shared
/**
* Shared cache-first UI state for a screen / tab that resolves to a
* single payload. Mirrors the shape every screen had reinvented:
* - [Loading] cold start, before either the cache or the refresh
* has emitted anything
* - [Empty] the cache + refresh both succeeded with no data
* - [Success] the cache (or refresh) has a payload — render it
* - [Error] no cached data + the refresh failed; UI surfaces
* [message] from `ErrorCopy.fromThrowable`
*
* Each screen / tab parameterizes [T] with whatever it actually
* renders (`HomeSections`, `List<PlaylistRef>`, etc.), so a single
* generic replaces the per-screen sealed interface declarations.
*/
sealed interface UiState<out T> {
data object Loading : UiState<Nothing>
data object Empty : UiState<Nothing>
data class Success<T>(val data: T) : UiState<T>
data class Error(val message: String) : UiState<Nothing>
}