Move SSD area group mutations to typed Kotlin

ober

19cde10fa7960906743776b3a90cd338e922a6c2

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 7e83a5f..7e6f08e 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -572,7 +572,8 @@
                 ssdSessionStoreSsdArea ssdSessionSsdAreaOutsideCount
                 ssdSessionSetSsdArea ssdSessionPruneGroupsOutsideSsdArea
                 createManualCells selectedOrManualCellIds
-                copyStringIds ssdSessionNextCellId ssdSessionNextGroupId
+                copyStringIds copyMutableStringIds
+                ssdSessionNextCellId ssdSessionNextGroupId
                 bboxForMutableCells)
         (type Int32)
         (type FloatArray)
@@ -832,6 +833,12 @@
             (begin
               (mutable-list-add! out (list-ref ids i))
               out)))
+        (def (copyMutableStringIds (ids : (MutableList String))) : (MutableList String)
+          (for/fold ((out (mutable-list-empty String)))
+                    ((i (in-range (int32 0) (list-size ids))))
+            (begin
+              (mutable-list-add! out (list-ref ids i))
+              out)))
         (def (selectedOrManualCellIds (session : SsdSession)
                                       (rect : FloatArray)
                                       (detectedIds : (List String))
@@ -994,7 +1001,7 @@
                     ((i (in-range (int32 0) (list-size (SsdGroup-cellIds group)))))
             (or found (equal? (list-ref (SsdGroup-cellIds group) i) id))))
         (def (appendUniqueCellIdsToGroup (group : SsdGroup)
-                                         (ids : (List String))) : Int32
+                                         (ids : (MutableList String))) : Int32
           (for/fold ((added (int32 0)))
                     ((i (in-range (int32 0) (list-size ids))))
             (let ((id (list-ref ids i)))
@@ -1044,7 +1051,7 @@
             (ssdSessionRecomputeGroup session group)))
         (def (ssdSessionAppendAreaToGroup (session : SsdSession)
                                           (group : SsdGroup)
-                                          (ids : (List String))) : Int32
+                                          (ids : (MutableList String))) : Int32
           (let ((added (appendUniqueCellIdsToGroup group ids)))
             (begin
               (ssdSessionRecomputeGroup session group)
@@ -4657,6 +4664,8 @@
                 mainActivitySelectGroupId
                 mainActivitySelectRequestedGroup
                 mainActivitySelectCurrentGroup
+                mainActivityAddApprovedAreaGroup
+                mainActivityAppendAreaToGroup
                 mainActivityClearSession
                 mainActivityShowSession mainActivitySetAppendMode
                 mainActivitySetSsdAreaMode mainActivityClearInteractionModes
@@ -5303,11 +5312,11 @@
         (def (editedGroupCountText (text : String) (fallback : Int32)) : Int32
           (parsedCountOrFallback text fallback))
         (def (ssdSessionAddApprovedAreaGroup (session : SsdSession)
-                                             (ids : (List String))
+                                             (ids : (MutableList String))
                                              (label : String)
                                              (boxTypeId : String)
                                              (firingArcText : String)) : SsdGroup
-          (let ((groupIds (copyStringIds ids)))
+          (let ((groupIds (copyMutableStringIds ids)))
             (let ((group
                     (make-SsdGroup
                       (ssdSessionNextGroupId session)
@@ -5492,6 +5501,45 @@
                   view
                   (nullable-some (SsdGroup-id (nullable-get group))))
                 group))))
+        (def (mainActivityAddApprovedAreaGroup
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (session : SsdSession)
+               (rect : FloatArray)
+               (detectedIds : (List String))
+               (label : String)
+               (boxTypeId : String)
+               (firingArc : String)
+               (count : Int32)) : SsdGroup
+          (let ((ids (selectedOrManualCellIds session rect detectedIds count)))
+            (let ((group (ssdSessionAddApprovedAreaGroup
+                           session
+                           ids
+                           label
+                           boxTypeId
+                           firingArc)))
+              (begin
+                (mainActivitySelectGroupId
+                  activity
+                  view
+                  (nullable-some (SsdGroup-id group)))
+                group))))
+        (def (mainActivityAppendAreaToGroup
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (session : SsdSession)
+               (rect : FloatArray)
+               (detectedIds : (List String))
+               (group : SsdGroup)
+               (count : Int32)) : Int32
+          (let ((ids (selectedOrManualCellIds session rect detectedIds count)))
+            (let ((added (ssdSessionAppendAreaToGroup session group ids)))
+              (begin
+                (mainActivitySelectGroupId
+                  activity
+                  view
+                  (nullable-some (SsdGroup-id group)))
+                added))))
         (def (mainActivityClearSession (activity : MainActivity)
                                        (view : SsdReviewView)) : Unit
           (begin
@@ -7824,17 +7872,15 @@
        "        val session = ssdSessionOrEmpty(currentSession)"
        "        val resolvedType = BoxTypes.resolve(this, boxType)"
        "        val cleanLabel = manualGroupLabel(resolvedLabelForBoxTypeAndroid(this, label, boxType, \"\"), resolvedBoxTypeNameOr(resolvedType, \"\"), \"\")"
-       "        val ids = selectedOrManualCellIds(session, rect, detectedIds, count)"
-       "        val group = ssdSessionAddApprovedAreaGroup(session, ids, cleanLabel, resolvedBoxTypeIdOr(resolvedType, boxType), firingArc)"
+       "        val group = mainActivityAddApprovedAreaGroup(this, reviewView, session, rect, detectedIds, cleanLabel, resolvedBoxTypeIdOr(resolvedType, boxType), firingArc, count)"
        "        truthStore.appendEvent(\"group_approved\", session)"
-       "        mainActivitySelectGroupId(this, reviewView, group.id)"
        "        finishSelectInteraction()"
        "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
        "        reviewView.invalidate()"
        "        saveSessionAsync("
        "            session,"
-       "            approveCountSavingStatus(group, ids.size),"
-       "            approveCountSavedStatus(group, ids.size)"
+       "            approveCountSavingStatus(group, group.count),"
+       "            approveCountSavedStatus(group, group.count)"
        "        )"
        "    }"
        ""
@@ -7842,10 +7888,8 @@
        "        if (sessionMissing(currentSession)) return"
        "        val session = ssdSessionOrEmpty(currentSession)"
        "        if (ssdSessionGroupMissing(session, group)) return"
-       "        val ids = selectedOrManualCellIds(session, rect, detectedIds, count)"
-       "        val added = ssdSessionAppendAreaToGroup(session, group, ids)"
+       "        val added = mainActivityAppendAreaToGroup(this, reviewView, session, rect, detectedIds, group, count)"
        "        finishSelectInteraction()"
-       "        mainActivitySelectGroupId(this, reviewView, group.id)"
        "        truthStore.appendEvent(\"group_appended\", session)"
        "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
        "        reviewView.invalidate()"