git.iko.soy/opencode-android
on 9ba5eec help sign in
52 lines 1.8 kB history raw
1package soy.iko.opencode
3import android.app.Application
4import android.content.Context
5import androidx.core.content.edit
6import androidx.lifecycle.AndroidViewModel
7import androidx.lifecycle.viewModelScope
8import kotlinx.coroutines.flow.distinctUntilChangedBy
9import kotlinx.coroutines.launch
10import soy.iko.opencode.core.Event
11import soy.iko.opencode.core.OpencodeCore
13/**
14 * Lifecycle-scoped host for the [OpencodeCore] so a single core (and its SSE
15 * connection) survives configuration changes. It also persists the last server
16 * URL / username so reconnecting is one tap.
17 */
18class CoreViewModel(app: Application) : AndroidViewModel(app) {
19 private val prefs = app.getSharedPreferences("opencode", Context.MODE_PRIVATE)
21 val core = OpencodeCore(viewModelScope)
23 init {
24 prefs.getString(KEY_URL, null)?.let { core.dispatch(Event.ServerUrlChanged(it)) }
25 prefs.getString(KEY_USER, null)?.let { core.dispatch(Event.UsernameChanged(it)) }
27 // On a fresh process after a configuration change, resume the SSE stream if
28 // the core is already connected (no-op otherwise — it guards on `connected`).
29 core.resumeStreamingIfConnected()
31 // Persist connection details once a connection succeeds.
32 viewModelScope.launch {
33 core.view.distinctUntilChangedBy { it.connected to it.serverUrl }.collect { state ->
34 if (state.connected) {
35 prefs.edit {
36 putString(KEY_URL, state.serverUrl)
37 putString(KEY_USER, state.username)
38 }
39 }
40 }
41 }
42 }
44 override fun onCleared() {
45 core.shutdown()
46 }
48 private companion object {
49 const val KEY_URL = "serverUrl"
50 const val KEY_USER = "username"
51 }