package de.timklge.karoopowerbar import android.content.Context import android.util.Log import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import de.timklge.karoopowerbar.screens.SelectedSource import io.hammerhead.karooext.KarooSystemService import io.hammerhead.karooext.models.OnStreamState import io.hammerhead.karooext.models.RideState import io.hammerhead.karooext.models.StreamState import io.hammerhead.karooext.models.UserProfile import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.serialization.Serializable import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json val jsonWithUnknownKeys = Json { ignoreUnknownKeys = true } val settingsKey = stringPreferencesKey("settings") @Serializable data class PowerbarSettings( val source: SelectedSource = SelectedSource.POWER, val topBarSource: SelectedSource = SelectedSource.NONE, val onlyShowWhileRiding: Boolean = true, val showLabelOnBars: Boolean = true, val useZoneColors: Boolean = true, ){ companion object { val defaultSettings = Json.encodeToString(PowerbarSettings()) } } suspend fun saveSettings(context: Context, settings: PowerbarSettings) { context.dataStore.edit { t -> t[settingsKey] = Json.encodeToString(settings) } } fun Context.streamSettings(): Flow { return dataStore.data.map { settingsJson -> try { jsonWithUnknownKeys.decodeFromString( settingsJson[settingsKey] ?: PowerbarSettings.defaultSettings ) } catch(e: Throwable){ Log.e(KarooPowerbarExtension.TAG, "Failed to read preferences", e) jsonWithUnknownKeys.decodeFromString(PowerbarSettings.defaultSettings) } }.distinctUntilChanged() } fun KarooSystemService.streamDataFlow(dataTypeId: String): Flow { return callbackFlow { val listenerId = addConsumer(OnStreamState.StartStreaming(dataTypeId)) { event: OnStreamState -> trySendBlocking(event.state) } awaitClose { removeConsumer(listenerId) } } } fun KarooSystemService.streamRideState(): Flow { return callbackFlow { val listenerId = addConsumer { rideState: RideState -> trySendBlocking(rideState) } awaitClose { removeConsumer(listenerId) } } } fun KarooSystemService.streamUserProfile(): Flow { return callbackFlow { val listenerId = addConsumer { userProfile: UserProfile -> trySendBlocking(userProfile) } awaitClose { removeConsumer(listenerId) } } }