diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index e4fdd6f..18b5418 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -20,6 +20,7 @@ body: - **Flutter**: 2.5.2 - **Dart**: 2.14.3 - **DocMan version**: 1.0.2 + Android information (optional): - **OS**: Android 11 - **Device**: Pixel 5 diff --git a/android/src/main/kotlin/devdf/plugins/docman/DocManDocumentsProvider.kt b/android/src/main/kotlin/devdf/plugins/docman/DocManDocumentsProvider.kt index 6c99e09..e0471c7 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/DocManDocumentsProvider.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/DocManDocumentsProvider.kt @@ -265,7 +265,7 @@ class DocManDocumentsProvider : DocumentsProvider() { ) removeDocument(sourceDocumentId, sourceParentDocumentId) return newDocumentId - } catch (e: FileNotFoundException) { + } catch (_: FileNotFoundException) { throw FileNotFoundException("Couldn't move document '$sourceDocumentId'") } } diff --git a/android/src/main/kotlin/devdf/plugins/docman/channels/DocManActivity.kt b/android/src/main/kotlin/devdf/plugins/docman/channels/DocManActivity.kt index b3c2f8b..320f518 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/channels/DocManActivity.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/channels/DocManActivity.kt @@ -42,8 +42,8 @@ internal class DocManActivity(private val plugin: DocManPlugin) : EngineBase, override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { - return plugin.queue.methodCast(requestCode) - ?.onActivityResult(resultCode, data) ?: false + return plugin.queue.methodCast(requestCode.toString()) + ?.onActivityResult(resultCode, data) == true } override fun onAttach() { diff --git a/android/src/main/kotlin/devdf/plugins/docman/definitions/DocManInterface.kt b/android/src/main/kotlin/devdf/plugins/docman/definitions/DocManInterface.kt index 1704196..93b2564 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/definitions/DocManInterface.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/definitions/DocManInterface.kt @@ -128,8 +128,8 @@ interface MethodMeta { get() = meta.errorCode val method: String get() = meta.methodName - val requestCode: Int - get() = meta.requestCode + val requestCode: String + get() = meta.requestCode.toString() } diff --git a/android/src/main/kotlin/devdf/plugins/docman/extensions/DocumentFileExt.kt b/android/src/main/kotlin/devdf/plugins/docman/extensions/DocumentFileExt.kt index d67ea28..c18243d 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/extensions/DocumentFileExt.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/extensions/DocumentFileExt.kt @@ -156,7 +156,7 @@ fun DocumentFile.canCreate(context: Context): Boolean = */ //TODO: add additional thumbnail types like docx, xls, maybe others fun DocumentFile.canThumbnailAlternate(context: Context): Boolean = - canRead() && (type == "application/pdf" || isVideo(context) || isImage(context)) + canRead() && (isPDF() || isVideo(context) || isImage(context)) /** Get the persisted URI of the [DocumentFile] * @@ -320,6 +320,9 @@ fun DocumentFile.isVideo(context: Context): Boolean = fun DocumentFile.isVisualMedia(context: Context): Boolean = isImage(context) || isVideo(context) +/** Check if the [DocumentFile] is a PDF file */ +fun DocumentFile.isPDF(): Boolean = type == "application/pdf" + /** Copy the [DocumentFile] to the cache directory. * * Must be called from a coroutine. diff --git a/android/src/main/kotlin/devdf/plugins/docman/extensions/StringExt.kt b/android/src/main/kotlin/devdf/plugins/docman/extensions/StringExt.kt index ab2a309..1b281f7 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/extensions/StringExt.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/extensions/StringExt.kt @@ -13,7 +13,7 @@ fun String.toUri(): Uri { return if (parsedScheme.isNullOrEmpty() || ("${this[0]}" == "/")) { try { Uri.fromFile(File(this)) - } catch (e: Exception) { + } catch (_: Exception) { parsed } } else parsed diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/AppDirsAction.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/AppDirsAction.kt index ffe423d..91eb2d7 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/AppDirsAction.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/AppDirsAction.kt @@ -59,6 +59,7 @@ class AppDirsAction( dirPath?.let { success(it) } ?: dirPathError() } + private fun clear() { // Clear the cache directory, currently only cache directory is supported if (dir == AppDirType.Cache) DocManFiles.clearCacheDirectories(plugin.context) diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileAction.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileAction.kt index ee1c8a6..25d8165 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileAction.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileAction.kt @@ -40,6 +40,8 @@ class DocumentFileAction( override val meta: DocManMethod = DocManMethod.DocumentFileAction + /// Override the requestCode, to allow multiple actions on different documents + override val requestCode: String = call.argument("uri") ?: meta.requestCode.toString() private lateinit var doc: DocumentFile override fun oMethodCall() { diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileActivity.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileActivity.kt index a5d6a4a..538447d 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileActivity.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/DocumentFileActivity.kt @@ -53,8 +53,8 @@ class DocumentFileActivity( } try { - plugin.binding?.activity?.startActivityForResult(intent, requestCode) - } catch (e: Exception) { + plugin.binding?.activity?.startActivityForResult(intent, requestCode.toInt()) + } catch (_: Exception) { plugin.queue.finishWithError(requestCode, "no_activity", action, null) } } @@ -79,7 +79,7 @@ class DocumentFileActivity( } private fun actionCreateDocumentIntent(): Intent { - val localOnly = call.argument("localOnly") ?: false + val localOnly = call.argument("localOnly") == true val initDir = call.argument("initDir") return Intent(Intent.ACTION_CREATE_DOCUMENT).apply { addCategory(Intent.CATEGORY_OPENABLE) @@ -104,7 +104,7 @@ class DocumentFileActivity( } private fun processSaveTo(data: Intent?) { - val deleteSource = call.argument("deleteSource") ?: false + val deleteSource = call.argument("deleteSource") == true if (data != null && data.data != null) { CoroutineScope(Dispatchers.IO).launch { val newDoc = doc.saveToUri(data.data!!, deleteSource, plugin.context) diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsAction.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsAction.kt index cbd322a..e9c16e2 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsAction.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsAction.kt @@ -32,9 +32,9 @@ class PermissionsAction( private val uri: Uri? = call.argument("uri")?.toUri() - private val dirs: Boolean = call.argument("dirs") ?: true + private val dirs: Boolean = call.argument("dirs") != false - private val files: Boolean = call.argument("files") ?: true + private val files: Boolean = call.argument("files") != false override fun oMethodCall() { //Validate the action diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsEvents.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsEvents.kt index 650a0da..68c6bf4 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsEvents.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/PermissionsEvents.kt @@ -18,8 +18,8 @@ class PermissionsEvents( override val meta: DocManMethod = DocManMethod.PermissionsEvent - private val dirs = call.argument("dirs") ?: true - private val files = call.argument("files") ?: true + private val dirs = call.argument("dirs") != false + private val files = call.argument("files") != false override suspend fun onListen() { when (val action = call.argument("action")) { diff --git a/android/src/main/kotlin/devdf/plugins/docman/methods/PickActivity.kt b/android/src/main/kotlin/devdf/plugins/docman/methods/PickActivity.kt index 1b1b989..24d184e 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/methods/PickActivity.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/methods/PickActivity.kt @@ -81,13 +81,13 @@ internal data class PickActivityArgs( call.argAsListString("mimeTypes"), call.argAsListString("extensions") ), - localOnly = call.argument("localOnly") ?: false, - grantPermissions = call.argument("grantPermissions") ?: true, + localOnly = call.argument("localOnly") == true, + grantPermissions = call.argument("grantPermissions") != false, limit = call.argument("limit") ?: 1, limitResult = PickLimitResult.fromString(call.argument("limitType")), limitToast = call.argument("limitToast") ?: "Pick limit reached", imageQuality = call.argument("imageQuality") ?: 100, - usePhotoPicker = call.argument("usePhotoPicker") ?: true, + usePhotoPicker = call.argument("usePhotoPicker") != false, initDir = call.argument("initDir") ) } @@ -135,8 +135,8 @@ class PickActivity( //2. Start the activity try { - plugin.binding?.activity?.startActivityForResult(activityIntent(), requestCode) - } catch (e: Exception) { + plugin.binding?.activity?.startActivityForResult(activityIntent(), requestCode.toInt()) + } catch (_: Exception) { plugin.queue.finishWithError( requestCode, "no_activity", diff --git a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManFiles.kt b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManFiles.kt index 10abd63..2f3eb59 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManFiles.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManFiles.kt @@ -17,6 +17,7 @@ import devdf.plugins.docman.extensions.getFileExtension import devdf.plugins.docman.extensions.isAppFile import devdf.plugins.docman.extensions.isImage import devdf.plugins.docman.extensions.isMediaMimeType +import devdf.plugins.docman.extensions.isPDF import devdf.plugins.docman.extensions.isVideo import devdf.plugins.docman.extensions.isVisualMedia import devdf.plugins.docman.extensions.nameAsFileName @@ -179,7 +180,7 @@ class DocManFiles { /** Read the content of the [DocumentFile] as a byte array */ fun readDocumentFile(doc: DocumentFile, context: Context): ByteArray? = try { context.contentResolver.openInputStream(doc.uri)?.use { it.readBytes() } - } catch (e: Exception) { + } catch (_: Exception) { null } @@ -239,7 +240,7 @@ class DocManFiles { } targetFile.path } - } catch (e: Exception) { + } catch (_: Exception) { null } } @@ -256,7 +257,7 @@ class DocManFiles { when { doc.isVideo(context) -> DocManMedia.videoThumbnail(doc, thumbSize, context) - doc.type == "application/pdf" -> DocManMedia.pdfThumbnail( + doc.isPDF() -> DocManMedia.pdfThumbnail( doc, thumbSize, context diff --git a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMedia.kt b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMedia.kt index 68d5c5f..19894d4 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMedia.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMedia.kt @@ -16,6 +16,7 @@ import android.util.Size import androidx.documentfile.provider.DocumentFile import devdf.plugins.docman.extensions.canThumbnailAlternate import devdf.plugins.docman.extensions.isImage +import devdf.plugins.docman.extensions.isPDF import devdf.plugins.docman.extensions.isVideo import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext @@ -73,13 +74,17 @@ class DocManMedia { size: Size, context: Context, ): Bitmap? = runCatching { - //1. Check if we can get thumbnail from the document fastest way - DocumentsContract.getDocumentThumbnail( - context.contentResolver, - doc.uri, - Point(size.width, size.height), - null - ) + //1. If document is local file just skip this section + //1.1. Check if we can get thumbnail from the document fastest way + if (doc.uri.scheme != "file") { + DocumentsContract.getDocumentThumbnail( + context.contentResolver, + doc.uri, + Point(size.width, size.height), + null + ) + } else null + }.getOrNull() ?: runCatching { //2. If not, try to load thumbnail from content resolver if allowed if (DocManBuild.loadThumbnail()) { @@ -90,7 +95,7 @@ class DocManMedia { when { doc.isImage(context) -> imageThumbnail(doc, size, context) doc.isVideo(context) -> videoThumbnail(doc, size, context) - doc.type == "application/pdf" -> pdfThumbnail(doc, size, context) + doc.isPDF() -> pdfThumbnail(doc, size, context) else -> null } } else null diff --git a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMimeType.kt b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMimeType.kt index df581f1..7438df8 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMimeType.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManMimeType.kt @@ -77,7 +77,7 @@ class DocManMimeType { cursor.getString(cursor.getColumnIndexOrThrow(column)) } else null } - } catch (e: Exception) { + } catch (_: Exception) { null } } @@ -87,7 +87,7 @@ class DocManMimeType { return try { retriever.setDataSource(context, uri) retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_MIMETYPE) - } catch (e: Exception) { + } catch (_: Exception) { null } finally { retriever.release() diff --git a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManProviderSettings.kt b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManProviderSettings.kt index 3ce6834..d3d4327 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManProviderSettings.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManProviderSettings.kt @@ -14,11 +14,11 @@ data class DirectoryFlags( ) { companion object { fun fromJson(resultMap: Map?): DirectoryFlags = DirectoryFlags( - create = resultMap?.get("create") as? Boolean ?: true, - delete = resultMap?.get("delete") as? Boolean ?: true, - move = resultMap?.get("move") as? Boolean ?: true, - rename = resultMap?.get("rename") as? Boolean ?: true, - copy = resultMap?.get("copy") as? Boolean ?: true, + create = resultMap?.get("create") as? Boolean != false, + delete = resultMap?.get("delete") as? Boolean != false, + move = resultMap?.get("move") as? Boolean != false, + rename = resultMap?.get("rename") as? Boolean != false, + copy = resultMap?.get("copy") as? Boolean != false, ) } } @@ -33,12 +33,12 @@ data class FileFlags( ) { companion object { fun fromJson(resultMap: Map?): FileFlags = FileFlags( - write = resultMap?.get("write") as? Boolean ?: true, - delete = resultMap?.get("delete") as? Boolean ?: true, - move = resultMap?.get("move") as? Boolean ?: true, - rename = resultMap?.get("rename") as? Boolean ?: true, - copy = resultMap?.get("copy") as? Boolean ?: true, - thumbnail = resultMap?.get("thumbnail") as? Boolean ?: true, + write = resultMap?.get("write") as? Boolean != false, + delete = resultMap?.get("delete") as? Boolean != false, + move = resultMap?.get("move") as? Boolean != false, + rename = resultMap?.get("rename") as? Boolean != false, + copy = resultMap?.get("copy") as? Boolean != false, + thumbnail = resultMap?.get("thumbnail") as? Boolean != false, ) } } @@ -79,9 +79,9 @@ class DocManProviderSettings( providerName = map["providerName"] as? String, providerSubtitle = map["providerSubtitle"] as? String, mimeTypes = mimeTypes, - showInSystemUI = map["showInSystemUI"] as? Boolean ?: true, - supportRecent = map["supportRecent"] as? Boolean ?: true, - supportSearch = map["supportSearch"] as? Boolean ?: true, + showInSystemUI = map["showInSystemUI"] as? Boolean != false, + supportRecent = map["supportRecent"] as? Boolean != false, + supportSearch = map["supportSearch"] as? Boolean != false, maxRecentFiles = map["maxRecentFiles"] as? Int ?: 15, maxSearchResults = map["maxSearchResults"] as? Int ?: 10, directoryFlags = dirFlags, diff --git a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManQueueManager.kt b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManQueueManager.kt index e2f7c3e..9c18cee 100644 --- a/android/src/main/kotlin/devdf/plugins/docman/utils/DocManQueueManager.kt +++ b/android/src/main/kotlin/devdf/plugins/docman/utils/DocManQueueManager.kt @@ -5,7 +5,8 @@ import devdf.plugins.docman.extensions.alreadyRunning /** Queue for the method calls, and manages the method calls in it. */ class DocManQueueManager { - val queue: MutableMap = mutableMapOf() + /** The queue used for all methods for activity channel, */ + val queue: MutableMap = mutableMapOf() /** Adds method to the queue with validation. * If the method is already in the queue, set result as error, @@ -33,7 +34,7 @@ class DocManQueueManager { * @param result Any data to send as result. * @return true if the method call is removed from the queue, false otherwise. */ - fun finishWithSuccess(requestCode: Int, result: Any?): Boolean { + fun finishWithSuccess(requestCode: String, result: Any?): Boolean { //1. Send the result method(requestCode)?.result?.success(result) //2. Remove the method call from the queue @@ -51,7 +52,7 @@ class DocManQueueManager { * @return true if the method call is removed from the queue, false otherwise. */ fun finishWithError( - request: Int, + request: String, code: String, message: String?, details: Any? @@ -71,7 +72,7 @@ class DocManQueueManager { * It's `ordinal` from the `DocManMethod` enum. * @return true if the method call is removed from the queue, false otherwise. */ - fun finishNotImplemented(requestCode: Int): Boolean { + fun finishNotImplemented(requestCode: String): Boolean { //1. Send the error method(requestCode)?.result?.notImplemented() //2. Remove the method call from the queue @@ -85,7 +86,7 @@ class DocManQueueManager { * It's `ordinal` from the `DocManMethod` enum. * @return The method that was removed from the queue. */ - fun remove(requestCode: Int): MethodBase? = + fun remove(requestCode: String): MethodBase? = queue.remove(requestCode) /** Get the method call from the queue with the [requestCode] @@ -94,7 +95,7 @@ class DocManQueueManager { * It's `ordinal` from the `DocManMethod` enum. * @return The method call. * */ - fun method(requestCode: Int): MethodBase? = queue[requestCode] + fun method(requestCode: String): MethodBase? = queue[requestCode] /** Get the method call from the queue with the [requestCode] * @@ -102,7 +103,7 @@ class DocManQueueManager { * It's `ordinal` from the `DocManMethod` enum. * @return The method call casted to the [T] type. * */ - inline fun methodCast(requestCode: Int): T? { + inline fun methodCast(requestCode: String): T? { return queue[requestCode] as? T } } \ No newline at end of file diff --git a/example/pubspec.lock b/example/pubspec.lock index a7d5b5f..02afb87 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: lints - sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 url: "https://pub.dev" source: hosted - version: "5.0.0" + version: "5.1.1" matcher: dependency: transitive description: @@ -271,5 +271,5 @@ packages: source: hosted version: "3.0.4" sdks: - dart: ">=3.5.2 <4.0.0" + dart: ">=3.6.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/lib/src/data/document_thumbnail.dart b/lib/src/data/document_thumbnail.dart index 166fd4f..aae2ebf 100644 --- a/lib/src/data/document_thumbnail.dart +++ b/lib/src/data/document_thumbnail.dart @@ -30,6 +30,8 @@ class DocumentThumbnail { height: map['height'] as int, ); + //TODO get thumbnail directly from filePath or Uri + /// Converts the instance to a map. Map toMap() => { 'bytes': bytes, @@ -39,7 +41,7 @@ class DocumentThumbnail { @override String toString() => - 'DocumentThumbnail(bytes: $bytes, width: $width, height: $height)'; + 'DocumentThumbnail(bytes: ${bytes.length}, width: $width, height: $height)'; @override bool operator ==(Object other) {