Move SSD PDF choice helpers to typed Kotlin

ober

d716e3a9a841bb81f4e22490a3564bd639670bd2

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 0d3e5dc..ce94646 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -1144,7 +1144,8 @@
       (typed-library (com sfb ssdreview)
         (export make-SsdPdfChoice SsdPdfChoice?
                 SsdPdfChoice-label SsdPdfChoice-uri
-                ssdPdfChoiceLabels)
+                ssdPdfChoiceLabels ssdPdfChoiceUriAt
+                ssdPdfUniqueChoicesByLabel)
         (type Int32)
         (type Uri)
         (record SsdPdfChoice
@@ -1155,7 +1156,21 @@
                     ((i (in-range (int32 0) (list-size choices))))
             (begin
               (mutable-list-add! labels (SsdPdfChoice-label (list-ref choices i)))
-              labels)))))
+              labels)))
+        (def (ssdPdfChoiceUriAt (choices : (List SsdPdfChoice)) (index : Int32)) : Uri
+          (SsdPdfChoice-uri (list-ref choices index)))
+        (def (ssdPdfUniqueChoicesByLabel (choices : (List SsdPdfChoice))) : (MutableList SsdPdfChoice)
+          (let ((seen (mutable-set-empty String)))
+            (for/fold ((out (mutable-list-empty SsdPdfChoice)))
+                      ((i (in-range (int32 0) (list-size choices))))
+              (let ((choice (list-ref choices i)))
+                (let ((key (string-lowercase (SsdPdfChoice-label choice))))
+                  (if (set-contains? seen key)
+                    out
+                    (begin
+                      (mutable-set-add! seen key)
+                      (mutable-list-add! out choice)
+                      out)))))))))
 
     (typed-kotlin-file "com/sfb/ssdreview/TruthStoreRecords.kt"
       (kotlin-imports (java io File) (java net URL))
@@ -4691,7 +4706,7 @@
        "        AlertDialog.Builder(this)"
        "            .setTitle(title)"
        "            .setItems(ssdPdfChoiceLabels(choices).toTypedArray()) { _, which ->"
-       "                loadPdf(choices[which].uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)"
+       "                loadPdf(ssdPdfChoiceUriAt(choices, which), Intent.FLAG_GRANT_READ_URI_PERMISSION)"
        "            }"
        "            .setNegativeButton(\"Cancel\", null)"
        "            .setNeutralButton(\"Change Folder\") { _, _ -> chooseSsdPdfFolder() }"
@@ -4810,12 +4825,7 @@
        "    }"
        ""
        "    private fun uniquePdfChoices(choices: List<SsdPdfChoice>): List<SsdPdfChoice> {"
-       "        val unique = linkedMapOf<String, SsdPdfChoice>()"
-       "        choices.forEach { choice ->"
-       "            val key = choice.label.lowercase()"
-       "            if (!unique.containsKey(key)) unique[key] = choice"
-       "        }"
-       "        return unique.values.sortedBy { it.label.lowercase() }.take(MAX_SSD_PDF_CHOICES)"
+       "        return ssdPdfUniqueChoicesByLabel(choices).sortedBy { it.label.lowercase() }.take(MAX_SSD_PDF_CHOICES)"
        "    }"
        ""
        "    private fun hasDirectDownloadAccess(): Boolean {"