snapshot of https://github.com/tauri-apps/tauri.git (dev, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Audit / audit-js (push) Failing after 0s
bench / bench (map[os:ubuntu-latest runner:xvfb-run --auto-servernum target:x86_64-unknown-linux-gnu], nightly) (push) Failing after 0s
covector version or publish / run-integration-tests (ubuntu-latest) (push) Failing after 0s
Audit / audit-rust (push) Failing after 0s
test `@tauri-apps/cli` / test (ubuntu-latest) (push) Failing after 0s
test `tauri-cli` / test (map[os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:ubuntu-latest target:x86_64-unknown-linux-gnu toolchain:1.90]) (push) Failing after 0s
test core / test (map[args:--no-default-features key:no-default], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
deploy schema worker / deploy (push) Failing after 0s
lint rust / clippy (map[cargo:cargo include: os:ubuntu-latest target:x86_64-unknown-linux-gnu]) (push) Failing after 0s
lint rust / clippy (map[cargo:cross include:--package api os:ubuntu-latest target:aarch64-linux-android]) (push) Failing after 0s
supply chain health status / check rust dependencies with cargo vet (push) Failing after 0s
test `@tauri-apps/api` e2e (mobile) / android (push) Failing after 0s
test `@tauri-apps/api` e2e / test (map[name:Linux os:ubuntu-latest]) (push) Failing after 0s
test core / test (map[args:--all-features key:all], map[cargo:cross command:build os:ubuntu-latest target:aarch64-linux-android toolchain:1.90]) (push) Failing after 0s
Udeps / changes (push) Failing after 0s
Udeps / setup (push) Has been skipped
Udeps / udeps (push) Has been skipped
bench / bench (map[os:macos-latest runner: target:aarch64-apple-darwin], nightly) (push) Has been cancelled
bench / bench (map[os:windows-latest runner: target:x86_64-pc-windows-msvc], nightly) (push) Has been cancelled
covector version or publish / run-integration-tests (macos-latest) (push) Has been cancelled
covector version or publish / run-integration-tests (windows-latest) (push) Has been cancelled
covector version or publish / version-or-publish (push) Has been cancelled
test `@tauri-apps/cli` / test (macos-latest) (push) Has been cancelled
test `tauri-cli` / test (map[args:--no-default-features --features native-tls-vendored os:windows-latest restore-only:true target:aarch64-pc-windows-msvc]) (push) Has been cancelled
test `tauri-cli` / test (map[os:macos-latest target:x86_64-apple-darwin]) (push) Has been cancelled
test `tauri-cli` / test (map[os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:macos-latest target:aarch64-apple-darwin]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include: os:windows-latest target:x86_64-pc-windows-msvc]) (push) Has been cancelled
lint rust / clippy (map[cargo:cargo include:--package api os:macos-latest target:aarch64-apple-ios]) (push) Has been cancelled
test `@tauri-apps/api` e2e (mobile) / ios (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:Windows os:windows-latest]) (push) Has been cancelled
test `@tauri-apps/api` e2e / test (map[name:macOS os:macos-latest]) (push) Has been cancelled
test `@tauri-apps/cli` / test (windows-latest) (push) Has been cancelled
test core / test (map[args:--all-features key:all], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:build os:macos-latest target:aarch64-apple-ios toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:macos-14 target:aarch64-apple-darwin toolchain:1.90]) (push) Has been cancelled
test core / test (map[args:--no-default-features key:no-default], map[cargo:cargo command:test os:windows-latest target:x86_64-pc-windows-msvc toolchain:1.90]) (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 17:00:42 +05:00
commit feda81bf2f
1178 changed files with 156404 additions and 0 deletions

6
examples/api/src-tauri/.gitignore vendored Normal file
View File

@@ -0,0 +1,6 @@
# Generated by Cargo
# will have compiled files and executables
/target/
# cargo-mobile
/gen

View File

@@ -0,0 +1 @@
tauri-plugin-sample/

View File

@@ -0,0 +1,51 @@
[package]
name = "api"
version = "0.1.0"
description = "An example Tauri Application showcasing the api"
edition = "2024"
rust-version = "1.90"
license = "Apache-2.0 OR MIT"
[lib]
name = "api_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
[build-dependencies]
tauri-build = { workspace = true, default-features = true, features = [
"codegen",
"isolation",
] }
[dependencies]
serde_json = "1"
serde = { version = "1", features = ["derive"] }
log = "0.4.21"
tauri-plugin-sample = { path = "./tauri-plugin-sample/" }
tauri-plugin-log = "2"
# WebDriver automation bridge, used by the `@tauri-apps/api` e2e suite (packages/api-e2e).
# Desktop-only and behind the off-by-default `automation` feature so it never ships in a
# regular build.
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-automation = { version = "0.2", optional = true }
[dependencies.tauri]
workspace = true
default-features = true
features = [
"protocol-asset",
"image-ico",
"image-png",
"isolation",
"macos-private-api",
"tray-icon",
]
[dev-dependencies.tauri]
workspace = true
features = ["test"]
[features]
prod = ["tauri/custom-protocol"]
# Enables the WebDriver automation bridge; set by the e2e suite's build (packages/api-e2e).
automation = ["dep:tauri-plugin-automation"]

View File

@@ -0,0 +1,17 @@
[build.env]
# must set ICONS_VOLUME, DIST_VOLUME, ISOLATION_VOLUME and WORKSPACE_VOLUME environment variables
# ICONS_VOLUME: absolute path to the .icons folder
# DIST_VOLUME: absolute path to the dist folder
# ISOLATION_VOLUME: absolute path to the isolation dist folder
# WORKSPACE_VOLUME: absolute path to the workspace
# this can be done running `$ . .setup-cross.sh` in the examples/api folder
volumes = [
"ICONS_VOLUME",
"DIST_VOLUME",
"ISOLATION_VOLUME",
"WORKSPACE_VOLUME",
]
[target.aarch64-unknown-linux-gnu]
image = "aarch64-unknown-linux-gnu:latest"
#image = "ghcr.io/tauri-apps/tauri/aarch64-unknown-linux-gnu:latest"

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>Request camera access for WebRTC</string>
<key>NSMicrophoneUsageDescription</key>
<string>Request microphone access for WebRTC</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<true/>
<key>UISceneConfigurations</key>
<dict/>
</dict>
</dict>
</plist>

View File

@@ -0,0 +1,56 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri_build::WindowsAttributes;
fn main() {
tauri_build::try_build(
tauri_build::Attributes::new()
.codegen(tauri_build::CodegenContext::new())
.windows_attributes(WindowsAttributes::new_without_app_manifest())
.plugin(
"app-menu",
tauri_build::InlinedPlugin::new().commands(&["toggle", "popup"]),
)
.app_manifest(tauri_build::AppManifest::new().commands(&[
"log_operation",
"perform_request",
"echo",
"spam",
])),
)
.expect("failed to run tauri-build");
#[cfg(windows)]
{
// workaround needed to prevent `STATUS_ENTRYPOINT_NOT_FOUND` error in tests
// see https://github.com/tauri-apps/tauri/pull/4383#issuecomment-1212221864
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
let target_env = std::env::var("CARGO_CFG_TARGET_ENV");
let is_tauri_workspace = std::env::var("__TAURI_WORKSPACE__").is_ok_and(|v| v == "true");
if is_tauri_workspace && target_os == "windows" && Ok("msvc") == target_env.as_deref() {
embed_manifest_for_tests();
}
}
}
#[cfg(windows)]
fn embed_manifest_for_tests() {
static WINDOWS_MANIFEST_FILE: &str = "windows-app-manifest.xml";
let manifest = std::env::current_dir()
.unwrap()
.join("../../../crates/tauri-build/src")
.join(WINDOWS_MANIFEST_FILE);
println!("cargo:rerun-if-changed={}", manifest.display());
// Embed the Windows application manifest file.
println!("cargo:rustc-link-arg=/MANIFEST:EMBED");
println!(
"cargo:rustc-link-arg=/MANIFESTINPUT:{}",
manifest.to_str().unwrap()
);
// Turn linker warnings into errors.
println!("cargo:rustc-link-arg=/WX");
}

View File

@@ -0,0 +1 @@
schemas/

View File

@@ -0,0 +1,16 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "secondary-window",
"description": "capability for secondary window",
"windows": ["main-*"],
"permissions": [
{
"identifier": "sample:allow-ping",
"deny": [
{
"path": "tauri.app"
}
]
}
]
}

View File

@@ -0,0 +1,75 @@
{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "run-app",
"description": "permissions to run the app",
"windows": ["main", "main-*"],
"permissions": [
"core:window:allow-is-enabled",
"core:window:allow-set-enabled",
{
"identifier": "allow-log-operation",
"allow": [
{
"event": "tauri-click"
}
]
},
"allow-perform-request",
"allow-echo",
"allow-spam",
"app-menu:default",
"sample:allow-ping-scoped",
"sample:allow-js-values",
"sample:global-scope",
"core:default",
"core:app:allow-app-hide",
"core:app:allow-app-show",
"core:app:allow-set-app-theme",
"core:app:allow-set-dock-visibility",
"core:app:allow-default-window-icon",
"core:app:allow-exit",
"core:window:allow-set-theme",
"core:window:allow-center",
"core:window:allow-request-user-attention",
"core:window:allow-set-resizable",
"core:window:allow-set-maximizable",
"core:window:allow-set-minimizable",
"core:window:allow-set-closable",
"core:window:allow-set-title",
"core:window:allow-maximize",
"core:window:allow-unmaximize",
"core:window:allow-minimize",
"core:window:allow-unminimize",
"core:window:allow-show",
"core:window:allow-hide",
"core:window:allow-close",
"core:window:allow-set-decorations",
"core:window:allow-set-shadow",
"core:window:allow-set-effects",
"core:window:allow-set-always-on-top",
"core:window:allow-set-always-on-bottom",
"core:window:allow-set-content-protected",
"core:window:allow-set-size",
"core:window:allow-set-min-size",
"core:window:allow-set-max-size",
"core:window:allow-set-position",
"core:window:allow-set-fullscreen",
"core:window:allow-set-fullscreen-on-monitor",
"core:window:allow-set-simple-fullscreen",
"core:window:allow-set-focus",
"core:window:allow-set-focusable",
"core:window:allow-set-skip-taskbar",
"core:window:allow-set-cursor-grab",
"core:window:allow-set-cursor-visible",
"core:window:allow-set-cursor-icon",
"core:window:allow-set-cursor-position",
"core:window:allow-set-ignore-cursor-events",
"core:window:allow-start-dragging",
"core:window:allow-set-progress-bar",
"core:window:allow-set-icon",
"core:window:allow-toggle-maximize",
"core:webview:allow-create-webview-window",
"core:webview:allow-print",
"core:webview:allow-set-webview-zoom"
]
}

View File

@@ -0,0 +1,6 @@
<WixLocalization Culture="pt-BR" xmlns="http://schemas.microsoft.com/wix/2006/localization">
<String Id="LaunchApp">Executar Tauri API</String>
<String Id="DowngradeErrorMessage">Uma versão mais recente de Tauri API está instalada.</String>
<String Id="PathEnvVarFeature">Adiciona o caminho do executável de Tauri API para a variável de ambiente PATH. Isso permite Tauri API ser executado pela linha de comando.</String>
<String Id="InstallAppFeature">Instala Tauri API.</String>
</WixLocalization>

View File

@@ -0,0 +1,3 @@
[default]
description = "Default permissions for the plugin"
permissions = ["allow-toggle", "allow-popup"]

View File

@@ -0,0 +1,11 @@
# Automatically generated - DO NOT EDIT!
[[permission]]
identifier = "allow-echo"
description = "Enables the echo command without any pre-configured scope."
commands.allow = ["echo"]
[[permission]]
identifier = "deny-echo"
description = "Denies the echo command without any pre-configured scope."
commands.deny = ["echo"]

View File

@@ -0,0 +1,11 @@
# Automatically generated - DO NOT EDIT!
[[permission]]
identifier = "allow-log-operation"
description = "Enables the log_operation command without any pre-configured scope."
commands.allow = ["log_operation"]
[[permission]]
identifier = "deny-log-operation"
description = "Denies the log_operation command without any pre-configured scope."
commands.deny = ["log_operation"]

View File

@@ -0,0 +1,11 @@
# Automatically generated - DO NOT EDIT!
[[permission]]
identifier = "allow-perform-request"
description = "Enables the perform_request command without any pre-configured scope."
commands.allow = ["perform_request"]
[[permission]]
identifier = "deny-perform-request"
description = "Denies the perform_request command without any pre-configured scope."
commands.deny = ["perform_request"]

View File

@@ -0,0 +1,11 @@
# Automatically generated - DO NOT EDIT!
[[permission]]
identifier = "allow-spam"
description = "Enables the spam command without any pre-configured scope."
commands.allow = ["spam"]
[[permission]]
identifier = "deny-spam"
description = "Denies the spam command without any pre-configured scope."
commands.deny = ["spam"]

View File

@@ -0,0 +1,63 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{Deserialize, Serialize};
use tauri::{
command,
ipc::{Channel, CommandScope},
};
#[derive(Debug, Deserialize)]
#[allow(unused)]
pub struct RequestBody {
id: i32,
name: String,
}
#[derive(Debug, Deserialize)]
pub struct LogScope {
event: String,
}
#[command]
pub fn log_operation(
event: String,
payload: Option<String>,
command_scope: CommandScope<LogScope>,
) -> Result<(), &'static str> {
if command_scope.denies().iter().any(|s| s.event == event) {
Err("denied")
} else if !command_scope.allows().iter().any(|s| s.event == event) {
Err("not allowed")
} else {
log::info!("{event} {payload:?}");
Ok(())
}
}
#[derive(Serialize)]
pub struct ApiResponse {
message: String,
}
#[command]
pub fn perform_request(endpoint: String, body: RequestBody) -> ApiResponse {
println!("{endpoint} {body:?}");
ApiResponse {
message: "message response".into(),
}
}
#[command]
pub fn echo(request: tauri::ipc::Request<'_>) -> tauri::ipc::Response {
tauri::ipc::Response::new(request.body().clone())
}
#[command]
pub fn spam(channel: Channel<i32>) -> tauri::Result<()> {
for i in 1..=1_000 {
channel.send(i)?;
}
Ok(())
}

View File

@@ -0,0 +1,231 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
mod cmd;
#[cfg(all(desktop, not(test)))]
mod menu_plugin;
#[cfg(all(desktop, not(test)))]
mod tray;
use serde::Serialize;
use tauri::{
App, Emitter, Listener, Runtime, WebviewUrl,
ipc::Channel,
webview::{PageLoadEvent, WebviewWindowBuilder},
};
#[allow(unused)]
use tauri::{Manager, RunEvent};
use tauri_plugin_sample::{PingRequest, SampleExt};
#[derive(Clone, Serialize)]
struct Reply {
data: String,
}
#[cfg(target_os = "macos")]
pub struct AppMenu<R: Runtime>(pub std::sync::Mutex<Option<tauri::menu::Menu<R>>>);
#[cfg(all(desktop, not(test)))]
pub struct PopupMenu<R: Runtime>(tauri::menu::Menu<R>);
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
run_app(tauri::Builder::default(), |_app| {})
}
pub fn run_app<R: Runtime, F: FnOnce(&App<R>) + Send + 'static>(
builder: tauri::Builder<R>,
setup: F,
) {
// WebDriver automation bridge for the `@tauri-apps/api` e2e suite (packages/api-e2e).
// Registered as early as possible per the plugin's docs. Behind the off-by-default
// `automation` feature, and `not(test)` so it never interferes with the mock-runtime
// unit test below.
#[cfg(all(desktop, feature = "automation", not(test)))]
let builder = builder.plugin(tauri_plugin_automation::init());
let builder = builder
.plugin(
tauri_plugin_log::Builder::default()
.level(log::LevelFilter::Info)
.build(),
)
.plugin(tauri_plugin_sample::init())
.setup(move |app| {
#[cfg(all(desktop, not(test)))]
{
let handle = app.handle();
tray::create_tray(handle)?;
handle.plugin(menu_plugin::init())?;
}
#[cfg(target_os = "macos")]
app.manage(AppMenu::<R>(Default::default()));
#[cfg(all(desktop, not(test)))]
app.manage(PopupMenu(
tauri::menu::MenuBuilder::new(app)
.check("check", "Tauri is awesome!")
.text("text", "Do something")
.copy()
.build()?,
));
#[allow(unused_mut)]
let mut window_builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
.disable_drag_drop_handler()
.on_document_title_changed(|_window, title| {
println!("document title changed: {title}");
});
#[cfg(all(desktop, not(test)))]
{
use std::sync::atomic::{AtomicU64, Ordering};
let app_ = app.handle().clone();
let created_window_count = AtomicU64::new(0);
window_builder = window_builder
.title("Tauri API Validation")
.inner_size(1000., 800.)
.min_inner_size(600., 400.)
.menu(tauri::menu::Menu::default(app.handle())?)
.on_new_window(move |url, features| {
println!("new window requested: {url:?} {features:?}");
let number = created_window_count.fetch_add(1, Ordering::Relaxed);
let builder = WebviewWindowBuilder::new(
&app_,
format!("new-{number}"),
tauri::WebviewUrl::External("about:blank".parse().unwrap()),
)
.window_features(features)
.on_document_title_changed(|window, title| {
window.set_title(&title).unwrap();
})
.title(url.as_str());
let window = builder.build().unwrap();
tauri::webview::NewWindowResponse::Create { window }
});
// Liquid Glass effects need a transparent window to show through
#[cfg(target_os = "macos")]
{
window_builder = window_builder.transparent(true);
}
}
let _webview = window_builder.build()?;
let value = Some("test".to_string());
let response = app.sample().ping(PingRequest {
value: value.clone(),
on_event: Channel::new(|event| {
println!("got channel event: {event:?}");
Ok(())
}),
});
log::info!("got response: {response:?}");
if let Ok(res) = response {
assert_eq!(res.value, value);
}
setup(app);
Ok(())
})
.on_page_load(|webview, payload| {
if payload.event() == PageLoadEvent::Finished {
let webview_ = webview.clone();
webview.listen("js-event", move |event| {
println!("got js-event with message '{:?}'", event.payload());
let reply = Reply {
data: "something else".to_string(),
};
webview_
.emit("rust-event", Some(reply))
.expect("failed to emit");
});
}
});
#[allow(unused_mut)]
let mut app = builder
.invoke_handler(tauri::generate_handler![
cmd::log_operation,
cmd::perform_request,
cmd::echo,
cmd::spam,
])
.build(tauri::tauri_build_context!())
.expect("error while building tauri application");
#[cfg(target_os = "macos")]
app.set_activation_policy(tauri::ActivationPolicy::Regular);
#[cfg(target_os = "ios")]
let mut counter = 0;
app.run(move |_app_handle, event| {
match event {
// Keep the event loop running even if all windows are closed
// This allow us to catch tray icon events when there is no window
// if we manually requested an exit (code is Some(_)) we will let it go through
#[cfg(all(desktop, not(test)))]
RunEvent::ExitRequested { api, code, .. } if code.is_none() => {
api.prevent_exit();
}
#[cfg(desktop)]
RunEvent::WindowEvent {
event: tauri::WindowEvent::CloseRequested { api, .. },
label,
..
} => {
println!("closing window...");
// run the window destroy manually just for fun :)
// usually you'd show a dialog here to ask for confirmation or whatever
api.prevent_close();
_app_handle
.get_webview_window(&label)
.unwrap()
.destroy()
.unwrap();
}
#[cfg(target_os = "ios")]
RunEvent::SceneRequested { .. } => {
counter += 1;
WebviewWindowBuilder::new(
_app_handle,
format!("main-from-scene-{counter}"),
WebviewUrl::default(),
)
.build()
.unwrap();
}
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
RunEvent::Opened { urls } => {
println!("opened urls: {:?}", urls);
}
_ => (),
}
})
}
#[cfg(test)]
mod tests {
use tauri::Manager;
#[test]
fn run_app() {
super::run_app(tauri::test::mock_builder(), |app| {
let window = app.get_webview_window("main").unwrap();
std::thread::spawn(move || {
std::thread::sleep(std::time::Duration::from_secs(1));
window.close().unwrap();
});
})
}
}

View File

@@ -0,0 +1,10 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
fn main() {
api_lib::run();
}

View File

@@ -0,0 +1,50 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use tauri::{
Runtime, command,
plugin::{Builder, TauriPlugin},
};
#[cfg(not(target_os = "macos"))]
#[command]
pub fn toggle<R: tauri::Runtime>(window: tauri::Window<R>) {
if window.is_menu_visible().unwrap_or_default() {
let _ = window.hide_menu();
} else {
let _ = window.show_menu();
}
}
#[cfg(target_os = "macos")]
#[command]
pub fn toggle<R: tauri::Runtime>(
app: tauri::AppHandle<R>,
app_menu: tauri::State<'_, crate::AppMenu<R>>,
) {
if let Some(menu) = app.remove_menu().unwrap() {
app_menu.0.lock().unwrap().replace(menu);
} else {
app
.set_menu(app_menu.0.lock().unwrap().clone().expect("no app menu"))
.unwrap();
}
}
#[command]
pub fn popup<R: tauri::Runtime>(
window: tauri::Window<R>,
popup_menu: tauri::State<'_, crate::PopupMenu<R>>,
) {
window.popup_menu(&popup_menu.0).unwrap();
}
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("app-menu")
.invoke_handler(tauri::generate_handler![
#![plugin(app_menu)]
popup, toggle
])
.build()
}

View File

@@ -0,0 +1,126 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use std::sync::atomic::{AtomicBool, Ordering};
use tauri::{
Manager, Runtime, WebviewUrl, include_image,
menu::{Menu, MenuItem},
tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
};
pub fn create_tray<R: Runtime>(app: &tauri::AppHandle<R>) -> tauri::Result<()> {
let toggle_i = MenuItem::with_id(app, "toggle", "Toggle", true, None::<&str>)?;
let new_window_i = MenuItem::with_id(app, "new-window", "New window", true, None::<&str>)?;
let icon_i_1 = MenuItem::with_id(app, "icon-1", "Icon 1", true, None::<&str>)?;
let icon_i_2 = MenuItem::with_id(app, "icon-2", "Icon 2", true, None::<&str>)?;
#[cfg(target_os = "macos")]
let set_title_i = MenuItem::with_id(app, "set-title", "Set Title", true, None::<&str>)?;
let switch_i = MenuItem::with_id(app, "switch-menu", "Switch Menu", true, None::<&str>)?;
let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
let remove_tray_i =
MenuItem::with_id(app, "remove-tray", "Remove Tray icon", true, None::<&str>)?;
let menu1 = Menu::with_items(
app,
&[
&toggle_i,
&new_window_i,
&icon_i_1,
&icon_i_2,
#[cfg(target_os = "macos")]
&set_title_i,
&switch_i,
&quit_i,
&remove_tray_i,
],
)?;
let menu2 = Menu::with_items(
app,
&[&toggle_i, &new_window_i, &switch_i, &quit_i, &remove_tray_i],
)?;
let is_menu1 = AtomicBool::new(true);
let _tray = TrayIconBuilder::with_id("tray-1")
.tooltip("Tauri")
.icon(app.default_window_icon().unwrap().clone())
.menu(&menu1)
.show_menu_on_left_click(false)
.on_menu_event(move |app, event| match event.id.as_ref() {
"quit" => {
app.exit(0);
}
"remove-tray" => {
app.remove_tray_by_id("tray-1");
}
"toggle" => {
if let Some(window) = app.get_webview_window("main") {
let new_title = if window.is_visible().unwrap_or_default() {
let _ = window.hide();
"Show"
} else {
let _ = window.show();
let _ = window.set_focus();
"Hide"
};
toggle_i.set_text(new_title).unwrap();
}
}
"new-window" => {
let _webview =
tauri::WebviewWindowBuilder::new(app, "new", WebviewUrl::App("index.html".into()))
.title("Tauri")
.build()
.unwrap();
}
#[cfg(target_os = "macos")]
"set-title" => {
if let Some(tray) = app.tray_by_id("tray-1") {
let _ = tray.set_title(Some("Tauri"));
}
}
i @ "icon-1" | i @ "icon-2" => {
if let Some(tray) = app.tray_by_id("tray-1") {
let icon = if i == "icon-1" {
include_image!("../../.icons/icon.ico")
} else {
include_image!("../../.icons/tray_icon_with_transparency.png")
};
let _ = tray.set_icon(Some(icon));
}
}
"switch-menu" => {
let flag = is_menu1.load(Ordering::Relaxed);
let (menu, tooltip) = if flag {
(menu2.clone(), "Menu 2")
} else {
(menu1.clone(), "Tauri")
};
if let Some(tray) = app.tray_by_id("tray-1") {
let _ = tray.set_menu(Some(menu));
let _ = tray.set_tooltip(Some(tooltip));
}
is_menu1.store(!flag, Ordering::Relaxed);
}
_ => {}
})
.on_tray_icon_event(|tray, event| {
if let TrayIconEvent::Click {
button: MouseButton::Left,
button_state: MouseButtonState::Up,
..
} = event
{
let app = tray.app_handle();
if let Some(window) = app.get_webview_window("main") {
let _ = window.unminimize();
let _ = window.show();
let _ = window.set_focus();
}
}
})
.build(app)?;
Ok(())
}

View File

@@ -0,0 +1 @@
.tauri

View File

@@ -0,0 +1,18 @@
[package]
name = "tauri-plugin-sample"
version = "0.1.0"
edition = "2024"
links = "tauri-plugin-sample"
[dependencies]
tauri = { workspace = true }
log = "0.4"
serde = "1"
serde_json = "1"
thiserror = "2"
[target.'cfg(any(target_os = "ios", target_os = "android"))'.dependencies]
tauri = { workspace = true, features = ["wry"] }
[build-dependencies]
tauri-plugin = { workspace = true, features = ["build"] }

View File

@@ -0,0 +1,2 @@
/build
.tauri

View File

@@ -0,0 +1,40 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
}
android {
namespace = "com.plugin.sample"
compileSdk = 36
defaultConfig {
minSdk = 21
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
}
kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_1_8
}
}
dependencies {
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.0")
implementation("com.google.android.material:material:1.7.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
implementation(project(":tauri-android"))
}

View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,31 @@
pluginManagement {
repositories {
mavenCentral()
gradlePluginPortal()
google()
}
resolutionStrategy {
eachPlugin {
switch (requested.id.id) {
case "com.android.library":
useVersion("8.0.2")
break
case "org.jetbrains.kotlin.android":
useVersion("1.8.20")
break
}
}
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
google()
}
}
include ':tauri-android'
project(':tauri-android').projectDir = new File('./.tauri/tauri-api')

View File

@@ -0,0 +1,28 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package com.plugin.sample
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.plugin.sample", appContext.packageName)
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
</manifest>

View File

@@ -0,0 +1,14 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package com.plugin.sample
import android.util.Log
class Example {
fun pong(value: String): String {
Log.i("Pong", value)
return value
}
}

View File

@@ -0,0 +1,57 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package com.plugin.sample
import android.app.Activity
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.Channel
import app.tauri.plugin.JSArray
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import app.tauri.plugin.Invoke
@InvokeArg
class PingArgs {
var value: String? = null
var onEvent: Channel? = null
}
class JsValues(val array: JSArray, val obj: JSObject)
@TauriPlugin
class ExamplePlugin(private val activity: Activity): Plugin(activity) {
private val implementation = Example()
@Command
fun ping(invoke: Invoke) {
val args = invoke.parseArgs(PingArgs::class.java)
val event = JSObject()
event.put("kind", "ping")
args.onEvent?.send(event)
val ret = JSObject()
ret.put("value", implementation.pong(args.value ?: "default value :("))
invoke.resolve(ret)
}
// Resolves org.json values through the plugin JSON mapper (`resolveObject`),
// both as a property of a plain object and nested in one another.
@Command
fun jsValues(invoke: Invoke) {
val array = JSArray()
array.put("a")
array.put(1)
array.put(true)
val obj = JSObject()
obj.put("kind", "object")
obj.put("nested", JSArray(listOf(1, 2)))
invoke.resolveObject(JsValues(array, obj))
}
}

View File

@@ -0,0 +1,21 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
package com.plugin.sample
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}

View File

@@ -0,0 +1,7 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
if ('__TAURI__' in window) {
window.__TAURI__.sample = {}
}

View File

@@ -0,0 +1,13 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
const COMMANDS: &[&str] = &["ping", "js_values"];
fn main() {
tauri_plugin::Builder::new(COMMANDS)
.android_path("android")
.ios_path("ios")
.global_api_script_path("./api-iife.js")
.build();
}

View File

@@ -0,0 +1,10 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
Package.resolved

View File

@@ -0,0 +1,35 @@
// swift-tools-version:5.3
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import PackageDescription
let package = Package(
name: "tauri-plugin-sample",
platforms: [
.macOS(.v10_13),
.iOS(.v13),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "tauri-plugin-sample",
type: .static,
targets: ["tauri-plugin-sample"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
.package(name: "Tauri", path: "../../../../../crates/tauri/mobile/ios-api")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "tauri-plugin-sample",
dependencies: [
.byName(name: "Tauri")
],
path: "Sources")
]
)

View File

@@ -0,0 +1,3 @@
# Tauri Plugin sample
A description of this package.

View File

@@ -0,0 +1,32 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import SwiftRs
import Tauri
import UIKit
import WebKit
class PingArgs: Decodable {
let value: String?
let onEvent: Channel?
}
class ExamplePlugin: Plugin {
@objc public func ping(_ invoke: Invoke) throws {
let args = try invoke.parseArgs(PingArgs.self)
try args.onEvent?.send(["kind": "ping"])
invoke.resolve(["value": args.value ?? ""])
}
@objc public func jsValues(_ invoke: Invoke) throws {
let array: JSArray = ["a", 1, true]
let obj: JSObject = ["kind": "object", "nested": [1, 2] as JSArray]
invoke.resolve(["array": array, "obj": obj])
}
}
@_cdecl("init_plugin_sample")
func initPlugin() -> Plugin {
return ExamplePlugin()
}

View File

@@ -0,0 +1,12 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
import XCTest
@testable import ExamplePlugin
final class ExamplePluginTests: XCTestCase {
func testExample() throws {
let plugin = ExamplePlugin()
}
}

View File

@@ -0,0 +1 @@
schemas/

View File

@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-js-values"
description = "Enables the js_values command without any pre-configured scope."
commands.allow = ["js_values"]
[[permission]]
identifier = "deny-js-values"
description = "Denies the js_values command without any pre-configured scope."
commands.deny = ["js_values"]

View File

@@ -0,0 +1,13 @@
# Automatically generated - DO NOT EDIT!
"$schema" = "../../schemas/schema.json"
[[permission]]
identifier = "allow-ping"
description = "Enables the ping command without any pre-configured scope."
commands.allow = ["ping"]
[[permission]]
identifier = "deny-ping"
description = "Denies the ping command without any pre-configured scope."
commands.deny = ["ping"]

View File

@@ -0,0 +1,87 @@
## Permission Table
<table>
<tr>
<th>Identifier</th>
<th>Description</th>
</tr>
<tr>
<td>
`sample:allow-js-values`
</td>
<td>
Enables the js_values command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`sample:deny-js-values`
</td>
<td>
Denies the js_values command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`sample:allow-ping`
</td>
<td>
Enables the ping command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`sample:deny-ping`
</td>
<td>
Denies the ping command without any pre-configured scope.
</td>
</tr>
<tr>
<td>
`sample:global-scope`
</td>
<td>
Sets a global scope.
</td>
</tr>
<tr>
<td>
`sample:allow-ping-scoped`
</td>
<td>
Enables the ping command with a test scope.
</td>
</tr>
</table>

View File

@@ -0,0 +1,7 @@
"$schema" = "schemas/schema.json"
[[permission]]
identifier = "global-scope"
description = "Sets a global scope."
[[permission.scope.allow]]
path = "global"

View File

@@ -0,0 +1,8 @@
"$schema" = "schemas/schema.json"
[[permission]]
identifier = "allow-ping-scoped"
description = "Enables the ping command with a test scope."
commands.allow = ["ping"]
[[permission.scope.allow]]
path = "x"

View File

@@ -0,0 +1,30 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
use tauri::{AppHandle, Runtime, plugin::PluginApi};
use crate::models::*;
pub fn init<R: Runtime, C: DeserializeOwned>(
app: &AppHandle<R>,
_api: PluginApi<R, C>,
) -> crate::Result<Sample<R>> {
Ok(Sample(app.clone()))
}
/// A helper class to access the sample APIs.
pub struct Sample<R: Runtime>(AppHandle<R>);
impl<R: Runtime> Sample<R> {
pub fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
payload.on_event.send(Event {
kind: "ping".to_string(),
value: payload.value.clone(),
})?;
Ok(PingResponse {
value: payload.value,
})
}
}

View File

@@ -0,0 +1,14 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[cfg(mobile)]
#[error(transparent)]
PluginInvoke(#[from] tauri::plugin::mobile::PluginInvokeError),
#[error(transparent)]
Tauri(#[from] tauri::Error),
}
pub type Result<T> = std::result::Result<T, Error>;

View File

@@ -0,0 +1,101 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::Deserialize;
use std::path::PathBuf;
use tauri::{
Manager, Runtime, State,
plugin::{Builder, TauriPlugin},
};
pub use models::*;
#[cfg(desktop)]
mod desktop;
#[cfg(mobile)]
mod mobile;
mod error;
mod models;
#[cfg(desktop)]
use desktop::Sample;
#[cfg(mobile)]
use mobile::Sample;
pub use error::*;
/// Extensions to [`tauri::App`], [`tauri::AppHandle`] and [`tauri::Window`] to access the sample APIs.
pub trait SampleExt<R: Runtime> {
fn sample(&self) -> State<'_, Sample<R>>;
}
impl<R: Runtime, T: Manager<R>> crate::SampleExt<R> for T {
fn sample(&self) -> State<'_, Sample<R>> {
self.state::<Sample<R>>()
}
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
struct PingScope {
path: PathBuf,
}
#[allow(dead_code)]
#[derive(Debug, Deserialize)]
struct SampleScope {
path: PathBuf,
}
#[tauri::command]
fn ping<R: tauri::Runtime>(
app: tauri::AppHandle<R>,
value: Option<String>,
scope: tauri::ipc::CommandScope<PingScope>,
global_scope: tauri::ipc::GlobalScope<SampleScope>,
) -> std::result::Result<PingResponse, String> {
println!("local scope {scope:?}");
println!("global scope {global_scope:?}");
app
.sample()
.ping(PingRequest {
value,
on_event: tauri::ipc::Channel::new(|_| Ok(())),
})
.map_err(|e| e.to_string())
}
/// Resolves `JSArray` and `JSObject` values from the native (Kotlin or Swift) plugin.
#[tauri::command]
fn js_values<R: tauri::Runtime>(
app: tauri::AppHandle<R>,
) -> std::result::Result<serde_json::Value, String> {
#[cfg(mobile)]
return app.sample().js_values().map_err(|e| e.to_string());
#[cfg(desktop)]
{
let _ = app;
Err("js_values is only implemented on mobile".into())
}
}
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::new("sample")
.setup(|app, api| {
#[cfg(mobile)]
let sample = mobile::init(app, api)?;
#[cfg(desktop)]
let sample = desktop::init(app, api)?;
app.manage(sample);
Ok(())
})
.invoke_handler(tauri::generate_handler![ping, js_values])
.on_navigation(|window, url| {
println!("navigation {} {url}", window.label());
true
})
.build()
}

View File

@@ -0,0 +1,45 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::de::DeserializeOwned;
use tauri::{
AppHandle, Runtime,
plugin::{PluginApi, PluginHandle},
};
use crate::models::*;
#[cfg(target_os = "android")]
const PLUGIN_IDENTIFIER: &str = "com.plugin.sample";
#[cfg(target_os = "ios")]
tauri::ios_plugin_binding!(init_plugin_sample);
// initializes the Kotlin or Swift plugin classes
pub fn init<R: Runtime, C: DeserializeOwned>(
_app: &AppHandle<R>,
api: PluginApi<R, C>,
) -> crate::Result<Sample<R>> {
#[cfg(target_os = "android")]
let handle = api.register_android_plugin(PLUGIN_IDENTIFIER, "ExamplePlugin")?;
#[cfg(target_os = "ios")]
let handle = api.register_ios_plugin(init_plugin_sample)?;
Ok(Sample(handle))
}
/// A helper class to access the sample APIs.
pub struct Sample<R: Runtime>(PluginHandle<R>);
impl<R: Runtime> Sample<R> {
pub fn ping(&self, payload: PingRequest) -> crate::Result<PingResponse> {
self
.0
.run_mobile_plugin("ping", payload)
.map_err(Into::into)
}
pub fn js_values(&self) -> crate::Result<serde_json::Value> {
self.0.run_mobile_plugin("jsValues", ()).map_err(Into::into)
}
}

View File

@@ -0,0 +1,24 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use serde::{Deserialize, Serialize};
use tauri::ipc::Channel;
#[derive(Serialize)]
pub struct Event {
pub kind: String,
pub value: Option<String>,
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PingRequest {
pub value: Option<String>,
pub on_event: Channel<Event>,
}
#[derive(Debug, Clone, Default, Deserialize, Serialize)]
pub struct PingResponse {
pub value: Option<String>,
}

View File

@@ -0,0 +1,132 @@
{
"$schema": "../../../crates/tauri-schema-generator/schemas/config.schema.json",
"productName": "Tauri API",
"version": "1.0.0",
"identifier": "com.tauri.api",
"build": {
"frontendDist": "../dist",
"devUrl": "http://localhost:1420",
"beforeDevCommand": "pnpm dev",
"beforeBuildCommand": "pnpm build",
"removeUnusedCommands": true
},
"app": {
"withGlobalTauri": true,
"macOSPrivateApi": true,
"security": {
"pattern": {
"use": "isolation",
"options": {
"dir": "../isolation-dist/"
}
},
"csp": {
"default-src": "'self' customprotocol: asset:",
"connect-src": "ipc: http://ipc.localhost",
"font-src": ["https://fonts.gstatic.com"],
"img-src": "'self' asset: http://asset.localhost blob: data:",
"style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com"
},
"freezePrototype": true,
"assetProtocol": {
"enable": true,
"scope": {
"allow": ["$APPDATA/db/**", "$RESOURCE/**"],
"deny": ["$APPDATA/db/*.stronghold"]
}
}
}
},
"plugins": {
"cli": {
"description": "Tauri API example",
"args": [
{
"short": "c",
"name": "config",
"takesValue": true,
"description": "Config path"
},
{
"short": "t",
"name": "theme",
"takesValue": true,
"description": "App theme",
"possibleValues": ["light", "dark", "system"]
},
{
"short": "v",
"name": "verbose",
"description": "Verbosity level"
}
],
"subcommands": {
"update": {
"description": "Updates the app",
"args": [
{
"short": "b",
"name": "background",
"description": "Update in background"
}
]
}
}
}
},
"bundle": {
"active": true,
"fileAssociations": [
{
"ext": ["png"],
"mimeType": "image/png",
"rank": "Default"
},
{
"ext": ["jpg", "jpeg"],
"mimeType": "image/jpeg",
"rank": "Alternate"
},
{
"ext": ["gif"],
"mimeType": "image/gif",
"rank": "Owner"
},
{
"ext": ["taurijson"],
"exportedType": {
"identifier": "com.tauri.dev-file-associations-demo.taurijson",
"conformsTo": ["public.json"]
}
},
{
"ext": ["taurid"],
"exportedType": {
"identifier": "com.tauri.dev-file-associations-demo.tauridata",
"conformsTo": ["public.data"]
}
}
],
"icon": [
"../../.icons/32x32.png",
"../../.icons/128x128.png",
"../../.icons/128x128@2x.png",
"../../.icons/icon.icns",
"../../.icons/icon.ico",
"../../.icons/AppIcon.icon"
],
"windows": {
"wix": {
"language": {
"en-US": {},
"pt-BR": {
"localePath": "locales/pt-BR.wxl"
}
}
},
"nsis": {
"compression": "none"
}
}
}
}