Generate SSD approve dialog from typed Jerboa

ober

a654dedab1c2b5527d3323eaff167240d599681c

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 77132f3..93a7382 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4767,6 +4767,7 @@
                       (android content ContentUris)
                       (android content ContentResolver)
                       (android content Context)
+                      (android content res Resources)
                       (android content DialogInterface)
                       (android graphics Bitmap)
                       (android content Intent)
@@ -4789,6 +4790,7 @@
                       (android widget LinearLayout LayoutParams)
                       (android widget TextView)
                       (android widget Toast)
+                      (android util DisplayMetrics)
                       (androidx documentfile provider DocumentFile)
                       (org json JSONObject))
       (typed-library (com sfb ssdreview)
@@ -4893,6 +4895,7 @@
                 mainActivitySaveTruth
                 mainActivityDeleteGroup
                 mainActivityDeleteSelectedGroup
+                mainActivityShowApproveDialog
                 mainActivityApproveArea
                 mainActivityAppendAreaToGroupAction
                 mainActivityShowAppendDialog
@@ -5021,6 +5024,7 @@
         (type Thread)
         (type AlertDialog)
         (type Builder)
+        (type Resources)
         (type AdapterView)
         (type ArrayAdapter)
         (type AutoCompleteTextView)
@@ -5043,6 +5047,7 @@
         (type ParcelFileDescriptor)
         (type View)
         (type Window)
+        (type DisplayMetrics)
         (type GradientDrawable)
         (type DocumentFile)
         (type NativeDetection)
@@ -5192,6 +5197,10 @@
                   (builder : Builder)
                   (view : EditText)) : Builder
           (kotlin-member-call setView))
+        (extern (alertDialogBuilderSetLinearLayoutViewRaw
+                  (builder : Builder)
+                  (view : LinearLayout)) : Builder
+          (kotlin-member-call setView))
         (extern (alertDialogBuilderShowRaw
                   (builder : Builder)) : AlertDialog
           (kotlin-member-call show))
@@ -5388,6 +5397,34 @@
                   (layout : LinearLayout)
                   (gravity : Int32)) : Unit
           (kotlin-member-set gravity))
+        (extern (linearLayoutSetPaddingRaw
+                  (layout : LinearLayout)
+                  (left : Int32)
+                  (top : Int32)
+                  (right : Int32)
+                  (bottom : Int32)) : Unit
+          (kotlin-member-call setPadding))
+        (extern (linearLayoutAddEditTextViewRaw
+                  (layout : LinearLayout)
+                  (view : EditText)) : Unit
+          (kotlin-member-call addView))
+        (extern (linearLayoutAddAutoCompleteViewRaw
+                  (layout : LinearLayout)
+                  (view : AutoCompleteTextView)) : Unit
+          (kotlin-member-call addView))
+        (extern (mainActivityResourcesRaw
+                  (activity : MainActivity)) : Resources
+          (kotlin-member-get resources))
+        (extern (resourcesDisplayMetricsRaw
+                  (resources : Resources)) : DisplayMetrics
+          (kotlin-member-get displayMetrics))
+        (extern (displayMetricsHeightPixelsRaw
+                  (metrics : DisplayMetrics)) : Int32
+          (kotlin-member-get heightPixels))
+        (extern (softInputAdjustResize) : Int32
+          (kotlin-value android view WindowManager LayoutParams SOFT_INPUT_ADJUST_RESIZE))
+        (extern (softInputStateAlwaysVisible) : Int32
+          (kotlin-value android view WindowManager LayoutParams SOFT_INPUT_STATE_ALWAYS_VISIBLE))
         (extern (buttonArrayAsList
                   (buttons : (Array Button))) : (List Button)
           (kotlin-member-call asList))
@@ -5772,6 +5809,12 @@
         (extern (mainActivitySelectedGroupIdRaw
                   (activity : MainActivity)) : (Nullable String)
           (kotlin-member-get selectedGroupId))
+        (extern (mainActivityAppendModeRaw
+                  (activity : MainActivity)) : Bool
+          (kotlin-member-get appendMode))
+        (extern (mainActivityBoxTypeDisplaysRaw
+                  (activity : MainActivity)) : (List String)
+          (kotlin-member-get boxTypeDisplays))
         (extern (mainActivityRunOnUiThreadRaw
                   (activity : MainActivity)
                   (callback : (-> Unit))) : Unit
@@ -5783,11 +5826,6 @@
         (extern (mainActivityRenderCurrentPageRaw
                   (activity : MainActivity)) : Unit
           (kotlin-member-call renderCurrentPage))
-        (extern (mainActivityShowApproveDialogRaw
-                  (activity : MainActivity)
-                  (rect : FloatArray)
-                  (detectedIds : (List String))) : Unit
-          (kotlin-member-call showApproveDialog))
         (extern (mainActivityOpenAnyPdfRaw
                   (activity : MainActivity)) : Unit
           (kotlin-member-call openAnyPdf))
@@ -7169,6 +7207,93 @@
                         store
                         confirmHaptic)
                       (editTextRequestFocusRaw count))))))))
+        (def (mainActivityShowApproveDialog
+               (activity : MainActivity)
+               (view : SsdReviewView)
+               (store : TruthStore)
+               (session : (Nullable SsdSession))
+               (appendMode : Bool)
+               (selectedGroupId : (Nullable String))
+               (rect : FloatArray)
+               (detectedIds : (List String))
+               (boxTypeDisplays : (List String))
+               (confirmHaptic : Int32)) : Unit
+          (if (sessionMissing session)
+            (mainActivitySetStatusRaw
+              activity
+              (selectionIgnoredLoadingStatus))
+            (if appendMode
+              (mainActivityShowAppendDialog
+                activity
+                view
+                store
+                session
+                selectedGroupId
+                rect
+                detectedIds
+                confirmHaptic)
+              (let ((layout (mainActivityDialogColumn activity))
+                    (label
+                      (mainActivityTextInput
+                        activity
+                        "Label, e.g. Phaser-1"))
+                    (boxType
+                      (mainActivityBoxTypeInputWithHint
+                        activity
+                        boxTypeDisplays
+                        "Box type id/name"))
+                    (firingArc
+                      (mainActivityFiringArcInput
+                        activity
+                        (firingArcDisplaysValue)))
+                    (count
+                      (mainActivityNumberInput
+                        activity
+                        "Count"
+                        (detectedIdsCountText (list-size detectedIds)))))
+                (begin
+                  (mainActivityAddApproveDialogInputs
+                    layout
+                    label
+                    boxType
+                    firingArc
+                    count)
+                  (autoCompleteInstallBoxTypeDialogBehavior
+                    activity
+                    label
+                    boxType
+                    firingArc
+                    "")
+                  (let ((dialog
+                          (alertDialogBuilderShowRaw
+                            (alertDialogBuilderSetPositiveAction
+                              (alertDialogBuilderSetCancelAction
+                                (alertDialogBuilderSetLinearLayoutViewRaw
+                                  (alertDialogBuilderSetTitleRaw
+                                    (alertDialogBuilderForActivityRaw activity)
+                                    (detectedBoxesTitle
+                                      (list-size detectedIds)))
+                                  layout))
+                              "Approve"
+                              (lambda () (begin))))))
+                    (begin
+                      (mainActivityInstallApproveAreaDialogButton
+                        activity
+                        dialog
+                        rect
+                        detectedIds
+                        label
+                        boxType
+                        firingArc
+                        count
+                        view
+                        store
+                        confirmHaptic)
+                      (mainActivityFocusBoxTypeDropdown
+                        dialog
+                        boxType
+                        (mainActivityDisplayHeightPixels activity)
+                        (mainActivityDialogSoftInputMode)))))))))
         (def (mainActivityDetectCurrentForceWithState
                (activity : MainActivity)) : Unit
           (mainActivityDetectCurrentRaw
@@ -7433,7 +7558,17 @@
                     (mainActivitySelectedGroupIdRaw activity)
                     rect
                     confirmHaptic)
-                  (mainActivityShowApproveDialogRaw activity rect detectedIds))))
+                  (mainActivityShowApproveDialog
+                    activity
+                    view
+                    store
+                    (mainActivityCurrentSessionRaw activity)
+                    (mainActivityAppendModeRaw activity)
+                    (mainActivitySelectedGroupIdRaw activity)
+                    rect
+                    detectedIds
+                    (mainActivityBoxTypeDisplaysRaw activity)
+                    confirmHaptic))))
             (int32 80)))
         (def (mainActivitySetTruthStore (activity : MainActivity)
                                         (store : TruthStore)) : Unit
@@ -7545,6 +7680,8 @@
           (kotlin-value Intent FLAG_GRANT_PERSISTABLE_URI_PERMISSION))
         (extern (intentFlagGrantPrefixUriPermission) : Int32
           (kotlin-value Intent FLAG_GRANT_PREFIX_URI_PERMISSION))
+        (extern (firingArcDisplaysValue) : (List String)
+          (kotlin-value firingArcDisplays))
         (extern (intentAddCategoryRaw
                   (intent : Intent)
                   (category : String)) : Unit
@@ -7765,6 +7902,54 @@
               (editTextInputTypeSetRaw input (inputTypeClassNumber))
               (editTextSetTextRaw input text)
               input)))
+        (def (mainActivityTextInput
+               (activity : MainActivity)
+               (hint : String)) : EditText
+          (let ((input (editTextForActivity activity)))
+            (begin
+              (editTextHintSetRaw input hint)
+              (editTextInputTypeSetRaw input (inputTypeClassText))
+              input)))
+        (def (mainActivityBoxTypeInputWithHint
+               (activity : MainActivity)
+               (displays : (List String))
+               (hint : String)) : AutoCompleteTextView
+          (let ((input (mainActivityBoxTypeInput activity displays)))
+            (begin
+              (autoCompleteHintSetRaw input hint)
+              input)))
+        (def (mainActivityDialogColumn
+               (activity : MainActivity)) : LinearLayout
+          (let ((layout (linearLayoutForActivity activity)))
+            (begin
+              (linearLayoutOrientationSetRaw layout (int32 1))
+              (linearLayoutSetPaddingRaw
+                layout
+                (int32 32)
+                (int32 16)
+                (int32 32)
+                (int32 8))
+              layout)))
+        (def (mainActivityAddApproveDialogInputs
+               (layout : LinearLayout)
+               (label : EditText)
+               (boxType : AutoCompleteTextView)
+               (firingArc : AutoCompleteTextView)
+               (count : EditText)) : Unit
+          (begin
+            (linearLayoutAddEditTextViewRaw layout label)
+            (linearLayoutAddAutoCompleteViewRaw layout boxType)
+            (linearLayoutAddAutoCompleteViewRaw layout firingArc)
+            (linearLayoutAddEditTextViewRaw layout count)))
+        (def (mainActivityDisplayHeightPixels
+               (activity : MainActivity)) : Int32
+          (displayMetricsHeightPixelsRaw
+            (resourcesDisplayMetricsRaw
+              (mainActivityResourcesRaw activity))))
+        (def (mainActivityDialogSoftInputMode) : Int32
+          (bitwise-ior
+            (softInputAdjustResize)
+            (softInputStateAlwaysVisible)))
         (def (editTextReplaceAutoLabelForBoxType
                (activity : MainActivity)
                (label : EditText)
@@ -10767,7 +10952,7 @@
 	       "    internal var ssdAreaMode: Boolean = false"
 	       "    internal var reopenSsdBrowserOnResume: Boolean = false"
        "    @Volatile internal var loadGeneration: Int = 0"
-       "    private val boxTypeDisplays: List<String> by lazy { boxTypeDisplays(boxTypesLoadAndroid(this)) }"
+       "    internal val boxTypeDisplays: List<String> by lazy { boxTypeDisplays(boxTypesLoadAndroid(this)) }"
        "    override fun onCreate(savedInstanceState: Bundle?) {"
        "        super.onCreate(savedInstanceState)"
        "        installClientCrashLogger()"
@@ -10977,48 +11162,6 @@
        "        )"
        "    }"
        ""
-       "    internal fun showApproveDialog(rect: FloatArray, detectedIds: List<String>) {"
-	       "        val session = currentSession"
-	       "        if (sessionMissing(session)) {"
-       "            setStatus(selectionIgnoredLoadingStatus())"
-	       "            return"
-	       "        }"
-	       "        if (appendMode) {"
-	       "            mainActivityShowAppendDialog(this, reviewView, truthStore, session, selectedGroupId, rect, detectedIds, HapticFeedbackConstants.CONFIRM)"
-	       "            return"
-       "        }"
-       "        val layout = LinearLayout(this).apply {"
-       "            orientation = LinearLayout.VERTICAL"
-       "            setPadding(32, 16, 32, 8)"
-       "        }"
-       "        val label = EditText(this).apply {"
-       "            hint = \"Label, e.g. Phaser-1\""
-       "            inputType = InputType.TYPE_CLASS_TEXT"
-       "        }"
-       "        val boxType = mainActivityBoxTypeInput(this, boxTypeDisplays).apply {"
-       "            hint = \"Box type id/name\""
-       "        }"
-       "        val firingArc = mainActivityFiringArcInput(this, firingArcDisplays)"
-       "        val count = EditText(this).apply {"
-       "            hint = \"Count\""
-       "            inputType = InputType.TYPE_CLASS_NUMBER"
-       "            setText(detectedIdsCountText(detectedIds.size))"
-       "        }"
-       "        layout.addView(label)"
-       "        layout.addView(boxType)"
-       "        layout.addView(firingArc)"
-       "        layout.addView(count)"
-       "        autoCompleteInstallBoxTypeDialogBehavior(this, label, boxType, firingArc, \"\")"
-       "        val dialog = AlertDialog.Builder(this)"
-       "            .setTitle(detectedBoxesTitle(detectedIds.size))"
-       "            .setView(layout)"
-       "            .setNegativeButton(\"Cancel\", null)"
-       "            .setPositiveButton(\"Approve\", null)"
-       "            .show()"
-       "        mainActivityInstallApproveAreaDialogButton(this, dialog, rect, detectedIds, label, boxType, firingArc, count, reviewView, truthStore, HapticFeedbackConstants.CONFIRM)"
-       "        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 showGroupEditDialog(group: SsdGroup) {"
        "        if (sessionMissing(currentSession)) return"
        "        val session = ssdSessionOrEmpty(currentSession)"