Task 8: Wire StationPreference into StreamResolver

- Add StationPreferenceDao to StreamResolver constructor
- Check station_preferences before station.qualityOverride / global prefs
- Mock stationPrefDao in StreamResolverTest, add precedence test

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-11 16:20:21 -04:00
parent 2087b48e4e
commit 92f3b35418
3 changed files with 36 additions and 6 deletions

View File

@@ -36,7 +36,7 @@ class RadioApplication : Application() {
}
val streamResolver: StreamResolver by lazy {
StreamResolver(database.stationStreamDao(), preferences)
StreamResolver(database.stationStreamDao(), preferences, database.stationPreferenceDao())
}
val historyWriter: NowPlayingHistoryWriter by lazy {

View File

@@ -1,5 +1,6 @@
package xyz.cottongin.radio247.service
import xyz.cottongin.radio247.data.db.StationPreferenceDao
import xyz.cottongin.radio247.data.db.StationStreamDao
import xyz.cottongin.radio247.data.model.Station
import xyz.cottongin.radio247.data.prefs.RadioPreferences
@@ -8,7 +9,8 @@ import org.json.JSONArray
class StreamResolver(
private val streamDao: StationStreamDao,
private val preferences: RadioPreferences
private val preferences: RadioPreferences,
private val stationPreferenceDao: StationPreferenceDao
) {
/**
* Returns an ordered list of stream URLs to try for the given station.
@@ -19,7 +21,11 @@ class StreamResolver(
val streams = streamDao.getStreamsForStation(station.id)
if (streams.isEmpty()) return listOf(station.url)
val order = parseOrder(station.qualityOverride ?: preferences.qualityPreference.first())
val pref = stationPreferenceDao.getByStationId(station.id)
val qualityJson = pref?.qualityOverride
?: station.qualityOverride
?: preferences.qualityPreference.first()
val order = parseOrder(qualityJson)
val sorted = streams.sortedBy { stream ->
val key = "${stream.bitrate}-${if (stream.ssl) "ssl" else "nossl"}"
val idx = order.indexOf(key)

View File

@@ -6,8 +6,10 @@ import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertEquals
import org.junit.Test
import xyz.cottongin.radio247.data.db.StationPreferenceDao
import xyz.cottongin.radio247.data.db.StationStreamDao
import xyz.cottongin.radio247.data.model.Station
import xyz.cottongin.radio247.data.model.StationPreference
import xyz.cottongin.radio247.data.model.StationStream
import xyz.cottongin.radio247.data.prefs.RadioPreferences
@@ -15,6 +17,7 @@ class StreamResolverTest {
private val streamDao = mockk<StationStreamDao>()
private val prefs = mockk<RadioPreferences>()
private val stationPrefDao = mockk<StationPreferenceDao>()
private val testStation = Station(
id = 1L,
@@ -25,7 +28,8 @@ class StreamResolverTest {
@Test
fun `returns station url when no streams exist`() = runTest {
coEvery { streamDao.getStreamsForStation(1L) } returns emptyList()
val resolver = StreamResolver(streamDao, prefs)
coEvery { stationPrefDao.getByStationId(any()) } returns null
val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
val urls = resolver.resolveUrls(testStation)
assertEquals(listOf("http://fallback.com/stream"), urls)
}
@@ -37,8 +41,9 @@ class StreamResolverTest {
StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com"),
StationStream(id = 3, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com")
)
coEvery { stationPrefDao.getByStationId(any()) } returns null
coEvery { prefs.qualityPreference } returns flowOf(StreamResolver.DEFAULT_ORDER_JSON)
val resolver = StreamResolver(streamDao, prefs)
val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
val urls = resolver.resolveUrls(testStation)
assertEquals("https://256.com", urls[0])
assertEquals("https://128.com", urls[1])
@@ -55,10 +60,29 @@ class StreamResolverTest {
StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com"),
StationStream(id = 3, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com")
)
val resolver = StreamResolver(streamDao, prefs)
coEvery { stationPrefDao.getByStationId(any()) } returns null
val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
val urls = resolver.resolveUrls(stationWithOverride)
assertEquals("https://128.com", urls[0])
assertEquals("http://128.com", urls[1])
assertEquals("https://256.com", urls[2])
}
@Test
fun `stationPreference qualityOverride takes precedence over station field`() = runTest {
coEvery { streamDao.getStreamsForStation(1L) } returns listOf(
StationStream(id = 1, stationId = 1, bitrate = 128, ssl = true, url = "https://128.com"),
StationStream(id = 2, stationId = 1, bitrate = 256, ssl = true, url = "https://256.com")
)
coEvery { stationPrefDao.getByStationId(1L) } returns StationPreference(
stationId = 1L,
qualityOverride = """["128-ssl","256-ssl"]"""
)
val stationWithOverride = testStation.copy(
qualityOverride = """["256-ssl","128-ssl"]"""
)
val resolver = StreamResolver(streamDao, prefs, stationPrefDao)
val urls = resolver.resolveUrls(stationWithOverride)
assertEquals("https://128.com", urls[0])
}
}