feat: implement periodic refresh for "Updated ... ago" labels in ListsScreen

This commit is contained in:
2025-10-29 19:43:44 +01:00
parent c017307c4e
commit eb88e11f94
@@ -79,6 +79,22 @@ fun ListsScreen(
val lists by viewModel.lists.collectAsState() val lists by viewModel.lists.collectAsState()
val isLoading by viewModel.isLoading.collectAsState() val isLoading by viewModel.isLoading.collectAsState()
var nowMs by remember { mutableStateOf(System.currentTimeMillis()) }
// Periodically refresh 'now' to keep the relative "Updated … ago" labels current.
// Use fine-grained updates (1s) while any table is < 60s old; otherwise back off to 30s.
LaunchedEffect(lists) {
while (true) {
val currentNow = System.currentTimeMillis()
val minAgeSec =
lists.minOfOrNull { list ->
((currentNow - list.updatedAt).coerceAtLeast(0L) / 1000L)
} ?: Long.MAX_VALUE
val delayMs = if (minAgeSec < 60L) 1_000L else 30_000L
delay(delayMs)
nowMs = System.currentTimeMillis()
}
}
var showCreateDialog by remember { mutableStateOf(false) } var showCreateDialog by remember { mutableStateOf(false) }
var listToDelete by remember { mutableStateOf<CollabList?>(null) } var listToDelete by remember { mutableStateOf<CollabList?>(null) }
@@ -226,6 +242,7 @@ fun ListsScreen(
Box(modifier = Modifier.animateItemPlacement()) { Box(modifier = Modifier.animateItemPlacement()) {
ListItem( ListItem(
list = list, list = list,
nowMs = nowMs,
onListClick = { onNavigateToList(list.id) }, onListClick = { onNavigateToList(list.id) },
onEditClick = { listToEdit = list }, onEditClick = { listToEdit = list },
onDeleteClick = { listToDelete = list }, onDeleteClick = { listToDelete = list },
@@ -295,6 +312,7 @@ fun ListsScreen(
@Composable @Composable
fun ListItem( fun ListItem(
list: CollabList, list: CollabList,
nowMs: Long,
onListClick: () -> Unit, onListClick: () -> Unit,
onEditClick: () -> Unit, onEditClick: () -> Unit,
onDeleteClick: () -> Unit, onDeleteClick: () -> Unit,
@@ -323,6 +341,12 @@ fun ListItem(
) { ) {
Text(text = list.name, style = MaterialTheme.typography.titleMedium) Text(text = list.name, style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(2.dp)) Spacer(modifier = Modifier.height(2.dp))
val subtitle = remember(list.updatedAt, nowMs) { formatUpdatedAgo(list.updatedAt, nowMs) }
Text(
text = subtitle,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
} }
// Actions on the right // Actions on the right
@@ -451,3 +475,26 @@ private fun SortMenu(prefs: PreferencesManager) {
} }
} }
} }
// Format updatedAt relative to now: "Updated 5 sec/min/hour(s) ago" (days included when applicable)
private fun formatUpdatedAgo(updatedAt: Long, nowMs: Long): String {
val delta = (nowMs - updatedAt).coerceAtLeast(0L)
val seconds = delta / 1000
return when {
seconds < 60 -> "Updated ${seconds}s ago"
seconds < 3600 -> {
val minutes = seconds / 60
"Updated ${minutes}m ago"
}
seconds < 86_400 -> {
val hours = seconds / 3600
val unit = if (hours == 1L) "hour" else "hours"
"Updated ${hours} $unit ago"
}
else -> {
val days = seconds / 86_400
val unit = if (days == 1L) "day" else "days"
"Updated ${days} $unit ago"
}
}
}