Move SSD status formatting to typed Kotlin

ober

9c2455158194b8bc36e69c5b6829455b1fbcfe5b

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 58b0457..b07a160 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1187,14 +1187,24 @@
                 ImportBudget-expandedBytes ImportBudget-expandedBytes-set!
                 make-StorageStats StorageStats?
                 StorageStats-files StorageStats-files-set!
-                StorageStats-bytes StorageStats-bytes-set!)
+                StorageStats-bytes StorageStats-bytes-set!
+                storageSummaryText)
         (type Int32)
         (record ImportBudget
           ((mut entries : Int32)
            (mut expandedBytes : Int)))
         (record StorageStats
           ((mut files : Int32)
-           (mut bytes : Int)))))
+           (mut bytes : Int)))
+        (def (storageSummaryText (truthCount : Int32)
+                                 (eventCount : Int32)) : String
+          (string-append
+            (int32->string truthCount)
+            (string-append
+              " truth files, "
+              (string-append
+                (int32->string eventCount)
+                " event logs"))))))
 
     (typed-kotlin-file "com/sfb/ssdreview/BytesHex.kt"
       (typed-library (com sfb ssdreview)
@@ -3565,7 +3575,8 @@
                 boxTypeFallbackName boxTypeLabelMatches defaultBoxTypeLabel
                 isGenericGuessLabel isSsdPdfName
                 sourceBaseName canonicalSourceName isUsefulGuessLabel isErrorStatus
-                formatActivityDuration)
+                formatActivityDuration groupDisplayLabel appendModeStatus
+                selectedGroupStatus)
         (def (normalizeFiringArc (value : String)) : String
           (string-uppercase (string-trim value)))
         (def (normalizeLabel (value : String)) : String
@@ -3666,6 +3677,41 @@
                     (string-contains? lower "error"))
                 (or (string-contains? lower "exception")
                     (string-contains? lower "rejected")))))
+        (def (groupDisplayLabel (group : SsdGroup)) : String
+          (let ((label (SsdGroup-label group)))
+            (if (string-blank? label)
+              (SsdGroup-id group)
+              label)))
+        (def (appendModeStatus (group : SsdGroup)) : String
+          (string-append
+            "Append mode: drag boxes to add to "
+            (groupDisplayLabel group)))
+        (def (selectedGroupStatus (group : SsdGroup)) : String
+          (let ((arc
+                  (if (string-blank? (SsdGroup-firingArc group))
+                    ""
+                    (string-append ", arc " (SsdGroup-firingArc group))))
+                (label
+                  (if (string-blank? (SsdGroup-label group))
+                    "unlabeled"
+                    (SsdGroup-label group))))
+            (string-append
+              (SsdGroup-id group)
+              (string-append
+                ": "
+                (string-append
+                  label
+                  (string-append
+                    " ("
+                    (string-append
+                      (int32->string (SsdGroup-count group))
+                      (string-append
+                        " boxes"
+                        (string-append
+                          arc
+                          (string-append
+                            ", "
+                            (string-append (SsdGroup-status group) ")")))))))))))
         (def (formatActivityDuration (ms : Int)) : String
           (let ((safe (if (< ms (int 0)) (int 0) ms)))
             (if (< safe (int 1000))
@@ -4871,7 +4917,7 @@
 	       "        reviewView.snapSelectionToCells = true"
 	       "        reviewView.selectMode = true"
 	       "        reviewView.selectedGroupId = group.id"
-	       "        setStatus(\"Append mode: drag boxes to add to ${group.label.ifBlank { group.id }}\")"
+	       "        setStatus(appendModeStatus(group))"
 	       "    }"
 	       ""
 	       "    private fun startSsdAreaMode() {"
@@ -4946,8 +4992,7 @@
 	       "        reviewView.selectedGroupId = group.id"
 	       "        reviewView.centerOnGroup(group)"
 	       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)"
-       "        val arc = if (group.firingArc.isNotBlank()) \", arc ${group.firingArc}\" else \"\""
-       "        setStatus(\"${group.id}: ${group.label.ifBlank { \"unlabeled\" }} (${group.count} boxes$arc, ${group.status})\")"
+       "        setStatus(selectedGroupStatus(group))"
        "    }"
        ""
        "    private fun selectedGroup(): SsdGroup? {"
@@ -7458,7 +7503,7 @@
        "    fun storageSummary(): String {"
        "        val truthCount = groundTruthDir.listFiles { f -> f.name.endsWith(\".truth.json\") }?.size ?: 0"
        "        val eventCount = eventsDir.listFiles()?.size ?: 0"
-       "        return \"$truthCount truth files, $eventCount event logs\""
+       "        return storageSummaryText(truthCount, eventCount)"
        "    }"
        ""
        "    fun seedBundledTruthAsync(done: (Int) -> Unit) {"