diff --git a/Sources/SkipKit/DocumentPicker.swift b/Sources/SkipKit/DocumentPicker.swift index 4e7792b..8a34cdb 100644 --- a/Sources/SkipKit/DocumentPicker.swift +++ b/Sources/SkipKit/DocumentPicker.swift @@ -42,38 +42,51 @@ extension View { logger.log(message: "selected document uri: \(uri)") if let uri = uri { let resolver = context.contentResolver - + var resolvedName: String? = nil + var resolvedMime: String? = nil + if let query = resolver.query(uri, nil, nil, nil, nil) { - let nameIndex = query.getColumnIndexOrThrow(android.provider.OpenableColumns.DISPLAY_NAME) - let mimetypeIndex = query.getColumnIndexOrThrow(android.provider.DocumentsContract.Document.COLUMN_MIME_TYPE) - query.moveToFirst() - let name = query.getString(nameIndex) - let type = query.getString(mimetypeIndex) - - selectedFilename.wrappedValue = name - selectedFileMimeType.wrappedValue = type - - // To be able to access the file from another part of the app it needs to be copied in tha cached directory: - if let storageDir = context.cacheDir, let url = URL(string: storageDir.path) { - let filemanager = FileManager.default - let destinationFileURL = url.appendingPathComponent(selectedFilename.wrappedValue!) - - if filemanager.fileExists(atPath: destinationFileURL.path) { - try? filemanager.removeItem(at: destinationFileURL) + if query.moveToFirst() { + // Downloads provider omits these columns; tolerate -1. + let nameIndex = query.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME) + if nameIndex >= 0 { + resolvedName = query.getString(nameIndex) + } + let mimeIndex = query.getColumnIndex(android.provider.DocumentsContract.Document.COLUMN_MIME_TYPE) + if mimeIndex >= 0 { + resolvedMime = query.getString(mimeIndex) } - - let inputStream = resolver.openInputStream(uri)! - let outputFile = java.io.File(destinationFileURL.path) - let outputStream = java.io.FileOutputStream(outputFile) + } + query.close() + } + + if resolvedMime == nil { + resolvedMime = resolver.getType(uri) + } + + let safeName: String = resolvedName ?? "import-\(java.util.UUID.randomUUID().toString())" + + selectedFilename.wrappedValue = safeName + selectedFileMimeType.wrappedValue = resolvedMime + + // java.io.File path avoids Skip URL.appendingPathComponent NPE. + if let cacheDir = context.cacheDir { + let destinationFile = java.io.File(cacheDir, safeName) + if destinationFile.exists() { + destinationFile.delete() + } + if let inputStream = resolver.openInputStream(uri) { + let outputStream = java.io.FileOutputStream(destinationFile) inputStream.copyTo(outputStream) - outputStream.close() inputStream.close() - - selectedDocumentURL.wrappedValue = destinationFileURL + // File.toURI() percent-encodes; raw path would crash java.net.URI. + selectedDocumentURL.wrappedValue = URL(platformValue: destinationFile.toURI()) } else { selectedDocumentURL.wrappedValue = URL(platformValue: java.net.URI.create(uri.toString())) } + } else { + selectedDocumentURL.wrappedValue = URL(platformValue: java.net.URI.create(uri.toString())) } } }