Generate SSD save async flow from typed Jerboa

ober

9f31547645c4e29cb26b31155c8f38af16a520a8

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index dd57024..2a77b7f 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4843,6 +4843,7 @@
                 mainActivitySetPdfChoiceItems
                 mainActivityPullTruthDumpAsync
                 mainActivityPushTruthDumpAsync
+                mainActivitySaveTruthSnapshotAsync
                 mainActivityMergeRemoteTruthAsync
                 mainActivityRenderCurrentPageAsync
                 mainActivitySyncSelectedTreeAsync
@@ -7003,6 +7004,39 @@
                         readTimeoutMillis)
                       (catch (error : Exception)
                         (begin))))))))
+        (def (mainActivitySaveTruthSnapshotAsync
+               (activity : MainActivity)
+               (store : TruthStore)
+               (truth : JSONObject)
+               (viewport : (Nullable ViewportState))
+               (savedStatus : String)
+               (afterSaved : (-> Unit))) : Unit
+          (runBackground
+            (lambda ()
+              (try
+                (begin
+                  (truthStoreSaveSnapshot store truth)
+                  (mainActivityRunOnUiThreadRaw
+                    activity
+                    (lambda ()
+                      (begin
+                        (mainActivityRestoreViewportAfterLayoutRaw
+                          activity
+                          viewport)
+                        (mainActivitySetStatusRaw activity savedStatus)
+                        (invoke afterSaved)))))
+                (catch (error : Exception)
+                  (mainActivityRunOnUiThreadRaw
+                    activity
+                    (lambda ()
+                      (begin
+                        (mainActivityRestoreViewportAfterLayoutRaw
+                          activity
+                          viewport)
+                        (mainActivitySetStatusRaw
+                          activity
+                          (saveFailedStatus
+                            (exceptionMessageRaw error)))))))))))
         (def (mainActivitySetPdfChoiceItems
                (builder : Builder)
                (activity : MainActivity)
@@ -9857,21 +9891,7 @@
        "        finishSelectInteraction()"
        "        restoreViewportAfterLayout(viewport)"
        "        setStatus(savingStatus)"
-       "        thread(name = \"sfb-truth-save\") {"
-       "            try {"
-       "                truthStoreSaveSnapshot(truthStore, truth)"
-       "                runOnUiThread {"
-       "                    restoreViewportAfterLayout(viewport)"
-       "                    setStatus(savedStatus)"
-       "                    afterSaved()"
-       "                }"
-       "            } catch (error: Exception) {"
-       "                runOnUiThread {"
-       "                    restoreViewportAfterLayout(viewport)"
-       "                    setStatus(saveFailedStatus(error.message))"
-       "                }"
-       "            }"
-       "        }"
+       "        mainActivitySaveTruthSnapshotAsync(this, truthStore, truth, viewport, savedStatus, afterSaved)"
        "    }"
        ""
        "    internal fun approveArea("