Open winjeysong opened 1 month ago
Considering we have the opposite behavior in https://github.com/tauri-apps/plugins-workspace/issues/1578 i have to admit that this is quite confusing to me. Anyway, just wrote this to link to 1578 so that when someone works one of those issues the other one will be looked at & resolved as well.
Thanks for the report.
From my testing the following opens the file dialog:
await open({ filters: [{ extensions: ["pdf", "txt"], name: "Documents" }]});
but interestingly the following opens photo chooser:
await open({ filters: [{ extensions: ["pdf"], name: "Documents" }]});
Checking the source code, open
method can show multiple dialogs depending on the parsing of the filters
attribute so both issues are valid. Parsing logic should be fixed.
Confirmed. Adding the second extension to the extensions array opens the Files app. However, for some reason the target files are greyed out and not selectable.
file = await open({
multiple: false,
directory: false,
filters: [{ name: 'CSV', extensions: ['txt', 'csv'] }]
})
I wonder if this may be of use:
PLEASE USE CAUTION WITH THE CODE BELOW, I am not a Swift developer. I was looking to see what could be the issue with parsing the code and so asked Claude AI. I realize that asking AI may be bad form, but sometimes it proves to be useful.
The code is using kUTTagClassMIMEType
to create the UTI, but it's passing in the file extension. Instead, should it use kUTTagClassFilenameExtension
?
import MobileCoreServices
import Photos
import PhotosUI
import SwiftRs
import Tauri
import UIKit
import WebKit
// ... (previous code remains the same)
class DialogPlugin: Plugin {
var filePickerController: FilePickerController!
var pendingInvoke: Invoke? = nil
var pendingInvokeArgs: FilePickerOptions? = nil
override init() {
super.init()
filePickerController = FilePickerController(self)
}
@objc public func showFilePicker(_ invoke: Invoke) throws {
let args = try invoke.parseArgs(FilePickerOptions.self)
let parsedTypes = parseFiltersOption(args.filters ?? [])
pendingInvoke = invoke
pendingInvokeArgs = args
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = (args.multiple ?? false) ? 0 : 1
if !parsedTypes.isEmpty {
configuration.filter = self.createPHPickerFilter(from: parsedTypes)
}
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self.filePickerController
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
} else {
let picker = UIDocumentPickerViewController(documentTypes: parsedTypes, in: .import)
picker.delegate = self.filePickerController
picker.allowsMultipleSelection = args.multiple ?? false
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}
}
private func parseFiltersOption(_ filters: [Filter]) -> [String] {
var parsedTypes: [String] = []
for filter in filters {
for ext in filter.extensions ?? [] {
if let utType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, ext as CFString, nil)?.takeRetainedValue() as String? {
parsedTypes.append(utType)
} else {
// If we can't get a UTI for the extension, add a wildcard UTI
parsedTypes.append("public.item")
}
}
}
// If no valid types were found, allow all file types
return parsedTypes.isEmpty ? ["public.item"] : parsedTypes
}
@available(iOS 14, *)
private func createPHPickerFilter(from parsedTypes: [String]) -> PHPickerFilter? {
let filters = parsedTypes.compactMap { UTType($0) }.map { PHPickerFilter.any(of: [$0]) }
return filters.isEmpty ? nil : PHPickerFilter.any(of: filters)
}
private func presentViewController(_ viewControllerToPresent: UIViewController) {
self.manager.viewController?.present(viewControllerToPresent, animated: true, completion: nil)
}
// ... (rest of the code remains the same)
}
Thank you, guys
File chooser on a iOS webview asks for chooser type so I think it is best to have different commands/options for choosing the kind of the dialog.
No change when upgrading to RC
tauri-plugin-dialog = "2.0.0-rc.0"
"@tauri-apps/plugin-dialog": "2.0.0-rc.0"
file = await open({
multiple: false,
directory: false,
filters: [{ name: 'CSV', extensions: ['txt', 'csv'] }]
})
Dialog comes up but files cannot be selected. (iOS simulator)
using
open
imported from@tauri-apps/plugin-dialog
will open files picker on iOS 17.5 simulator. Is there a way to determine whether to open photos picker or files picker? I just want to open photos picker byopen
.tauri-plugin-dialog: 2.0.0-beta.11