Generate SSD PDF launchers from typed Jerboa

ober

8c4d6af90caa550432502c4f59a9a2edcb83d1ee

diff --git a/templates/ssd-review.ss b/templates/ssd-review.ss
index 1ae016d..7acdebe 100644
--- a/templates/ssd-review.ss
+++ b/templates/ssd-review.ss
@@ -4762,11 +4762,13 @@
                       (java lang Thread)
                       (java util UUID)
                       (kotlin io FileTreeWalk)
+                      (android Manifest)
                       (android app AlertDialog)
                       (android app AlertDialog Builder)
                       (android content ContentUris)
                       (android content ContentResolver)
                       (android content Context)
+                      (android content SharedPreferences)
                       (android content res Resources)
                       (android content DialogInterface)
                       (android graphics Bitmap)
@@ -4774,7 +4776,10 @@
                       (android database Cursor)
                       (android graphics drawable GradientDrawable)
                       (android net Uri)
+                      (android os Build)
                       (android os ParcelFileDescriptor)
+                      (android provider DocumentsContract)
+                      (android provider Settings)
                       (android text Editable)
                       (android text InputType)
                       (android text TextWatcher)
@@ -4916,6 +4921,9 @@
                 mainActivitySetPageIndex mainActivitySetPdfIdentity
                 mainActivitySetLoadedPdfState
                 mainActivityAdvanceLoadGeneration
+                mainActivityInitialPickerUri mainActivityOpenPdf
+                mainActivityOpenAnyPdf mainActivityChooseSsdPdfFolder
+                mainActivityRequestDownloadAccess
                 mainActivitySetPositiveChooseSsdPdfFolder
                 mainActivitySetNeutralChooseSsdPdfFolder
                 mainActivitySetPositiveOpenAnyPdf
@@ -5031,21 +5039,25 @@
         (type AdapterView)
         (type ArrayAdapter)
         (type AutoCompleteTextView)
+        (type Build)
         (type Button)
         (type ButtonKind)
         (type CharSequence)
         (type ContentResolver)
         (type Context)
         (type DialogInterface)
+        (type DocumentsContract)
         (type Editable)
         (type EditText)
         (type File)
         (type FileTreeWalk)
+        (type SharedPreferences)
         (type InputStream)
         (type OutputStream)
         (type LayoutParams)
         (type Cursor)
         (type Intent)
+        (type Manifest)
         (type Uri)
         (type ParcelFileDescriptor)
         (type View)
@@ -5062,6 +5074,7 @@
         (type SsdReviewView)
         (type SsdCell)
         (type SsdPdfChoice)
+        (type Settings)
         (type MainActivity)
         (type BoxType)
         (type TruthStore)
@@ -5837,15 +5850,6 @@
         (extern (mainActivityRenderCurrentPageRaw
                   (activity : MainActivity)) : Unit
           (kotlin-member-call renderCurrentPage))
-        (extern (mainActivityOpenAnyPdfRaw
-                  (activity : MainActivity)) : Unit
-          (kotlin-member-call openAnyPdf))
-        (extern (mainActivityChooseSsdPdfFolderRaw
-                  (activity : MainActivity)) : Unit
-          (kotlin-member-call chooseSsdPdfFolder))
-        (extern (mainActivityRequestDownloadAccessRaw
-                  (activity : MainActivity)) : Unit
-          (kotlin-member-call requestDownloadAccess))
         (extern (mainActivityFindDownloadSsdPdfsRaw
                   (activity : MainActivity)) : (List SsdPdfChoice)
           (kotlin-member-call findDownloadSsdPdfs))
@@ -7790,10 +7794,16 @@
           (kotlin-value Intent ACTION_OPEN_DOCUMENT))
         (extern (intentActionOpenDocumentTree) : String
           (kotlin-value Intent ACTION_OPEN_DOCUMENT_TREE))
+        (extern (intentActionManageAppAllFilesAccessPermission) : String
+          (kotlin-value Settings ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION))
+        (extern (intentActionManageAllFilesAccessPermission) : String
+          (kotlin-value Settings ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))
         (extern (intentCategoryOpenable) : String
           (kotlin-value Intent CATEGORY_OPENABLE))
         (extern (intentExtraTitle) : String
           (kotlin-value Intent EXTRA_TITLE))
+        (extern (documentsContractExtraInitialUri) : String
+          (kotlin-value DocumentsContract EXTRA_INITIAL_URI))
         (extern (intentFlagGrantReadUriPermission) : Int32
           (kotlin-value Intent FLAG_GRANT_READ_URI_PERMISSION))
         (extern (intentFlagGrantWriteUriPermission) : Int32
@@ -7812,11 +7822,20 @@
                   (intent : Intent)
                   (mimeType : String)) : Unit
           (kotlin-member-set type))
+        (extern (intentDataSetRaw
+                  (intent : Intent)
+                  (uri : Uri)) : Unit
+          (kotlin-member-set data))
         (extern (intentPutExtraStringRaw
                   (intent : Intent)
                   (name : String)
                   (value : String)) : Unit
           (kotlin-member-call putExtra))
+        (extern (intentPutExtraUriRaw
+                  (intent : Intent)
+                  (name : String)
+                  (value : Uri)) : Unit
+          (kotlin-member-call putExtra))
         (extern (intentAddFlagsRaw
                   (intent : Intent)
                   (flags : Int32)) : Unit
@@ -7826,10 +7845,36 @@
                   (intent : Intent)
                   (requestCode : Int32)) : Unit
           (kotlin-member-call startActivityForResult))
+        (extern (mainActivityStartActivityRaw
+                  (activity : MainActivity)
+                  (intent : Intent)) : Unit
+          (kotlin-member-call startActivity))
+        (extern (mainActivityRequestPermissionsRaw
+                  (activity : MainActivity)
+                  (permissions : (Array String))
+                  (requestCode : Int32)) : Unit
+          (kotlin-member-call requestPermissions))
         (extern (intentDataUri (intent : Intent)) : (Nullable Uri)
           (kotlin-member-call getData))
         (extern (intentFlags (intent : Intent)) : Int32
           (kotlin-member-get flags))
+        (extern (mainActivityPackageNameRaw (activity : MainActivity)) : String
+          (kotlin-member-get packageName))
+        (extern (mainActivityGetPreferencesRaw
+                  (activity : MainActivity)
+                  (mode : Int32)) : SharedPreferences
+          (kotlin-member-call getPreferences))
+        (extern (sharedPreferencesGetStringRaw
+                  (preferences : SharedPreferences)
+                  (key : String)
+                  (defaultValue : (Nullable String))) : (Nullable String)
+          (kotlin-member-call getString))
+        (extern (contextModePrivate) : Int32
+          (kotlin-value Context MODE_PRIVATE))
+        (extern (documentsContractBuildDocumentUriRaw
+                  (authority : String)
+                  (documentId : String)) : Uri
+          (kotlin-call DocumentsContract buildDocumentUri))
         (def (pdfUriLoaded (uri : (Nullable Uri))) : Bool
           (not (nullable-null? uri)))
         (def (uriOrEmpty (uri : (Nullable Uri))) : Uri
@@ -8330,46 +8375,264 @@
         (def (autoCompleteDismissDropDown
                (view : AutoCompleteTextView)) : Unit
           (autoCompleteDismissDropDownRaw view))
+        (def (mainActivityPreferenceString
+               (activity : MainActivity)
+               (key : String)) : (Nullable String)
+          (sharedPreferencesGetStringRaw
+            (mainActivityGetPreferencesRaw activity (contextModePrivate))
+            key
+            (nullable-none String)))
+        (def (mainActivitySdkAtLeast (sdk : Int32) (api : Int32)) : Bool
+          (>= sdk api))
+        (def (mainActivityInitialPickerUri
+               (activity : MainActivity)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : (Nullable Uri)
+          (let ((treeUri
+                  (mainActivityPreferenceString
+                    activity
+                    treePreferenceKey)))
+            (if (nullableTextPresent treeUri)
+              (nullable-some
+                (uriParse (nullableTextOrEmpty treeUri)))
+              (let ((lastUri
+                      (mainActivityPreferenceString
+                        activity
+                        lastPdfPreferenceKey)))
+                (if (nullableTextPresent lastUri)
+                  (nullable-some
+                    (uriParse (nullableTextOrEmpty lastUri)))
+                  (nullable-some
+                    (documentsContractBuildDocumentUriRaw
+                      "com.android.externalstorage.documents"
+                      "primary:Download")))))))
+        (def (intentPutInitialUriIfPresent
+               (intent : Intent)
+               (uri : (Nullable Uri))) : Unit
+          (if (pdfUriLoaded uri)
+            (intentPutExtraUriRaw
+              intent
+              (documentsContractExtraInitialUri)
+              (uriOrEmpty uri))
+            (begin)))
+        (def (mainActivityOpenPdf
+               (activity : MainActivity)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (requestReadStorageCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)
+               (sdkInt : Int32)
+               (androidRCode : Int32)
+               (androidMCode : Int32)
+               (readExternalStoragePermission : String)
+               (manageAppAllFilesAccessAction : String)
+               (manageAllFilesAccessAction : String)) : Unit
+          (mainActivityOpenPdfAsync
+            activity
+            (mainActivityPreferenceString activity treePreferenceKey)
+            requestOpenPdfCode
+            requestOpenTreeCode
+            requestReadStorageCode
+            treePreferenceKey
+            lastPdfPreferenceKey
+            sdkInt
+            androidRCode
+            androidMCode
+            readExternalStoragePermission
+            manageAppAllFilesAccessAction
+            manageAllFilesAccessAction))
+        (def (mainActivityOpenAnyPdf
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Unit
+          (let ((intent (intentForAction (intentActionOpenDocument))))
+            (begin
+              (intentAddCategoryRaw intent (intentCategoryOpenable))
+              (intentTypeSetRaw intent "application/pdf")
+              (intentAddFlagsRaw
+                intent
+                (bitwise-ior
+                  (intentFlagGrantReadUriPermission)
+                  (intentFlagGrantPersistableUriPermission)))
+              (intentPutInitialUriIfPresent
+                intent
+                (mainActivityInitialPickerUri
+                  activity
+                  treePreferenceKey
+                  lastPdfPreferenceKey))
+              (mainActivityStartActivityForResultRaw
+                activity
+                intent
+                requestCode))))
+        (def (mainActivityChooseSsdPdfFolder
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Unit
+          (let ((intent (intentForAction (intentActionOpenDocumentTree))))
+            (begin
+              (intentAddFlagsRaw
+                intent
+                (bitwise-ior
+                  (intentFlagGrantReadUriPermission)
+                  (bitwise-ior
+                    (intentFlagGrantPersistableUriPermission)
+                    (intentFlagGrantPrefixUriPermission))))
+              (intentPutInitialUriIfPresent
+                intent
+                (mainActivityInitialPickerUri
+                  activity
+                  treePreferenceKey
+                  lastPdfPreferenceKey))
+              (mainActivityStartActivityForResultRaw
+                activity
+                intent
+                requestCode))))
+        (def (mainActivityRequestDownloadAccess
+               (activity : MainActivity)
+               (requestReadStorageCode : Int32)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)
+               (sdkInt : Int32)
+               (androidRCode : Int32)
+               (androidMCode : Int32)
+               (readExternalStoragePermission : String)
+               (manageAppAllFilesAccessAction : String)
+               (manageAllFilesAccessAction : String)) : Unit
+          (begin
+            (mainActivitySetReopenSsdBrowserOnResume activity #t)
+            (if (mainActivitySdkAtLeast sdkInt androidRCode)
+              (let ((intent
+                      (intentForAction
+                        manageAppAllFilesAccessAction)))
+                (begin
+                  (intentDataSetRaw
+                    intent
+                    (uriParse
+                      (packageUriText
+                        (mainActivityPackageNameRaw activity))))
+                  (try
+                    (mainActivityStartActivityRaw activity intent)
+                    (catch (error : Exception)
+                      (mainActivityStartActivityRaw
+                        activity
+                        (intentForAction
+                          manageAllFilesAccessAction))))))
+              (if (mainActivitySdkAtLeast sdkInt androidMCode)
+                (mainActivityRequestPermissionsRaw
+                  activity
+                  (stringListToTypedArray
+                    (list-of String
+                      readExternalStoragePermission))
+                  requestReadStorageCode)
+                (mainActivityOpenPdf
+                  activity
+                  requestOpenPdfCode
+                  requestOpenTreeCode
+                  requestReadStorageCode
+                  treePreferenceKey
+                  lastPdfPreferenceKey
+                  sdkInt
+                  androidRCode
+                  androidMCode
+                  readExternalStoragePermission
+                  manageAppAllFilesAccessAction
+                  manageAllFilesAccessAction)))))
         (def (mainActivitySetPositiveChooseSsdPdfFolder
                (builder : Builder)
-               (activity : MainActivity)) : Builder
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Builder
           (alertDialogBuilderSetPositiveAction
             builder
             "Choose Folder"
             (lambda ()
-              (mainActivityChooseSsdPdfFolderRaw activity))))
+              (mainActivityChooseSsdPdfFolder
+                activity
+                requestCode
+                treePreferenceKey
+                lastPdfPreferenceKey))))
         (def (mainActivitySetNeutralChooseSsdPdfFolder
                (builder : Builder)
-               (activity : MainActivity)) : Builder
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Builder
           (alertDialogBuilderSetNeutralAction
             builder
             "Choose Folder"
             (lambda ()
-              (mainActivityChooseSsdPdfFolderRaw activity))))
+              (mainActivityChooseSsdPdfFolder
+                activity
+                requestCode
+                treePreferenceKey
+                lastPdfPreferenceKey))))
         (def (mainActivitySetPositiveOpenAnyPdf
                (builder : Builder)
-               (activity : MainActivity)) : Builder
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Builder
           (alertDialogBuilderSetPositiveAction
             builder
             "Open Any"
             (lambda ()
-              (mainActivityOpenAnyPdfRaw activity))))
+              (mainActivityOpenAnyPdf
+                activity
+                requestCode
+                treePreferenceKey
+                lastPdfPreferenceKey))))
         (def (mainActivitySetNegativeOpenAnyPdf
                (builder : Builder)
-               (activity : MainActivity)) : Builder
+               (activity : MainActivity)
+               (requestCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Builder
           (alertDialogBuilderSetNegativeAction
             builder
             "Open Any"
             (lambda ()
-              (mainActivityOpenAnyPdfRaw activity))))
+              (mainActivityOpenAnyPdf
+                activity
+                requestCode
+                treePreferenceKey
+                lastPdfPreferenceKey))))
         (def (mainActivitySetPositiveRequestDownloadAccess
                (builder : Builder)
-               (activity : MainActivity)) : Builder
+               (activity : MainActivity)
+               (requestReadStorageCode : Int32)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)
+               (sdkInt : Int32)
+               (androidRCode : Int32)
+               (androidMCode : Int32)
+               (readExternalStoragePermission : String)
+               (manageAppAllFilesAccessAction : String)
+               (manageAllFilesAccessAction : String)) : Builder
           (alertDialogBuilderSetPositiveAction
             builder
             "Access Downloads"
             (lambda ()
-              (mainActivityRequestDownloadAccessRaw activity))))
+              (mainActivityRequestDownloadAccess
+                activity
+                requestReadStorageCode
+                requestOpenPdfCode
+                requestOpenTreeCode
+                treePreferenceKey
+                lastPdfPreferenceKey
+                sdkInt
+                androidRCode
+                androidMCode
+                readExternalStoragePermission
+                manageAppAllFilesAccessAction
+                manageAllFilesAccessAction))))
         (def (mainActivitySetNegativeCancelAppend
                (builder : Builder)
                (activity : MainActivity)
@@ -8468,7 +8731,11 @@
         (def (mainActivityShowPdfChoiceDialog
                (activity : MainActivity)
                (choices : (List SsdPdfChoice))
-               (title : String)) : Unit
+               (title : String)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Unit
           (begin
             (alertDialogBuilderShowRaw
               (mainActivitySetPositiveOpenAnyPdf
@@ -8481,14 +8748,31 @@
                     activity
                     choices
                     (intentFlagGrantReadUriPermission))
-                  activity)
-                activity))
+                  activity
+                  requestOpenTreeCode
+                  treePreferenceKey
+                  lastPdfPreferenceKey)
+                activity
+                requestOpenPdfCode
+                treePreferenceKey
+                lastPdfPreferenceKey))
             (mainActivitySetStatusRaw
               activity
               (ssdPdfFoundStatus choices))))
         (def (mainActivityShowNoSsdPdfsDialog
                (activity : MainActivity)
-               (hasDirectAccess : Bool)) : Unit
+               (hasDirectAccess : Bool)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (requestReadStorageCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)
+               (sdkInt : Int32)
+               (androidRCode : Int32)
+               (androidMCode : Int32)
+               (readExternalStoragePermission : String)
+               (manageAppAllFilesAccessAction : String)
+               (manageAllFilesAccessAction : String)) : Unit
           (begin
             (alertDialogBuilderShowRaw
               (mainActivitySetPositiveRequestDownloadAccess
@@ -8499,9 +8783,26 @@
                         (alertDialogBuilderForActivityRaw activity)
                         (noSsdPdfsTitle))
                       (noSsdPdfsDialogMessage hasDirectAccess))
-                    activity)
-                  activity)
-                activity))
+                    activity
+                    requestOpenPdfCode
+                    treePreferenceKey
+                    lastPdfPreferenceKey)
+                  activity
+                  requestOpenTreeCode
+                  treePreferenceKey
+                  lastPdfPreferenceKey)
+                activity
+                requestReadStorageCode
+                requestOpenPdfCode
+                requestOpenTreeCode
+                treePreferenceKey
+                lastPdfPreferenceKey
+                sdkInt
+                androidRCode
+                androidMCode
+                readExternalStoragePermission
+                manageAppAllFilesAccessAction
+                manageAllFilesAccessAction))
             (mainActivitySetStatusRaw activity (noSsdPdfsFoundStatus))))
         (def (showShortToast
                (activity : MainActivity)
@@ -8809,7 +9110,18 @@
                             (exceptionMessageRaw error)))))))))))
         (def (mainActivityOpenPdfAsync
                (activity : MainActivity)
-               (remembered : (Nullable String))) : Unit
+               (remembered : (Nullable String))
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (requestReadStorageCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)
+               (sdkInt : Int32)
+               (androidRCode : Int32)
+               (androidMCode : Int32)
+               (readExternalStoragePermission : String)
+               (manageAppAllFilesAccessAction : String)
+               (manageAllFilesAccessAction : String)) : Unit
           (begin
             (mainActivitySetStatusRaw
               activity
@@ -8839,11 +9151,26 @@
                             (mainActivityShowPdfChoiceDialog
                               activity
                               unique
-                              "Open SSD PDF")
+                              "Open SSD PDF"
+                              requestOpenPdfCode
+                              requestOpenTreeCode
+                              treePreferenceKey
+                              lastPdfPreferenceKey)
                             (mainActivityShowNoSsdPdfsDialog
                               activity
                               (mainActivityHasDirectDownloadAccessRaw
-                                activity))))))))))))
+                                activity)
+                              requestOpenPdfCode
+                              requestOpenTreeCode
+                              requestReadStorageCode
+                              treePreferenceKey
+                              lastPdfPreferenceKey
+                              sdkInt
+                              androidRCode
+                              androidMCode
+                              readExternalStoragePermission
+                              manageAppAllFilesAccessAction
+                              manageAllFilesAccessAction)))))))))))
         (def (alertDialogBuilderSetCancelAction
                (builder : Builder)) : Builder
           (alertDialogBuilderSetNegativeAction
@@ -8852,7 +9179,10 @@
             (lambda ()
               (begin))))
         (def (showNoSsdPdfsInFolderDialog
-               (activity : MainActivity)) : Unit
+               (activity : MainActivity)
+               (requestOpenTreeCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Unit
           (begin
             (alertDialogBuilderShowRaw
               (mainActivitySetPositiveChooseSsdPdfFolder
@@ -8862,11 +9192,18 @@
                       (alertDialogBuilderForActivityRaw activity)
                       (noSsdPdfsTitle))
                     (noSsdPdfsInFolderMessage)))
-                activity))
+                activity
+                requestOpenTreeCode
+                treePreferenceKey
+                lastPdfPreferenceKey))
             (begin)))
         (def (mainActivityShowSsdPdfBrowserAsync
                (activity : MainActivity)
-               (treeUri : Uri)) : Unit
+               (treeUri : Uri)
+               (requestOpenPdfCode : Int32)
+               (requestOpenTreeCode : Int32)
+               (treePreferenceKey : String)
+               (lastPdfPreferenceKey : String)) : Unit
           (begin
             (mainActivitySetStatusRaw activity (scanningSsdPdfsStatus))
             (runBackground
@@ -8879,9 +9216,13 @@
                     (mainActivityRunOnUiThreadRaw
                       activity
                       (lambda ()
-                        (if (ssdPdfChoicesEmpty choices)
+                          (if (ssdPdfChoicesEmpty choices)
                           (begin
-                            (showNoSsdPdfsInFolderDialog activity)
+                            (showNoSsdPdfsInFolderDialog
+                              activity
+                              requestOpenTreeCode
+                              treePreferenceKey
+                              lastPdfPreferenceKey)
                             (mainActivitySetStatusRaw
                               activity
                               (noSsdPdfsChooseFolderStatus)))
@@ -8889,7 +9230,11 @@
                             (mainActivityShowPdfChoiceDialog
                               activity
                               choices
-                              (openSsdPdfTitle))
+                              (openSsdPdfTitle)
+                              requestOpenPdfCode
+                              requestOpenTreeCode
+                              treePreferenceKey
+                              lastPdfPreferenceKey)
                             (begin))))))
                   (catch (error : Exception)
                     (mainActivityRunOnUiThreadRaw
@@ -8900,8 +9245,11 @@
                             activity
                             (ssdBrowserFailedStatus
                               (exceptionMessageRaw error)))
-                          (mainActivityChooseSsdPdfFolderRaw
-                            activity))))))))))
+                          (mainActivityChooseSsdPdfFolder
+                            activity
+                            requestOpenTreeCode
+                            treePreferenceKey
+                            lastPdfPreferenceKey))))))))))
         (def (newDetectionSessionId) : String
           (sessionIdFromUuid (uuidToStringRaw (uuidRandomRaw))))
         (def (mainActivityDetectionSession
@@ -11157,7 +11505,7 @@
        "        super.onResume()"
        "        if (ssdBrowserResumeReady(reopenSsdBrowserOnResume, hasDirectDownloadAccess())) {"
        "            mainActivitySetReopenSsdBrowserOnResume(this, false)"
-       "            openPdf()"
+       "            mainActivityOpenPdf(this, REQ_OPEN_PDF, REQ_OPEN_SSD_PDF_TREE, REQ_READ_STORAGE, PREF_SSD_PDF_TREE_URI, PREF_LAST_PDF_URI, Build.VERSION.SDK_INT, Build.VERSION_CODES.R, Build.VERSION_CODES.M, Manifest.permission.READ_EXTERNAL_STORAGE, Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)"
        "        }"
        "    }"
        ""
@@ -11187,12 +11535,12 @@
        "        val controls = LinearLayout(this).apply {"
        "            orientation = LinearLayout.VERTICAL"
        "            addView(mainActivityActionRow(this@MainActivity, LinearLayout.HORIZONTAL, Gravity.CENTER_VERTICAL,"
-	       "                mainActivityButton(this@MainActivity, \"Open SSDs\", ButtonKind.PRIMARY) { openPdf() },"
+	       "                mainActivityButton(this@MainActivity, \"Open SSDs\", ButtonKind.PRIMARY) { mainActivityOpenPdf(this@MainActivity, REQ_OPEN_PDF, REQ_OPEN_SSD_PDF_TREE, REQ_READ_STORAGE, PREF_SSD_PDF_TREE_URI, PREF_LAST_PDF_URI, Build.VERSION.SDK_INT, Build.VERSION_CODES.R, Build.VERSION_CODES.M, Manifest.permission.READ_EXTERNAL_STORAGE, Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) },"
 	       "                mainActivityButton(this@MainActivity, \"Detect\", ButtonKind.ACCENT) { detectCurrent(forceDetect = true) },"
 	       "                mainActivityButton(this@MainActivity, \"Set SSD Area\", ButtonKind.MODE) { mainActivityStartSsdAreaMode(this@MainActivity, reviewView, currentSession, selectedGroupId, HapticFeedbackConstants.CLOCK_TICK) },"
 	       "            ))"
 	       "            addView(mainActivityActionRow(this@MainActivity, LinearLayout.HORIZONTAL, Gravity.CENTER_VERTICAL,"
-	       "                mainActivityButton(this@MainActivity, \"Open Any\") { openAnyPdf() },"
+	       "                mainActivityButton(this@MainActivity, \"Open Any\") { mainActivityOpenAnyPdf(this@MainActivity, REQ_OPEN_PDF, PREF_SSD_PDF_TREE_URI, PREF_LAST_PDF_URI) },"
 	       "                mainActivityButton(this@MainActivity, \"Rotate\") { mainActivityRotatePage(this@MainActivity, reviewView, loadGeneration, currentSession) },"
 	       "                mainActivityButton(this@MainActivity, \"Fit\") { reviewViewFitImage(reviewView) },"
 	       "            ))"
@@ -11232,65 +11580,6 @@
        "        return root"
        "    }"
        ""
-       "    private fun openPdf() {"
-       "        val remembered = getPreferences(MODE_PRIVATE).getString(PREF_SSD_PDF_TREE_URI, null)"
-       "        mainActivityOpenPdfAsync(this, remembered)"
-       "    }"
-       ""
-       "    internal fun openAnyPdf() {"
-       "        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {"
-       "            addCategory(Intent.CATEGORY_OPENABLE)"
-       "            type = \"application/pdf\""
-       "            addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)"
-       "            val initialUri = initialPickerUri()"
-       "            if (pdfUriLoaded(initialUri)) putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriOrEmpty(initialUri))"
-       "        }"
-       "        startActivityForResult(intent, REQ_OPEN_PDF)"
-       "    }"
-       ""
-       "    internal fun chooseSsdPdfFolder() {"
-       "        val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {"
-       "            addFlags("
-       "                Intent.FLAG_GRANT_READ_URI_PERMISSION or"
-       "                    Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or"
-       "                    Intent.FLAG_GRANT_PREFIX_URI_PERMISSION"
-       "            )"
-       "            val initialUri = initialPickerUri()"
-       "            if (pdfUriLoaded(initialUri)) putExtra(DocumentsContract.EXTRA_INITIAL_URI, uriOrEmpty(initialUri))"
-       "        }"
-       "        startActivityForResult(intent, REQ_OPEN_SSD_PDF_TREE)"
-       "    }"
-       ""
-       "    internal fun requestDownloadAccess() {"
-       "        mainActivitySetReopenSsdBrowserOnResume(this, true)"
-       "        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))"
-       "            }"
-       "            try {"
-       "                startActivity(intent)"
-       "            } catch (_: Exception) {"
-       "                startActivity(Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION))"
-       "            }"
-       "        } else if (sdkAtLeast(Build.VERSION.SDK_INT, Build.VERSION_CODES.M)) {"
-       "            requestPermissions(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), REQ_READ_STORAGE)"
-       "        } else {"
-       "            openPdf()"
-       "        }"
-       "    }"
-       ""
-       "    private fun initialPickerUri(): Uri? {"
-       "        val prefs = getPreferences(MODE_PRIVATE)"
-       "        val treeUri = prefs.getString(PREF_SSD_PDF_TREE_URI, null)"
-       "        if (nullableTextPresent(treeUri)) return Uri.parse(nullableTextOrEmpty(treeUri))"
-       "        val lastUri = prefs.getString(PREF_LAST_PDF_URI, null)"
-       "        if (nullableTextPresent(lastUri)) return Uri.parse(nullableTextOrEmpty(lastUri))"
-       "        return DocumentsContract.buildDocumentUri("
-       "            \"com.android.externalstorage.documents\","
-       "            \"primary:Download\""
-       "        )"
-       "    }"
-       ""
        "    internal fun renderCurrentPage() {"
        "        if (!pdfUriLoaded(pdfUri)) return"
        "        val uri = uriOrEmpty(pdfUri)"
@@ -11384,7 +11673,7 @@
        "        super.onRequestPermissionsResult(requestCode, permissions, grantResults)"
        "        if (requestIsReadStorage(requestCode, REQ_READ_STORAGE)) {"
        "            mainActivitySetReopenSsdBrowserOnResume(this, false)"
-       "            openPdf()"
+       "            mainActivityOpenPdf(this, REQ_OPEN_PDF, REQ_OPEN_SSD_PDF_TREE, REQ_READ_STORAGE, PREF_SSD_PDF_TREE_URI, PREF_LAST_PDF_URI, Build.VERSION.SDK_INT, Build.VERSION_CODES.R, Build.VERSION_CODES.M, Manifest.permission.READ_EXTERNAL_STORAGE, Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)"
        "        }"
        "    }"
        ""
@@ -11400,7 +11689,7 @@
        "            .edit()"
        "            .putString(PREF_SSD_PDF_TREE_URI, uri.toString())"
        "            .apply()"
-       "        mainActivityShowSsdPdfBrowserAsync(this, uri)"
+       "        mainActivityShowSsdPdfBrowserAsync(this, uri, REQ_OPEN_PDF, REQ_OPEN_SSD_PDF_TREE, PREF_SSD_PDF_TREE_URI, PREF_LAST_PDF_URI)"
        "    }"
        ""
        "    internal fun findSsdPdfsFromTree(treeUri: Uri): List<SsdPdfChoice> {"