Move SSD API level checks to typed Kotlin

ober

20ebcd816076c1ede357ea699489005c31ee2ee1

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index afdcfa2..e759878 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -5251,6 +5251,15 @@
                   lower
                   "^172\\.(1[6-9]|2[0-9]|3[0-1])\\..*")))))))
 
+    (typed-kotlin-file "com/sfb/ssdreview/AndroidApi.kt"
+      (typed-library (com sfb ssdreview)
+        (export sdkAtLeast sdkBefore)
+        (type Int32)
+        (def (sdkAtLeast (sdk : Int32) (api : Int32)) : Bool
+          (>= sdk api))
+        (def (sdkBefore (sdk : Int32) (api : Int32)) : Bool
+          (< sdk api))))
+
     (typed-kotlin-file "com/sfb/ssdreview/RemoteTruthQuery.kt"
       (typed-library (com sfb ssdreview)
         (export remoteTruthQuery)
@@ -5652,7 +5661,7 @@
        ""
        "    private fun requestDownloadAccess() {"
        "        reopenSsdBrowserOnResume = true"
-       "        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {"
+       "        if (sdkAtLeast(Build.VERSION.SDK_INT, Build.VERSION_CODES.R)) {"
        "            val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {"
        "                data = Uri.parse(packageUriText(packageName))"
        "            }"
@@ -5661,7 +5670,7 @@
        "            } catch (_: Exception) {"
        "                startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))"
        "            }"
-       "        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {"
+       "        } else if (sdkAtLeast(Build.VERSION.SDK_INT, Build.VERSION_CODES.M)) {"
        "            requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQ_READ_STORAGE)"
        "        } else {"
        "            openPdf()"
@@ -6503,7 +6512,7 @@
        "    }"
        ""
        "    private fun findDownloadSsdPdfsViaMediaStore(): List<SsdPdfChoice> {"
-       "        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return emptyList()"
+       "        if (sdkBefore(Build.VERSION.SDK_INT, Build.VERSION_CODES.Q)) return emptyList()"
        "        val choices = mutableListOf<SsdPdfChoice>()"
        "        val projection = arrayOf("
        "            MediaStore.Downloads._ID,"
@@ -6588,9 +6597,9 @@
        "    }"
        ""
        "    private fun hasDirectDownloadAccess(): Boolean {"
-       "        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {"
+       "        if (sdkAtLeast(Build.VERSION.SDK_INT, Build.VERSION_CODES.R)) {"
        "            if (Environment.isExternalStorageManager()) return true"
-       "        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {"
+       "        } else if (sdkBefore(Build.VERSION.SDK_INT, Build.VERSION_CODES.M)) {"
        "            return true"
        "        } else if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {"
        "            return true"