This binary can be run from the terminal and takes the following arguments:
@@ -17,7 +17,7 @@
--verbose
Additionally, it has a update --background subcommand.
-
+
Note that the arguments are only parsed, not implemented.
diff --git a/examples/api/src/views/Clipboard.svelte b/examples/api/src/views/Clipboard.svelte
index f571b2ee..f16a7d71 100644
--- a/examples/api/src/views/Clipboard.svelte
+++ b/examples/api/src/views/Clipboard.svelte
@@ -1,23 +1,59 @@
@@ -27,6 +63,7 @@
placeholder="Text to write to the clipboard"
bind:value={text}
/>
-
+
+
diff --git a/examples/api/src/views/Communication.svelte b/examples/api/src/views/Communication.svelte
index a9f4826f..f34dcd3e 100644
--- a/examples/api/src/views/Communication.svelte
+++ b/examples/api/src/views/Communication.svelte
@@ -1,15 +1,15 @@
diff --git a/examples/api/src/views/Dialog.svelte b/examples/api/src/views/Dialog.svelte
index 3e594c90..462eecff 100644
--- a/examples/api/src/views/Dialog.svelte
+++ b/examples/api/src/views/Dialog.svelte
@@ -23,11 +23,7 @@
async function prompt() {
confirm("Do you want to do something?")
- .then((res) =>
- onMessage(
- res ? "Yes" : "No"
- )
- )
+ .then((res) => onMessage(res ? "Yes" : "No"))
.catch(onMessage);
}
@@ -67,14 +63,15 @@
if (Array.isArray(res)) {
onMessage(res);
} else {
- var pathToRead = typeof res === "string" ? res : res.path;
+ var pathToRead = res;
var isFile = pathToRead.match(/\S+\.\S+$/g);
readFile(pathToRead)
.then(function (response) {
if (isFile) {
if (
pathToRead.includes(".png") ||
- pathToRead.includes(".jpg")
+ pathToRead.includes(".jpg") ||
+ pathToRead.includes(".jpeg")
) {
arrayBufferToBase64(
new Uint8Array(response),
@@ -144,5 +141,7 @@
>Open save dialog
-
+
diff --git a/examples/api/src/views/FileSystem.svelte b/examples/api/src/views/FileSystem.svelte
index dce83663..baf9f607 100644
--- a/examples/api/src/views/FileSystem.svelte
+++ b/examples/api/src/views/FileSystem.svelte
@@ -1,16 +1,19 @@
-
-For the complete list of sponsors please visit our [website](https://tauri.app#sponsors) and [Open Collective](https://opencollective.com/tauri).
-
-## License
-
-Code: (c) 2015 - Present - The Tauri Programme within The Commons Conservancy.
-
-MIT or MIT/Apache 2.0 where applicable.
diff --git a/plugins/authenticator/banner.png b/plugins/authenticator/banner.png
deleted file mode 100644
index 405dc601..00000000
Binary files a/plugins/authenticator/banner.png and /dev/null differ
diff --git a/plugins/authenticator/build.rs b/plugins/authenticator/build.rs
deleted file mode 100644
index 993df57a..00000000
--- a/plugins/authenticator/build.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-const COMMANDS: &[&str] = &[
- "init_auth",
- "register",
- "verify_registration",
- "sign",
- "verify_signature",
-];
-
-fn main() {
- tauri_plugin::Builder::new(COMMANDS).build();
-}
diff --git a/plugins/authenticator/guest-js/index.ts b/plugins/authenticator/guest-js/index.ts
deleted file mode 100644
index b1446eea..00000000
--- a/plugins/authenticator/guest-js/index.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-import { invoke } from "@tauri-apps/api/core";
-
-export class Authenticator {
- async init(): Promise {
- return await invoke("plugin:authenticator|init_auth");
- }
-
- async register(challenge: string, application: string): Promise {
- return await invoke("plugin:authenticator|register", {
- timeout: 10000,
- challenge,
- application,
- });
- }
-
- async verifyRegistration(
- challenge: string,
- application: string,
- registerData: string,
- clientData: string,
- ): Promise {
- return await invoke("plugin:authenticator|verify_registration", {
- challenge,
- application,
- registerData,
- clientData,
- });
- }
-
- async sign(
- challenge: string,
- application: string,
- keyHandle: string,
- ): Promise {
- return await invoke("plugin:authenticator|sign", {
- timeout: 10000,
- challenge,
- application,
- keyHandle,
- });
- }
-
- async verifySignature(
- challenge: string,
- application: string,
- signData: string,
- clientData: string,
- keyHandle: string,
- pubkey: string,
- ): Promise {
- return await invoke("plugin:authenticator|verify_signature", {
- challenge,
- application,
- signData,
- clientData,
- keyHandle,
- pubkey,
- });
- }
-}
diff --git a/plugins/authenticator/permissions/autogenerated/commands/init_auth.toml b/plugins/authenticator/permissions/autogenerated/commands/init_auth.toml
deleted file mode 100644
index 4781773e..00000000
--- a/plugins/authenticator/permissions/autogenerated/commands/init_auth.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-init-auth"
-description = "Enables the init_auth command without any pre-configured scope."
-commands.allow = ["init_auth"]
-
-[[permission]]
-identifier = "deny-init-auth"
-description = "Denies the init_auth command without any pre-configured scope."
-commands.deny = ["init_auth"]
diff --git a/plugins/authenticator/permissions/autogenerated/commands/sign.toml b/plugins/authenticator/permissions/autogenerated/commands/sign.toml
deleted file mode 100644
index f8b6a778..00000000
--- a/plugins/authenticator/permissions/autogenerated/commands/sign.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-sign"
-description = "Enables the sign command without any pre-configured scope."
-commands.allow = ["sign"]
-
-[[permission]]
-identifier = "deny-sign"
-description = "Denies the sign command without any pre-configured scope."
-commands.deny = ["sign"]
diff --git a/plugins/authenticator/permissions/autogenerated/commands/verify_registration.toml b/plugins/authenticator/permissions/autogenerated/commands/verify_registration.toml
deleted file mode 100644
index f6b15d58..00000000
--- a/plugins/authenticator/permissions/autogenerated/commands/verify_registration.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-verify-registration"
-description = "Enables the verify_registration command without any pre-configured scope."
-commands.allow = ["verify_registration"]
-
-[[permission]]
-identifier = "deny-verify-registration"
-description = "Denies the verify_registration command without any pre-configured scope."
-commands.deny = ["verify_registration"]
diff --git a/plugins/authenticator/permissions/autogenerated/commands/verify_signature.toml b/plugins/authenticator/permissions/autogenerated/commands/verify_signature.toml
deleted file mode 100644
index 90b24095..00000000
--- a/plugins/authenticator/permissions/autogenerated/commands/verify_signature.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-verify-signature"
-description = "Enables the verify_signature command without any pre-configured scope."
-commands.allow = ["verify_signature"]
-
-[[permission]]
-identifier = "deny-verify-signature"
-description = "Denies the verify_signature command without any pre-configured scope."
-commands.deny = ["verify_signature"]
diff --git a/plugins/authenticator/permissions/autogenerated/reference.md b/plugins/authenticator/permissions/autogenerated/reference.md
deleted file mode 100644
index 8e3cbb52..00000000
--- a/plugins/authenticator/permissions/autogenerated/reference.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Permissions
-
-## allow-init-auth
-
-Enables the init_auth command without any pre-configured scope.
-
-## deny-init-auth
-
-Denies the init_auth command without any pre-configured scope.
-
-## allow-register
-
-Enables the register command without any pre-configured scope.
-
-## deny-register
-
-Denies the register command without any pre-configured scope.
-
-## allow-sign
-
-Enables the sign command without any pre-configured scope.
-
-## deny-sign
-
-Denies the sign command without any pre-configured scope.
-
-## allow-verify-registration
-
-Enables the verify_registration command without any pre-configured scope.
-
-## deny-verify-registration
-
-Denies the verify_registration command without any pre-configured scope.
-
-## allow-verify-signature
-
-Enables the verify_signature command without any pre-configured scope.
-
-## deny-verify-signature
-
-Denies the verify_signature command without any pre-configured scope.
-
diff --git a/plugins/authenticator/src/api-iife.js b/plugins/authenticator/src/api-iife.js
deleted file mode 100644
index 5a3ceb7d..00000000
--- a/plugins/authenticator/src/api-iife.js
+++ /dev/null
@@ -1 +0,0 @@
-if("__TAURI__"in window){var __TAURI_PLUGIN_AUTHENTICATOR__=function(t){"use strict";async function i(t,i={},a){return window.__TAURI_INTERNALS__.invoke(t,i,a)}"function"==typeof SuppressedError&&SuppressedError;return t.Authenticator=class{async init(){return await i("plugin:authenticator|init_auth")}async register(t,a){return await i("plugin:authenticator|register",{timeout:1e4,challenge:t,application:a})}async verifyRegistration(t,a,e,n){return await i("plugin:authenticator|verify_registration",{challenge:t,application:a,registerData:e,clientData:n})}async sign(t,a,e){return await i("plugin:authenticator|sign",{timeout:1e4,challenge:t,application:a,keyHandle:e})}async verifySignature(t,a,e,n,r,u){return await i("plugin:authenticator|verify_signature",{challenge:t,application:a,signData:e,clientData:n,keyHandle:r,pubkey:u})}},t}({});Object.defineProperty(window.__TAURI__,"authenticator",{value:__TAURI_PLUGIN_AUTHENTICATOR__})}
diff --git a/plugins/authenticator/src/auth.rs b/plugins/authenticator/src/auth.rs
deleted file mode 100644
index 34bc332b..00000000
--- a/plugins/authenticator/src/auth.rs
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use authenticator::{
- authenticatorservice::AuthenticatorService, statecallback::StateCallback,
- AuthenticatorTransports, KeyHandle, RegisterFlags, SignFlags, StatusUpdate,
-};
-use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
-use once_cell::sync::Lazy;
-use serde::Serialize;
-use sha2::{Digest, Sha256};
-use std::io;
-use std::sync::mpsc::channel;
-use std::{convert::Into, sync::Mutex};
-
-static MANAGER: Lazy> = Lazy::new(|| {
- let manager = AuthenticatorService::new().expect("The auth service should initialize safely");
- Mutex::new(manager)
-});
-
-pub fn init_usb() {
- let mut manager = MANAGER.lock().unwrap();
- // theres also "add_detected_transports()" in the docs?
- manager.add_u2f_usb_hid_platform_transports();
-}
-
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct Registration {
- pub key_handle: String,
- pub pubkey: String,
- pub register_data: String,
- pub client_data: String,
-}
-
-pub fn register(application: String, timeout: u64, challenge: String) -> crate::Result {
- let (chall_bytes, app_bytes, client_data_string) =
- format_client_data(application.as_str(), challenge.as_str());
-
- // log the status rx?
- let (status_tx, _status_rx) = channel::();
-
- let mut manager = MANAGER.lock().unwrap();
-
- let (register_tx, register_rx) = channel();
- let callback = StateCallback::new(Box::new(move |rv| {
- register_tx.send(rv).unwrap();
- }));
-
- let res = manager.register(
- RegisterFlags::empty(),
- timeout,
- chall_bytes,
- app_bytes,
- vec![],
- status_tx,
- callback,
- );
-
- match res {
- Ok(_r) => {
- let register_result = register_rx
- .recv()
- .expect("Problem receiving, unable to continue");
-
- if let Err(e) = register_result {
- return Err(e.into());
- }
-
- let (register_data, device_info) = register_result.unwrap(); // error already has been checked
-
- // println!("Register result: {}", base64::encode(®ister_data));
- println!("Device info: {}", &device_info);
-
- let (key_handle, public_key) =
- _u2f_get_key_handle_and_public_key_from_register_response(®ister_data).unwrap();
- let key_handle_base64 = URL_SAFE_NO_PAD.encode(key_handle);
- let public_key_base64 = URL_SAFE_NO_PAD.encode(public_key);
- let register_data_base64 = URL_SAFE_NO_PAD.encode(®ister_data);
- println!("Key Handle: {}", &key_handle_base64);
- println!("Public Key: {}", &public_key_base64);
-
- // Ok(base64::encode(®ister_data))
- // Ok(key_handle_base64)
- let res = serde_json::to_string(&Registration {
- key_handle: key_handle_base64,
- pubkey: public_key_base64,
- register_data: register_data_base64,
- client_data: client_data_string,
- })?;
- Ok(res)
- }
- Err(e) => Err(e.into()),
- }
-}
-
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct Signature {
- pub key_handle: String,
- pub sign_data: String,
-}
-
-pub fn sign(
- application: String,
- timeout: u64,
- challenge: String,
- key_handle: String,
-) -> crate::Result {
- let credential = match URL_SAFE_NO_PAD.decode(key_handle) {
- Ok(v) => v,
- Err(e) => {
- return Err(e.into());
- }
- };
- let key_handle = KeyHandle {
- credential,
- transports: AuthenticatorTransports::empty(),
- };
-
- let (chall_bytes, app_bytes, _) = format_client_data(application.as_str(), challenge.as_str());
-
- let (sign_tx, sign_rx) = channel();
- let callback = StateCallback::new(Box::new(move |rv| {
- sign_tx.send(rv).unwrap();
- }));
-
- // log the status rx?
- let (status_tx, _status_rx) = channel::();
-
- let mut manager = MANAGER.lock().unwrap();
-
- let res = manager.sign(
- SignFlags::empty(),
- timeout,
- chall_bytes,
- vec![app_bytes],
- vec![key_handle],
- status_tx,
- callback,
- );
- match res {
- Ok(_v) => {
- let sign_result = sign_rx
- .recv()
- .expect("Problem receiving, unable to continue");
-
- if let Err(e) = sign_result {
- return Err(e.into());
- }
-
- let (_, handle_used, sign_data, device_info) = sign_result.unwrap();
-
- let sig = URL_SAFE_NO_PAD.encode(sign_data);
-
- println!("Sign result: {sig}");
- println!("Key handle used: {}", URL_SAFE_NO_PAD.encode(&handle_used));
- println!("Device info: {}", &device_info);
- println!("Done.");
-
- let res = serde_json::to_string(&Signature {
- sign_data: sig,
- key_handle: URL_SAFE_NO_PAD.encode(&handle_used),
- })?;
- Ok(res)
- }
- Err(e) => Err(e.into()),
- }
-}
-
-fn format_client_data(application: &str, challenge: &str) -> (Vec, Vec, String) {
- let d =
- format!(r#"{{"challenge": "{challenge}", "version": "U2F_V2", "appId": "{application}"}}"#);
- let mut challenge = Sha256::new();
- challenge.update(d.as_bytes());
- let chall_bytes = challenge.finalize().to_vec();
-
- let mut app = Sha256::new();
- app.update(application.as_bytes());
- let app_bytes = app.finalize().to_vec();
-
- (chall_bytes, app_bytes, d)
-}
-
-fn _u2f_get_key_handle_and_public_key_from_register_response(
- register_response: &[u8],
-) -> io::Result<(Vec, Vec)> {
- if register_response[0] != 0x05 {
- return Err(io::Error::new(
- io::ErrorKind::InvalidData,
- "Reserved byte not set correctly",
- ));
- }
-
- // 1: reserved
- // 65: public key
- // 1: key handle length
- // key handle
- // x.509 cert
- // sig
-
- let key_handle_len = register_response[66] as usize;
- let mut public_key = register_response.to_owned();
- let mut key_handle = public_key.split_off(67);
- let _attestation = key_handle.split_off(key_handle_len);
-
- // remove fist (reserved) and last (handle len) bytes
- let pk: Vec = public_key[1..public_key.len() - 1].to_vec();
-
- Ok((key_handle, pk))
-}
diff --git a/plugins/authenticator/src/lib.rs b/plugins/authenticator/src/lib.rs
deleted file mode 100644
index b9979b7f..00000000
--- a/plugins/authenticator/src/lib.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-//! [](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/authenticator)
-//!
-//! Use hardware security-keys in your Tauri App.
-//!
-//! - Supported platforms: Windows, Linux, FreeBSD, NetBSD, OpenBSD, and macOS.
-
-#![doc(
- html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
- html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
-)]
-#![cfg(not(any(target_os = "android", target_os = "ios")))]
-
-mod auth;
-mod error;
-mod u2f;
-mod u2f_crate;
-
-use tauri::{
- plugin::{Builder as PluginBuilder, TauriPlugin},
- Runtime,
-};
-
-pub use error::Error;
-type Result = std::result::Result;
-
-#[tauri::command]
-fn init_auth() {
- auth::init_usb();
-}
-
-#[tauri::command]
-fn register(timeout: u64, challenge: String, application: String) -> crate::Result {
- auth::register(application, timeout, challenge)
-}
-
-#[tauri::command]
-fn verify_registration(
- challenge: String,
- application: String,
- register_data: String,
- client_data: String,
-) -> crate::Result {
- u2f::verify_registration(application, challenge, register_data, client_data)
-}
-
-#[tauri::command]
-fn sign(
- timeout: u64,
- challenge: String,
- application: String,
- key_handle: String,
-) -> crate::Result {
- auth::sign(application, timeout, challenge, key_handle)
-}
-
-#[tauri::command]
-fn verify_signature(
- challenge: String,
- application: String,
- sign_data: String,
- client_data: String,
- key_handle: String,
- pubkey: String,
-) -> crate::Result {
- u2f::verify_signature(
- application,
- challenge,
- sign_data,
- client_data,
- key_handle,
- pubkey,
- )
-}
-
-pub fn init() -> TauriPlugin {
- PluginBuilder::new("authenticator")
- .js_init_script(include_str!("api-iife.js").to_string())
- .invoke_handler(tauri::generate_handler![
- init_auth,
- register,
- verify_registration,
- sign,
- verify_signature
- ])
- .build()
-}
diff --git a/plugins/authenticator/src/u2f.rs b/plugins/authenticator/src/u2f.rs
deleted file mode 100644
index 9e246094..00000000
--- a/plugins/authenticator/src/u2f.rs
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use crate::u2f_crate::messages::*;
-use crate::u2f_crate::protocol::*;
-use crate::u2f_crate::register::*;
-use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
-use chrono::prelude::*;
-use serde::Serialize;
-use std::convert::Into;
-
-static VERSION: &str = "U2F_V2";
-
-pub fn make_challenge(app_id: &str, challenge_bytes: Vec) -> Challenge {
- let utc: DateTime = Utc::now();
- Challenge {
- challenge: URL_SAFE_NO_PAD.encode(challenge_bytes),
- timestamp: format!("{utc:?}"),
- app_id: app_id.to_string(),
- }
-}
-
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct RegistrationVerification {
- pub key_handle: String,
- pub pubkey: String,
- pub device_name: Option,
-}
-
-pub fn verify_registration(
- app_id: String,
- challenge: String,
- register_data: String,
- client_data: String,
-) -> crate::Result {
- let challenge_bytes = URL_SAFE_NO_PAD.decode(challenge)?;
- let challenge = make_challenge(&app_id, challenge_bytes);
- let client_data_bytes: Vec = client_data.as_bytes().into();
- let client_data_base64 = URL_SAFE_NO_PAD.encode(client_data_bytes);
- let client = U2f::new(app_id);
- match client.register_response(
- challenge,
- RegisterResponse {
- registration_data: register_data,
- client_data: client_data_base64,
- version: VERSION.to_string(),
- },
- ) {
- Ok(v) => {
- let rv = RegistrationVerification {
- key_handle: URL_SAFE_NO_PAD.encode(&v.key_handle),
- pubkey: URL_SAFE_NO_PAD.encode(&v.pub_key),
- device_name: v.device_name,
- };
- Ok(serde_json::to_string(&rv)?)
- }
- Err(e) => Err(e.into()),
- }
-}
-
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct SignatureVerification {
- pub counter: u8,
-}
-
-pub fn verify_signature(
- app_id: String,
- challenge: String,
- sign_data: String,
- client_data: String,
- key_handle: String,
- pub_key: String,
-) -> crate::Result {
- let challenge_bytes = URL_SAFE_NO_PAD.decode(challenge)?;
- let chal = make_challenge(&app_id, challenge_bytes);
- let client_data_bytes: Vec = client_data.as_bytes().into();
- let client_data_base64 = URL_SAFE_NO_PAD.encode(client_data_bytes);
- let key_handle_bytes = URL_SAFE_NO_PAD.decode(&key_handle)?;
- let pubkey_bytes = URL_SAFE_NO_PAD.decode(pub_key)?;
- let client = U2f::new(app_id);
- let mut _counter: u32 = 0;
- match client.sign_response(
- chal,
- Registration {
- // here only needs pubkey and keyhandle
- key_handle: key_handle_bytes,
- pub_key: pubkey_bytes,
- attestation_cert: None,
- device_name: None,
- },
- SignResponse {
- // here needs client data and sig data and key_handle
- signature_data: sign_data,
- client_data: client_data_base64,
- key_handle,
- },
- _counter,
- ) {
- Ok(v) => Ok(v),
- Err(e) => Err(e.into()),
- }
-}
diff --git a/plugins/authenticator/src/u2f_crate/LICENSE b/plugins/authenticator/src/u2f_crate/LICENSE
deleted file mode 100644
index d26d5f6c..00000000
--- a/plugins/authenticator/src/u2f_crate/LICENSE
+++ /dev/null
@@ -1,8 +0,0 @@
-Copyright (c) 2017
-
-Licensed under either of
-
- * Apache License, Version 2.0, (http://www.apache.org/licenses/LICENSE-2.0)
- * MIT license (http://opensource.org/licenses/MIT)
-
-at your option.
\ No newline at end of file
diff --git a/plugins/authenticator/src/u2f_crate/authorization.rs b/plugins/authenticator/src/u2f_crate/authorization.rs
deleted file mode 100644
index 0e667ea6..00000000
--- a/plugins/authenticator/src/u2f_crate/authorization.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use bytes::{Buf, BufMut};
-use openssl::sha::sha256;
-use serde::Serialize;
-use std::io::Cursor;
-
-use crate::u2f_crate::u2ferror::U2fError;
-
-/// The `Result` type used in this crate.
-type Result = ::std::result::Result;
-
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct Authorization {
- pub counter: u32,
- pub user_presence: bool,
-}
-
-pub fn parse_sign_response(
- app_id: String,
- client_data: Vec,
- public_key: Vec,
- sign_data: Vec,
-) -> Result {
- if sign_data.len() <= 5 {
- return Err(U2fError::InvalidSignatureData);
- }
-
- let user_presence_flag = &sign_data[0];
- let counter = &sign_data[1..=4];
- let signature = &sign_data[5..];
-
- // Let's build the msg to verify the signature
- let app_id_hash = sha256(&app_id.into_bytes());
- let client_data_hash = sha256(&client_data[..]);
-
- let mut msg = vec![];
- msg.put(app_id_hash.as_ref());
- msg.put_u8(*user_presence_flag);
- msg.put(counter);
- msg.put(client_data_hash.as_ref());
-
- let public_key = super::crypto::NISTP256Key::from_bytes(&public_key)?;
-
- // The signature is to be verified by the relying party using the public key obtained during registration.
- let verified = public_key.verify_signature(signature, msg.as_ref())?;
- if !verified {
- return Err(U2fError::BadSignature);
- }
-
- let authorization = Authorization {
- counter: get_counter(counter),
- user_presence: true,
- };
-
- Ok(authorization)
-}
-
-fn get_counter(counter: &[u8]) -> u32 {
- let mut buf = Cursor::new(counter);
- buf.get_u32()
-}
diff --git a/plugins/authenticator/src/u2f_crate/crypto.rs b/plugins/authenticator/src/u2f_crate/crypto.rs
deleted file mode 100644
index ddcdf1b6..00000000
--- a/plugins/authenticator/src/u2f_crate/crypto.rs
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-//! Cryptographic operation wrapper for Webauthn. This module exists to
-//! allow ease of auditing, safe operation wrappers for the webauthn library,
-//! and cryptographic provider abstraction. This module currently uses OpenSSL
-//! as the cryptographic primitive provider.
-
-// Source can be found here: https://github.com/Firstyear/webauthn-rs/blob/master/src/crypto.rs
-
-#![allow(non_camel_case_types)]
-
-use openssl::{bn, ec, hash, nid, sign, x509};
-use std::convert::TryFrom;
-
-// use super::constants::*;
-use crate::u2f_crate::u2ferror::U2fError;
-use openssl::pkey::Public;
-
-// use super::proto::*;
-
-// Why OpenSSL over another rust crate?
-// - Well, the openssl crate allows us to reconstruct a public key from the
-// x/y group coords, where most others want a pkcs formatted structure. As
-// a result, it's easiest to use openssl as it gives us exactly what we need
-// for these operations, and despite it's many challenges as a library, it
-// has resources and investment into it's maintenance, so we can a least
-// assert a higher level of confidence in it that .
-
-// Object({Integer(-3): Bytes([48, 185, 178, 204, 113, 186, 105, 138, 190, 33, 160, 46, 131, 253, 100, 177, 91, 243, 126, 128, 245, 119, 209, 59, 186, 41, 215, 196, 24, 222, 46, 102]), Integer(-2): Bytes([158, 212, 171, 234, 165, 197, 86, 55, 141, 122, 253, 6, 92, 242, 242, 114, 158, 221, 238, 163, 127, 214, 120, 157, 145, 226, 232, 250, 144, 150, 218, 138]), Integer(-1): U64(1), Integer(1): U64(2), Integer(3): I64(-7)})
-//
-
-/// An X509PublicKey. This is what is otherwise known as a public certificate
-/// which comprises a public key and other signed metadata related to the issuer
-/// of the key.
-pub struct X509PublicKey {
- pubk: x509::X509,
-}
-
-impl std::fmt::Debug for X509PublicKey {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
- write!(f, "X509PublicKey")
- }
-}
-
-impl TryFrom<&[u8]> for X509PublicKey {
- type Error = U2fError;
-
- // Must be DER bytes. If you have PEM, base64decode first!
- fn try_from(d: &[u8]) -> Result {
- let pubk = x509::X509::from_der(d)?;
- Ok(X509PublicKey { pubk })
- }
-}
-
-impl X509PublicKey {
- pub(crate) fn common_name(&self) -> Option {
- let cert = &self.pubk;
-
- let subject = cert.subject_name();
- let common = subject
- .entries_by_nid(openssl::nid::Nid::COMMONNAME)
- .next()
- .map(|b| b.data().as_slice());
-
- if let Some(common) = common {
- std::str::from_utf8(common).ok().map(|s| s.to_string())
- } else {
- None
- }
- }
-
- pub(crate) fn is_secp256r1(&self) -> Result {
- // Can we get the public key?
- let pk = self.pubk.public_key()?;
-
- let ec_key = pk.ec_key()?;
-
- ec_key.check_key()?;
-
- let ec_grpref = ec_key.group();
-
- let ec_curve = ec_grpref.curve_name().ok_or(U2fError::OpenSSLNoCurveName)?;
-
- Ok(ec_curve == nid::Nid::X9_62_PRIME256V1)
- }
-
- pub(crate) fn verify_signature(
- &self,
- signature: &[u8],
- verification_data: &[u8],
- ) -> Result {
- let pkey = self.pubk.public_key()?;
-
- // TODO: Should this determine the hash type from the x509 cert? Or other?
- let mut verifier = sign::Verifier::new(hash::MessageDigest::sha256(), &pkey)?;
- verifier.update(verification_data)?;
- Ok(verifier.verify(signature)?)
- }
-}
-
-pub struct NISTP256Key {
- /// The key's public X coordinate.
- pub x: [u8; 32],
- /// The key's public Y coordinate.
- pub y: [u8; 32],
-}
-
-impl NISTP256Key {
- pub fn from_bytes(public_key_bytes: &[u8]) -> Result {
- if public_key_bytes.len() != 65 {
- return Err(U2fError::InvalidPublicKey);
- }
-
- if public_key_bytes[0] != 0x04 {
- return Err(U2fError::InvalidPublicKey);
- }
-
- let mut x: [u8; 32] = Default::default();
- x.copy_from_slice(&public_key_bytes[1..=32]);
-
- let mut y: [u8; 32] = Default::default();
- y.copy_from_slice(&public_key_bytes[33..=64]);
-
- Ok(NISTP256Key { x, y })
- }
-
- fn get_key(&self) -> Result, U2fError> {
- let ec_group = ec::EcGroup::from_curve_name(openssl::nid::Nid::X9_62_PRIME256V1)?;
-
- let xbn = bn::BigNum::from_slice(&self.x)?;
- let ybn = bn::BigNum::from_slice(&self.y)?;
-
- let ec_key = openssl::ec::EcKey::from_public_key_affine_coordinates(&ec_group, &xbn, &ybn)?;
-
- // Validate the key is sound. IIRC this actually checks the values
- // are correctly on the curve as specified
- ec_key.check_key()?;
-
- Ok(ec_key)
- }
-
- pub fn verify_signature(
- &self,
- signature: &[u8],
- verification_data: &[u8],
- ) -> Result {
- let pkey = self.get_key()?;
-
- let signature = openssl::ecdsa::EcdsaSig::from_der(signature)?;
- let hash = openssl::sha::sha256(verification_data);
-
- Ok(signature.verify(hash.as_ref(), &pkey)?)
- }
-}
diff --git a/plugins/authenticator/src/u2f_crate/messages.rs b/plugins/authenticator/src/u2f_crate/messages.rs
deleted file mode 100644
index be22f965..00000000
--- a/plugins/authenticator/src/u2f_crate/messages.rs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-// As defined by FIDO U2F Javascript API.
-// https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-u2f-javascript-api.html#registration
-
-use serde::{Deserialize, Serialize};
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct U2fRegisterRequest {
- pub app_id: String,
- pub register_requests: Vec,
- pub registered_keys: Vec,
-}
-
-#[derive(Serialize)]
-pub struct RegisterRequest {
- pub version: String,
- pub challenge: String,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RegisteredKey {
- pub version: String,
- pub key_handle: Option,
- pub app_id: String,
-}
-
-#[derive(Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct RegisterResponse {
- pub registration_data: String,
- pub version: String,
- pub client_data: String,
-}
-
-#[derive(Serialize)]
-#[serde(rename_all = "camelCase")]
-pub struct U2fSignRequest {
- pub app_id: String,
- pub challenge: String,
- pub registered_keys: Vec,
-}
-
-#[derive(Clone, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct SignResponse {
- pub key_handle: String,
- pub signature_data: String,
- pub client_data: String,
-}
diff --git a/plugins/authenticator/src/u2f_crate/mod.rs b/plugins/authenticator/src/u2f_crate/mod.rs
deleted file mode 100644
index ab2a1e0c..00000000
--- a/plugins/authenticator/src/u2f_crate/mod.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-mod util;
-
-pub mod authorization;
-mod crypto;
-pub mod messages;
-pub mod protocol;
-pub mod register;
-pub mod u2ferror;
diff --git a/plugins/authenticator/src/u2f_crate/protocol.rs b/plugins/authenticator/src/u2f_crate/protocol.rs
deleted file mode 100644
index 94ebce6f..00000000
--- a/plugins/authenticator/src/u2f_crate/protocol.rs
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use crate::u2f_crate::authorization::*;
-use crate::u2f_crate::messages::*;
-use crate::u2f_crate::register::*;
-use crate::u2f_crate::u2ferror::U2fError;
-use crate::u2f_crate::util::*;
-
-use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
-use chrono::prelude::*;
-use chrono::Duration;
-use serde::{Deserialize, Serialize};
-
-type Result = ::std::result::Result;
-
-#[derive(Clone)]
-pub struct U2f {
- app_id: String,
-}
-
-#[derive(Deserialize, Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct Challenge {
- pub app_id: String,
- pub challenge: String,
- pub timestamp: String,
-}
-
-impl Challenge {
- // Not used in this plugin.
- #[allow(dead_code)]
- pub fn new() -> Self {
- Challenge {
- app_id: String::new(),
- challenge: String::new(),
- timestamp: String::new(),
- }
- }
-}
-
-impl U2f {
- // The app ID is a string used to uniquely identify an U2F app
- pub fn new(app_id: String) -> Self {
- U2f { app_id }
- }
-
- // Not used in this plugin.
- #[allow(dead_code)]
- pub fn generate_challenge(&self) -> Result {
- let utc: DateTime = Utc::now();
-
- let challenge_bytes = generate_challenge(32)?;
- let challenge = Challenge {
- challenge: URL_SAFE_NO_PAD.encode(challenge_bytes),
- timestamp: format!("{:?}", utc),
- app_id: self.app_id.clone(),
- };
-
- Ok(challenge.clone())
- }
-
- // Not used in this plugin.
- #[allow(dead_code)]
- pub fn request(
- &self,
- challenge: Challenge,
- registrations: Vec,
- ) -> Result {
- let u2f_request = U2fRegisterRequest {
- app_id: self.app_id.clone(),
- register_requests: self.register_request(challenge),
- registered_keys: self.registered_keys(registrations),
- };
-
- Ok(u2f_request)
- }
-
- fn register_request(&self, challenge: Challenge) -> Vec {
- let mut requests: Vec = vec![];
-
- let request = RegisterRequest {
- version: U2F_V2.into(),
- challenge: challenge.challenge,
- };
- requests.push(request);
-
- requests
- }
-
- pub fn register_response(
- &self,
- challenge: Challenge,
- response: RegisterResponse,
- ) -> Result {
- if expiration(challenge.timestamp) > Duration::seconds(300) {
- return Err(U2fError::ChallengeExpired);
- }
-
- let registration_data: Vec = URL_SAFE_NO_PAD
- .decode(&response.registration_data[..])
- .unwrap();
- let client_data: Vec = URL_SAFE_NO_PAD.decode(&response.client_data[..]).unwrap();
-
- parse_registration(challenge.app_id, client_data, registration_data)
- }
-
- fn registered_keys(&self, registrations: Vec) -> Vec {
- let mut keys: Vec = vec![];
-
- for registration in registrations {
- keys.push(get_registered_key(
- self.app_id.clone(),
- registration.key_handle,
- ));
- }
-
- keys
- }
-
- // Not used in this plugin.
- #[allow(dead_code)]
- pub fn sign_request(
- &self,
- challenge: Challenge,
- registrations: Vec,
- ) -> U2fSignRequest {
- let mut keys: Vec = vec![];
-
- for registration in registrations {
- keys.push(get_registered_key(
- self.app_id.clone(),
- registration.key_handle,
- ));
- }
-
- let signed_request = U2fSignRequest {
- app_id: self.app_id.clone(),
- challenge: URL_SAFE_NO_PAD.encode(challenge.challenge.as_bytes()),
- registered_keys: keys,
- };
-
- signed_request
- }
-
- pub fn sign_response(
- &self,
- challenge: Challenge,
- reg: Registration,
- sign_resp: SignResponse,
- counter: u32,
- ) -> Result {
- if expiration(challenge.timestamp) > Duration::seconds(300) {
- return Err(U2fError::ChallengeExpired);
- }
-
- if sign_resp.key_handle != get_encoded(®.key_handle[..]) {
- return Err(U2fError::WrongKeyHandler);
- }
-
- let client_data: Vec = URL_SAFE_NO_PAD
- .decode(&sign_resp.client_data[..])
- .map_err(|_e| U2fError::InvalidClientData)?;
- let sign_data: Vec = URL_SAFE_NO_PAD
- .decode(&sign_resp.signature_data[..])
- .map_err(|_e| U2fError::InvalidSignatureData)?;
-
- let public_key = reg.pub_key;
-
- let auth = parse_sign_response(
- self.app_id.clone(),
- client_data.clone(),
- public_key,
- sign_data.clone(),
- );
-
- match auth {
- Ok(ref res) => {
- // CounterTooLow is raised when the counter value received from the device is
- // lower than last stored counter value.
- if res.counter < counter {
- Err(U2fError::CounterTooLow)
- } else {
- Ok(res.counter)
- }
- }
- Err(e) => Err(e),
- }
- }
-}
diff --git a/plugins/authenticator/src/u2f_crate/register.rs b/plugins/authenticator/src/u2f_crate/register.rs
deleted file mode 100644
index 6b47817d..00000000
--- a/plugins/authenticator/src/u2f_crate/register.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use byteorder::{BigEndian, ByteOrder};
-use bytes::{BufMut, Bytes};
-use openssl::sha::sha256;
-use serde::Serialize;
-
-use crate::u2f_crate::messages::RegisteredKey;
-use crate::u2f_crate::u2ferror::U2fError;
-use crate::u2f_crate::util::*;
-use std::convert::TryFrom;
-
-/// The `Result` type used in this crate.
-type Result = ::std::result::Result;
-
-// Single enrolment or pairing between an application and a token.
-#[derive(Serialize, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct Registration {
- pub key_handle: Vec,
- pub pub_key: Vec,
-
- // AttestationCert can be null for Authenticate requests.
- pub attestation_cert: Option>,
- pub device_name: Option,
-}
-
-pub fn parse_registration(
- app_id: String,
- client_data: Vec,
- registration_data: Vec,
-) -> Result {
- let reserved_byte = registration_data[0];
- if reserved_byte != 0x05 {
- return Err(U2fError::InvalidReservedByte);
- }
-
- let mut mem = Bytes::from(registration_data);
-
- //Start parsing ... advance the reserved byte.
- let _ = mem.split_to(1);
-
- // P-256 NIST elliptic curve
- let public_key = mem.split_to(65);
-
- // Key Handle
- let key_handle_size = mem.split_to(1);
- let key_len = BigEndian::read_uint(&key_handle_size[..], 1);
- let key_handle = mem.split_to(key_len as usize);
-
- // The certificate length needs to be inferred by parsing.
- let cert_len = asn_length(mem.clone()).unwrap();
- let attestation_certificate = mem.split_to(cert_len);
-
- // Remaining data corresponds to the signature
- let signature = mem;
-
- // Let's build the msg to verify the signature
- let app_id_hash = sha256(&app_id.into_bytes());
- let client_data_hash = sha256(&client_data[..]);
-
- let mut msg = vec![0x00]; // A byte reserved for future use [1 byte] with the value 0x00
- msg.put(app_id_hash.as_ref());
- msg.put(client_data_hash.as_ref());
- msg.put(key_handle.clone());
- msg.put(public_key.clone());
-
- // The signature is to be verified by the relying party using the public key certified
- // in the attestation certificate.
- let cerificate_public_key =
- super::crypto::X509PublicKey::try_from(&attestation_certificate[..])?;
-
- if !(cerificate_public_key.is_secp256r1()?) {
- return Err(U2fError::BadCertificate);
- }
-
- let verified = cerificate_public_key.verify_signature(&signature[..], &msg[..])?;
-
- if !verified {
- return Err(U2fError::BadCertificate);
- }
-
- let registration = Registration {
- key_handle: key_handle[..].to_vec(),
- pub_key: public_key[..].to_vec(),
- attestation_cert: Some(attestation_certificate[..].to_vec()),
- device_name: cerificate_public_key.common_name(),
- };
-
- Ok(registration)
-}
-
-pub fn get_registered_key(app_id: String, key_handle: Vec) -> RegisteredKey {
- RegisteredKey {
- app_id,
- version: U2F_V2.into(),
- key_handle: Some(get_encoded(key_handle.as_slice())),
- }
-}
diff --git a/plugins/authenticator/src/u2f_crate/u2ferror.rs b/plugins/authenticator/src/u2f_crate/u2ferror.rs
deleted file mode 100644
index 377af9d8..00000000
--- a/plugins/authenticator/src/u2f_crate/u2ferror.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use thiserror::Error;
-
-#[derive(Debug, Error)]
-pub enum U2fError {
- #[error("ASM1 Decoder error")]
- Asm1DecoderError,
- #[error("Not able to verify signature")]
- BadSignature,
- #[error("Not able to generate random bytes")]
- RandomSecureBytesError,
- #[error("Invalid Reserved Byte")]
- InvalidReservedByte,
- #[error("Challenge Expired")]
- ChallengeExpired,
- #[error("Wrong Key Handler")]
- WrongKeyHandler,
- #[error("Invalid Client Data")]
- InvalidClientData,
- #[error("Invalid Signature Data")]
- InvalidSignatureData,
- #[error("Invalid User Presence Byte")]
- InvalidUserPresenceByte,
- #[error("Failed to parse certificate")]
- BadCertificate,
- #[error("Not Trusted Anchor")]
- NotTrustedAnchor,
- #[error("Counter too low")]
- CounterTooLow,
- #[error("Invalid public key")]
- OpenSSLNoCurveName,
- #[error("OpenSSL no curve name")]
- InvalidPublicKey,
- #[error(transparent)]
- OpenSSLError(#[from] openssl::error::ErrorStack),
-}
diff --git a/plugins/authenticator/src/u2f_crate/util.rs b/plugins/authenticator/src/u2f_crate/util.rs
deleted file mode 100644
index 6a7e3fbd..00000000
--- a/plugins/authenticator/src/u2f_crate/util.rs
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2021 Flavio Oliveira
-// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
-// SPDX-License-Identifier: Apache-2.0
-// SPDX-License-Identifier: MIT
-
-use crate::u2f_crate::u2ferror::U2fError;
-use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine};
-use bytes::Bytes;
-use chrono::prelude::*;
-use chrono::Duration;
-use openssl::rand;
-
-/// The `Result` type used in this crate.
-type Result = ::std::result::Result;
-
-pub const U2F_V2: &str = "U2F_V2";
-
-// Generates a challenge from a secure, random source.
-pub fn generate_challenge(size: usize) -> Result> {
- let mut bytes: Vec = vec![0; size];
- rand::rand_bytes(&mut bytes).map_err(|_e| U2fError::RandomSecureBytesError)?;
- Ok(bytes)
-}
-
-pub fn expiration(timestamp: String) -> Duration {
- let now: DateTime = Utc::now();
-
- let ts = timestamp.parse::>();
-
- now.signed_duration_since(ts.unwrap())
-}
-
-// Decode initial bytes of buffer as ASN and return the length of the encoded structure.
-// http://en.wikipedia.org/wiki/X.690
-pub fn asn_length(mem: Bytes) -> Result {
- let buffer: &[u8] = &mem[..];
-
- if mem.len() < 2 || buffer[0] != 0x30 {
- // Type
- return Err(U2fError::Asm1DecoderError);
- }
-
- let len = buffer[1]; // Len
- if len & 0x80 == 0 {
- return Ok((len & 0x7f) as usize);
- }
-
- let numbem_of_bytes = len & 0x7f;
- if numbem_of_bytes == 0 {
- return Err(U2fError::Asm1DecoderError);
- }
-
- let mut length: usize = 0;
- for num in 0..numbem_of_bytes {
- length = length * 0x100 + (buffer[(2 + num) as usize] as usize);
- }
-
- length += numbem_of_bytes as usize;
-
- Ok(length + 2) // Add the 2 initial bytes: type and length.
-}
-
-pub fn get_encoded(data: &[u8]) -> String {
- let encoded: String = URL_SAFE_NO_PAD.encode(data);
-
- encoded.trim_end_matches('=').to_string()
-}
diff --git a/plugins/autostart/.gitignore b/plugins/autostart/.gitignore
deleted file mode 100644
index b512c09d..00000000
--- a/plugins/autostart/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-node_modules
\ No newline at end of file
diff --git a/plugins/autostart/CHANGELOG.md b/plugins/autostart/CHANGELOG.md
index 84b71e6f..2a2f31e5 100644
--- a/plugins/autostart/CHANGELOG.md
+++ b/plugins/autostart/CHANGELOG.md
@@ -1,5 +1,66 @@
# Changelog
+## \[2.3.0]
+
+- [`8ecb418a`](https://github.com/tauri-apps/plugins-workspace/commit/8ecb418a1a35d7f234dc5d833746ac2d8e062aec) ([#2569](https://github.com/tauri-apps/plugins-workspace/pull/2569)) Add a `Builder` for more flexible settings
+
+## \[2.2.0]
+
+- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+
+## \[2.0.1]
+
+- [`a1a82208`](https://github.com/tauri-apps/plugins-workspace/commit/a1a82208ed4ab87f83310be0dc95428aec9ab241) ([#1873](https://github.com/tauri-apps/plugins-workspace/pull/1873) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
+
+## \[2.0.0]
+
+- [`e2c4dfb6`](https://github.com/tauri-apps/plugins-workspace/commit/e2c4dfb6af43e5dd8d9ceba232c315f5febd55c1) Update to tauri v2 stable release.
+
+## \[2.0.0-rc.1]
+
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+
+## \[2.0.0-rc.0]
+
+- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+
+## \[2.0.0-beta.8]
+
+- [`99d6ac0f`](https://github.com/tauri-apps/plugins-workspace/commit/99d6ac0f9506a6a4a1aa59c728157190a7441af6) ([#1606](https://github.com/tauri-apps/plugins-workspace/pull/1606) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The JS packages now specify the *minimum* `@tauri-apps/api` version instead of a single exact version.
+- [`6de87966`](https://github.com/tauri-apps/plugins-workspace/commit/6de87966ecc00ad9d91c25be452f1f46bd2b7e1f) ([#1597](https://github.com/tauri-apps/plugins-workspace/pull/1597) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Update to tauri beta.25.
+
+## \[2.0.0-beta.7]
+
+- [`22a17980`](https://github.com/tauri-apps/plugins-workspace/commit/22a17980ff4f6f8c40adb1b8f4ffc6dae2fe7e30) ([#1537](https://github.com/tauri-apps/plugins-workspace/pull/1537) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri beta.24.
+
+## \[2.0.0-beta.6]
+
+- [`76daee7a`](https://github.com/tauri-apps/plugins-workspace/commit/76daee7aafece34de3092c86e531cf9eb1138989) ([#1512](https://github.com/tauri-apps/plugins-workspace/pull/1512) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update to tauri beta.23.
+
+## \[2.0.0-beta.5]
+
+- [`9013854f`](https://github.com/tauri-apps/plugins-workspace/commit/9013854f42a49a230b9dbb9d02774765528a923f)([#1382](https://github.com/tauri-apps/plugins-workspace/pull/1382)) Update to tauri beta.22.
+
+## \[2.0.0-beta.4]
+
+- [`430bd6f4`](https://github.com/tauri-apps/plugins-workspace/commit/430bd6f4f379bee5d232ae6b098ae131db7f178a)([#1363](https://github.com/tauri-apps/plugins-workspace/pull/1363)) Update to tauri beta.20.
+
+## \[2.0.0-beta.3]
+
+- [`bd1ed590`](https://github.com/tauri-apps/plugins-workspace/commit/bd1ed5903ffcce5500310dac1e59e8c67674ef1e)([#1237](https://github.com/tauri-apps/plugins-workspace/pull/1237)) Update to tauri beta.17.
+
+## \[2.0.0-beta.4]
+
+- [`a233919`](https://github.com/tauri-apps/plugins-workspace/commit/a2339195aa940bff86d76375fd05087595bf06ce)([#1118](https://github.com/tauri-apps/plugins-workspace/pull/1118)) Fix LaunchAgent-based autostart for macOS.
+
+## \[2.0.0-beta.3]
+
+- [`a04ea2f`](https://github.com/tauri-apps/plugins-workspace/commit/a04ea2f38294d5a3987578283badc8eec87a7752)([#1071](https://github.com/tauri-apps/plugins-workspace/pull/1071)) The global API script is now only added to the binary when the `withGlobalTauri` config is true.
+
+## \[2.0.0-beta.2]
+
+- [`99bea25`](https://github.com/tauri-apps/plugins-workspace/commit/99bea2559c2c0648c2519c50a18cd124dacef57b)([#1005](https://github.com/tauri-apps/plugins-workspace/pull/1005)) Update to tauri beta.8.
+
## \[2.0.0-beta.1]
- [`569defb`](https://github.com/tauri-apps/plugins-workspace/commit/569defbe9492e38938554bb7bdc1be9151456d21) Update to tauri beta.4.
@@ -35,10 +96,3 @@
## \[2.0.0-alpha.0]
- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
- te to alpha.11.
-
-## \[2.0.0-alpha.0]
-
-- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
- ae67\`]\(https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
-717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
diff --git a/plugins/autostart/Cargo.toml b/plugins/autostart/Cargo.toml
index f9c4fc86..9a30eff9 100644
--- a/plugins/autostart/Cargo.toml
+++ b/plugins/autostart/Cargo.toml
@@ -1,24 +1,31 @@
[package]
name = "tauri-plugin-autostart"
-version = "2.0.0-beta.1"
+version = "2.3.0"
description = "Automatically launch your application at startup."
authors = { workspace = true }
license = { workspace = true }
edition = { workspace = true }
rust-version = { workspace = true }
+repository = { workspace = true }
links = "tauri-plugin-autostart"
[package.metadata.docs.rs]
-rustc-args = [ "--cfg", "docsrs" ]
-rustdoc-args = [ "--cfg", "docsrs" ]
+rustc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs"]
+
+[package.metadata.platforms.support]
+windows = { level = "full", notes = "" }
+linux = { level = "full", notes = "" }
+macos = { level = "full", notes = "" }
+android = { level = "none", notes = "" }
+ios = { level = "none", notes = "" }
[build-dependencies]
-tauri-plugin = { workspace = true, features = [ "build" ] }
+tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
tauri = { workspace = true }
-log = { workspace = true }
thiserror = { workspace = true }
auto-launch = "0.5"
diff --git a/plugins/autostart/README.md b/plugins/autostart/README.md
index 01f385ab..bae2802a 100644
--- a/plugins/autostart/README.md
+++ b/plugins/autostart/README.md
@@ -1,10 +1,18 @@

-Automatically launch your application at startup. Supports Windows, Mac (via AppleScript or Launch Agent), and Linux.
+Automatically launch your application at startup.
+
+| Platform | Supported |
+| -------- | --------- |
+| Linux | ✓ |
+| Windows | ✓ |
+| macOS | ✓ |
+| Android | x |
+| iOS | x |
## Install
-_This plugin requires a Rust version of at least **1.75**_
+_This plugin requires a Rust version of at least **1.77.2**_
There are three general methods of installation that we can recommend.
@@ -18,7 +26,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
-tauri-plugin-autostart = "2.0.0-beta"
+tauri-plugin-autostart = "2.0.0"
# alternatively with Git:
tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
@@ -46,14 +54,12 @@ yarn add https://github.com/tauri-apps/tauri-plugin-autostart#v2
First you need to register the core plugin with Tauri:
-`src-tauri/src/main.rs`
+`src-tauri/src/lib.rs`
```rust
-use tauri_plugin_autostart::MacosLauncher;
-
fn main() {
tauri::Builder::default()
- .plugin(tauri_plugin_autostart::init(MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"]) /* arbitrary number of args to pass to your app */))
+ .plugin(tauri_plugin_autostart::Builder::new().args((["--flag1", "--flag2"])).build()))
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
@@ -62,13 +68,13 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { enable, isEnabled, disable } from "@tauri-apps/plugin-autostart";
+import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart'
-await enable();
+await enable()
-console.log(`registered for autostart? ${await isEnabled()}`);
+console.log(`registered for autostart? ${await isEnabled()}`)
-disable();
+disable()
```
## Contributing
diff --git a/plugins/autostart/SECURITY.md b/plugins/autostart/SECURITY.md
new file mode 100644
index 00000000..4f09bbac
--- /dev/null
+++ b/plugins/autostart/SECURITY.md
@@ -0,0 +1,23 @@
+# Security Policy
+
+**Do not report security vulnerabilities through public GitHub issues.**
+
+**Please use the [Private Vulnerability Disclosure](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) feature of GitHub.**
+
+Include as much of the following information:
+
+- Type of issue (e.g. improper input parsing, privilege escalation, etc.)
+- The location of the affected source code (tag/branch/commit or direct URL)
+- Any special configuration required to reproduce the issue
+- The distribution affected or used to help us with reproduction of the issue
+- Step-by-step instructions to reproduce the issue
+- Ideally a reproduction repository
+- Impact of the issue, including how an attacker might exploit the issue
+
+We prefer to receive reports in English.
+
+## Contact
+
+Please disclose a vulnerability or security relevant issue here: [https://github.com/tauri-apps/plugins-workspace/security/advisories/new](https://github.com/tauri-apps/plugins-workspace/security/advisories/new).
+
+Alternatively, you can also contact us by email via [security@tauri.app](mailto:security@tauri.app).
diff --git a/plugins/autostart/src/api-iife.js b/plugins/autostart/api-iife.js
similarity index 100%
rename from plugins/autostart/src/api-iife.js
rename to plugins/autostart/api-iife.js
diff --git a/plugins/autostart/build.rs b/plugins/autostart/build.rs
index 2b27eff0..1460469b 100644
--- a/plugins/autostart/build.rs
+++ b/plugins/autostart/build.rs
@@ -5,5 +5,7 @@
const COMMANDS: &[&str] = &["enable", "disable", "is_enabled"];
fn main() {
- tauri_plugin::Builder::new(COMMANDS).build();
+ tauri_plugin::Builder::new(COMMANDS)
+ .global_api_script_path("./api-iife.js")
+ .build();
}
diff --git a/plugins/autostart/guest-js/index.ts b/plugins/autostart/guest-js/index.ts
index 81471b74..fca8344f 100644
--- a/plugins/autostart/guest-js/index.ts
+++ b/plugins/autostart/guest-js/index.ts
@@ -2,16 +2,16 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { invoke } from "@tauri-apps/api/core";
+import { invoke } from '@tauri-apps/api/core'
export async function isEnabled(): Promise {
- return await invoke("plugin:autostart|is_enabled");
+ return await invoke('plugin:autostart|is_enabled')
}
export async function enable(): Promise {
- await invoke("plugin:autostart|enable");
+ await invoke('plugin:autostart|enable')
}
export async function disable(): Promise {
- await invoke("plugin:autostart|disable");
+ await invoke('plugin:autostart|disable')
}
diff --git a/plugins/autostart/package.json b/plugins/autostart/package.json
index ad33dd84..c2840616 100644
--- a/plugins/autostart/package.json
+++ b/plugins/autostart/package.json
@@ -1,10 +1,11 @@
{
"name": "@tauri-apps/plugin-autostart",
- "version": "2.0.0-beta.1",
- "license": "MIT or APACHE-2.0",
+ "version": "2.3.0",
+ "license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
+ "repository": "https://github.com/tauri-apps/plugins-workspace",
"type": "module",
"types": "./dist-js/index.d.ts",
"main": "./dist-js/index.cjs",
@@ -23,6 +24,6 @@
"LICENSE"
],
"dependencies": {
- "@tauri-apps/api": "2.0.0-beta.2"
+ "@tauri-apps/api": "^2.0.0"
}
}
diff --git a/plugins/autostart/permissions/autogenerated/reference.md b/plugins/autostart/permissions/autogenerated/reference.md
index e129ae02..6adb2be4 100644
--- a/plugins/autostart/permissions/autogenerated/reference.md
+++ b/plugins/autostart/permissions/autogenerated/reference.md
@@ -1,26 +1,106 @@
-# Permissions
+## Default Permission
-## allow-disable
+This permission set configures if your
+application can enable or disable auto
+starting the application on boot.
+
+#### Granted Permissions
+
+It allows all to check, enable and
+disable the automatic start on boot.
+
+
+
+#### This default permission set includes the following:
+
+- `allow-enable`
+- `allow-disable`
+- `allow-is-enabled`
+
+## Permission Table
+
+
+
+
Identifier
+
Description
+
+
+
+
+
+
+`autostart:allow-disable`
+
+
+
Enables the disable command without any pre-configured scope.
-## deny-disable
+
+
+
+
+
+
+`autostart:deny-disable`
+
+
+
Denies the disable command without any pre-configured scope.
-## allow-enable
+
+
+
+
+
+
+`autostart:allow-enable`
+
+
+
Enables the enable command without any pre-configured scope.
-## deny-enable
+
+
+
+
+
+
+`autostart:deny-enable`
+
+
+
Denies the enable command without any pre-configured scope.
-## allow-is-enabled
+
+
+
+
+
+
+`autostart:allow-is-enabled`
+
+
+
Enables the is_enabled command without any pre-configured scope.
-## deny-is-enabled
+
+
+
+
+
+
+`autostart:deny-is-enabled`
+
+
+
Denies the is_enabled command without any pre-configured scope.
+
+
+
diff --git a/plugins/autostart/permissions/default.toml b/plugins/autostart/permissions/default.toml
new file mode 100644
index 00000000..a2ac766f
--- /dev/null
+++ b/plugins/autostart/permissions/default.toml
@@ -0,0 +1,15 @@
+"$schema" = "schemas/schema.json"
+[default]
+description = """
+This permission set configures if your
+application can enable or disable auto
+starting the application on boot.
+
+#### Granted Permissions
+
+It allows all to check, enable and
+disable the automatic start on boot.
+
+"""
+
+permissions = ["allow-enable", "allow-disable", "allow-is-enabled"]
diff --git a/plugins/autostart/permissions/schemas/schema.json b/plugins/autostart/permissions/schemas/schema.json
index 9a471e09..af681221 100644
--- a/plugins/autostart/permissions/schemas/schema.json
+++ b/plugins/autostart/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,50 +251,90 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-disable -> Enables the disable command without any pre-configured scope.",
+ "description": "MacOS.",
"type": "string",
"enum": [
- "allow-disable"
+ "macOS"
]
},
{
- "description": "deny-disable -> Denies the disable command without any pre-configured scope.",
+ "description": "Windows.",
"type": "string",
"enum": [
- "deny-disable"
+ "windows"
]
},
{
- "description": "allow-enable -> Enables the enable command without any pre-configured scope.",
+ "description": "Linux.",
"type": "string",
"enum": [
- "allow-enable"
+ "linux"
]
},
{
- "description": "deny-enable -> Denies the enable command without any pre-configured scope.",
+ "description": "Android.",
"type": "string",
"enum": [
- "deny-enable"
+ "android"
]
},
{
- "description": "allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
+ "description": "iOS.",
"type": "string",
"enum": [
- "allow-is-enabled"
+ "iOS"
]
+ }
+ ]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the disable command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-disable",
+ "markdownDescription": "Enables the disable command without any pre-configured scope."
},
{
- "description": "deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
+ "description": "Denies the disable command without any pre-configured scope.",
"type": "string",
- "enum": [
- "deny-is-enabled"
- ]
+ "const": "deny-disable",
+ "markdownDescription": "Denies the disable command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the enable command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-enable",
+ "markdownDescription": "Enables the enable command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the enable command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-enable",
+ "markdownDescription": "Denies the enable command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the is_enabled command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-is-enabled",
+ "markdownDescription": "Enables the is_enabled command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the is_enabled command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-is-enabled",
+ "markdownDescription": "Denies the is_enabled command without any pre-configured scope."
+ },
+ {
+ "description": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`",
+ "type": "string",
+ "const": "default",
+ "markdownDescription": "This permission set configures if your\napplication can enable or disable auto\nstarting the application on boot.\n\n#### Granted Permissions\n\nIt allows all to check, enable and\ndisable the automatic start on boot.\n\n\n#### This default permission set includes:\n\n- `allow-enable`\n- `allow-disable`\n- `allow-is-enabled`"
}
]
}
diff --git a/plugins/autostart/rollup.config.js b/plugins/autostart/rollup.config.js
index 977dfac8..1f349ec8 100644
--- a/plugins/autostart/rollup.config.js
+++ b/plugins/autostart/rollup.config.js
@@ -2,6 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { createConfig } from "../../shared/rollup.config.js";
+import { createConfig } from '../../shared/rollup.config.js'
-export default createConfig();
+export default createConfig()
diff --git a/plugins/autostart/src/lib.rs b/plugins/autostart/src/lib.rs
index b4338208..83cac89c 100644
--- a/plugins/autostart/src/lib.rs
+++ b/plugins/autostart/src/lib.rs
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-//! [](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/autostart)
-//!
//! Automatically launch your application at startup. Supports Windows, Mac (via AppleScript or Launch Agent), and Linux.
#![doc(
@@ -13,12 +11,10 @@
#![cfg(not(any(target_os = "android", target_os = "ios")))]
use auto_launch::{AutoLaunch, AutoLaunchBuilder};
-#[cfg(target_os = "macos")]
-use log::info;
use serde::{ser::Serializer, Serialize};
use tauri::{
command,
- plugin::{Builder, TauriPlugin},
+ plugin::{Builder as PluginBuilder, TauriPlugin},
Manager, Runtime, State,
};
@@ -26,8 +22,9 @@ use std::env::current_exe;
type Result = std::result::Result;
-#[derive(Debug, Copy, Clone)]
+#[derive(Debug, Default, Copy, Clone)]
pub enum MacosLauncher {
+ #[default]
LaunchAgent,
AppleScript,
}
@@ -75,10 +72,12 @@ impl AutoLaunchManager {
}
pub trait ManagerExt {
+ /// TODO: Rename these to `autostart` or `auto_start` in v3
fn autolaunch(&self) -> State<'_, AutoLaunchManager>;
}
impl> ManagerExt for T {
+ /// TODO: Rename these to `autostart` or `auto_start` in v3
fn autolaunch(&self) -> State<'_, AutoLaunchManager> {
self.state::()
}
@@ -99,60 +98,132 @@ async fn is_enabled(manager: State<'_, AutoLaunchManager>) -> Result {
manager.is_enabled()
}
+#[derive(Default)]
+pub struct Builder {
+ #[cfg(target_os = "macos")]
+ macos_launcher: MacosLauncher,
+ args: Vec,
+}
+
+impl Builder {
+ /// Create a new auto start builder with default settings
+ pub fn new() -> Self {
+ Self::default()
+ }
+
+ /// Adds an argument to pass to your app on startup.
+ ///
+ /// ## Examples
+ ///
+ /// ```no_run
+ /// Builder::new()
+ /// .arg("--from-autostart")
+ /// .arg("--hey")
+ /// .build();
+ /// ```
+ pub fn arg>(mut self, arg: S) -> Self {
+ self.args.push(arg.into());
+ self
+ }
+
+ /// Adds multiple arguments to pass to your app on startup.
+ ///
+ /// ## Examples
+ ///
+ /// ```no_run
+ /// Builder::new()
+ /// .args(["--from-autostart", "--hey"])
+ /// .build();
+ /// ```
+ pub fn args(mut self, args: I) -> Self
+ where
+ I: IntoIterator,
+ S: Into,
+ {
+ for arg in args {
+ self = self.arg(arg);
+ }
+ self
+ }
+
+ /// Sets whether to use launch agent or apple script to be used to enable auto start,
+ /// the builder's default is [`MacosLauncher::LaunchAgent`]
+ #[cfg(target_os = "macos")]
+ pub fn macos_launcher(mut self, macos_launcher: MacosLauncher) -> Self {
+ self.macos_launcher = macos_launcher;
+ self
+ }
+
+ pub fn build(self) -> TauriPlugin {
+ PluginBuilder::new("autostart")
+ .invoke_handler(tauri::generate_handler![enable, disable, is_enabled])
+ .setup(move |app, _api| {
+ let mut builder = AutoLaunchBuilder::new();
+ builder.set_app_name(&app.package_info().name);
+ builder.set_args(&self.args);
+
+ let current_exe = current_exe()?;
+
+ #[cfg(windows)]
+ builder.set_app_path(¤t_exe.display().to_string());
+
+ #[cfg(target_os = "macos")]
+ {
+ builder.set_use_launch_agent(matches!(
+ self.macos_launcher,
+ MacosLauncher::LaunchAgent
+ ));
+ // on macOS, current_exe gives path to /Applications/Example.app/MacOS/Example
+ // but this results in seeing a Unix Executable in macOS login items
+ // It must be: /Applications/Example.app
+ // If it didn't find exactly a single occurance of .app, it will default to
+ // exe path to not break it.
+ let exe_path = current_exe.canonicalize()?.display().to_string();
+ let parts: Vec<&str> = exe_path.split(".app/").collect();
+ let app_path = if parts.len() == 2
+ && matches!(self.macos_launcher, MacosLauncher::AppleScript)
+ {
+ format!("{}.app", parts.first().unwrap())
+ } else {
+ exe_path
+ };
+ builder.set_app_path(&app_path);
+ }
+
+ #[cfg(target_os = "linux")]
+ if let Some(appimage) = app
+ .env()
+ .appimage
+ .and_then(|p| p.to_str().map(|s| s.to_string()))
+ {
+ builder.set_app_path(&appimage);
+ } else {
+ builder.set_app_path(¤t_exe.display().to_string());
+ }
+
+ app.manage(AutoLaunchManager(
+ builder.build().map_err(|e| e.to_string())?,
+ ));
+ Ok(())
+ })
+ .build()
+ }
+}
+
/// Initializes the plugin.
///
/// `args` - are passed to your app on startup.
pub fn init(
- macos_launcher: MacosLauncher,
+ #[allow(unused)] macos_launcher: MacosLauncher,
args: Option>,
) -> TauriPlugin {
- Builder::new("autostart")
- .js_init_script(include_str!("api-iife.js").to_string())
- .invoke_handler(tauri::generate_handler![enable, disable, is_enabled])
- .setup(move |app, _api| {
- let mut builder = AutoLaunchBuilder::new();
- builder.set_app_name(&app.package_info().name);
- if let Some(args) = args {
- builder.set_args(&args);
- }
- builder.set_use_launch_agent(matches!(macos_launcher, MacosLauncher::LaunchAgent));
-
- let current_exe = current_exe()?;
-
- #[cfg(windows)]
- builder.set_app_path(¤t_exe.display().to_string());
- #[cfg(target_os = "macos")]
- {
- // on macOS, current_exe gives path to /Applications/Example.app/MacOS/Example
- // but this results in seeing a Unix Executable in macOS login items
- // It must be: /Applications/Example.app
- // If it didn't find exactly a single occurance of .app, it will default to
- // exe path to not break it.
- let exe_path = current_exe.canonicalize()?.display().to_string();
- let parts: Vec<&str> = exe_path.split(".app/").collect();
- let app_path = if parts.len() == 2 {
- format!("{}.app", parts.first().unwrap())
- } else {
- exe_path
- };
- info!("auto_start path {}", &app_path);
- builder.set_app_path(&app_path);
- }
- #[cfg(target_os = "linux")]
- if let Some(appimage) = app
- .env()
- .appimage
- .and_then(|p| p.to_str().map(|s| s.to_string()))
- {
- builder.set_app_path(&appimage);
- } else {
- builder.set_app_path(¤t_exe.display().to_string());
- }
-
- app.manage(AutoLaunchManager(
- builder.build().map_err(|e| e.to_string())?,
- ));
- Ok(())
- })
- .build()
+ let mut builder = Builder::new();
+ if let Some(args) = args {
+ builder = builder.args(args)
+ }
+ #[cfg(target_os = "macos")]
+ {
+ builder = builder.macos_launcher(macos_launcher);
+ }
+ builder.build()
}
diff --git a/plugins/barcode-scanner/CHANGELOG.md b/plugins/barcode-scanner/CHANGELOG.md
index 01a59b61..3fa878fd 100644
--- a/plugins/barcode-scanner/CHANGELOG.md
+++ b/plugins/barcode-scanner/CHANGELOG.md
@@ -1,5 +1,84 @@
# Changelog
+## \[2.2.0]
+
+- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+
+## \[2.0.1]
+
+- [`a1a82208`](https://github.com/tauri-apps/plugins-workspace/commit/a1a82208ed4ab87f83310be0dc95428aec9ab241) ([#1873](https://github.com/tauri-apps/plugins-workspace/pull/1873) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
+
+## \[2.0.0]
+
+- [`e2c4dfb6`](https://github.com/tauri-apps/plugins-workspace/commit/e2c4dfb6af43e5dd8d9ceba232c315f5febd55c1) Update to tauri v2 stable release.
+
+## \[2.0.0-rc.2]
+
+- [`79d6e19c`](https://github.com/tauri-apps/plugins-workspace/commit/79d6e19c4b38bae0cab29eb88df379e2237d9aac) ([#1777](https://github.com/tauri-apps/plugins-workspace/pull/1777)) Fixed an issue which caused checkPermission and requestPermission to be mixed up.
+
+## \[2.0.0-rc.4]
+
+- [`713c54ef`](https://github.com/tauri-apps/plugins-workspace/commit/713c54ef8365d36afd84585dcabed2fbb751223d) ([#1749](https://github.com/tauri-apps/plugins-workspace/pull/1749) by [@olivierlemasle](https://github.com/tauri-apps/plugins-workspace/../../olivierlemasle)) Remove unused Android dependencies.
+- [`8c3a6a25`](https://github.com/tauri-apps/plugins-workspace/commit/8c3a6a253d7029d370659d2102f91a458745d345) ([#1758](https://github.com/tauri-apps/plugins-workspace/pull/1758) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Validate missing `NSCameraUsageDescription` Info.plist value.
+
+## \[2.0.0-rc.1]
+
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Use `PermissionState` from the `tauri` crate, which now also includes a "prompt with rationale" variant for Android (returned when your app must explain to the user why it needs the permission).
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+
+## \[2.0.0-rc.2]
+
+- [`b9147758`](https://github.com/tauri-apps/plugins-workspace/commit/b914775898c2bee7ceb20bd17ee595005cd17a64) ([#1679](https://github.com/tauri-apps/plugins-workspace/pull/1679) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Explicitly set a minimum macOS version for the Swift package.
+
+## \[2.0.0-rc.1]
+
+- [`2c00c029`](https://github.com/tauri-apps/plugins-workspace/commit/2c00c0292c9127b81567de46691e8c0f73557261) ([#1630](https://github.com/tauri-apps/plugins-workspace/pull/1630) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused multi-word IIFE names to not be formatted correctly. For example the `barcode-scanner` was defined as `window.__TAURI_PLUGIN_CLIPBOARDMANAGER__` instead of `window.__TAURI_PLUGIN_CLIPBOARD_MANAGER__`.
+
+### changes
+
+- [`6b079cfd`](https://github.com/tauri-apps/plugins-workspace/commit/6b079cfdd107c94abc2c7300f6af00bac3ff4040) ([#1649](https://github.com/tauri-apps/plugins-workspace/pull/1649) by [@ahqsoftwares](https://github.com/tauri-apps/plugins-workspace/../../ahqsoftwares)) Remove targetSdk from build.kts files as it is deprecated and will be removed from DSL v9.0
+
+## \[2.0.0-rc.0]
+
+- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+
+## \[2.0.0-beta.8]
+
+- [`99d6ac0f`](https://github.com/tauri-apps/plugins-workspace/commit/99d6ac0f9506a6a4a1aa59c728157190a7441af6) ([#1606](https://github.com/tauri-apps/plugins-workspace/pull/1606) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The JS packages now specify the *minimum* `@tauri-apps/api` version instead of a single exact version.
+- [`6de87966`](https://github.com/tauri-apps/plugins-workspace/commit/6de87966ecc00ad9d91c25be452f1f46bd2b7e1f) ([#1597](https://github.com/tauri-apps/plugins-workspace/pull/1597) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Update to tauri beta.25.
+
+## \[2.0.0-beta.7]
+
+- [`22a17980`](https://github.com/tauri-apps/plugins-workspace/commit/22a17980ff4f6f8c40adb1b8f4ffc6dae2fe7e30) ([#1537](https://github.com/tauri-apps/plugins-workspace/pull/1537) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri beta.24.
+
+## \[2.0.0-beta.6]
+
+- [`76daee7a`](https://github.com/tauri-apps/plugins-workspace/commit/76daee7aafece34de3092c86e531cf9eb1138989) ([#1512](https://github.com/tauri-apps/plugins-workspace/pull/1512) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update to tauri beta.23.
+
+## \[2.0.0-beta.5]
+
+- [`9013854f`](https://github.com/tauri-apps/plugins-workspace/commit/9013854f42a49a230b9dbb9d02774765528a923f)([#1382](https://github.com/tauri-apps/plugins-workspace/pull/1382)) Update to tauri beta.22.
+
+## \[2.0.0-beta.4]
+
+- [`430bd6f4`](https://github.com/tauri-apps/plugins-workspace/commit/430bd6f4f379bee5d232ae6b098ae131db7f178a)([#1363](https://github.com/tauri-apps/plugins-workspace/pull/1363)) Update to tauri beta.20.
+
+## \[2.0.0-beta.3]
+
+- [`bd1ed590`](https://github.com/tauri-apps/plugins-workspace/commit/bd1ed5903ffcce5500310dac1e59e8c67674ef1e)([#1237](https://github.com/tauri-apps/plugins-workspace/pull/1237)) Update to tauri beta.17.
+
+## \[2.0.0-beta.4]
+
+- [`326df688`](https://github.com/tauri-apps/plugins-workspace/commit/326df6883998d416fc0837583ed972854628bb52)([#1236](https://github.com/tauri-apps/plugins-workspace/pull/1236)) Fixes command argument parsing on iOS.
+
+## \[2.0.0-beta.3]
+
+- [`a04ea2f`](https://github.com/tauri-apps/plugins-workspace/commit/a04ea2f38294d5a3987578283badc8eec87a7752)([#1071](https://github.com/tauri-apps/plugins-workspace/pull/1071)) The global API script is now only added to the binary when the `withGlobalTauri` config is true.
+
+## \[2.0.0-beta.2]
+
+- [`99bea25`](https://github.com/tauri-apps/plugins-workspace/commit/99bea2559c2c0648c2519c50a18cd124dacef57b)([#1005](https://github.com/tauri-apps/plugins-workspace/pull/1005)) Update to tauri beta.8.
+
## \[2.0.0-beta.1]
- [`569defb`](https://github.com/tauri-apps/plugins-workspace/commit/569defbe9492e38938554bb7bdc1be9151456d21) Update to tauri beta.4.
@@ -28,4 +107,9 @@
## \[2.0.0-alpha.0]
- [`454428c`](https://github.com/tauri-apps/plugins-workspace/commit/454428cd50ce4962f0bad8e355aebc68af8cc61f)([#536](https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
-commit/454428cd50ce4962f0bad8e355aebc68af8cc61f)([#536](https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
+ commit/454428cd50ce4962f0bad8e355aebc68af8cc61f)([#536](https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
+ 36]\(https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
+ commit/454428cd50ce4962f0bad8e355aebc68af8cc61f)([#536](https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
+ .
+ commit/454428cd50ce4962f0bad8e355aebc68af8cc61f)([#536](https://github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
+ github.com/tauri-apps/plugins-workspace/pull/536)) Initial release.
diff --git a/plugins/barcode-scanner/Cargo.toml b/plugins/barcode-scanner/Cargo.toml
index 81f8e4f1..018b4908 100644
--- a/plugins/barcode-scanner/Cargo.toml
+++ b/plugins/barcode-scanner/Cargo.toml
@@ -1,20 +1,29 @@
[package]
name = "tauri-plugin-barcode-scanner"
-version = "2.0.0-beta.1"
+version = "2.2.0"
description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS"
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }
+repository = { workspace = true }
links = "tauri-plugin-barcode-scanner"
[package.metadata.docs.rs]
-rustc-args = [ "--cfg", "docsrs" ]
-rustdoc-args = [ "--cfg", "docsrs" ]
-targets = [ "x86_64-linux-android" ]
+rustc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs"]
+targets = ["x86_64-linux-android"]
+
+[package.metadata.platforms.support]
+windows = { level = "none", notes = "" }
+linux = { level = "none", notes = "" }
+macos = { level = "none", notes = "" }
+android = { level = "full", notes = "" }
+ios = { level = "full", notes = "" }
+
[build-dependencies]
-tauri-plugin = { workspace = true, features = [ "build" ] }
+tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
@@ -22,3 +31,6 @@ serde_json = { workspace = true }
tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
+
+[target.'cfg(target_os = "ios")'.dependencies]
+tauri = { workspace = true, features = ["wry"] }
diff --git a/plugins/barcode-scanner/README.md b/plugins/barcode-scanner/README.md
index 1a7d59e6..4abbef0a 100644
--- a/plugins/barcode-scanner/README.md
+++ b/plugins/barcode-scanner/README.md
@@ -1,7 +1,15 @@
-
+
Allows your mobile application to use the camera to scan QR codes, EAN-13 and other kinds of barcodes.
+| Platform | Supported |
+| -------- | --------- |
+| Linux | x |
+| Windows | x |
+| macOS | x |
+| Android | ✓ |
+| iOS | ✓ |
+
## Install
_This plugin requires a Rust version of at least **1.64**_
@@ -18,7 +26,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
-tauri-plugin-barcode-scanner = "2.0.0-beta"
+tauri-plugin-barcode-scanner = "2.0.0"
# alternatively with Git:
tauri-plugin-barcode-scanner = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
@@ -46,7 +54,7 @@ yarn add https://github.com/tauri-apps/tauri-plugin-barcode-scanner#v2
First you need to register the core plugin with Tauri:
-`src-tauri/src/main.rs`
+`src-tauri/src/lib.rs`
```rust
fn main() {
@@ -60,12 +68,12 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { scan } from "@tauri-apps/plugin-barcode-scanner";
+import { scan } from '@tauri-apps/plugin-barcode-scanner'
// `windowed: true` actually sets the webview to transparent
// instead of opening a separate view for the camera
// make sure your user interface is ready to show what is underneath with a transparent element
-scan({ windowed: true, formats: [""] })
+scan({ windowed: true, formats: [''] })
```
## Contributing
diff --git a/plugins/barcode-scanner/SECURITY.md b/plugins/barcode-scanner/SECURITY.md
index 36a863c6..135504ec 100644
--- a/plugins/barcode-scanner/SECURITY.md
+++ b/plugins/barcode-scanner/SECURITY.md
@@ -54,7 +54,6 @@ The camera has two modes. The first one is where the user can see the background
The second mode allows the developer to assist the user and add a transparent overlay to the image, providing hints or additional information (like a link preview).
The overlay could be made non-transparent by the application frontend and as long as the app is open (and in some cases) it could read QR codes in range of the camera lense.
-
#### Out Of Scope
- Exploits in the operating system QR code parsing functionality
diff --git a/plugins/barcode-scanner/android/build.gradle.kts b/plugins/barcode-scanner/android/build.gradle.kts
index 8b060f64..f3ecd6c7 100644
--- a/plugins/barcode-scanner/android/build.gradle.kts
+++ b/plugins/barcode-scanner/android/build.gradle.kts
@@ -5,11 +5,10 @@ plugins {
android {
namespace = "app.tauri.barcodescanner"
- compileSdk = 32
+ compileSdk = 34
defaultConfig {
- minSdk = 24
- targetSdk = 32
+ minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
@@ -48,9 +47,5 @@ dependencies {
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
- implementation("com.journeyapps:zxing-android-embedded:4.3.0") {
- isTransitive = false
- }
- implementation("com.google.zxing:core:3.3.0")
implementation(project(":tauri-android"))
}
diff --git a/plugins/barcode-scanner/android/src/main/AndroidManifest.xml b/plugins/barcode-scanner/android/src/main/AndroidManifest.xml
index b4050b4f..750a724b 100644
--- a/plugins/barcode-scanner/android/src/main/AndroidManifest.xml
+++ b/plugins/barcode-scanner/android/src/main/AndroidManifest.xml
@@ -2,10 +2,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:hardwareAccelerated="true">
-
-
-
-
-
+
+
+
diff --git a/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt b/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt
index 4728bad0..ef2eeb34 100644
--- a/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt
+++ b/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt
@@ -42,7 +42,6 @@ import app.tauri.annotation.Permission
import app.tauri.annotation.PermissionCallback
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 com.google.common.util.concurrent.ListenableFuture
@@ -50,7 +49,6 @@ import com.google.mlkit.vision.barcode.BarcodeScannerOptions
import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
-import org.json.JSONException
import java.util.Collections
import java.util.concurrent.ExecutionException
diff --git a/plugins/barcode-scanner/android/src/main/java/GraphicOverlay.kt b/plugins/barcode-scanner/android/src/main/java/GraphicOverlay.kt
index 76817540..1b1d3b2c 100644
--- a/plugins/barcode-scanner/android/src/main/java/GraphicOverlay.kt
+++ b/plugins/barcode-scanner/android/src/main/java/GraphicOverlay.kt
@@ -91,22 +91,10 @@ class GraphicOverlay: View {
return
}
- val zLowerBoundInScreenPixel: Float
- val zUpperBoundInScreenPixel: Float
- if (rescaleZForVisualization) {
- zLowerBoundInScreenPixel = (-0.001f).coerceAtMost(scale(zMin))
- zUpperBoundInScreenPixel = 0.001f.coerceAtLeast(scale(zMax))
- } else {
- val defaultRangeFactor = 1f
- zLowerBoundInScreenPixel = -defaultRangeFactor * canvas.width
- zUpperBoundInScreenPixel = defaultRangeFactor * canvas.width
- }
val zInScreenPixel = scale(zInImagePixel)
if (zInScreenPixel < 0) {
- val v = (zInScreenPixel / zLowerBoundInScreenPixel * 255).toInt()
paint.setARGB(0, 0, 255, 0)
} else {
- val v = (zInScreenPixel / zUpperBoundInScreenPixel * 255).toInt()
paint.setARGB(0, 0, 255, 0)
}
}
@@ -180,7 +168,7 @@ class GraphicOverlay: View {
needUpdateTransformation = false
}
- override fun onDraw(canvas: Canvas?) {
+ override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
synchronized(lock) {
updateTransformationIfNeeded()
diff --git a/plugins/barcode-scanner/api-iife.js b/plugins/barcode-scanner/api-iife.js
new file mode 100644
index 00000000..620b59a7
--- /dev/null
+++ b/plugins/barcode-scanner/api-iife.js
@@ -0,0 +1 @@
+if("__TAURI__"in window){var __TAURI_PLUGIN_BARCODE_SCANNER__=function(n){"use strict";async function e(n,e={},r){return window.__TAURI_INTERNALS__.invoke(n,e,r)}var r;return"function"==typeof SuppressedError&&SuppressedError,n.Format=void 0,(r=n.Format||(n.Format={})).QRCode="QR_CODE",r.UPC_A="UPC_A",r.UPC_E="UPC_E",r.EAN8="EAN_8",r.EAN13="EAN_13",r.Code39="CODE_39",r.Code93="CODE_93",r.Code128="CODE_128",r.Codabar="CODABAR",r.ITF="ITF",r.Aztec="AZTEC",r.DataMatrix="DATA_MATRIX",r.PDF417="PDF_417",n.cancel=async function(){await e("plugin:barcode-scanner|cancel")},n.checkPermissions=async function(){return await async function(n){return e(`plugin:${n}|check_permissions`)}("barcode-scanner").then((n=>n.camera))},n.openAppSettings=async function(){await e("plugin:barcode-scanner|open_app_settings")},n.requestPermissions=async function(){return await async function(n){return e(`plugin:${n}|request_permissions`)}("barcode-scanner").then((n=>n.camera))},n.scan=async function(n){return await e("plugin:barcode-scanner|scan",{...n})},n}({});Object.defineProperty(window.__TAURI__,"barcodeScanner",{value:__TAURI_PLUGIN_BARCODE_SCANNER__})}
diff --git a/plugins/barcode-scanner/build.rs b/plugins/barcode-scanner/build.rs
index 9239a404..25896b57 100644
--- a/plugins/barcode-scanner/build.rs
+++ b/plugins/barcode-scanner/build.rs
@@ -12,15 +12,14 @@ const COMMANDS: &[&str] = &[
];
fn main() {
- if let Err(error) = tauri_plugin::Builder::new(COMMANDS)
+ let result = tauri_plugin::Builder::new(COMMANDS)
+ .global_api_script_path("./api-iife.js")
.android_path("android")
.ios_path("ios")
- .try_build()
- {
- println!("{error:#}");
- // when building documentation for Android the plugin build result is irrelevant to the crate itself
- if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
- std::process::exit(1);
- }
+ .try_build();
+
+ // when building documentation for Android the plugin build result is always Err() and is irrelevant to the crate documentation build
+ if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
+ result.unwrap();
}
}
diff --git a/plugins/barcode-scanner/guest-js/index.ts b/plugins/barcode-scanner/guest-js/index.ts
index 8e964420..2f2361be 100644
--- a/plugins/barcode-scanner/guest-js/index.ts
+++ b/plugins/barcode-scanner/guest-js/index.ts
@@ -2,36 +2,40 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { invoke } from "@tauri-apps/api/core";
+import {
+ invoke,
+ requestPermissions as requestPermissions_,
+ checkPermissions as checkPermissions_
+} from '@tauri-apps/api/core'
-export type PermissionState = "granted" | "denied" | "prompt";
+export type { PermissionState } from '@tauri-apps/api/core'
export enum Format {
- QRCode = "QR_CODE",
- UPC_A = "UPC_A",
- UPC_E = "UPC_E",
- EAN8 = "EAN_8",
- EAN13 = "EAN_13",
- Code39 = "CODE_39",
- Code93 = "CODE_93",
- Code128 = "CODE_128",
- Codabar = "CODABAR",
- ITF = "ITF",
- Aztec = "AZTEC",
- DataMatrix = "DATA_MATRIX",
- PDF417 = "PDF_417",
+ QRCode = 'QR_CODE',
+ UPC_A = 'UPC_A',
+ UPC_E = 'UPC_E',
+ EAN8 = 'EAN_8',
+ EAN13 = 'EAN_13',
+ Code39 = 'CODE_39',
+ Code93 = 'CODE_93',
+ Code128 = 'CODE_128',
+ Codabar = 'CODABAR',
+ ITF = 'ITF',
+ Aztec = 'AZTEC',
+ DataMatrix = 'DATA_MATRIX',
+ PDF417 = 'PDF_417'
}
export interface ScanOptions {
- cameraDirection?: "back" | "front";
- formats?: Format[];
- windowed?: boolean;
+ cameraDirection?: 'back' | 'front'
+ formats?: Format[]
+ windowed?: boolean
}
export interface Scanned {
- content: string;
- format: Format;
- bounds: unknown;
+ content: string
+ format: Format
+ bounds: unknown
}
/**
@@ -39,37 +43,37 @@ export interface Scanned {
* @param options
*/
export async function scan(options?: ScanOptions): Promise {
- return await invoke("plugin:barcode-scanner|scan", { ...options });
+ return await invoke('plugin:barcode-scanner|scan', { ...options })
}
/**
* Cancel the current scan process.
*/
export async function cancel(): Promise {
- return await invoke("plugin:barcode-scanner|cancel");
+ await invoke('plugin:barcode-scanner|cancel')
}
/**
* Get permission state.
*/
export async function checkPermissions(): Promise {
- return await invoke<{ camera: PermissionState }>(
- "plugin:barcode-scanner|check_permissions",
- ).then((r) => r.camera);
+ return await checkPermissions_<{ camera: PermissionState }>(
+ 'barcode-scanner'
+ ).then((r) => r.camera)
}
/**
* Request permissions to use the camera.
*/
export async function requestPermissions(): Promise {
- return await invoke<{ camera: PermissionState }>(
- "plugin:barcode-scanner|request_permissions",
- ).then((r) => r.camera);
+ return await requestPermissions_<{ camera: PermissionState }>(
+ 'barcode-scanner'
+ ).then((r) => r.camera)
}
/**
* Open application settings. Useful if permission was denied and the user must manually enable it.
*/
export async function openAppSettings(): Promise {
- return await invoke("plugin:barcode-scanner|open_app_settings");
+ await invoke('plugin:barcode-scanner|open_app_settings')
}
diff --git a/plugins/barcode-scanner/ios/Package.swift b/plugins/barcode-scanner/ios/Package.swift
index aafb41c3..cf39b812 100644
--- a/plugins/barcode-scanner/ios/Package.swift
+++ b/plugins/barcode-scanner/ios/Package.swift
@@ -10,7 +10,8 @@ import PackageDescription
let package = Package(
name: "tauri-plugin-barcode-scanner",
platforms: [
- .iOS(.v13)
+ .macOS(.v10_13),
+ .iOS(.v13),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
diff --git a/plugins/barcode-scanner/ios/Sources/BarcodeScannerPlugin.swift b/plugins/barcode-scanner/ios/Sources/BarcodeScannerPlugin.swift
index 7a329e37..cde8d680 100644
--- a/plugins/barcode-scanner/ios/Sources/BarcodeScannerPlugin.swift
+++ b/plugins/barcode-scanner/ios/Sources/BarcodeScannerPlugin.swift
@@ -8,9 +8,9 @@ import UIKit
import WebKit
struct ScanOptions: Decodable {
- var formats: [SupportedFormat] = []
- let windowed: Bool?
- let cameraDirection: String?
+ var formats: [SupportedFormat]?
+ var windowed: Bool?
+ var cameraDirection: String?
}
enum SupportedFormat: String, CaseIterable, Decodable {
@@ -241,7 +241,7 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
private func runScanner(_ invoke: Invoke, args: ScanOptions) {
scanFormats = [AVMetadataObject.ObjectType]()
- args.formats.forEach { format in
+ (args.formats ?? []).forEach { format in
scanFormats.append(format.value)
}
@@ -262,6 +262,13 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
self.invoke = invoke
+ let entry = Bundle.main.infoDictionary?["NSCameraUsageDescription"] as? String
+
+ if entry == nil || entry?.count == 0 {
+ invoke.reject("NSCameraUsageDescription is not in the app Info.plist")
+ return
+ }
+
var iOS14min: Bool = false
if #available(iOS 14.0, *) { iOS14min = true }
if !iOS14min && self.getPermissionState() != "granted" {
diff --git a/plugins/barcode-scanner/package.json b/plugins/barcode-scanner/package.json
index e1fe29bd..9e8c8b56 100644
--- a/plugins/barcode-scanner/package.json
+++ b/plugins/barcode-scanner/package.json
@@ -1,11 +1,12 @@
{
"name": "@tauri-apps/plugin-barcode-scanner",
- "version": "2.0.0-beta.1",
+ "version": "2.2.0",
"description": "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS",
- "license": "MIT or APACHE-2.0",
+ "license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
+ "repository": "https://github.com/tauri-apps/plugins-workspace",
"type": "module",
"types": "./dist-js/index.d.ts",
"main": "./dist-js/index.cjs",
@@ -24,6 +25,6 @@
"LICENSE"
],
"dependencies": {
- "@tauri-apps/api": "2.0.0-beta.2"
+ "@tauri-apps/api": "^2.0.0"
}
}
diff --git a/plugins/barcode-scanner/permissions/autogenerated/reference.md b/plugins/barcode-scanner/permissions/autogenerated/reference.md
index d20ff148..9cc9f3c6 100644
--- a/plugins/barcode-scanner/permissions/autogenerated/reference.md
+++ b/plugins/barcode-scanner/permissions/autogenerated/reference.md
@@ -1,50 +1,185 @@
-# Permissions
+## Default Permission
-## allow-cancel
+This permission set configures which
+barcode scanning features are by default exposed.
+
+#### Granted Permissions
+
+It allows all barcode related features.
+
+
+
+#### This default permission set includes the following:
+
+- `allow-cancel`
+- `allow-check-permissions`
+- `allow-open-app-settings`
+- `allow-request-permissions`
+- `allow-scan`
+- `allow-vibrate`
+
+## Permission Table
+
+
+
+
Identifier
+
Description
+
+
+
+
+
+
+`barcode-scanner:allow-cancel`
+
+
+
Enables the cancel command without any pre-configured scope.
-## deny-cancel
+
+
+
+
+
+
+`barcode-scanner:deny-cancel`
+
+
+
Denies the cancel command without any pre-configured scope.
-## allow-check-permissions
+
+
+
+
+
+
+`barcode-scanner:allow-check-permissions`
+
+
+
Enables the check_permissions command without any pre-configured scope.
-## deny-check-permissions
+
+
+
+
+
+
+`barcode-scanner:deny-check-permissions`
+
+
+
Denies the check_permissions command without any pre-configured scope.
-## allow-open-app-settings
+
+
+
+
+
+
+`barcode-scanner:allow-open-app-settings`
+
+
+
Enables the open_app_settings command without any pre-configured scope.
-## deny-open-app-settings
+
+
+
+
+
+
+`barcode-scanner:deny-open-app-settings`
+
+
+
Denies the open_app_settings command without any pre-configured scope.
-## allow-request-permissions
+
Enables the request_permissions command without any pre-configured scope.
-## deny-request-permissions
+
+
+
+
+
+
+`barcode-scanner:deny-request-permissions`
+
+
+
Denies the request_permissions command without any pre-configured scope.
-## allow-scan
+
+
+
+
+
+
+`barcode-scanner:allow-scan`
+
+
+
Enables the scan command without any pre-configured scope.
-## deny-scan
+
+
+
+
+
+
+`barcode-scanner:deny-scan`
+
+
+
Denies the scan command without any pre-configured scope.
-## allow-vibrate
+
+
+
+
+
+
+`barcode-scanner:allow-vibrate`
+
+
+
Enables the vibrate command without any pre-configured scope.
-## deny-vibrate
+
+
+
+
+
+
+`barcode-scanner:deny-vibrate`
+
+
+
Denies the vibrate command without any pre-configured scope.
+
+
+
diff --git a/plugins/barcode-scanner/permissions/default.toml b/plugins/barcode-scanner/permissions/default.toml
new file mode 100644
index 00000000..3b5a2dfd
--- /dev/null
+++ b/plugins/barcode-scanner/permissions/default.toml
@@ -0,0 +1,20 @@
+"$schema" = "schemas/schema.json"
+[default]
+description = """
+This permission set configures which
+barcode scanning features are by default exposed.
+
+#### Granted Permissions
+
+It allows all barcode related features.
+
+"""
+
+permissions = [
+ "allow-cancel",
+ "allow-check-permissions",
+ "allow-open-app-settings",
+ "allow-request-permissions",
+ "allow-scan",
+ "allow-vibrate",
+]
diff --git a/plugins/barcode-scanner/permissions/schemas/schema.json b/plugins/barcode-scanner/permissions/schemas/schema.json
index 1fd55fd1..69fb0d5d 100644
--- a/plugins/barcode-scanner/permissions/schemas/schema.json
+++ b/plugins/barcode-scanner/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,92 +251,126 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-cancel -> Enables the cancel command without any pre-configured scope.",
+ "description": "MacOS.",
"type": "string",
"enum": [
- "allow-cancel"
+ "macOS"
]
},
{
- "description": "deny-cancel -> Denies the cancel command without any pre-configured scope.",
+ "description": "Windows.",
"type": "string",
"enum": [
- "deny-cancel"
+ "windows"
]
},
{
- "description": "allow-check-permissions -> Enables the check_permissions command without any pre-configured scope.",
+ "description": "Linux.",
"type": "string",
"enum": [
- "allow-check-permissions"
+ "linux"
]
},
{
- "description": "deny-check-permissions -> Denies the check_permissions command without any pre-configured scope.",
+ "description": "Android.",
"type": "string",
"enum": [
- "deny-check-permissions"
+ "android"
]
},
{
- "description": "allow-open-app-settings -> Enables the open_app_settings command without any pre-configured scope.",
+ "description": "iOS.",
"type": "string",
"enum": [
- "allow-open-app-settings"
+ "iOS"
]
+ }
+ ]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the cancel command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-cancel",
+ "markdownDescription": "Enables the cancel command without any pre-configured scope."
},
{
- "description": "deny-open-app-settings -> Denies the open_app_settings command without any pre-configured scope.",
+ "description": "Denies the cancel command without any pre-configured scope.",
"type": "string",
- "enum": [
- "deny-open-app-settings"
- ]
+ "const": "deny-cancel",
+ "markdownDescription": "Denies the cancel command without any pre-configured scope."
},
{
- "description": "allow-request-permissions -> Enables the request_permissions command without any pre-configured scope.",
+ "description": "Enables the check_permissions command without any pre-configured scope.",
"type": "string",
- "enum": [
- "allow-request-permissions"
- ]
+ "const": "allow-check-permissions",
+ "markdownDescription": "Enables the check_permissions command without any pre-configured scope."
},
{
- "description": "deny-request-permissions -> Denies the request_permissions command without any pre-configured scope.",
+ "description": "Denies the check_permissions command without any pre-configured scope.",
"type": "string",
- "enum": [
- "deny-request-permissions"
- ]
+ "const": "deny-check-permissions",
+ "markdownDescription": "Denies the check_permissions command without any pre-configured scope."
},
{
- "description": "allow-scan -> Enables the scan command without any pre-configured scope.",
+ "description": "Enables the open_app_settings command without any pre-configured scope.",
"type": "string",
- "enum": [
- "allow-scan"
- ]
+ "const": "allow-open-app-settings",
+ "markdownDescription": "Enables the open_app_settings command without any pre-configured scope."
},
{
- "description": "deny-scan -> Denies the scan command without any pre-configured scope.",
+ "description": "Denies the open_app_settings command without any pre-configured scope.",
"type": "string",
- "enum": [
- "deny-scan"
- ]
+ "const": "deny-open-app-settings",
+ "markdownDescription": "Denies the open_app_settings command without any pre-configured scope."
},
{
- "description": "allow-vibrate -> Enables the vibrate command without any pre-configured scope.",
+ "description": "Enables the request_permissions command without any pre-configured scope.",
"type": "string",
- "enum": [
- "allow-vibrate"
- ]
+ "const": "allow-request-permissions",
+ "markdownDescription": "Enables the request_permissions command without any pre-configured scope."
},
{
- "description": "deny-vibrate -> Denies the vibrate command without any pre-configured scope.",
+ "description": "Denies the request_permissions command without any pre-configured scope.",
"type": "string",
- "enum": [
- "deny-vibrate"
- ]
+ "const": "deny-request-permissions",
+ "markdownDescription": "Denies the request_permissions command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the scan command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-scan",
+ "markdownDescription": "Enables the scan command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the scan command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-scan",
+ "markdownDescription": "Denies the scan command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the vibrate command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-vibrate",
+ "markdownDescription": "Enables the vibrate command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the vibrate command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-vibrate",
+ "markdownDescription": "Denies the vibrate command without any pre-configured scope."
+ },
+ {
+ "description": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`",
+ "type": "string",
+ "const": "default",
+ "markdownDescription": "This permission set configures which\nbarcode scanning features are by default exposed.\n\n#### Granted Permissions\n\nIt allows all barcode related features.\n\n\n#### This default permission set includes:\n\n- `allow-cancel`\n- `allow-check-permissions`\n- `allow-open-app-settings`\n- `allow-request-permissions`\n- `allow-scan`\n- `allow-vibrate`"
}
]
}
diff --git a/plugins/barcode-scanner/rollup.config.js b/plugins/barcode-scanner/rollup.config.js
index 977dfac8..1f349ec8 100644
--- a/plugins/barcode-scanner/rollup.config.js
+++ b/plugins/barcode-scanner/rollup.config.js
@@ -2,6 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { createConfig } from "../../shared/rollup.config.js";
+import { createConfig } from '../../shared/rollup.config.js'
-export default createConfig();
+export default createConfig()
diff --git a/plugins/barcode-scanner/src/api-iife.js b/plugins/barcode-scanner/src/api-iife.js
deleted file mode 100644
index 77c9d45c..00000000
--- a/plugins/barcode-scanner/src/api-iife.js
+++ /dev/null
@@ -1 +0,0 @@
-if("__TAURI__"in window){var __TAURI_PLUGIN_BARCODESCANNER__=function(n){"use strict";async function e(n,e={},r){return window.__TAURI_INTERNALS__.invoke(n,e,r)}var r;return"function"==typeof SuppressedError&&SuppressedError,n.Format=void 0,(r=n.Format||(n.Format={})).QRCode="QR_CODE",r.UPC_A="UPC_A",r.UPC_E="UPC_E",r.EAN8="EAN_8",r.EAN13="EAN_13",r.Code39="CODE_39",r.Code93="CODE_93",r.Code128="CODE_128",r.Codabar="CODABAR",r.ITF="ITF",r.Aztec="AZTEC",r.DataMatrix="DATA_MATRIX",r.PDF417="PDF_417",n.cancel=async function(){return await e("plugin:barcode-scanner|cancel")},n.checkPermissions=async function(){return await e("plugin:barcode-scanner|check_permissions").then((n=>n.camera))},n.openAppSettings=async function(){return await e("plugin:barcode-scanner|open_app_settings")},n.requestPermissions=async function(){return await e("plugin:barcode-scanner|request_permissions").then((n=>n.camera))},n.scan=async function(n){return await e("plugin:barcode-scanner|scan",{...n})},n}({});Object.defineProperty(window.__TAURI__,"barcodeScanner",{value:__TAURI_PLUGIN_BARCODESCANNER__})}
diff --git a/plugins/barcode-scanner/src/lib.rs b/plugins/barcode-scanner/src/lib.rs
index 1b6fcff4..2f2e7ee9 100644
--- a/plugins/barcode-scanner/src/lib.rs
+++ b/plugins/barcode-scanner/src/lib.rs
@@ -27,7 +27,7 @@ pub struct BarcodeScanner(PluginHandle);
impl BarcodeScanner {}
-/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the barcode scanner APIs.
+/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the barcode scanner APIs.
pub trait BarcodeScannerExt {
fn barcode_scanner(&self) -> &BarcodeScanner;
}
diff --git a/plugins/biometric/CHANGELOG.md b/plugins/biometric/CHANGELOG.md
index 67aa19f9..5ebbe50f 100644
--- a/plugins/biometric/CHANGELOG.md
+++ b/plugins/biometric/CHANGELOG.md
@@ -1,5 +1,74 @@
# Changelog
+## \[2.2.1]
+
+### bug
+
+- [`10f9e66e`](https://github.com/tauri-apps/plugins-workspace/commit/10f9e66e32141dd35f4bf884fbf9102691187e92) ([#2633](https://github.com/tauri-apps/plugins-workspace/pull/2633) by [@pjf-dev](https://github.com/tauri-apps/plugins-workspace/../../pjf-dev)) Fix biometric plugin ignoring fallback logic when biometry status is unavailable or not enrolled on iOS.
+
+## \[2.2.0]
+
+- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+
+## \[2.0.1]
+
+- [`a1a82208`](https://github.com/tauri-apps/plugins-workspace/commit/a1a82208ed4ab87f83310be0dc95428aec9ab241) ([#1873](https://github.com/tauri-apps/plugins-workspace/pull/1873) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
+
+## \[2.0.0]
+
+- [`e2c4dfb6`](https://github.com/tauri-apps/plugins-workspace/commit/e2c4dfb6af43e5dd8d9ceba232c315f5febd55c1) Update to tauri v2 stable release.
+
+## \[2.0.0-rc.1]
+
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+
+## \[2.0.0-rc.2]
+
+- [`b9147758`](https://github.com/tauri-apps/plugins-workspace/commit/b914775898c2bee7ceb20bd17ee595005cd17a64) ([#1679](https://github.com/tauri-apps/plugins-workspace/pull/1679) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Explicitly set a minimum macOS version for the Swift package.
+
+## \[2.0.0-rc.1]
+
+### changes
+
+- [`6b079cfd`](https://github.com/tauri-apps/plugins-workspace/commit/6b079cfdd107c94abc2c7300f6af00bac3ff4040) ([#1649](https://github.com/tauri-apps/plugins-workspace/pull/1649) by [@ahqsoftwares](https://github.com/tauri-apps/plugins-workspace/../../ahqsoftwares)) Remove targetSdk from build.kts files as it is deprecated and will be removed from DSL v9.0
+
+## \[2.0.0-rc.0]
+
+- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+
+## \[2.0.0-beta.8]
+
+- [`99d6ac0f`](https://github.com/tauri-apps/plugins-workspace/commit/99d6ac0f9506a6a4a1aa59c728157190a7441af6) ([#1606](https://github.com/tauri-apps/plugins-workspace/pull/1606) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The JS packages now specify the *minimum* `@tauri-apps/api` version instead of a single exact version.
+- [`6de87966`](https://github.com/tauri-apps/plugins-workspace/commit/6de87966ecc00ad9d91c25be452f1f46bd2b7e1f) ([#1597](https://github.com/tauri-apps/plugins-workspace/pull/1597) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Update to tauri beta.25.
+
+## \[2.0.0-beta.7]
+
+- [`22a17980`](https://github.com/tauri-apps/plugins-workspace/commit/22a17980ff4f6f8c40adb1b8f4ffc6dae2fe7e30) ([#1537](https://github.com/tauri-apps/plugins-workspace/pull/1537) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri beta.24.
+
+## \[2.0.0-beta.6]
+
+- [`76daee7a`](https://github.com/tauri-apps/plugins-workspace/commit/76daee7aafece34de3092c86e531cf9eb1138989) ([#1512](https://github.com/tauri-apps/plugins-workspace/pull/1512) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update to tauri beta.23.
+
+## \[2.0.0-beta.5]
+
+- [`9013854f`](https://github.com/tauri-apps/plugins-workspace/commit/9013854f42a49a230b9dbb9d02774765528a923f)([#1382](https://github.com/tauri-apps/plugins-workspace/pull/1382)) Update to tauri beta.22.
+
+## \[2.0.0-beta.4]
+
+- [`430bd6f4`](https://github.com/tauri-apps/plugins-workspace/commit/430bd6f4f379bee5d232ae6b098ae131db7f178a)([#1363](https://github.com/tauri-apps/plugins-workspace/pull/1363)) Update to tauri beta.20.
+
+## \[2.0.0-beta.3]
+
+- [`bd1ed590`](https://github.com/tauri-apps/plugins-workspace/commit/bd1ed5903ffcce5500310dac1e59e8c67674ef1e)([#1237](https://github.com/tauri-apps/plugins-workspace/pull/1237)) Update to tauri beta.17.
+
+## \[2.0.0-beta.3]
+
+- [`a04ea2f`](https://github.com/tauri-apps/plugins-workspace/commit/a04ea2f38294d5a3987578283badc8eec87a7752)([#1071](https://github.com/tauri-apps/plugins-workspace/pull/1071)) The global API script is now only added to the binary when the `withGlobalTauri` config is true.
+
+## \[2.0.0-beta.2]
+
+- [`99bea25`](https://github.com/tauri-apps/plugins-workspace/commit/99bea2559c2c0648c2519c50a18cd124dacef57b)([#1005](https://github.com/tauri-apps/plugins-workspace/pull/1005)) Update to tauri beta.8.
+
## \[2.0.0-beta.1]
- [`569defb`](https://github.com/tauri-apps/plugins-workspace/commit/569defbe9492e38938554bb7bdc1be9151456d21) Update to tauri beta.4.
@@ -12,4 +81,14 @@
- [`8df28a9`](https://github.com/tauri-apps/plugins-workspace/commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
- [`8df28a9`](https://github.com/tauri-apps/plugins-workspace/commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
-commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ 29]\(https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ .
+ commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ itial release.
+ 29]\(https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ .
+ commit/8df28a987519ecfa03dcb8635443025f8d010362)([#829](https://github.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
+ ithub.com/tauri-apps/plugins-workspace/pull/829)) Initial release.
diff --git a/plugins/biometric/Cargo.toml b/plugins/biometric/Cargo.toml
index c1699fd4..2b76fea4 100644
--- a/plugins/biometric/Cargo.toml
+++ b/plugins/biometric/Cargo.toml
@@ -1,18 +1,28 @@
[package]
name = "tauri-plugin-biometric"
-version = "2.0.0-beta.1"
+version = "2.2.1"
description = "Prompt the user for biometric authentication on Android and iOS."
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
+repository = { workspace = true }
links = "tauri-plugin-biometric"
[package.metadata.docs.rs]
-rustc-args = [ "--cfg", "docsrs" ]
-rustdoc-args = [ "--cfg", "docsrs" ]
+rustc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs"]
+targets = ["x86_64-linux-android"]
+
+[package.metadata.platforms.support]
+windows = { level = "none", notes = "" }
+linux = { level = "none", notes = "" }
+macos = { level = "none", notes = "" }
+android = { level = "full", notes = "" }
+ios = { level = "full", notes = "" }
+
[build-dependencies]
-tauri-plugin = { workspace = true, features = [ "build" ] }
+tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
diff --git a/plugins/biometric/README.md b/plugins/biometric/README.md
index 459441eb..c7844f7b 100644
--- a/plugins/biometric/README.md
+++ b/plugins/biometric/README.md
@@ -2,6 +2,14 @@
Prompt the user for biometric authentication on Android and iOS.
+| Platform | Supported |
+| -------- | --------- |
+| Linux | x |
+| Windows | x |
+| macOS | x |
+| Android | ✓ |
+| iOS | ✓ |
+
## Install
_This plugin requires a Rust version of at least **1.65**_
@@ -18,7 +26,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
-tauri-plugin-biometric = "2.0.0-beta"
+tauri-plugin-biometric = "2.0.0"
# alternatively with Git:
tauri-plugin-biometric = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
@@ -48,7 +56,7 @@ yarn add https://github.com/tauri-apps/tauri-plugin-biometric#v2
First you need to register the core plugin with Tauri:
-`src-tauri/src/main.rs`
+`src-tauri/src/lib.rs`
```rust
fn main() {
@@ -62,8 +70,8 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { authenticate } from "@tauri-apps/plugin-biometric";
-await authenticate('Open your wallet');
+import { authenticate } from '@tauri-apps/plugin-biometric'
+await authenticate('Open your wallet')
```
## Contributing
diff --git a/plugins/biometric/SECURITY.md b/plugins/biometric/SECURITY.md
new file mode 100644
index 00000000..4f09bbac
--- /dev/null
+++ b/plugins/biometric/SECURITY.md
@@ -0,0 +1,23 @@
+# Security Policy
+
+**Do not report security vulnerabilities through public GitHub issues.**
+
+**Please use the [Private Vulnerability Disclosure](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) feature of GitHub.**
+
+Include as much of the following information:
+
+- Type of issue (e.g. improper input parsing, privilege escalation, etc.)
+- The location of the affected source code (tag/branch/commit or direct URL)
+- Any special configuration required to reproduce the issue
+- The distribution affected or used to help us with reproduction of the issue
+- Step-by-step instructions to reproduce the issue
+- Ideally a reproduction repository
+- Impact of the issue, including how an attacker might exploit the issue
+
+We prefer to receive reports in English.
+
+## Contact
+
+Please disclose a vulnerability or security relevant issue here: [https://github.com/tauri-apps/plugins-workspace/security/advisories/new](https://github.com/tauri-apps/plugins-workspace/security/advisories/new).
+
+Alternatively, you can also contact us by email via [security@tauri.app](mailto:security@tauri.app).
diff --git a/plugins/biometric/android/build.gradle.kts b/plugins/biometric/android/build.gradle.kts
index 81d4f70e..d8833662 100644
--- a/plugins/biometric/android/build.gradle.kts
+++ b/plugins/biometric/android/build.gradle.kts
@@ -5,11 +5,10 @@ plugins {
android {
namespace = "app.tauri.biometric"
- compileSdk = 32
+ compileSdk = 34
defaultConfig {
- minSdk = 24
- targetSdk = 32
+ minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
diff --git a/plugins/biometric/android/src/main/java/BiometricPlugin.kt b/plugins/biometric/android/src/main/java/BiometricPlugin.kt
index 11e3ddf5..b3436fd4 100644
--- a/plugins/biometric/android/src/main/java/BiometricPlugin.kt
+++ b/plugins/biometric/android/src/main/java/BiometricPlugin.kt
@@ -115,6 +115,7 @@ class BiometricPlugin(private val activity: Activity): Plugin(activity) {
val biometryResult = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
manager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)
} else {
+ @Suppress("DEPRECATION")
manager.canAuthenticate()
}
val ret = JSObject()
diff --git a/plugins/biometric/api-iife.js b/plugins/biometric/api-iife.js
new file mode 100644
index 00000000..3da2296b
--- /dev/null
+++ b/plugins/biometric/api-iife.js
@@ -0,0 +1 @@
+if("__TAURI__"in window){var __TAURI_PLUGIN_BIOMETRIC__=function(e){"use strict";async function i(e,i={},t){return window.__TAURI_INTERNALS__.invoke(e,i,t)}var t;return"function"==typeof SuppressedError&&SuppressedError,e.BiometryType=void 0,(t=e.BiometryType||(e.BiometryType={}))[t.None=0]="None",t[t.TouchID=1]="TouchID",t[t.FaceID=2]="FaceID",t[t.Iris=3]="Iris",e.authenticate=async function(e,t){await i("plugin:biometric|authenticate",{reason:e,...t})},e.checkStatus=async function(){return await i("plugin:biometric|status")},e}({});Object.defineProperty(window.__TAURI__,"biometric",{value:__TAURI_PLUGIN_BIOMETRIC__})}
diff --git a/plugins/biometric/build.rs b/plugins/biometric/build.rs
index 3df01ac9..070986b2 100644
--- a/plugins/biometric/build.rs
+++ b/plugins/biometric/build.rs
@@ -5,8 +5,14 @@
const COMMANDS: &[&str] = &["authenticate", "status"];
fn main() {
- tauri_plugin::Builder::new(COMMANDS)
+ let result = tauri_plugin::Builder::new(COMMANDS)
+ .global_api_script_path("./api-iife.js")
.android_path("android")
.ios_path("ios")
- .build();
+ .try_build();
+
+ // when building documentation for Android the plugin build result is always Err() and is irrelevant to the crate documentation build
+ if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
+ result.unwrap();
+ }
}
diff --git a/plugins/biometric/guest-js/index.ts b/plugins/biometric/guest-js/index.ts
index 16ab3807..5c3eb8df 100644
--- a/plugins/biometric/guest-js/index.ts
+++ b/plugins/biometric/guest-js/index.ts
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { invoke } from "@tauri-apps/api/core";
+import { invoke } from '@tauri-apps/api/core'
export enum BiometryType {
None = 0,
@@ -11,39 +11,39 @@ export enum BiometryType {
// Apple FaceID or Android face authentication
FaceID = 2,
// Android iris authentication
- Iris = 3,
+ Iris = 3
}
export interface Status {
- isAvailable: boolean;
- biometryType: BiometryType;
- error?: string;
+ isAvailable: boolean
+ biometryType: BiometryType
+ error?: string
errorCode?:
- | "appCancel"
- | "authenticationFailed"
- | "invalidContext"
- | "notInteractive"
- | "passcodeNotSet"
- | "systemCancel"
- | "userCancel"
- | "userFallback"
- | "biometryLockout"
- | "biometryNotAvailable"
- | "biometryNotEnrolled";
+ | 'appCancel'
+ | 'authenticationFailed'
+ | 'invalidContext'
+ | 'notInteractive'
+ | 'passcodeNotSet'
+ | 'systemCancel'
+ | 'userCancel'
+ | 'userFallback'
+ | 'biometryLockout'
+ | 'biometryNotAvailable'
+ | 'biometryNotEnrolled'
}
export interface AuthOptions {
- allowDeviceCredential?: boolean;
- cancelTitle?: string;
+ allowDeviceCredential?: boolean
+ cancelTitle?: string
// iOS options
- fallbackTitle?: string;
+ fallbackTitle?: string
// android options
- title?: string;
- subtitle?: string;
- confirmationRequired?: boolean;
- maxAttemps?: number;
+ title?: string
+ subtitle?: string
+ confirmationRequired?: boolean
+ maxAttemps?: number
}
/**
@@ -51,7 +51,7 @@ export interface AuthOptions {
* @returns a promise resolving to an object containing all the information about the status of the biometry.
*/
export async function checkStatus(): Promise {
- return invoke("plugin:biometric|status");
+ return await invoke('plugin:biometric|status')
}
/**
@@ -68,10 +68,10 @@ export async function checkStatus(): Promise {
*/
export async function authenticate(
reason: string,
- options?: AuthOptions,
+ options?: AuthOptions
): Promise {
- return invoke("plugin:biometric|authenticate", {
+ await invoke('plugin:biometric|authenticate', {
reason,
- ...options,
- });
+ ...options
+ })
}
diff --git a/plugins/biometric/ios/Package.swift b/plugins/biometric/ios/Package.swift
index 34c9f87e..7860f476 100644
--- a/plugins/biometric/ios/Package.swift
+++ b/plugins/biometric/ios/Package.swift
@@ -8,7 +8,8 @@ import PackageDescription
let package = Package(
name: "tauri-plugin-biometric",
platforms: [
- .iOS(.v13)
+ .macOS(.v10_13),
+ .iOS(.v13),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
diff --git a/plugins/biometric/ios/Sources/BiometricPlugin.swift b/plugins/biometric/ios/Sources/BiometricPlugin.swift
index 7e3e8bbd..c295904a 100644
--- a/plugins/biometric/ios/Sources/BiometricPlugin.swift
+++ b/plugins/biometric/ios/Sources/BiometricPlugin.swift
@@ -25,8 +25,8 @@ class BiometricStatus {
struct AuthOptions: Decodable {
let reason: String
var allowDeviceCredential: Bool?
- let fallbackTitle: String?
- let cancelTitle: String?
+ var fallbackTitle: String?
+ var cancelTitle: String?
}
class BiometricPlugin: Plugin {
@@ -98,7 +98,12 @@ class BiometricPlugin: Plugin {
}
@objc func authenticate(_ invoke: Invoke) throws {
- guard self.status.available else {
+ let args = try invoke.parseArgs(AuthOptions.self)
+
+ let allowDeviceCredential = args.allowDeviceCredential ?? false
+
+ guard self.status.available || allowDeviceCredential else {
+ // Biometry unavailable, fallback disabled
invoke.reject(
self.status.errorReason ?? "",
code: self.status.errorCode ?? ""
@@ -106,15 +111,11 @@ class BiometricPlugin: Plugin {
return
}
- let args = try invoke.parseArgs(AuthOptions.self)
-
let context = LAContext()
context.localizedFallbackTitle = args.fallbackTitle
context.localizedCancelTitle = args.cancelTitle
context.touchIDAuthenticationAllowableReuseDuration = 0
- let allowDeviceCredential = args.allowDeviceCredential ?? false
-
// force system default fallback title if an empty string is provided (the OS hides the fallback button in this case)
if allowDeviceCredential,
let fallbackTitle = context.localizedFallbackTitle,
diff --git a/plugins/biometric/package.json b/plugins/biometric/package.json
index 82578b0a..2307d67b 100644
--- a/plugins/biometric/package.json
+++ b/plugins/biometric/package.json
@@ -1,10 +1,11 @@
{
"name": "@tauri-apps/plugin-biometric",
- "version": "2.0.0-beta.1",
- "license": "MIT or APACHE-2.0",
+ "version": "2.2.1",
+ "license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
+ "repository": "https://github.com/tauri-apps/plugins-workspace",
"type": "module",
"types": "./dist-js/index.d.ts",
"main": "./dist-js/index.cjs",
@@ -23,10 +24,7 @@
"README.md",
"LICENSE"
],
- "devDependencies": {
- "tslib": "2.6.0"
- },
"dependencies": {
- "@tauri-apps/api": "2.0.0-beta.2"
+ "@tauri-apps/api": "^2.0.0"
}
}
diff --git a/plugins/biometric/permissions/autogenerated/reference.md b/plugins/biometric/permissions/autogenerated/reference.md
index ef091dfa..8f085093 100644
--- a/plugins/biometric/permissions/autogenerated/reference.md
+++ b/plugins/biometric/permissions/autogenerated/reference.md
@@ -1,18 +1,77 @@
-# Permissions
+## Default Permission
-## allow-authenticate
+This permission set configures which
+biometric features are by default exposed.
+
+#### Granted Permissions
+
+It allows acccess to all biometric commands.
+
+
+
+#### This default permission set includes the following:
+
+- `allow-authenticate`
+- `allow-status`
+
+## Permission Table
+
+
+
+
Identifier
+
Description
+
+
+
+
+
+
+`biometric:allow-authenticate`
+
+
+
Enables the authenticate command without any pre-configured scope.
-## deny-authenticate
+
+
+
+
+
+
+`biometric:deny-authenticate`
+
+
+
Denies the authenticate command without any pre-configured scope.
-## allow-status
+
+
+
+
+
+
+`biometric:allow-status`
+
+
+
Enables the status command without any pre-configured scope.
-## deny-status
+
+
+
+
+
+
+`biometric:deny-status`
+
+
+
Denies the status command without any pre-configured scope.
+
+
+
diff --git a/plugins/biometric/permissions/default.toml b/plugins/biometric/permissions/default.toml
new file mode 100644
index 00000000..651990ef
--- /dev/null
+++ b/plugins/biometric/permissions/default.toml
@@ -0,0 +1,13 @@
+"$schema" = "schemas/schema.json"
+[default]
+description = """
+This permission set configures which
+biometric features are by default exposed.
+
+#### Granted Permissions
+
+It allows acccess to all biometric commands.
+
+"""
+
+permissions = ["allow-authenticate", "allow-status"]
diff --git a/plugins/biometric/permissions/schemas/schema.json b/plugins/biometric/permissions/schemas/schema.json
index 8a83e483..416759b5 100644
--- a/plugins/biometric/permissions/schemas/schema.json
+++ b/plugins/biometric/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,36 +251,78 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-authenticate -> Enables the authenticate command without any pre-configured scope.",
+ "description": "MacOS.",
"type": "string",
"enum": [
- "allow-authenticate"
+ "macOS"
]
},
{
- "description": "deny-authenticate -> Denies the authenticate command without any pre-configured scope.",
+ "description": "Windows.",
"type": "string",
"enum": [
- "deny-authenticate"
+ "windows"
]
},
{
- "description": "allow-status -> Enables the status command without any pre-configured scope.",
+ "description": "Linux.",
"type": "string",
"enum": [
- "allow-status"
+ "linux"
]
},
{
- "description": "deny-status -> Denies the status command without any pre-configured scope.",
+ "description": "Android.",
"type": "string",
"enum": [
- "deny-status"
+ "android"
]
+ },
+ {
+ "description": "iOS.",
+ "type": "string",
+ "enum": [
+ "iOS"
+ ]
+ }
+ ]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the authenticate command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-authenticate",
+ "markdownDescription": "Enables the authenticate command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the authenticate command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-authenticate",
+ "markdownDescription": "Denies the authenticate command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the status command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-status",
+ "markdownDescription": "Enables the status command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the status command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-status",
+ "markdownDescription": "Denies the status command without any pre-configured scope."
+ },
+ {
+ "description": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`",
+ "type": "string",
+ "const": "default",
+ "markdownDescription": "This permission set configures which\nbiometric features are by default exposed.\n\n#### Granted Permissions\n\nIt allows acccess to all biometric commands.\n\n\n#### This default permission set includes:\n\n- `allow-authenticate`\n- `allow-status`"
}
]
}
diff --git a/plugins/biometric/rollup.config.js b/plugins/biometric/rollup.config.js
index 977dfac8..1f349ec8 100644
--- a/plugins/biometric/rollup.config.js
+++ b/plugins/biometric/rollup.config.js
@@ -2,6 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { createConfig } from "../../shared/rollup.config.js";
+import { createConfig } from '../../shared/rollup.config.js'
-export default createConfig();
+export default createConfig()
diff --git a/plugins/biometric/src/api-iife.js b/plugins/biometric/src/api-iife.js
deleted file mode 100644
index 450585b5..00000000
--- a/plugins/biometric/src/api-iife.js
+++ /dev/null
@@ -1 +0,0 @@
-if("__TAURI__"in window){var __TAURI_PLUGIN_BIOMETRIC__=function(e){"use strict";async function n(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var r;return"function"==typeof SuppressedError&&SuppressedError,e.BiometryType=void 0,(r=e.BiometryType||(e.BiometryType={}))[r.None=0]="None",r[r.TouchID=1]="TouchID",r[r.FaceID=2]="FaceID",r[r.Iris=3]="Iris",e.authenticate=async function(e,r){return n("plugin:biometric|authenticate",{reason:e,...r})},e.checkStatus=async function(){return n("plugin:biometric|status")},e}({});Object.defineProperty(window.__TAURI__,"biometric",{value:__TAURI_PLUGIN_BIOMETRIC__})}
diff --git a/plugins/biometric/src/lib.rs b/plugins/biometric/src/lib.rs
index 8b0d472d..f79a104d 100644
--- a/plugins/biometric/src/lib.rs
+++ b/plugins/biometric/src/lib.rs
@@ -45,7 +45,7 @@ impl Biometric {
}
}
-/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the biometric APIs.
+/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the biometric APIs.
pub trait BiometricExt {
fn biometric(&self) -> &Biometric;
}
@@ -59,7 +59,6 @@ impl> crate::BiometricExt for T {
/// Initializes the plugin.
pub fn init() -> TauriPlugin {
Builder::new("biometric")
- .js_init_script(include_str!("api-iife.js").to_string())
.setup(|app, api| {
#[cfg(target_os = "android")]
let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "BiometricPlugin")?;
diff --git a/plugins/biometric/src/models.rs b/plugins/biometric/src/models.rs
index e4fceedc..49c84300 100644
--- a/plugins/biometric/src/models.rs
+++ b/plugins/biometric/src/models.rs
@@ -7,16 +7,17 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AuthOptions {
+ /// Enables authentication using the device's password. This feature is available on both Android and iOS.
pub allow_device_credential: bool,
- /// iOS only.
- pub fallback_title: Option,
- /// iOS only.
+ /// Label for the Cancel button. This feature is available on both Android and iOS.
pub cancel_title: Option,
- /// Android only.
+ /// Specifies the text displayed on the fallback button if biometric authentication fails. This feature is available iOS only.
+ pub fallback_title: Option,
+ /// Title indicating the purpose of biometric verification. This feature is available Android only.
pub title: Option,
- /// Android only.
+ /// SubTitle providing contextual information of biometric verification. This feature is available Android only.
pub subtitle: Option,
- /// Android only.
+ /// Specifies whether additional user confirmation is required, such as pressing a button after successful biometric authentication. This feature is available Android only.
pub confirmation_required: Option,
}
diff --git a/plugins/cli/CHANGELOG.md b/plugins/cli/CHANGELOG.md
index 84b71e6f..c2c011e2 100644
--- a/plugins/cli/CHANGELOG.md
+++ b/plugins/cli/CHANGELOG.md
@@ -1,5 +1,62 @@
# Changelog
+## \[2.2.0]
+
+- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+
+## \[2.0.1]
+
+- [`a1a82208`](https://github.com/tauri-apps/plugins-workspace/commit/a1a82208ed4ab87f83310be0dc95428aec9ab241) ([#1873](https://github.com/tauri-apps/plugins-workspace/pull/1873) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
+
+## \[2.0.0]
+
+- [`e2c4dfb6`](https://github.com/tauri-apps/plugins-workspace/commit/e2c4dfb6af43e5dd8d9ceba232c315f5febd55c1) Update to tauri v2 stable release.
+
+## \[2.0.0-rc.2]
+
+- [`68579934`](https://github.com/tauri-apps/plugins-workspace/commit/68579934c93f6ed2edbc97474560d6a8a00e8f70) ([#1856](https://github.com/tauri-apps/plugins-workspace/pull/1856) by [@amrbashir](https://github.com/tauri-apps/plugins-workspace/../../amrbashir)) Expose `Matches`, `SubcommandMatches` and `ArgData` structs.
+
+## \[2.0.0-rc.1]
+
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+
+## \[2.0.0-rc.0]
+
+- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+
+## \[2.0.0-beta.8]
+
+- [`99d6ac0f`](https://github.com/tauri-apps/plugins-workspace/commit/99d6ac0f9506a6a4a1aa59c728157190a7441af6) ([#1606](https://github.com/tauri-apps/plugins-workspace/pull/1606) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The JS packages now specify the *minimum* `@tauri-apps/api` version instead of a single exact version.
+- [`6de87966`](https://github.com/tauri-apps/plugins-workspace/commit/6de87966ecc00ad9d91c25be452f1f46bd2b7e1f) ([#1597](https://github.com/tauri-apps/plugins-workspace/pull/1597) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Update to tauri beta.25.
+
+## \[2.0.0-beta.7]
+
+- [`22a17980`](https://github.com/tauri-apps/plugins-workspace/commit/22a17980ff4f6f8c40adb1b8f4ffc6dae2fe7e30) ([#1537](https://github.com/tauri-apps/plugins-workspace/pull/1537) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri beta.24.
+
+## \[2.0.0-beta.6]
+
+- [`76daee7a`](https://github.com/tauri-apps/plugins-workspace/commit/76daee7aafece34de3092c86e531cf9eb1138989) ([#1512](https://github.com/tauri-apps/plugins-workspace/pull/1512) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update to tauri beta.23.
+
+## \[2.0.0-beta.5]
+
+- [`9013854f`](https://github.com/tauri-apps/plugins-workspace/commit/9013854f42a49a230b9dbb9d02774765528a923f)([#1382](https://github.com/tauri-apps/plugins-workspace/pull/1382)) Update to tauri beta.22.
+
+## \[2.0.0-beta.4]
+
+- [`430bd6f4`](https://github.com/tauri-apps/plugins-workspace/commit/430bd6f4f379bee5d232ae6b098ae131db7f178a)([#1363](https://github.com/tauri-apps/plugins-workspace/pull/1363)) Update to tauri beta.20.
+
+## \[2.0.0-beta.3]
+
+- [`bd1ed590`](https://github.com/tauri-apps/plugins-workspace/commit/bd1ed5903ffcce5500310dac1e59e8c67674ef1e)([#1237](https://github.com/tauri-apps/plugins-workspace/pull/1237)) Update to tauri beta.17.
+
+## \[2.0.0-beta.3]
+
+- [`a04ea2f`](https://github.com/tauri-apps/plugins-workspace/commit/a04ea2f38294d5a3987578283badc8eec87a7752)([#1071](https://github.com/tauri-apps/plugins-workspace/pull/1071)) The global API script is now only added to the binary when the `withGlobalTauri` config is true.
+
+## \[2.0.0-beta.2]
+
+- [`99bea25`](https://github.com/tauri-apps/plugins-workspace/commit/99bea2559c2c0648c2519c50a18cd124dacef57b)([#1005](https://github.com/tauri-apps/plugins-workspace/pull/1005)) Update to tauri beta.8.
+
## \[2.0.0-beta.1]
- [`569defb`](https://github.com/tauri-apps/plugins-workspace/commit/569defbe9492e38938554bb7bdc1be9151456d21) Update to tauri beta.4.
@@ -36,9 +93,3 @@
- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
te to alpha.11.
-
-## \[2.0.0-alpha.0]
-
-- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
- ae67\`]\(https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
-717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
diff --git a/plugins/cli/Cargo.toml b/plugins/cli/Cargo.toml
index 478d6b47..500ba957 100644
--- a/plugins/cli/Cargo.toml
+++ b/plugins/cli/Cargo.toml
@@ -1,19 +1,28 @@
[package]
name = "tauri-plugin-cli"
-version = "2.0.0-beta.1"
+version = "2.2.0"
description = "Parse arguments from your Tauri application's command line interface."
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }
+repository = { workspace = true }
links = "tauri-plugin-cli"
[package.metadata.docs.rs]
-rustc-args = [ "--cfg", "docsrs" ]
-rustdoc-args = [ "--cfg", "docsrs" ]
+rustc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs"]
+
+[package.metadata.platforms.support]
+windows = { level = "full", notes = "" }
+linux = { level = "full", notes = "" }
+macos = { level = "full", notes = "" }
+android = { level = "none", notes = "" }
+ios = { level = "none", notes = "" }
+
[build-dependencies]
-tauri-plugin = { workspace = true, features = [ "build" ] }
+tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
@@ -21,4 +30,4 @@ serde_json = { workspace = true }
tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
-clap = { version = "4", features = [ "string" ] }
+clap = { version = "4", features = ["string"] }
diff --git a/plugins/cli/README.md b/plugins/cli/README.md
index c58a6f31..91a8080b 100644
--- a/plugins/cli/README.md
+++ b/plugins/cli/README.md
@@ -2,11 +2,17 @@
Parse arguments from your Command Line Interface.
-- Supported platforms: Windows, Linux and macOS.
+| Platform | Supported |
+| -------- | --------- |
+| Linux | ✓ |
+| Windows | ✓ |
+| macOS | ✓ |
+| Android | x |
+| iOS | x |
## Install
-_This plugin requires a Rust version of at least **1.75**_
+_This plugin requires a Rust version of at least **1.77.2**_
There are three general methods of installation that we can recommend.
@@ -21,7 +27,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
# you can add the dependencies on the `[dependencies]` section if you do not target mobile
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
-tauri-plugin-cli = "2.0.0-beta"
+tauri-plugin-cli = "2.0.0"
# alternatively with Git:
tauri-plugin-cli = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
@@ -49,7 +55,7 @@ yarn add https://github.com/tauri-apps/tauri-plugin-cli#v2
First you need to register the core plugin with Tauri:
-`src-tauri/src/main.rs`
+`src-tauri/src/lib.rs`
```rust
fn main() {
@@ -67,16 +73,16 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { getMatches } from "@tauri-apps/plugin-cli";
-const matches = await getMatches();
-if (matches.subcommand?.name === "run") {
+import { getMatches } from '@tauri-apps/plugin-cli'
+const matches = await getMatches()
+if (matches.subcommand?.name === 'run') {
// `./your-app run $ARGS` was executed
- const args = matches.subcommand?.matches.args;
- if ("debug" in args) {
+ const args = matches.subcommand?.matches.args
+ if ('debug' in args) {
// `./your-app run --debug` was executed
}
} else {
- const args = matches.args;
+ const args = matches.args
// `./your-app $ARGS` was executed
}
```
diff --git a/plugins/cli/SECURITY.md b/plugins/cli/SECURITY.md
new file mode 100644
index 00000000..4f09bbac
--- /dev/null
+++ b/plugins/cli/SECURITY.md
@@ -0,0 +1,23 @@
+# Security Policy
+
+**Do not report security vulnerabilities through public GitHub issues.**
+
+**Please use the [Private Vulnerability Disclosure](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) feature of GitHub.**
+
+Include as much of the following information:
+
+- Type of issue (e.g. improper input parsing, privilege escalation, etc.)
+- The location of the affected source code (tag/branch/commit or direct URL)
+- Any special configuration required to reproduce the issue
+- The distribution affected or used to help us with reproduction of the issue
+- Step-by-step instructions to reproduce the issue
+- Ideally a reproduction repository
+- Impact of the issue, including how an attacker might exploit the issue
+
+We prefer to receive reports in English.
+
+## Contact
+
+Please disclose a vulnerability or security relevant issue here: [https://github.com/tauri-apps/plugins-workspace/security/advisories/new](https://github.com/tauri-apps/plugins-workspace/security/advisories/new).
+
+Alternatively, you can also contact us by email via [security@tauri.app](mailto:security@tauri.app).
diff --git a/plugins/cli/src/api-iife.js b/plugins/cli/api-iife.js
similarity index 100%
rename from plugins/cli/src/api-iife.js
rename to plugins/cli/api-iife.js
diff --git a/plugins/cli/build.rs b/plugins/cli/build.rs
index 15ff656f..50d88849 100644
--- a/plugins/cli/build.rs
+++ b/plugins/cli/build.rs
@@ -5,5 +5,7 @@
const COMMANDS: &[&str] = &["cli_matches"];
fn main() {
- tauri_plugin::Builder::new(COMMANDS).build();
+ tauri_plugin::Builder::new(COMMANDS)
+ .global_api_script_path("./api-iife.js")
+ .build();
}
diff --git a/plugins/cli/guest-js/index.ts b/plugins/cli/guest-js/index.ts
index 0ab7868e..7a7f4acf 100644
--- a/plugins/cli/guest-js/index.ts
+++ b/plugins/cli/guest-js/index.ts
@@ -8,7 +8,7 @@
* @module
*/
-import { invoke } from "@tauri-apps/api/core";
+import { invoke } from '@tauri-apps/api/core'
/**
* @since 2.0.0
@@ -19,27 +19,27 @@ interface ArgMatch {
* boolean if flag
* string[] or null if takes multiple values
*/
- value: string | boolean | string[] | null;
+ value: string | boolean | string[] | null
/**
* Number of occurrences
*/
- occurrences: number;
+ occurrences: number
}
/**
* @since 2.0.0
*/
interface SubcommandMatch {
- name: string;
- matches: CliMatches;
+ name: string
+ matches: CliMatches
}
/**
* @since 2.0.0
*/
interface CliMatches {
- args: Record;
- subcommand: SubcommandMatch | null;
+ args: Record
+ subcommand: SubcommandMatch | null
}
/**
@@ -64,9 +64,9 @@ interface CliMatches {
* @since 2.0.0
*/
async function getMatches(): Promise {
- return await invoke("plugin:cli|cli_matches");
+ return await invoke('plugin:cli|cli_matches')
}
-export type { ArgMatch, SubcommandMatch, CliMatches };
+export type { ArgMatch, SubcommandMatch, CliMatches }
-export { getMatches };
+export { getMatches }
diff --git a/plugins/cli/package.json b/plugins/cli/package.json
index be8cebba..e5ff8b73 100644
--- a/plugins/cli/package.json
+++ b/plugins/cli/package.json
@@ -1,10 +1,11 @@
{
"name": "@tauri-apps/plugin-cli",
- "version": "2.0.0-beta.1",
- "license": "MIT or APACHE-2.0",
+ "version": "2.2.0",
+ "license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
+ "repository": "https://github.com/tauri-apps/plugins-workspace",
"type": "module",
"types": "./dist-js/index.d.ts",
"main": "./dist-js/index.cjs",
@@ -23,6 +24,6 @@
"LICENSE"
],
"dependencies": {
- "@tauri-apps/api": "2.0.0-beta.2"
+ "@tauri-apps/api": "^2.0.0"
}
}
diff --git a/plugins/cli/permissions/autogenerated/reference.md b/plugins/cli/permissions/autogenerated/reference.md
index 0f231dc3..cfa83f0a 100644
--- a/plugins/cli/permissions/autogenerated/reference.md
+++ b/plugins/cli/permissions/autogenerated/reference.md
@@ -1,14 +1,43 @@
-# Permissions
+## Default Permission
-## allow-cli-matches
+Allows reading the CLI matches
+
+#### This default permission set includes the following:
+
+- `allow-cli-matches`
+
+## Permission Table
+
+
+
+
Identifier
+
Description
+
+
+
+
+
+
+`cli:allow-cli-matches`
+
+
+
Enables the cli_matches command without any pre-configured scope.
-## deny-cli-matches
+
+
-Denies the cli_matches command without any pre-configured scope.
+
+
-## default
+`cli:deny-cli-matches`
-Allows reading the CLI matches
+
+
+
+Denies the cli_matches command without any pre-configured scope.
+
+
+
diff --git a/plugins/cli/permissions/schemas/schema.json b/plugins/cli/permissions/schemas/schema.json
index 47519c42..45941514 100644
--- a/plugins/cli/permissions/schemas/schema.json
+++ b/plugins/cli/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,31 +251,68 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-cli-matches -> Enables the cli_matches command without any pre-configured scope.",
+ "description": "MacOS.",
+ "type": "string",
+ "enum": [
+ "macOS"
+ ]
+ },
+ {
+ "description": "Windows.",
+ "type": "string",
+ "enum": [
+ "windows"
+ ]
+ },
+ {
+ "description": "Linux.",
"type": "string",
"enum": [
- "allow-cli-matches"
+ "linux"
]
},
{
- "description": "deny-cli-matches -> Denies the cli_matches command without any pre-configured scope.",
+ "description": "Android.",
"type": "string",
"enum": [
- "deny-cli-matches"
+ "android"
]
},
{
- "description": "default -> Allows reading the CLI matches",
+ "description": "iOS.",
"type": "string",
"enum": [
- "default"
+ "iOS"
]
}
]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the cli_matches command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-cli-matches",
+ "markdownDescription": "Enables the cli_matches command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the cli_matches command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-cli-matches",
+ "markdownDescription": "Denies the cli_matches command without any pre-configured scope."
+ },
+ {
+ "description": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`",
+ "type": "string",
+ "const": "default",
+ "markdownDescription": "Allows reading the CLI matches\n#### This default permission set includes:\n\n- `allow-cli-matches`"
+ }
+ ]
}
}
}
\ No newline at end of file
diff --git a/plugins/cli/rollup.config.js b/plugins/cli/rollup.config.js
index 977dfac8..1f349ec8 100644
--- a/plugins/cli/rollup.config.js
+++ b/plugins/cli/rollup.config.js
@@ -2,6 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { createConfig } from "../../shared/rollup.config.js";
+import { createConfig } from '../../shared/rollup.config.js'
-export default createConfig();
+export default createConfig()
diff --git a/plugins/cli/src/error.rs b/plugins/cli/src/error.rs
index b4bd2872..2b5e1602 100644
--- a/plugins/cli/src/error.rs
+++ b/plugins/cli/src/error.rs
@@ -18,3 +18,5 @@ impl Serialize for Error {
serializer.serialize_str(self.to_string().as_ref())
}
}
+
+pub type Result = std::result::Result;
diff --git a/plugins/cli/src/lib.rs b/plugins/cli/src/lib.rs
index c666874c..3e144376 100644
--- a/plugins/cli/src/lib.rs
+++ b/plugins/cli/src/lib.rs
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-//! [](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/cli)
-//!
//! Parse arguments from your Command Line Interface.
//!
//! - Supported platforms: Windows, Linux and macOS.
@@ -23,8 +21,9 @@ mod error;
mod parser;
use config::{Arg, Config};
-pub use error::Error;
-type Result = std::result::Result;
+
+pub use error::{Error, Result};
+pub use parser::{ArgData, Matches, SubcommandMatches};
pub struct Cli(PluginApi);
@@ -51,7 +50,6 @@ fn cli_matches(_app: AppHandle, cli: State<'_, Cli>) -> Result
pub fn init() -> TauriPlugin {
Builder::new("cli")
- .js_init_script(include_str!("api-iife.js").to_string())
.invoke_handler(tauri::generate_handler![cli_matches])
.setup(|app, api| {
app.manage(Cli(api));
diff --git a/plugins/clipboard-manager/CHANGELOG.md b/plugins/clipboard-manager/CHANGELOG.md
index 46f2509a..895d8c71 100644
--- a/plugins/clipboard-manager/CHANGELOG.md
+++ b/plugins/clipboard-manager/CHANGELOG.md
@@ -1,5 +1,99 @@
# Changelog
+## \[2.2.2]
+
+### bug
+
+- [`d37bbdef`](https://github.com/tauri-apps/plugins-workspace/commit/d37bbdef8dc70e61e59f9fe0bb8b2a48999d0aa1) ([#2507](https://github.com/tauri-apps/plugins-workspace/pull/2507) by [@SquitchYT](https://github.com/tauri-apps/plugins-workspace/../../SquitchYT)) Fix clipboard-manager Wayland support.
+
+## \[2.2.1]
+
+- [`ce11079f`](https://github.com/tauri-apps/plugins-workspace/commit/ce11079f19852fbefdecf0e4c7d947af3624fee0) ([#2280](https://github.com/tauri-apps/plugins-workspace/pull/2280) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Explicitly drop `arboard::Clipboard` on exit. Add recommendation to not use read methods on the mainthread.
+
+## \[2.2.0]
+
+- [`3a79266b`](https://github.com/tauri-apps/plugins-workspace/commit/3a79266b8cf96a55b1ae6339d725567d45a44b1d) ([#2173](https://github.com/tauri-apps/plugins-workspace/pull/2173) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Bumped all plugins to `v2.2.0`. From now, the versions for the Rust and JavaScript packages of each plugin will be in sync with each other.
+
+## \[2.0.1]
+
+- [`3fa0fc09`](https://github.com/tauri-apps/plugins-workspace/commit/3fa0fc09bbee0d619801e5757af9fb3c09883c97) ([#2099](https://github.com/tauri-apps/plugins-workspace/pull/2099) by [@rasteiner](https://github.com/tauri-apps/plugins-workspace/../../rasteiner)) Fix clipboard manager client side api not copying fallback alternative text when calling `writeHtml`.
+
+## \[2.0.2]
+
+- [`d57df4de`](https://github.com/tauri-apps/plugins-workspace/commit/d57df4debe7c75cfbd6d6558fff1beb07dbee54c) ([#1986](https://github.com/tauri-apps/plugins-workspace/pull/1986) by [@RikaKagurasaka](https://github.com/tauri-apps/plugins-workspace/../../RikaKagurasaka)) Fix that `read_image` wrongly set the image rgba data with binary PNG data.
+
+## \[2.0.1]
+
+- [`a1a82208`](https://github.com/tauri-apps/plugins-workspace/commit/a1a82208ed4ab87f83310be0dc95428aec9ab241) ([#1873](https://github.com/tauri-apps/plugins-workspace/pull/1873) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Downgrade MSRV to 1.77.2 to support Windows 7.
+
+## \[2.0.0]
+
+- [`e2c4dfb6`](https://github.com/tauri-apps/plugins-workspace/commit/e2c4dfb6af43e5dd8d9ceba232c315f5febd55c1) Update to tauri v2 stable release.
+
+## \[2.0.0-rc.2]
+
+- [`341a5320`](https://github.com/tauri-apps/plugins-workspace/commit/341a5320c33d3c7b041abf7eb0ab7ad8009e6c3f) ([#1771](https://github.com/tauri-apps/plugins-workspace/pull/1771)) Fix warnings and clear implementation on Android below SDK 28.
+
+## \[2.0.0-rc.1]
+
+- [`e2e97db5`](https://github.com/tauri-apps/plugins-workspace/commit/e2e97db51983267f5be84d4f6f0278d58834d1f5) ([#1701](https://github.com/tauri-apps/plugins-workspace/pull/1701) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri 2.0.0-rc.8
+
+## \[2.0.0-rc.2]
+
+- [`b9147758`](https://github.com/tauri-apps/plugins-workspace/commit/b914775898c2bee7ceb20bd17ee595005cd17a64) ([#1679](https://github.com/tauri-apps/plugins-workspace/pull/1679) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Explicitly set a minimum macOS version for the Swift package.
+
+## \[2.0.0-rc.1]
+
+- [`2c00c029`](https://github.com/tauri-apps/plugins-workspace/commit/2c00c0292c9127b81567de46691e8c0f73557261) ([#1630](https://github.com/tauri-apps/plugins-workspace/pull/1630) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Fixed an issue that caused multi-word IIFE names to not be formatted correctly. For example the `barcode-scanner` was defined as `window.__TAURI_PLUGIN_CLIPBOARDMANAGER__` instead of `window.__TAURI_PLUGIN_CLIPBOARD_MANAGER__`.
+
+### changes
+
+- [`6b079cfd`](https://github.com/tauri-apps/plugins-workspace/commit/6b079cfdd107c94abc2c7300f6af00bac3ff4040) ([#1649](https://github.com/tauri-apps/plugins-workspace/pull/1649) by [@ahqsoftwares](https://github.com/tauri-apps/plugins-workspace/../../ahqsoftwares)) Remove targetSdk from build.kts files as it is deprecated and will be removed from DSL v9.0
+
+## \[2.0.0-rc.0]
+
+- [`9887d1`](https://github.com/tauri-apps/plugins-workspace/commit/9887d14bd0e971c4c0f5c1188fc4005d3fc2e29e) Update to tauri RC.
+
+## \[2.1.0-beta.6]
+
+- [`99d6ac0f`](https://github.com/tauri-apps/plugins-workspace/commit/99d6ac0f9506a6a4a1aa59c728157190a7441af6) ([#1606](https://github.com/tauri-apps/plugins-workspace/pull/1606) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) The JS packages now specify the *minimum* `@tauri-apps/api` version instead of a single exact version.
+- [`6de87966`](https://github.com/tauri-apps/plugins-workspace/commit/6de87966ecc00ad9d91c25be452f1f46bd2b7e1f) ([#1597](https://github.com/tauri-apps/plugins-workspace/pull/1597) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Update to tauri beta.25.
+
+## \[2.1.0-beta.5]
+
+- [`22a17980`](https://github.com/tauri-apps/plugins-workspace/commit/22a17980ff4f6f8c40adb1b8f4ffc6dae2fe7e30) ([#1537](https://github.com/tauri-apps/plugins-workspace/pull/1537) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Update to tauri beta.24.
+
+## \[2.1.0-beta.4]
+
+- [`76daee7a`](https://github.com/tauri-apps/plugins-workspace/commit/76daee7aafece34de3092c86e531cf9eb1138989) ([#1512](https://github.com/tauri-apps/plugins-workspace/pull/1512) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update to tauri beta.23.
+
+## \[2.1.0-beta.3]
+
+- [`9013854f`](https://github.com/tauri-apps/plugins-workspace/commit/9013854f42a49a230b9dbb9d02774765528a923f)([#1382](https://github.com/tauri-apps/plugins-workspace/pull/1382)) Update to tauri beta.22.
+
+## \[2.1.0-beta.2]
+
+- [`430bd6f4`](https://github.com/tauri-apps/plugins-workspace/commit/430bd6f4f379bee5d232ae6b098ae131db7f178a)([#1363](https://github.com/tauri-apps/plugins-workspace/pull/1363)) Update to tauri beta.20.
+
+## \[2.1.0-beta.1]
+
+- [`bd1ed590`](https://github.com/tauri-apps/plugins-workspace/commit/bd1ed5903ffcce5500310dac1e59e8c67674ef1e)([#1237](https://github.com/tauri-apps/plugins-workspace/pull/1237)) Update to tauri beta.17.
+
+## \[2.1.0-beta.1]
+
+- [`27b258c`](https://github.com/tauri-apps/plugins-workspace/commit/27b258cf31ae5557c99ae66537fb9196368d4d8b)([#1185](https://github.com/tauri-apps/plugins-workspace/pull/1185)) Expose `Clipboard` struct
+- [`e3d41f4`](https://github.com/tauri-apps/plugins-workspace/commit/e3d41f4011bd3ea3ce281bb38bbe31d3709f8e0f)([#1191](https://github.com/tauri-apps/plugins-workspace/pull/1191)) Internally use the webview scoped resources table instead of the app one, so other webviews can't access other webviews resources.
+- [`e3d41f4`](https://github.com/tauri-apps/plugins-workspace/commit/e3d41f4011bd3ea3ce281bb38bbe31d3709f8e0f)([#1191](https://github.com/tauri-apps/plugins-workspace/pull/1191)) Update for tauri 2.0.0-beta.15.
+
+## \[2.1.0-beta.0]
+
+- [`9dec960`](https://github.com/tauri-apps/plugins-workspace/commit/9dec9605ed1ce19dbef697e55debddf9008ecba1)([#845](https://github.com/tauri-apps/plugins-workspace/pull/845)) Add support for `read_image` and `write_image` to the clipboard plugin (desktop).
+
+## \[2.0.0-beta.2]
+
+- [`dc6d332`](https://github.com/tauri-apps/plugins-workspace/commit/dc6d3321e5305fa8b7250553bd179cbee995998a)([#977](https://github.com/tauri-apps/plugins-workspace/pull/977)) Add support for writing HTML content to the clipboard.
+- [`99bea25`](https://github.com/tauri-apps/plugins-workspace/commit/99bea2559c2c0648c2519c50a18cd124dacef57b)([#1005](https://github.com/tauri-apps/plugins-workspace/pull/1005)) Update to tauri beta.8.
+
## \[2.0.0-beta.1]
- [`569defb`](https://github.com/tauri-apps/plugins-workspace/commit/569defbe9492e38938554bb7bdc1be9151456d21) Update to tauri beta.4.
@@ -36,9 +130,3 @@
## \[2.0.0-alpha.0]
- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
- te to alpha.11.
-
-## \[2.0.0-alpha.0]
-
-- [`717ae67`](https://github.com/tauri-apps/plugins-workspace/commit/717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
-717ae670978feb4492fac1f295998b93f2b9347f)([#371](https://github.com/tauri-apps/plugins-workspace/pull/371)) First v2 alpha release!
diff --git a/plugins/clipboard-manager/Cargo.toml b/plugins/clipboard-manager/Cargo.toml
index cd032ac1..0c35e591 100644
--- a/plugins/clipboard-manager/Cargo.toml
+++ b/plugins/clipboard-manager/Cargo.toml
@@ -1,20 +1,29 @@
[package]
name = "tauri-plugin-clipboard-manager"
-version = "2.0.0-beta.1"
+version = "2.2.2"
description = "Read and write to the system clipboard."
edition = { workspace = true }
authors = { workspace = true }
license = { workspace = true }
rust-version = { workspace = true }
+repository = { workspace = true }
links = "tauri-plugin-clipboard-manager"
[package.metadata.docs.rs]
-rustc-args = [ "--cfg", "docsrs" ]
-rustdoc-args = [ "--cfg", "docsrs" ]
-targets = [ "x86_64-unknown-linux-gnu", "x86_64-linux-android" ]
+rustc-args = ["--cfg", "docsrs"]
+rustdoc-args = ["--cfg", "docsrs"]
+targets = ["x86_64-unknown-linux-gnu", "x86_64-linux-android"]
+
+[package.metadata.platforms.support]
+windows = { level = "full", notes = "" }
+linux = { level = "full", notes = "" }
+macos = { level = "full", notes = "" }
+android = { level = "partial", notes = "Only plain-text content support" }
+ios = { level = "partial", notes = "Only plain-text content support" }
+
[build-dependencies]
-tauri-plugin = { workspace = true, features = [ "build" ] }
+tauri-plugin = { workspace = true, features = ["build"] }
[dependencies]
serde = { workspace = true }
@@ -23,5 +32,8 @@ tauri = { workspace = true }
log = { workspace = true }
thiserror = { workspace = true }
+[target.'cfg(target_os = "ios")'.dependencies]
+tauri = { workspace = true, features = ["wry"] }
+
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\"))".dependencies]
-arboard = "3"
+arboard = { version = "3", features = ["wayland-data-control"] }
diff --git a/plugins/clipboard-manager/README.md b/plugins/clipboard-manager/README.md
index 02b26b3c..57b89526 100644
--- a/plugins/clipboard-manager/README.md
+++ b/plugins/clipboard-manager/README.md
@@ -2,9 +2,17 @@
Read and write to the system clipboard.
+| Platform | Supported |
+| -------- | --------- |
+| Linux | ✓ |
+| Windows | ✓ |
+| macOS | ✓ |
+| Android | ✓ |
+| iOS | ✓ |
+
## Install
-_This plugin requires a Rust version of at least **1.75**_
+_This plugin requires a Rust version of at least **1.77.2**_
There are three general methods of installation that we can recommend.
@@ -18,7 +26,7 @@ Install the Core plugin by adding the following to your `Cargo.toml` file:
```toml
[dependencies]
-tauri-plugin-clipboard-manager = "2.0.0-beta"
+tauri-plugin-clipboard-manager = "2.0.0"
# alternatively with Git:
tauri-plugin-clipboard-manager = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v2" }
```
@@ -46,7 +54,7 @@ yarn add https://github.com/tauri-apps/tauri-plugin-clipboard-manager#v2
First you need to register the core plugin with Tauri:
-`src-tauri/src/main.rs`
+`src-tauri/src/lib.rs`
```rust
fn main() {
@@ -60,9 +68,14 @@ fn main() {
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
```javascript
-import { writeText, readText } from "@tauri-apps/plugin-clipboard-manager";
-await writeText("Tauri is awesome!");
-assert(await readText(), "Tauri is awesome!");
+import {
+ writeText,
+ readText,
+ writeHtml,
+ clear
+} from '@tauri-apps/plugin-clipboard-manager'
+await writeText('Tauri is awesome!')
+assert(await readText(), 'Tauri is awesome!')
```
## Contributing
diff --git a/plugins/clipboard-manager/SECURITY.md b/plugins/clipboard-manager/SECURITY.md
new file mode 100644
index 00000000..4f09bbac
--- /dev/null
+++ b/plugins/clipboard-manager/SECURITY.md
@@ -0,0 +1,23 @@
+# Security Policy
+
+**Do not report security vulnerabilities through public GitHub issues.**
+
+**Please use the [Private Vulnerability Disclosure](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability#privately-reporting-a-security-vulnerability) feature of GitHub.**
+
+Include as much of the following information:
+
+- Type of issue (e.g. improper input parsing, privilege escalation, etc.)
+- The location of the affected source code (tag/branch/commit or direct URL)
+- Any special configuration required to reproduce the issue
+- The distribution affected or used to help us with reproduction of the issue
+- Step-by-step instructions to reproduce the issue
+- Ideally a reproduction repository
+- Impact of the issue, including how an attacker might exploit the issue
+
+We prefer to receive reports in English.
+
+## Contact
+
+Please disclose a vulnerability or security relevant issue here: [https://github.com/tauri-apps/plugins-workspace/security/advisories/new](https://github.com/tauri-apps/plugins-workspace/security/advisories/new).
+
+Alternatively, you can also contact us by email via [security@tauri.app](mailto:security@tauri.app).
diff --git a/plugins/clipboard-manager/android/build.gradle.kts b/plugins/clipboard-manager/android/build.gradle.kts
index b3caf13e..b12a7482 100644
--- a/plugins/clipboard-manager/android/build.gradle.kts
+++ b/plugins/clipboard-manager/android/build.gradle.kts
@@ -5,11 +5,10 @@ plugins {
android {
namespace = "app.tauri.clipboard"
- compileSdk = 32
+ compileSdk = 34
defaultConfig {
- minSdk = 24
- targetSdk = 32
+ minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
diff --git a/plugins/clipboard-manager/android/src/main/java/ClipboardPlugin.kt b/plugins/clipboard-manager/android/src/main/java/ClipboardPlugin.kt
index 432e337e..ebb931b4 100644
--- a/plugins/clipboard-manager/android/src/main/java/ClipboardPlugin.kt
+++ b/plugins/clipboard-manager/android/src/main/java/ClipboardPlugin.kt
@@ -4,12 +4,12 @@
package app.tauri.clipboard
-import android.R.attr.value
import android.app.Activity
import android.content.ClipData
import android.content.ClipDescription
import android.content.ClipboardManager
import android.content.Context
+import android.os.Build
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin
@@ -59,7 +59,9 @@ internal class ReadClipDataSerializer @JvmOverloads constructor(t: Class {}
+ else -> {
+ throw Exception("unimplemented ReadClipData")
+ }
}
jgen.writeEndObject()
@@ -87,17 +89,17 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
@Command
@Suppress("MoveVariableDeclarationIntoWhen")
- fun write(invoke: Invoke) {
+ fun writeText(invoke: Invoke) {
val args = invoke.parseArgs(WriteOptions::class.java)
val clipData = when (args) {
is WriteOptions.PlainText -> {
ClipData.newPlainText(args.label, args.text)
- }
- else -> {
- invoke.reject("unimplemented clip data")
+ } else -> {
+ invoke.reject("unimplemented WriteOptions")
return
}
+
}
manager.setPrimaryClip(clipData)
@@ -106,7 +108,7 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
}
@Command
- fun read(invoke: Invoke) {
+ fun readText(invoke: Invoke) {
val data = if (manager.hasPrimaryClip()) {
if (manager.primaryClipDescription?.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) == true) {
val item: ClipData.Item = manager.primaryClip!!.getItemAt(0)
@@ -125,4 +127,16 @@ class ClipboardPlugin(private val activity: Activity) : Plugin(activity) {
invoke.resolveObject(data)
}
+
+ @Command
+ fun clear(invoke: Invoke) {
+ if (manager.hasPrimaryClip()) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
+ manager.clearPrimaryClip()
+ } else {
+ manager.setPrimaryClip(ClipData.newPlainText("", ""))
+ }
+ }
+ invoke.resolve()
+ }
}
diff --git a/plugins/clipboard-manager/api-iife.js b/plugins/clipboard-manager/api-iife.js
new file mode 100644
index 00000000..f3e28be5
--- /dev/null
+++ b/plugins/clipboard-manager/api-iife.js
@@ -0,0 +1 @@
+if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARD_MANAGER__=function(e){"use strict";var n;async function t(e,n={},t){return window.__TAURI_INTERNALS__.invoke(e,n,t)}"function"==typeof SuppressedError&&SuppressedError;class r{get rid(){return function(e,n,t,r){if("function"==typeof n||!n.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?r:"a"===t?r.call(e):r?r.value:n.get(e)}(this,n,"f")}constructor(e){n.set(this,void 0),function(e,n,t){if("function"==typeof n||!n.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");n.set(e,t)}(this,n,e)}async close(){return t("plugin:resources|close",{rid:this.rid})}}n=new WeakMap;class a extends r{constructor(e){super(e)}static async new(e,n,r){return t("plugin:image|new",{rgba:i(e),width:n,height:r}).then((e=>new a(e)))}static async fromBytes(e){return t("plugin:image|from_bytes",{bytes:i(e)}).then((e=>new a(e)))}static async fromPath(e){return t("plugin:image|from_path",{path:e}).then((e=>new a(e)))}async rgba(){return t("plugin:image|rgba",{rid:this.rid}).then((e=>new Uint8Array(e)))}async size(){return t("plugin:image|size",{rid:this.rid})}}function i(e){return null==e?null:"string"==typeof e?e:e instanceof a?e.rid:e}return e.clear=async function(){await t("plugin:clipboard-manager|clear")},e.readImage=async function(){return await t("plugin:clipboard-manager|read_image").then((e=>new a(e)))},e.readText=async function(){return await t("plugin:clipboard-manager|read_text")},e.writeHtml=async function(e,n){await t("plugin:clipboard-manager|write_html",{html:e,altText:n})},e.writeImage=async function(e){await t("plugin:clipboard-manager|write_image",{image:i(e)})},e.writeText=async function(e,n){await t("plugin:clipboard-manager|write_text",{label:n?.label,text:e})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARD_MANAGER__})}
diff --git a/plugins/clipboard-manager/build.rs b/plugins/clipboard-manager/build.rs
index 758d64f3..9bbeddfc 100644
--- a/plugins/clipboard-manager/build.rs
+++ b/plugins/clipboard-manager/build.rs
@@ -2,18 +2,24 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-const COMMANDS: &[&str] = &["write", "read"];
+const COMMANDS: &[&str] = &[
+ "write_text",
+ "read_text",
+ "write_image",
+ "read_image",
+ "write_html",
+ "clear",
+];
fn main() {
- if let Err(error) = tauri_plugin::Builder::new(COMMANDS)
+ let result = tauri_plugin::Builder::new(COMMANDS)
+ .global_api_script_path("./api-iife.js")
.android_path("android")
.ios_path("ios")
- .try_build()
- {
- println!("{error:#}");
- // when building documentation for Android the plugin build result is irrelevant to the crate itself
- if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
- std::process::exit(1);
- }
+ .try_build();
+
+ // when building documentation for Android the plugin build result is always Err() and is irrelevant to the crate documentation build
+ if !(cfg!(docsrs) && std::env::var("TARGET").unwrap().contains("android")) {
+ result.unwrap();
}
}
diff --git a/plugins/clipboard-manager/guest-js/index.ts b/plugins/clipboard-manager/guest-js/index.ts
index 4a9d10a0..a37bbfab 100644
--- a/plugins/clipboard-manager/guest-js/index.ts
+++ b/plugins/clipboard-manager/guest-js/index.ts
@@ -8,9 +8,8 @@
* @module
*/
-import { invoke } from "@tauri-apps/api/core";
-
-type ClipResponse = Record<"plainText", { text: string }>;
+import { invoke } from '@tauri-apps/api/core'
+import { Image, transformImage } from '@tauri-apps/api/image'
/**
* Writes plain text to the clipboard.
@@ -27,16 +26,12 @@ type ClipResponse = Record<"plainText", { text: string }>;
*/
async function writeText(
text: string,
- opts?: { label?: string },
+ opts?: { label?: string }
): Promise {
- return invoke("plugin:clipboard-manager|write", {
- data: {
- plainText: {
- label: opts?.label,
- text,
- },
- },
- });
+ await invoke('plugin:clipboard-manager|write_text', {
+ label: opts?.label,
+ text
+ })
}
/**
@@ -49,8 +44,108 @@ async function writeText(
* @since 2.0.0
*/
async function readText(): Promise {
- const kind: ClipResponse = await invoke("plugin:clipboard-manager|read");
- return kind.plainText.text;
+ return await invoke('plugin:clipboard-manager|read_text')
+}
+
+/**
+ * Writes image buffer to the clipboard.
+ *
+ * #### Platform-specific
+ *
+ * - **Android / iOS:** Not supported.
+ *
+ * @example
+ * ```typescript
+ * import { writeImage } from '@tauri-apps/plugin-clipboard-manager';
+ * const buffer = [
+ * // A red pixel
+ * 255, 0, 0, 255,
+ *
+ * // A green pixel
+ * 0, 255, 0, 255,
+ * ];
+ * await writeImage(buffer);
+ * ```
+ *
+ * @returns A promise indicating the success or failure of the operation.
+ *
+ * @since 2.0.0
+ */
+async function writeImage(
+ image: string | Image | Uint8Array | ArrayBuffer | number[]
+): Promise {
+ await invoke('plugin:clipboard-manager|write_image', {
+ image: transformImage(image)
+ })
+}
+
+/**
+ * Gets the clipboard content as Uint8Array image.
+ *
+ * #### Platform-specific
+ *
+ * - **Android / iOS:** Not supported.
+ *
+ * @example
+ * ```typescript
+ * import { readImage } from '@tauri-apps/plugin-clipboard-manager';
+ *
+ * const clipboardImage = await readImage();
+ * const blob = new Blob([await clipboardImage.rgba()], { type: 'image' })
+ * const url = URL.createObjectURL(blob)
+ * ```
+ * @since 2.0.0
+ */
+async function readImage(): Promise {
+ return await invoke('plugin:clipboard-manager|read_image').then(
+ (rid) => new Image(rid)
+ )
+}
+
+/**
+ * * Writes HTML or fallbacks to write provided plain text to the clipboard.
+ *
+ * #### Platform-specific
+ *
+ * - **Android / iOS:** Not supported.
+ *
+ * @example
+ * ```typescript
+ * import { writeHtml } from '@tauri-apps/plugin-clipboard-manager';
+ * await writeHtml('
Tauri is awesome!
', 'plaintext');
+ * // The following will write "
Tauri is awesome
" as plain text
+ * await writeHtml('
Tauri is awesome!
', '
Tauri is awesome
');
+ * // we can read html data only as a string so there's just readText(), no readHtml()
+ * assert(await readText(), '
Tauri is awesome!
');
+ * ```
+ *
+ * @returns A promise indicating the success or failure of the operation.
+ *
+ * @since 2.0.0
+ */
+async function writeHtml(html: string, altText?: string): Promise {
+ await invoke('plugin:clipboard-manager|write_html', {
+ html,
+ altText
+ })
+}
+
+/**
+ * Clears the clipboard.
+ *
+ * #### Platform-specific
+ *
+ * - **Android:** Only supported on SDK 28+. For older releases we write an empty string to the clipboard instead.
+ *
+ * @example
+ * ```typescript
+ * import { clear } from '@tauri-apps/plugin-clipboard-manager';
+ * await clear();
+ * ```
+ * @since 2.0.0
+ */
+async function clear(): Promise {
+ await invoke('plugin:clipboard-manager|clear')
}
-export { writeText, readText };
+export { writeText, readText, writeHtml, clear, readImage, writeImage }
diff --git a/plugins/clipboard-manager/ios/Package.swift b/plugins/clipboard-manager/ios/Package.swift
index f6200857..6da5303e 100644
--- a/plugins/clipboard-manager/ios/Package.swift
+++ b/plugins/clipboard-manager/ios/Package.swift
@@ -6,28 +6,29 @@
import PackageDescription
let package = Package(
- name: "tauri-plugin-clipboard-manager",
- platforms: [
- .iOS(.v13),
- ],
- products: [
- // Products define the executables and libraries a package produces, and make them visible to other packages.
- .library(
- name: "tauri-plugin-clipboard-manager",
- type: .static,
- targets: ["tauri-plugin-clipboard-manager"]),
- ],
- dependencies: [
- .package(name: "Tauri", path: "../.tauri/tauri-api")
- ],
- targets: [
- // Targets are the basic building blocks of a package. A target can define a module or a test suite.
- // Targets can depend on other targets in this package, and on products in packages this package depends on.
- .target(
- name: "tauri-plugin-clipboard-manager",
- dependencies: [
- .byName(name: "Tauri")
- ],
- path: "Sources")
- ]
+ name: "tauri-plugin-clipboard-manager",
+ platforms: [
+ .macOS(.v10_13),
+ .iOS(.v13),
+ ],
+ products: [
+ // Products define the executables and libraries a package produces, and make them visible to other packages.
+ .library(
+ name: "tauri-plugin-clipboard-manager",
+ type: .static,
+ targets: ["tauri-plugin-clipboard-manager"])
+ ],
+ dependencies: [
+ .package(name: "Tauri", path: "../.tauri/tauri-api")
+ ],
+ targets: [
+ // Targets are the basic building blocks of a package. A target can define a module or a test suite.
+ // Targets can depend on other targets in this package, and on products in packages this package depends on.
+ .target(
+ name: "tauri-plugin-clipboard-manager",
+ dependencies: [
+ .byName(name: "Tauri")
+ ],
+ path: "Sources")
+ ]
)
diff --git a/plugins/clipboard-manager/ios/Sources/ClipboardPlugin.swift b/plugins/clipboard-manager/ios/Sources/ClipboardPlugin.swift
index 30729d53..cb4fc9b2 100644
--- a/plugins/clipboard-manager/ios/Sources/ClipboardPlugin.swift
+++ b/plugins/clipboard-manager/ios/Sources/ClipboardPlugin.swift
@@ -16,7 +16,7 @@ enum ReadClipData: Codable {
}
class ClipboardPlugin: Plugin {
- @objc public func write(_ invoke: Invoke) throws {
+ @objc public func writeText(_ invoke: Invoke) throws {
let options = try invoke.parseArgs(WriteOptions.self)
let clipboard = UIPasteboard.general
switch options {
@@ -30,7 +30,7 @@ class ClipboardPlugin: Plugin {
}
- @objc public func read(_ invoke: Invoke) throws {
+ @objc public func readText(_ invoke: Invoke) throws {
let clipboard = UIPasteboard.general
if let text = clipboard.string {
invoke.resolve(ReadClipData.plainText(text: text))
@@ -38,6 +38,12 @@ class ClipboardPlugin: Plugin {
invoke.reject("Clipboard is empty")
}
}
+
+ @objc public func clear(_ invoke: Invoke) throws {
+ let clipboard = UIPasteboard.general
+ clipboard.items = []
+ invoke.resolve()
+ }
}
@_cdecl("init_plugin_clipboard")
diff --git a/plugins/clipboard-manager/package.json b/plugins/clipboard-manager/package.json
index 038613cc..9b78843b 100644
--- a/plugins/clipboard-manager/package.json
+++ b/plugins/clipboard-manager/package.json
@@ -1,10 +1,11 @@
{
"name": "@tauri-apps/plugin-clipboard-manager",
- "version": "2.0.0-beta.1",
- "license": "MIT or APACHE-2.0",
+ "version": "2.2.2",
+ "license": "MIT OR Apache-2.0",
"authors": [
"Tauri Programme within The Commons Conservancy"
],
+ "repository": "https://github.com/tauri-apps/plugins-workspace",
"type": "module",
"types": "./dist-js/index.d.ts",
"main": "./dist-js/index.cjs",
@@ -23,6 +24,6 @@
"LICENSE"
],
"dependencies": {
- "@tauri-apps/api": "2.0.0-beta.2"
+ "@tauri-apps/api": "^2.0.0"
}
}
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/clear.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/clear.toml
new file mode 100644
index 00000000..83de1819
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/clear.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-clear"
+description = "Enables the clear command without any pre-configured scope."
+commands.allow = ["clear"]
+
+[[permission]]
+identifier = "deny-clear"
+description = "Denies the clear command without any pre-configured scope."
+commands.deny = ["clear"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/read.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/read.toml
deleted file mode 100644
index 20fa10c6..00000000
--- a/plugins/clipboard-manager/permissions/autogenerated/commands/read.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-read"
-description = "Enables the read command without any pre-configured scope."
-commands.allow = ["read"]
-
-[[permission]]
-identifier = "deny-read"
-description = "Denies the read command without any pre-configured scope."
-commands.deny = ["read"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/read_image.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/read_image.toml
new file mode 100644
index 00000000..cfed86db
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/read_image.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-read-image"
+description = "Enables the read_image command without any pre-configured scope."
+commands.allow = ["read_image"]
+
+[[permission]]
+identifier = "deny-read-image"
+description = "Denies the read_image command without any pre-configured scope."
+commands.deny = ["read_image"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/read_text.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/read_text.toml
new file mode 100644
index 00000000..29844892
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/read_text.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-read-text"
+description = "Enables the read_text command without any pre-configured scope."
+commands.allow = ["read_text"]
+
+[[permission]]
+identifier = "deny-read-text"
+description = "Denies the read_text command without any pre-configured scope."
+commands.deny = ["read_text"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/write.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/write.toml
deleted file mode 100644
index 73d1d387..00000000
--- a/plugins/clipboard-manager/permissions/autogenerated/commands/write.toml
+++ /dev/null
@@ -1,13 +0,0 @@
-# Automatically generated - DO NOT EDIT!
-
-"$schema" = "../../schemas/schema.json"
-
-[[permission]]
-identifier = "allow-write"
-description = "Enables the write command without any pre-configured scope."
-commands.allow = ["write"]
-
-[[permission]]
-identifier = "deny-write"
-description = "Denies the write command without any pre-configured scope."
-commands.deny = ["write"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/write_html.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/write_html.toml
new file mode 100644
index 00000000..5e292808
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/write_html.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-write-html"
+description = "Enables the write_html command without any pre-configured scope."
+commands.allow = ["write_html"]
+
+[[permission]]
+identifier = "deny-write-html"
+description = "Denies the write_html command without any pre-configured scope."
+commands.deny = ["write_html"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/write_image.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/write_image.toml
new file mode 100644
index 00000000..12e8e235
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/write_image.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-write-image"
+description = "Enables the write_image command without any pre-configured scope."
+commands.allow = ["write_image"]
+
+[[permission]]
+identifier = "deny-write-image"
+description = "Denies the write_image command without any pre-configured scope."
+commands.deny = ["write_image"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/commands/write_text.toml b/plugins/clipboard-manager/permissions/autogenerated/commands/write_text.toml
new file mode 100644
index 00000000..ebff875a
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/autogenerated/commands/write_text.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-write-text"
+description = "Enables the write_text command without any pre-configured scope."
+commands.allow = ["write_text"]
+
+[[permission]]
+identifier = "deny-write-text"
+description = "Denies the write_text command without any pre-configured scope."
+commands.deny = ["write_text"]
diff --git a/plugins/clipboard-manager/permissions/autogenerated/reference.md b/plugins/clipboard-manager/permissions/autogenerated/reference.md
index 02d3e533..f8bed009 100644
--- a/plugins/clipboard-manager/permissions/autogenerated/reference.md
+++ b/plugins/clipboard-manager/permissions/autogenerated/reference.md
@@ -1,18 +1,177 @@
-# Permissions
+## Default Permission
-## allow-read
+No features are enabled by default, as we believe
+the clipboard can be inherently dangerous and it is
+application specific if read and/or write access is needed.
-Enables the read command without any pre-configured scope.
+Clipboard interaction needs to be explicitly enabled.
-## deny-read
-Denies the read command without any pre-configured scope.
+#### This default permission set includes the following:
-## allow-write
-Enables the write command without any pre-configured scope.
+## Permission Table
-## deny-write
+
+
+
Identifier
+
Description
+
-Denies the write command without any pre-configured scope.
+
+
+
+`clipboard-manager:allow-clear`
+
+
+
+
+Enables the clear command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-clear`
+
+
+
+
+Denies the clear command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:allow-read-image`
+
+
+
+
+Enables the read_image command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-read-image`
+
+
+
+
+Denies the read_image command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:allow-read-text`
+
+
+
+
+Enables the read_text command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-read-text`
+
+
+
+
+Denies the read_text command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:allow-write-html`
+
+
+
+
+Enables the write_html command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-write-html`
+
+
+
+
+Denies the write_html command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:allow-write-image`
+
+
+
+
+Enables the write_image command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-write-image`
+
+
+
+
+Denies the write_image command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:allow-write-text`
+
+
+
+
+Enables the write_text command without any pre-configured scope.
+
+
+
+
+
+
+
+`clipboard-manager:deny-write-text`
+
+
+
+
+Denies the write_text command without any pre-configured scope.
+
+
+
+
diff --git a/plugins/clipboard-manager/permissions/default.toml b/plugins/clipboard-manager/permissions/default.toml
new file mode 100644
index 00000000..d6f65195
--- /dev/null
+++ b/plugins/clipboard-manager/permissions/default.toml
@@ -0,0 +1,11 @@
+"$schema" = "schemas/schema.json"
+[default]
+description = """
+No features are enabled by default, as we believe
+the clipboard can be inherently dangerous and it is
+application specific if read and/or write access is needed.
+
+Clipboard interaction needs to be explicitly enabled.
+"""
+
+permissions = []
diff --git a/plugins/clipboard-manager/permissions/schemas/schema.json b/plugins/clipboard-manager/permissions/schemas/schema.json
index 9691ab99..891c6f0d 100644
--- a/plugins/clipboard-manager/permissions/schemas/schema.json
+++ b/plugins/clipboard-manager/permissions/schemas/schema.json
@@ -17,7 +17,6 @@
},
"set": {
"description": "A list of permissions sets defined",
- "default": [],
"type": "array",
"items": {
"$ref": "#/definitions/PermissionSet"
@@ -50,7 +49,7 @@
"minimum": 1.0
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -112,7 +111,7 @@
"type": "string"
},
"description": {
- "description": "Human-readable description of what the permission does.",
+ "description": "Human-readable description of what the permission does. Tauri internal convention is to use `
` headings in markdown content for Tauri documentation generation purposes.",
"type": [
"string",
"null"
@@ -132,12 +131,21 @@
},
"scope": {
"description": "Allowed or denied scoped when using this permission.",
- "default": {},
"allOf": [
{
"$ref": "#/definitions/Scopes"
}
]
+ },
+ "platforms": {
+ "description": "Target platforms this permission applies. By default all platforms are affected by this permission.",
+ "type": [
+ "array",
+ "null"
+ ],
+ "items": {
+ "$ref": "#/definitions/Target"
+ }
}
}
},
@@ -164,7 +172,7 @@
}
},
"Scopes": {
- "description": "A restriction of the command/endpoint functionality.\n\nIt can be of any serde serializable type and is used for allowing or preventing certain actions inside a Tauri command.\n\nThe scope is passed to the command and handled/enforced by the command itself.",
+ "description": "An argument for fine grained behavior control of Tauri commands.\n\nIt can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.\n\n## Example\n\n```json { \"allow\": [{ \"path\": \"$HOME/**\" }], \"deny\": [{ \"path\": \"$HOME/secret.txt\" }] } ```",
"type": "object",
"properties": {
"allow": {
@@ -178,7 +186,7 @@
}
},
"deny": {
- "description": "Data that defines what is denied by the scope.",
+ "description": "Data that defines what is denied by the scope. This should be prioritized by validation logic.",
"type": [
"array",
"null"
@@ -243,36 +251,126 @@
}
]
},
- "PermissionKind": {
- "type": "string",
+ "Target": {
+ "description": "Platform target.",
"oneOf": [
{
- "description": "allow-read -> Enables the read command without any pre-configured scope.",
+ "description": "MacOS.",
"type": "string",
"enum": [
- "allow-read"
+ "macOS"
]
},
{
- "description": "deny-read -> Denies the read command without any pre-configured scope.",
+ "description": "Windows.",
"type": "string",
"enum": [
- "deny-read"
+ "windows"
]
},
{
- "description": "allow-write -> Enables the write command without any pre-configured scope.",
+ "description": "Linux.",
"type": "string",
"enum": [
- "allow-write"
+ "linux"
]
},
{
- "description": "deny-write -> Denies the write command without any pre-configured scope.",
+ "description": "Android.",
"type": "string",
"enum": [
- "deny-write"
+ "android"
]
+ },
+ {
+ "description": "iOS.",
+ "type": "string",
+ "enum": [
+ "iOS"
+ ]
+ }
+ ]
+ },
+ "PermissionKind": {
+ "type": "string",
+ "oneOf": [
+ {
+ "description": "Enables the clear command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-clear",
+ "markdownDescription": "Enables the clear command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the clear command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-clear",
+ "markdownDescription": "Denies the clear command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the read_image command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-read-image",
+ "markdownDescription": "Enables the read_image command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the read_image command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-read-image",
+ "markdownDescription": "Denies the read_image command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the read_text command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-read-text",
+ "markdownDescription": "Enables the read_text command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the read_text command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-read-text",
+ "markdownDescription": "Denies the read_text command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the write_html command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-write-html",
+ "markdownDescription": "Enables the write_html command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the write_html command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-write-html",
+ "markdownDescription": "Denies the write_html command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the write_image command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-write-image",
+ "markdownDescription": "Enables the write_image command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the write_image command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-write-image",
+ "markdownDescription": "Denies the write_image command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the write_text command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-write-text",
+ "markdownDescription": "Enables the write_text command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the write_text command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-write-text",
+ "markdownDescription": "Denies the write_text command without any pre-configured scope."
+ },
+ {
+ "description": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n",
+ "type": "string",
+ "const": "default",
+ "markdownDescription": "No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n"
}
]
}
diff --git a/plugins/clipboard-manager/rollup.config.js b/plugins/clipboard-manager/rollup.config.js
index 977dfac8..1f349ec8 100644
--- a/plugins/clipboard-manager/rollup.config.js
+++ b/plugins/clipboard-manager/rollup.config.js
@@ -2,6 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-import { createConfig } from "../../shared/rollup.config.js";
+import { createConfig } from '../../shared/rollup.config.js'
-export default createConfig();
+export default createConfig()
diff --git a/plugins/clipboard-manager/src/api-iife.js b/plugins/clipboard-manager/src/api-iife.js
deleted file mode 100644
index 8dc51655..00000000
--- a/plugins/clipboard-manager/src/api-iife.js
+++ /dev/null
@@ -1 +0,0 @@
-if("__TAURI__"in window){var __TAURI_PLUGIN_CLIPBOARDMANAGER__=function(e){"use strict";async function n(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}return"function"==typeof SuppressedError&&SuppressedError,e.readText=async function(){return(await n("plugin:clipboard-manager|read")).plainText.text},e.writeText=async function(e,r){return n("plugin:clipboard-manager|write",{data:{plainText:{label:r?.label,text:e}}})},e}({});Object.defineProperty(window.__TAURI__,"clipboardManager",{value:__TAURI_PLUGIN_CLIPBOARDMANAGER__})}
diff --git a/plugins/clipboard-manager/src/commands.rs b/plugins/clipboard-manager/src/commands.rs
index eec868a8..a8dd94ac 100644
--- a/plugins/clipboard-manager/src/commands.rs
+++ b/plugins/clipboard-manager/src/commands.rs
@@ -2,23 +2,79 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-use tauri::{command, AppHandle, Runtime, State};
+use tauri::{command, image::JsImage, AppHandle, Manager, ResourceId, Runtime, State, Webview};
-use crate::{ClipKind, Clipboard, ClipboardContents, Result};
+use crate::{Clipboard, Result};
#[command]
-pub(crate) async fn write(
+#[cfg(desktop)]
+pub(crate) async fn write_text(
_app: AppHandle,
clipboard: State<'_, Clipboard>,
- data: ClipKind,
+ text: &str,
+ #[allow(unused)] label: Option,
) -> Result<()> {
- clipboard.write(data)
+ clipboard.write_text(text)
}
#[command]
-pub(crate) async fn read(
+#[cfg(not(desktop))]
+pub(crate) async fn write_text(
_app: AppHandle,
clipboard: State<'_, Clipboard>,
-) -> Result {
- clipboard.read()
+ text: &str,
+ #[allow(unused)] label: Option<&str>,
+) -> Result<()> {
+ match label {
+ Some(label) => clipboard.write_text_with_label(text, label),
+ None => clipboard.write_text(text),
+ }
+}
+
+#[command]
+pub(crate) async fn read_text(
+ _app: AppHandle,
+ clipboard: State<'_, Clipboard>,
+) -> Result {
+ clipboard.read_text()
+}
+
+#[command]
+pub(crate) async fn write_image(
+ webview: Webview,
+ clipboard: State<'_, Clipboard>,
+ image: JsImage,
+) -> Result<()> {
+ let resources_table = webview.resources_table();
+ let image = image.into_img(&resources_table)?;
+ clipboard.write_image(&image)
+}
+
+#[command]
+pub(crate) async fn read_image(
+ webview: Webview,
+ clipboard: State<'_, Clipboard>,
+) -> Result {
+ let image = clipboard.read_image()?.to_owned();
+ let mut resources_table = webview.resources_table();
+ let rid = resources_table.add(image);
+ Ok(rid)
+}
+
+#[command]
+pub(crate) async fn write_html(
+ _app: AppHandle,
+ clipboard: State<'_, Clipboard>,
+ html: &str,
+ alt_text: Option<&str>,
+) -> Result<()> {
+ clipboard.write_html(html, alt_text)
+}
+
+#[command]
+pub(crate) async fn clear(
+ _app: AppHandle,
+ clipboard: State<'_, Clipboard>,
+) -> Result<()> {
+ clipboard.clear()
}
diff --git a/plugins/clipboard-manager/src/desktop.rs b/plugins/clipboard-manager/src/desktop.rs
index 555321dc..f3570cc0 100644
--- a/plugins/clipboard-manager/src/desktop.rs
+++ b/plugins/clipboard-manager/src/desktop.rs
@@ -2,12 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
+use arboard::ImageData;
use serde::de::DeserializeOwned;
-use tauri::{plugin::PluginApi, AppHandle, Runtime};
+use tauri::{image::Image, plugin::PluginApi, AppHandle, Runtime};
-use crate::models::*;
-
-use std::sync::Mutex;
+use std::{borrow::Cow, sync::Mutex};
pub fn init(
app: &AppHandle,
@@ -15,7 +14,7 @@ pub fn init(
) -> crate::Result> {
Ok(Clipboard {
app: app.clone(),
- clipboard: arboard::Clipboard::new().map(Mutex::new),
+ clipboard: arboard::Clipboard::new().map(|c| Mutex::new(Some(c))),
})
}
@@ -23,25 +22,102 @@ pub fn init(
pub struct Clipboard {
#[allow(dead_code)]
app: AppHandle,
- clipboard: Result, arboard::Error>,
+ // According to arboard docs the clipboard must be dropped before exit.
+ // Since tauri doesn't call drop on exit we'll use an Option to take() on RunEvent::Exit.
+ clipboard: Result>, arboard::Error>,
}
impl Clipboard {
- pub fn write(&self, kind: ClipKind) -> crate::Result<()> {
- let ClipKind::PlainText { text, .. } = kind;
+ pub fn write_text<'a, T: Into>>(&self, text: T) -> crate::Result<()> {
+ match &self.clipboard {
+ Ok(clipboard) => clipboard
+ .lock()
+ .unwrap()
+ .as_mut()
+ .unwrap()
+ .set_text(text)
+ .map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ }
+ }
+
+ pub fn write_image(&self, image: &Image<'_>) -> crate::Result<()> {
+ match &self.clipboard {
+ Ok(clipboard) => clipboard
+ .lock()
+ .unwrap()
+ .as_mut()
+ .unwrap()
+ .set_image(ImageData {
+ bytes: Cow::Borrowed(image.rgba()),
+ width: image.width() as usize,
+ height: image.height() as usize,
+ })
+ .map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ }
+ }
+
+ /// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
+ pub fn read_text(&self) -> crate::Result {
+ match &self.clipboard {
+ Ok(clipboard) => {
+ let text = clipboard.lock().unwrap().as_mut().unwrap().get_text()?;
+ Ok(text)
+ }
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ }
+ }
+
+ pub fn write_html<'a, T: Into>>(
+ &self,
+ html: T,
+ alt_text: Option,
+ ) -> crate::Result<()> {
match &self.clipboard {
- Ok(clipboard) => clipboard.lock().unwrap().set_text(text).map_err(Into::into),
+ Ok(clipboard) => clipboard
+ .lock()
+ .unwrap()
+ .as_mut()
+ .unwrap()
+ .set_html(html, alt_text)
+ .map_err(Into::into),
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
- pub fn read(&self) -> crate::Result {
+ pub fn clear(&self) -> crate::Result<()> {
+ match &self.clipboard {
+ Ok(clipboard) => clipboard
+ .lock()
+ .unwrap()
+ .as_mut()
+ .unwrap()
+ .clear()
+ .map_err(Into::into),
+ Err(e) => Err(crate::Error::Clipboard(e.to_string())),
+ }
+ }
+
+ /// Warning: This method should not be used on the main thread! Otherwise the underlying libraries may deadlock on Linux, freezing the whole app, when trying to copy data copied from this app, for example if the user copies text from the WebView.
+ pub fn read_image(&self) -> crate::Result> {
match &self.clipboard {
Ok(clipboard) => {
- let text = clipboard.lock().unwrap().get_text()?;
- Ok(ClipboardContents::PlainText { text })
+ let image = clipboard.lock().unwrap().as_mut().unwrap().get_image()?;
+ let image = Image::new_owned(
+ image.bytes.to_vec(),
+ image.width as u32,
+ image.height as u32,
+ );
+ Ok(image)
}
Err(e) => Err(crate::Error::Clipboard(e.to_string())),
}
}
+
+ pub(crate) fn cleanup(&self) {
+ if let Ok(clipboard) = &self.clipboard {
+ clipboard.lock().unwrap().take();
+ }
+ }
}
diff --git a/plugins/clipboard-manager/src/error.rs b/plugins/clipboard-manager/src/error.rs
index bf71802f..1b8cf482 100644
--- a/plugins/clipboard-manager/src/error.rs
+++ b/plugins/clipboard-manager/src/error.rs
@@ -11,9 +11,10 @@ pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
- #[cfg(desktop)]
#[error("{0}")]
Clipboard(String),
+ #[error(transparent)]
+ Tauri(#[from] tauri::Error),
}
impl Serialize for Error {
diff --git a/plugins/clipboard-manager/src/lib.rs b/plugins/clipboard-manager/src/lib.rs
index 2b7934ab..0cbb4e41 100644
--- a/plugins/clipboard-manager/src/lib.rs
+++ b/plugins/clipboard-manager/src/lib.rs
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
-//! [](https://github.com/tauri-apps/plugins-workspace/tree/v2/plugins/clipboard-manager)
-//!
//! Read and write to the system clipboard.
#![doc(
@@ -13,11 +11,9 @@
use tauri::{
plugin::{Builder, TauriPlugin},
- Manager, Runtime,
+ Manager, RunEvent, Runtime,
};
-pub use models::*;
-
#[cfg(desktop)]
mod desktop;
#[cfg(mobile)]
@@ -25,16 +21,15 @@ mod mobile;
mod commands;
mod error;
-mod models;
pub use error::{Error, Result};
#[cfg(desktop)]
-use desktop::Clipboard;
+pub use desktop::Clipboard;
#[cfg(mobile)]
-use mobile::Clipboard;
+pub use mobile::Clipboard;
-/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the clipboard APIs.
+/// Extensions to [`tauri::App`], [`tauri::AppHandle`], [`tauri::WebviewWindow`], [`tauri::Webview`] and [`tauri::Window`] to access the clipboard APIs.
pub trait ClipboardExt {
fn clipboard(&self) -> &Clipboard;
}
@@ -48,8 +43,14 @@ impl> crate::ClipboardExt for T {
/// Initializes the plugin.
pub fn init() -> TauriPlugin {
Builder::new("clipboard-manager")
- .js_init_script(include_str!("api-iife.js").to_string())
- .invoke_handler(tauri::generate_handler![commands::write, commands::read])
+ .invoke_handler(tauri::generate_handler![
+ commands::write_text,
+ commands::read_text,
+ commands::read_image,
+ commands::write_image,
+ commands::write_html,
+ commands::clear
+ ])
.setup(|app, api| {
#[cfg(mobile)]
let clipboard = mobile::init(app, api)?;
@@ -58,5 +59,11 @@ pub fn init() -> TauriPlugin {
app.manage(clipboard);
Ok(())
})
+ .on_event(|_app, _event| {
+ #[cfg(desktop)]
+ if let RunEvent::Exit = _event {
+ _app.clipboard().cleanup();
+ }
+ })
.build()
}
diff --git a/plugins/clipboard-manager/src/mobile.rs b/plugins/clipboard-manager/src/mobile.rs
index 07964711..72d5f6e0 100644
--- a/plugins/clipboard-manager/src/mobile.rs
+++ b/plugins/clipboard-manager/src/mobile.rs
@@ -3,12 +3,14 @@
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
+use serde::{Deserialize, Serialize};
use tauri::{
+ image::Image,
plugin::{PluginApi, PluginHandle},
AppHandle, Runtime,
};
-use crate::models::*;
+use std::borrow::Cow;
#[cfg(target_os = "android")]
const PLUGIN_IDENTIFIER: &str = "app.tauri.clipboard";
@@ -32,11 +34,76 @@ pub fn init(
pub struct Clipboard(PluginHandle);
impl Clipboard