feat: update to alpha.17, typed mobile plugin IPC arguments (#676)

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
This commit is contained in:
Lucas Fernandes Nogueira
2023-10-29 16:06:44 -03:00
committed by GitHub
parent 76cfdc32b4
commit e438e0a62d
158 changed files with 1677 additions and 1658 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
## \[2.0.0-alpha.2]
- [`5c13736`](https://github.com/tauri-apps/plugins-workspace/commit/5c137365c60790e8d4037d449e8237aa3fffdab0)([#673](https://github.com/tauri-apps/plugins-workspace/pull/673)) Update to @tauri-apps/api v2.0.0-alpha.16.
- [`5c13736`](https://github.com/tauri-apps/plugins-workspace/commit/5c137365c60790e8d4037d449e8237aa3fffdab0)([#673](https://github.com/tauri-apps/plugins-workspace/pull/673)) Update to @tauri-apps/api v2.0.0-alpha.9.
## \[2.0.0-alpha.2]
+3 -5
View File
@@ -9,7 +9,8 @@ rust-version = { workspace = true }
links = "tauri-plugin-dialog"
[package.metadata.docs.rs]
features = [ "dox" ]
rustc-args = [ "--cfg", "docsrs" ]
rustdoc-args = [ "--cfg", "docsrs" ]
targets = [ "x86_64-unknown-linux-gnu", "x86_64-linux-android" ]
[dependencies]
@@ -24,11 +25,8 @@ tauri-plugin-fs = { path = "../fs", version = "2.0.0-alpha.3" }
glib = "0.16"
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
rfd = { version = "0.11", features = [ "gtk3", "common-controls-v6" ] }
rfd = { version = "0.12", features = [ "gtk3", "common-controls-v6" ] }
raw-window-handle = "0.5"
[build-dependencies]
tauri-build = { workspace = true }
[features]
dox = [ "tauri/dox" ]
@@ -14,24 +14,44 @@ import androidx.activity.result.ActivityResult
import app.tauri.Logger
import app.tauri.annotation.ActivityCallback
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.Invoke
import app.tauri.plugin.JSArray
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import org.json.JSONException
@InvokeArg
class Filter {
lateinit var extensions: Array<String>
}
@InvokeArg
class FilePickerOptions {
lateinit var filters: Array<Filter>
var multiple: Boolean? = null
var readData: Boolean? = null
}
@InvokeArg
class MessageOptions {
var title: String?
lateinit var message: String
var okButtonLabel: String?
var cancelButtonLabel: String?
}
@TauriPlugin
class DialogPlugin(private val activity: Activity): Plugin(activity) {
var filePickerOptions: FilePickerOptions? = null
@Command
fun showFilePicker(invoke: Invoke) {
try {
val filters = invoke.getArray("filters", JSArray())
val multiple = invoke.getBoolean("multiple", false)
val parsedTypes = parseFiltersOption(filters)
val args = invoke.parseArgs(FilePickerOptions::class.java)
val parsedTypes = parseFiltersOption(args.filters)
val intent = if (parsedTypes != null && parsedTypes.isNotEmpty()) {
val intent = if (parsedTypes.isNotEmpty()) {
val intent = Intent(Intent.ACTION_PICK)
intent.putExtra(Intent.EXTRA_MIME_TYPES, parsedTypes)
@@ -55,7 +75,7 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
intent
}
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, multiple)
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, args.multiple ?: false)
startActivityForResult(invoke, intent, "filePickerResult")
} catch (ex: Exception) {
@@ -68,10 +88,9 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
@ActivityCallback
fun filePickerResult(invoke: Invoke, result: ActivityResult) {
try {
val readData = invoke.getBoolean("readData", false)
when (result.resultCode) {
Activity.RESULT_OK -> {
val callResult = createPickFilesResult(result.data, readData)
val callResult = createPickFilesResult(result.data, filePickerOptions?.readData ?: false)
invoke.resolve(callResult)
}
Activity.RESULT_CANCELED -> invoke.reject("File picker cancelled")
@@ -130,36 +149,19 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
return callResult
}
private fun parseFiltersOption(filters: JSArray): Array<String>? {
return try {
val filtersList: List<JSObject> = filters.toList()
val mimeTypes = mutableListOf<String>()
for (filter in filtersList) {
val extensionsList = filter.getJSONArray("extensions")
for (i in 0 until extensionsList.length()) {
val mime = extensionsList.getString(i)
mimeTypes.add(if (mime == "text/csv") "text/comma-separated-values" else mime)
}
private fun parseFiltersOption(filters: Array<Filter>): Array<String> {
val mimeTypes = mutableListOf<String>()
for (filter in filters) {
for (mime in filter.extensions) {
mimeTypes.add(if (mime == "text/csv") "text/comma-separated-values" else mime)
}
mimeTypes.toTypedArray()
} catch (exception: JSONException) {
Logger.error("parseTypesOption failed.", exception)
null
}
return mimeTypes.toTypedArray()
}
@Command
fun showMessageDialog(invoke: Invoke) {
val title = invoke.getString("title")
val message = invoke.getString("message")
val okButtonLabel = invoke.getString("okButtonLabel", "OK")
val cancelButtonLabel = invoke.getString("cancelButtonLabel", "Cancel")
if (message == null) {
invoke.reject("The `message` argument is required")
return
}
val args = invoke.parseArgs(MessageOptions::class.java)
if (activity.isFinishing) {
invoke.reject("App is finishing")
@@ -177,19 +179,19 @@ class DialogPlugin(private val activity: Activity): Plugin(activity) {
.post {
val builder = AlertDialog.Builder(activity)
if (title != null) {
builder.setTitle(title)
if (args.title != null) {
builder.setTitle(args.title)
}
builder
.setMessage(message)
.setMessage(args.message)
.setPositiveButton(
okButtonLabel
args.okButtonLabel ?: "OK"
) { dialog, _ ->
dialog.dismiss()
handler(false, true)
}
.setNegativeButton(
cancelButtonLabel
args.cancelButtonLabel ?: "Cancel"
) { dialog, _ ->
dialog.dismiss()
handler(false, false)
+1 -1
View File
@@ -10,7 +10,7 @@ fn main() {
{
println!("{error:#}");
// when building documentation for Android the plugin build result is irrelevant to the crate itself
if !(cfg!(feature = "dox") && std::env::var("TARGET").unwrap().contains("android")) {
if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
std::process::exit(1);
}
}
+199 -183
View File
@@ -2,207 +2,223 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import UIKit
import MobileCoreServices
import PhotosUI
import Photos
import WebKit
import Tauri
import PhotosUI
import SwiftRs
import Tauri
import UIKit
import WebKit
enum FilePickerEvent {
case selected([URL])
case cancelled
case error(String)
case selected([URL])
case cancelled
case error(String)
}
struct MessageDialogOptions: Decodable {
let title: String?
let message: String
var okButtonLabel = "OK"
var cancelButtonLabel = "Cancel"
}
struct Filter: Decodable {
var extensions: [String] = []
}
struct FilePickerOptions: Decodable {
var multiple = false
var readData = false
var filters: [Filter] = []
}
class DialogPlugin: Plugin {
var filePickerController: FilePickerController!
var pendingInvoke: Invoke? = nil
var filePickerController: FilePickerController!
var pendingInvoke: Invoke? = nil
var pendingInvokeArgs: FilePickerOptions? = nil
override init() {
super.init()
filePickerController = FilePickerController(self)
}
@objc public func showFilePicker(_ invoke: Invoke) {
let multiple = invoke.getBool("multiple", false)
let filters = invoke.getArray("filters") ?? []
let parsedTypes = parseFiltersOption(filters)
var isMedia = true
var uniqueMimeType: Bool? = nil
var mimeKind: String? = nil
if !parsedTypes.isEmpty {
uniqueMimeType = true
for mime in parsedTypes {
let kind = mime.components(separatedBy: "/")[0]
if kind != "image" && kind != "video" {
isMedia = false
}
if (mimeKind == nil) {
mimeKind = kind
} else if (mimeKind != kind) {
uniqueMimeType = false
}
}
}
pendingInvoke = invoke
if uniqueMimeType == true || isMedia {
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = multiple ? 0 : 1
if uniqueMimeType == true {
if mimeKind == "image" {
configuration.filter = .images
} else if mimeKind == "video" {
configuration.filter = .videos
}
}
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self.filePickerController
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
} else {
let picker = UIImagePickerController()
picker.delegate = self.filePickerController
if uniqueMimeType == true && mimeKind == "image" {
picker.sourceType = .photoLibrary
}
picker.sourceType = .photoLibrary
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}
} else {
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes
DispatchQueue.main.async {
let picker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import)
picker.delegate = self.filePickerController
picker.allowsMultipleSelection = multiple
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}
}
private func presentViewController(_ viewControllerToPresent: UIViewController) {
self.manager.viewController?.present(viewControllerToPresent, animated: true, completion: nil)
}
private func parseFiltersOption(_ filters: JSArray) -> [String] {
var parsedTypes: [String] = []
for (_, filter) in filters.enumerated() {
let filterObj = filter as? JSObject
if let filterObj = filterObj {
let extensions = filterObj["extensions"] as? JSArray
if let extensions = extensions {
for e in extensions {
let ext = e as? String ?? ""
guard let utType: String = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, ext as CFString, nil)?.takeRetainedValue() as String? else {
continue
}
parsedTypes.append(utType)
}
}
}
}
return parsedTypes
override init() {
super.init()
filePickerController = FilePickerController(self)
}
public func onFilePickerEvent(_ event: FilePickerEvent) {
switch event {
case .selected(let urls):
let readData = pendingInvoke?.getBool("readData", false) ?? false
do {
let filesResult = try urls.map {(url: URL) -> JSObject in
var file = JSObject()
@objc public func showFilePicker(_ invoke: Invoke) throws {
let args = try invoke.parseArgs(FilePickerOptions.self)
let mimeType = filePickerController.getMimeTypeFromUrl(url)
let isVideo = mimeType.hasPrefix("video")
let isImage = mimeType.hasPrefix("image")
let parsedTypes = parseFiltersOption(args.filters)
if readData {
file["data"] = try Data(contentsOf: url).base64EncodedString()
}
if isVideo {
file["duration"] = filePickerController.getVideoDuration(url)
let (height, width) = filePickerController.getVideoDimensions(url)
if let height = height {
file["height"] = height
}
if let width = width {
file["width"] = width
}
} else if isImage {
let (height, width) = filePickerController.getImageDimensions(url)
if let height = height {
file["height"] = height
}
if let width = width {
file["width"] = width
}
}
file["modifiedAt"] = filePickerController.getModifiedAtFromUrl(url)
file["mimeType"] = mimeType
file["name"] = url.lastPathComponent
file["path"] = url.absoluteString
file["size"] = try filePickerController.getSizeFromUrl(url)
return file
}
pendingInvoke?.resolve(["files": filesResult])
} catch let error as NSError {
pendingInvoke?.reject(error.localizedDescription, nil, error)
return
var isMedia = true
var uniqueMimeType: Bool? = nil
var mimeKind: String? = nil
if !parsedTypes.isEmpty {
uniqueMimeType = true
for mime in parsedTypes {
let kind = mime.components(separatedBy: "/")[0]
if kind != "image" && kind != "video" {
isMedia = false
}
if mimeKind == nil {
mimeKind = kind
} else if mimeKind != kind {
uniqueMimeType = false
}
}
}
pendingInvoke?.resolve(["files": urls])
case .cancelled:
let files: JSArray = []
pendingInvoke?.resolve(["files": files])
case .error(let error):
pendingInvoke?.reject(error)
}
}
pendingInvoke = invoke
pendingInvokeArgs = args
@objc public func showMessageDialog(_ invoke: Invoke) {
let manager = self.manager
let title = invoke.getString("title")
guard let message = invoke.getString("message") else {
invoke.reject("The `message` argument is required")
return
}
let okButtonLabel = invoke.getString("okButtonLabel") ?? "OK"
let cancelButtonLabel = invoke.getString("cancelButtonLabel") ?? "Cancel"
DispatchQueue.main.async { [] in
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: cancelButtonLabel, style: UIAlertAction.Style.default, handler: { (_) -> Void in
invoke.resolve([
"value": false,
"cancelled": false
])
}))
alert.addAction(UIAlertAction(title: okButtonLabel, style: UIAlertAction.Style.default, handler: { (_) -> Void in
invoke.resolve([
"value": true,
"cancelled": false
])
}))
if uniqueMimeType == true || isMedia {
DispatchQueue.main.async {
if #available(iOS 14, *) {
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
configuration.selectionLimit = args.multiple ? 0 : 1
manager.viewController?.present(alert, animated: true, completion: nil)
}
}
if uniqueMimeType == true {
if mimeKind == "image" {
configuration.filter = .images
} else if mimeKind == "video" {
configuration.filter = .videos
}
}
let picker = PHPickerViewController(configuration: configuration)
picker.delegate = self.filePickerController
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
} else {
let picker = UIImagePickerController()
picker.delegate = self.filePickerController
if uniqueMimeType == true && mimeKind == "image" {
picker.sourceType = .photoLibrary
}
picker.sourceType = .photoLibrary
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}
} else {
let documentTypes = parsedTypes.isEmpty ? ["public.data"] : parsedTypes
DispatchQueue.main.async {
let picker = UIDocumentPickerViewController(documentTypes: documentTypes, in: .import)
picker.delegate = self.filePickerController
picker.allowsMultipleSelection = args.multiple
picker.modalPresentationStyle = .fullScreen
self.presentViewController(picker)
}
}
}
private func presentViewController(_ viewControllerToPresent: UIViewController) {
self.manager.viewController?.present(viewControllerToPresent, animated: true, completion: nil)
}
private func parseFiltersOption(_ filters: [Filter]) -> [String] {
var parsedTypes: [String] = []
for filter in filters {
for ext in filter.extensions {
guard
let utType: String = UTTypeCreatePreferredIdentifierForTag(
kUTTagClassMIMEType, ext as CFString, nil)?.takeRetainedValue() as String?
else {
continue
}
parsedTypes.append(utType)
}
}
return parsedTypes
}
public func onFilePickerEvent(_ event: FilePickerEvent) {
switch event {
case .selected(let urls):
let readData = pendingInvokeArgs?.readData ?? false
do {
let filesResult = try urls.map { (url: URL) -> JSObject in
var file = JSObject()
let mimeType = filePickerController.getMimeTypeFromUrl(url)
let isVideo = mimeType.hasPrefix("video")
let isImage = mimeType.hasPrefix("image")
if readData {
file["data"] = try Data(contentsOf: url).base64EncodedString()
}
if isVideo {
file["duration"] = filePickerController.getVideoDuration(url)
let (height, width) = filePickerController.getVideoDimensions(url)
if let height = height {
file["height"] = height
}
if let width = width {
file["width"] = width
}
} else if isImage {
let (height, width) = filePickerController.getImageDimensions(url)
if let height = height {
file["height"] = height
}
if let width = width {
file["width"] = width
}
}
file["modifiedAt"] = filePickerController.getModifiedAtFromUrl(url)
file["mimeType"] = mimeType
file["name"] = url.lastPathComponent
file["path"] = url.absoluteString
file["size"] = try filePickerController.getSizeFromUrl(url)
return file
}
pendingInvoke?.resolve(["files": filesResult])
} catch let error as NSError {
pendingInvoke?.reject(error.localizedDescription, error: error)
return
}
pendingInvoke?.resolve(["files": urls])
case .cancelled:
let files: JSArray = []
pendingInvoke?.resolve(["files": files])
case .error(let error):
pendingInvoke?.reject(error)
}
}
@objc public func showMessageDialog(_ invoke: Invoke) throws {
let manager = self.manager
let args = try invoke.parseArgs(MessageDialogOptions.self)
DispatchQueue.main.async { [] in
let alert = UIAlertController(
title: args.title, message: args.message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(
UIAlertAction(
title: args.cancelButtonLabel, style: UIAlertAction.Style.default,
handler: { (_) -> Void in
invoke.resolve([
"value": false,
"cancelled": false,
])
}))
alert.addAction(
UIAlertAction(
title: args.okButtonLabel, style: UIAlertAction.Style.default,
handler: { (_) -> Void in
invoke.resolve([
"value": true,
"cancelled": false,
])
}))
manager.viewController?.present(alert, animated: true, completion: nil)
}
}
}
@_cdecl("init_plugin_dialog")
+1 -1
View File
@@ -27,6 +27,6 @@
"tslib": "^2.4.1"
},
"dependencies": {
"@tauri-apps/api": "2.0.0-alpha.9"
"@tauri-apps/api": "2.0.0-alpha.11"
}
}
+1 -1
View File
@@ -1 +1 @@
if("__TAURI__"in window){var __TAURI_DIALOG__=function(n){"use strict";var t=Object.defineProperty,e=(n,t,e)=>{if(!t.has(n))throw TypeError("Cannot "+e)},i=(n,t,i)=>(e(n,t,"read from private field"),i?i.call(n):t.get(n));function o(n,t=!1){return window.__TAURI_INTERNALS__.transformCallback(n,t)}((n,e)=>{for(var i in e)t(n,i,{get:e[i],enumerable:!0})})({},{Channel:()=>r,PluginListener:()=>a,addPluginListener:()=>s,convertFileSrc:()=>d,invoke:()=>u,transformCallback:()=>o});var l,r=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((n,t,e)=>{if(t.has(n))throw TypeError("Cannot add the same private member more than once");t instanceof WeakSet?t.add(n):t.set(n,e)})(this,l,(()=>{})),this.id=o((n=>{i(this,l).call(this,n)}))}set onmessage(n){var t,i,o,r;o=n,e(t=this,i=l,"write to private field"),r?r.call(t,o):i.set(t,o)}get onmessage(){return i(this,l)}toJSON(){return`__CHANNEL__:${this.id}`}};l=new WeakMap;var a=class{constructor(n,t,e){this.plugin=n,this.event=t,this.channelId=e}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function s(n,t,e){let i=new r;return i.onmessage=e,u(`plugin:${n}|register_listener`,{event:t,handler:i}).then((()=>new a(n,t,i.id)))}async function u(n,t={},e){return window.__TAURI_INTERNALS__.invoke(n,t,e)}function d(n,t="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(n,t)}return n.ask=async function(n,t){var e,i,o,l,r;const a="string"==typeof t?{title:t}:t;return u("plugin:dialog|ask",{message:n.toString(),title:null===(e=null==a?void 0:a.title)||void 0===e?void 0:e.toString(),type_:null==a?void 0:a.type,okButtonLabel:null!==(o=null===(i=null==a?void 0:a.okLabel)||void 0===i?void 0:i.toString())&&void 0!==o?o:"Yes",cancelButtonLabel:null!==(r=null===(l=null==a?void 0:a.cancelLabel)||void 0===l?void 0:l.toString())&&void 0!==r?r:"No"})},n.confirm=async function(n,t){var e,i,o,l,r;const a="string"==typeof t?{title:t}:t;return u("plugin:dialog|confirm",{message:n.toString(),title:null===(e=null==a?void 0:a.title)||void 0===e?void 0:e.toString(),type_:null==a?void 0:a.type,okButtonLabel:null!==(o=null===(i=null==a?void 0:a.okLabel)||void 0===i?void 0:i.toString())&&void 0!==o?o:"Ok",cancelButtonLabel:null!==(r=null===(l=null==a?void 0:a.cancelLabel)||void 0===l?void 0:l.toString())&&void 0!==r?r:"Cancel"})},n.message=async function(n,t){var e,i;const o="string"==typeof t?{title:t}:t;return u("plugin:dialog|message",{message:n.toString(),title:null===(e=null==o?void 0:o.title)||void 0===e?void 0:e.toString(),type_:null==o?void 0:o.type,okButtonLabel:null===(i=null==o?void 0:o.okLabel)||void 0===i?void 0:i.toString()})},n.open=async function(n={}){return"object"==typeof n&&Object.freeze(n),u("plugin:dialog|open",{options:n})},n.save=async function(n={}){return"object"==typeof n&&Object.freeze(n),u("plugin:dialog|save",{options:n})},n}({});Object.defineProperty(window.__TAURI__,"dialog",{value:__TAURI_DIALOG__})}
if("__TAURI__"in window){var __TAURI_DIALOG__=function(n){"use strict";async function o(n,o={},t){return window.__TAURI_INTERNALS__.invoke(n,o,t)}return"function"==typeof SuppressedError&&SuppressedError,n.ask=async function(n,t){var i,l,e,u,r;const d="string"==typeof t?{title:t}:t;return o("plugin:dialog|ask",{message:n.toString(),title:null===(i=null==d?void 0:d.title)||void 0===i?void 0:i.toString(),type_:null==d?void 0:d.type,okButtonLabel:null!==(e=null===(l=null==d?void 0:d.okLabel)||void 0===l?void 0:l.toString())&&void 0!==e?e:"Yes",cancelButtonLabel:null!==(r=null===(u=null==d?void 0:d.cancelLabel)||void 0===u?void 0:u.toString())&&void 0!==r?r:"No"})},n.confirm=async function(n,t){var i,l,e,u,r;const d="string"==typeof t?{title:t}:t;return o("plugin:dialog|confirm",{message:n.toString(),title:null===(i=null==d?void 0:d.title)||void 0===i?void 0:i.toString(),type_:null==d?void 0:d.type,okButtonLabel:null!==(e=null===(l=null==d?void 0:d.okLabel)||void 0===l?void 0:l.toString())&&void 0!==e?e:"Ok",cancelButtonLabel:null!==(r=null===(u=null==d?void 0:d.cancelLabel)||void 0===u?void 0:u.toString())&&void 0!==r?r:"Cancel"})},n.message=async function(n,t){var i,l;const e="string"==typeof t?{title:t}:t;return o("plugin:dialog|message",{message:n.toString(),title:null===(i=null==e?void 0:e.title)||void 0===i?void 0:i.toString(),type_:null==e?void 0:e.type,okButtonLabel:null===(l=null==e?void 0:e.okLabel)||void 0===l?void 0:l.toString()})},n.open=async function(n={}){return"object"==typeof n&&Object.freeze(n),o("plugin:dialog|open",{options:n})},n.save=async function(n={}){return"object"==typeof n&&Object.freeze(n),o("plugin:dialog|save",{options:n})},n}({});Object.defineProperty(window.__TAURI__,"dialog",{value:__TAURI_DIALOG__})}
+8 -2
View File
@@ -56,7 +56,10 @@ macro_rules! run_dialog {
($e:expr, $h: ident) => {{
std::thread::spawn(move || {
let response = tauri::async_runtime::block_on($e);
$h(response);
$h(!matches!(
response,
rfd::MessageDialogResult::No | rfd::MessageDialogResult::Cancel
));
});
}};
}
@@ -68,7 +71,10 @@ macro_rules! run_dialog {
let context = glib::MainContext::default();
context.invoke_with_priority(glib::PRIORITY_HIGH, move || {
let response = $e;
$h(response);
$h(!matches!(
response,
rfd::MessageDialogResult::No | rfd::MessageDialogResult::Cancel
));
});
});
}};
+1 -1
View File
@@ -1 +1 @@
!function(){"use strict";var e=Object.defineProperty,n=(e,n,t)=>{if(!n.has(e))throw TypeError("Cannot "+t)},t=(e,t,r)=>(n(e,t,"read from private field"),r?r.call(e):t.get(e));function r(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}((n,t)=>{for(var r in t)e(n,r,{get:t[r],enumerable:!0})})({},{Channel:()=>s,PluginListener:()=>a,addPluginListener:()=>o,convertFileSrc:()=>c,invoke:()=>l,transformCallback:()=>r});var i,s=class{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,((e,n,t)=>{if(n.has(e))throw TypeError("Cannot add the same private member more than once");n instanceof WeakSet?n.add(e):n.set(e,t)})(this,i,(()=>{})),this.id=r((e=>{t(this,i).call(this,e)}))}set onmessage(e){var t,r,s,a;s=e,n(t=this,r=i,"write to private field"),a?a.call(t,s):r.set(t,s)}get onmessage(){return t(this,i)}toJSON(){return`__CHANNEL__:${this.id}`}};i=new WeakMap;var a=class{constructor(e,n,t){this.plugin=e,this.event=n,this.channelId=t}async unregister(){return l(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}};async function o(e,n,t){let r=new s;return r.onmessage=t,l(`plugin:${e}|register_listener`,{event:n,handler:r}).then((()=>new a(e,n,r.id)))}async function l(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}function c(e,n="asset"){return window.__TAURI_INTERNALS__.convertFileSrc(e,n)}window.alert=function(e){l("plugin:dialog|message",{message:e.toString()})},window.confirm=function(e){return l("plugin:dialog|confirm",{message:e.toString()})}}();
!function(){"use strict";async function n(n,i={},o){return window.__TAURI_INTERNALS__.invoke(n,i,o)}"function"==typeof SuppressedError&&SuppressedError,window.alert=function(i){n("plugin:dialog|message",{message:i.toString()})},window.confirm=function(i){return n("plugin:dialog|confirm",{message:i.toString()})}}();