Generate SSD PDF discovery from typed Jerboa
ober
32a195363e4aef5e76558efc3c1040e666ba5d45
--- a/templates/ssd-review.ss +++ b/templates/ssd-review.ss @@ -5986,13 +5986,13 @@ (activity : MainActivity) (callback : (-> Unit))) : Unit (kotlin-member-call runOnUiThread)) - (extern (mainActivityFindDownloadSsdPdfsRaw + (extern (ssdPdfFindDownloadSsdPdfsRaw (activity : MainActivity)) : (List SsdPdfChoice) - (kotlin-member-call findDownloadSsdPdfs)) - (extern (mainActivityFindSsdPdfsFromTreeRaw + (kotlin-call ssdPdfFindDownloadSsdPdfs)) + (extern (ssdPdfFindSsdPdfsFromTreeRaw (activity : MainActivity) (uri : Uri)) : (List SsdPdfChoice) - (kotlin-member-call findSsdPdfsFromTree)) + (kotlin-call ssdPdfFindSsdPdfsFromTree)) (extern (sendClientLogBlockingRaw (payload : JSONObject) (readTimeoutMillis : Int32)) : Unit @@ -7992,6 +7992,13 @@ (payload : JSONObject) (readTimeoutMillis : Int32)) : Unit (sendClientLogBlockingRaw payload readTimeoutMillis)) + (def (mainActivityFindDownloadSsdPdfsRaw + (activity : MainActivity)) : (List SsdPdfChoice) + (ssdPdfFindDownloadSsdPdfsRaw activity)) + (def (mainActivityFindSsdPdfsFromTreeRaw + (activity : MainActivity) + (uri : Uri)) : (List SsdPdfChoice) + (ssdPdfFindSsdPdfsFromTreeRaw activity uri)) (def (mainActivityLogDetectResultRaw (activity : MainActivity) (stage : String) @@ -12733,104 +12740,280 @@ " mainActivityHandleReadStoragePermissionResult(this, requestCode, REQ_READ_STORAGE, REQ_OPEN_PDF, REQ_OPEN_SSD_PDF_TREE, 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, PackageManager.PERMISSION_GRANTED, Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION, Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)" " }" "" - " internal fun findSsdPdfsFromTree(treeUri: Uri): List<SsdPdfChoice> {" - " val maybeRoot = DocumentFile.fromTreeUri(this, treeUri)" - " if (!documentFilePresent(maybeRoot)) return emptyList()" - " val root = checkNotNull(maybeRoot)" - " return findSsdPdfs(root)" - " }" - "" - " internal fun findDownloadSsdPdfs(): List<SsdPdfChoice> {" - " val choices = mutableListOf<SsdPdfChoice>()" - " choices.addAll(findDownloadSsdPdfsViaMediaStore())" - " choices.addAll(findDownloadSsdPdfsViaFiles())" - " return ssdPdfUniqueSortedLimitedChoices(choices, MAX_SSD_PDF_CHOICES)" - " }" - "" - " private fun findDownloadSsdPdfsViaMediaStore(): List<SsdPdfChoice> {" - " if (sdkBefore(Build.VERSION.SDK_INT, Build.VERSION_CODES.Q)) return emptyList()" - " val choices = mutableListOf<SsdPdfChoice>()" - " val projection = arrayOf(" - " MediaStore.Downloads._ID," - " MediaStore.MediaColumns.DISPLAY_NAME," - " MediaStore.MediaColumns.RELATIVE_PATH," - " MediaStore.MediaColumns.MIME_TYPE" - " )" - " val selection = mediaStorePdfSelection(MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.DISPLAY_NAME)" - " val selectionArgs = arrayOf(\"application/pdf\", \"%.pdf\")" - " val downloadCursor = contentResolver.query(" - " MediaStore.Downloads.EXTERNAL_CONTENT_URI," - " projection," - " selection," - " selectionArgs," - " mediaStoreDisplayNameSort(MediaStore.MediaColumns.DISPLAY_NAME)" - " )" - " if (cursorPresent(downloadCursor)) checkNotNull(downloadCursor).use { cursor ->" - " val idCol = cursor.getColumnIndexOrThrow(MediaStore.Downloads._ID)" - " val nameCol = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)" - " val pathCol = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH)" - " collectSsdPdfChoicesFromMediaCursor(" - " cursor," - " choices," - " idCol," - " nameCol," - " pathCol," - " MediaStore.Downloads.EXTERNAL_CONTENT_URI," - " MAX_SSD_PDF_CHOICES" - " )" - " }" - " return choices" - " }" - "" - " private fun findDownloadSsdPdfsViaFiles(): List<SsdPdfChoice> {" - " val dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)" - " if (fileIsNotDirectory(dir)) return emptyList()" - " val choices = mutableListOf<SsdPdfChoice>()" - " try {" - " collectSsdPdfChoicesFromDownloadFiles(" - " dir," - " choices," - " MAX_SSD_PDF_SCAN_DEPTH," - " MAX_SSD_PDF_CHOICES" - " )" - " } catch (_: Exception) {" - " }" - " return choices" - " }" - "" - " private fun findSsdPdfs(root: DocumentFile): List<SsdPdfChoice> {" - " val choices = mutableListOf<SsdPdfChoice>()" - " collectSsdPdfs(root, \"\", choices, 0)" - " return ssdPdfUniqueSortedLimitedChoices(choices, MAX_SSD_PDF_CHOICES)" - " }" - "" - " private fun collectSsdPdfs(" - " dir: DocumentFile," - " prefix: String," - " choices: MutableList<SsdPdfChoice>," - " depth: Int" - " ) {" - " 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)) {" - " val name = nullableTextOrEmpty(rawName)" - " val label = ssdPdfTreeLabel(prefix, name)" - " if (ssdPdfDocumentIsDirectory(child)) {" - " collectSsdPdfs(child, label, choices, depth + 1)" - " } else if (shouldIncludeSsdPdfDocument(child, name, choices.size, MAX_SSD_PDF_CHOICES)) {" - " choices.add(SsdPdfChoice(label, child.uri))" - " }" - " }" - " }" - " }" - " }" - "" "}" )) + (typed-kotlin-file "com/sfb/ssdreview/SsdPdfDiscovery.kt" + (kotlin-imports (android content ContentResolver) + (android database Cursor) + (android net Uri) + (android os Build) + (android os Environment) + (android provider MediaStore) + (androidx documentfile provider DocumentFile) + (java io File)) + (typed-library (com sfb ssdreview) + (export ssdPdfFindSsdPdfsFromTree ssdPdfFindDownloadSsdPdfs) + (type ContentResolver) + (type Cursor) + (type DocumentFile) + (type Exception) + (type File) + (type Int) + (type Int32) + (type MainActivity) + (type SsdPdfChoice) + (type Uri) + (extern (ssdPdfMaxScanDepthValue) : Int32 + (kotlin-value MAX_SSD_PDF_SCAN_DEPTH)) + (extern (ssdPdfMaxChoicesValue) : Int32 + (kotlin-value MAX_SSD_PDF_CHOICES)) + (extern (ssdPdfBuildSdkIntValue) : Int32 + (kotlin-value Build VERSION SDK_INT)) + (extern (ssdPdfBuildVersionCodesQValue) : Int32 + (kotlin-value Build VERSION_CODES Q)) + (extern (ssdPdfEnvironmentDirectoryDownloadsValue) : String + (kotlin-value Environment DIRECTORY_DOWNLOADS)) + (extern (ssdPdfEnvironmentDownloadsDirectory + (kind : String)) : File + (kotlin-call Environment getExternalStoragePublicDirectory)) + (extern (ssdPdfDocumentFileFromTreeUri + (activity : MainActivity) + (uri : Uri)) : (Nullable DocumentFile) + (kotlin-call DocumentFile fromTreeUri)) + (extern (ssdPdfDocumentFileListFiles + (file : DocumentFile)) : (Array DocumentFile) + (kotlin-member-call listFiles)) + (extern (ssdPdfDocumentFileName + (file : DocumentFile)) : (Nullable String) + (kotlin-member-get name)) + (extern (ssdPdfDocumentFileUri + (file : DocumentFile)) : Uri + (kotlin-member-get uri)) + (extern (ssdPdfMainActivityContentResolver + (activity : MainActivity)) : ContentResolver + (kotlin-member-get contentResolver)) + (extern (ssdPdfMediaStoreDownloadsIdColumn) : String + (kotlin-value MediaStore Downloads _ID)) + (extern (ssdPdfMediaStoreDisplayNameColumn) : String + (kotlin-value MediaStore MediaColumns DISPLAY_NAME)) + (extern (ssdPdfMediaStoreRelativePathColumn) : String + (kotlin-value MediaStore MediaColumns RELATIVE_PATH)) + (extern (ssdPdfMediaStoreMimeTypeColumn) : String + (kotlin-value MediaStore MediaColumns MIME_TYPE)) + (extern (ssdPdfMediaStoreDownloadsExternalContentUri) : Uri + (kotlin-value MediaStore Downloads EXTERNAL_CONTENT_URI)) + (extern (ssdPdfStringListToArray + (items : (List String))) : (Array String) + (kotlin-member-call toTypedArray)) + (extern (ssdPdfContentResolverQuery + (resolver : ContentResolver) + (uri : Uri) + (projection : (Nullable (Array String))) + (selection : (Nullable String)) + (selectionArgs : (Nullable (Array String))) + (sortOrder : (Nullable String))) : (Nullable Cursor) + (kotlin-member-call query)) + (extern (ssdPdfCursorGetColumnIndexOrThrow + (cursor : Cursor) + (name : String)) : Int32 + (kotlin-member-call getColumnIndexOrThrow)) + (extern (ssdPdfCursorClose + (cursor : Cursor)) : Unit + (kotlin-member-call close)) + (def (ssdPdfDiscoveryCursorPresent + (cursor : (Nullable Cursor))) : Bool + (not (nullable-null? cursor))) + (def (ssdPdfDiscoveryProjection) : (Array String) + (ssdPdfStringListToArray + (list-of String + (ssdPdfMediaStoreDownloadsIdColumn) + (ssdPdfMediaStoreDisplayNameColumn) + (ssdPdfMediaStoreRelativePathColumn) + (ssdPdfMediaStoreMimeTypeColumn)))) + (def (ssdPdfDiscoverySelectionArgs) : (Array String) + (ssdPdfStringListToArray + (list-of String "application/pdf" "%.pdf"))) + (def (ssdPdfDocumentSortName + (file : DocumentFile)) : String + (string-lowercase + (nullableTextOrEmpty + (ssdPdfDocumentFileName file)))) + (def (ssdPdfDocumentBefore? + (candidate : DocumentFile) + (existing : DocumentFile)) : Bool + (let ((candidateFile? (ssdPdfDocumentNotDirectory candidate)) + (existingFile? (ssdPdfDocumentNotDirectory existing))) + (if (not (equal? candidateFile? existingFile?)) + (not candidateFile?) + (< (string-compare-to + (ssdPdfDocumentSortName candidate) + (ssdPdfDocumentSortName existing)) + (int32 0))))) + (def (ssdPdfDocumentInsertIndex + (sorted : (MutableList DocumentFile)) + (file : DocumentFile)) : Int32 + (for/fold ((found (int32 -1))) + ((i (in-range (int32 0) (list-size sorted)))) + (if (>= found (int32 0)) + found + (if (ssdPdfDocumentBefore? file (list-ref sorted i)) + i + found)))) + (def (ssdPdfDocumentInsertSorted + (sorted : (MutableList DocumentFile)) + (file : DocumentFile)) : (MutableList DocumentFile) + (let ((insertAt (ssdPdfDocumentInsertIndex sorted file))) + (if (< insertAt (int32 0)) + (begin + (mutable-list-add! sorted file) + sorted) + (let ((out (mutable-list-empty DocumentFile))) + (begin + (for/fold ((ignored (int32 0))) + ((i (in-range (int32 0) (list-size sorted)))) + (begin + (if (= i insertAt) + (begin + (mutable-list-add! out file) + (mutable-list-add! out (list-ref sorted i))) + (mutable-list-add! out (list-ref sorted i))) + ignored)) + out))))) + (def (ssdPdfSortedDocumentChildren + (dir : DocumentFile)) : (MutableList DocumentFile) + (let ((files (ssdPdfDocumentFileListFiles dir))) + (for/fold ((sorted (mutable-list-empty DocumentFile))) + ((i (in-range (int32 0) (list-size files)))) + (ssdPdfDocumentInsertSorted sorted (list-ref files i))))) + (def (ssdPdfCollectTree + (dir : DocumentFile) + (prefix : String) + (choices : (MutableList SsdPdfChoice)) + (depth : Int32)) : Unit + (if (shouldStopSsdPdfTreeScan + depth + (list-size choices) + (ssdPdfMaxChoicesValue) + (ssdPdfMaxScanDepthValue)) + (begin) + (forEachDocumentFile + (ssdPdfSortedDocumentChildren dir) + (lambda ((child : DocumentFile)) + (if (shouldStopSsdPdfTreeScan + depth + (list-size choices) + (ssdPdfMaxChoicesValue) + (ssdPdfMaxScanDepthValue)) + (begin) + (let ((rawName (ssdPdfDocumentFileName child))) + (if (nullableTextPresent rawName) + (let ((name (nullableTextOrEmpty rawName))) + (let ((label (ssdPdfTreeLabel prefix name))) + (if (ssdPdfDocumentIsDirectory child) + (ssdPdfCollectTree + child + label + choices + (+ depth (int32 1))) + (if (shouldIncludeSsdPdfDocument + child + name + (list-size choices) + (ssdPdfMaxChoicesValue)) + (mutable-list-add! + choices + (make-SsdPdfChoice + label + (ssdPdfDocumentFileUri child))) + (begin))))) + (begin)))))))) + (def (ssdPdfFindSsdPdfs + (root : DocumentFile)) : (MutableList SsdPdfChoice) + (let ((choices (mutable-list-empty SsdPdfChoice))) + (begin + (ssdPdfCollectTree root "" choices (int32 0)) + (ssdPdfUniqueSortedLimitedChoices + choices + (ssdPdfMaxChoicesValue))))) + (def (ssdPdfFindSsdPdfsFromTree + (activity : MainActivity) + (treeUri : Uri)) : (List SsdPdfChoice) + (let ((maybeRoot + (ssdPdfDocumentFileFromTreeUri activity treeUri))) + (if (documentFilePresent maybeRoot) + (ssdPdfFindSsdPdfs (nullable-get maybeRoot)) + (mutable-list-empty SsdPdfChoice)))) + (def (ssdPdfFindDownloadSsdPdfsViaMediaStore + (activity : MainActivity)) : (MutableList SsdPdfChoice) + (if (sdkBefore + (ssdPdfBuildSdkIntValue) + (ssdPdfBuildVersionCodesQValue)) + (mutable-list-empty SsdPdfChoice) + (let ((choices (mutable-list-empty SsdPdfChoice))) + (let ((downloadCursor + (ssdPdfContentResolverQuery + (ssdPdfMainActivityContentResolver activity) + (ssdPdfMediaStoreDownloadsExternalContentUri) + (nullable-some (ssdPdfDiscoveryProjection)) + (nullable-some + (mediaStorePdfSelection + (ssdPdfMediaStoreMimeTypeColumn) + (ssdPdfMediaStoreDisplayNameColumn))) + (nullable-some (ssdPdfDiscoverySelectionArgs)) + (nullable-some + (mediaStoreDisplayNameSort + (ssdPdfMediaStoreDisplayNameColumn)))))) + (begin + (if (ssdPdfDiscoveryCursorPresent downloadCursor) + (let ((cursor (nullable-get downloadCursor))) + (try-finally + (collectSsdPdfChoicesFromMediaCursor + cursor + choices + (ssdPdfCursorGetColumnIndexOrThrow + cursor + (ssdPdfMediaStoreDownloadsIdColumn)) + (ssdPdfCursorGetColumnIndexOrThrow + cursor + (ssdPdfMediaStoreDisplayNameColumn)) + (ssdPdfCursorGetColumnIndexOrThrow + cursor + (ssdPdfMediaStoreRelativePathColumn)) + (ssdPdfMediaStoreDownloadsExternalContentUri) + (ssdPdfMaxChoicesValue)) + (ssdPdfCursorClose cursor))) + (begin)) + choices))))) + (def (ssdPdfFindDownloadSsdPdfsViaFiles) : (MutableList SsdPdfChoice) + (let ((dir + (ssdPdfEnvironmentDownloadsDirectory + (ssdPdfEnvironmentDirectoryDownloadsValue)))) + (if (fileIsNotDirectory dir) + (mutable-list-empty SsdPdfChoice) + (let ((choices (mutable-list-empty SsdPdfChoice))) + (begin + (try + (collectSsdPdfChoicesFromDownloadFiles + dir + choices + (ssdPdfMaxScanDepthValue) + (ssdPdfMaxChoicesValue)) + (catch (error : Exception) + (begin))) + choices))))) + (def (ssdPdfFindDownloadSsdPdfs + (activity : MainActivity)) : (List SsdPdfChoice) + (let ((choices (mutable-list-empty SsdPdfChoice))) + (begin + (mutable-list-add-all! + choices + (ssdPdfFindDownloadSsdPdfsViaMediaStore activity)) + (mutable-list-add-all! + choices + (ssdPdfFindDownloadSsdPdfsViaFiles)) + (ssdPdfUniqueSortedLimitedChoices + choices + (ssdPdfMaxChoicesValue))))))) (typed-kotlin-file "com/sfb/ssdreview/MainActivityConstants.kt" (typed-library (com sfb ssdreview) (export DPI