From 92f3b3541813763380c1761d8454b26ad20f5631 Mon Sep 17 00:00:00 2001 From: cottongin Date: Wed, 11 Mar 2026 16:20:21 -0400 Subject: [PATCH] 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 --- .../cottongin/radio247/RadioApplication.kt | 2 +- .../radio247/service/StreamResolver.kt | 10 +++++-- .../radio247/service/StreamResolverTest.kt | 30 +++++++++++++++++-- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/xyz/cottongin/radio247/RadioApplication.kt b/app/src/main/java/xyz/cottongin/radio247/RadioApplication.kt index be1e836..2c88c96 100644 --- a/app/src/main/java/xyz/cottongin/radio247/RadioApplication.kt +++ b/app/src/main/java/xyz/cottongin/radio247/RadioApplication.kt @@ -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 { diff --git a/app/src/main/java/xyz/cottongin/radio247/service/StreamResolver.kt b/app/src/main/java/xyz/cottongin/radio247/service/StreamResolver.kt index f48dca4..8da32fa 100644 --- a/app/src/main/java/xyz/cottongin/radio247/service/StreamResolver.kt +++ b/app/src/main/java/xyz/cottongin/radio247/service/StreamResolver.kt @@ -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) diff --git a/app/src/test/java/xyz/cottongin/radio247/service/StreamResolverTest.kt b/app/src/test/java/xyz/cottongin/radio247/service/StreamResolverTest.kt index 02a4287..952335f 100644 --- a/app/src/test/java/xyz/cottongin/radio247/service/StreamResolverTest.kt +++ b/app/src/test/java/xyz/cottongin/radio247/service/StreamResolverTest.kt @@ -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() private val prefs = mockk() + private val stationPrefDao = mockk() 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]) + } }