wire the sync fetch concurrency to a Settings option

The bound was only a constructor default with no production consumer. Add a
"Sync concurrency" preference (Settings -> Network, default 4) and pass it
through SourceRepository to SubsonicSource, so sync parallelism is tunable
without a rebuild. Both the app-scoped source and the on-demand
`activeMusicSource()` used by sync read the preference.

- UserPreferences.syncConcurrency()/setSyncConcurrency() (clamped >= 1)
- SourceRepository combines the preference into toMusicSource
- Settings row + dialog; SettingsViewModel state and setter
- Preferences test for default/round-trip/clamp
This commit is contained in:
austinried
2026-10-04 00:30:02 +00:00
parent adcdc442e4
commit a4149690e5
7 changed files with 116 additions and 14 deletions
@@ -43,6 +43,8 @@ data class StreamQuality(
val transcodes: Boolean get() = maxBitrate > 0 || !format.isNullOrEmpty()
}
const val DEFAULT_SYNC_CONCURRENCY = 4
private val Context.preferences: DataStore<Preferences> by preferencesDataStore("user_prefs")
data class ArtworkSeedValue(
@@ -77,6 +79,14 @@ class UserPreferences(
private fun streamQualityKey(mode: NetworkMode) = stringPreferencesKey("stream_quality_${mode.key}")
fun syncConcurrency(): Flow<Int> = store.data.map { prefs -> prefs[syncConcurrencyKey] ?: DEFAULT_SYNC_CONCURRENCY }
suspend fun setSyncConcurrency(value: Int) {
store.edit { prefs -> prefs[syncConcurrencyKey] = value.coerceAtLeast(1) }
}
private val syncConcurrencyKey = intPreferencesKey("sync_concurrency")
suspend fun lastSeed(): ArtworkSeedValue? {
val prefs = store.data.first()
val cacheKey = prefs[lastSeedKey] ?: return null