mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-05-07 12:26:41 +02:00
Merge branch 'v2' into feature/fallback_targets
This commit is contained in:
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.5.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`764e8f77`](https://github.com/tauri-apps/plugins-workspace/commit/764e8f7719247da515243d9c9cafa6d087d21769) ([#2707](https://github.com/tauri-apps/plugins-workspace/pull/2707)) Added a new builder method app_name() to allow customizing the application name in the autostart entry.
|
||||
|
||||
## \[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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-autostart"
|
||||
version = "2.3.0"
|
||||
version = "2.5.0"
|
||||
description = "Automatically launch your application at startup."
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
@@ -59,7 +59,10 @@ First you need to register the core plugin with Tauri:
|
||||
```rust
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_autostart::Builder::new().args((["--flag1", "--flag2"])).build()))
|
||||
.plugin(tauri_plugin_autostart::Builder::new()
|
||||
.args(["--flag1", "--flag2"])
|
||||
.app_name("My Custom Name")
|
||||
.build())
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-autostart",
|
||||
"version": "2.3.0",
|
||||
"version": "2.5.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ starting the application on boot.
|
||||
It allows all to check, enable and
|
||||
disable the automatic start on boot.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-enable`
|
||||
|
||||
@@ -103,6 +103,7 @@ pub struct Builder {
|
||||
#[cfg(target_os = "macos")]
|
||||
macos_launcher: MacosLauncher,
|
||||
args: Vec<String>,
|
||||
app_name: Option<String>,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
@@ -154,12 +155,32 @@ impl Builder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the app name to be used for the auto start entry.
|
||||
///
|
||||
/// ## Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// Builder::new()
|
||||
/// .app_name("My Custom Name"))
|
||||
/// .build();
|
||||
/// ```
|
||||
pub fn app_name<S: Into<String>>(mut self, app_name: S) -> Self {
|
||||
self.app_name = Some(app_name.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build<R: Runtime>(self) -> TauriPlugin<R> {
|
||||
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);
|
||||
|
||||
let app_name = self
|
||||
.app_name
|
||||
.as_ref()
|
||||
.unwrap_or_else(|| &app.package_info().name);
|
||||
builder.set_app_name(app_name);
|
||||
|
||||
builder.set_args(&self.args);
|
||||
|
||||
let current_exe = current_exe()?;
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-barcode-scanner"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS"
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -1 +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__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_BARCODE_SCANNER__=function(n){"use strict";async function a(n,a={},e){return window.__TAURI_INTERNALS__.invoke(n,a,e)}var e;return"function"==typeof SuppressedError&&SuppressedError,n.Format=void 0,(e=n.Format||(n.Format={})).QRCode="QR_CODE",e.UPC_A="UPC_A",e.UPC_E="UPC_E",e.EAN8="EAN_8",e.EAN13="EAN_13",e.Code39="CODE_39",e.Code93="CODE_93",e.Code128="CODE_128",e.Codabar="CODABAR",e.ITF="ITF",e.Aztec="AZTEC",e.DataMatrix="DATA_MATRIX",e.PDF417="PDF_417",e.GS1DataBar="GS1_DATA_BAR",e.GS1DataBarLimited="GS1_DATA_BAR_LIMITED",e.GS1DataBarExpanded="GS1_DATA_BAR_EXPANDED",n.cancel=async function(){await a("plugin:barcode-scanner|cancel")},n.checkPermissions=async function(){return await async function(n){return a(`plugin:${n}|check_permissions`)}("barcode-scanner").then((n=>n.camera))},n.openAppSettings=async function(){await a("plugin:barcode-scanner|open_app_settings")},n.requestPermissions=async function(){return await async function(n){return a(`plugin:${n}|request_permissions`)}("barcode-scanner").then((n=>n.camera))},n.scan=async function(n){return await a("plugin:barcode-scanner|scan",{...n})},n}({});Object.defineProperty(window.__TAURI__,"barcodeScanner",{value:__TAURI_PLUGIN_BARCODE_SCANNER__})}
|
||||
|
||||
@@ -12,6 +12,9 @@ export type { PermissionState } from '@tauri-apps/api/core'
|
||||
|
||||
export enum Format {
|
||||
QRCode = 'QR_CODE',
|
||||
/**
|
||||
* Not supported on iOS.
|
||||
*/
|
||||
UPC_A = 'UPC_A',
|
||||
UPC_E = 'UPC_E',
|
||||
EAN8 = 'EAN_8',
|
||||
@@ -19,11 +22,26 @@ export enum Format {
|
||||
Code39 = 'CODE_39',
|
||||
Code93 = 'CODE_93',
|
||||
Code128 = 'CODE_128',
|
||||
/**
|
||||
* Not supported on iOS.
|
||||
*/
|
||||
Codabar = 'CODABAR',
|
||||
ITF = 'ITF',
|
||||
Aztec = 'AZTEC',
|
||||
DataMatrix = 'DATA_MATRIX',
|
||||
PDF417 = 'PDF_417'
|
||||
PDF417 = 'PDF_417',
|
||||
/**
|
||||
* Not supported on Android. Requires iOS 15.4+
|
||||
*/
|
||||
GS1DataBar = 'GS1_DATA_BAR',
|
||||
/**
|
||||
* Not supported on Android. Requires iOS 15.4+
|
||||
*/
|
||||
GS1DataBarLimited = 'GS1_DATA_BAR_LIMITED',
|
||||
/**
|
||||
* Not supported on Android. Requires iOS 15.4+
|
||||
*/
|
||||
GS1DataBarExpanded = 'GS1_DATA_BAR_EXPANDED'
|
||||
}
|
||||
|
||||
export interface ScanOptions {
|
||||
|
||||
@@ -27,8 +27,11 @@ enum SupportedFormat: String, CaseIterable, Decodable {
|
||||
case DATA_MATRIX
|
||||
case PDF_417
|
||||
case QR_CODE
|
||||
case GS1_DATA_BAR
|
||||
case GS1_DATA_BAR_LIMITED
|
||||
case GS1_DATA_BAR_EXPANDED
|
||||
|
||||
var value: AVMetadataObject.ObjectType {
|
||||
var value: AVMetadataObject.ObjectType? {
|
||||
switch self {
|
||||
case .UPC_E: return AVMetadataObject.ObjectType.upce
|
||||
case .EAN_8: return AVMetadataObject.ObjectType.ean8
|
||||
@@ -41,6 +44,24 @@ enum SupportedFormat: String, CaseIterable, Decodable {
|
||||
case .DATA_MATRIX: return AVMetadataObject.ObjectType.dataMatrix
|
||||
case .PDF_417: return AVMetadataObject.ObjectType.pdf417
|
||||
case .QR_CODE: return AVMetadataObject.ObjectType.qr
|
||||
case .GS1_DATA_BAR:
|
||||
if #available(iOS 15.4, *) {
|
||||
return AVMetadataObject.ObjectType.gs1DataBar
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case .GS1_DATA_BAR_LIMITED:
|
||||
if #available(iOS 15.4, *) {
|
||||
return AVMetadataObject.ObjectType.gs1DataBarLimited
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
case .GS1_DATA_BAR_EXPANDED:
|
||||
if #available(iOS 15.4, *) {
|
||||
return AVMetadataObject.ObjectType.gs1DataBarExpanded
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -242,13 +263,20 @@ class BarcodeScannerPlugin: Plugin, AVCaptureMetadataOutputObjectsDelegate {
|
||||
scanFormats = [AVMetadataObject.ObjectType]()
|
||||
|
||||
(args.formats ?? []).forEach { format in
|
||||
scanFormats.append(format.value)
|
||||
if let formatValue = format.value {
|
||||
scanFormats.append(formatValue)
|
||||
} else {
|
||||
invoke.reject("Unsupported barcode format on this iOS version: \(format)")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if scanFormats.count == 0 {
|
||||
for supportedFormat in SupportedFormat.allCases {
|
||||
scanFormats.append(supportedFormat.value)
|
||||
}
|
||||
if scanFormats.isEmpty {
|
||||
for supportedFormat in SupportedFormat.allCases {
|
||||
if let formatValue = supportedFormat.value {
|
||||
scanFormats.append(formatValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.metaOutput!.metadataObjectTypes = self.scanFormats
|
||||
|
||||
@@ -52,6 +52,15 @@ func discoverCaptureDevices() -> [AVCaptureDevice] {
|
||||
}
|
||||
|
||||
func formatStringFromMetadata(_ type: AVMetadataObject.ObjectType) -> String {
|
||||
if #available(iOS 15.4, *) {
|
||||
if type == .gs1DataBar {
|
||||
return "GS1_DATA_BAR"
|
||||
} else if type == .gs1DataBarLimited {
|
||||
return "GS1_DATA_BAR_LIMITED"
|
||||
} else if type == .gs1DataBarExpanded {
|
||||
return "GS1_DATA_BAR_EXPANDED"
|
||||
}
|
||||
}
|
||||
switch type {
|
||||
case AVMetadataObject.ObjectType.upce:
|
||||
return "UPC_E"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-barcode-scanner",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"description": "Scan QR codes, EAN-13 and other kinds of barcodes on Android and iOS",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ barcode scanning features are by default exposed.
|
||||
|
||||
It allows all barcode related features.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-cancel`
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-biometric"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Prompt the user for biometric authentication on Android and iOS."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-biometric",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ biometric features are by default exposed.
|
||||
|
||||
It allows acccess to all biometric commands.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-authenticate`
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f6e11282`](https://github.com/tauri-apps/plugins-workspace/commit/f6e11282a7f4036dd6d1dbb8f100e777e9e42f11) ([#2787](https://github.com/tauri-apps/plugins-workspace/pull/2787) by [@mikew](https://github.com/tauri-apps/plugins-workspace/../../mikew)) Added `Cli.matches_from(args)`. This can be combined with the `args` passed to the callback of `tauri_plugin_single_instance::init` to parse the command line arguments passed to subsequent instances of the application.
|
||||
- [`37c2fb41`](https://github.com/tauri-apps/plugins-workspace/commit/37c2fb41201160e85c8dc3ad40f462cd4e17a304) ([#2772](https://github.com/tauri-apps/plugins-workspace/pull/2772) by [@floriskn](https://github.com/tauri-apps/plugins-workspace/../../floriskn)) Added a new `global` boolean flag to the `CliArg` struct to support global CLI arguments. This flag allows arguments like `--verbose` to be marked as global and automatically propagated to all subcommands, enabling consistent availability throughout the CLI.
|
||||
|
||||
The new field is optional and defaults to false.
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-cli"
|
||||
version = "2.2.0"
|
||||
version = "2.4.0"
|
||||
description = "Parse arguments from your Tauri application's command line interface."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-cli",
|
||||
"version": "2.2.0",
|
||||
"version": "2.4.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,6 +114,12 @@ pub struct Arg {
|
||||
/// It does not define position in the argument list as a whole. When utilized with multiple=true,
|
||||
/// only the last positional argument may be defined as multiple (i.e. the one with the highest index).
|
||||
pub index: Option<usize>,
|
||||
/// Specifies whether the argument should be global.
|
||||
///
|
||||
/// Global arguments are propagated to all subcommands automatically,
|
||||
/// making them available throughout the CLI regardless of where they are defined.
|
||||
#[serde(default)]
|
||||
pub global: bool,
|
||||
}
|
||||
|
||||
/// describes a CLI configuration
|
||||
|
||||
@@ -29,7 +29,11 @@ pub struct Cli<R: Runtime>(PluginApi<R, Config>);
|
||||
|
||||
impl<R: Runtime> Cli<R> {
|
||||
pub fn matches(&self) -> Result<parser::Matches> {
|
||||
parser::get_matches(self.0.config(), self.0.app().package_info())
|
||||
parser::get_matches(self.0.config(), self.0.app().package_info(), None)
|
||||
}
|
||||
|
||||
pub fn matches_from(&self, args: Vec<String>) -> Result<parser::Matches> {
|
||||
parser::get_matches(self.0.config(), self.0.app().package_info(), Some(args))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::collections::HashMap;
|
||||
mod macros;
|
||||
|
||||
/// The resolution of a argument match.
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
#[derive(Default, Debug, Serialize, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub struct ArgData {
|
||||
/// - [`Value::Bool`] if it's a flag,
|
||||
@@ -33,7 +33,7 @@ pub struct ArgData {
|
||||
}
|
||||
|
||||
/// The matched subcommand.
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
#[derive(Default, Debug, Serialize, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub struct SubcommandMatches {
|
||||
/// The subcommand name.
|
||||
@@ -43,7 +43,7 @@ pub struct SubcommandMatches {
|
||||
}
|
||||
|
||||
/// The argument matches of a command.
|
||||
#[derive(Default, Debug, Serialize)]
|
||||
#[derive(Default, Debug, Serialize, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub struct Matches {
|
||||
/// Data structure mapping each found arg with its resolution.
|
||||
@@ -79,7 +79,11 @@ impl Matches {
|
||||
/// Ok(())
|
||||
/// });
|
||||
/// ```
|
||||
pub fn get_matches(cli: &Config, package_info: &PackageInfo) -> crate::Result<Matches> {
|
||||
pub fn get_matches(
|
||||
cli: &Config,
|
||||
package_info: &PackageInfo,
|
||||
args: Option<Vec<String>>,
|
||||
) -> crate::Result<Matches> {
|
||||
let about = cli
|
||||
.description()
|
||||
.unwrap_or(&package_info.description.to_string())
|
||||
@@ -92,7 +96,14 @@ pub fn get_matches(cli: &Config, package_info: &PackageInfo) -> crate::Result<Ma
|
||||
Some(&about),
|
||||
cli,
|
||||
);
|
||||
match app.try_get_matches() {
|
||||
|
||||
let matches = if let Some(args) = args {
|
||||
app.try_get_matches_from(args)
|
||||
} else {
|
||||
app.try_get_matches()
|
||||
};
|
||||
|
||||
match matches {
|
||||
Ok(matches) => Ok(get_matches_internal(cli, &matches)),
|
||||
Err(e) => match e.kind() {
|
||||
ErrorKind::DisplayHelp => {
|
||||
@@ -278,5 +289,7 @@ fn get_arg(arg_name: String, arg: &Arg) -> ClapArg {
|
||||
clap_arg = bind_value_arg!(arg, clap_arg, require_equals);
|
||||
clap_arg = bind_value_arg!(arg, clap_arg, index);
|
||||
|
||||
clap_arg = clap_arg.global(arg.global);
|
||||
|
||||
clap_arg
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.3]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
### bug
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-clipboard-manager"
|
||||
version = "2.2.2"
|
||||
version = "2.3.0"
|
||||
description = "Read and write to the system clipboard."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -1 +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__})}
|
||||
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?e!==n||!r:!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__})}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-clipboard-manager",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,6 @@ application specific if read and/or write access is needed.
|
||||
|
||||
Clipboard interaction needs to be explicitly enabled.
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
|
||||
## Permission Table
|
||||
|
||||
<table>
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`4d10acee`](https://github.com/tauri-apps/plugins-workspace/commit/4d10acee61bad8045705508121424ed5f2d381f6) ([#993](https://github.com/tauri-apps/plugins-workspace/pull/993) by [@m00nwtchr](https://github.com/tauri-apps/plugins-workspace/../../m00nwtchr)) Exposed Android's `path`, `pathPattern` and `pathSuffix` configurations.
|
||||
- [`4d10acee`](https://github.com/tauri-apps/plugins-workspace/commit/4d10acee61bad8045705508121424ed5f2d381f6) ([#993](https://github.com/tauri-apps/plugins-workspace/pull/993) by [@m00nwtchr](https://github.com/tauri-apps/plugins-workspace/../../m00nwtchr)) Added a `scheme` configuration to set a scheme other than http/https. This is only supported on Android and will still default to http,https if not set.
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
### bug
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-deep-link"
|
||||
version = "2.2.1"
|
||||
version = "2.4.0"
|
||||
description = "Set your Tauri application as the default handler for an URL"
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_DEEP_LINK__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var t;async function i(e,t,i){const a={kind:"Any"};return r("plugin:event|listen",{event:e,target:a,handler:n(t)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(t||(t={})),e.getCurrent=async function(){return await r("plugin:deep-link|get_current")},e.isRegistered=async function(e){return await r("plugin:deep-link|is_registered",{protocol:e})},e.onOpenUrl=async function(e){return await i("deep-link://new-url",(n=>{e(n.payload)}))},e.register=async function(e){return await r("plugin:deep-link|register",{protocol:e})},e.unregister=async function(e){return await r("plugin:deep-link|unregister",{protocol:e})},e}({});Object.defineProperty(window.__TAURI__,"deepLink",{value:__TAURI_PLUGIN_DEEP_LINK__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_DEEP_LINK__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var t;async function i(e,t,i){const _={kind:"Any"};return r("plugin:event|listen",{event:e,target:_,handler:n(t)}).then((n=>async()=>async function(e,n){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(e,n),await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(t||(t={})),e.getCurrent=async function(){return await r("plugin:deep-link|get_current")},e.isRegistered=async function(e){return await r("plugin:deep-link|is_registered",{protocol:e})},e.onOpenUrl=async function(e){return await i("deep-link://new-url",(n=>{e(n.payload)}))},e.register=async function(e){return await r("plugin:deep-link|register",{protocol:e})},e.unregister=async function(e){return await r("plugin:deep-link|unregister",{protocol:e})},e}({});Object.defineProperty(window.__TAURI__,"deepLink",{value:__TAURI_PLUGIN_DEEP_LINK__})}
|
||||
|
||||
@@ -9,25 +9,50 @@ use config::{AssociatedDomain, Config};
|
||||
const COMMANDS: &[&str] = &["get_current", "register", "unregister", "is_registered"];
|
||||
|
||||
// TODO: Consider using activity-alias in case users may have multiple activities in their app.
|
||||
// TODO: Do we want to support the other path* configs too?
|
||||
fn intent_filter(domain: &AssociatedDomain) -> String {
|
||||
format!(
|
||||
r#"<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="http" />
|
||||
<data android:scheme="https" />
|
||||
{}
|
||||
<data android:host="{}" />
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
{}
|
||||
</intent-filter>"#,
|
||||
domain
|
||||
.scheme
|
||||
.iter()
|
||||
.map(|scheme| format!(r#"<data android:scheme="{scheme}" />"#))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n "),
|
||||
domain.host,
|
||||
domain
|
||||
.path
|
||||
.iter()
|
||||
.map(|path| format!(r#"<data android:path="{path}" />"#))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n "),
|
||||
domain
|
||||
.path_pattern
|
||||
.iter()
|
||||
.map(|pattern| format!(r#"<data android:pathPattern="{pattern}" />"#))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n "),
|
||||
domain
|
||||
.path_prefix
|
||||
.iter()
|
||||
.map(|prefix| format!(r#"<data android:pathPrefix="{prefix}" />"#))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n ")
|
||||
.join("\n "),
|
||||
domain
|
||||
.path_suffix
|
||||
.iter()
|
||||
.map(|suffix| format!(r#"<data android:pathSuffix="{suffix}" />"#))
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n "),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.2.3]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `deep-link-js@2.4.0`
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `deep-link-js@2.3.0`
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "deep-link-example",
|
||||
"private": true,
|
||||
"version": "2.2.1",
|
||||
"version": "2.2.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
@@ -10,11 +10,11 @@
|
||||
"tauri": "tauri"
|
||||
},
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "2.4.1",
|
||||
"@tauri-apps/plugin-deep-link": "2.2.1"
|
||||
"@tauri-apps/api": "2.6.0",
|
||||
"@tauri-apps/plugin-deep-link": "2.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "2.4.1",
|
||||
"@tauri-apps/cli": "2.6.2",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.2.6"
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ tauri-build = { workspace = true }
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tauri = { workspace = true, features = ["wry", "compression"] }
|
||||
tauri = { workspace = true, features = ["wry", "common-controls-v6", "x11"] }
|
||||
tauri-plugin-deep-link = { path = "../../../" }
|
||||
tauri-plugin-log = { path = "../../../../log" }
|
||||
tauri-plugin-single-instance = { path = "../../../../single-instance", features = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-deep-link",
|
||||
"version": "2.2.1",
|
||||
"version": "2.4.0",
|
||||
"description": "Set your Tauri application as the default handler for an URL",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,25 @@ use tauri_utils::config::DeepLinkProtocol;
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
pub struct AssociatedDomain {
|
||||
#[serde(default = "default_schemes")]
|
||||
pub scheme: Vec<String>,
|
||||
|
||||
#[serde(deserialize_with = "deserialize_associated_host")]
|
||||
pub host: String,
|
||||
|
||||
#[serde(default)]
|
||||
pub path: Vec<String>,
|
||||
#[serde(default, alias = "path-pattern", rename = "pathPattern")]
|
||||
pub path_pattern: Vec<String>,
|
||||
#[serde(default, alias = "path-prefix", rename = "pathPrefix")]
|
||||
pub path_prefix: Vec<String>,
|
||||
#[serde(default, alias = "path-suffix", rename = "pathSuffix")]
|
||||
pub path_suffix: Vec<String>,
|
||||
}
|
||||
|
||||
// TODO: Consider removing this in v3
|
||||
fn default_schemes() -> Vec<String> {
|
||||
vec!["https".to_string(), "http".to_string()]
|
||||
}
|
||||
|
||||
fn deserialize_associated_host<'de, D>(deserializer: D) -> Result<String, D::Error>
|
||||
|
||||
@@ -114,8 +114,8 @@ mod imp {
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Windows / Linux**: This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
|
||||
/// Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
||||
/// Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
|
||||
/// Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
||||
/// Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
|
||||
pub fn get_current(&self) -> crate::Result<Option<Vec<url::Url>>> {
|
||||
self.plugin_handle
|
||||
.run_mobile_plugin::<GetCurrentResponse>("getCurrent", ())
|
||||
@@ -226,8 +226,8 @@ mod imp {
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Windows / Linux**: This function reads the command line arguments and checks if there's only one value, which must be an URL with scheme matching one of the configured values.
|
||||
/// Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
||||
/// Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
|
||||
/// Note that you must manually check the arguments when registering deep link schemes dynamically with [`Self::register`].
|
||||
/// Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.
|
||||
pub fn get_current(&self) -> crate::Result<Option<Vec<url::Url>>> {
|
||||
return Ok(self.current.lock().unwrap().clone());
|
||||
}
|
||||
@@ -350,7 +350,7 @@ mod imp {
|
||||
/// ## Platform-specific:
|
||||
///
|
||||
/// - **Windows**: Requires admin rights if the protocol is registered on local machine
|
||||
/// (this can happen when registered from the NSIS installer when the install mode is set to both or per machine)
|
||||
/// (this can happen when registered from the NSIS installer when the install mode is set to both or per machine)
|
||||
/// - **Linux**: Can only unregister the scheme if it was initially registered with [`register`](`Self::register`). May not work on older distros.
|
||||
/// - **macOS / Android / iOS**: Unsupported, will return [`Error::UnsupportedPlatform`](`crate::Error::UnsupportedPlatform`).
|
||||
pub fn unregister<S: AsRef<str>>(&self, _protocol: S) -> crate::Result<()> {
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `fs-js@2.4.0`
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `fs-js@2.3.0`
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
### Dependencies
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.2.1"
|
||||
version = "2.3.0"
|
||||
description = "Native system dialogs for opening and saving files along with message dialogs on your Tauri application."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -34,7 +34,7 @@ tauri = { workspace = true }
|
||||
log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
tauri-plugin-fs = { path = "../fs", version = "2.2.1" }
|
||||
tauri-plugin-fs = { path = "../fs", version = "2.4.0" }
|
||||
|
||||
[target.'cfg(target_os = "ios")'.dependencies]
|
||||
tauri = { workspace = true, features = ["wry"] }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-dialog",
|
||||
"version": "2.2.1",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@ available from the dialog plugin.
|
||||
|
||||
All dialog types are enabled.
|
||||
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-ask`
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`dac4d537`](https://github.com/tauri-apps/plugins-workspace/commit/dac4d53724bb3430a00a3f0119857cba32a031e8) ([#2613](https://github.com/tauri-apps/plugins-workspace/pull/2613) by [@Legend-Master](https://github.com/tauri-apps/plugins-workspace/../../Legend-Master)) Reduce the overhead of `watch` and `unwatch`
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
### bug
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.2.1"
|
||||
version = "2.4.0"
|
||||
description = "Access the file system."
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
@@ -35,7 +35,6 @@ tauri = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
url = { workspace = true }
|
||||
anyhow = "1"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
glob = { workspace = true }
|
||||
# TODO: Remove `serialization-compat-6` in v3
|
||||
notify = { version = "8", optional = true, features = [
|
||||
|
||||
@@ -68,9 +68,9 @@ fn main() {
|
||||
Afterwards all the plugin's APIs are available through the JavaScript guest bindings:
|
||||
|
||||
```javascript
|
||||
import { metadata } from '@tauri-apps/plugin-fs'
|
||||
import { stat } from '@tauri-apps/plugin-fs'
|
||||
|
||||
await metadata('/path/to/file')
|
||||
await stat('/path/to/file')
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -101,6 +101,7 @@ const COMMANDS: &[(&str, &[&str])] = &[
|
||||
("fstat", &[]),
|
||||
("exists", &[]),
|
||||
("watch", &[]),
|
||||
// TODO: Remove this in v3
|
||||
("unwatch", &[]),
|
||||
("size", &[]),
|
||||
];
|
||||
|
||||
@@ -1245,15 +1245,44 @@ type WatchEventKindRemove =
|
||||
| { kind: 'folder' }
|
||||
| { kind: 'other' }
|
||||
|
||||
// TODO: Remove this in v3, return `Watcher` instead
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
type UnwatchFn = () => void
|
||||
|
||||
async function unwatch(rid: number): Promise<void> {
|
||||
await invoke('plugin:fs|unwatch', { rid })
|
||||
class Watcher extends Resource {}
|
||||
|
||||
async function watchInternal(
|
||||
paths: string | string[] | URL | URL[],
|
||||
cb: (event: WatchEvent) => void,
|
||||
options: DebouncedWatchOptions
|
||||
): Promise<UnwatchFn> {
|
||||
const watchPaths = Array.isArray(paths) ? paths : [paths]
|
||||
|
||||
for (const path of watchPaths) {
|
||||
if (path instanceof URL && path.protocol !== 'file:') {
|
||||
throw new TypeError('Must be a file URL.')
|
||||
}
|
||||
}
|
||||
|
||||
const onEvent = new Channel<WatchEvent>()
|
||||
onEvent.onmessage = cb
|
||||
|
||||
const rid: number = await invoke('plugin:fs|watch', {
|
||||
paths: watchPaths.map((p) => (p instanceof URL ? p.toString() : p)),
|
||||
options,
|
||||
onEvent
|
||||
})
|
||||
|
||||
const watcher = new Watcher(rid)
|
||||
|
||||
return () => {
|
||||
void watcher.close()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return `Watcher` instead in v3
|
||||
/**
|
||||
* Watch changes (after a delay) on files or directories.
|
||||
*
|
||||
@@ -1264,34 +1293,13 @@ async function watch(
|
||||
cb: (event: WatchEvent) => void,
|
||||
options?: DebouncedWatchOptions
|
||||
): Promise<UnwatchFn> {
|
||||
const opts = {
|
||||
recursive: false,
|
||||
return await watchInternal(paths, cb, {
|
||||
delayMs: 2000,
|
||||
...options
|
||||
}
|
||||
|
||||
const watchPaths = Array.isArray(paths) ? paths : [paths]
|
||||
|
||||
for (const path of watchPaths) {
|
||||
if (path instanceof URL && path.protocol !== 'file:') {
|
||||
throw new TypeError('Must be a file URL.')
|
||||
}
|
||||
}
|
||||
|
||||
const onEvent = new Channel<WatchEvent>()
|
||||
onEvent.onmessage = cb
|
||||
|
||||
const rid: number = await invoke('plugin:fs|watch', {
|
||||
paths: watchPaths.map((p) => (p instanceof URL ? p.toString() : p)),
|
||||
options: opts,
|
||||
onEvent
|
||||
})
|
||||
|
||||
return () => {
|
||||
void unwatch(rid)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Return `Watcher` instead in v3
|
||||
/**
|
||||
* Watch changes on files or directories.
|
||||
*
|
||||
@@ -1302,32 +1310,10 @@ async function watchImmediate(
|
||||
cb: (event: WatchEvent) => void,
|
||||
options?: WatchOptions
|
||||
): Promise<UnwatchFn> {
|
||||
const opts = {
|
||||
recursive: false,
|
||||
return await watchInternal(paths, cb, {
|
||||
...options,
|
||||
delayMs: null
|
||||
}
|
||||
|
||||
const watchPaths = Array.isArray(paths) ? paths : [paths]
|
||||
|
||||
for (const path of watchPaths) {
|
||||
if (path instanceof URL && path.protocol !== 'file:') {
|
||||
throw new TypeError('Must be a file URL.')
|
||||
}
|
||||
}
|
||||
|
||||
const onEvent = new Channel<WatchEvent>()
|
||||
onEvent.onmessage = cb
|
||||
|
||||
const rid: number = await invoke('plugin:fs|watch', {
|
||||
paths: watchPaths.map((p) => (p instanceof URL ? p.toString() : p)),
|
||||
options: opts,
|
||||
onEvent
|
||||
delayMs: undefined
|
||||
})
|
||||
|
||||
return () => {
|
||||
void unwatch(rid)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-fs",
|
||||
"version": "2.2.1",
|
||||
"version": "2.4.0",
|
||||
"description": "Access the file system.",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ This default permission set prevents access to critical components
|
||||
of the Tauri application by default.
|
||||
On Windows the webview data folder access is denied.
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `create-app-specific-dirs`
|
||||
|
||||
@@ -150,11 +150,6 @@ pub fn open<R: Runtime>(
|
||||
Ok(rid)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn close<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> CommandResult<()> {
|
||||
webview.resources_table().close(rid).map_err(Into::into)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CopyFileOptions {
|
||||
|
||||
@@ -397,7 +397,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
|
||||
commands::create,
|
||||
commands::open,
|
||||
commands::copy_file,
|
||||
commands::close,
|
||||
commands::mkdir,
|
||||
commands::read_dir,
|
||||
commands::read,
|
||||
@@ -420,8 +419,6 @@ pub fn init<R: Runtime>() -> TauriPlugin<R, Option<config::Config>> {
|
||||
commands::size,
|
||||
#[cfg(feature = "watch")]
|
||||
watcher::watch,
|
||||
#[cfg(feature = "watch")]
|
||||
watcher::unwatch
|
||||
])
|
||||
.setup(|app, api| {
|
||||
let scope = Scope {
|
||||
|
||||
+43
-98
@@ -2,8 +2,8 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use notify::{Config, Event, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
use notify_debouncer_full::{new_debouncer, DebounceEventResult, Debouncer, RecommendedCache};
|
||||
use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher};
|
||||
use notify_debouncer_full::{new_debouncer, DebouncedEvent, Debouncer, RecommendedCache};
|
||||
use serde::Deserialize;
|
||||
use tauri::{
|
||||
ipc::{Channel, CommandScope, GlobalScope},
|
||||
@@ -11,15 +11,7 @@ use tauri::{
|
||||
Manager, Resource, ResourceId, Runtime, Webview,
|
||||
};
|
||||
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{
|
||||
mpsc::{channel, Receiver},
|
||||
Mutex,
|
||||
},
|
||||
thread::spawn,
|
||||
time::Duration,
|
||||
};
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::{
|
||||
commands::{resolve_path, CommandResult},
|
||||
@@ -27,79 +19,44 @@ use crate::{
|
||||
SafeFilePath,
|
||||
};
|
||||
|
||||
struct InnerWatcher {
|
||||
pub kind: WatcherKind,
|
||||
paths: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
pub struct WatcherResource(Mutex<InnerWatcher>);
|
||||
impl WatcherResource {
|
||||
fn new(kind: WatcherKind, paths: Vec<PathBuf>) -> Self {
|
||||
Self(Mutex::new(InnerWatcher { kind, paths }))
|
||||
}
|
||||
|
||||
fn with_lock<R, F: FnMut(&mut InnerWatcher) -> R>(&self, mut f: F) -> R {
|
||||
let mut watcher = self.0.lock().unwrap();
|
||||
f(&mut watcher)
|
||||
}
|
||||
}
|
||||
|
||||
impl Resource for WatcherResource {}
|
||||
|
||||
#[allow(unused)]
|
||||
enum WatcherKind {
|
||||
Debouncer(Debouncer<RecommendedWatcher, RecommendedCache>),
|
||||
Watcher(RecommendedWatcher),
|
||||
}
|
||||
|
||||
fn watch_raw(on_event: Channel<Event>, rx: Receiver<notify::Result<Event>>) {
|
||||
spawn(move || {
|
||||
while let Ok(event) = rx.recv() {
|
||||
if let Ok(event) = event {
|
||||
// TODO: Should errors be emitted too?
|
||||
let _ = on_event.send(event);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn watch_debounced(on_event: Channel<Event>, rx: Receiver<DebounceEventResult>) {
|
||||
spawn(move || {
|
||||
while let Ok(Ok(events)) = rx.recv() {
|
||||
for event in events {
|
||||
// TODO: Should errors be emitted too?
|
||||
let _ = on_event.send(event.event);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
impl Resource for WatcherKind {}
|
||||
|
||||
#[derive(Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct WatchOptions {
|
||||
base_dir: Option<BaseDirectory>,
|
||||
#[serde(default)]
|
||||
recursive: bool,
|
||||
delay_ms: Option<u64>,
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn watch<R: Runtime>(
|
||||
pub fn watch<R: Runtime>(
|
||||
webview: Webview<R>,
|
||||
paths: Vec<SafeFilePath>,
|
||||
options: WatchOptions,
|
||||
on_event: Channel<Event>,
|
||||
on_event: Channel<notify::Event>,
|
||||
global_scope: GlobalScope<Entry>,
|
||||
command_scope: CommandScope<Entry>,
|
||||
) -> CommandResult<ResourceId> {
|
||||
let mut resolved_paths = Vec::with_capacity(paths.capacity());
|
||||
for path in paths {
|
||||
resolved_paths.push(resolve_path(
|
||||
&webview,
|
||||
&global_scope,
|
||||
&command_scope,
|
||||
path,
|
||||
options.base_dir,
|
||||
)?);
|
||||
}
|
||||
let resolved_paths = paths
|
||||
.into_iter()
|
||||
.map(|path| {
|
||||
resolve_path(
|
||||
&webview,
|
||||
&global_scope,
|
||||
&command_scope,
|
||||
path,
|
||||
options.base_dir,
|
||||
)
|
||||
})
|
||||
.collect::<CommandResult<Vec<_>>>()?;
|
||||
|
||||
let recursive_mode = if options.recursive {
|
||||
RecursiveMode::Recursive
|
||||
@@ -107,52 +64,40 @@ pub async fn watch<R: Runtime>(
|
||||
RecursiveMode::NonRecursive
|
||||
};
|
||||
|
||||
let kind = if let Some(delay) = options.delay_ms {
|
||||
let (tx, rx) = channel();
|
||||
let mut debouncer = new_debouncer(Duration::from_millis(delay), None, tx)?;
|
||||
let watcher_kind = if let Some(delay) = options.delay_ms {
|
||||
let mut debouncer = new_debouncer(
|
||||
Duration::from_millis(delay),
|
||||
None,
|
||||
move |events: Result<Vec<DebouncedEvent>, Vec<notify::Error>>| {
|
||||
if let Ok(events) = events {
|
||||
for event in events {
|
||||
// TODO: Should errors be emitted too?
|
||||
let _ = on_event.send(event.event);
|
||||
}
|
||||
}
|
||||
},
|
||||
)?;
|
||||
for path in &resolved_paths {
|
||||
debouncer.watch(path, recursive_mode)?;
|
||||
}
|
||||
watch_debounced(on_event, rx);
|
||||
WatcherKind::Debouncer(debouncer)
|
||||
} else {
|
||||
let (tx, rx) = channel();
|
||||
let mut watcher = RecommendedWatcher::new(tx, Config::default())?;
|
||||
let mut watcher = RecommendedWatcher::new(
|
||||
move |event| {
|
||||
if let Ok(event) = event {
|
||||
// TODO: Should errors be emitted too?
|
||||
let _ = on_event.send(event);
|
||||
}
|
||||
},
|
||||
Config::default(),
|
||||
)?;
|
||||
for path in &resolved_paths {
|
||||
watcher.watch(path, recursive_mode)?;
|
||||
}
|
||||
watch_raw(on_event, rx);
|
||||
WatcherKind::Watcher(watcher)
|
||||
};
|
||||
|
||||
let rid = webview
|
||||
.resources_table()
|
||||
.add(WatcherResource::new(kind, resolved_paths));
|
||||
let rid = webview.resources_table().add(watcher_kind);
|
||||
|
||||
Ok(rid)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn unwatch<R: Runtime>(webview: Webview<R>, rid: ResourceId) -> CommandResult<()> {
|
||||
let watcher = webview.resources_table().take::<WatcherResource>(rid)?;
|
||||
WatcherResource::with_lock(&watcher, |watcher| {
|
||||
match &mut watcher.kind {
|
||||
WatcherKind::Debouncer(ref mut debouncer) => {
|
||||
for path in &watcher.paths {
|
||||
debouncer.unwatch(path).map_err(|e| {
|
||||
format!("failed to unwatch path: {} with error: {e}", path.display())
|
||||
})?;
|
||||
}
|
||||
}
|
||||
WatcherKind::Watcher(ref mut w) => {
|
||||
for path in &watcher.paths {
|
||||
w.unwatch(path).map_err(|e| {
|
||||
format!("failed to unwatch path: {} with error: {e}", path.display())
|
||||
})?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.5]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[2.2.4]
|
||||
|
||||
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tauri-plugin-geolocation"
|
||||
description = "Get and track the device's current position"
|
||||
version = "2.2.4"
|
||||
version = "2.3.0"
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
@@ -72,7 +72,7 @@ This plugin automatically adds the following permissions to your `AndroidManifes
|
||||
If your app requires GPS functionality to function, **you** should add the following to your `AndroidManifest.xml` file:
|
||||
|
||||
```xml
|
||||
<uses-feature android:name="android.hardware.gps" android:required="true" />
|
||||
<uses-feature android:name="android.hardware.location.gps" android:required="true" />
|
||||
```
|
||||
|
||||
The Google Play Store uses this property to decide whether it should show the app to devices without GPS capabilities.
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,e,i){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===e?i:"a"===e?i.call(t):i?i.value:n.get(t)}function e(t,n,e,i,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,e),e}var i,s,o;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,i.set(this,(()=>{})),s.set(this,0),o.set(this,[]),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((({message:t,id:r})=>{if(r==n(this,s,"f"))for(n(this,i,"f").call(this,t),e(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,i,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],e(this,s,n(this,s,"f")+1)}else n(this,o,"f")[r]=t}))}set onmessage(t){e(this,i,t)}get onmessage(){return n(this,i,"f")}[(i=new WeakMap,s=new WeakMap,o=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function c(t,n={},e){return window.__TAURI_INTERNALS__.invoke(t,n,e)}return t.checkPermissions=async function(){return await async function(t){return c(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await c("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await c("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await c("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const e=new a;return e.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await c("plugin:geolocation|watch_position",{options:t,channel:e}),e.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GEOLOCATION__=function(t){"use strict";function n(t,n,i,e){if("function"==typeof n?t!==n||!e:!n.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===i?e:"a"===i?e.call(t):e?e.value:n.get(t)}function i(t,n,i,e,s){if("function"==typeof n||!n.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(t,i),i}var e,s,o,a;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class c{constructor(t){e.set(this,void 0),s.set(this,0),o.set(this,[]),a.set(this,void 0),i(this,e,t||(()=>{})),this.id=function(t,n=!1){return window.__TAURI_INTERNALS__.transformCallback(t,n)}((t=>{const r=t.index;if("end"in t)return void(r==n(this,s,"f")?this.cleanupCallback():i(this,a,r));const c=t.message;if(r==n(this,s,"f")){for(n(this,e,"f").call(this,c),i(this,s,n(this,s,"f")+1);n(this,s,"f")in n(this,o,"f");){const t=n(this,o,"f")[n(this,s,"f")];n(this,e,"f").call(this,t),delete n(this,o,"f")[n(this,s,"f")],i(this,s,n(this,s,"f")+1)}n(this,s,"f")===n(this,a,"f")&&this.cleanupCallback()}else n(this,o,"f")[r]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(t){i(this,e,t)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,s=new WeakMap,o=new WeakMap,a=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}async function _(t,n={},i){return window.__TAURI_INTERNALS__.invoke(t,n,i)}return t.checkPermissions=async function(){return await async function(t){return _(`plugin:${t}|check_permissions`)}("geolocation")},t.clearWatch=async function(t){await _("plugin:geolocation|clear_watch",{channelId:t})},t.getCurrentPosition=async function(t){return await _("plugin:geolocation|get_current_position",{options:t})},t.requestPermissions=async function(t){return await _("plugin:geolocation|request_permissions",{permissions:t})},t.watchPosition=async function(t,n){const i=new c;return i.onmessage=t=>{"string"==typeof t?n(null,t):n(t)},await _("plugin:geolocation|watch_position",{options:t,channel:i}),i.id},t}({});Object.defineProperty(window.__TAURI__,"geolocation",{value:__TAURI_PLUGIN_GEOLOCATION__})}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-geolocation",
|
||||
"version": "2.2.4",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
## Permission Table
|
||||
|
||||
<table>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`494d1fea`](https://github.com/tauri-apps/plugins-workspace/commit/494d1fea137ffd60da98b25305c9d666df62cc63) ([#2684](https://github.com/tauri-apps/plugins-workspace/pull/2684) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated `global-hotkey` crate to `0.7` to fix a panic when trying to register a key combination which was already registered by another program. No API changes.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-global-shortcut"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Register global hotkeys listeners on your Tauri application."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -31,4 +31,4 @@ log = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
|
||||
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
|
||||
global-hotkey = { version = "0.6", features = ["serde"] }
|
||||
global-hotkey = { version = "0.7", features = ["serde"] }
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,r,s){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?s:"a"===r?s.call(t):s?s.value:e.get(t)}function r(t,e,r,s,i){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,r),r}var s,i,n;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class a{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,s.set(this,(()=>{})),i.set(this,0),n.set(this,[]),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((({message:t,id:o})=>{if(o==e(this,i,"f"))for(e(this,s,"f").call(this,t),r(this,i,e(this,i,"f")+1);e(this,i,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,i,"f")];e(this,s,"f").call(this,t),delete e(this,n,"f")[e(this,i,"f")],r(this,i,e(this,i,"f")+1)}else e(this,n,"f")[o]=t}))}set onmessage(t){r(this,s,t)}get onmessage(){return e(this,s,"f")}[(s=new WeakMap,i=new WeakMap,n=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function _(t,e={},r){return window.__TAURI_INTERNALS__.invoke(t,e,r)}return t.isRegistered=async function(t){return await _("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const r=new a;return r.onmessage=e,await _("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:r})},t.unregister=async function(t){return await _("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await _("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_GLOBAL_SHORTCUT__=function(t){"use strict";function e(t,e,s,i){if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(t):i?i.value:e.get(t)}function s(t,e,s,i,r){if("function"==typeof e||!e.has(t))throw new TypeError("Cannot write private member to an object whose class did not declare it");return e.set(t,s),s}var i,r,n,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class c{constructor(t){i.set(this,void 0),r.set(this,0),n.set(this,[]),a.set(this,void 0),s(this,i,t||(()=>{})),this.id=function(t,e=!1){return window.__TAURI_INTERNALS__.transformCallback(t,e)}((t=>{const o=t.index;if("end"in t)return void(o==e(this,r,"f")?this.cleanupCallback():s(this,a,o));const c=t.message;if(o==e(this,r,"f")){for(e(this,i,"f").call(this,c),s(this,r,e(this,r,"f")+1);e(this,r,"f")in e(this,n,"f");){const t=e(this,n,"f")[e(this,r,"f")];e(this,i,"f").call(this,t),delete e(this,n,"f")[e(this,r,"f")],s(this,r,e(this,r,"f")+1)}e(this,r,"f")===e(this,a,"f")&&this.cleanupCallback()}else e(this,n,"f")[o]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(t){s(this,i,t)}get onmessage(){return e(this,i,"f")}[(i=new WeakMap,r=new WeakMap,n=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function u(t,e={},s){return window.__TAURI_INTERNALS__.invoke(t,e,s)}return t.isRegistered=async function(t){return await u("plugin:global-shortcut|is_registered",{shortcut:t})},t.register=async function(t,e){const s=new c;return s.onmessage=e,await u("plugin:global-shortcut|register",{shortcuts:Array.isArray(t)?t:[t],handler:s})},t.unregister=async function(t){return await u("plugin:global-shortcut|unregister",{shortcuts:Array.isArray(t)?t:[t]})},t.unregisterAll=async function(){return await u("plugin:global-shortcut|unregister_all",{})},t}({});Object.defineProperty(window.__TAURI__,"globalShortcut",{value:__TAURI_PLUGIN_GLOBAL_SHORTCUT__})}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-global-shortcut",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,6 @@ the shortcuts can be inherently dangerous and it is
|
||||
application specific if specific shortcuts should be
|
||||
registered or unregistered.
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
|
||||
## Permission Table
|
||||
|
||||
<table>
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.5]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[2.2.4]
|
||||
|
||||
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[package]
|
||||
name = "tauri-plugin-haptics"
|
||||
description = "Haptic feedback and vibrations on Android and iOS"
|
||||
version = "2.2.4"
|
||||
version = "2.3.0"
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-haptics",
|
||||
"version": "2.2.4",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
## Permission Table
|
||||
|
||||
<table>
|
||||
|
||||
@@ -1,5 +1,21 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.5.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `fs-js@2.4.0`
|
||||
|
||||
## \[2.4.4]
|
||||
|
||||
- [`ff384cba`](https://github.com/tauri-apps/plugins-workspace/commit/ff384cbabe82ae715798a4ee49fd07ffcfbcdb5d) ([#2636](https://github.com/tauri-apps/plugins-workspace/pull/2636) by [@asomethings](https://github.com/tauri-apps/plugins-workspace/../../asomethings)) Properly handle responses with status code 204.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Upgraded to `fs-js@2.3.0`
|
||||
|
||||
## \[2.4.3]
|
||||
|
||||
- [`37c0477a`](https://github.com/tauri-apps/plugins-workspace/commit/37c0477afe926d326573f1827045875ce8bf8187) ([#2561](https://github.com/tauri-apps/plugins-workspace/pull/2561)) Add `zstd` cargo feature flag to enable `reqwest/zstd` flag.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.4.3"
|
||||
version = "2.5.0"
|
||||
description = "Access an HTTP client written in Rust."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -34,7 +34,7 @@ serde_json = { workspace = true }
|
||||
tauri = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
tokio = { version = "1", features = ["sync", "macros"] }
|
||||
tauri-plugin-fs = { path = "../fs", version = "2.2.1" }
|
||||
tauri-plugin-fs = { path = "../fs", version = "2.4.0" }
|
||||
urlpattern = "0.3"
|
||||
regex = "1"
|
||||
http = "1"
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function r(e,t,r,n,s){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,r),r}var n,s,a;"function"==typeof SuppressedError&&SuppressedError;const i="__TAURI_TO_IPC_KEY__";class o{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,n.set(this,(()=>{})),s.set(this,0),a.set(this,[]),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((({message:e,id:i})=>{if(i==t(this,s,"f"))for(t(this,n,"f").call(this,e),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,a,"f");){const e=t(this,a,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,a,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}else t(this,a,"f")[i]=e}))}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,a=new WeakMap,i)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[i]()}}async function c(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const d="Request cancelled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(d);const n=t?.maxRedirections,s=t?.connectTimeout,a=t?.proxy,i=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const h=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,f=new Request(e,t),_=await f.arrayBuffer(),u=0!==_.byteLength?Array.from(new Uint8Array(_)):null;for(const[e,t]of f.headers)h.get(e)||h.set(e,t);const l=(h instanceof Headers?Array.from(h.entries()):Array.isArray(h)?h:Object.entries(h)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(d);const w=await c("plugin:http|fetch",{clientConfig:{method:f.method,url:f.url,headers:l,data:u,maxRedirections:n,connectTimeout:s,proxy:a,danger:i}}),p=()=>c("plugin:http|fetch_cancel",{rid:w});if(r?.aborted)throw p(),new Error(d);r?.addEventListener("abort",(()=>{p()}));const{status:y,statusText:m,url:T,headers:g,rid:b}=await c("plugin:http|fetch_send",{rid:w}),A=new ReadableStream({start:e=>{const t=new o;t.onmessage=t=>{if(r?.aborted)return void e.error(d);const n=new Uint8Array(t),s=n[n.byteLength-1],a=n.slice(0,n.byteLength-1);1!=s?e.enqueue(a):e.close()},c("plugin:http|fetch_read_body",{rid:b,streamChannel:t}).catch((t=>{e.error(t)}))}}),R=new Response(A,{status:y,statusText:m});return Object.defineProperty(R,"url",{value:T}),Object.defineProperty(R,"headers",{value:new Headers(g)}),R},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_HTTP__=function(e){"use strict";function t(e,t,r,n){if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===r?n:"a"===r?n.call(e):n?n.value:t.get(e)}function r(e,t,r,n,s){if("function"==typeof t||!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return t.set(e,r),r}var n,s,i,a;"function"==typeof SuppressedError&&SuppressedError;const o="__TAURI_TO_IPC_KEY__";class c{constructor(e){n.set(this,void 0),s.set(this,0),i.set(this,[]),a.set(this,void 0),r(this,n,e||(()=>{})),this.id=function(e,t=!1){return window.__TAURI_INTERNALS__.transformCallback(e,t)}((e=>{const o=e.index;if("end"in e)return void(o==t(this,s,"f")?this.cleanupCallback():r(this,a,o));const c=e.message;if(o==t(this,s,"f")){for(t(this,n,"f").call(this,c),r(this,s,t(this,s,"f")+1);t(this,s,"f")in t(this,i,"f");){const e=t(this,i,"f")[t(this,s,"f")];t(this,n,"f").call(this,e),delete t(this,i,"f")[t(this,s,"f")],r(this,s,t(this,s,"f")+1)}t(this,s,"f")===t(this,a,"f")&&this.cleanupCallback()}else t(this,i,"f")[o]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(e){r(this,n,e)}get onmessage(){return t(this,n,"f")}[(n=new WeakMap,s=new WeakMap,i=new WeakMap,a=new WeakMap,o)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[o]()}}async function d(e,t={},r){return window.__TAURI_INTERNALS__.invoke(e,t,r)}const h="Request cancelled";return e.fetch=async function(e,t){const r=t?.signal;if(r?.aborted)throw new Error(h);const n=t?.maxRedirections,s=t?.connectTimeout,i=t?.proxy,a=t?.danger;t&&(delete t.maxRedirections,delete t.connectTimeout,delete t.proxy,delete t.danger);const o=t?.headers?t.headers instanceof Headers?t.headers:new Headers(t.headers):new Headers,f=new Request(e,t),l=await f.arrayBuffer(),u=0!==l.byteLength?Array.from(new Uint8Array(l)):null;for(const[e,t]of f.headers)o.get(e)||o.set(e,t);const _=(o instanceof Headers?Array.from(o.entries()):Array.isArray(o)?o:Object.entries(o)).map((([e,t])=>[e,"string"==typeof t?t:t.toString()]));if(r?.aborted)throw new Error(h);const w=await d("plugin:http|fetch",{clientConfig:{method:f.method,url:f.url,headers:_,data:u,maxRedirections:n,connectTimeout:s,proxy:i,danger:a}}),p=()=>d("plugin:http|fetch_cancel",{rid:w});if(r?.aborted)throw p(),new Error(h);r?.addEventListener("abort",(()=>{p()}));const{status:y,statusText:m,url:b,headers:T,rid:g}=await d("plugin:http|fetch_send",{rid:w}),A=[101,103,204,205,304].includes(y)?null:new ReadableStream({start:e=>{const t=new c;t.onmessage=t=>{if(r?.aborted)return void e.error(h);const n=new Uint8Array(t),s=n[n.byteLength-1],i=n.slice(0,n.byteLength-1);1!=s?e.enqueue(i):e.close()},d("plugin:http|fetch_read_body",{rid:g,streamChannel:t}).catch((t=>{e.error(t)}))}}),R=new Response(A,{status:y,statusText:m});return Object.defineProperty(R,"url",{value:b}),Object.defineProperty(R,"headers",{value:new Headers(T)}),R},e}({});Object.defineProperty(window.__TAURI__,"http",{value:__TAURI_PLUGIN_HTTP__})}
|
||||
|
||||
@@ -229,40 +229,44 @@ export async function fetch(
|
||||
rid
|
||||
})
|
||||
|
||||
const readableStreamBody = new ReadableStream({
|
||||
start: (controller) => {
|
||||
const streamChannel = new Channel<ArrayBuffer | number[]>()
|
||||
streamChannel.onmessage = (res: ArrayBuffer | number[]) => {
|
||||
// close early if aborted
|
||||
if (signal?.aborted) {
|
||||
controller.error(ERROR_REQUEST_CANCELLED)
|
||||
return
|
||||
// no body for 101, 103, 204, 205 and 304
|
||||
// see https://fetch.spec.whatwg.org/#null-body-status
|
||||
const body = [101, 103, 204, 205, 304].includes(status)
|
||||
? null
|
||||
: new ReadableStream({
|
||||
start: (controller) => {
|
||||
const streamChannel = new Channel<ArrayBuffer | number[]>()
|
||||
streamChannel.onmessage = (res: ArrayBuffer | number[]) => {
|
||||
// close early if aborted
|
||||
if (signal?.aborted) {
|
||||
controller.error(ERROR_REQUEST_CANCELLED)
|
||||
return
|
||||
}
|
||||
|
||||
const resUint8 = new Uint8Array(res)
|
||||
const lastByte = resUint8[resUint8.byteLength - 1]
|
||||
const actualRes = resUint8.slice(0, resUint8.byteLength - 1)
|
||||
|
||||
// close when the signal to close (last byte is 1) is sent from the IPC.
|
||||
if (lastByte == 1) {
|
||||
controller.close()
|
||||
return
|
||||
}
|
||||
|
||||
controller.enqueue(actualRes)
|
||||
}
|
||||
|
||||
// run a non-blocking body stream fetch
|
||||
invoke('plugin:http|fetch_read_body', {
|
||||
rid: responseRid,
|
||||
streamChannel
|
||||
}).catch((e) => {
|
||||
controller.error(e)
|
||||
})
|
||||
}
|
||||
|
||||
const resUint8 = new Uint8Array(res)
|
||||
const lastByte = resUint8[resUint8.byteLength - 1]
|
||||
const actualRes = resUint8.slice(0, resUint8.byteLength - 1)
|
||||
|
||||
// close when the signal to close (last byte is 1) is sent from the IPC.
|
||||
if (lastByte == 1) {
|
||||
controller.close()
|
||||
return
|
||||
}
|
||||
|
||||
controller.enqueue(actualRes)
|
||||
}
|
||||
|
||||
// run a non-blocking body stream fetch
|
||||
invoke('plugin:http|fetch_read_body', {
|
||||
rid: responseRid,
|
||||
streamChannel
|
||||
}).catch((e) => {
|
||||
controller.error(e)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const res = new Response(readableStreamBody, {
|
||||
const res = new Response(body, {
|
||||
status,
|
||||
statusText
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-http",
|
||||
"version": "2.4.3",
|
||||
"version": "2.5.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@ be manually configured before usage.
|
||||
|
||||
All fetch operations are enabled.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-fetch`
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-localhost"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Expose your apps assets through a localhost server instead of the default custom protocol."
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
|
||||
@@ -1,5 +1,29 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.6.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.5.1]
|
||||
|
||||
### bug
|
||||
|
||||
- [`9799f0db`](https://github.com/tauri-apps/plugins-workspace/commit/9799f0dbabea0b572a9b9111954fbf9aca63da71) ([#2802](https://github.com/tauri-apps/plugins-workspace/pull/2802) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fixes iOS simulator still freezing sometimes due to early logging.
|
||||
|
||||
## \[2.5.0]
|
||||
|
||||
- [`106e46ed`](https://github.com/tauri-apps/plugins-workspace/commit/106e46ed5125be33d0427cab9c5c066802f68791) ([#677](https://github.com/tauri-apps/plugins-workspace/pull/677)) Added the `KeepSome` rotation strategy. Like `KeepAll` it will rename files when the max file size is exceeded but will keep only the specified amount of files around.
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`c9b21f6f`](https://github.com/tauri-apps/plugins-workspace/commit/c9b21f6f4345806eff5f495885f20dea0082b7d7) ([#2625](https://github.com/tauri-apps/plugins-workspace/pull/2625) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Export the `LogLevel` type.
|
||||
- [`9629c2f4`](https://github.com/tauri-apps/plugins-workspace/commit/9629c2f4f90a56b5c2d265d1d13d3af40fc0c525) ([#2600](https://github.com/tauri-apps/plugins-workspace/pull/2600) by [@exoego](https://github.com/tauri-apps/plugins-workspace/../../exoego)) Adds a new varient `TargetKind::Dispatch` that allows you to construct arbitrary log targets
|
||||
- [`686a839c`](https://github.com/tauri-apps/plugins-workspace/commit/686a839c96fae1b0334f2df9dc76ca5cdbe00dbe) ([#2626](https://github.com/tauri-apps/plugins-workspace/pull/2626) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Fix iOS app stuck when using the iOS Simulator and the log plugin due to a deadlock when calling os_log too early.
|
||||
|
||||
### feat
|
||||
|
||||
- [`60fc35d3`](https://github.com/tauri-apps/plugins-workspace/commit/60fc35d35cccaf1654eceb4446ecf0f89dc15502) ([#2576](https://github.com/tauri-apps/plugins-workspace/pull/2576) by [@3lpsy](https://github.com/tauri-apps/plugins-workspace/../../3lpsy)) Add a `tracing` feature to the `log` plugin that emits log messages to the `tracing` system.
|
||||
|
||||
## \[2.3.1]
|
||||
|
||||
- [`1bb1ced5`](https://github.com/tauri-apps/plugins-workspace/commit/1bb1ced53820127204aa7adf57510c1cbce55e12) ([#2524](https://github.com/tauri-apps/plugins-workspace/pull/2524) by [@elwerene](https://github.com/tauri-apps/plugins-workspace/../../elwerene)) enable TargetKind::LogDir on mobile
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.3.1"
|
||||
version = "2.6.0"
|
||||
description = "Configurable logging for your Tauri app."
|
||||
authors = { workspace = true }
|
||||
license = { workspace = true }
|
||||
@@ -31,11 +31,15 @@ thiserror = { workspace = true }
|
||||
serde_repr = "0.1"
|
||||
byte-unit = "5"
|
||||
log = { workspace = true, features = ["kv_unstable"] }
|
||||
time = { version = "0.3", features = ["formatting", "local-offset", "macros"] }
|
||||
time = { version = "0.3", features = [
|
||||
"formatting",
|
||||
"local-offset",
|
||||
"macros",
|
||||
"parsing",
|
||||
] }
|
||||
fern = "0.7"
|
||||
tracing = { workspace = true, optional = true }
|
||||
|
||||
|
||||
[target."cfg(target_os = \"android\")".dependencies]
|
||||
android_logger = "0.15"
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,t;async function o(e,a,t){const o={kind:"Any"};return r("plugin:event|listen",{event:e,target:o,handler:n(a)}).then((n=>async()=>async function(e,n){await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const t=function(e){if(e){if(!e.startsWith("Error")){const n=e.split("\n").map((e=>e.split("@"))).filter((([e,n])=>e.length>0&&"[native code]"!==n));return n[2]?.filter((e=>e.length>0)).join("@")}{const n=e.split("\n"),r=n[3]?.trim();if(!r)return;const a=/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/,t=r.match(a);if(t){const{functionName:e,fileName:n,lineNumber:r,columnNumber:a}=t.groups;return`${e}@${n}:${r}:${a}`}{const e=/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/,n=r.match(e);if(n){const{fileName:e,lineNumber:r,columnNumber:a}=n.groups;return`<anonymous>@${e}:${r}:${a}`}}}}}((new Error).stack),{file:o,line:i,keyValues:u}=a??{};await r("plugin:log|log",{level:e,message:n,location:t,file:o,line:i,keyValues:u})}async function u(e){return await o("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),function(e){e[e.Trace=1]="Trace",e[e.Debug=2]="Debug",e[e.Info=3]="Info",e[e.Warn=4]="Warn",e[e.Error=5]="Error"}(t||(t={})),e.attachConsole=async function(){return await u((({level:e,message:n})=>{switch(e){case t.Trace:console.log(n);break;case t.Debug:console.debug(n);break;case t.Info:console.info(n);break;case t.Warn:console.warn(n);break;case t.Error:console.error(n);break;default:throw new Error(`unknown log level ${e}`)}}))},e.attachLogger=u,e.debug=async function(e,n){await i(t.Debug,e,n)},e.error=async function(e,n){await i(t.Error,e,n)},e.info=async function(e,n){await i(t.Info,e,n)},e.trace=async function(e,n){await i(t.Trace,e,n)},e.warn=async function(e,n){await i(t.Warn,e,n)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_LOG__=function(e){"use strict";function n(e,n=!1){return window.__TAURI_INTERNALS__.transformCallback(e,n)}async function r(e,n={},r){return window.__TAURI_INTERNALS__.invoke(e,n,r)}var a,t;async function o(e,a,t){const o={kind:"Any"};return r("plugin:event|listen",{event:e,target:o,handler:n(a)}).then((n=>async()=>async function(e,n){window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener(e,n),await r("plugin:event|unlisten",{event:e,eventId:n})}(e,n)))}async function i(e,n,a){const t=function(e){if(e){if(!e.startsWith("Error")){const n=e.split("\n").map((e=>e.split("@"))).filter((([e,n])=>e.length>0&&"[native code]"!==n));return n[2]?.filter((e=>e.length>0)).join("@")}{const n=e.split("\n"),r=n[3]?.trim();if(!r)return;const a=/at\s+(?<functionName>.*?)\s+\((?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)\)/,t=r.match(a);if(t){const{functionName:e,fileName:n,lineNumber:r,columnNumber:a}=t.groups;return`${e}@${n}:${r}:${a}`}{const e=/at\s+(?<fileName>.*?):(?<lineNumber>\d+):(?<columnNumber>\d+)/,n=r.match(e);if(n){const{fileName:e,lineNumber:r,columnNumber:a}=n.groups;return`<anonymous>@${e}:${r}:${a}`}}}}}((new Error).stack),{file:o,line:i,keyValues:u}=a??{};await r("plugin:log|log",{level:e,message:n,location:t,file:o,line:i,keyValues:u})}async function u(e){return await o("log://log",(n=>{const{level:r}=n.payload;let{message:a}=n.payload;a=a.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,""),e({message:a,level:r})}))}return"function"==typeof SuppressedError&&SuppressedError,function(e){e.WINDOW_RESIZED="tauri://resize",e.WINDOW_MOVED="tauri://move",e.WINDOW_CLOSE_REQUESTED="tauri://close-requested",e.WINDOW_DESTROYED="tauri://destroyed",e.WINDOW_FOCUS="tauri://focus",e.WINDOW_BLUR="tauri://blur",e.WINDOW_SCALE_FACTOR_CHANGED="tauri://scale-change",e.WINDOW_THEME_CHANGED="tauri://theme-changed",e.WINDOW_CREATED="tauri://window-created",e.WEBVIEW_CREATED="tauri://webview-created",e.DRAG_ENTER="tauri://drag-enter",e.DRAG_OVER="tauri://drag-over",e.DRAG_DROP="tauri://drag-drop",e.DRAG_LEAVE="tauri://drag-leave"}(a||(a={})),e.LogLevel=void 0,(t=e.LogLevel||(e.LogLevel={}))[t.Trace=1]="Trace",t[t.Debug=2]="Debug",t[t.Info=3]="Info",t[t.Warn=4]="Warn",t[t.Error=5]="Error",e.attachConsole=async function(){return await u((({level:n,message:r})=>{switch(n){case e.LogLevel.Trace:console.log(r);break;case e.LogLevel.Debug:console.debug(r);break;case e.LogLevel.Info:console.info(r);break;case e.LogLevel.Warn:console.warn(r);break;case e.LogLevel.Error:console.error(r);break;default:throw new Error(`unknown log level ${n}`)}}))},e.attachLogger=u,e.debug=async function(n,r){await i(e.LogLevel.Debug,n,r)},e.error=async function(n,r){await i(e.LogLevel.Error,n,r)},e.info=async function(n,r){await i(e.LogLevel.Info,n,r)},e.trace=async function(n,r){await i(e.LogLevel.Trace,n,r)},e.warn=async function(n,r){await i(e.LogLevel.Warn,n,r)},e}({});Object.defineProperty(window.__TAURI__,"log",{value:__TAURI_PLUGIN_LOG__})}
|
||||
|
||||
@@ -11,7 +11,7 @@ export interface LogOptions {
|
||||
keyValues?: Record<string, string | undefined>
|
||||
}
|
||||
|
||||
enum LogLevel {
|
||||
export enum LogLevel {
|
||||
/**
|
||||
* The "trace" level.
|
||||
*
|
||||
|
||||
@@ -2,16 +2,57 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import UIKit
|
||||
import Tauri
|
||||
import SwiftRs
|
||||
import Tauri
|
||||
import UIKit
|
||||
import os.log
|
||||
|
||||
#if targetEnvironment(simulator)
|
||||
var logReady = false
|
||||
#else
|
||||
var logReady = true
|
||||
#endif
|
||||
|
||||
var pendingLogs: [(Int, NSString)] = []
|
||||
var elapsedTime: TimeInterval = 0
|
||||
var logFlushScheduled = false
|
||||
|
||||
@_cdecl("tauri_log")
|
||||
func log(level: Int, message: NSString) {
|
||||
switch level {
|
||||
case 1: Logger.debug(message as String)
|
||||
case 2: Logger.info(message as String)
|
||||
case 3: Logger.error(message as String)
|
||||
default: break
|
||||
}
|
||||
if logReady {
|
||||
os_log(level, message)
|
||||
} else {
|
||||
pendingLogs.append((level, message))
|
||||
scheduleLogFlush()
|
||||
}
|
||||
}
|
||||
|
||||
// delay logging when the logger isn't immediately available
|
||||
// in some cases when using the simulator the app would hang when calling os_log too soon
|
||||
// better be safe here and wait a few seconds than actually freeze the app in dev mode
|
||||
// in production this isn't a problem
|
||||
func scheduleLogFlush() {
|
||||
guard !logFlushScheduled else { return }
|
||||
logFlushScheduled = true
|
||||
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
|
||||
logReady = true
|
||||
flushLogs()
|
||||
}
|
||||
}
|
||||
|
||||
func flushLogs() {
|
||||
for (level, message) in pendingLogs {
|
||||
os_log(level, message)
|
||||
}
|
||||
pendingLogs.removeAll()
|
||||
}
|
||||
|
||||
func os_log(_ level: Int, _ message: NSString) {
|
||||
switch level {
|
||||
case 1: Logger.debug(message as String)
|
||||
case 2: Logger.info(message as String)
|
||||
case 3: Logger.error(message as String)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-log",
|
||||
"version": "2.3.1",
|
||||
"version": "2.6.0",
|
||||
"description": "Configurable logging for your Tauri app.",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
+63
-21
@@ -47,6 +47,7 @@ const DEFAULT_LOG_TARGETS: [Target; 2] = [
|
||||
Target::new(TargetKind::Stdout),
|
||||
Target::new(TargetKind::LogDir { file_name: None }),
|
||||
];
|
||||
const LOG_DATE_FORMAT: &str = "[year]-[month]-[day]_[hour]-[minute]-[second]";
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
@@ -115,8 +116,12 @@ impl From<log::Level> for LogLevel {
|
||||
}
|
||||
|
||||
pub enum RotationStrategy {
|
||||
/// Will keep all the logs, renaming them to include the date.
|
||||
KeepAll,
|
||||
/// Will only keep the most recent log up to its maximal size.
|
||||
KeepOne,
|
||||
/// Will keep some of the most recent logs, renaming them to include the date.
|
||||
KeepSome(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -577,6 +582,34 @@ pub fn attach_logger(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rename_file_to_dated(
|
||||
path: &impl AsRef<Path>,
|
||||
dir: &impl AsRef<Path>,
|
||||
file_name: &str,
|
||||
timezone_strategy: &TimezoneStrategy,
|
||||
) -> Result<(), Error> {
|
||||
let to = dir.as_ref().join(format!(
|
||||
"{}_{}.log",
|
||||
file_name,
|
||||
timezone_strategy
|
||||
.get_now()
|
||||
.format(&time::format_description::parse(LOG_DATE_FORMAT).unwrap())
|
||||
.unwrap(),
|
||||
));
|
||||
if to.is_file() {
|
||||
// designated rotated log file name already exists
|
||||
// highly unlikely but defensively handle anyway by adding .bak to filename
|
||||
let mut to_bak = to.clone();
|
||||
to_bak.set_file_name(format!(
|
||||
"{}.bak",
|
||||
to_bak.file_name().unwrap().to_string_lossy()
|
||||
));
|
||||
fs::rename(&to, to_bak)?;
|
||||
}
|
||||
fs::rename(path, to)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_log_file_path(
|
||||
dir: &impl AsRef<Path>,
|
||||
file_name: &str,
|
||||
@@ -591,27 +624,37 @@ fn get_log_file_path(
|
||||
if log_size > max_file_size {
|
||||
match rotation_strategy {
|
||||
RotationStrategy::KeepAll => {
|
||||
let to = dir.as_ref().join(format!(
|
||||
"{}_{}.log",
|
||||
file_name,
|
||||
timezone_strategy.get_now().format(&format_description!(
|
||||
"[year]-[month]-[day]_[hour]-[minute]-[second]"
|
||||
))?,
|
||||
));
|
||||
if to.is_file() {
|
||||
// designated rotated log file name already exists
|
||||
// highly unlikely but defensively handle anyway by adding .bak to filename
|
||||
let mut to_bak = to.clone();
|
||||
to_bak.set_file_name(format!(
|
||||
"{}.bak",
|
||||
to_bak
|
||||
.file_name()
|
||||
.map(|f| f.to_string_lossy())
|
||||
.unwrap_or_default()
|
||||
));
|
||||
fs::rename(&to, to_bak)?;
|
||||
rename_file_to_dated(&path, dir, file_name, timezone_strategy)?;
|
||||
}
|
||||
RotationStrategy::KeepSome(how_many) => {
|
||||
let mut files = fs::read_dir(dir)?
|
||||
.filter_map(|entry| {
|
||||
let entry = entry.ok()?;
|
||||
let path = entry.path();
|
||||
let old_file_name = path.file_name()?.to_string_lossy().into_owned();
|
||||
if old_file_name.starts_with(file_name) {
|
||||
let date = old_file_name
|
||||
.strip_prefix(file_name)?
|
||||
.strip_prefix("_")?
|
||||
.strip_suffix(".log")?;
|
||||
Some((path, date.to_string()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
// Regular sorting, so the oldest files are first. Lexicographical
|
||||
// sorting is fine due to the date format.
|
||||
files.sort_by(|a, b| a.1.cmp(&b.1));
|
||||
// We want to make space for the file we will be soon renaming, AND
|
||||
// the file we will be creating. Thus we need to keep how_many - 2 files.
|
||||
if files.len() > (*how_many - 2) {
|
||||
files.truncate(files.len() + 2 - *how_many);
|
||||
for (old_log_path, _) in files {
|
||||
fs::remove_file(old_log_path)?;
|
||||
}
|
||||
}
|
||||
fs::rename(&path, to)?;
|
||||
rename_file_to_dated(&path, dir, file_name, timezone_strategy)?;
|
||||
}
|
||||
RotationStrategy::KeepOne => {
|
||||
fs::remove_file(&path)?;
|
||||
@@ -619,6 +662,5 @@ fn get_log_file_path(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.1]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[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.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-nfc"
|
||||
version = "2.2.0"
|
||||
version = "2.3.0"
|
||||
description = "Read and write NFC tags on Android and iOS."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-nfc",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -25,6 +25,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ Checking if the NFC functionality is available
|
||||
and scanning nearby tags is allowed.
|
||||
Writing to tags needs to be manually enabled.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-is-available`
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.2.3]
|
||||
|
||||
- [`f634e524`](https://github.com/tauri-apps/plugins-workspace/commit/f634e5248ebe428f8305a59f74c13fc15147fb8e) This is an "empty" release to update the plugins' source files on crates.io and docs.rs. This should fix docs.rs build failures for projects using tauri plugins as dependencies.
|
||||
|
||||
## \[2.2.2]
|
||||
|
||||
- [`a1b3fa27`](https://github.com/tauri-apps/plugins-workspace/commit/a1b3fa27f11022c9b6622b4fab12d93239eb05de) ([#2515](https://github.com/tauri-apps/plugins-workspace/pull/2515) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Re-exported the `Geolocation`, `Haptics`, `Notification`, and `Os` structs so that they show up on docs.rs.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-notification"
|
||||
version = "2.2.2"
|
||||
version = "2.3.0"
|
||||
description = "Send desktop and mobile notifications on your Tauri application."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
|
||||
@@ -1 +1 @@
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function n(i,n,t,e){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?e:"a"===t?e.call(i):e?e.value:n.get(i)}function t(i,n,t,e,o){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(i,t),t}var e,o,a;"function"==typeof SuppressedError&&SuppressedError;const r="__TAURI_TO_IPC_KEY__";class c{constructor(){this.__TAURI_CHANNEL_MARKER__=!0,e.set(this,(()=>{})),o.set(this,0),a.set(this,[]),this.id=function(i,n=!1){return window.__TAURI_INTERNALS__.transformCallback(i,n)}((({message:i,id:r})=>{if(r==n(this,o,"f"))for(n(this,e,"f").call(this,i),t(this,o,n(this,o,"f")+1);n(this,o,"f")in n(this,a,"f");){const i=n(this,a,"f")[n(this,o,"f")];n(this,e,"f").call(this,i),delete n(this,a,"f")[n(this,o,"f")],t(this,o,n(this,o,"f")+1)}else n(this,a,"f")[r]=i}))}set onmessage(i){t(this,e,i)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,o=new WeakMap,a=new WeakMap,r)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[r]()}}class s{constructor(i,n,t){this.plugin=i,this.event=n,this.channelId=t}async unregister(){return u(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function l(i,n,t){const e=new c;return e.onmessage=t,u(`plugin:${i}|registerListener`,{event:n,handler:e}).then((()=>new s(i,n,e.id)))}async function u(i,n={},t){return window.__TAURI_INTERNALS__.invoke(i,n,t)}var f,h,d;i.ScheduleEvery=void 0,(f=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",f.Month="month",f.TwoWeeks="twoWeeks",f.Week="week",f.Day="day",f.Hour="hour",f.Minute="minute",f.Second="second";return i.Importance=void 0,(h=i.Importance||(i.Importance={}))[h.None=0]="None",h[h.Min=1]="Min",h[h.Low=2]="Low",h[h.Default=3]="Default",h[h.High=4]="High",i.Visibility=void 0,(d=i.Visibility||(i.Visibility={}))[d.Secret=-1]="Secret",d[d.Private=0]="Private",d[d.Public=1]="Public",i.Schedule=class{static at(i,n=!1,t=!1){return{at:{date:i,repeating:n,allowWhileIdle:t},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,t=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:t}}}},i.active=async function(){return await u("plugin:notification|get_active")},i.cancel=async function(i){await u("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await u("plugin:notification|cancel")},i.channels=async function(){return await u("plugin:notification|listChannels")},i.createChannel=async function(i){await u("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await u("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await l("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await l("notification","notification",i)},i.pending=async function(){return await u("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await u("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await u("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await u("plugin:notification|remove_active")},i.removeChannel=async function(i){await u("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
|
||||
if("__TAURI__"in window){var __TAURI_PLUGIN_NOTIFICATION__=function(i){"use strict";function n(i,n,t,e){if("function"==typeof n?i!==n||!e:!n.has(i))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===t?e:"a"===t?e.call(i):e?e.value:n.get(i)}function t(i,n,t,e,a){if("function"==typeof n||!n.has(i))throw new TypeError("Cannot write private member to an object whose class did not declare it");return n.set(i,t),t}var e,a,o,r;"function"==typeof SuppressedError&&SuppressedError;const s="__TAURI_TO_IPC_KEY__";class c{constructor(i){e.set(this,void 0),a.set(this,0),o.set(this,[]),r.set(this,void 0),t(this,e,i||(()=>{})),this.id=function(i,n=!1){return window.__TAURI_INTERNALS__.transformCallback(i,n)}((i=>{const s=i.index;if("end"in i)return void(s==n(this,a,"f")?this.cleanupCallback():t(this,r,s));const c=i.message;if(s==n(this,a,"f")){for(n(this,e,"f").call(this,c),t(this,a,n(this,a,"f")+1);n(this,a,"f")in n(this,o,"f");){const i=n(this,o,"f")[n(this,a,"f")];n(this,e,"f").call(this,i),delete n(this,o,"f")[n(this,a,"f")],t(this,a,n(this,a,"f")+1)}n(this,a,"f")===n(this,r,"f")&&this.cleanupCallback()}else n(this,o,"f")[s]=c}))}cleanupCallback(){window.__TAURI_INTERNALS__.unregisterCallback(this.id)}set onmessage(i){t(this,e,i)}get onmessage(){return n(this,e,"f")}[(e=new WeakMap,a=new WeakMap,o=new WeakMap,r=new WeakMap,s)](){return`__CHANNEL__:${this.id}`}toJSON(){return this[s]()}}class l{constructor(i,n,t){this.plugin=i,this.event=n,this.channelId=t}async unregister(){return f(`plugin:${this.plugin}|remove_listener`,{event:this.event,channelId:this.channelId})}}async function u(i,n,t){const e=new c(t);return f(`plugin:${i}|registerListener`,{event:n,handler:e}).then((()=>new l(i,n,e.id)))}async function f(i,n={},t){return window.__TAURI_INTERNALS__.invoke(i,n,t)}var h,d,w;i.ScheduleEvery=void 0,(h=i.ScheduleEvery||(i.ScheduleEvery={})).Year="year",h.Month="month",h.TwoWeeks="twoWeeks",h.Week="week",h.Day="day",h.Hour="hour",h.Minute="minute",h.Second="second";return i.Importance=void 0,(d=i.Importance||(i.Importance={}))[d.None=0]="None",d[d.Min=1]="Min",d[d.Low=2]="Low",d[d.Default=3]="Default",d[d.High=4]="High",i.Visibility=void 0,(w=i.Visibility||(i.Visibility={}))[w.Secret=-1]="Secret",w[w.Private=0]="Private",w[w.Public=1]="Public",i.Schedule=class{static at(i,n=!1,t=!1){return{at:{date:i,repeating:n,allowWhileIdle:t},interval:void 0,every:void 0}}static interval(i,n=!1){return{at:void 0,interval:{interval:i,allowWhileIdle:n},every:void 0}}static every(i,n,t=!1){return{at:void 0,interval:void 0,every:{interval:i,count:n,allowWhileIdle:t}}}},i.active=async function(){return await f("plugin:notification|get_active")},i.cancel=async function(i){await f("plugin:notification|cancel",{notifications:i})},i.cancelAll=async function(){await f("plugin:notification|cancel")},i.channels=async function(){return await f("plugin:notification|listChannels")},i.createChannel=async function(i){await f("plugin:notification|create_channel",{...i})},i.isPermissionGranted=async function(){return"default"!==window.Notification.permission?await Promise.resolve("granted"===window.Notification.permission):await f("plugin:notification|is_permission_granted")},i.onAction=async function(i){return await u("notification","actionPerformed",i)},i.onNotificationReceived=async function(i){return await u("notification","notification",i)},i.pending=async function(){return await f("plugin:notification|get_pending")},i.registerActionTypes=async function(i){await f("plugin:notification|register_action_types",{types:i})},i.removeActive=async function(i){await f("plugin:notification|remove_active",{notifications:i})},i.removeAllActive=async function(){await f("plugin:notification|remove_active")},i.removeChannel=async function(i){await f("plugin:notification|delete_channel",{id:i})},i.requestPermission=async function(){return await window.Notification.requestPermission()},i.sendNotification=function(i){"string"==typeof i?new window.Notification(i):new window.Notification(i.title,i)},i}({});Object.defineProperty(window.__TAURI__,"notification",{value:__TAURI_PLUGIN_NOTIFICATION__})}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@tauri-apps/plugin-notification",
|
||||
"version": "2.2.2",
|
||||
"version": "2.3.0",
|
||||
"license": "MIT OR Apache-2.0",
|
||||
"authors": [
|
||||
"Tauri Programme within The Commons Conservancy"
|
||||
@@ -24,6 +24,6 @@
|
||||
"LICENSE"
|
||||
],
|
||||
"dependencies": {
|
||||
"@tauri-apps/api": "^2.0.0"
|
||||
"@tauri-apps/api": "^2.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ notification features are by default exposed.
|
||||
|
||||
It allows all notification related features.
|
||||
|
||||
|
||||
|
||||
#### This default permission set includes the following:
|
||||
|
||||
- `allow-is-permission-granted`
|
||||
|
||||
@@ -1,5 +1,24 @@
|
||||
# Changelog
|
||||
|
||||
## \[2.4.0]
|
||||
|
||||
- [`f209b2f2`](https://github.com/tauri-apps/plugins-workspace/commit/f209b2f23cb29133c97ad5961fb46ef794dbe063) ([#2804](https://github.com/tauri-apps/plugins-workspace/pull/2804) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Updated tauri to 2.6
|
||||
|
||||
## \[2.3.1]
|
||||
|
||||
### feat
|
||||
|
||||
- [`2aec8ff4`](https://github.com/tauri-apps/plugins-workspace/commit/2aec8ff4c41d178ea9804f7b6eff343c726be015) ([#2803](https://github.com/tauri-apps/plugins-workspace/pull/2803) by [@lucasfernog](https://github.com/tauri-apps/plugins-workspace/../../lucasfernog)) Add `inAppBrowser` option to open URLs in an in-app browser on Android and iOS.
|
||||
|
||||
## \[2.3.0]
|
||||
|
||||
- [`ce9888a2`](https://github.com/tauri-apps/plugins-workspace/commit/ce9888a2d4c9b449bd2a306f0fa6c76507fd46d3) ([#2762](https://github.com/tauri-apps/plugins-workspace/pull/2762)) Similar to the `fs` plugin the `opener` plugin now supports a `requireLiteralLeadingDot` configuration in `tauri.conf.json`.
|
||||
|
||||
## \[2.2.7]
|
||||
|
||||
- [`6c9e08dc`](https://github.com/tauri-apps/plugins-workspace/commit/6c9e08dccb3ac99fccfce586fa2b69717ba81b52) ([#2695](https://github.com/tauri-apps/plugins-workspace/pull/2695) by [@ShaunSHamilton](https://github.com/tauri-apps/plugins-workspace/../../ShaunSHamilton)) Adjust `open_url` url type to allow `URL`
|
||||
- [`dde6f3c3`](https://github.com/tauri-apps/plugins-workspace/commit/dde6f3c31c1b79942abb556be31757dc583f509e) ([#2549](https://github.com/tauri-apps/plugins-workspace/pull/2549) by [@renovate](https://github.com/tauri-apps/plugins-workspace/../../renovate)) Update `windows` crate to 0.61 to align with Tauri 2.5
|
||||
|
||||
## \[2.2.6]
|
||||
|
||||
- [`1a984659`](https://github.com/tauri-apps/plugins-workspace/commit/1a9846599b6a71faf330845847a30f6bf9735898) ([#2469](https://github.com/tauri-apps/plugins-workspace/pull/2469) by [@FabianLars](https://github.com/tauri-apps/plugins-workspace/../../FabianLars)) Update `objc2` crate to 0.6. No user facing changes.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tauri-plugin-opener"
|
||||
version = "2.2.6"
|
||||
version = "2.4.0"
|
||||
description = "Open files and URLs using their default application."
|
||||
edition = { workspace = true }
|
||||
authors = { workspace = true }
|
||||
@@ -40,7 +40,7 @@ glob = { workspace = true }
|
||||
dunce = { workspace = true }
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = "0.60"
|
||||
version = "0.61"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_UI_Shell_Common",
|
||||
|
||||
@@ -35,5 +35,6 @@ android {
|
||||
dependencies {
|
||||
implementation("androidx.core:core-ktx:1.9.0")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.15.3")
|
||||
implementation("androidx.browser:browser:1.8.0")
|
||||
implementation(project(":tauri-android"))
|
||||
}
|
||||
|
||||
@@ -6,22 +6,36 @@ package app.tauri.opener
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import app.tauri.annotation.Command
|
||||
import app.tauri.annotation.TauriPlugin
|
||||
import app.tauri.plugin.Invoke
|
||||
import app.tauri.plugin.Plugin
|
||||
import java.io.File
|
||||
import androidx.core.net.toUri
|
||||
import app.tauri.annotation.InvokeArg
|
||||
|
||||
@InvokeArg
|
||||
class OpenArgs {
|
||||
lateinit var url: String
|
||||
var with: String? = null
|
||||
}
|
||||
|
||||
@TauriPlugin
|
||||
class OpenerPlugin(private val activity: Activity) : Plugin(activity) {
|
||||
@Command
|
||||
fun open(invoke: Invoke) {
|
||||
try {
|
||||
val url = invoke.parseArgs(String::class.java)
|
||||
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activity.applicationContext?.startActivity(intent)
|
||||
val args = invoke.parseArgs(OpenArgs::class.java)
|
||||
|
||||
if (args.with == "inAppBrowser") {
|
||||
val builder = CustomTabsIntent.Builder()
|
||||
val intent = builder.build()
|
||||
intent.launchUrl(activity, args.url.toUri())
|
||||
} else {
|
||||
val intent = Intent(Intent.ACTION_VIEW, args.url.toUri())
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activity.applicationContext?.startActivity(intent)
|
||||
}
|
||||
invoke.resolve()
|
||||
} catch (ex: Exception) {
|
||||
invoke.reject(ex.message)
|
||||
|
||||
@@ -35,10 +35,15 @@ import { invoke } from '@tauri-apps/api/core'
|
||||
*
|
||||
* @param url The URL to open.
|
||||
* @param openWith The app to open the URL with. If not specified, defaults to the system default application for the specified url type.
|
||||
* On mobile, `openWith` can be provided as `inAppBrowser` to open the URL in an in-app browser. Otherwise, it will open the URL in the system default browser.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
export async function openUrl(url: string, openWith?: string): Promise<void> {
|
||||
export async function openUrl(
|
||||
url: string | URL,
|
||||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
||||
openWith?: 'inAppBrowser' | string
|
||||
): Promise<void> {
|
||||
await invoke('plugin:opener|open_url', {
|
||||
url,
|
||||
with: openWith
|
||||
|
||||
@@ -3,21 +3,35 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import Foundation
|
||||
import SafariServices
|
||||
import SwiftRs
|
||||
import Tauri
|
||||
import UIKit
|
||||
import WebKit
|
||||
|
||||
struct OpenArgs: Decodable {
|
||||
let url: String
|
||||
let with: String?
|
||||
}
|
||||
|
||||
class OpenerPlugin: Plugin {
|
||||
@objc public func open(_ invoke: Invoke) throws {
|
||||
do {
|
||||
let urlString = try invoke.parseArgs(String.self)
|
||||
if let url = URL(string: urlString) {
|
||||
if #available(iOS 10, *) {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
let args = try invoke.parseArgs(OpenArgs.self)
|
||||
if let url = URL(string: args.url) {
|
||||
if args.with == "inAppBrowser" {
|
||||
DispatchQueue.main.async {
|
||||
let safariVC = SFSafariViewController(url: url)
|
||||
self.manager.viewController?.present(safariVC, animated: true)
|
||||
}
|
||||
} else {
|
||||
UIApplication.shared.openURL(url)
|
||||
if #available(iOS 10, *) {
|
||||
UIApplication.shared.open(url, options: [:])
|
||||
} else {
|
||||
UIApplication.shared.openURL(url)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
invoke.resolve()
|
||||
} catch {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user