git.iko.soy/opencode-android
on 06fd41b help sign in
64 lines 2.7 kB history raw
1package soy.iko.opencode.data.repo
3import android.content.Context
4import androidx.datastore.preferences.core.edit
5import androidx.datastore.preferences.core.stringSetPreferencesKey
6import androidx.datastore.preferences.preferencesDataStore
7import kotlinx.coroutines.flow.Flow
8import kotlinx.coroutines.flow.flowOf
9import kotlinx.coroutines.flow.map
11private val Context.sessionPrefsDataStore by preferencesDataStore(name = "session_prefs")
13/**
14 * Local, per-session organization flags the opencode server doesn't track: **pinned**
15 * (sorted to the top of the session list) and **archived** (hidden from the list unless the
16 * user opts to show them). Keyed by opencode session id.
17 *
18 * `open` with a `protected` no-arg constructor so tests can subclass and override the flows
19 * without a real DataStore (mirrors the other stores). The flow accessors are getters (not
20 * eager initializers) and null-guard the context so the test constructor never touches disk.
21 */
22open class SessionPrefsStore private constructor(
23 private val appContext: Context?,
24 @Suppress("unused") private val testMode: Boolean,
25) {
26 constructor(context: Context) : this(context.applicationContext, false)
27 protected constructor() : this(null, true)
29 private val pinnedKey = stringSetPreferencesKey("pinned")
30 private val archivedKey = stringSetPreferencesKey("archived")
32 open val pinned: Flow<Set<String>>
33 get() = appContext?.sessionPrefsDataStore?.data?.map { it[pinnedKey] ?: emptySet() }
34 ?: flowOf(emptySet())
36 open val archived: Flow<Set<String>>
37 get() = appContext?.sessionPrefsDataStore?.data?.map { it[archivedKey] ?: emptySet() }
38 ?: flowOf(emptySet())
40 open suspend fun setPinned(sessionId: String, pinned: Boolean) = toggle(pinnedKey, sessionId, pinned)
42 open suspend fun setArchived(sessionId: String, archived: Boolean) = toggle(archivedKey, sessionId, archived)
44 /** Drop a session from both sets — call on deletion so ids don't accumulate forever. */
45 open suspend fun forget(sessionId: String) {
46 val ctx = appContext ?: return
47 ctx.sessionPrefsDataStore.edit { prefs ->
48 prefs[pinnedKey] = (prefs[pinnedKey] ?: emptySet()) - sessionId
49 prefs[archivedKey] = (prefs[archivedKey] ?: emptySet()) - sessionId
50 }
51 }
53 private suspend fun toggle(
54 key: androidx.datastore.preferences.core.Preferences.Key<Set<String>>,
55 sessionId: String,
56 on: Boolean,
57 ) {
58 val ctx = appContext ?: return
59 ctx.sessionPrefsDataStore.edit { prefs ->
60 val current = prefs[key] ?: emptySet()
61 prefs[key] = if (on) current + sessionId else current - sessionId
62 }
63 }