Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 688147b8ef |
@@ -342,6 +342,9 @@ private fun HistoryTab(onEditSession: (Session) -> Unit, onOpenToken: () -> Unit
|
||||
val sessions by SessionStore.sessions.collectAsState()
|
||||
val pending by SessionStore.pendingSync.collectAsState()
|
||||
|
||||
// Pull the server history (incl. legacy Jhana-app sessions) on open.
|
||||
LaunchedEffect(Unit) { SessionStore.refresh() }
|
||||
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
|
||||
@@ -55,6 +55,7 @@ object SessionStore {
|
||||
publish(load())
|
||||
}
|
||||
syncPending()
|
||||
refresh()
|
||||
}
|
||||
|
||||
var token: String
|
||||
@@ -93,6 +94,68 @@ object SessionStore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pull the full server history (incl. sessions from other apps/devices,
|
||||
* e.g. the legacy Jhana app) and merge it into the local log. Local
|
||||
* sessions still awaiting push (synced=false) always win over the server
|
||||
* copy; everything else takes the server's version.
|
||||
*/
|
||||
fun refresh() {
|
||||
val tok = token
|
||||
if (tok.isEmpty()) return
|
||||
scope.launch {
|
||||
val remote = fetchSessions(tok) ?: return@launch
|
||||
synchronized(lock) {
|
||||
val local = load().associateBy { it.id }
|
||||
val merged = LinkedHashMap(local)
|
||||
for (r in remote) {
|
||||
val l = local[r.id]
|
||||
if (l == null || l.synced) {
|
||||
// Keep any locally-entered rating/note if the server has none.
|
||||
merged[r.id] = r.copy(
|
||||
rating = r.rating ?: l?.rating,
|
||||
note = r.note ?: l?.note,
|
||||
synced = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
persist(merged.values.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchSessions(tok: String): List<Session>? = try {
|
||||
val conn = URL("$BASE_URL/v1/sessions?limit=1000").openConnection() as HttpURLConnection
|
||||
conn.requestMethod = "GET"
|
||||
conn.setRequestProperty("Authorization", "Bearer $tok")
|
||||
conn.connectTimeout = 10_000
|
||||
conn.readTimeout = 10_000
|
||||
val body = if (conn.responseCode in 200..299) {
|
||||
conn.inputStream.bufferedReader().use { it.readText() }
|
||||
} else null
|
||||
conn.disconnect()
|
||||
body?.let {
|
||||
val arr = JSONObject(it).getJSONArray("sessions")
|
||||
(0 until arr.length()).map { i ->
|
||||
val o = arr.getJSONObject(i)
|
||||
Session(
|
||||
id = o.getString("id"),
|
||||
startedAt = o.getString("startedAt"),
|
||||
endedAt = o.optString("endedAt").ifEmpty { null },
|
||||
plannedMin = o.optInt("plannedMin", 0),
|
||||
actualMin = o.optInt("actualMin", 0),
|
||||
completed = o.optBoolean("completed", false),
|
||||
pauseCount = o.optInt("pauseCount", 0),
|
||||
rating = if (o.isNull("rating")) null else o.optInt("rating"),
|
||||
note = o.optString("note").ifEmpty { null },
|
||||
synced = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
} catch (_: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
private fun postSession(s: Session, tok: String): Boolean = try {
|
||||
val conn = URL("$BASE_URL/v1/sessions").openConnection() as HttpURLConnection
|
||||
conn.requestMethod = "POST"
|
||||
|
||||
Reference in New Issue
Block a user