Move SSD UI state checks to typed Kotlin

ober

938f64b78c523f6115cc03266ee38b73d2baa952

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index d4655f2..30b0664 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4212,12 +4212,14 @@
                 shouldShowFiringArc shouldFocusFiringArc
                 canvasLabelPresent canvasLabelMissing groupIdSelected
                 shouldCaptureViewport
-                hasReplacementLabel hasResolvedLabel
+                hasReplacementLabel missingReplacementLabel hasResolvedLabel
                 ssdBrowserResumeReady focusChangeShouldShowDropdown
                 dialogReadyToShowDropdown focusedDialogReadyToShowDropdown
                 permissionResultGranted downloadAccessBeforeRuntimePermissions
                 downloadAccessFromPermission activityResultRejected
+                pageNavigationBlocked selectModeDisabled ssdAreaModeInactive
                 shouldPersistLoadedPdfState viewportScalePreferencePresent
+                viewportScalePreferenceMissing
                 lastPdfUriMismatch lastViewportPageMismatch
                 displayNameColumnPresent displayNameCursorHasFirstRow
                 currentLoadMatches currentLoadStale
@@ -4700,8 +4702,16 @@
           (and (pdfLoaded hasPdf) (positiveCount pageCount)))
         (def (hasReplacementLabel (replacement : String)) : Bool
           (not (string-blank? replacement)))
+        (def (missingReplacementLabel (replacement : String)) : Bool
+          (not (hasReplacementLabel replacement)))
         (def (hasResolvedLabel (resolved : String)) : Bool
           (not (string-blank? resolved)))
+        (def (pageNavigationBlocked (hasPdf : Bool) (pageCount : Int32)) : Bool
+          (not (pageNavigationReady hasPdf pageCount)))
+        (def (selectModeDisabled (enabled : Bool)) : Bool
+          (not enabled))
+        (def (ssdAreaModeInactive (enabled : Bool)) : Bool
+          (not enabled))
         (def (ssdBrowserResumeReady (pending : Bool) (hasDirectAccess : Bool)) : Bool
           (and pending hasDirectAccess))
         (def (focusChangeShouldShowDropdown (hasFocus : Bool)) : Bool
@@ -4723,6 +4733,8 @@
           (not restoring))
         (def (viewportScalePreferencePresent (present : Bool)) : Bool
           present)
+        (def (viewportScalePreferenceMissing (present : Bool)) : Bool
+          (not (viewportScalePreferencePresent present)))
         (def (lastPdfUriMismatch (saved : (Nullable String)) (uriText : String)) : Bool
           (or (nullable-null? saved)
               (not (equal? (nullable-get saved) uriText))))
@@ -5350,7 +5362,8 @@
       (typed-library (com sfb ssdreview)
         (export defaultLabelForBoxTypeAndroid
                 resolvedLabelForBoxTypeAndroid
-                shouldReplaceLabelForBoxTypeAndroid)
+                shouldReplaceLabelForBoxTypeAndroid
+                shouldKeepLabelForBoxTypeAndroid)
         (type Context)
         (extern (boxTypesResolve (context : Context) (raw : String)) : (Nullable BoxType)
           (kotlin-call BoxTypes resolve))
@@ -5388,7 +5401,11 @@
                                                   (previousBoxType : String)) : Bool
           (shouldReplaceBoxTypeLabel
             label
-            (boxTypeLabelMatchesAndroid context (string-trim label) previousBoxType)))))
+            (boxTypeLabelMatchesAndroid context (string-trim label) previousBoxType)))
+        (def (shouldKeepLabelForBoxTypeAndroid (context : Context)
+                                               (label : String)
+                                               (previousBoxType : String)) : Bool
+          (not (shouldReplaceLabelForBoxTypeAndroid context label previousBoxType)))))
 
     (typed-kotlin-file "com/sfb/ssdreview/Guessing.kt"
       (kotlin-imports (android content Context))
@@ -6178,9 +6195,9 @@
        "    }"
        ""
        "    private fun replaceAutoLabelForBoxType(label: EditText, boxType: String, previousBoxType: String) {"
-       "        if (!shouldReplaceLabelForBoxTypeAndroid(this, label.text.toString(), previousBoxType)) return"
+       "        if (shouldKeepLabelForBoxTypeAndroid(this, label.text.toString(), previousBoxType)) return"
        "        val replacement = defaultLabelForBoxTypeAndroid(this, boxType)"
-       "        if (!hasReplacementLabel(replacement)) return"
+       "        if (missingReplacementLabel(replacement)) return"
        "        label.setText(replacement)"
        "        label.setSelection(label.text.length)"
        "    }"
@@ -6284,7 +6301,7 @@
        "    }"
        ""
        "    private fun changePage(delta: Int) {"
-       "        if (!pageNavigationReady(pdfUri != null, pageCount)) return"
+       "        if (pageNavigationBlocked(pdfUri != null, pageCount)) return"
        "        pageIndex = shiftPageIndex(pageIndex, pageCount, delta)"
        "        persistCurrentPdfState(includeViewport = false)"
        "        renderCurrentPage()"
@@ -6295,11 +6312,11 @@
        "    }"
        ""
 	       "    private fun setSelectMode(enabled: Boolean) {"
-	       "        if (!enabled) {"
+	       "        if (selectModeDisabled(enabled)) {"
 	       "            appendMode = false"
 	       "            ssdAreaMode = false"
 	       "            reviewView.snapSelectionToCells = true"
-	       "        } else if (!ssdAreaMode) {"
+	       "        } else if (ssdAreaModeInactive(ssdAreaMode)) {"
 	       "            reviewView.snapSelectionToCells = true"
 	       "        }"
 	       "        reviewView.selectMode = enabled"
@@ -6355,7 +6372,7 @@
        "    }"
        ""
        "    private fun showPageDialog() {"
-       "        if (!pageNavigationReady(pdfUri != null, pageCount)) return"
+       "        if (pageNavigationBlocked(pdfUri != null, pageCount)) return"
        "        val input = EditText(this).apply {"
        "            inputType = InputType.TYPE_CLASS_NUMBER"
        "            setText(pageNumberText(pageIndex))"
@@ -7309,7 +7326,7 @@
        "        val prefs = getPreferences(MODE_PRIVATE)"
        "        if (lastPdfUriMismatch(prefs.getString(PREF_LAST_PDF_URI, null), uri.toString())) return null"
        "        if (lastViewportPageMismatch(prefs.getInt(PREF_LAST_VIEWPORT_PAGE_INDEX, -1), page)) return null"
-       "        if (!viewportScalePreferencePresent(prefs.contains(PREF_LAST_VIEWPORT_SCALE))) return null"
+       "        if (viewportScalePreferenceMissing(prefs.contains(PREF_LAST_VIEWPORT_SCALE))) return null"
        "        return ViewportState("
        "            prefs.getFloat(PREF_LAST_VIEWPORT_SCALE, 1f),"
        "            prefs.getFloat(PREF_LAST_VIEWPORT_OFFSET_X, 0f),"