Preserve typed SSD state across configuration changes

ober

bb8ac800ba163fdc4f15e440c4d062abd07d08b0

diff --git a/templates/ssd-review-parts/MainActivity.ss b/templates/ssd-review-parts/MainActivity.ss
index c7b0ca1..44c7205 100644
--- a/templates/ssd-review-parts/MainActivity.ss
+++ b/templates/ssd-review-parts/MainActivity.ss
@@ -4,10 +4,12 @@
      '((typed-kotlin-file
          "com/sfb/ssdreview/MainActivity.kt"
          (kotlin-imports (android app Activity) (android content Intent)
+           (android content res Configuration)
            (android graphics Bitmap) (android net Uri)
            (android os Bundle) (android widget TextView))
          (typed-library (com sfb ssdreview) (export MainActivity)
           (type Activity) (type Bitmap) (type BoxType) (type Bundle)
+          (type Configuration)
           (type Int32) (type IntArray) (type Intent)
           (type SfbAiReportClient) (type SfbServerClient)
           (type SsdSelfTestMode)
@@ -30,6 +32,12 @@
             Unit
             (kotlin-call super onPause))
           (extern
+            (mainActivitySuperOnConfigurationChanged
+              (configuration : Configuration))
+            :
+            Unit
+            (kotlin-call super onConfigurationChanged))
+          (extern
             (mainActivitySuperOnActivityResult
               (requestCode : Int32)
               (resultCode : Int32)
@@ -111,6 +119,15 @@
                 (begin
                   (mainActivitySuperOnPause)
                   (mainActivityOnPause this)))
+           (def (onConfigurationChanged
+                  (configuration : Configuration))
+                :
+                Unit
+                (modifiers override)
+                (kotlin-name onConfigurationChanged)
+                (begin
+                  (mainActivitySuperOnConfigurationChanged configuration)
+                  (mainActivityOnConfigurationChanged this)))
            (def (onActivityResult
                   (requestCode : Int32)
                   (resultCode : Int32)
diff --git a/templates/ssd-review-parts/MainActivityLifecycle.ss b/templates/ssd-review-parts/MainActivityLifecycle.ss
index 6aebfdd..97e0633 100644
--- a/templates/ssd-review-parts/MainActivityLifecycle.ss
+++ b/templates/ssd-review-parts/MainActivityLifecycle.ss
@@ -11,9 +11,11 @@
          (typed-library (com sfb ssdreview)
           (export mainActivityOnCreate mainActivityOnResume
             mainActivityOnPause mainActivityOnActivityResult
-            mainActivityOnReadStoragePermissionResult)
+            mainActivityOnReadStoragePermissionResult
+            mainActivityOnConfigurationChanged)
           (type Intent) (type Int32) (type LinearLayout)
-          (type MainActivity) (type JSONObject) (type TruthStore)
+          (type MainActivity) (type JSONObject) (type SsdReviewView)
+          (type TruthStore) (type ViewportState)
           (extern
             (mainLifecycleTruthStore (activity : MainActivity))
             :
@@ -150,6 +152,40 @@
             Unit
             (kotlin-call mainAiOnResume))
           (extern
+            (mainLifecycleReviewView (activity : MainActivity))
+            :
+            SsdReviewView
+            (kotlin-member-get reviewView))
+          (extern
+            (mainLifecycleCaptureViewport (view : SsdReviewView))
+            :
+            (Nullable ViewportState)
+            (kotlin-member-call captureViewport))
+          (extern
+            (mainLifecycleRestoreViewport
+              (view : SsdReviewView)
+              (viewport : (Nullable ViewportState)))
+            :
+            Unit
+            (kotlin-member-call restoreViewport))
+          (extern
+            (mainLifecycleInvalidate (view : SsdReviewView))
+            :
+            Unit
+            (kotlin-member-call invalidate))
+          (extern
+            (mainLifecycleViewPost
+              (view : SsdReviewView)
+              (action : (-> Unit)))
+            :
+            Unit
+            (kotlin-member-call post))
+          (extern
+            (mainLifecycleLoadGeneration (activity : MainActivity))
+            :
+            Int32
+            (kotlin-member-get loadGeneration))
+          (extern
             (mainLifecycleSelfTestInitialize (activity : MainActivity))
             :
             Unit
@@ -231,6 +267,24 @@
                :
                Unit
                (mainActivityPersistCurrentPdfState activity #t))
+          (def (mainActivityOnConfigurationChanged (activity : MainActivity))
+               :
+               Unit
+               (let ([view (mainLifecycleReviewView activity)])
+                 (let ([viewport (mainLifecycleCaptureViewport view)]
+                       [fields (json-object-empty)])
+                   (begin
+                     (mainLifecycleViewPost
+                       view
+                       (lambda ()
+                         (begin
+                           (mainLifecycleRestoreViewport view viewport)
+                           (mainLifecycleInvalidate view))))
+                     (json-object-put-bool! fields "pipeline_active" #f)
+                     (json-object-put-int32! fields "generation"
+                       (mainLifecycleLoadGeneration activity))
+                     (mainActivityLogClientEvent activity
+                       "ssd-config-changed" fields)))))
           (def (mainActivityOnActivityResult
                  (activity : MainActivity)
                  (requestCode : Int32)
diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 17bfdfd..7c8fbdf 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1,7 +1,8 @@
 (import (jerboa prelude))
 
 (def fragment
-     '((include-fragment "ssd-review-parts/BoxType.ss")
+     '((activity-config-changes "keyboardHidden|orientation|screenSize")
+       (include-fragment "ssd-review-parts/BoxType.ss")
        (include-fragment "ssd-review-parts/BoxTypeResolve.ss")
        (include-fragment "ssd-review-parts/BoxTypeCsv.ss")
        (include-fragment "ssd-review-parts/OcrWord.ss")