git.iko.soy/opencode-android
on 0bc1eda help sign in
51 lines 2.0 kB history raw
1package soy.iko.opencode.ui.components
3import androidx.compose.runtime.Composable
4import androidx.compose.runtime.LaunchedEffect
5import androidx.compose.runtime.getValue
6import androidx.compose.runtime.mutableLongStateOf
7import androidx.compose.runtime.remember
8import androidx.compose.runtime.setValue
9import kotlinx.coroutines.delay
10import java.util.concurrent.TimeUnit
12/** Formats an epoch-millis timestamp as a short relative string (e.g. "3m", "2h", "5d"). */
13fun relativeTime(epochMillis: Long?): String {
14 if (epochMillis == null || epochMillis <= 0) return ""
15 val diff = System.currentTimeMillis() - epochMillis
16 if (diff < 0) return "now"
17 val minutes = TimeUnit.MILLISECONDS.toMinutes(diff)
18 if (minutes < 1) return "now"
19 if (minutes < 60) return "${minutes}m"
20 val hours = TimeUnit.MILLISECONDS.toHours(diff)
21 if (hours < 24) return "${hours}h"
22 val days = TimeUnit.MILLISECONDS.toDays(diff)
23 if (days < 7) return "${days}d"
24 val weeks = days / 7
25 if (weeks < 5) return "${weeks}w"
26 val months = days / 30
27 if (months < 12) return "${months}mo"
28 return "${days / 365}y"
31/**
32 * Returns a relative-time string for [epochMillis] that auto-refreshes so the label
33 * doesn't go stale (e.g. "3m" → "4m" → "5m" while the screen is visible). Re-evaluates
34 * every [intervalMs] (default 30 s — coarse enough for battery, fine enough for the
35 * smallest unit we show, which is minutes).
36 */
37@Composable
38fun rememberRelativeTime(epochMillis: Long?, intervalMs: Long = 30_000L): String {
39 // Recompose trigger: incrementing this state causes the composable to re-execute
40 // on each interval, re-evaluating relativeTime() so the label stays fresh.
41 var tick by remember { mutableLongStateOf(0L) }
42 LaunchedEffect(epochMillis) {
43 while (true) {
44 delay(intervalMs)
45 tick++
46 }
47 }
48 // Read tick so Compose tracks it as a dependency and recomposes when it changes.
49 @Suppress("UNUSED_EXPRESSION") tick
50 return relativeTime(epochMillis)