Move SSD review feedback refreshes to typed Kotlin

ober

2a57a223b72ef9566381d07164459eea664aaae1

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index a0a1108..cda52de 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4661,6 +4661,9 @@
                 reviewViewClearDragPoints reviewViewClearInteractionDetails
                 reviewViewSetLastTouchPosition
                 reviewViewSetPointerPosition
+                reviewViewPerformHaptic
+                reviewViewPerformHapticAndInvalidate
+                reviewViewRefresh
                 mainActivitySelectGroupId
                 mainActivitySelectRequestedGroup
                 mainActivitySelectCurrentGroup
@@ -4800,6 +4803,12 @@
           (kotlin-member-call captureViewport))
         (extern (reviewViewRotateClockwise (view : SsdReviewView)) : Unit
           (kotlin-member-call rotateClockwise))
+        (extern (reviewViewPerformHapticFeedback
+                  (view : SsdReviewView)
+                  (feedbackConstant : Int32)) : Bool
+          (kotlin-member-call performHapticFeedback))
+        (extern (reviewViewInvalidate (view : SsdReviewView)) : Unit
+          (kotlin-member-call invalidate))
         (extern (reviewViewSelectedGroupIdSet (view : SsdReviewView)
                                               (id : (Nullable String))) : Unit
           (kotlin-member-set selectedGroupId))
@@ -5485,6 +5494,21 @@
           (begin
             (reviewViewPointerXSet view x)
             (reviewViewPointerYSet view y)))
+        (def (reviewViewPerformHaptic
+               (view : SsdReviewView)
+               (feedbackConstant : Int32)) : Unit
+          (begin
+            (reviewViewPerformHapticFeedback view feedbackConstant)
+            (begin)))
+        (def (reviewViewPerformHapticAndInvalidate
+               (view : SsdReviewView)
+               (feedbackConstant : Int32)) : Unit
+          (begin
+            (reviewViewPerformHapticFeedback view feedbackConstant)
+            (reviewViewInvalidate view)
+            (begin)))
+        (def (reviewViewRefresh (view : SsdReviewView)) : Unit
+          (reviewViewInvalidate view))
         (def (mainActivitySelectGroupId (activity : MainActivity)
                                         (view : SsdReviewView)
                                         (id : (Nullable String))) : Unit
@@ -7523,7 +7547,7 @@
 	       "    private fun startSsdAreaMode() {"
 	       "        if (sessionMissing(currentSession)) return"
 	       "        mainActivityStartSsdAreaInteractionForSelection(this, reviewView, selectedGroupId)"
-	       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)"
+	       "        reviewViewPerformHaptic(reviewView, HapticFeedbackConstants.CLOCK_TICK)"
 	       "        setStatus(\"SSD area mode: drag around the ship SSD; tags outside that area will be removed\")"
 	       "    }"
        ""
@@ -7566,8 +7590,7 @@
 	       "        mainActivitySelectGroupId(this, reviewView, ssdSessionSelectedGroupId(session, selectedGroupId))"
 	       "        reviewViewSetSsdAreaFromSession(reviewView, session)"
 	       "        truthStoreAppendSsdAreaSet(truthStore, session, details)"
-	       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
-	       "        reviewView.invalidate()"
+	       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
 	       "        saveSessionAsync("
 	       "            session,"
 	       "            \"SSD area set; saving boundary...\","
@@ -7582,7 +7605,7 @@
        "        if (ssdGroupMissing(group)) return"
        "        val selectedGroup = ssdGroupOrEmpty(group)"
 	       "        reviewView.centerOnGroup(selectedGroup)"
-	       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK)"
+	       "        reviewViewPerformHaptic(reviewView, HapticFeedbackConstants.CLOCK_TICK)"
        "        setStatus(selectedGroupStatus(selectedGroup))"
        "    }"
        ""
@@ -7613,8 +7636,7 @@
        "        finalizeGroupLabel(approvedGroup)"
        "        ssdSessionApproveGroup(session, approvedGroup)"
        "        truthStoreAppendGroupApproved(truthStore, session)"
-       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
-       "        reviewView.invalidate()"
+       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
        "        saveSessionAsync("
        "            session,"
        "            approveSavingStatus(approvedGroup),"
@@ -7779,7 +7801,7 @@
        "            runOnUiThread {"
        "                if (isStaleLoad(generation, uri, page)) return@runOnUiThread"
        "                mainActivityShowSession(this, reviewView, merged)"
-       "                reviewView.invalidate()"
+       "                reviewViewRefresh(reviewView)"
        "                setStatus(sessionCountsStatus(merged, \", pulled remote truth\"))"
        "                logDetectResult(\"remote-truth\", merged, \"remote-truth\")"
        "            }"
@@ -7940,8 +7962,7 @@
        "        val group = mainActivityAddApprovedAreaGroup(this, reviewView, session, rect, detectedIds, cleanLabel, resolvedBoxTypeIdOr(resolvedType, boxType), firingArc, count)"
        "        truthStoreAppendGroupApproved(truthStore, session)"
        "        finishSelectInteraction()"
-       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
-       "        reviewView.invalidate()"
+       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
        "        saveSessionAsync("
        "            session,"
        "            approveCountSavingStatus(group, group.count),"
@@ -7956,8 +7977,7 @@
        "        val added = mainActivityAppendAreaToGroup(this, reviewView, session, rect, detectedIds, group, count)"
        "        finishSelectInteraction()"
        "        truthStoreAppendGroupAppended(truthStore, session)"
-       "        reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
-       "        reviewView.invalidate()"
+       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
        "        saveSessionAsync("
        "            session,"
        "            appendSavingStatus(group, added),"
@@ -8021,8 +8041,7 @@
        "                count.text.toString()"
        "            )"
        "            truthStoreAppendGroupEdited(truthStore, session)"
-       "            reviewView.performHapticFeedback(HapticFeedbackConstants.CONFIRM)"
-       "            reviewView.invalidate()"
+       "            reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.CONFIRM)"
        "            saveSessionAsync("
        "                session,"
        "                editSavingStatus(group),"
@@ -8057,8 +8076,7 @@
        "        val deletedGroup = ssdGroupOrEmpty(group)"
        "        mainActivitySuppressGroupAsDeleted(this, reviewView, session, deletedGroup)"
        "        truthStoreAppendGroupDeleted(truthStore, session)"
-       "        reviewView.performHapticFeedback(HapticFeedbackConstants.REJECT)"
-       "        reviewView.invalidate()"
+       "        reviewViewPerformHapticAndInvalidate(reviewView, HapticFeedbackConstants.REJECT)"
        "        saveSessionAsync("
        "            session,"
        "            deleteSavingStatus(deletedGroup),"