diff --git a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanEventFormatter.kt b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanEventFormatter.kt index 6aaf5164..0a90454e 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanEventFormatter.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanEventFormatter.kt @@ -6,9 +6,33 @@ import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive +enum class KanbanEventMessage { + CREATED, + CREATED_BY, + MOVED, + ASSIGNED, + UNASSIGNED, + COMMENTED, + CLAIMED_REVIEW, + CLAIMED_WORKER, + WORKER_STARTED, + COMPLETED, + BLOCKED, + UNBLOCKED, + RECLAIMED, + SPECIFIED, + PROMOTED, + SCHEDULED, + ARCHIVED, + PRIORITY, + UNKNOWN, +} + data class FormattedKanbanEvent( val label: String, val detail: String? = null, + val message: KanbanEventMessage = KanbanEventMessage.UNKNOWN, + val arguments: List = emptyList(), ) object KanbanEventFormatter { @@ -51,7 +75,11 @@ object KanbanEventFormatter { val status = col("status") ?: "Todo" val assignee = str("assignee") val label = if (assignee != null) "Created in $status by $assignee" else "Created in $status" - FormattedKanbanEvent(label = label) + FormattedKanbanEvent( + label = label, + message = if (assignee != null) KanbanEventMessage.CREATED_BY else KanbanEventMessage.CREATED, + arguments = listOfNotNull(status, assignee), + ) } "status" -> { @@ -66,6 +94,8 @@ object KanbanEventFormatter { FormattedKanbanEvent( label = "Moved to $targetStatus", detail = detail, + message = KanbanEventMessage.MOVED, + arguments = listOf(targetStatus), ) } @@ -73,18 +103,32 @@ object KanbanEventFormatter { val assignee = str("assignee") FormattedKanbanEvent( label = if (assignee != null) "Assigned to $assignee" else "Unassigned", + message = if (assignee != null) KanbanEventMessage.ASSIGNED else KanbanEventMessage.UNASSIGNED, + arguments = listOfNotNull(assignee), ) } "commented" -> { val author = str("author") ?: "someone" - FormattedKanbanEvent(label = "Comment by $author") + FormattedKanbanEvent( + label = "Comment by $author", + message = KanbanEventMessage.COMMENTED, + arguments = listOf(author), + ) } "claimed" -> { val source = str("source_status") FormattedKanbanEvent( label = if (source == "review") "Claimed for review" else "Claimed by worker", + message = + if (source == + "review" + ) { + KanbanEventMessage.CLAIMED_REVIEW + } else { + KanbanEventMessage.CLAIMED_WORKER + }, ) } @@ -93,49 +137,59 @@ object KanbanEventFormatter { FormattedKanbanEvent( label = "Worker started", detail = if (pid != null && pid != "null") "PID $pid" else null, + message = KanbanEventMessage.WORKER_STARTED, + arguments = listOfNotNull(pid?.takeIf { it != "null" }), ) } "completed" -> { - FormattedKanbanEvent(label = "Completed") + FormattedKanbanEvent(label = "Completed", message = KanbanEventMessage.COMPLETED) } "blocked" -> { val reason = str("reason") - FormattedKanbanEvent(label = "Blocked", detail = reason) + FormattedKanbanEvent(label = "Blocked", detail = reason, message = KanbanEventMessage.BLOCKED) } "unblocked" -> { val status = col("status") val label = if (status != null) "Unblocked ($status)" else "Unblocked" - FormattedKanbanEvent(label = label) + FormattedKanbanEvent( + label = label, + message = KanbanEventMessage.UNBLOCKED, + arguments = listOfNotNull(status), + ) } "reclaimed" -> { val reason = str("reason") - FormattedKanbanEvent(label = "Reclaimed", detail = reason) + FormattedKanbanEvent(label = "Reclaimed", detail = reason, message = KanbanEventMessage.RECLAIMED) } "specified" -> { - FormattedKanbanEvent(label = "Specified") + FormattedKanbanEvent(label = "Specified", message = KanbanEventMessage.SPECIFIED) } "promoted" -> { - FormattedKanbanEvent(label = "Promoted to ready") + FormattedKanbanEvent(label = "Promoted to ready", message = KanbanEventMessage.PROMOTED) } "scheduled" -> { val reason = str("reason") - FormattedKanbanEvent(label = "Scheduled", detail = reason) + FormattedKanbanEvent(label = "Scheduled", detail = reason, message = KanbanEventMessage.SCHEDULED) } "archived" -> { - FormattedKanbanEvent(label = "Archived") + FormattedKanbanEvent(label = "Archived", message = KanbanEventMessage.ARCHIVED) } "reprioritized" -> { val priority = str("priority") ?: payloadMap["priority"]?.toString() ?: "?" - FormattedKanbanEvent(label = "Priority set to $priority") + FormattedKanbanEvent( + label = "Priority set to $priority", + message = KanbanEventMessage.PRIORITY, + arguments = listOf(priority), + ) } else -> { diff --git a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanTaskScreen.kt b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanTaskScreen.kt index b972a14f..228ad295 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanTaskScreen.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/kanban/KanbanTaskScreen.kt @@ -882,6 +882,94 @@ private fun TaskRunsTab( } } +@Composable +private fun localizedKanbanEventLabel(event: FormattedKanbanEvent): String = + when (event.message) { + KanbanEventMessage.CREATED -> { + stringResource(R.string.kanban_event_created, event.arguments.getOrElse(0) { "Todo" }) + } + + KanbanEventMessage.CREATED_BY -> { + stringResource( + R.string.kanban_event_created_by, + event.arguments.getOrElse(0) { "Todo" }, + event.arguments.getOrElse(1) { "" }, + ) + } + + KanbanEventMessage.MOVED -> { + stringResource(R.string.kanban_event_moved, event.arguments.getOrElse(0) { "?" }) + } + + KanbanEventMessage.ASSIGNED -> { + stringResource(R.string.kanban_event_assigned, event.arguments.getOrElse(0) { "" }) + } + + KanbanEventMessage.UNASSIGNED -> { + stringResource(R.string.kanban_event_unassigned) + } + + KanbanEventMessage.COMMENTED -> { + stringResource(R.string.kanban_event_commented, event.arguments.getOrElse(0) { "someone" }) + } + + KanbanEventMessage.CLAIMED_REVIEW -> { + stringResource(R.string.kanban_event_claimed_review) + } + + KanbanEventMessage.CLAIMED_WORKER -> { + stringResource(R.string.kanban_event_claimed_worker) + } + + KanbanEventMessage.WORKER_STARTED -> { + stringResource(R.string.kanban_event_worker_started) + } + + KanbanEventMessage.COMPLETED -> { + stringResource(R.string.kanban_event_completed) + } + + KanbanEventMessage.BLOCKED -> { + stringResource(R.string.kanban_event_blocked) + } + + KanbanEventMessage.UNBLOCKED -> { + if (event.arguments.isEmpty()) { + stringResource(R.string.kanban_event_unblocked) + } else { + stringResource(R.string.kanban_event_unblocked_to, event.arguments[0]) + } + } + + KanbanEventMessage.RECLAIMED -> { + stringResource(R.string.kanban_event_reclaimed) + } + + KanbanEventMessage.SPECIFIED -> { + stringResource(R.string.kanban_event_specified) + } + + KanbanEventMessage.PROMOTED -> { + stringResource(R.string.kanban_event_promoted) + } + + KanbanEventMessage.SCHEDULED -> { + stringResource(R.string.kanban_event_scheduled) + } + + KanbanEventMessage.ARCHIVED -> { + stringResource(R.string.kanban_event_archived) + } + + KanbanEventMessage.PRIORITY -> { + stringResource(R.string.kanban_event_priority, event.arguments.getOrElse(0) { "?" }) + } + + KanbanEventMessage.UNKNOWN -> { + event.label + } + } + @Composable private fun TaskActivityTab( events: List, @@ -920,7 +1008,7 @@ private fun TaskActivityTab( Spacer(modifier = Modifier.width(10.dp)) Column(modifier = Modifier.weight(1f)) { Text( - text = formatted.label, + text = localizedKanbanEventLabel(formatted), style = MaterialTheme.typography.bodySmall, fontWeight = FontWeight.SemiBold, ) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 64f7abeb..bf4e4366 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -432,6 +432,25 @@ عوامل التصفية تأكيد الإجراء تعديل الوصف + أُنشئت في %1$s + أُنشئت في %1$s بواسطة %2$s + نُقلت إلى %1$s + عُيّنت إلى %1$s + غير معيّنة + تعليق بواسطة %1$s + تمت المطالبة للمراجعة + تمت المطالبة بواسطة العامل + بدأ العامل + مكتملة + محظورة + أزيل حظرها + أزيل حظرها (%1$s) + تمت الاستعادة + تم التحديد + تمت الترقية إلى جاهزة + مجدولة + مؤرشفة + تم ضبط الأولوية على %1$s مؤقت (افتراضي) شجرة عمل مجلد diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index c0b78d96..d9743130 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -430,6 +430,25 @@ 필터 작업 확인 설명 편집 + %1$s에서 생성됨 + %1$s에서 %2$s가 생성함 + %1$s로 이동됨 + %1$s에게 할당됨 + 미지정 + %1$s의 댓글 + 검토를 위해 할당됨 + 워커가 할당함 + 워커 시작됨 + 완료됨 + 차단됨 + 차단 해제됨 + 차단 해제됨 (%1$s) + 회수됨 + 지정됨 + 준비 상태로 승격됨 + 예약됨 + 보관됨 + 우선순위가 %1$s로 설정됨 임시 (기본값) 작업 트리 디렉터리 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 116b4a8d..6a5b472b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -431,6 +431,25 @@ 筛选 确认操作 编辑描述 + 创建于 %1$s + 由 %2$s 创建于 %1$s + 移动到 %1$s + 分配给 %1$s + 未分配 + %1$s 的评论 + 已领取进行审核 + 已由工作器领取 + 工作器已启动 + 已完成 + 已阻塞 + 已解除阻塞 + 已解除阻塞(%1$s) + 已回收 + 已指定 + 已提升为就绪 + 已计划 + 已归档 + 优先级设置为 %1$s 临时(默认) 工作树 目录 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47e97456..e5873dc0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -467,6 +467,25 @@ Filters Confirm action Edit Description + Created in %1$s + Created in %1$s by %2$s + Moved to %1$s + Assigned to %1$s + Unassigned + Comment by %1$s + Claimed for review + Claimed by worker + Worker started + Completed + Blocked + Unblocked + Unblocked (%1$s) + Reclaimed + Specified + Promoted to ready + Scheduled + Archived + Priority set to %1$s Scratch (Default) Worktree Dir