Generate SSD PDF tree scan loop from typed Jerboa

ober

893099b947c4b7e3c69ccb85f0bff3f8d2c981ae

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 30c3468..397c32e 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4851,6 +4851,7 @@
                 reviewViewRestoreViewportAfterLayout
                 reviewViewClearInteractionState
                 reviewViewMakeScaleGestureDetector
+                forEachDocumentFile
                 mainActivityInstallReviewViewCallbacks
                 mainActivitySelectGroupId
                 mainActivitySelectRequestedGroup
@@ -5815,6 +5816,16 @@
                           (int32 0)
                           (- (list-size parts) (int32 1)))))
             (invoke ensure current (list-ref parts i))))
+        (def (forEachDocumentFile
+               (files : (List DocumentFile))
+               (action : (-> DocumentFile Unit))) : Unit
+          (begin
+            (for/fold ((ignored (int32 0)))
+                      ((i (in-range (int32 0) (list-size files))))
+              (begin
+                (invoke action (list-ref files i))
+                ignored))
+            (begin)))
         (def (trimmedNonBlankLines (text : String)) : (MutableList String)
           (let ((lines (stringLines text)))
             (for/fold ((out (mutable-list-empty String)))
@@ -10358,12 +10369,12 @@
        "        depth: Int"
        "    ) {"
        "        if (shouldStopSsdPdfTreeScan(depth, choices.size, MAX_SSD_PDF_CHOICES, MAX_SSD_PDF_SCAN_DEPTH)) return"
-       "        dir.listFiles()"
-       "            .sortedWith(compareBy<DocumentFile>({ ssdPdfDocumentNotDirectory(it) }, { nullableLowercaseOrEmpty(it.name) }))"
-       "            .forEach { child ->"
-       "                if (shouldStopSsdPdfTreeScan(depth, choices.size, MAX_SSD_PDF_CHOICES, MAX_SSD_PDF_SCAN_DEPTH)) return"
+       "        forEachDocumentFile("
+       "            dir.listFiles().sortedWith(compareBy<DocumentFile>({ ssdPdfDocumentNotDirectory(it) }, { nullableLowercaseOrEmpty(it.name) }))"
+       "        ) { child ->"
+       "            if (!shouldStopSsdPdfTreeScan(depth, choices.size, MAX_SSD_PDF_CHOICES, MAX_SSD_PDF_SCAN_DEPTH)) {"
        "                val rawName = child.name"
-       "                if (!nullableTextPresent(rawName)) return@forEach"
+       "                if (nullableTextPresent(rawName)) {"
        "                val name = nullableTextOrEmpty(rawName)"
        "                val label = ssdPdfTreeLabel(prefix, name)"
        "                if (ssdPdfDocumentIsDirectory(child)) {"
@@ -10371,6 +10382,8 @@
        "                } else if (shouldIncludeSsdPdfDocument(child, name, choices.size, MAX_SSD_PDF_CHOICES)) {"
        "                    choices.add(SsdPdfChoice(label, child.uri))"
        "                }"
+       "                }"
+       "            }"
        "            }"
        "    }"
        ""