Generate SSD activity action helpers from typed Jerboa

ober

72b5582fc597798c7a04527d541ed64690aa26f0

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 1877e50..7127ecf 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4881,6 +4881,14 @@
                 mainActivitySelectRelativeGroup
                 mainActivityFinalizeGroupLabel
                 mainActivityFocusBoxTypeDropdown
+                mainActivityChangePage
+                mainActivityStartAppendMode
+                mainActivityStartSsdAreaMode
+                mainActivityRotatePage
+                mainActivityApproveSelectedGroup
+                mainActivitySaveTruth
+                mainActivityDeleteGroup
+                mainActivityDeleteSelectedGroup
                 mainActivityAddApprovedAreaGroup
                 mainActivityAppendAreaToGroup
                 mainActivitySuppressGroupAsDeleted
@@ -5677,9 +5685,6 @@
                   (group : SsdGroup)
                   (count : Int32)) : Unit
           (kotlin-member-call appendAreaToGroup))
-        (extern (mainActivityDeleteSelectedGroupRaw
-                  (activity : MainActivity)) : Unit
-          (kotlin-member-call deleteSelectedGroup))
         (extern (mainActivitySaveSessionAsyncRaw
                   (activity : MainActivity)
                   (session : SsdSession)
@@ -6666,6 +6671,166 @@
               (alertDialogWindowOrNull dialog)
               softInputMode)
             (autoCompleteFocusAndShowDropdown dialog boxType)))
+        (def (mainActivitySaveSessionNoAfter
+               (activity : MainActivity)
+               (session : SsdSession)
+               (savingStatus : String)
+               (savedStatus : String)) : Unit
+          (mainActivitySaveSessionAsyncRaw
+            activity
+            session
+            savingStatus
+            savedStatus
+            (lambda ()
+              (begin))))
+        (def (mainActivityChangePage
+               (activity : MainActivity)
+               (uri : (Nullable Uri))
+               (pageCount : Int32)
+               (pageIndex : Int32)
+               (delta : Int32)) : Unit
+          (if (pageNavigationBlockedForUri uri pageCount)
+            (begin)
+            (begin
+              (mainActivitySetPageIndex
+                activity
+                (shiftPageIndex pageIndex pageCount delta))
+              (mainActivityPersistCurrentPdfStateRaw activity #f)
+              (mainActivityRenderCurrentPageRaw activity))))
+        (def (mainActivityStartAppendMode
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (session : (Nullable SsdSession))
+               (selectedGroupId : (Nullable String))) : Unit
+          (if (sessionMissing session)
+            (begin)
+            (let ((group
+                    (mainActivitySelectRequestedGroup
+                      activity
+                      view
+                      session
+                      selectedGroupId)))
+              (if (ssdGroupMissing group)
+                (begin
+                  (mainActivityClearInteractionModes activity view)
+                  (mainActivitySetStatusRaw
+                    activity
+                    (appendRequiresSelectedGroupStatus)))
+                (let ((appendGroup (ssdGroupOrEmpty group)))
+                  (begin
+                    (mainActivityStartAppendInteraction activity view)
+                    (mainActivitySetStatusRaw
+                      activity
+                      (appendModeStatus appendGroup))))))))
+        (def (mainActivityStartSsdAreaMode
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (session : (Nullable SsdSession))
+               (selectedGroupId : (Nullable String))
+               (feedbackConstant : Int32)) : Unit
+          (if (sessionMissing session)
+            (begin)
+            (begin
+              (mainActivityStartSsdAreaInteractionForSelection
+                activity
+                view
+                selectedGroupId)
+              (reviewViewPerformHaptic view feedbackConstant)
+              (mainActivitySetStatusRaw
+                activity
+                (ssdAreaModeInstructionStatus)))))
+        (def (mainActivityRotatePage
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (currentGeneration : Int32)
+               (session : (Nullable SsdSession))) : Unit
+          (begin
+            (mainActivityRotateReviewPage activity view currentGeneration)
+            (mainActivitySetStatusRaw activity (rotatedPageStatus session))))
+        (def (mainActivityApproveSelectedGroup
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (store : TruthStore)
+               (session : (Nullable SsdSession))
+               (selectedGroupId : (Nullable String))
+               (confirmHaptic : Int32)) : Unit
+          (if (sessionMissing session)
+            (begin)
+            (let ((loadedSession (ssdSessionOrEmpty session)))
+              (let ((group
+                      (mainActivitySelectedGroup
+                        activity
+                        view
+                        session
+                        selectedGroupId)))
+                (if (ssdGroupMissing group)
+                  (begin)
+                  (let ((approvedGroup (ssdGroupOrEmpty group)))
+                    (begin
+                      (mainActivityFinalizeGroupLabel activity approvedGroup)
+                      (ssdSessionApproveGroup loadedSession approvedGroup)
+                      (truthStoreAppendGroupApproved store loadedSession)
+                      (reviewViewPerformHapticAndInvalidate
+                        view
+                        confirmHaptic)
+                      (mainActivitySaveSessionNoAfter
+                        activity
+                        loadedSession
+                        (approveSavingStatus approvedGroup)
+                        (approveSavedStatus approvedGroup)))))))))
+        (def (mainActivitySaveTruth
+               (activity : MainActivity)
+               (store : TruthStore)
+               (session : (Nullable SsdSession))) : Unit
+          (if (sessionMissing session)
+            (begin)
+            (let ((loadedSession (ssdSessionOrEmpty session)))
+              (mainActivitySaveSessionNoAfter
+                activity
+                loadedSession
+                (saveTruthSavingStatus)
+                (saveTruthSavedStatus (truthStoreStorageSummary store))))))
+        (def (mainActivityDeleteGroup
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (store : TruthStore)
+               (session : SsdSession)
+               (group : SsdGroup)
+               (rejectHaptic : Int32)) : Unit
+          (begin
+            (mainActivitySuppressGroupAsDeleted activity view session group)
+            (truthStoreAppendGroupDeleted store session)
+            (reviewViewPerformHapticAndInvalidate view rejectHaptic)
+            (mainActivitySaveSessionNoAfter
+              activity
+              session
+              (deleteSavingStatus group)
+              (deleteSavedStatus group))))
+        (def (mainActivityDeleteSelectedGroup
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (store : TruthStore)
+               (session : (Nullable SsdSession))
+               (selectedGroupId : (Nullable String))
+               (rejectHaptic : Int32)) : Unit
+          (if (sessionMissing session)
+            (begin)
+            (let ((loadedSession (ssdSessionOrEmpty session)))
+              (let ((group
+                      (mainActivitySelectedGroup
+                        activity
+                        view
+                        session
+                        selectedGroupId)))
+                (if (ssdGroupMissing group)
+                  (begin)
+                  (mainActivityDeleteGroup
+                    activity
+                    view
+                    store
+                    loadedSession
+                    (ssdGroupOrEmpty group)
+                    rejectHaptic))))))
         (def (mainActivityAddApprovedAreaGroup
                (activity : MainActivity)
                (view : SsdReviewView)
@@ -8157,7 +8322,8 @@
                (count : EditText)
                (view : SsdReviewView)
                (truthStore : TruthStore)
-               (confirmHaptic : Int32)) : Unit
+               (confirmHaptic : Int32)
+               (rejectHaptic : Int32)) : Unit
           (begin
             (alertDialogSetPositiveButtonAction
               dialog
@@ -8206,7 +8372,13 @@
                   (autoCompleteDismissDropDown boxType)
                   (autoCompleteDismissDropDown firingArc)
                   (alertDialogDismiss dialog)
-                  (mainActivityDeleteSelectedGroupRaw activity))))))
+                  (mainActivityDeleteGroup
+                    activity
+                    view
+                    truthStore
+                    session
+                    group
+                    rejectHaptic))))))
         (def (permissionResultGranted (actual : Int32) (granted : Int32)) : Bool
           (= actual granted))
         (def (downloadAccessBeforeRuntimePermissions (beforeRuntimePermissions : Bool)) : Bool
@@ -10026,22 +10198,22 @@
        "            addView(actionRow("
 	       "                button(\"Open SSDs\", ButtonKind.PRIMARY) { openPdf() },"
 	       "                button(\"Detect\", ButtonKind.ACCENT) { detectCurrent(forceDetect = true) },"
-	       "                button(\"Set SSD Area\", ButtonKind.MODE) { startSsdAreaMode() },"
+	       "                button(\"Set SSD Area\", ButtonKind.MODE) { mainActivityStartSsdAreaMode(this@MainActivity, reviewView, currentSession, selectedGroupId, HapticFeedbackConstants.CLOCK_TICK) },"
 	       "            ))"
 	       "            addView(actionRow("
 	       "                button(\"Open Any\") { openAnyPdf() },"
-	       "                button(\"Rotate\") { rotatePage() },"
+	       "                button(\"Rotate\") { mainActivityRotatePage(this@MainActivity, reviewView, loadGeneration, currentSession) },"
 	       "                button(\"Fit\") { reviewViewFitImage(reviewView) },"
 	       "            ))"
 	       "            addView(actionRow("
-	       "                button(\"Prev Page\") { changePage(-1) },"
+	       "                button(\"Prev Page\") { mainActivityChangePage(this@MainActivity, pdfUri, pageCount, pageIndex, -1) },"
 	       "                button(\"Page #\") { showPageDialog() },"
-	       "                button(\"Next Page\") { changePage(1) },"
+	       "                button(\"Next Page\") { mainActivityChangePage(this@MainActivity, pdfUri, pageCount, pageIndex, 1) },"
 	       "            ))"
 	       "            addView(actionRow("
 	       "                button(\"Pan\", ButtonKind.NEUTRAL) { mainActivityApplySelectMode(this@MainActivity, reviewView, ssdAreaMode, appendMode, false) },"
 	       "                button(\"Select Area\", ButtonKind.PRIMARY) { mainActivityApplySelectMode(this@MainActivity, reviewView, ssdAreaMode, appendMode, true) },"
-	       "                button(\"Add\", ButtonKind.ACCENT) { startAppendMode() },"
+	       "                button(\"Add\", ButtonKind.ACCENT) { mainActivityStartAppendMode(this@MainActivity, reviewView, currentSession, selectedGroupId) },"
 	       "            ))"
 	       "            addView(actionRow("
 	       "                button(\"Prev\", ButtonKind.NAV) { mainActivitySelectRelativeGroup(this@MainActivity, reviewView, currentSession, selectedGroupId, -1, HapticFeedbackConstants.CLOCK_TICK) },"
@@ -10049,9 +10221,9 @@
 	       "                button(\"Edit\") { editSelectedGroup() },"
 	       "            ))"
 	       "            addView(actionRow("
-	       "                button(\"Approve\", ButtonKind.ACCENT) { approveSelectedGroup() },"
-	       "                button(\"Delete\", ButtonKind.DANGER) { deleteSelectedGroup() },"
-	       "                button(\"Save\") { saveTruth() },"
+	       "                button(\"Approve\", ButtonKind.ACCENT) { mainActivityApproveSelectedGroup(this@MainActivity, reviewView, truthStore, currentSession, selectedGroupId, HapticFeedbackConstants.CONFIRM) },"
+	       "                button(\"Delete\", ButtonKind.DANGER) { mainActivityDeleteSelectedGroup(this@MainActivity, reviewView, truthStore, currentSession, selectedGroupId, HapticFeedbackConstants.REJECT) },"
+	       "                button(\"Save\") { mainActivitySaveTruth(this@MainActivity, truthStore, currentSession) },"
 	       "            ))"
        "            addView(actionRow("
        "                button(\"Pull Truth\") { pullTruthDump() },"
@@ -10176,39 +10348,6 @@
        "        )"
        "    }"
        ""
-       "    private fun changePage(delta: Int) {"
-       "        if (pageNavigationBlockedForUri(pdfUri, pageCount)) return"
-       "        mainActivitySetPageIndex(this, shiftPageIndex(pageIndex, pageCount, delta))"
-       "        persistCurrentPdfState(includeViewport = false)"
-       "        renderCurrentPage()"
-       "    }"
-       ""
-       "    private fun startAppendMode() {"
-       "        if (sessionMissing(currentSession)) return"
-       "        val group = mainActivitySelectRequestedGroup(this, reviewView, currentSession, selectedGroupId)"
-       "        if (ssdGroupMissing(group)) {"
-       "            mainActivityClearInteractionModes(this, reviewView)"
-       "            setStatus(appendRequiresSelectedGroupStatus())"
-       "            return"
-	       "        }"
-	       "        val appendGroup = ssdGroupOrEmpty(group)"
-	       "        mainActivityStartAppendInteraction(this, reviewView)"
-	       "        setStatus(appendModeStatus(appendGroup))"
-	       "    }"
-	       ""
-	       "    private fun startSsdAreaMode() {"
-	       "        if (sessionMissing(currentSession)) return"
-	       "        mainActivityStartSsdAreaInteractionForSelection(this, reviewView, selectedGroupId)"
-	       "        reviewViewPerformHaptic(reviewView, HapticFeedbackConstants.CLOCK_TICK)"
-	       "        setStatus(ssdAreaModeInstructionStatus())"
-	       "    }"
-       ""
-       "    private fun rotatePage() {"
-       "        mainActivityRotateReviewPage(this, reviewView, loadGeneration)"
-       "        val session = currentSession"
-       "        setStatus(rotatedPageStatus(session))"
-       "    }"
-       ""
        "    private fun showPageDialog() {"
        "        if (pageNavigationBlockedForUri(pdfUri, pageCount)) return"
        "        val input = EditText(this).apply {"
@@ -10256,23 +10395,6 @@
        "        showGroupEditDialog(ssdGroupOrEmpty(group))"
        "    }"
        ""
-       "    private fun approveSelectedGroup() {"
-       "        if (sessionMissing(currentSession)) return"
-       "        val session = ssdSessionOrEmpty(currentSession)"
-       "        val group = mainActivitySelectedGroup(this, reviewView, currentSession, selectedGroupId)"
-       "        if (ssdGroupMissing(group)) return"
-       "        val approvedGroup = ssdGroupOrEmpty(group)"
-       "        mainActivityFinalizeGroupLabel(this, approvedGroup)"
-       "        ssdSessionApproveGroup(session, approvedGroup)"
-       "        truthStoreAppendGroupApproved(truthStore, session)"
-       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
-       "        saveSessionAsync("
-       "            session,"
-       "            approveSavingStatus(approvedGroup),"
-       "            approveSavedStatus(approvedGroup)"
-       "        )"
-       "    }"
-       ""
        "    internal fun renderCurrentPage() {"
        "        if (!pdfUriLoaded(pdfUri)) return"
        "        val uri = uriOrEmpty(pdfUri)"
@@ -10507,38 +10629,13 @@
        "            count,"
        "            reviewView,"
        "            truthStore,"
-       "            HapticFeedbackConstants.CONFIRM"
+       "            HapticFeedbackConstants.CONFIRM,"
+       "            HapticFeedbackConstants.REJECT"
        "        )"
        "        boxType.selectAll()"
        "        mainActivityFocusBoxTypeDropdown(dialog, boxType, resources.displayMetrics.heightPixels, android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)"
        "    }"
        ""
-       "    private fun saveTruth() {"
-       "        if (sessionMissing(currentSession)) return"
-       "        val session = ssdSessionOrEmpty(currentSession)"
-       "        saveSessionAsync("
-       "            session,"
-       "            saveTruthSavingStatus(),"
-       "            saveTruthSavedStatus(truthStoreStorageSummary(truthStore))"
-       "        )"
-       "    }"
-       ""
-       "    internal fun deleteSelectedGroup() {"
-       "        if (sessionMissing(currentSession)) return"
-       "        val session = ssdSessionOrEmpty(currentSession)"
-       "        val group = mainActivitySelectedGroup(this, reviewView, currentSession, selectedGroupId)"
-       "        if (ssdGroupMissing(group)) return"
-       "        val deletedGroup = ssdGroupOrEmpty(group)"
-       "        mainActivitySuppressGroupAsDeleted(this, reviewView, session, deletedGroup)"
-       "        truthStoreAppendGroupDeleted(truthStore, session)"
-       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.REJECT)"
-       "        saveSessionAsync("
-       "            session,"
-       "            deleteSavingStatus(deletedGroup),"
-       "            deleteSavedStatus(deletedGroup)"
-       "        )"
-       "    }"
-       ""
        "    private fun exportTruthZip() {"
        "        val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {"
        "            addCategory(Intent.CATEGORY_OPENABLE)"