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")
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.
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.
22open class SessionPrefsStore private constructor(
23 private val appContext: Context?,
24 @Suppress("unused") private val testMode: Boolean,
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")
31 private val mutedKey = stringSetPreferencesKey("muted")
33 open val pinned: Flow<Set<String>>
34 get() = appContext?.sessionPrefsDataStore?.data?.map { it[pinnedKey] ?: emptySet() }
37 open val archived: Flow<Set<String>>
38 get() = appContext?.sessionPrefsDataStore?.data?.map { it[archivedKey] ?: emptySet() }
41 /** Session ids the user has muted (suppress unread badge + completion notification). */
42 open val muted: Flow<Set<String>>
43 get() = appContext?.sessionPrefsDataStore?.data?.map { it[mutedKey] ?: emptySet() }
46 open suspend fun setPinned(sessionId: String, pinned: Boolean) = toggle(pinnedKey, sessionId, pinned)
48 open suspend fun setArchived(sessionId: String, archived: Boolean) = toggle(archivedKey, sessionId, archived)
50 open suspend fun setMuted(sessionId: String, muted: Boolean) = toggle(mutedKey, sessionId, muted)
52 /** Drop a session from all sets — call on deletion so ids don't accumulate forever. */
53 open suspend fun forget(sessionId: String) {
54 val ctx = appContext ?: return
55 ctx.sessionPrefsDataStore.edit { prefs ->
56 prefs[pinnedKey] = (prefs[pinnedKey] ?: emptySet()) - sessionId
57 prefs[archivedKey] = (prefs[archivedKey] ?: emptySet()) - sessionId
58 prefs[mutedKey] = (prefs[mutedKey] ?: emptySet()) - sessionId
62 private suspend fun toggle(
63 key: androidx.datastore.preferences.core.Preferences.Key<Set<String>>,
67 val ctx = appContext ?: return
68 ctx.sessionPrefsDataStore.edit { prefs ->
69 val current = prefs[key] ?: emptySet()
70 prefs[key] = if (on) current + sessionId else current - sessionId
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list