feat(deck): бейдж чек-пунктов «☑ x/total» на карточке (P1 diff — CardBadges)
deckChecklistCounts парсит чекбоксы описания (regex как веб). Green compile+detekt.
This commit is contained in:
@@ -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<Int, Int> {
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user