diff --git a/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt b/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt index ac40eb2..d0e8d4c 100644 --- a/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt +++ b/feature/deck/src/main/java/ru/forbion/f7cloud/feature/deck/DeckScreen.kt @@ -362,7 +362,9 @@ private fun DeckCardRow(card: DeckCard, onClick: () -> Unit, onToggleDone: () -> ) } val due = card.duedate?.let { formatDeckDue(it) } - if (due != null || card.assignees.isNotEmpty() || card.commentsCount > 0) { + val (checked, total) = deckChecklistCounts(card.description) + val hasMeta = listOf(due != null, total > 0, card.commentsCount > 0, card.assignees.isNotEmpty()) + if (hasMeta.any { it }) { Row( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), @@ -371,6 +373,10 @@ private fun DeckCardRow(card: DeckCard, onClick: () -> Unit, onToggleDone: () -> if (due != null) { Text("🗓 $due", style = MaterialTheme.typography.labelMedium, color = F7Colors.TextSecondary) } + if (total > 0) { + val todo = "☑ $checked/$total" + Text(todo, style = MaterialTheme.typography.labelMedium, color = F7Colors.TextSecondary) + } if (card.commentsCount > 0) { val comments = "💬 ${card.commentsCount}" Text(comments, style = MaterialTheme.typography.labelMedium, color = F7Colors.TextSecondary) @@ -403,6 +409,17 @@ internal fun DeckLabelChip(label: DeckLabel) { } } +private val deckChecklistRe = Regex("(?im)^\\s*([*+-]|\\d\\.)\\s+\\[\\s*(\\s|[xX])\\s*\\].*$") +private val deckCheckedRe = Regex("(?im)^\\s*([*+-]|\\d\\.)\\s+\\[\\s*[xX]\\s*\\].*$") + +/** Чек-пункты из описания карточки (как веб CardBadges): (отмечено, всего). */ +internal fun deckChecklistCounts(description: String): Pair { + if (description.isBlank()) return 0 to 0 + val total = deckChecklistRe.findAll(description).count() + val checked = deckCheckedRe.findAll(description).count() + return checked to total +} + /** Цвет Deck («RRGGBB» без #, иногда с #). */ internal fun parseDeckColor(hex: String?): Color? { val h = hex?.trim()?.removePrefix("#")?.takeIf { it.length == 6 } ?: return null