feat: implement periodic refresh for "Updated ... ago" labels in ListsScreen
This commit is contained in:
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user