Compare commits

...

435 Commits

Author SHA1 Message Date
github-actions[bot]
8d869717da apply version updates (#14041)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-08-19 09:08:54 -03:00
Kushal Meghani
f0172a454a fix(app): correct removeDataStore return type, add docs for getBundle… (#14038)
* fix(app): correct removeDataStore return type, add docs for getBundleType

* add change file

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-19 08:02:21 -03:00
Lucas Fernandes Nogueira
5075b67d36 fix(tauri): build without the wry feature flag (#14039)
* fix(tauri): build without the wry feature flag

* change file

* fix windows
2025-08-19 07:42:41 -03:00
Lucas Nogueira
c3252f72f6 fix(tauri): on_related_view should be behind the wry feature flag 2025-08-18 17:23:06 -03:00
github-actions[bot]
b4abb6cae8 Apply Version Updates From Current Changes (#13887)
* apply version updates

* chore: minor bump codegen, build, macros

* fix audit

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-18 15:50:13 -03:00
Will
1a3d1a024e fix(ios): Tauri iOS build with binary XCFramework dependencies (#13995)
* Fix Tauri iOS build not having a PATH variable to access unzip to extract binaryTargets and also not including Frameworks when linking

* Add covector change

* fmt

* Update crates/tauri-utils/src/build.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2025-08-18 07:35:49 -03:00
renovate[bot]
37154ebdcd chore(deps): update dependency rollup to v4.46.3 (#14027)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-18 14:34:25 +08:00
Tony
380656874e Remove AsRef<Window> on WebviewWindow (#14026) 2025-08-18 13:45:43 +08:00
Lucas Fernandes Nogueira
bc4afe7dd4 feat(cli): check plugin versions for incompatibilities (#13993)
* feat(cli): check plugin versions for incompatibilities

check core plugin versions for incompatibilities between Cargo and NPM releases

a plugin NPM/cargo version is considered "incompatible" if their major or minor versions are not equal

on dev we show an warning
on build we error out (with a `--ignore-incompatible-plugins` flag to prevent that)

this is an idea from @oscartbeaumont
we've seen several plugin changes that require updates for both the cargo and the NPM releases of a plugin, and if they are not in sync, the functionality does not work
e.g. https://github.com/tauri-apps/plugins-workspace/pull/2573 where the change actually breaks the app updater if you miss the NPM update

* Use list to get multiple package versions at once

* Fix for older rust versions

* Clippy

* Support yarn classic

* Support yarn berry

* Use `.cmd` only for `npm`, `yarn`, `pnpm`

* Use yarn list without --pattern

* rename

* Extract function `check_incompatible_packages`

* Check `tauri` <-> `@tauri-apps/api`

* incompatible -> mismatched

* run build check in parallel

* rename struct

* Switch back to use sync check and add todo

* Extract to function `cargo_manifest_and_lock`

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-08-17 12:24:40 -03:00
Akshanabha Chakraborty
7c2eb31c83 feat: add PluginHandle::run_mobile_plugin_async (#13895)
* add async

* chore: fmt

* feat: add run_mobile_plugin_async

* changes

* chore: fix misplaced `}`

* chore: fix minor pattern matching error

* fix: copy the response handling directly from run_mobile_plugin

* fix android build

* Fix clippy lint

* lint

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-17 12:14:16 -03:00
Tony
737364b8d3 fix: a few regressions from previous PRs (#14020)
* fix: a few regressions from previous PRs

* rename with_window_features to window_features

* Clippy

* clippy

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-17 12:03:31 -03:00
Robert
68874c68c5 feat(core): webview window focusable property, closes #11130 (#13564)
* Adds the ability to set the focused property from tauri.conf.json -- windows

* add set_focusable, pin tao

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-17 11:50:17 -03:00
Sean Wang
dfadcb764b feat: add WebView::set_cookie and WebView::delete_cookie (#13661)
* chore: patch wry

* feat: added `Webview::set_cookie` and `Webview::delete_cookie`

* chore: changes-files

* fmt

* owned cookie, re-export crate

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-16 23:41:16 -03:00
Sean Wang
22d6bcacbb feat(tauri): impl App::set_device_event_filter for AppHandle also (#14008)
* feat(tauri): impl `App::set_device_event_filter` for `AppHandle` also

* Update .changes/impl-set_device_event_filter-for-apphandle.md

* Update .changes/impl-set_device_event_filter-for-apphandle.md

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2025-08-16 15:30:46 -03:00
Tony
b21d86a8a3 fix(cli): permission add could add duplicated (#13981) 2025-08-16 14:51:45 -03:00
THELOSTSOUL
33d0b3f0c1 feat: add WebviewBuilder::on_new_window and WebviewBuilder::on_document_title_changed (#13876)
* add "new window" and "document title changed" webview handler

* take document title changed handler

* update example, add missing api, change files

* allow creating tauri window for the window.open call

* set size and position, fix linux, example

* enhance document title change

* fix windows deadlock

* wry 0.53

* update wry

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-16 14:49:01 -03:00
Petr
f1232671ab feat: expose internal TrayIcon (#13959) 2025-08-17 00:23:23 +08:00
Lucas Fernandes Nogueira
0c402bfb6b feat(cli): increase iOS deployment target to 14.0 (#13997)
* feat(cli): increase iOS deployment target to 14.0

closes https://github.com/tauri-apps/plugins-workspace/issues/1876

ref https://github.com/tauri-apps/tauri-docs/pull/3455

* fix tests
2025-08-16 10:32:26 -03:00
Lucas Fernandes Nogueira
d6d5f37077 feat: add --root-certificate-path option for mobile dev (#13358)
* feat: add `--root-certificate-path` option for mobile dev

lets you use a HTTPS development server

example usage:
```
cargo install tauri-cli --git https://github.com/tauri-apps/tauri --branch feat/mobile-dev-cert
cargo tauri android dev --open --root-certificate-path "/Users/lucas/Library/Application Support/mkcert/rootCA.pem" --features tauri/rustls-tls
```

* Apply suggestions from code review

Co-authored-by: Fabian-Lars <github@fabianlars.de>

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-08-16 09:13:10 -03:00
Sean Wang
7261a14368 feat: impl AsRef<Window> and on_webview_event for WebviewWindow (#14012) 2025-08-16 11:01:53 +08:00
Sean Wang
0e6b5cbe5f feat(tauri): re-export PixelUnit, PhysicalUnit, LogicalUnit (#14009)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-08-15 15:24:34 +02:00
Sean Wang
a3dc42477a feat(tauri): export TitleBarStyle for all platforms (#14013) 2025-08-15 15:13:05 +02:00
Sean Wang
21ebc6e820 feat(tauri): remove 'static lifetime bound from AppHandle::remove_plugin (#14007) 2025-08-15 15:28:39 +08:00
Lucas Fernandes Nogueira
2d5f5a9230 chore: update tests (#13998) 2025-08-13 13:34:01 -03:00
Fabian-Lars
4475e93e13 feat(bundler/cli): Add feature flag to use system certificates (#13824) 2025-08-12 13:30:23 +02:00
Naman Khandelwal
5110a762e9 feat(window): add macOS window::set_simple_fullscreen (closes #13670) (#13830)
* add implementation of set_simple_fullscreen

* add simple fullscreen API for macos

* register desktop command

* format

* fix errors

* chore: format

* change implementation

* add api

* fix tests

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-12 08:03:29 -03:00
Fabian-Lars
a9ec12843a feat: add option to not wait on notarization to finish (#13521)
* feat: add option to not wait on notarization to finish

* cli arg istead of config

* changefile

* fix serde

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-08-11 14:29:41 -03:00
Tony
f0dcf9637c fix(cli): add single-instance autostart init code (#13980) 2025-08-11 19:40:18 +08:00
Tony
196ace3c04 fix: return error on window creation failed (#13970)
* fix: return error on window creation failed

* Add todo about adding error inside `CreateWindow`
2025-08-09 22:43:18 +08:00
Aly Cerruti
82e264552e fix(windows): fix double free (STATUS_HEAP_CORRUPTION) of resizing handler's userdata (#13968)
* fix: double free of resizing handler's userdata on Windows

Using WM_NCDESTROY instead of WM_DESTROY is more correct for freeing userdata, as windows can receive multiple WM_DESTROY events if they're parented.

* chore: add change entry for resizing handler double-free fix
2025-08-09 12:03:21 +08:00
Tony
c134a769ea chore: fix some warnings on new rust version (#13965)
* chore: fix some warnings on new rust version

* No main

* allow dead code on specta Channel
2025-08-09 08:19:03 +08:00
Fabian-Lars
390cb9c36a fix(cli): reduce log level for goblin and handlebars (#13953) 2025-08-07 14:40:41 +02:00
Jaken Herman
9300b59f65 feat: Added fips_compliant field to WixConfig (#13787)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-08-05 20:35:25 +02:00
Jadon Jesse
e1d7be8e57 fix(example): runtime crash when counter less than 0 (#13955) 2025-08-05 18:45:49 +02:00
renovate[bot]
90c1c327ac chore(deps): update dependency cross-env to v10 (#13894)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-05 17:15:22 +02:00
renovate[bot]
83032e273b chore(deps): update rust crate which to v8 (#13711)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-08-05 14:59:02 +02:00
Tony
a8f1569b04 fix(windows): bundler should not sign non-binaries (#13921)
* fix(windows): bundler should not sign non-binaries

* Fix non Windows
2025-08-05 11:06:43 +08:00
Tony
0ea08e901e fix(example): unminimize window on tray icon click (#13949) 2025-08-05 10:07:16 +08:00
Fabian-Lars
887b8da684 fix(bundler): improve log format of sign command stdout (#13947) 2025-08-04 15:38:56 +02:00
Tony
7d21e3b2fa docs: how security > capabilities works (#13946)
* docs: how `security > capabilities` works

* Add how to use it

* Apply suggestions

* Relative to `Cargo.toml`

* Remove the relative base wording
2025-08-04 18:13:02 +08:00
Sam Lidder
4d270a96a8 fix(windows): patch_binary causing codesigning verification failure (#13943)
* fix(windows): `patch_binary` causing codesigning verification failure

* `cargo fmt`

* add change file

* Update .changes/fix-binary-patching-codesign-verification-failure.md

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-08-04 16:58:04 +08:00
renovate[bot]
bcc7a82a3a chore(deps): update rust crate notify-debouncer-full to 0.6 (#13945)
* chore(deps): update rust crate notify-debouncer-full to 0.6

* Bump jsonschema
2025-08-04 10:39:34 +08:00
Fabian-Lars
8b465a12ba fix(bundler/linux): pull latest appimage plugin (#13913) 2025-07-31 20:06:57 +02:00
Tony
ee68c918a1 chore(deps): unpin serialize-to-javascript (#13932) 2025-07-31 17:52:51 +08:00
renovate[bot]
d7075b66bd chore(deps): update rust crate toml to 0.9 (#13784)
* chore(deps): update rust crate toml to 0.9

* Bump toml_edit and cargo_toml

* Update tauri-winres

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-31 17:14:09 +08:00
xeodus
bbcea1f5e8 fix(cli): improve error messages regarding cargo metadata command (#13918) 2025-07-30 11:23:54 +02:00
Pavel Kuzmin
5ba1c3faa4 feat(menu): add icon support for Submenu in Rust and JS/TS APIs (#13722)
* feat(menu): add icon and nativeIcon support for Submenu in tauri and @tauri-apps/api

* Merge branch 'dev' into dev

* Update muda

* feat(menu): add set_icon and set_native_icon methods to set submenu icons

* feat(menu): unify icon handling by introducing MenuIcon type

* chore: sync bundle.global.js

* Make setIcon actually work

* Regenerate `bundle.global.js`

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-30 13:48:55 +08:00
renovate[bot]
e27427f795 chore(deps): update dependency rollup to v4.46.2 (#13914)
* chore(deps): update dependency rollup to v4.46.2

* Bump @eslint/plugin-kit

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-30 09:39:22 +08:00
renovate[bot]
a32a4ce3be chore(deps): update rust crate jsonschema to 0.32 (#13915)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-30 09:26:04 +08:00
Andrew Voynov
bc6b125b24 fix(bundler): replace empty RPM release value with 1 (#13909)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-07-29 22:20:25 +02:00
Takeaki Kobayashi
9c938be452 fix(cli): properly migrate svelte to v5 in the plugin example template (#13912)
* fix: update vite.config.ts to support Svelte 4 in example app

* Migrate the code to svelte 5 instead

* Add change file

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-29 17:47:17 +08:00
renovate[bot]
5c8182860c chore(deps): update rust crate jsonschema to 0.31 (#13903)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 23:29:31 +08:00
renovate[bot]
1d31e4647c chore(deps): update dependency rollup to v4.46.1 (#13904)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-28 15:19:30 +08:00
renovate[bot]
517e7b60e1 chore(deps): update dependency rollup to v4.46.0 (#13897)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-27 20:38:49 +08:00
Robin van Boven
72b4226ee9 feat: reduce Debug format size for binary buffers (#13809)
* feat: reduce Image debug output

For example now:
`Image { rgba: Cow::Borrowed([u8; 4096]), width: 32, height: 32 }) }`

* feat: reduce EmbeddedAssets debug size

For example now:
```
EmbeddedAssets {
    assets: {
        "/index.html": [u8; 1835],
        "/index.js": [u8; 212],
    },
    global_hashes: [
        Script(
            "'sha256-EOd6N98xxmK5s7VvxV7W2w7YG+dmP52MqNiZUq1NLeE='",
        ),
        Style(
            "'sha256-YEercZJImS+vUX2bz7vkQ0aA4rtBIPLuCEWz+yraQ/g='",
        ),
    ],
    html_hashes: {
        "/index.html": [
            Script(
                "'sha256-3g8CfFrjFLGpwD2o+hwMt+lh/hsHbQ3XY+EPJ35fFKk='",
            ),
            Script(
                "'sha256-EOd6N98xxmK5s7VvxV7W2w7YG+dmP52MqNiZUq1NLeE='",
            ),
        ],
    },
}
```

* feat: reduce `app_icon` debug size

* chore: changelog

* chore: include tauri-utils in changelog

* doc: comment had extra closing brackets [skip ci]
2025-07-25 07:55:00 -03:00
Lucas Fernandes Nogueira
d6d941c3a7 chore(cli): update plugin template (#13882) 2025-07-25 07:50:41 -03:00
Lucas Fernandes Nogueira
a0113a8c64 feat(tauri-plugin): add build::mobile::update_info_plist (#13888)
* feat(tauri-plugin): add build::mobile::update_info_plist

needed for https://github.com/tauri-apps/plugins-workspace/pull/2870

* Update .changes/update-info-plist.md
2025-07-25 07:50:24 -03:00
Jack Lavigne
91508c0b8d feat: add config option for custom watch folders (#13881)
* feat: add config option for custom watch folders

* fix: cargo clippy changes

* chore: remove file

* fix: ios dev

* docs: clarify absolute allowed

* refactor: rename variable

* fix: review suggestions

* fix: resolve paths

* fixL use canonicalize

* chore: add changefile

* chore: add error if cant canonicalize

* reformat changelog

* Update .changes/additional-watch-folders.md

* Update crates/tauri-cli/src/interface/rust.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* Revert "Update .changes/additional-watch-folders.md"

This reverts commit 98186b1a89.

* Also bump `@tauri-apps/cli`

* Apparently I'm so used to a higher rust version

* Revert "Apparently I'm so used to a higher rust version"

This reverts commit ea1d89e2d3.

* Need to check for existence for abs paths as well

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-24 22:21:00 +08:00
github-actions[bot]
fd63f229d5 apply version updates (#13871)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-22 12:32:14 +08:00
Krishna Chaitanya
af95fb6014 fix: sign main binary after patching with bundle info (fix #13868) (#13870)
* fixed #13868

* add main binary singing only on windows

* updated readme message
2025-07-22 11:32:49 +08:00
FabianLars
65bb24b9ae fix(cli): fix metadata version 2025-07-21 10:10:12 +02:00
FabianLars
332ec355a1 fix(cli): add default triplets to napi targets config 2025-07-21 09:59:32 +02:00
renovate[bot]
2c46b1873e chore(deps): update dependency eslint-config-prettier to v10.1.8 (#13855)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-21 10:23:19 +08:00
FabianLars
96439c2c42 chore(deps): Update @eslint/plugin-kit to fix pnpm audit 2025-07-21 00:37:41 +02:00
github-actions[bot]
ab97f36b64 apply version updates (#13751)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-07-21 00:09:52 +02:00
Tony
6a4451bcd9 fix(windows): isolation pattern create iframe loop (#13849) 2025-07-20 23:33:14 +02:00
Tony
56277e4722 chore(deps): update napi to v3 (#13852) 2025-07-20 23:03:51 +02:00
Fabian-Lars
7a6fd5b75d fix(bundler): Move AppRun to mirror (#13863) 2025-07-20 23:00:19 +02:00
Sean Wang
7f3c989111 feat(tauri): add plugin_boxed methods (#13837)
* feat(tauri): add `plugin_dyn` methods

* refactor: rename `plugin_dyn` to `plugin_boxed`
2025-07-18 11:48:10 +08:00
Tony
bda8304107 fix(cli): error out when migrating from v2 alpha (#13833) 2025-07-16 22:06:17 +08:00
Fabian-Lars
fb9d9c7fd1 chore(readme): Update discord invite (#13836) 2025-07-16 11:02:23 +02:00
renovate[bot]
8263b412c6 chore(deps): update dependency rollup to v4.45.1 (#13831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-15 23:10:12 +08:00
Siddharth
3025d90951 feat: expose some window props from runtime-wry (#13822)
* test: make some of window id + stores public

* test: make window wrapper label pub

* feat: make label accessible for windowwrapper

* chore: adds wry runtime changefile

* chore: avoid forced clone on label

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-07-15 14:32:19 +08:00
Joseph Brooksbank
96391467e9 feat(mock): add mock for listen and emit (#13783)
* feat(mock): add mock for listen and emit
* feat(mock): add mock for listen and emit

* feat(mock): add mock for listen and emit

* Add change file

* correctly clear unregisterListener

* format with prettier

* build project

* opt-in to mocking events

* Use a minor bump
2025-07-15 09:30:01 +08:00
kandrelczyk
c0a654b863 failed binary patch warning (#13825)
* failed binary patch warning

* Update crates/tauri-bundler/src/bundle.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-07-14 22:24:11 +08:00
Lucas Raposeiras
b821796add docs: add missing trafficLightPosition to WindowOptions (fix #13790) (#13810)
* docs: add missing `trafficLightPosition` to `WindowOptions`

* Change file and tweak docs

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-13 20:58:39 +08:00
Mohammad Hossein Bagheri
33d079392a feat(cli): allow runner configuration to be an object with cwd and args (#13811)
* Update config.schema.json

* Add RunnerConfig for customizable build runner

Replaces runner String with RunnerConfig in CLI and config, allowing advanced runner configuration via string or object with cmd, cwd, and args. Updates schema and usage to support new format, and adds tests for serialization, deserialization, and API. Enables more flexible build and run command customization.

* Create runner-object-config.md

* Remove unused RunnerConfig import in tests

Cleaned up the test module in config.rs by removing the unused RunnerConfig import from two test functions.

* Fix tests failing

Updates related tests in tauri-utils to improve readability and maintain consistency. Minor import reordering in tauri-cli for clarity.

* Move RunnerConfig enum and impls above BuildConfig

Relocated the RunnerConfig enum and its associated implementations to appear before the BuildConfig definition. This improves code organization and logical grouping of configuration-related types.
2025-07-13 19:28:09 +08:00
Tony
7bc77a038a feat: allow all frame init scripts in plugin (#13609)
* feat: allow all frame init scripts in plugin

* Add change files

* Update crates/tauri/src/plugin.rs

Co-authored-by: Fabian-Lars <github@fabianlars.de>

* Default impl initialization_script_2 from 1

* Update crates/tauri/src/plugin.rs

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2025-07-13 14:12:39 +08:00
kandrelczyk
371ee34383 make static bundle type var mutable (#13812)
* make static bundle type var mutable

* remove unsafe from no_mangle and link_section
2025-07-12 18:48:13 +08:00
renovate[bot]
22cd1e2846 chore(deps): update dependency rollup to v4.45.0 (#13813)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-12 17:55:16 +08:00
M
1c5df96fe8 fix(protocol): proxy body in mobile dev (#13773)
* proxy body in mobile dev

* add change file, use std::mem::take

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-07-11 07:22:46 -03:00
kandrelczyk
4f96ed41ca add #[used] to __TAURI_BUNDLE_TYPE so that it's not stripped in release builds (#13808) 2025-07-11 15:52:37 +08:00
renovate[bot]
24eb2b1cd3 chore(deps): update dependency @sveltejs/vite-plugin-svelte to v6 (#13803)
* chore(deps): update dependency @sveltejs/vite-plugin-svelte to v6

* Bump vite

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-07-11 13:22:46 +08:00
Lucas Fernandes Nogueira
0f248b111f fix(cli): install iOS dependencies when needed (#13799)
currently deps are only installed on init, which might not be executed on someone's machine if the xcode project is commited to the repo. we need to ensure dependencies are installed before running them

applies https://github.com/tauri-apps/cargo-mobile2/pull/468
2025-07-10 10:17:23 -03:00
Lucas Fernandes Nogueira
4ba871c5d2 fix(core): loading remote URLs on mobile, closes #13461 (#13782) 2025-07-09 17:08:38 -03:00
Catalin Andrei Cacuci
f94af90359 fix(nsis): per-machine installer not requesting elevation when run by non-admin users (#13786) 2025-07-09 13:42:07 +02:00
Tony
cfc5bb8196 feat(android): edge to edge in init template (#13780)
* feat(android): edge to edge in init template

* Add androidx.activity:activity-ktx

* androidx.webkit:webkit:1.14.0
2025-07-09 10:05:27 +08:00
Lucas Fernandes Nogueira
916aeaa486 fix(cli): android commands reading iOS config closes #13765 (#13781) 2025-07-08 08:49:47 -03:00
Jeong Min Oh
12e3590613 Fix(package.json) build script, Fix(android) build template (#13759)
* Update compileSdk targetSdk, Fix build cmd

* Add changelog

* Update AGP version

* Update package.json

* Update AGP

* Update SDK

* Update

* Update .changes/update-android-sdk.md

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* Use changes tag in change file

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-07-08 17:00:26 +08:00
kandrelczyk
232265c70e feat: bundle type detection at runtime via binary patching (#13209)
* patch binary with bundle type info

* only patch if the updater is included

* fix linux warnings

* patch binary when updaer is configured

* patch binary with bundle type info

only patch if the updater is included

fix linux warnings

patch binary when updaer is configured

* fix formatting

* fix license header

* fix taplo error

* move __TAURI_BUNDLE_TYPE to utils

* export get_current_bundle_type

* macos fix

* cleanup, add api

* update change file

* fix windows

* fmt, fix rust version support

* fix macos

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-07-07 12:08:00 -03:00
renovate[bot]
02440b875c chore(deps): update dependency rollup to v4.44.2 (#13766)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-06 20:39:00 +08:00
Catalin Andrei Cacuci
f2dbe73097 fix(nsis): wrong required files path for nsis_tauri_utils.dll (#13772)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-07-05 23:42:25 +02:00
Tony
152d971bcd fix(mock): expose callback functions (#13744)
* fix(mock): expose callback functions

* Add change file

* Bumped the wrong package

* Fix end quote in comment
2025-07-02 22:23:23 +08:00
Jeong Min Oh
acd7574284 fix(cli/ios): fix CFBundleVersion type (#13743)
Co-authored-by: devfive <devfive@devfiveui-MacStudio.local>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-07-02 16:01:59 +02:00
renovate[bot]
e296e4bc38 chore(deps): update dependency @rollup/plugin-typescript to v12.1.4 (#13729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-30 14:07:17 +02:00
AprilNEA
11b4a03881 fix(cli): remove unnecessary files in npm package, closes #12139 (#13735)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-06-30 14:02:03 +02:00
github-actions[bot]
0277596341 apply version updates (#13731)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-06-28 17:48:13 -03:00
Lucas Fernandes Nogueira
cbd9629729 fix(cli): load --config values on xcode and android-studio scripts (#13730) 2025-06-28 17:16:36 -03:00
FabianLars
0079d08ba9 chore(worker): Enable observability 2025-06-27 17:20:01 +02:00
FabianLars
effd106adf fix(worker): Fix route syntax 2025-06-27 17:14:34 +02:00
github-actions[bot]
4053ad1b58 apply version updates (#13724)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-06-27 16:22:27 +02:00
Fabian-Lars
f010ca5e91 fix(core): compile error without common-controls-v6 (#13719) 2025-06-27 15:54:10 +02:00
Fabian-Lars
6b2b9d6cbf chore: clippy 1.88 (#13720) 2025-06-27 15:33:36 +02:00
renovate[bot]
b6de1c89c2 chore(deps): update rust crate md5 to 0.8 (#13712)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-06-26 16:29:19 +02:00
renovate[bot]
a3ae2cebbf chore(deps): update rust crate rand to 0.9 (#13700)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-06-26 15:47:42 +02:00
github-actions[bot]
a3f11b4f3b apply version updates (#13693)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-06-26 20:47:38 +08:00
Fabian-Lars
4b7370e9e0 fix(cli): fix rollup-plugin-typescript v12 compatiblity (#13710)
* fix(cli): fix rollup-plugin-typescript v12 compatiblity

* always the same mistake
2025-06-26 20:13:05 +08:00
Tony
5bbcaaec89 fix: can't set tray menus and icons in js (#13707) 2025-06-26 19:42:01 +08:00
renovate[bot]
3eb3162404 chore(deps): update rust crate muda to 0.17 - tray-icon to 0.21 (#13695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-06-26 12:31:00 +02:00
renovate[bot]
0cbfd8923c chore(deps): update dependency rollup to v4.44.1 (#13696)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-26 15:33:56 +08:00
montyc1999
0a552a868c fix(macros): cache rustc -V output (#13690) 2025-06-26 10:48:52 +08:00
renovate[bot]
560067cd7e chore(deps): update rust crate getrandom to 0.3 (#13685)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-06-25 23:05:29 +02:00
Fabian-Lars
6a4ea10274 fix(worker): add workaround to fix build on rust 1.87 2025-06-25 22:19:47 +02:00
Fabian-Lars
349bbfc5c7 chore(deps): update axum to 0.8 and worker to 0.6 (#13677) 2025-06-25 20:57:52 +02:00
Fabian-Lars
32a84650c0 ci: disable renovate for 1.x branch (#13673) 2025-06-25 17:36:07 +02:00
Tony
b19f16aba1 ci: enable create-pull-request sign commits (#13668) 2025-06-25 15:50:45 +02:00
github-actions[bot]
594822aa55 Apply Version Updates From Current Changes (#13282)
* apply version updates

* minor bump for build, plugin, macros and runtime

---------

Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-06-24 15:50:44 -03:00
Lucas Nogueira
e4aa35e083 fix(cli): init tests 2025-06-24 15:02:22 -03:00
sftse
9c16eefa31 Update kuchikiki, html5ever, tao, wry, webview2-com (#13629)
* fix: dont depend on private schemars api

* tauri-cli/deps: update kuchikiki and html5ever
tauri-utils/deps: update kuchikiki and html5ever
tauri-runtime-wry/deps: update wry to match kuchikiki and html5ever versions

* fix: specify exact patch version of schemars

Without this, cargo resolves the patch version of schemars to one that
does not include the _private module on which tauri-utils v1 depends,
which is a dependency of tauri-cli. As a result of this, the build breaks.

* tauri-utils/fix: inline tauri-utils v1 config module

* deps: upgrade and pin schemars 0.8.21 to pick up crate patch in Cargo.toml

* update tao, wry

* lint, license

* lint

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-06-24 14:39:20 -03:00
Lucas Fernandes Nogueira
3242e1c946 feat(cli): allow passing Cargo commands to mobile dev/build commands (#13659)
* feat(cli): allow passing Cargo commands to mobile dev/build commands

* fmt
2025-06-23 14:47:21 -03:00
Lucas Fernandes Nogueira
4a880ca697 feat(cli): synchronize productName changes with iOS Xcode project (#13658)
* feat(cli): synchronize productName changes with iOS Xcode project

* fmt
2025-06-23 14:47:10 -03:00
Lucas Fernandes Nogueira
d1ce9af628 feat(cli): add --config arg to the mobile init cmds, closes #13284 (#13660) 2025-06-23 12:55:07 -03:00
Lucas Fernandes Nogueira
ec6065fa4a fix(cli): use original identifier to fix mobile options reading (#13625)
* fix(cli): read original identifier to fix mobile options reading

the iOS and Android CLI commands leverage an android_studio_script/xcode_script that is executed by the native IDE or build tool. This script reads the Tauri configuration to find the app identifier used to communicate with the parent Tauri CLI process to read CLI options.

The communication is broken when the `--config` arg is used, since the IDE script does not have access to that value before reaching the parent process, which is impossible without knowing the actual identifier used.

To bypass this we'll agree on using the original identifier. This obviously won't work if the original tauri.conf.json do not have an identifier, so we error out in this case

* fix build, lint
2025-06-23 09:29:46 -03:00
Tony
18b5299952 docs: where does resource dir resolve to (#13640)
* docs: where does resource dir resolve to

* Add note about potential change
2025-06-21 10:22:24 +08:00
Tony
eb3f0248c2 fix: write default permission words if not empty (#13646)
* fix: write default permission words if not empty

* Remove left over format!
2025-06-21 09:52:36 +08:00
Tony
c03cc586e3 chore: check generated file on package lock change (#13641)
* chore: check generated file on package lock change

* Build bundle.global.js

looks like it's already outdated
2025-06-20 20:13:16 +08:00
renovate[bot]
488bcea970 chore(deps): update dependency rollup to v4.44.0 (#13635)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-19 19:20:17 +08:00
kandrelczyk
d48e7a39a7 chore: improve contributing guide (#13594) 2025-06-18 11:34:19 +02:00
renovate[bot]
221254738a chore(deps): update dependency @rollup/plugin-typescript to v12.1.3 (#13628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-17 23:43:38 +08:00
Naman Khandelwal
9fb0586909 fix(cli) : final changes for macOS identifier issue (fix #12674) (#13627)
* fix(cli) : final changes for macOS identifier issue

* chore:formatted the code
2025-06-17 12:18:50 -03:00
Naman Khandelwal
8ee14a8648 fix(cli): prevent .app identifier (fix #12674) (#13618)
* fix(cli): prevent .app identifier

* chore(cli): changed warn log of non macOS

* Add change file

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-06-16 23:48:54 +08:00
renovate[bot]
0f0d6a4e02 chore(deps): update rust crate windows-sys to 0.60 (dev) (#13616)
* chore(deps): update rust crate windows-sys to 0.60

* Fix compile and update lock file

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-06-16 17:58:29 +08:00
Tony
f9bdb9b230 fix: failing scope test on Windows (#13596) 2025-06-11 15:10:25 +02:00
renovate[bot]
f34acf161d chore(deps): update dependency rollup to v4.43.0 (dev) (#13604)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-06-11 14:52:46 +02:00
Emmanuel Ferdman
87b3cdce48 fix: resolve typos in schema (#13591)
* fix: update `English.nsh` reference

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

* fix: resolve typos in schema

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

* Generate schema

---------

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-06-08 00:50:10 +08:00
renovate[bot]
aa1131a047 chore(deps): update dependency rollup to v4.42.0 (#13583)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 23:10:34 +02:00
Pierre de la Martinière
bd8a7cf39d fix(bundler/linux): fix app icon not showing on Gnome+Wayland (#5258) (#13581) 2025-06-06 22:46:24 +02:00
Tony
f1891540bf refactor: simplify future in command IPC structs (#13529) 2025-06-04 20:32:51 +08:00
renovate[bot]
d15da3daae chore(deps): update rust crate duct to v1 (dev) (#13397)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-06-03 16:54:27 +02:00
Tunglies
414619c36e feat: add bundleName field to schema and MacConfig (#13110) (#13536) 2025-06-03 15:44:49 +02:00
Fabian-Lars
25757fece4 chore(cli): Remove outdated licensing errata in readme (#13548) 2025-06-03 13:58:40 +02:00
Tony
78d15e892d fix(windows): allow web fullscreen APIs to work (#13558)
* fix(windows): allow web fullscreen APIs to work

* tauri-runtime-wry not tauri-wry

* Remove last clone

* Change file on windows
2025-06-03 19:04:14 +08:00
Tony
6a39f49991 refactor: dynamic dispatch async commands in debug (#13464)
* Dynamic dispatch async commands

* format

* Preserve `'static`

* Use a inner function instead

* Only do it for dev for now

* Add change file

* Tag respond_async_serialized_dyn with debug
2025-05-29 22:02:56 +08:00
Tony
a35600cbd7 docs: fix setAutoResize typo (#13526) 2025-05-29 17:54:22 +08:00
Tunglies
1c53640ac3 fix(schema): update hardened_runtime description to include link (#13512) 2025-05-27 17:38:18 +02:00
Amr Bashir
e7f2d8cba4 chore: remove leftover in utils.nsh (#13507) 2025-05-26 06:20:31 +03:00
Amr Bashir
7322f05792 feat(nsis): allow using CheckIfAppIsRunning macro inside NSIS hooks (#13502) 2025-05-25 23:03:10 +03:00
renovate[bot]
06c75fd98b chore(deps): update dependency rollup to v4.41.1 (#13499)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-24 21:37:42 +08:00
Lucas Fernandes Nogueira
c8a30a61d2 fix(core): capability filtering crashing allowed command generation (#13476)
* fix(core): capability filtering crashing allowed command generation

tauri-plugin and tauri build scripts cannot have access to the capabilities file (generated by tauri-build) and can only infer capabilities from the config path

* cleanup

* unused import

* followup

* fix reassign

* mut

* Update crates/tauri-utils/src/acl/build.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-05-22 07:45:32 -03:00
renovate[bot]
650c91c114 chore(deps): update rust crate zip to v4 (#13487)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 09:11:50 +08:00
Lucas Fernandes Nogueira
5a5291d66c fix(cli): use platform name to detect iOS architecture to build (#13483) 2025-05-21 14:12:44 -03:00
renovate[bot]
dbcfaa18d7 chore(deps): update dependency rollup to v4.41.0 (#13467)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 09:10:35 +08:00
WofWca
923b7c7bc6 docs: fix build instructions somewhat (#13463) 2025-05-18 20:43:49 +02:00
Tony
626165eeb4 fix: mock context without dynamic-acl feature (#13455) 2025-05-17 18:08:53 +08:00
Kingsword
638804e9c4 fix: ensure set_window_effects runs on main thread in WindowBuilder (#13422) (#13423)
Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-05-16 23:38:12 +02:00
Tony
1686296463 refactor: put dynamic acl to a feature (#13418)
* refactor: put dynamic acl to a feature

* Add change file

* Tweak remove_unused_commands's docs

* License header

* Document the feature

* Merge remote-tracking branch 'upstream/dev' into dynamic-acl-feature

* Use a inner non generic fn for add_capability

* Clippy and macro stability notice

* Merge remote-tracking branch 'upstream/dev' into dynamic-acl-feature

* Format
2025-05-16 22:54:23 +08:00
dependabot[bot]
85baacd18b chore(deps): bump undici from 5.28.5 to 5.29.0 (#13450)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-05-15 18:41:01 +02:00
Tony
c31c75fffc docs: fix missing docs for a few methods (#13449) 2025-05-16 00:17:28 +08:00
renovate[bot]
9687a9b4fb chore(deps): update rust crate zip to v3 (#13445)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 15:25:25 +08:00
Tony
4acae1ec02 fix(macos): run app.set_theme on main thread (#13443)
* fix(macos): run `app.set_theme` on main thread

* Change file
2025-05-15 15:13:23 +08:00
Tony
d38d90b8d9 refactor: reduce the code in macro pass (#13441) 2025-05-15 09:26:49 +08:00
Tony
b52da29d5d fix: main binary name can't contain dots (#13429)
* fix: main binary name can't contain dots

* Revert the change in tauri.conf.json

* Change file

* Use target platform when matching extension
2025-05-14 16:50:12 +08:00
Tony
574a4d4d36 fix(cli): slow dev startup (#13426)
* fix(cli): slow dev startup

* Use `recv_timeout` instead

* Update crates/tauri-cli/src/interface/rust.rs

Co-authored-by: Fabian-Lars <github@fabianlars.de>

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-05-14 16:48:05 +08:00
Tony
1777406a16 chore: apply some clippy suggestions (#13424) 2025-05-13 14:18:24 +08:00
MidnightCrowing
d3586a2afa docs(api): fix incorrect example and clarify description for dirname in path API docs (#13417) 2025-05-12 16:35:35 +08:00
Tony
b7cdb3b39e chore: feature gate html manipulation code (#13410)
* Feature gate html manipulation code

* Change file
2025-05-11 00:13:19 +08:00
Amr Bashir
96ecfca428 feat: check if webview runtime is accessible when creating a webview (#13406) 2025-05-10 06:00:09 +03:00
dependabot[bot]
0e616dbbcb chore(deps): bump ring from 0.17.8 to 0.17.14 (#13409)
Bumps [ring](https://github.com/briansmith/ring) from 0.17.8 to 0.17.14.
- [Changelog](https://github.com/briansmith/ring/blob/main/RELEASES.md)
- [Commits](https://github.com/briansmith/ring/commits)

---
updated-dependencies:
- dependency-name: ring
  dependency-version: 0.17.14
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-05-10 09:58:21 +08:00
Oscar Beaumont
bc2f0e48ac fix(macOS): caculation for work area (#13401)
* remove y offset

* Create change-pr-13401.md
2025-05-09 08:36:12 -03:00
renovate[bot]
efcc840ff0 chore(deps): update dependency eslint-config-prettier to v10.1.5 (#13403)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 15:27:18 +08:00
Fabian-Lars
7897ed257d fix(cli): don't canonicalize cargo's target dir in frontendDist verification (#13392) 2025-05-07 23:00:24 +02:00
renovate[bot]
1a018878ab chore(deps): update dependency eslint-config-prettier to v10.1.3 (#13387)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 21:17:19 +08:00
renovate[bot]
e15f665efc chore(deps): update dependency rollup to v4.40.2 (#13381)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 20:12:53 +08:00
Fabian-Lars
479cee3d36 fix(bundler): set ARCH env var for appimagetool (#13260) 2025-05-06 08:48:56 -03:00
39zde
09c19932d2 feat: add support for Service-Woker-Allowed HTTP header (#13304)
* add support for Service-Worker-Allowed headers

* add changes readme

* add service_worker_allowed in to_tokens
2025-05-06 08:15:19 -03:00
Tony
4221124c4e fix: use app's resource table for storing tray icons (#13316)
* Use app's resource table for storing tray icons

* Clean up

* Move remove tray logic to Resource::close
2025-05-06 08:11:49 -03:00
Lucas Fernandes Nogueira
b985eaf0a2 fix(core): immediately unregister event listener on unlisten call (#13306)
* fix(core): immediately unregister event listener on unlisten call

the unlisten function is currently async, but marked as `() => void` in the TypeScript definition. To avoid a breaking change, we're going to immediately unregister the listener function so it's not called.

this fixes a race condition where after calling unlisten() you would still receive events if you do not `await` it and there's a new event triggering while the unlisten command is running

* cleanup

* fix build

* fix ci
2025-05-05 10:46:05 -03:00
Miguel Duarte
c84b162374 docs: Fix description and add example for WebviewWindowBuilder::from_config (#13374)
* Update docs for WebviewWindowBuilder::from_config

The documentation for `WebviewWindowBuilder::from_config` mentions changing the label of the new `WebviewWindowBuilder`, which is not possible.

Instead, the label must be changed in the `WindowConfig` that is passed into `WebviewWindowBuilder::from_config`.

This change fixes that description and adds an example code snippet for this use-case.

* Add reference to function arguments so the type is correctly inferred

* Remove unnecesary reference

* fix tests

* fix doctest

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-05-05 09:37:53 -03:00
geeseofbeverlyroad
4f75bf5bdb docs: Added more detailed comments to menu popup method and DPI-related classes (#13368)
* Detailed function description for popup()

* Expanded DPI class descriptions

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-05-05 09:25:30 -03:00
Tony
b5c549d189 refactor: rework transformCallback (#13325)
* refactor: rework `transformCallback`

* Migrate listen and unlisten js

* handlerId -> listener.handlerId

* Update docs

* `transformCallback` change file

* typo
2025-05-05 09:15:38 -03:00
Daniil Oberlev
208f4bcadc changed operator in vite.config.js (#13373)
Prefer using nullish coalescing operator (`??`) instead of a logical or (`||`), as it is a safer operator.
2025-05-04 03:56:28 +03:00
Lucas Fernandes Nogueira
f0662e41f4 fix(tauri-runtime-wry): window prevent overflow monitor check (#13365) 2025-05-03 14:31:43 -03:00
Matthew Richardson
dfacb656d2 fix: Can't register multiple plugin listeners for an event (#13360)
* fix: Can't register multiple listeners for an event

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-05-02 15:43:47 -03:00
Tony
db03f00693 refactor: use WindowConfig for create_webview (#13322)
* refactor: use WindowConfig for `create_webview`

* Pass in label inside options

* Fix compile
2025-05-01 09:43:25 -03:00
Lucas Nogueira
a60a383360 chore(ci): tweak workflow name reference in paths list 2025-05-01 09:20:52 -03:00
Tony
aa8661acfd chore(deps): bump js dependencies (#13355) 2025-05-01 11:29:35 +02:00
Lucas Fernandes Nogueira
e045fe32c9 fix(bundler): custom sign command failing to sign uninstaller executable (#13334) 2025-04-30 15:21:14 -03:00
Kingsword
197da6fe78 docs(window): monitorFromPoint example error (#13340) 2025-04-30 03:24:32 +03:00
Oscar Beaumont
94b77b36e3 fix: use format_callback::format_raw for channels (#13288)
* fix it

* Create change-pr-13288.md

* fixes

* fixes

* fix .change
2025-04-29 08:45:22 +08:00
renovate[bot]
527bf0031e chore(deps): update dependency rollup to v4.40.1 (#13328)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 15:03:27 +08:00
Kingsword
35aa7e1218 fix(cli): Allow the use of target dir inside frontendDist/distDir (unless it's cargo's target dir) (#13294)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-04-27 21:37:50 +02:00
Kingsword
23b9da75b9 fix path joining behavior where path.join('', 'a') incorrectly returns "/a" instead of "a" (#13313) (#13324)
* fix path joining behavior where path.join('', 'a') incorrectly returns "/a" instead of "a" (#13313)

* Clean up

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-27 14:18:27 +08:00
Neriya Cohen
8a8c1f9f3b fix(windows): typos in Hebrew translation for NSIS installer (#13317) 2025-04-27 11:09:20 +08:00
Kingsword
50ebddaa2d feat: expose the setAutoResize API for webviews in @tauri-apps/api (#13318) (#13319) 2025-04-27 10:27:23 +08:00
Lucas Fernandes Nogueira
568efb4568 fix: follow-up fix for monitor work area on macOS (#13310)
follow-up for #13309
2025-04-26 15:03:35 -03:00
Lucas Fernandes Nogueira
6ce10ab773 fix: monitor work_area on macOS (#13309)
macOS uses a different coordinate system for visibleFrame, so to get accurate values we should only get the diff between frame() and visibleFrame() and apply that to the standard monitor position returned by CGDisplayBounds. Size isn't impacted by this, and properly returns the value (accounting for dock position).
2025-04-25 20:08:46 -03:00
Lucas Fernandes Nogueira
039f44b7b1 fix(core): fix TrayIcon.getById returning new resource IDs (#13307)
* fix(core): fix TrayIcon.getById returning new resource IDs

this prevents the close() from working properly if you somehow lose the new() resource ID (for instance when the app reloads) and need to pick it up again and close it.

* cleanup on close
2025-04-25 15:30:53 -03:00
situ2001
00dfc32a2d docs(webview): corrected examples to ensure webview is created after window initialization (#13279)
* fix: typo

* docs(webview): corrected examples to ensure webview is created after window initialization
2025-04-23 04:56:52 +02:00
situ2001
76cbeef208 fix: add proxy URL support to Webview at Rust-side. (#13278)
* fix: add proxy URL support to Webview

* chore: add .changes file

* Change file
2025-04-23 09:38:43 +08:00
Amr Bashir
267368fd4f feat: add workarea getter for monitor (#13276) 2025-04-23 03:29:03 +02:00
situ2001
4e00b27913 docs: update example for in webview ts api (#13272) 2025-04-21 18:15:14 +02:00
github-actions[bot]
766bccc341 apply version updates (#13243)
Co-authored-by: amrbashir <48618675+amrbashir@users.noreply.github.com>
2025-04-21 05:54:30 +02:00
Amr Bashir
31becbd1d1 enhance(core): respect data-tauri-drag-region="false" (#13269) 2025-04-21 05:03:54 +02:00
Tony
da2a6ae5e3 fix(core): raw channel message type regression (#13268)
* Fix raw channel message type regression

* Re-word change file

* Rename formated_bytes to bytes_as_json_array
2025-04-21 10:26:00 +08:00
renovate[bot]
87fdc3b9cd chore(deps): update rust crate jsonschema to 0.30 (#13249)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 20:37:48 +08:00
renovate[bot]
30e76c7d3a chore(deps): update rust crate brotli to v8 (#13264)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-20 20:23:13 +08:00
Tony
85b1912529 Make tauri-runtime-wry optional with features (#13241) 2025-04-16 14:50:11 +08:00
Lucas Fernandes Nogueira
82da4f17f5 fix(ci): ubuntu 20.04 no longer exists (#13240) 2025-04-15 17:45:05 -03:00
github-actions[bot]
977c4b496c apply version updates (#13123)
Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
2025-04-15 14:42:44 -03:00
Lucas Nogueira
48b12b4404 chore: bump crates depending on tauri-utils as minor 2025-04-15 14:18:15 -03:00
Lucas Fernandes Nogueira
9356fa15d8 feat(core): include type name in state panic message (#13239)
* feat(core): include type name in state panic message

* tweak message
2025-04-15 14:15:45 -03:00
Kingsword
2dccfab532 fix: fileAssociations missing LSHandlerRank on macOS (#13159) (#13236) 2025-04-15 13:45:46 -03:00
Lucas Nogueira
5d3687e8c3 chore(tauri-driver): update README 2025-04-15 13:44:07 -03:00
Lucas Fernandes Nogueira
0cf2d9933f fix(tauri-driver): append .exe ext on app path on Windows, closes #11317 (#13238) 2025-04-15 13:43:19 -03:00
Tony
1734273bbe fix: using center and overflow together crashes (#13235) 2025-04-15 16:59:01 +08:00
Tony
690146e311 fix(macros): invoke handler stack overflow (#13217)
* Fix invoke handler stack overflow

* Format and inline iife in release build

* Add change file

* The comment should be one level up
2025-04-14 18:52:23 -03:00
Tony
f888502fd2 fix(core): use Headers in sendIpcMessage (#13227)
* Use `Headers` in `sendIpcMessage`

* Add change file

* Change files

* Don't use optional chaining
Seems like we have changed it in #9530 deliberately,
so preserving it in this change

* do not let the tauri headers to be overwritten

Co-authored-by: Sean Wang <126865849+WSH032@users.noreply.github.com>

* use HeadersInit on the type definition

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Co-authored-by: Sean Wang <126865849+WSH032@users.noreply.github.com>
2025-04-14 17:58:20 -03:00
Mateusz Kurowski
577c7ffc45 fix(webdriver): windows: make native webdriver close with parent process (fix #8610) (#10108)
* fix(webdriver): windows: make native webdriver close with parent process

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-14 17:57:44 -03:00
Lucas Fernandes Nogueira
82406c61e0 feat(cli): improve iOS simulator usage and check SDK installation (#13231)
applies https://github.com/tauri-apps/cargo-mobile2/pull/453
2025-04-14 14:57:13 -03:00
Lucas Fernandes Nogueira
07953fb9c3 fix(tauri-runtime-wry): send focused events on multiwebview for Windows (#13222)
* fix(tauri-runtime-wry): send focused events on multiwebview for Windows

closes #9755

follow-up for #12014

* fix mobile build
2025-04-14 14:56:57 -03:00
thewh1teagle
8d994f60fe fix(bundler): sign DLLs (#11676)
* fix: sign nsis plugin DLLs

* also sign DLLs on unix

* fix build

* create copy of nsis dir

* always make a copy of nsis (so linux works, permission error otherwise)

* fix windows build

* fix

* to_path_buf

* also create wix copy

* remove unused toolset change

* fix unused var

* fmt

* fix wix build

* fix build

* fix plugin copy

* fix conflict

* fix file download

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-13 18:46:14 -03:00
sftse
8a1d490820 Clippy (#12485)
* fix: remove unused clones, discovered with clippy nursery lint clippy::redundant_clone

* fix: clippy

* fix: remove no longer used clippy allow directives

* more lint

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-13 08:21:34 -03:00
Lucas Fernandes Nogueira
89c6e436ea chore(api): add typescript dependency (#13220)
I noticed `pnpm ts:check` isn't working on my end, currently only works if the typescript package is globally installed
2025-04-12 22:04:40 -03:00
Neriya Cohen
b0babb6df1 Add Hebrew translation to NSIS languages (#12938)
* Create Hebrew.nsh

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 22:04:30 -03:00
Typed SIGTERM
b8f86669ab fix: make isTauri runtime-unrelated (#13145)
* Update core.ts

* Update core.ts

* Update core.ts

* lint

* build

* fix lint, add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 21:30:03 -03:00
Tony
7ed877a0ae chore(example): migrate API example to svelte 5 (#13146)
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 21:11:21 -03:00
Lucas Fernandes Nogueira
ea36294cbc feat(core): allow changing or disabling the input accessory view on iOS (#13208)
* feat(core): allow changing or disabling the input accessory view on iOS

needs https://github.com/tauri-apps/wry/pull/1544

* remove unused code

* fix imports

* lint

* fix features

* wry 0.51.2
2025-04-12 21:10:07 -03:00
Tony
0d39ff6b09 fix(core): missing core: in referenced commands (#13150) 2025-04-12 21:03:19 -03:00
Tony
ad3fd3890f feat(cli): try detect package manager from env (#13152)
* fix(cli): try detect package manager from env

* Typo
2025-04-12 21:01:06 -03:00
Lucas Fernandes Nogueira
3752fed282 feat(cli): enhance iOS bundle version formatting (#13218)
* feat(cli): enhance iOS bundle version formatting

follow-up for #13030 and https://github.com/tauri-apps/cargo-mobile2/pull/450

the bundle version validation has been updated, now it can actually handle one or two integers (e.g. `100` or `10.7`) instead of just full triple semver strings (e.g. `10.7.1`).

* lint
2025-04-12 20:51:56 -03:00
Tony
b072e2b296 feat(core): add an option for preventing window overflow (#9687)
* Add an option for preventing window overflow

* Fix shadow counted as part of the width

* Enable prevent overflow by default

* Fix crashing when margin is bigger than screen

* Config file support

* Add to ts type

* Add mac implementation

* Should be let some

* Apply suggestions from code review

Co-authored-by: Jason Tsai <jason@pews.dev>

* checked_sub -> saturating_sub

* Revert license header

* Migrate windows 0.58

* Generate schema

* Fix merge conflict

* Try casting to objc2_app_kit::NSScreen

* Add NSScreen feature

* Use cast instead of as

* fmt

* Deref first

* Wrong unsafe block

* Add change file

* Add serde alias

* More docs

* Disable prevent_overflow by default
since we can't make breaking changes anymore right now

* Remove unused default impl

* Missing pub

* Fix mock_runtime on ios

* Match PreventOverflowMargin's description

* Typo

* Apply suggestions from code review

* Move get_work_area_size to seperate files

* Unused imports

* Add prevent_overflow to WebviewWindowBuilder

* Fix mac compile

* MonitorExt is only for desktop

* Rename to work_area

* Use workarea for linux

* Missing `()`

* Convert size

* Import MonitorExt

* as u32

* Re-build API js

* Fix wrong docs for work_area

* Remove linux platform specific note

* Remove left over linux platform specific note

* Use work area API for center as well

* Fix mobile

* Clean up

* small cleanup

* fix codegen

* update docs

* fix generated

---------

Co-authored-by: Jason Tsai <jason@pews.dev>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 13:56:43 -03:00
Lucas Fernandes Nogueira
0802529031 fix(cli): iOS dev broken on Xcode 16.3, closes #13128 (#13210)
* fix(cli): iOS dev broken on Xcode 16.3, closes #13128

Looks like we cannot use the arm64-sim custom architecture on Xcode 16.3, as it incorrectly appends the -sim suffix on some clang build scripts which ends up with an invalid target triple.

Currently we do not have automation to update Xcode/Android projects, so a manual intervention is required by our users, either recreating the project or modifying it manually (the arm64-sim arch must be removed and all its references).

ref https://github.com/tauri-apps/cargo-mobile2/pull/445

* fix dev on macOS with intel chip
2025-04-12 12:50:06 -03:00
Tony
66e6325f43 fix: channel callback never cleaned up from window (#13136)
* Fix channel cb never cleaned up from `window`

* Should be `_{id}`

* Still need to manually impl clone

* Regenerate bundle.global.js

* Remove current_index from ChannelInner

* Move phantom to `Channel`

* `Channel` not `Self`

* Clean up

* Clean up

* Fix missing end quote

* Add change file

* Rename id to index to match js side

* Improve channel speed on small data

* do the same perf check for IPC responses and raw bytes

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 10:31:25 -03:00
Matthew Richardson
0aa48fb9e4 feat: Support custom CFBundleVersion for iOS and macOS (#13030)
* feat: Add bundleVersion for iOS and macOS

* feat: Use bundleVersion for CFBundleVersion

* feat: Synchronize bundleVersion with Info.plist

* cleanup

* fix bundle version, enhance prerelease/buildnumber support and checks

* fix change file

* tauri-bundler to change file

* expand doc

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-12 09:28:48 -03:00
renovate[bot]
628f4a97e4 chore(deps): update dependency rollup to v4.40.0 (#13214)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-12 18:16:09 +08:00
Tony
fca5154e7a chore(core)!: remove re-exported WebviewAttributes (#13130) 2025-04-11 20:34:15 -03:00
Tony
fbd57a1afd feat(core): make invoke_system take AsRef<str> (#13175)
* feat(core): make `invoke_system` take `AsRef<str>`

* Use minor bump
2025-04-11 20:30:05 -03:00
The1111mp
dd4f13ce4b feat: add set_dock_visibility method (#13185)
* feat: add `set_dock_visibility` method

Signed-off-by: The1111mp <The1111mp@outlook.com>

* add api

* retain focus

* fmt

* make SetDockVisibility message conditional (macos only)

* lint

---------

Signed-off-by: The1111mp <The1111mp@outlook.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-11 15:13:07 -03:00
dependabot[bot]
7b14531f24 chore(deps-dev): bump vite from 6.2.5 to 6.2.6 (#13206)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.5 to 6.2.6.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.6/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.6/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.6
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-11 23:48:57 +08:00
Trivikram Kamat
7a86e0f8a1 ci: remove redundant corepack enable (#13203) 2025-04-11 09:04:19 -03:00
Simon Laux
c1cd0a2ddb feat: macOS/iOS: add option to disable or enable link previews when building a webview (#13090)
* macOS/iOS: add option to disable or enable link previews when building a webview (the webkit api has it enabled by default)
  -  `WebViewBuilderExtDarwin.allow_link_preview(allow_link_preview: bool)`
  -  `WebViewBuilder.allow_link_preview(allow_link_preview: bool)`
  -  `WebviewWindowBuilder.allow_link_preview(allow_link_preview: bool)`

* also call on iOS

* add api

* fix tests

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-11 09:00:34 -03:00
dependabot[bot]
073dbc3953 chore(deps): bump crossbeam-channel from 0.5.14 to 0.5.15 (#13194)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-10 16:54:11 +02:00
renovate[bot]
47df696dfb chore(deps): update dependency eslint-config-prettier to v10.1.2 (#13192)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-10 15:03:40 +02:00
Tony
9ea76503dc fix(nsis): can't include resources with $ (#13186) 2025-04-09 20:03:35 +08:00
Lucas Fernandes Nogueira
bb5faa21f4 chore: update tao, wry, windows, webview2-com (#13163)
* chore: update tao, wry, windows, webview2-com

* update docs

* Use `impl Into<String>`

* More docs

---------

Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-09 08:15:31 -03:00
renovate[bot]
b32153b437 chore(deps): update rust crate tokio to v1.43.1 [security] (#13172)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-08 09:35:03 +08:00
dependabot[bot]
c71755fd5f chore(deps-dev): bump vite from 6.2.4 to 6.2.5 (#13138)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.4 to 6.2.5.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.5/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.5/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 6.2.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-05 10:08:12 +08:00
dependabot[bot]
7b81825144 chore(deps): bump openssl from 0.10.70 to 0.10.72 (#13140)
Bumps [openssl](https://github.com/sfackler/rust-openssl) from 0.10.70 to 0.10.72.
- [Release notes](https://github.com/sfackler/rust-openssl/releases)
- [Commits](https://github.com/sfackler/rust-openssl/compare/openssl-v0.10.70...openssl-v0.10.72)

---
updated-dependencies:
- dependency-name: openssl
  dependency-version: 0.10.72
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-05 10:07:41 +08:00
Tony
ebd3dcb92f enhance(core): change eval to take Into<String> (#13135) 2025-04-04 10:06:22 +02:00
Tony
80dccb6a2e chore: fix a few internal docs and apply clippy suggestions (#13131)
* chore: fix a few internal docs

* Remove label clone

* Unused allow lint

* No way clippy just updated

* `cargo clippy --fix -- -W clippy::redundant_clone`

* format
2025-04-03 17:57:36 +02:00
WofWca
cf0b3588a3 docs: add SafePathBuf examples (#13122) 2025-04-02 14:02:48 -03:00
Tony
b8c0d7e402 fix: run_return not responding to restart (#13040)
* fix: `run_return` not responding to `restart`

* Document run_return will handle restart requests

* Add change file
2025-04-02 09:54:38 -03:00
renovate[bot]
e4982dff73 chore(deps): update dependency rollup to v4.39.0 (#13125)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 17:17:43 +08:00
Simon Laux
8cf662e34b feat: expose api to run initialization scripts on all frames. (#13076)
* api!: expose api to run initialisation scripts on all frames.

* remove breaking change, add new api instead.

* Update .changes/init-script-on-all-frames.md

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* use struct `InitializationScript` instead of tuple

* Update crates/tauri-runtime/src/webview.rs

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>

* Apply suggestions from code review

* Update crates/tauri/src/webview/webview_window.rs

---------

Co-authored-by: Tony <68118705+Legend-Master@users.noreply.github.com>
2025-04-02 08:41:34 +08:00
github-actions[bot]
b154826881 apply version updates (#13060)
Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
2025-04-01 13:52:38 -03:00
Lucas Nogueira
dade232592 chore: change bumps to patches 2025-04-01 13:14:28 -03:00
Tony
aa6b4d4edf fix(cli): preserve null when merging patches (#13120)
* fix(cli): preserve null when merging patches

* add test

* remove commented out code

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-04-01 13:09:50 -03:00
Tony
794af778e4 fix(cli): merge config based on the first one (#13117)
* fix(cli): merge config based on the first one

* Add change file
2025-04-01 17:18:13 +08:00
dependabot[bot]
4e22ae29d3 chore(deps-dev): bump vite from 6.2.3 to 6.2.4 (#13111)
* chore(deps-dev): bump vite from 6.2.3 to 6.2.4

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.3 to 6.2.4.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.4/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.4/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update esbuild

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-04-01 09:05:10 +08:00
Tony
4ae14bf2f2 fix: suppress deprecated warning in tray icon codegen (#13093) 2025-03-31 09:54:07 +08:00
Pietagorh
f805061d11 feat(cli): allow for toml and json5 files in --config arg (#13079) 2025-03-30 18:11:47 +02:00
Tony
30beb6fee7 fix(cli): tauri info can't find the latest version for rust crates (#13096)
* fix(cli): `tauri info` can't find the latest version for rust crates

* Forget to remove dbg!

* Use strip_suffix

* Add change file
2025-03-29 23:45:38 +08:00
renovate[bot]
22c7a877e3 chore(deps): update dependency rollup to v4.38.0 (#13094)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-29 17:32:15 +08:00
Tony
2138bbc212 fix(nsis): in wrong language if SpanishInternational is included (#13087) 2025-03-28 03:45:13 -07:00
dependabot[bot]
5c2b3b8b65 chore(deps-dev): bump vite from 6.2.0 to 6.2.3 (#13072)
* chore(deps-dev): bump vite from 6.2.0 to 6.2.3

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.2.0 to 6.2.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v6.2.3/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.2.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update esbuilds to the same version

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Tony <legendmastertony@gmail.com>
2025-03-26 15:10:34 +08:00
阿豪
dd13728334 enhance(api): add generic parameter to emit and emitTo functions (#13066)
closes #13059
2025-03-25 05:34:20 +02:00
renovate[bot]
f235ec0113 chore(deps): update dependency rollup to v4.37.0 (#13062)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-24 21:14:02 +08:00
Matthew Richardson
f182b0bb93 docs: Update general setup in contributing guide (#13065) 2025-03-24 05:51:09 -07:00
Tony
a851b6597f enhance: include permission group permissions in the generated schema (#13057)
* enhance: include permissions in default permission description

* Only include in schema

* Remove 'which includes` to tauri's build script

* Also bump utils

* Clippy
My local clippy didn't report this, weird

* Use `which enables all commands`
for default permissions that enables everything

* Extract description into a variable

* Generate permissions with or without description

* Tweak the docs and generate 'which includes'

* Simplify to just `includes`

* Docs change change file

* Put the change in minor

* Update .changes/include-permissions-in-schema.md

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>

* Remove unused change file

---------

Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com>
2025-03-23 21:35:45 +08:00
WofWca
be31675fbc docs: improve Builder::run docs (#13058)
Otherwise people might use it and not realize
that `App::run` also takes the callback argument,
which could be useful for some.
2025-03-23 15:07:33 +02:00
Lőrik Levente
dea8bbf6cd docs: Improve BaseDirectory documentation (#13043)
* add notes

* Add links

* fix fmt
2025-03-21 13:57:34 +02:00
github-actions[bot]
be3a79c864 apply version updates (#12856)
Co-authored-by: lucasfernog <20051258+lucasfernog@users.noreply.github.com>
2025-03-20 15:34:59 -03:00
Lucas Nogueira
ba42a1f553 chore: pin tao and wry to latest patch versions
they include necessary bug fixes for the 2.4 release
2025-03-20 14:52:38 -03:00
Tony
1cd8f55eed fix: don't ship global api bundle if withGlobalTauri is false (#13033)
* fix: don't ship global api bundle if withGlobalTauri is false

* Comment and prettier
2025-03-20 12:37:31 -03:00
Tony
8603e42a6b fix: channel no longer being always allowed (#13032)
* fix: channel no longer being always allowed

* Prettier

* Don't change the plugin name just yet

* Handle TAURI_CHANNEL as a special case in macro

* remove commented out code

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-20 12:19:55 -03:00
Akshanabha Chakraborty
c32bd722d3 prettify: Remove beta tag and alert users that tauri for android currently doesn't work on android 7 (#12646) 2025-03-18 08:33:47 -03:00
Lucas Fernandes Nogueira
bcdd510254 feat(core): resolve file names from Android content URIs (#13012)
* feat(core): resolve file names from Android content URIs

This PR adds a new Android path plugin function to resolve file names from content URIs. `PathResolver::file_name` was added to expose this API on Rust, and the existing `@tauri-apps/api/path` basename and extname function now leverages it on Android.

Closes https://github.com/tauri-apps/plugins-workspace/issues/1775

Tauri core port from https://github.com/tauri-apps/plugins-workspace/pull/2421

Co-authored-by: VulnX

* update change file [skip ci]

Co-authored-by: VulnX <62636727+VulnX@users.noreply.github.com>

---------

Co-authored-by: VulnX <62636727+VulnX@users.noreply.github.com>
2025-03-18 08:29:07 -03:00
WofWca
71cb1e26d7 docs: update .disable_javascript() docs (#13013)
The initial version of the MR that introduced this to Wry
(https://github.com/tauri-apps/wry/pull/1496)
had no Android implementation, but it has been added
in a later version of the MR, so the comment is no longer valid.
2025-03-18 09:47:27 +02:00
WofWca
b459f1d405 docs: improve Capability docs: mention webviews (#13015) 2025-03-18 09:46:48 +02:00
dependabot[bot]
8cc0067165 chore(deps): bump zip from 2.2.2 to 2.3.0 (#13016)
Bumps [zip](https://github.com/zip-rs/zip2) from 2.2.2 to 2.3.0.
- [Release notes](https://github.com/zip-rs/zip2/releases)
- [Changelog](https://github.com/zip-rs/zip2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zip-rs/zip2/compare/v2.2.2...v2.3.0)

---
updated-dependencies:
- dependency-name: zip
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 11:35:36 +08:00
Lucas Fernandes Nogueira
f2c94aaca0 feat(core): add startIntentSenderForResult Android API for plugins (#12682) 2025-03-17 11:52:11 -03:00
WofWca
cefefa930b docs: improve tauri_build::build & try_build (#13001)
* docs: remove outdated `tauri_build::build` docs

The docstring has been unchanged ever since
40ac52971e (2021).
The `build()` function has grown massivly since then,
now it's not only about Windows.

* docs: `tauri_build::build`: see `try_build` for more config

`try_build` is not only about not panicing, but it also takes the
`attributes: Attributes` argument,
which is very important for controlling command permissions.

* Update crates/tauri-build/src/lib.rs

Co-authored-by: Amr Bashir <github@amrbashir.me>

* update docs

---------

Co-authored-by: Amr Bashir <github@amrbashir.me>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-17 09:28:09 -03:00
renovate[bot]
4a01299e31 chore(deps): update dependency rollup to v4.36.0 (#13010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-17 19:36:29 +08:00
WofWca
5a23146566 docs: clarify Capability::windows/webviews OR nature (#13000)
* docs: clarify Capability::windows/webviews OR nature

It is intuitive to expect that for the capability to be enabled,
_both_ the window label and the webview label have to match.
However, this is not the case: the capability is enabled
if _either_ the window label matches a pattern
in `Capability::windows` _or_ the webview label matches a pattern
in `Capability::webviews`.

This commit should somewhat clarify this oddity
and protect developers from adding excessive permissions.

For reference, `Capability::webviews` was added in
0cb0a15ce2
(https://github.com/tauri-apps/tauri/pull/8789).

* Apply suggestions from code review

Co-authored-by: Amr Bashir <github@amrbashir.me>

* update schemas

---------

Co-authored-by: Amr Bashir <github@amrbashir.me>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-17 08:29:58 -03:00
Tony
4062e49914 fix: always delete auto start registry entry (#13006) 2025-03-17 08:21:14 -03:00
Nano
a483ba7c27 enhance: align log like Cargo (#13002) 2025-03-17 02:39:36 +02:00
Levi Zim
f981a5ee8b feat: basic support for linux riscv64 (#12602) 2025-03-16 16:33:17 -03:00
animesh chaudhri
2b960dfd9f feat(uninstaller): remove autostart entry during uninstallation (#12643)
* feat(uninstaller): remove autostart entry during uninstallation

Signed-off-by: animeshchaudri <animeshchaudhri3@gmail.com>

* add change file

* check when not updating

* delete registry value only if install mode is "currentUser"

---------

Signed-off-by: animeshchaudri <animeshchaudhri3@gmail.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-16 16:28:10 -03:00
Xuan
eec08a18b6 fix: use bun.lock to identify bun's lockfile (fix #12914) (#12998)
* fix: use bun.lock to identify bun's lockfile

* fix: also check bun.lockb

* doc: add changes doc
2025-03-16 18:00:04 +01:00
Tony
35018eed02 chore: fix missing .md on request-restart.md (#12996) 2025-03-16 21:20:25 +08:00
Tony
de7f34bff4 feat: introduce request_restart (#12874)
* Introduce request_restart

* Migrate `restart`

* Add change file

* Save restart_on_exit and add docs

* Tweak docs to include `restart`

* clear restart flow

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-16 08:42:29 -03:00
Tony
72df2e4a04 refactor: remove permission description from runtime (#12994)
* Remove description from runtime

* Just use none instead

* global_scope_schema and add comments about it

* Tweak wording

* remove comments [skip ci]

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-16 07:33:41 -03:00
Fabian-Lars
0d1446857c fix: Don't minify api dist files (#12989) 2025-03-16 07:11:42 -03:00
Thomas Eizinger
658e5f5d1d feat: introduce App::run_return (#12668)
* Introduce `run_return`

* Fix compile error

* Clone web_context

* Refactor to Result API

* Fix clippy

* Impl mock runtime

* Make it desktop-only

* Add changelog entry

* Fix compile error

* Make it semver compatible

* Extend changelog entry

* Undo semver-hack

* Reduce diff

* Remove unnecessary mut

* Make it take `self` by value

* Reduce diff

* Undo diff hack

* Make everything cfg(desktop)

* Rename vars to reduce diff

* Fix clippy

* Extract make_event_handler

* Reduce diff

* Deprecate `App::run_return`

* Update changelog

* Fix compile errors

* Accept reference

* Create event handler first

* Update example

* Update manifest

* Fix example

* Fix example docs

* Call `setup` only upon Ready

* Update changelog entry

* Update docs

* Update changelog

* Add platform-specific note

* update docs

* run_return on mobile

* Apply suggestions from code review

* remove change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-16 07:04:22 -03:00
WofWca
7930dde85c chore: examples: fix & simplify helloworld (#12995)
Remove the cookies code from it.
Firtly, they are not necessary: "Hello, world!" should be simple.
Secondly, it's broken on Windows: `.cookies()` hangs.

The cookies stuff was introduced recently,
in cedb24d494
(https://github.com/tauri-apps/tauri/pull/12665).
This commit reverts the changes to the example.

This supersedes https://github.com/tauri-apps/tauri/pull/12992.
2025-03-16 11:50:06 +02:00
anatawa12
b05f82d35b fix: ensure RunEvent::Exit is triggered on restart (#12313)
* fix: AppHandle::restart() may not send RunEvent::Exit event

* docs: add changelog: `AppHandle::restart()` may not send `RunEvent::Exit` event before exiting the application.

* style: cargo fmt

* avoid deadlock on main thread

* do not let the restart be prevented

leads to a deadlock currently

* Apply suggestions from code review

* lint

* do not emit RunEvent on main thread

* re-export RESTART_EXIT_CODE

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 15:49:42 -03:00
Tony
51bcafe323 refactor: use a single closure for filtering in emit_to (#12907)
* Use a single closure for filtering

* clippy

* Update crates/tauri/src/manager/mod.rs

---------

Co-authored-by: Lucas Fernandes Nogueira <lucas@tauri.app>
2025-03-15 13:46:51 -03:00
Tony
013f8f6523 feat: add a new option to remove unused commands (#12890)
* Add a new option to remove unused commands

* Fix compile

* Add markers to all core plugins

* Clippy

* Add allow unused when running with this

* Use build script to generate allowed-commands.json

* Clean up and add proper reruns

* Wrong path

* Revert to #[cfg_attr(not(debug_assertions), allow(unused))]

* Add change files

* Some more docs

* Add version requirement note

* Avoid rerun if no capabilities folder

* Remove unused box

* small cleanup

* fix channel

* implement for app handler too

* rely on core:default for channel perms

* Move this feature to config

* Docs change

* Forget one last remove_unused_commands

* Remove removeUnusedCommands from helloworld

* tell handler that the app ACL manifest exists

* update change file

* update doc

* update change file

* Use a struct to pass the data instead of env var

* Clippy

* Fix can't exclude inlined plugins on Windows
due to UNC paths...

* Apply suggestion from code review

* Remove remove on empty to tauri-build

* Revert "Remove remove on empty to tauri-build"

This reverts commit b727dd621e.

* Centralize remove_file(allowed_commands_file_path)

* Escape glob pattern

* update change file

* remove unused commands for dev too

* Update crates/tauri-utils/src/config.rs

Co-authored-by: Fabian-Lars <github@fabianlars.de>

* regen schema

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-03-15 13:46:08 -03:00
Tobias Assarsson
5591a4f0b4 feature(linux) add mousewheel bindings for zoom functions (#12912)
* add mousewheel bindings commonly used for zooming

* add change file

* update docs

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 13:29:13 -03:00
Fabian-Lars
2fa33d5c44 chore: Fix example readme instructions. Add pnpm build:debug. (#12983)
* chore: Fix example readme instructions. Add `pnpm build:debug`.

* keep terser on bundle.global.js build to avoid file modifications

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 12:51:40 -03:00
Adam Charron
cedb24d494 feat: add Webview::cookies and Webview::cookies_for_url() (#12665)
* Add support for fetching cookies by url

* Add support for fetching all cookies

* add missing getters, update change file

* update docs for windows deadlock

* fix mobile build

* Update crates/tauri-runtime/Cargo.toml

* add docs for stability [skip ci]

---------

Co-authored-by: Adam Charron <acharron@higherlogic.com>
Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 12:34:41 -03:00
Fabian-Lars
30f5a1553d feat: traffic light position (#12366)
* moving to macbook

* that was so weird to implement

* rm patch

* Discard changes to Cargo.lock

* Create change-pr-12366.md

* add missing builder fn

* remove test

* split change files

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 12:18:11 -03:00
Lucas Fernandes Nogueira
08de8a172b chore: remove 2.0.0-rc references (#12987) 2025-03-15 12:03:09 -03:00
Sean Wang
c108024257 feat(tauri): derive Clone for tauri::ExitRequestApi (#12710) 2025-03-15 10:26:22 -03:00
Tobias Assarsson
dc90cd3919 fix(core): add ctrl '+' key as zoom in (#12911)
* add '+' key as zoom in

* add changefile

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-15 10:16:29 -03:00
renovate[bot]
0ec71a844c chore(deps): update dependency wrangler to v4 (#12967)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-15 08:23:47 -03:00
Fabian-Lars
0c4700e990 fix(cli): Remove mention of updater bundle arg in help output (#12985)
* fix(cli): Remove mention of `updater` bundle arg in help output

* allow --bundles updater but hide from help
2025-03-15 08:02:28 -03:00
Lucas Fernandes Nogueira
b83921226c fix(cli): ios command wrong cwd on bun 1.2, closes #12965 (#12977)
bun 1.2 changed the current working directory behavior to match NPM managers, so we must adapt our xcode-script logic to check the bun version

see https://bun.sh/blog/bun-v1.2#bun-run-uses-the-correct-directory
2025-03-14 16:20:39 -03:00
Oscar Beaumont
3cc4ad3c38 fix: allow double -- in permissions as command can have double __ (#12884)
* allow double `--` in permissions as command can have double `__`

* Create change-pr-12884.md

* Update .changes/change-pr-12884.md

Co-authored-by: Fabian-Lars <github@fabianlars.de>

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-03-14 12:13:48 -03:00
Lucas Fernandes Nogueira
d91bfa5cb9 feat(cli): allow merging multiple configuration values (#12970)
* feat(cli): allow merging multiple configuration values

Currently the dev/build/bundle commands can only merge a single Tauri configuration value (file or raw JSON string), which imposes a limitation in scenarios where you need more flexibility (like multiple app flavors and environments). This changes the config CLI option to allow multiple values, letting you merge multiple Tauri config files with the main one.

* fix ios build
2025-03-14 12:04:58 -03:00
WofWca
f67a4a6bfe fix(core): AssetResolver.get(): don't skip first char (#12971)
That is, it would try to get `sers/john` if you called
`AssetResolver.get("users/john")`.
This commit fixes the bug by only skipping the first character
only if it _is_ a slash (/).

Why it is important:
`tauri::WebviewUrl::App()` docs state that it's OK to specify
the path as `users/john` to get `tauri://localhost/users/john`
in the end.
So if an application developer is using `AssetResolver.get()`
together with `WebviewUrl::App()`, they will would get
inconsistent behavior: for the same path, the latter would work,
while the former would fail.
In fact, we encountered this bug in our code,
[here](c860b0f4c6/packages/target-tauri/src-tauri/src/help_window.rs (L34-L43)).
2025-03-14 05:29:55 +02:00
Simon Laux
d8059bad3c add AppHandle.fetch_data_store_identifiers and AppHandle.remove_data_store (#12900)
* add `AppHandle::fetch_all_data_store_identifiers` and `AppHandle::remove_data_store`

* make it run on main thread, so you can call the function from any thread and it works.

* changes file

* update signature, move functions to RuntimeHandle

* add api

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-13 18:17:22 -03:00
Simon Laux
be2e6b85fe add Window.is_always_on_top() and WebviewWindow.is_always_on_top() (#12944)
* add `Window.is_always_on_top()` and `WebviewWindow.is_always_on_top()`

* add api

* fmt

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-13 18:02:01 -03:00
Chandrasekaran Akash
b9ee806724 feat(tauri-build): set CompanyName for Windows (#12958) 2025-03-13 09:35:56 +02:00
renovate[bot]
339a075e33 chore(deps): update rust crate cargo_toml to 0.22 (#12940)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-12 13:42:37 +01:00
Fabian-Lars
93124ad2eb fix(tauri-utils): Set minimum patch version for glob (#12950) 2025-03-10 21:38:22 +01:00
tk
3a74dc8f34 fix(api): webview.close wrong command error (#12935) 2025-03-10 06:48:02 +02:00
ninjadev64
3626b7a92b fix(bundler): bundle resources to correct path during RPM bundling when resources are specified as a map (#12759)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-03-09 16:19:18 +01:00
renovate[bot]
eea12c196e chore(deps): update dependency rollup to v4.35.0 (#12932)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 10:12:56 +08:00
renovate[bot]
4ce5c74ab4 chore(deps): update dependency eslint-config-prettier to v10.1.1 (#12916)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-09 10:12:08 +08:00
Amr Bashir
2d029a9f53 fix(core): remove TSend: Clone for Channel in commands (#12878)
followup on #12876
2025-03-03 17:41:10 +02:00
Lucas Fernandes Nogueira
f268b3dbdf fix(cli): Tauri project path resolution, closes #3527 #12779 (#12871) 2025-03-03 08:18:00 -03:00
Amr Bashir
755533c518 fix(core): implement Clone manually on Channel. (#12876)
ref: https://github.com/tauri-apps/plugins-workspace/pull/2479#discussion_r1976864479
2025-03-03 08:32:17 +02:00
Tony
dc78dfecab chore: ignore vscode settings.json and tasks.json (#12875) 2025-03-03 05:38:47 +02:00
Lucas Fernandes Nogueira
f98598817c fix(core): compatibility check for Android SDK < 24 (#12870) 2025-03-02 17:56:25 -03:00
Niladri Adhikary
060de5bbdd feat(api): implement getIdentifier() to access tauri.conf.json identifier (#12837)
* feat(api): implement getIdentifier() to access tauri.conf.json identifier

* updated

* chore(api): update change file and rebuild bundle

* Update to @since 2.4.0

* added tag

* Update .changes/get-identifier.md

Co-authored-by: Fabian-Lars <github@fabianlars.de>

---------

Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-03-02 15:12:33 -03:00
Simon Laux
c698a6d6f3 feat: add Webview.reload and WebviewWindow.reload (#12818)
* feat: add `Webview.reload` and `WebviewWindow.reload`

* fix tests

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-02 15:11:25 -03:00
Simon Laux
20c1906912 feat: add WebviewBuilder.disable_javascript and WebviewWindowBuilder.disable_javascript (#12821)
* feat: add `WebviewBuilder.disable_javascript` and `WebviewWindowBuilder.disable_javascript`

* wry 0.50.3

* add missing config options and API types

* add change file for api

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-03-02 14:54:34 -03:00
renovate[bot]
3fb8d7ca6b chore(deps): update dependency rollup to v4.34.9 (#12862)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-01 11:16:25 +01:00
Lucas Fernandes Nogueira
55ffa23c9e fix(core): docs.rs mobile build (#12855) 2025-02-28 15:37:38 -03:00
github-actions[bot]
cab7f76d01 apply version updates (#12826)
Co-authored-by: amrbashir <48618675+amrbashir@users.noreply.github.com>
2025-02-28 14:14:08 +01:00
Amr Bashir
e103e87f15 fix(windows): ensure APIs exist before using it (#12848)
* fix(windows): ensure APIs exist before using it

* fix build on other platforms

* clippy

* use GetSystemMetricsForDpi
2025-02-28 14:46:16 +02:00
Fabian-Lars
bca02967a9 docs: Update wording from #12830 (#12839) 2025-02-28 00:12:19 +02:00
Tony
887db0813f chore(deps): update js dependencies (#12832)
* chore(deps): update js dependencies

* Update lock
2025-02-27 17:15:32 +08:00
Tony
4f26dcf309 fix(deps): os webview not gated in wry feature (#12833) 2025-02-27 16:38:20 +08:00
Simon Laux
4bffc326ea docs: update WebViewBuilder::with_asynchronous_custom_protocol with platform-specific notes (#12830) 2025-02-27 03:10:08 +02:00
renovate[bot]
b859dc43fc chore(deps): update rust crate resvg to 0.45.0 (#12825)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-26 22:00:52 +01:00
renovate[bot]
9332132239 chore(deps): update dependency eslint-config-prettier to v10.0.2 (#12822)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-26 20:46:52 +01:00
Timur Amirov
22e9bf74a4 fix(cli/ios): Configure initial view controller for the launch screen on iOS (#12538)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-02-26 20:42:24 +01:00
Fabian-Lars
b495fe0fdc ci: install corepack in docker (#12824)
* ci: install corepack in docker

this should fix the build errors from https://github.com/tauri-apps/tauri/actions/runs/13548556704/job/37866236681
i only added it outside of docker in my last pr

* remove musl
2025-02-26 13:41:32 -03:00
github-actions[bot]
7d618f12d8 apply version updates (#12518)
Co-authored-by: amrbashir <48618675+amrbashir@users.noreply.github.com>
2025-02-26 12:45:31 -03:00
Amr Bashir
385a41dea2 enhance(windows): disable our in-client resizing for undecorated window with shadows (#12817)
* enhance(windows): disable our in-client resizing for undecorated window with shadows

ref: https://github.com/tauri-apps/tao/pull/1052

* skip hittesting for undeceorated windows
2025-02-26 17:21:46 +02:00
Fabian-Lars
955832e56b ci: Build win-arm64 cli with rustls (#12813) 2025-02-25 21:47:46 +01:00
Fabian-Lars
c116dfcdee fix(cli): Hide updater bundle target in help output (#12801)
ref https://github.com/tauri-apps/tauri/issues/3251#issuecomment-2677139820
2025-02-25 20:25:28 +02:00
Fabian-Lars
d6520a21ce chore(deps): wry@0.50 muda@0.16 tray-icon@0.20 windows@0.60 webview2-com@0.36 objc@0.6 window-vibrancy@0.6 tao@0.32 (#12541)
* chore(deps): Update windows to 0.59. Update webview2-com to 0.35

* wry and other crates and objc2

* window-vibrancy 0.6

* Update windows059-webview035.md

* win compile error

* tao

* tao 0.32.1

* updatus maximus

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-02-25 19:41:00 +02:00
Simon Laux
ab81adb71b docs: improve documentation around incognito and data store (#12806) 2025-02-25 06:17:20 +02:00
kandrelczyk
6e417c9435 fix(linux): Add missing RPM signature (#12786) 2025-02-24 14:52:06 +01:00
Kotkoroid
ddc469367a style: fix Vite and React branding (#12768) 2025-02-22 11:30:31 +01:00
Sean Wang
d7b998fe71 fix(tauri): deprecate Manager::unmanage to fix use-after-free (#12723)
close #12721
2025-02-21 02:38:31 +02:00
renovate[bot]
d9a07e66af chore(deps): update dependency globals to v16 (#12750)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-20 15:26:14 +01:00
renovate[bot]
0adeb4e7c5 chore(deps): update rust crate infer to 0.19 (dev) (#12599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-02-20 14:36:44 +01:00
Jim
70d8557cc3 docs(testing): inform reader about 'tauri://localhost' (#12623) 2025-02-20 12:48:33 +01:00
Tony
95fc3cd424 chore: cleanup a few unneeded clones (#12733) 2025-02-18 18:35:40 +08:00
renovate[bot]
4633705da7 chore(deps): update dependency rollup to v4.34.8 (#12727)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-17 20:12:00 +08:00
Tony
3f680588cd chore: update prettier to 3.5.1 and enable experimentalOperatorPosition (#12715) 2025-02-16 20:34:19 +08:00
Sean Wang
7d8252679d feat(tauri): export struct tauri::ExitRequestApi (#12701) 2025-02-15 16:21:06 +01:00
renovate[bot]
ee95c1b1ed chore(deps): update dependency rollup to v4.34.7 (#12702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-15 10:19:48 +08:00
Ege Güngördü
741e44b45c fix: fix incorrect example for WebviewBuilder::from_config (#12695) 2025-02-13 00:04:29 +02:00
renovate[bot]
8e9339e880 chore(deps): update rust crate jsonschema to 0.29 (dev) (#12660)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-09 14:19:32 +01:00
renovate[bot]
053b57c1df chore(deps): update dependency rollup to v4.34.6 (dev) (#12647)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 20:07:55 +01:00
renovate[bot]
b6a56f3616 chore(deps): update dependency rollup to v4.34.5 (#12641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-07 10:18:38 +01:00
dependabot[bot]
11945e561c chore(deps-dev): bump vitest from 3.0.3 to 3.0.5 (#12637)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-06 18:48:57 +01:00
renovate[bot]
b6ad316460 chore(deps): update dependency rollup to v4.34.4 (dev) (#12604)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-02-06 18:32:56 +01:00
Nazar Antoniuk
5eba0785c4 feat: add Ukrainian translation for the custom tauri messages in the nsis bundle (#12605) 2025-02-06 17:44:48 +02:00
dependabot[bot]
6038f09d85 chore(deps): bump openssl from 0.10.68 to 0.10.70 (#12606)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-03 21:30:48 +01:00
renovate[bot]
e3b0260871 chore(deps): update dependency rollup to v4.34.0 (#12593)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-02 19:54:02 +08:00
Antony Kurniawan
a6ada76a9f docs: update devUrl on config schema (#12592) 2025-02-01 23:45:13 +02:00
renovate[bot]
bfc71e845b chore(deps): update rust crate ureq to v3 (dev) (#12524)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-01-29 23:23:38 +01:00
renovate[bot]
0a11b8741a chore(deps): update rust crate tauri-winres to 0.3 (dev) (#12559)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-29 21:51:24 +01:00
renovate[bot]
6b70fbcc84 chore(deps): update dependency rollup to v4.32.1 (dev) (#12548)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <github@fabianlars.de>
2025-01-28 14:46:04 +01:00
Amr Bashir
e9c9c4d6f6 feat: derive Clone for PathResolver (#12529)
closes #12528
2025-01-26 20:11:15 +02:00
Sean Wang
abdd558075 feat(tauri/Emitter): add emit_str* method to emit serialized data directly (#12460)
* feat(tauri/Emitter): add `emit_str*` method to emit serialized data

* style: rust fmt
2025-01-26 17:58:21 +02:00
Sean Wang
3dbcbe7685 fix(tauri): Webview::navigate unnecessarily borrows &mut self (#12461) 2025-01-25 22:21:04 +01:00
Bastian Kistner
a2d36b8c34 feat: disable background throttling (#12181)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-25 22:20:31 +01:00
github-actions[bot]
5a3647bdfe Apply Version Updates From Current Changes (#12515)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-25 20:51:13 +01:00
Fabian-Lars
477e9c0496 fix(core): Use safe_block_on in mobile proxy (#12514)
fixes #12513
2025-01-25 20:18:46 +01:00
github-actions[bot]
82d634f4a9 Apply Version Updates From Current Changes (#12512)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-25 18:23:32 +01:00
Fabian-Lars
8e9134c4a2 fix(cli): Apply --bins flag on build instead of dev (#12511) 2025-01-25 17:50:46 +01:00
github-actions[bot]
dc1997b77d apply version updates (#12439)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-25 15:29:40 +01:00
bradleat
1a86974aa3 fix(cli): let xcode handle building for ios build --open (#12406)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-25 13:42:20 +01:00
bicarlsen
fb294af8e3 fix(tauri-driver): Parse ms:edgeOptions separately (#12383)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-25 13:13:13 +01:00
Fabian-Lars
46c7b16111 ci(renovate): Disable oxc_ PRs 2025-01-25 12:10:59 +01:00
Fabian-Lars
9dac2863af fix(bundler): Don't self-sign dmg (#12323) 2025-01-25 11:46:16 +01:00
renovate[bot]
9a9d1205b0 chore(deps): update dependency rollup to v4.32.0 (dev) (#12502)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-25 11:45:16 +01:00
Fabian-Lars
27096cdc05 fix(cli): don't force native-tls feature on desktop (#12445) 2025-01-25 11:27:29 +01:00
sftse
6cbfc4878d refactor: document Emitter/Listner traits panics, refactor check into internal struct (#12444) 2025-01-24 04:17:17 +02:00
Andzej Korovacki
f5a59b93bf fix(bundler): change build metadata verification into a warning (#12136)
Co-authored-by: akorovacki <andzej.korovacki@geniussports.com>
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-23 15:25:11 +01:00
renovate[bot]
5432752e51 chore(deps): update dependency vitest to v3 (dev) (#12421)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-23 14:03:40 +01:00
renovate[bot]
bf912b8e08 chore(deps): update rust crate dirs to v6 (dev) (#12372)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-23 13:58:00 +01:00
Trey Smith
9a30bed98c fix(macos): frameworks being signed with entitlements unnecessarily (#12423) 2025-01-23 12:14:33 +01:00
dependabot[bot]
9d02c18ac2 chore(deps-dev): bump vite from 6.0.7 to 6.0.9 (#12469)
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 6.0.7 to 6.0.9.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v6.0.9/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-23 17:06:41 +08:00
anatawa12
de8600b4d9 fix(bundler): Bump nsis tauri utils to 0.4.2 (#12471)
* chore: bump nsis-tauri-utils

* docs(changelog)): Bump nsis-tauri-utils to 0.4.2
2025-01-22 03:01:04 +02:00
Mads Marquart
0ea8894579 chore(deps): prepare for objc2 frameworks v0.3 (#12468)
These will have a bunch of default features enabled, so let's
pre-emptively disable them.
2025-01-21 22:57:45 +02:00
Fabian-Lars
fbe7c9ead7 fix(bundler): fix injectedbundle search path (#12466) 2025-01-21 16:52:41 +02:00
Tony
b8eb28877f enhance(nsis): clean up reg keys in uninstaller (#12427) 2025-01-20 22:33:54 +02:00
Tomas Tamadamas
90c6546faf chore: Rewrite simply "Localhost free term" in README.md within #10510 (#12415) 2025-01-20 16:22:22 +02:00
renovate[bot]
4ed2ab76e2 chore(deps): update dependency rollup to v4.31.0 (dev) (#12446)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-19 17:59:01 +01:00
Fabian-Lars
bc43c738ba fix(cli): Add clipboard-manager to known plugins (#12442)
* fix(cli): Add `clipboard-manager` to known plugins

fixes #12440

* Update plugins.rs
2025-01-19 14:19:10 +02:00
Jim
0b79af7114 enhance(cli): log message to inform user of DevCommand being used (#12438) 2025-01-18 22:21:21 +02:00
github-actions[bot]
a70e690fe7 apply version updates (#12425)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-18 10:07:28 +01:00
Felix Eckhardt
72748cc45c fix(windows): Resolve broken installation directory handling in MSI & NSIS, preventing duplicate installations during updates (#12365) 2025-01-17 21:25:15 +01:00
Fabian-Lars
cf771bf69a fix(bundler/wix): Prevent dlls from overwriting root resources (#12402) 2025-01-17 16:41:31 +01:00
Fabian-Lars
07ccdc499c fix(bundler/nsis): Include WebView2Loader.dll if found to match msi (#12324)
* fix(bundler/nsis): Include WebView2Loader.dll if found to match msi behavior

* Update fix-nsis-webviewloaderdll.md

* only include dll in gnu builds
2025-01-17 17:12:58 +02:00
mattyg
d2c8f0eb5c fix: run tauri's internal init scripts before user's scripts (#12424) 2025-01-17 03:37:41 +02:00
Fabian-Lars
b643dcc1c4 docs(utils): Fix typo in useLocalToolsDir (#12409) 2025-01-15 14:59:34 +02:00
renovate[bot]
cd7d08b63f chore(deps): update dependency eslint-config-prettier to v10 (#12386)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-15 10:54:33 +08:00
github-actions[bot]
4c3f047735 Apply Version Updates From Current Changes (#12377)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-13 13:08:29 +01:00
Fabian-Lars
61e69db9e4 chore: Add changefile for #12371 (#12376) 2025-01-13 12:23:17 +01:00
Oscar Beaumont
75d56e8364 fix: fix Specta integration (#12371) 2025-01-13 04:03:36 +02:00
github-actions[bot]
a8aca70151 Apply Version Updates From Current Changes (#12355)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-11 18:13:55 +01:00
Fabian-Lars
cad5504455 fix(cli): Fix npm package name in tauri add (#12354) 2025-01-11 17:28:54 +01:00
renovate[bot]
f8e50e8e5b chore(deps): update rust crate tauri-winres to 0.2 (dev) (#12341)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-10 20:19:48 +01:00
renovate[bot]
cfe1af2848 chore(deps): update rust crate notify to v8 (dev) (#12342)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-10 20:02:53 +01:00
github-actions[bot]
89c6f08e82 Apply Version Updates From Current Changes (#12218)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-10 15:08:21 +01:00
Fabian-Lars
cde0ff7798 chore: Fix clippy 1.84 warnings (#12328) 2025-01-10 13:47:37 +01:00
renovate[bot]
b0d7527250 chore(deps): update rust crate windows-registry to 0.4 (dev) (#12301)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 23:04:03 +01:00
renovate[bot]
a28b5013c5 chore(deps): update rust crate ico to 0.4 (dev) (#12298)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 22:38:43 +01:00
Fabian-Lars
b9a99a5c69 fix(cli): Skip File Access events in dev server (#12297) 2025-01-07 21:11:24 +01:00
Marco Mengelkoch
98f62e65a2 fix(cli): tauri add NPM packages for community plugins (#12246)
It currently isn't possible to simply add a community plugin the same was as adding official plugins.
Trying to perform  `npm run tauri add tauri-plugin-python` is trying to install npm package `@tauri-apps/plugin-python`.
But the npm scope `@tauri-apps/` is reserved for official tauri plugins.

The official documentation recommends to name the npm package `tauri-plugin-{name}-api` and it should be possible to have a parameter that makes it possible to install that package.

- closes #12217

This changes the command to check if the plugin is an official tauri plugin or not, using the appropriate npm package name format

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
2025-01-07 10:16:35 -03:00
renovate[bot]
c130af6b06 chore(deps): update dependency rollup to v4.30.1 (dev) (#12291)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 13:48:40 +01:00
Lucas Fernandes Nogueira
ef21ed9ac1 fix(cli): iOS build crashing when development team has spaces (#12290)
Even though I couldn't even get the build to succeed when using the team name as the "developmentTeam" configuration (instead of the team ID), I've received reports that our processing of that value is broken and only works when it is escaped using `\"`.
2025-01-07 09:41:56 -03:00
Tony
cd1d026f97 fix: fails to build if the project path contains glob characters (#11961)
* Escape glob patterns

* Add change file

* Reword the change
2025-01-07 09:22:43 -03:00
Aurélien Jacobs
848d0e060e chore(deps): update cargo_toml for edition 2024 [fix #10412] (#12270)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-06 20:34:49 +01:00
Max Katz
ae75a353d0 chore: update copyright year (#12170)
Co-authored-by: Max Katz <zrxmax@icloud.com>
2025-01-06 13:46:06 +01:00
gerald
70f96e3222 chore(deps/driver): update hyper to version 1 (#12240)
Co-authored-by: Fabian-Lars <github@fabianlars.de>
2025-01-06 11:12:08 +01:00
renovate[bot]
3acf679c87 chore(deps): update dependency rollup to v4.30.0 (dev) (#12263)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 10:47:03 +01:00
renovate[bot]
22d5852208 chore(deps): update dependency rollup to v4.29.2 (dev) (#12238)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-05 14:58:18 +01:00
renovate[bot]
701778a195 chore(deps): update dependency fast-glob to v3.3.3 (dev) (#12233)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-05 12:46:30 +01:00
Patrick F.
a0f2c84d51 feat(cli): Add 64x64 png to default tauri icon command (#12204) 2025-01-04 23:26:18 +01:00
github-actions[bot]
f86e2387c9 apply version updates (#12183)
Co-authored-by: FabianLars <30730186+FabianLars@users.noreply.github.com>
2025-01-04 01:17:49 +01:00
Fabian-Lars
26fc9558fe fix(cli): Re-add TriggeredKill in dev watcher logic (#12178) 2025-01-04 00:39:07 +01:00
renovate[bot]
90dc7b19fc chore(deps): update rust crate which to v7 (dev) (#12144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 23:28:10 +01:00
renovate[bot]
c681d835d5 chore(deps): update dependency vite to v6 (dev) (#12133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: FabianLars <fabianlars@fabianlars.de>
2025-01-03 23:05:29 +01:00
Fabian-Lars
208d8968ce ci(deps): Update repository-dispatch to v3 (#12169) 2025-01-03 22:34:55 +01:00
Fabian-Lars
aaa7d9bb13 ci: Switch to upstream create-pull-request (#12123)
* ci: Switch to upstream create-pull-request

* what the actual f

* fix version comment

---------

Co-authored-by: Tillmann <28728469+tweidinger@users.noreply.github.com>
2025-01-03 22:48:50 +02:00
398 changed files with 23007 additions and 9234 deletions

View File

@@ -4,7 +4,7 @@
"feat": "New Features",
"enhance": "Enhancements",
"bug": "Bug Fixes",
"pref": "Performance Improvements",
"perf": "Performance Improvements",
"changes": "What's Changed",
"sec": "Security fixes",
"deps": "Dependencies",

View File

@@ -51,25 +51,47 @@ Hi! We, the maintainers, are really excited that you are interested in contribut
First, [join our Discord server](https://discord.gg/SpmNs4S) and let us know that you want to contribute. This way we can point you in the right direction and help ensure your contribution will be as helpful as possible.
To set up your machine for development, follow the [Tauri setup guide](https://v2.tauri.app/start/prerequisites/) to get all the tools you need to develop Tauri apps. The only additional tool you may need is [PNPM](https://pnpm.io/), it is only required if you are developing the Node CLI or API packages (`packages/cli` and `packages/api`). Next, fork and clone this repo. It is structured as a monorepo, which means that all the various Tauri packages are under the same repository. The development process varies depending on what part of Tauri you are contributing to, see the guides below for per-package instructions.
To set up your machine for development, follow the [Tauri setup guide](https://v2.tauri.app/start/prerequisites/) to get all the tools you need to develop Tauri apps. The only additional tool you may need is [PNPM](https://pnpm.io/), it is only required if you are developing the Node CLI or API packages (`packages/cli` and `packages/api`).
Some Tauri packages will be automatically built when running one of the examples. Others, however, will need to be built beforehand. To build these automatically, run the `.scripts/setup.sh` (Linux and macOS) or `.scripts/setup.ps1` (Windows) script. This will install the Rust and Node.js CLI and build the JS API. After that, you should be able to run all the examples. Note that the setup script should be executed from the root folder of the repository in order to run correctly.
Next, [fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) and clone [this repository](https://github.com/tauri-apps).
The development process varies depending on what part of Tauri you are contributing to, see the guides below for per-package instructions.
Some Tauri packages will be automatically built when running one of the examples. Others, however, will need to be built beforehand. To initialize, execute these commands in the repository root:
```bash
pnpm install
pnpm build
```
### Overview
See [Architecture](../ARCHITECTURE.md#major-components) for an overview of the packages in this repository.
### Developing Tauri Core and Related Components (Rust API, Macros, Codegen, and Utils)
The code for the Rust crates, including the Core, Macros, Utils, WRY runtime, and a few more are located in the [main Tauri repository](https://github.com/tauri-apps/tauri/tree/dev/crates).
The easiest way to test your changes is to use the [helloworld](https://github.com/tauri-apps/tauri/tree/dev/examples/helloworld) example app. It automatically rebuilds and uses your local copy of the Tauri core packages. Just run `cargo run --example helloworld` after making changes to test them out.
To test local changes against your own application simply point the Tauri create to your local repository. In `src-tauri/Cargo.toml` file change:
`tauri = { version = "2.1.1" }`
to:
`tauri = { path = "path/to/local/tauri/crates/tauri" }`
If any other crates depend on Tauri you will have to point them to the local repo as well.
### Developing Tauri Bundler and Rust CLI
The code for the bundler is located in `[Tauri repo root]/crates/tauri-bundler`, and the code for the Rust CLI is located in `[Tauri repo root]/crates/tauri-cli`. If you are using your local copy of `@tauri-apps/cli` (see above), any changes you make to the bundler and CLI will be automatically built and applied when running the build or dev command. Otherwise, running `cargo install --path .` in the Rust CLI directory will allow you to run `cargo tauri build` and `cargo tauri dev` anywhere, using the updated copy of the bundler and cli. You will have to run this command each time you make a change in either package.
The code for the bundler is located in [crates/tauri-bundler](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-bundler), and the code for the Rust CLI is located in [tauri-cli](https://github.com/tauri-apps/tauri/tree/dev/crates/tauri-cli).
Running `cargo install --path .` in the Rust CLI directory will allow you to run `cargo tauri build` and `cargo tauri dev` anywhere, using the updated copy of the bundler and cli. You will have to run this command each time you make a change in either package.
You can use `cargo install --path . --debug` to speed up test builds.
### Developing The Node.js CLI (`@tauri-apps/cli`)
`@tauri-apps/cli` is a wrapper to `tauri-cli` so most changes should be written on the Rust CLI. The `[Tauri repo root]/crates/tauri-cli` folder contains only packaging scripts to properly publish the Rust CLI binaries to NPM.
### Developing Tauri Core and Related Components (Rust API, Macros, Codegen, and Utils)
The code for the Rust crates, including the Core, Macros, Utils, WRY runtime, and a few more are located in `[Tauri repo root]/crates/tauri-(macros/utils)`. The easiest way to test your changes is to use the `[Tauri repo root]/examples/helloworld` app. It automatically rebuilds and uses your local copy of the Tauri core packages. Just run `cargo run --example helloworld` after making changes to test them out.
[`@tauri-apps/cli`](https://github.com/tauri-apps/tauri/tree/dev/packages/cli) is a small wrapper around `tauri-cli` so most changes should be happen in the Rust CLI (see above).
#### Building the documentation locally
@@ -81,7 +103,8 @@ $ RUSTDOCFLAGS="--cfg docsrs" cargo +nightly doc --all-features --open
### Developing the JS API
The JS API provides bindings between the developer's JS in the Webview and the builtin Tauri APIs, written in Rust. Its code is located in `[Tauri repo root]/packages/api`. After making changes to the code, run `pnpm build` to build it. To test your changes, we recommend using the API example app, located in `[Tauri repo root]/examples/api`. It will automatically use your local copy of the JS API and provides a helpful UI to test the various commands.
The JS API provides bindings between the developer's JS in the Webview and the built-in Tauri APIs, written in Rust. Its code is located in [/packages/api](https://github.com/tauri-apps/tauri/tree/dev/packages/api).
After making changes to the code, run `pnpm build` to build it. To test your changes, we recommend using the API example app, located in [/examples/api](https://github.com/tauri-apps/tauri/tree/dev/examples/api). It will automatically use your local copy of the JS API and provides a helpful UI to test the various commands.
## Financial Contribution

View File

@@ -33,11 +33,6 @@ Releasing can be as easy as merging the version pull request but here is a check
- [ ] Double check that every package is bumped correctly and there are no accidental major or minor being released unless that is indeed the intention.
- [ ] Make sure that there are no pending or unfinished [covector-version-or-publish.yml](./workflows/covector-version-or-publish.yml) workflow runs.
- [ ] Sign the Version PR before merging as we require signed commits
- [ ] `git fetch --all`
- [ ] `git checkout release/version-updates`
- [ ] `git commit --amend -S`
- [ ] `git push --force`
- [ ] Approve and merge the version pull request
## Publishing failed, what to do?

View File

@@ -34,7 +34,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'

View File

@@ -8,6 +8,7 @@ on:
pull_request:
paths:
- '.github/workflows/check-generated-files.yml'
- 'pnpm-lock.yaml'
- 'packages/api/src/**'
- 'crates/tauri/scripts/bundle.global.js'
- 'crates/tauri-utils/src/config.rs'
@@ -31,6 +32,7 @@ jobs:
with:
filters: |
api:
- 'pnpm-lock.yaml'
- 'packages/api/src/**'
- 'crates/tauri/scripts/bundle.global.js'
schema:
@@ -44,7 +46,7 @@ jobs:
if: needs.changes.outputs.api == 'true'
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'

View File

@@ -23,7 +23,7 @@ jobs:
with:
fetch-depth: 0
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 20
@@ -73,7 +73,7 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 20
@@ -111,7 +111,7 @@ jobs:
- name: Create Pull Request With Versions Bumped
if: steps.covector.outputs.commandRan == 'version'
uses: tauri-apps/create-pull-request@v3
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # 7.0.6
with:
token: ${{ secrets.GITHUB_TOKEN }}
branch: release/version-updates
@@ -119,12 +119,13 @@ jobs:
commit-message: 'apply version updates'
labels: 'version updates'
body: ${{ steps.covector.outputs.change }}
sign-commits: true
- name: Trigger doc update
if: |
steps.covector.outputs.successfulPublish == 'true' &&
steps.covector.outputs.packagesPublished != ''
uses: peter-evans/repository-dispatch@v1
uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # 3.0.0
with:
token: ${{ secrets.ORG_TAURI_BOT_PAT }}
repository: tauri-apps/tauri-docs

View File

@@ -66,7 +66,7 @@ jobs:
with:
targets: ${{ matrix.target.name }}
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
with:

View File

@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'

View File

@@ -19,7 +19,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'
@@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- uses: actions/setup-node@v4
with:
node-version: 'lts/*'

View File

@@ -10,7 +10,7 @@ on:
- dev
pull_request:
paths:
- '.github/workflows/lint-cli.yml'
- '.github/workflows/lint-rust.yml'
- 'crates/**'
env:

View File

@@ -43,15 +43,16 @@ jobs:
- host: windows-latest
architecture: x64
target: aarch64-pc-windows-msvc
build: pnpm build --target aarch64-pc-windows-msvc --features native-tls-vendored --cargo-flags="--no-default-features"
- host: ubuntu-20.04
build: pnpm build --target aarch64-pc-windows-msvc
- host: ubuntu-22.04
target: x86_64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian
build: |
npm i -g --force corepack
cd packages/cli
pnpm build --target x86_64-unknown-linux-gnu
strip *.node
- host: ubuntu-20.04
- host: ubuntu-22.04
target: x86_64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
build: |
@@ -63,14 +64,15 @@ jobs:
build: |
pnpm build --features native-tls-vendored --target=aarch64-apple-darwin
strip -x *.node
- host: ubuntu-20.04
- host: ubuntu-22.04
target: aarch64-unknown-linux-gnu
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-debian-aarch64
build: |
npm i -g --force corepack
cd packages/cli
pnpm build --target aarch64-unknown-linux-gnu
aarch64-unknown-linux-gnu-strip *.node
- host: ubuntu-20.04
- host: ubuntu-22.04
architecture: x64
target: armv7-unknown-linux-gnueabihf
setup: |
@@ -79,7 +81,7 @@ jobs:
build: |
pnpm build --target=armv7-unknown-linux-gnueabihf
arm-linux-gnueabihf-strip *.node
- host: ubuntu-20.04
- host: ubuntu-22.04
architecture: x64
target: aarch64-unknown-linux-musl
docker: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
@@ -88,11 +90,20 @@ jobs:
rustup target add aarch64-unknown-linux-musl
pnpm build --target aarch64-unknown-linux-musl
/aarch64-linux-musl-cross/bin/aarch64-linux-musl-strip *.node
- host: ubuntu-22.04
architecture: x64
target: riscv64gc-unknown-linux-gnu
setup: |
sudo apt-get update
sudo apt-get install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu -y
build: |
pnpm build --target=riscv64gc-unknown-linux-gnu
riscv64-linux-gnu-strip *.node
name: stable - ${{ matrix.settings.target }} - node@20
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
if: ${{ !matrix.settings.docker }}
@@ -202,7 +213,7 @@ jobs:
runs-on: ${{ matrix.settings.host }}
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
with:
@@ -233,7 +244,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
with:
@@ -270,7 +281,7 @@ jobs:
image: ghcr.io/napi-rs/napi-rs/nodejs-rust:lts-alpine
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
with:
@@ -308,7 +319,6 @@ jobs:
- '20'
image:
- ghcr.io/napi-rs/napi-rs/nodejs:aarch64-16
- ghcr.io/napi-rs/napi-rs/nodejs:armhf-16
runs-on: ubuntu-latest
steps:
- run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
@@ -361,7 +371,7 @@ jobs:
id-token: write # npm provenance
steps:
- uses: actions/checkout@v4
- run: corepack enable
- run: npm i -g --force corepack
- name: Setup node
uses: actions/setup-node@v4
with:

View File

@@ -18,7 +18,7 @@ jobs:
fail-fast: false
matrix:
config:
- os: ubuntu-20.04
- os: ubuntu-22.04
rust_target: x86_64-unknown-linux-gnu
ext: ''
args: ''
@@ -37,7 +37,7 @@ jobs:
- os: windows-latest
rust_target: aarch64-pc-windows-msvc
ext: '.exe'
args: '--no-default-features --features native-tls-vendored'
args: ''
steps:
- uses: actions/checkout@v4

View File

@@ -42,7 +42,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y libgtk-3-dev webkit2gtk-4.1
- run: corepack enable
- run: npm i -g --force corepack
- name: setup node
uses: actions/setup-node@v4
with:

View File

@@ -11,6 +11,7 @@ on:
pull_request:
paths:
- '.github/workflows/test-cli-js.yml'
- 'packages/cli/**'
# currently` @tauri-apps/cli` only tests the template
- 'crates/tauri-cli/templates/app/**'
@@ -37,7 +38,7 @@ jobs:
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
- run: corepack enable
- run: npm i -g --force corepack
- name: setup node
uses: actions/setup-node@v4
with:

View File

@@ -90,15 +90,15 @@ jobs:
- uses: Swatinem/rust-cache@v2
with:
prefix-key: v2
prefix-key: v3
save-if: ${{ matrix.features.key == 'all' }}
- name: test
if: ${{ !matrix.platform.cross }}
run: cargo ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml
run: cargo ${{ matrix.features.key == 'no-default' && 'check' || matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml
- name: test (using cross)
if: ${{ matrix.platform.cross }}
run: |
cargo install cross --git https://github.com/cross-rs/cross --rev ac4c11cedc97cd7c27faed36e55377a90e6ed618 --locked
cross ${{ matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml
cargo install cross --git https://github.com/cross-rs/cross --rev 51f46f296253d8122c927c5bb933e3c4f27cc317 --locked
cross ${{ matrix.features.key == 'no-default' && 'check' || matrix.platform.command }} --target ${{ matrix.platform.target }} ${{ matrix.features.args }} --manifest-path crates/tauri/Cargo.toml

107
.gitignore vendored
View File

@@ -1,52 +1,55 @@
# dependency directories
node_modules/
# Optional npm and yarn cache directory
.npm/
.yarn/
# Output of 'npm pack'
*.tgz
# dotenv environment variables file
.env
# .vscode workspace settings file
.vscode/settings.json
# npm, yarn and bun lock files
package-lock.json
yarn.lock
bun.lockb
# rust compiled folders
target/
# test video for streaming example
streaming_example_test_video.mp4
# examples /gen directory
/examples/**/src-tauri/gen/
/bench/**/src-tauri/gen/
# logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# runtime data
pids
*.pid
*.seed
*.pid.lock
# miscellaneous
/.vs
.DS_Store
.Thumbs.db
*.sublime*
.idea
debug.log
TODO.md
# dependency directories
node_modules/
# Optional npm and yarn cache directory
.npm/
.yarn/
# Output of 'npm pack'
*.tgz
# dotenv environment variables file
.env
# .vscode workspace settings file
.vscode/settings.json
.vscode/launch.json
.vscode/tasks.json
# npm, yarn and bun lock files
package-lock.json
yarn.lock
bun.lockb
# rust compiled folders
target/
# test video for streaming example
streaming_example_test_video.mp4
# examples /gen directory
/examples/**/src-tauri/gen/
/bench/**/src-tauri/gen/
# logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# runtime data
pids
*.pid
*.seed
*.pid.lock
# miscellaneous
/.vs
.DS_Store
.Thumbs.db
*.sublime*
.idea
debug.log
TODO.md
.aider*

View File

@@ -1,5 +1,6 @@
{
"singleQuote": true,
"semi": false,
"trailingComma": "none"
"trailingComma": "none",
"experimentalOperatorPosition": "start"
}

View File

@@ -28,8 +28,8 @@ const ignore = [
async function checkFile(file) {
if (
extensions.some((e) => file.endsWith(e)) &&
!ignore.some((i) => file.includes(`/${i}/`) || path.basename(file) == i)
extensions.some((e) => file.endsWith(e))
&& !ignore.some((i) => file.includes(`/${i}/`) || path.basename(file) == i)
) {
const fileStream = fs.createReadStream(file)
const rl = readline.createInterface({
@@ -42,11 +42,11 @@ async function checkFile(file) {
for await (let line of rl) {
// ignore empty lines, allow shebang and bundler license
if (
line.length === 0 ||
line.startsWith('#!') ||
line.startsWith('// swift-tools-version:') ||
line === bundlerLicense ||
line === denoLicense
line.length === 0
|| line.startsWith('#!')
|| line.startsWith('// swift-tools-version:')
|| line === bundlerLicense
|| line === denoLicense
) {
continue
}

3731
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -70,3 +70,4 @@ opt-level = "s"
[patch.crates-io]
schemars_derive = { git = 'https://github.com/tauri-apps/schemars.git', branch = 'feat/preserve-description-newlines' }
tauri = { path = "./crates/tauri" }
tauri-plugin = { path = "./crates/tauri-plugin" }

View File

@@ -6,7 +6,7 @@ PackageSupplier: Organization: The Tauri Programme in the Commons Conservancy
PackageHomePage: https://tauri.app
PackageLicenseDeclared: Apache-2.0
PackageLicenseDeclared: MIT
PackageCopyrightText: 2019-2024, The Tauri Programme in the Commons Conservancy
PackageCopyrightText: 2019-2025, The Tauri Programme in the Commons Conservancy
PackageSummary: <text>Tauri is a rust project that enables developers to make secure
and small desktop applications using a web frontend.
</text>

View File

@@ -4,7 +4,7 @@
[![License](https://img.shields.io/badge/License-MIT%20or%20Apache%202-green.svg)](https://opencollective.com/tauri)
[![test core](https://img.shields.io/github/actions/workflow/status/tauri-apps/tauri/test-core.yml?label=test%20core&logo=github)](https://github.com/tauri-apps/tauri/actions/workflows/test-core.yml)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Ftauri-apps%2Ftauri?ref=badge_shield)
[![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.gg/SpmNs4S)
[![Chat Server](https://img.shields.io/badge/chat-discord-7289da.svg)](https://discord.com/invite/tauri)
[![website](https://img.shields.io/badge/website-tauri.app-purple.svg)](https://tauri.app)
[![https://good-labs.github.io/greater-good-affirmation/assets/images/badge.svg](https://good-labs.github.io/greater-good-affirmation/assets/images/badge.svg)](https://good-labs.github.io/greater-good-affirmation)
[![support](https://img.shields.io/badge/sponsor-Open%20Collective-blue.svg)](https://opencollective.com/tauri)
@@ -35,7 +35,7 @@ The list of Tauri's features includes, but is not limited to:
- Built-in self updater (desktop only)
- System tray icons
- Native notifications
- [Localhost free (🔥)](https://github.com/tauri-apps/tauri/issues/10510)
- Native WebView Protocol (tauri doesn't create a localhost http(s) server to serve the WebView contents)
- GitHub action for streamlined CI
- VS Code extension
@@ -43,13 +43,13 @@ The list of Tauri's features includes, but is not limited to:
Tauri currently supports development and distribution on the following platforms:
| Platform | Versions |
| :---------------- | :-------------------------------------------------------------------------------------------------------------- |
| Windows | 7 and above |
| macOS | 10.15 and above |
| Linux | webkit2gtk 4.0 for Tauri v1 (for example Ubuntu 18.04). webkit2gtk 4.1 for Tauri v2 (for example Ubuntu 22.04). |
| iOS/iPadOS (beta) | 9 and above |
| Android (beta) | 7 and above |
| Platform | Versions |
| :--------- | :-------------------------------------------------------------------------------------------------------------- |
| Windows | 7 and above |
| macOS | 10.15 and above |
| Linux | webkit2gtk 4.0 for Tauri v1 (for example Ubuntu 18.04). webkit2gtk 4.1 for Tauri v2 (for example Ubuntu 22.04). |
| iOS/iPadOS | 9 and above |
| Android | 7 and above (currently 8 and above) |
## Contributing

View File

@@ -52,7 +52,7 @@ fn main() {
.expect("Something wrong with tauri_data"),
&serde_json::to_value(all_data).expect("Unable to build final json (all)"),
)
.unwrap_or_else(|_| panic!("Unable to write {:?}", tauri_data));
.unwrap_or_else(|_| panic!("Unable to write {tauri_data:?}"));
utils::write_json(
tauri_recent
@@ -60,5 +60,5 @@ fn main() {
.expect("Something wrong with tauri_recent"),
&serde_json::to_value(recent).expect("Unable to build final json (recent)"),
)
.unwrap_or_else(|_| panic!("Unable to write {:?}", tauri_recent));
.unwrap_or_else(|_| panic!("Unable to write {tauri_recent:?}"));
}

View File

@@ -89,7 +89,7 @@ fn run_max_mem_benchmark() -> Result<HashMap<String, u64>> {
let mut results = HashMap::<String, u64>::new();
for (name, example_exe) in get_all_benchmarks() {
let benchmark_file = utils::target_dir().join(format!("mprof{}_.dat", name));
let benchmark_file = utils::target_dir().join(format!("mprof{name}_.dat"));
let benchmark_file = benchmark_file.to_str().unwrap();
let proc = Command::new("mprof")
@@ -105,7 +105,7 @@ fn run_max_mem_benchmark() -> Result<HashMap<String, u64>> {
.spawn()?;
let proc_result = proc.wait_with_output()?;
println!("{:?}", proc_result);
println!("{proc_result:?}");
results.insert(
name.to_string(),
utils::parse_max_mem(benchmark_file).unwrap(),
@@ -126,11 +126,11 @@ fn rlib_size(target_dir: &std::path::Path, prefix: &str) -> u64 {
if name.starts_with(prefix) && name.ends_with(".rlib") {
let start = name.split('-').next().unwrap().to_string();
if seen.contains(&start) {
println!("skip {}", name);
println!("skip {name}");
} else {
seen.insert(start);
size += entry.metadata().unwrap().len();
println!("check size {} {}", name, size);
println!("check size {name} {size}");
}
}
}
@@ -142,7 +142,7 @@ fn get_binary_sizes(target_dir: &Path) -> Result<HashMap<String, u64>> {
let mut sizes = HashMap::<String, u64>::new();
let wry_size = rlib_size(target_dir, "libwry");
println!("wry {} bytes", wry_size);
println!("wry {wry_size} bytes");
sizes.insert("wry_rlib".to_string(), wry_size);
// add size for all EXEC_TIME_BENCHMARKS

View File

@@ -96,8 +96,8 @@ pub fn run_collect(cmd: &[&str]) -> (String, String) {
let stdout = String::from_utf8_lossy(&stdout).to_string();
let stderr = String::from_utf8_lossy(&stderr).to_string();
if !status.success() {
eprintln!("stdout: <<<{}>>>", stdout);
eprintln!("stderr: <<<{}>>>", stderr);
eprintln!("stdout: <<<{stdout}>>>");
eprintln!("stderr: <<<{stderr}>>>");
panic!("Unexpected exit code: {:?}", status.code());
}
(stdout, stderr)
@@ -230,7 +230,7 @@ pub fn download_file(url: &str, filename: PathBuf) {
// Downloading with curl this saves us from adding
// a Rust HTTP client dependency.
println!("Downloading {}", url);
println!("Downloading {url}");
let status = Command::new("curl")
.arg("-L")
.arg("-s")

View File

@@ -1,6 +1,7 @@
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
Arial, sans-serif;
font-family:
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial,
sans-serif;
margin: auto;
max-width: 38rem;
padding: 2rem;

View File

@@ -1,5 +1,70 @@
# Changelog
## \[2.4.0]
### Dependencies
- Upgraded to `tauri-utils@2.7.0`
- Upgraded to `tauri-codegen@2.4.0`
## \[2.3.1]
### Dependencies
- Upgraded to `tauri-utils@2.6.0`
- Upgraded to `tauri-codegen@2.3.1`
## \[2.2.1]
### Dependencies
- Upgraded to `tauri-codegen@2.3.0`
- Upgraded to `tauri-utils@2.5.0`
## \[2.2.0]
### Dependencies
- Upgraded to `tauri-utils@2.4.0`
- Upgraded to `tauri-codegen@2.2.0`
- [`48b12b440`](https://www.github.com/tauri-apps/tauri/commit/48b12b440478937c46fdfef9f9d95194be117020) Update to `tauri-utils@2.4.0`
## \[2.1.1]
### Dependencies
- Upgraded to `tauri-utils@2.3.1`
- Upgraded to `tauri-codegen@2.1.1`
## \[2.1.0]
### New Features
- [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Added `build > removeUnusedCommands` to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. Note this won't be accounting for dynamically added ACLs so make sure to check it when using this.
### Performance Improvements
- [`1cd8f55ee`](https://www.github.com/tauri-apps/tauri/commit/1cd8f55eed326d61860fee62ba2d2f4464bdcfcc) ([#13033](https://www.github.com/tauri-apps/tauri/pull/13033) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Don't ship global `bundle.global.js` if `app > withGlobalTauri` is set to false
### Dependencies
- Upgraded to `tauri-utils@2.3.0`
- Upgraded to `tauri-codegen@2.1.0`
## \[2.0.6]
### Dependencies
- Upgraded to `tauri-utils@2.2.0`
- Upgraded to `tauri-codegen@2.0.5`
## \[2.0.5]
### Bug Fixes
- [`848d0e060`](https://www.github.com/tauri-apps/tauri/commit/848d0e060e6eb3c8e9e8175adc7896587b5a947d) ([#12270](https://www.github.com/tauri-apps/tauri/pull/12270) by [@aurelj](https://www.github.com/tauri-apps/tauri/../../aurelj)) Update `cargo_toml` to `0.21.0`. This adds compatibility with Rust's 2024 Edition.
- [`cd1d026f9`](https://www.github.com/tauri-apps/tauri/commit/cd1d026f9799c26b04acb64f49e7ee0a8b193049) ([#11961](https://www.github.com/tauri-apps/tauri/pull/11961) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix tauri fails to build if the project path contains glob characters
## \[2.0.4]
### Dependencies

View File

@@ -1,6 +1,6 @@
[package]
name = "tauri-build"
version = "2.0.4"
version = "2.4.0"
description = "build time code to pair with https://crates.io/crates/tauri"
exclude = ["CHANGELOG.md", "/target"]
readme = "README.md"
@@ -28,24 +28,24 @@ rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
anyhow = "1"
quote = { version = "1", optional = true }
tauri-codegen = { version = "2.0.4", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "2.1.1", path = "../tauri-utils", features = [
tauri-codegen = { version = "2.4.0", path = "../tauri-codegen", optional = true }
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
"build",
"resources",
] }
cargo_toml = "0.17"
cargo_toml = "0.22"
serde = "1"
serde_json = "1"
heck = "0.5"
json-patch = "3"
walkdir = "2"
tauri-winres = "0.1"
tauri-winres = "0.3"
semver = "1"
dirs = "5"
dirs = "6"
glob = "0.3"
toml = "0.8"
# Our code requires at least 0.8.18 so don't simplify this to 0.8
schemars = { version = "0.8.18", features = ["preserve_order"] }
toml = "0.9"
# Our code requires at least 0.8.21 so don't simplify this to 0.8
schemars = { version = "0.8.21", features = ["preserve_order"] }
[features]
default = ["config-json"]

View File

@@ -11,7 +11,9 @@ use std::{
use anyhow::{Context, Result};
use tauri_utils::{
acl::{
capability::Capability, manifest::Manifest, schema::CAPABILITIES_SCHEMA_FOLDER_PATH,
capability::Capability,
manifest::{Manifest, PermissionFile},
schema::CAPABILITIES_SCHEMA_FOLDER_PATH,
ACL_MANIFESTS_FILE_NAME, APP_ACL_KEY, CAPABILITIES_FILE_NAME,
},
platform::Target,
@@ -155,11 +157,17 @@ fn read_plugins_manifests() -> Result<BTreeMap<String, Manifest>> {
Ok(manifests)
}
struct InlinedPuginsAcl {
manifests: BTreeMap<String, Manifest>,
permission_files: BTreeMap<String, Vec<PermissionFile>>,
}
fn inline_plugins(
out_dir: &Path,
inlined_plugins: HashMap<&'static str, InlinedPlugin>,
) -> Result<BTreeMap<String, Manifest>> {
) -> Result<InlinedPuginsAcl> {
let mut acl_manifests = BTreeMap::new();
let mut permission_files_map = BTreeMap::new();
for (name, plugin) in inlined_plugins {
let plugin_out_dir = out_dir.join("plugins").join(name);
@@ -199,7 +207,9 @@ permissions = [{default_permissions}]
}
tauri_utils::acl::build::define_permissions(
&plugin_out_dir.join("*").to_string_lossy(),
&PathBuf::from(glob::Pattern::escape(&plugin_out_dir.to_string_lossy()))
.join("*")
.to_string_lossy(),
name,
&plugin_out_dir,
|_| true,
@@ -222,28 +232,41 @@ permissions = [{default_permissions}]
);
}
permission_files.extend(tauri_utils::acl::build::define_permissions(
&default_permissions_path
.join("**")
.join("*")
.to_string_lossy(),
&PathBuf::from(glob::Pattern::escape(
&default_permissions_path.to_string_lossy(),
))
.join("**")
.join("*")
.to_string_lossy(),
name,
&plugin_out_dir,
|_| true,
)?);
}
permission_files_map.insert(name.into(), permission_files.clone());
let manifest = tauri_utils::acl::manifest::Manifest::new(permission_files, None);
acl_manifests.insert(name.into(), manifest);
}
Ok(acl_manifests)
Ok(InlinedPuginsAcl {
manifests: acl_manifests,
permission_files: permission_files_map,
})
}
#[derive(Debug)]
struct AppManifestAcl {
manifest: Manifest,
permission_files: Vec<PermissionFile>,
}
fn app_manifest_permissions(
out_dir: &Path,
manifest: AppManifest,
inlined_plugins: &HashMap<&'static str, InlinedPlugin>,
) -> Result<Manifest> {
) -> Result<AppManifestAcl> {
let app_out_dir = out_dir.join("app-manifest");
fs::create_dir_all(&app_out_dir)?;
let pkg_name = "__app__";
@@ -286,6 +309,7 @@ fn app_manifest_permissions(
let inlined_plugins_permissions: Vec<_> = inlined_plugins
.keys()
.map(|name| permissions_root.join(name))
.flat_map(|p| p.canonicalize())
.collect();
permission_files.extend(tauri_utils::acl::build::define_permissions(
@@ -304,10 +328,10 @@ fn app_manifest_permissions(
)?);
}
Ok(tauri_utils::acl::manifest::Manifest::new(
permission_files,
None,
))
Ok(AppManifestAcl {
permission_files: permission_files.clone(),
manifest: tauri_utils::acl::manifest::Manifest::new(permission_files, None),
})
}
fn validate_capabilities(
@@ -376,19 +400,21 @@ fn validate_capabilities(
pub fn build(out_dir: &Path, target: Target, attributes: &Attributes) -> super::Result<()> {
let mut acl_manifests = read_plugins_manifests()?;
let app_manifest = app_manifest_permissions(
let app_acl = app_manifest_permissions(
out_dir,
attributes.app_manifest,
&attributes.inlined_plugins,
)?;
if app_manifest.default_permission.is_some()
|| !app_manifest.permission_sets.is_empty()
|| !app_manifest.permissions.is_empty()
{
acl_manifests.insert(APP_ACL_KEY.into(), app_manifest);
let has_app_manifest = app_acl.manifest.default_permission.is_some()
|| !app_acl.manifest.permission_sets.is_empty()
|| !app_acl.manifest.permissions.is_empty();
if has_app_manifest {
acl_manifests.insert(APP_ACL_KEY.into(), app_acl.manifest);
}
acl_manifests.extend(inline_plugins(out_dir, attributes.inlined_plugins.clone())?);
let inline_plugins_acl = inline_plugins(out_dir, attributes.inlined_plugins.clone())?;
acl_manifests.extend(inline_plugins_acl.manifests);
let acl_manifests_path = save_acl_manifests(&acl_manifests)?;
fs::copy(acl_manifests_path, out_dir.join(ACL_MANIFESTS_FILE_NAME))?;
@@ -406,7 +432,12 @@ pub fn build(out_dir: &Path, target: Target, attributes: &Attributes) -> super::
let capabilities_path = save_capabilities(&capabilities)?;
fs::copy(capabilities_path, out_dir.join(CAPABILITIES_FILE_NAME))?;
tauri_utils::plugin::save_global_api_scripts_paths(out_dir);
let mut permissions_map = inline_plugins_acl.permission_files;
if has_app_manifest {
permissions_map.insert(APP_ACL_KEY.to_string(), app_acl.permission_files);
}
tauri_utils::acl::build::generate_allowed_commands(out_dir, Some(capabilities), permissions_map)?;
Ok(())
}

View File

@@ -68,7 +68,7 @@ fn copy_binaries(
.to_string_lossy()
.replace(&format!("-{target_triple}"), "");
if package_name.map_or(false, |n| n == &file_name) {
if package_name == Some(&file_name) {
return Err(anyhow::anyhow!(
"Cannot define a sidecar with the same name as the Cargo package name `{}`. Please change the sidecar name in the filesystem and the Tauri configuration.",
file_name
@@ -367,6 +367,8 @@ impl Attributes {
/// Set the glob pattern to be used to find the capabilities.
///
/// **WARNING:** The `removeUnusedCommands` option does not work with a custom capabilities path.
///
/// **Note:** You must emit [rerun-if-changed] instructions for your capabilities directory.
///
/// [rerun-if-changed]: https://doc.rust-lang.org/cargo/reference/build-scripts.html#rerun-if-changed
@@ -419,23 +421,26 @@ pub fn is_dev() -> bool {
/// Run all build time helpers for your Tauri Application.
///
/// The current helpers include the following:
/// * Generates a Windows Resource file when targeting Windows.
/// To provide extra configuration, such as [`AppManifest::commands`]
/// for fine-grained control over command permissions, see [`try_build`].
/// See [`Attributes`] for the complete list of configuration options.
///
/// # Platforms
///
/// [`build()`] should be called inside of `build.rs` regardless of the platform:
/// * New helpers may target more platforms in the future.
/// * Platform specific code is handled by the helpers automatically.
/// * A build script is required in order to activate some cargo environmental variables that are
/// used when generating code and embedding assets - so [`build()`] may as well be called.
/// [`build()`] should be called inside of `build.rs` regardless of the platform, so **DO NOT** use a [conditional compilation]
/// check that prevents it from running on any of your targets.
///
/// In short, this is saying don't put the call to [`build()`] behind a `#[cfg(windows)]`.
/// Platform specific code is handled by the helpers automatically.
///
/// A build script is required in order to activate some cargo environmental variables that are
/// used when generating code and embedding assets.
///
/// # Panics
///
/// If any of the build time helpers fail, they will [`std::panic!`] with the related error message.
/// This is typically desirable when running inside a build script; see [`try_build`] for no panics.
///
/// [conditional compilation]: https://web.mit.edu/rust-lang_v1.25/arch/amd64_ubuntu1404/share/doc/rust/html/book/first-edition/conditional-compilation.html
pub fn build() {
if let Err(error) = try_build(Attributes::default()) {
let error = format!("{error:#}");
@@ -450,18 +455,12 @@ pub fn build() {
}
}
/// Non-panicking [`build()`].
/// Same as [`build()`], but takes an extra configuration argument, and does not panic.
#[allow(unused_variables)]
pub fn try_build(attributes: Attributes) -> Result<()> {
use anyhow::anyhow;
println!("cargo:rerun-if-env-changed=TAURI_CONFIG");
#[cfg(feature = "config-json")]
println!("cargo:rerun-if-changed=tauri.conf.json");
#[cfg(feature = "config-json5")]
println!("cargo:rerun-if-changed=tauri.conf.json5");
#[cfg(feature = "config-toml")]
println!("cargo:rerun-if-changed=Tauri.toml");
let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap();
let mobile = target_os == "ios" || target_os == "android";
@@ -471,12 +470,11 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
let target_triple = env::var("TARGET").unwrap();
let target = tauri_utils::platform::Target::from_triple(&target_triple);
let (config, merged_config_path) =
tauri_utils::config::parse::read_from(target, env::current_dir().unwrap())?;
if let Some(merged_config_path) = merged_config_path {
println!("cargo:rerun-if-changed={}", merged_config_path.display());
let (mut config, config_paths) =
tauri_utils::config::parse::read_from(target, &env::current_dir().unwrap())?;
for config_file_path in config_paths {
println!("cargo:rerun-if-changed={}", config_file_path.display());
}
let mut config = serde_json::from_value(config)?;
if let Ok(env) = env::var("TAURI_CONFIG") {
let merge_config: serde_json::Value = serde_json::from_str(&env)?;
json_patch::merge(&mut config, &merge_config);
@@ -506,19 +504,8 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
cfg_alias("dev", is_dev());
let ws_path = get_workspace_dir()?;
let mut manifest =
Manifest::<cargo_toml::Value>::from_slice_with_metadata(&fs::read("Cargo.toml")?)?;
if let Ok(ws_manifest) = Manifest::from_path(ws_path.join("Cargo.toml")) {
Manifest::complete_from_path_and_workspace(
&mut manifest,
Path::new("Cargo.toml"),
Some((&ws_manifest, ws_path.as_path())),
)?;
} else {
Manifest::complete_from_path(&mut manifest, Path::new("Cargo.toml"))?;
}
let cargo_toml_path = Path::new("Cargo.toml").canonicalize()?;
let mut manifest = Manifest::<cargo_toml::Value>::from_path_with_metadata(cargo_toml_path)?;
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
@@ -526,6 +513,8 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
acl::build(&out_dir, target, &attributes)?;
tauri_utils::plugin::save_global_api_scripts_paths(&out_dir, None);
println!("cargo:rustc-env=TAURI_ENV_TARGET_TRIPLE={target_triple}");
// when running codegen in this build script, we need to access the env var directly
env::set_var("TAURI_ENV_TARGET_TRIPLE", &target_triple);
@@ -541,7 +530,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
if let Some(paths) = &config.bundle.external_bin {
copy_binaries(
ResourcePaths::new(external_binaries(paths, &target_triple).as_slice(), true),
ResourcePaths::new(&external_binaries(paths, &target_triple, &target), true),
&target_triple,
target_dir,
manifest.package.as_ref().map(|p| &p.name),
@@ -624,7 +613,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
if let Some(version_str) = &config.version {
if let Ok(v) = Version::parse(version_str) {
let version = v.major << 48 | v.minor << 32 | v.patch << 16;
let version = (v.major << 48) | (v.minor << 32) | (v.patch << 16);
res.set_version_info(VersionInfo::FILEVERSION, version);
res.set_version_info(VersionInfo::PRODUCTVERSION, version);
}
@@ -634,6 +623,17 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
res.set("ProductName", product_name);
}
let company_name = config.bundle.publisher.unwrap_or_else(|| {
config
.identifier
.split('.')
.nth(1)
.unwrap_or(&config.identifier)
.to_string()
});
res.set("CompanyName", &company_name);
let file_description = config
.product_name
.or_else(|| manifest.package.as_ref().map(|p| p.name.clone()))
@@ -686,7 +686,7 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
}
}
"msvc" => {
if env::var("STATIC_VCRUNTIME").map_or(false, |v| v == "true") {
if env::var("STATIC_VCRUNTIME").is_ok_and(|v| v == "true") {
static_vcruntime::build();
}
}
@@ -701,23 +701,3 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
Ok(())
}
#[derive(serde::Deserialize)]
struct CargoMetadata {
workspace_root: PathBuf,
}
fn get_workspace_dir() -> Result<PathBuf> {
let output = std::process::Command::new("cargo")
.args(["metadata", "--no-deps", "--format-version", "1"])
.output()?;
if !output.status.success() {
return Err(anyhow::anyhow!(
"cargo metadata command exited with a non zero exit code: {}",
String::from_utf8(output.stderr)?
));
}
Ok(serde_json::from_slice::<CargoMetadata>(&output.stdout)?.workspace_root)
}

View File

@@ -1,5 +1,146 @@
# Changelog
## \[2.6.0]
### New Features
- [`a9ec12843`](https://www.github.com/tauri-apps/tauri/commit/a9ec12843aa7d0eb774bd3a53e2e63da12cfa77b) ([#13521](https://www.github.com/tauri-apps/tauri/pull/13521) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added a `--skip-stapling` option to make `tauri build|bundle` *not* wait for notarization to finish on macOS.
### Enhancements
- [`8b465a12b`](https://www.github.com/tauri-apps/tauri/commit/8b465a12ba73e94d7a3995defd9cc362d15eeebe) ([#13913](https://www.github.com/tauri-apps/tauri/pull/13913) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler now pulls the latest AppImage linuxdeploy plugin instead of using the built-in one. This should remove the libfuse requirement.
- [`4475e93e1`](https://www.github.com/tauri-apps/tauri/commit/4475e93e136e9e2bd5f3c7817fa2040924f630f6) ([#13824](https://www.github.com/tauri-apps/tauri/pull/13824) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler and cli will now read TLS Certificates installed on the system when downloading tools and checking versions.
### Bug Fixes
- [`a8f1569b0`](https://www.github.com/tauri-apps/tauri/commit/a8f1569b04edf7b54a19e19ad37b421b0808f512) ([#13921](https://www.github.com/tauri-apps/tauri/pull/13921) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) The bundler will no longer try to sign non-binary and already signed binary files on Windows
- [`bc6b125b2`](https://www.github.com/tauri-apps/tauri/commit/bc6b125b24589ffc412a4f17d899a387a0fc0bb2) ([#13909](https://www.github.com/tauri-apps/tauri/pull/13909) by [@Andrew15-5](https://www.github.com/tauri-apps/tauri/../../Andrew15-5)) The bundler now falls back to `1` for the release in case an empty string was provided instead of using `-.` in the file name.
### Dependencies
- Upgraded to `tauri-utils@2.7.0`
- Upgraded to `tauri-macos-sign@2.2.0`
## \[2.5.2]
### Bug Fixes
- [`af95fb601`](https://www.github.com/tauri-apps/tauri/commit/af95fb6014ea54a2636bfd299095608f6cd93221) ([#13870](https://www.github.com/tauri-apps/tauri/pull/13870) by [@kittuov](https://www.github.com/tauri-apps/tauri/../../kittuov)) The bundler now signs the main binary after patching it for every package type on windows
## \[2.5.1]
### Bug Fixes
- [`f94af9035`](https://www.github.com/tauri-apps/tauri/commit/f94af90359ec8b01138ae542391caa704ec18ca8) ([#13786](https://www.github.com/tauri-apps/tauri/pull/13786) by [@catalinsh](https://www.github.com/tauri-apps/tauri/../../catalinsh)) Fix NSIS per-machine installer not requesting elevation when run by non-admin users.
- [`f2dbe7309`](https://www.github.com/tauri-apps/tauri/commit/f2dbe730979d570be3ee3ecac9621204c4ceb788) ([#13772](https://www.github.com/tauri-apps/tauri/pull/13772) by [@catalinsh](https://www.github.com/tauri-apps/tauri/../../catalinsh)) Fix incorrect expected file path for `nsis_tauri_utils.dll` resulting in tauri-cli re-downloading the file on every build.
- [`7a6fd5b75`](https://www.github.com/tauri-apps/tauri/commit/7a6fd5b75d61071e2771f6277c0376ec206d302a) ([#13863](https://www.github.com/tauri-apps/tauri/pull/13863) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The AppImage bundler now pulls the AppRun binaries from our GitHub mirror, fixing 404 errors.
### Dependencies
- Upgraded to `tauri-utils@2.6.0`
## \[2.5.0]
### New Features
- [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles.
- [`7322f0579`](https://www.github.com/tauri-apps/tauri/commit/7322f057923aaec88960ad5556776774b745762f) ([#13502](https://www.github.com/tauri-apps/tauri/pull/13502) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Allow using `CheckIfAppIsRunning` macro inside NSIS hooks, for example `!insertmacro CheckIfAppIsRunning "another-executable.exe" "Another Executable"`.
### Bug Fixes
- [`479cee3d3`](https://www.github.com/tauri-apps/tauri/commit/479cee3d3680f9020005bdfb380d3a9482e286a1) ([#13260](https://www.github.com/tauri-apps/tauri/pull/13260) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler now sets the `ARCH` env var to the current build target to prevent potential issues with `appimagetool`'s auto-detection.
- [`e045fe32c`](https://www.github.com/tauri-apps/tauri/commit/e045fe32c9b0bed954916dc42528e28ee19f75b8) ([#13334](https://www.github.com/tauri-apps/tauri/pull/13334) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix custom Windows sign command failing to sign app uninstaller if it references relative paths.
- [`bd8a7cf39`](https://www.github.com/tauri-apps/tauri/commit/bd8a7cf39df316bf27c73a303d5e650301af0104) ([#13581](https://www.github.com/tauri-apps/tauri/pull/13581) by [@martpie](https://www.github.com/tauri-apps/tauri/../../martpie)) Fixes app icon not being displayed on Gnome dock and grid view when using Wayland.
- [`b52da29d5`](https://www.github.com/tauri-apps/tauri/commit/b52da29d5dbdb675ddba438a335e6a59f620e536) ([#13429](https://www.github.com/tauri-apps/tauri/pull/13429) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `mainBinaryName` doesn't work when there's `.` in it
### Dependencies
- Upgraded to `tauri-utils@2.5.0`
## \[2.4.0]
### New Features
- [`b0babb6df`](https://www.github.com/tauri-apps/tauri/commit/b0babb6df12dafe45c21a2c9c424fd86ffd75ca7) ([#12938](https://www.github.com/tauri-apps/tauri/pull/12938)) Added hebrew translation for the custom Tauri messages in the NSIS bundle.
- [`0aa48fb9e`](https://www.github.com/tauri-apps/tauri/commit/0aa48fb9e4b9d7b5bf3522000a76ebc1836394ed) ([#13030](https://www.github.com/tauri-apps/tauri/pull/13030)) Added `bundleVersion` to iOS and macOS configuration to support specifying a `CFBundleVersion`.
### Enhancements
- [`8d994f60f`](https://www.github.com/tauri-apps/tauri/commit/8d994f60fe05ec0f45cbe926506bbe10b0d36e3c) ([#11676](https://www.github.com/tauri-apps/tauri/pull/11676)) Sign NSIS and WiX DLLs when bundling
- [`8d994f60f`](https://www.github.com/tauri-apps/tauri/commit/8d994f60fe05ec0f45cbe926506bbe10b0d36e3c) ([#11676](https://www.github.com/tauri-apps/tauri/pull/11676)) Sign DLLs from resources.
### Bug Fixes
- [`9ea76503d`](https://www.github.com/tauri-apps/tauri/commit/9ea76503dcf8da11fab65550f4ab8d3565a424ef) ([#13186](https://www.github.com/tauri-apps/tauri/pull/13186)) Fix NSIS bundler can't include resources and sidecars with `$` in the path
- [`2dccfab53`](https://www.github.com/tauri-apps/tauri/commit/2dccfab5321fef55d45f3a4c674b6151b1c4424a) ([#13236](https://www.github.com/tauri-apps/tauri/pull/13236)) Fix `fileAssociations` missing `LSHandlerRank` on macOS.
### Dependencies
- Upgraded to `tauri-utils@2.4.0`
## \[2.3.1]
### Bug Fixes
- [`2138bbc21`](https://www.github.com/tauri-apps/tauri/commit/2138bbc21294785df5f4144670104387289f79c1) ([#13087](https://www.github.com/tauri-apps/tauri/pull/13087) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix NSIS installer displaying in wrong language if `SpanishInternational` is included
### Dependencies
- Upgraded to `tauri-utils@2.3.1`
## \[2.3.0]
### Enhancements
- [`f981a5ee8`](https://www.github.com/tauri-apps/tauri/commit/f981a5ee8b292b9ea09329f60cecc7f688dda734) ([#12602](https://www.github.com/tauri-apps/tauri/pull/12602) by [@kxxt](https://www.github.com/tauri-apps/tauri/../../kxxt)) Add basic support for linux riscv64 platform.
### Bug Fixes
- [`3626b7a92`](https://www.github.com/tauri-apps/tauri/commit/3626b7a92be2890a82e8d5bd00d13887e199ea4a) ([#12759](https://www.github.com/tauri-apps/tauri/pull/12759) by [@ninjadev64](https://www.github.com/tauri-apps/tauri/../../ninjadev64)) Fix resources being bundled to the wrong path during RPM bundling when resources are specified as a map.
- [`2b960dfd9`](https://www.github.com/tauri-apps/tauri/commit/2b960dfd9fdc995bd6474958c05783ff53b64b7e) ([#12643](https://www.github.com/tauri-apps/tauri/pull/12643) by [@animeshchaudhri](https://www.github.com/tauri-apps/tauri/../../animeshchaudhri)) Remove the autostart plugin registry entry when the app is uninstalled (NSIS only).
### Dependencies
- Upgraded to `tauri-utils@2.3.0`
## \[2.2.4]
### Enhancements
- [`5eba0785c`](https://www.github.com/tauri-apps/tauri/commit/5eba0785c461a0d0bec47653eaf6ccdf5f05d347) ([#12605](https://www.github.com/tauri-apps/tauri/pull/12605) by [@niusia-ua](https://www.github.com/tauri-apps/tauri/../../niusia-ua)) Added Ukrainian translation for the custom tauri messages in the nsis bundle
### Dependencies
- Upgraded to `tauri-utils@2.2.0`
- Upgraded to `tauri-macos-sign@2.1.0`
## \[2.2.3]
### Bug Fixes
- [`de8600b4d`](https://www.github.com/tauri-apps/tauri/commit/de8600b4d9a04e809e078c8aea61825d1328201f) ([#12471](https://www.github.com/tauri-apps/tauri/pull/12471) by [@anatawa12](https://www.github.com/tauri-apps/tauri/../../anatawa12)) Bumped `nsis-tauri-utils` to `0.4.2` which fixes the following bugs:
- Fixed launch on start checkbox in nsis installer does not work well with applications that require elevated permissions
- Fixed nsis installer may fail to install if launched by updater plugin
- [`fbe7c9ead`](https://www.github.com/tauri-apps/tauri/commit/fbe7c9ead76e71ca258c6f48bbb62185fcc37b1c) ([#12466](https://www.github.com/tauri-apps/tauri/pull/12466) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the compiled AppImage to miss webkitgtk's internal `libwebkit2gtkinjectedbundle.so` file.
- [`f5a59b93b`](https://www.github.com/tauri-apps/tauri/commit/f5a59b93bfefb43ff131a7870b3c5d5e48c1ca1e) ([#12136](https://www.github.com/tauri-apps/tauri/pull/12136) by [@unknovvn](https://www.github.com/tauri-apps/tauri/../../unknovvn)) The NSIS bundler will now replace non-numeric build metadata with `0` instead of returning an error.
- [`9dac2863a`](https://www.github.com/tauri-apps/tauri/commit/9dac2863afa70fb0bcddf859b284afba917f28ae) ([#12323](https://www.github.com/tauri-apps/tauri/pull/12323) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Skip signing the .dmg if self signing via `"signingIdentity": "-"` is used.
- [`b8eb28877`](https://www.github.com/tauri-apps/tauri/commit/b8eb28877fe822dbe17999fc8af98ed7d0983679) ([#12427](https://www.github.com/tauri-apps/tauri/pull/12427) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Clean up `Software\${MANUFACTURER}\${PRODUCTNAME}` registry key in the NSIS uninstaller if "Delete application data" option is checked when uninstalling.
## \[2.2.2]
### Bug Fixes
- [`72748cc45`](https://www.github.com/tauri-apps/tauri/commit/72748cc45cf670dd03c86c8deceb5942598f5ad9) ([#12365](https://www.github.com/tauri-apps/tauri/pull/12365) by [@don41382](https://www.github.com/tauri-apps/tauri/../../don41382)) Fixed an issue that caused the `.msi` installer not to lookup the `INSTALLDIR` set in the `nsis` installer.
- [`cf771bf69`](https://www.github.com/tauri-apps/tauri/commit/cf771bf69aa26b62d11a54a69131c631505d8c55) ([#12402](https://www.github.com/tauri-apps/tauri/pull/12402) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the .msi installer to not contain root resources when there were .dll files present in the target directory.
- [`07ccdc499`](https://www.github.com/tauri-apps/tauri/commit/07ccdc499c3240e7240be3abf95ef2d7d00b2dc7) ([#12324](https://www.github.com/tauri-apps/tauri/pull/12324) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue leading to NSIS based installers to not contain the `WebView2Loader.dll` file when targetting `windows-gnu`.
## \[2.2.1]
### Bug Fixes
- [`cd1d026f9`](https://www.github.com/tauri-apps/tauri/commit/cd1d026f9799c26b04acb64f49e7ee0a8b193049) ([#11961](https://www.github.com/tauri-apps/tauri/pull/11961) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix tauri fails to build if the project path contains glob characters
## \[2.2.0]
### New Features

View File

@@ -1,6 +1,6 @@
[package]
name = "tauri-bundler"
version = "2.2.0"
version = "2.6.0"
authors = [
"George Burton <burtonageo@gmail.com>",
"Tauri Programme within The Commons Conservancy",
@@ -15,7 +15,7 @@ rust-version = "1.77.2"
exclude = ["CHANGELOG.md", "/target", "rustfmt.toml"]
[dependencies]
tauri-utils = { version = "2.1.1", path = "../tauri-utils", features = [
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
"resources",
] }
image = "0.25"
@@ -30,47 +30,52 @@ walkdir = "2"
handlebars = "6"
tempfile = "3"
log = { version = "0.4.21", features = ["kv"] }
dirs = "5"
dirs = "6"
os_pipe = "1"
ureq = { version = "2", default-features = false, features = ["socks-proxy"] }
ureq = { version = "3", default-features = false, features = ["socks-proxy"] }
native-tls = { version = "0.2", optional = true }
hex = "0.4"
semver = "1"
sha1 = "0.10"
sha2 = "0.10"
zip = { version = "2", default-features = false, features = ["deflate"] }
zip = { version = "4", default-features = false, features = ["deflate"] }
dunce = "1"
url = "2"
uuid = { version = "1", features = ["v4", "v5"] }
regex = "1"
goblin = "0.9"
[target."cfg(target_os = \"windows\")".dependencies]
bitness = "0.4"
windows-registry = "0.3"
windows-registry = "0.5"
glob = "0.3"
[target."cfg(target_os = \"windows\")".dependencies.windows-sys]
version = "0.59"
version = "0.60"
features = ["Win32_System_SystemInformation", "Win32_System_Diagnostics_Debug"]
[target."cfg(target_os = \"macos\")".dependencies]
icns = { package = "tauri-icns", version = "0.1" }
time = { version = "0.3", features = ["formatting"] }
plist = "1"
tauri-macos-sign = { version = "2.0.1", path = "../tauri-macos-sign" }
tauri-macos-sign = { version = "2.2.0", path = "../tauri-macos-sign" }
[target."cfg(target_os = \"linux\")".dependencies]
heck = "0.5"
ar = "0.9"
md5 = "0.7"
md5 = "0.8"
rpm = { version = "0.16", features = ["bzip2-compression"] }
[target."cfg(unix)".dependencies]
which = "8"
[lib]
name = "tauri_bundler"
path = "src/lib.rs"
[features]
default = ["rustls"]
default = ["rustls", "platform-certs"]
native-tls = ["ureq/native-tls"]
native-tls-vendored = ["native-tls", "native-tls/vendored"]
rustls = ["ureq/tls"]
rustls = ["ureq/rustls"]
platform-certs = ["ureq/platform-verifier"]

View File

@@ -13,21 +13,51 @@ mod settings;
mod updater_bundle;
mod windows;
use tauri_utils::display_path;
use tauri_utils::{display_path, platform::Target as TargetPlatform};
/// Patch a binary with bundle type information
fn patch_binary(binary: &PathBuf, package_type: &PackageType) -> crate::Result<()> {
match package_type {
#[cfg(target_os = "linux")]
PackageType::AppImage | PackageType::Deb | PackageType::Rpm => {
log::info!(
"Patching binary {:?} for type {}",
binary,
package_type.short_name()
);
linux::patch_binary(binary, package_type)?;
}
PackageType::Nsis | PackageType::WindowsMsi => {
log::info!(
"Patching binary {:?} for type {}",
binary,
package_type.short_name()
);
windows::patch_binary(binary, package_type)?;
}
_ => (),
}
Ok(())
}
pub use self::{
category::AppCategory,
settings::{
AppImageSettings, BundleBinary, BundleSettings, CustomSignCommandSettings, DebianSettings,
DmgSettings, MacOsSettings, PackageSettings, PackageType, Position, RpmSettings, Settings,
SettingsBuilder, Size, UpdaterSettings,
DmgSettings, IosSettings, MacOsSettings, PackageSettings, PackageType, Position, RpmSettings,
Settings, SettingsBuilder, Size, UpdaterSettings,
},
};
#[cfg(target_os = "macos")]
use anyhow::Context;
pub use settings::{NsisSettings, WindowsSettings, WixLanguage, WixLanguageConfig, WixSettings};
use std::{fmt::Write, path::PathBuf};
use std::{
fmt::Write,
io::{Seek, SeekFrom},
path::PathBuf,
};
/// Generated bundle metadata.
#[derive(Debug)]
@@ -48,21 +78,20 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
package_types.sort_by_key(|a| a.priority());
let target_os = settings
.target()
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS)
.replace("darwin", "macos");
let target_os = settings.target_platform();
if target_os != std::env::consts::OS {
if *target_os != TargetPlatform::current() {
log::warn!("Cross-platform compilation is experimental and does not support all features. Please use a matching host system for full compatibility.");
}
// Sign windows binaries before the bundling step in case neither wix and nsis bundles are enabled
if target_os == "windows" {
if matches!(target_os, TargetPlatform::Windows) {
if settings.can_sign() {
for bin in settings.binaries() {
if bin.main() {
// we will sign the main binary after patching per "package type"
continue;
}
let bin_path = settings.binary_path(bin);
windows::sign::try_sign(&bin_path, settings)?;
}
@@ -70,8 +99,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
// Sign the sidecar binaries
for bin in settings.external_binaries() {
let path = bin?;
let skip =
std::env::var("TAURI_SKIP_SIDECAR_SIGNATURE_CHECK").map_or(false, |v| v == "true");
let skip = std::env::var("TAURI_SKIP_SIDECAR_SIGNATURE_CHECK").is_ok_and(|v| v == "true");
if skip {
continue;
}
@@ -93,6 +121,28 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
}
}
let main_binary = settings
.binaries()
.iter()
.find(|b| b.main())
.expect("Main binary missing in settings");
let main_binary_path = settings.binary_path(main_binary);
// When packaging multiple binary types, we make a copy of the unsigned main_binary so that we can
// restore it after each package_type step. This avoids two issues:
// - modifying a signed binary without updating its PE checksum can break signature verification
// - codesigning tools should handle calculating+updating this, we just need to ensure
// (re)signing is performed after every `patch_binary()` operation
// - signing an already-signed binary can result in multiple signatures, causing verification errors
let main_binary_reset_required =
matches!(target_os, TargetPlatform::Windows) && settings.can_sign() && package_types.len() > 1;
let mut unsigned_main_binary_copy = tempfile::tempfile()?;
if main_binary_reset_required {
let mut unsigned_main_binary = std::fs::File::open(&main_binary_path)?;
std::io::copy(&mut unsigned_main_binary, &mut unsigned_main_binary_copy)?;
}
let mut main_binary_signed = false;
let mut bundles = Vec::<Bundle>::new();
for package_type in &package_types {
// bundle was already built! e.g. DMG already built .app
@@ -100,6 +150,24 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
continue;
}
if let Err(e) = patch_binary(&main_binary_path, package_type) {
log::warn!("Failed to add bundler type to the binary: {e}. Updater plugin may not be able to update this package. This shouldn't normally happen, please report it to https://github.com/tauri-apps/tauri/issues");
}
// sign main binary for every package type after patch
if matches!(target_os, TargetPlatform::Windows) && settings.can_sign() {
if main_binary_signed && main_binary_reset_required {
let mut signed_main_binary = std::fs::OpenOptions::new()
.write(true)
.truncate(true)
.open(&main_binary_path)?;
unsigned_main_binary_copy.seek(SeekFrom::Start(0))?;
std::io::copy(&mut unsigned_main_binary_copy, &mut signed_main_binary)?;
}
windows::sign::try_sign(&main_binary_path, settings)?;
main_binary_signed = true;
}
let bundle_paths = match package_type {
#[cfg(target_os = "macos")]
PackageType::MacOsBundle => macos::app::bundle_project(settings)?,
@@ -120,6 +188,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<Bundle>> {
#[cfg(target_os = "windows")]
PackageType::WindowsMsi => windows::msi::bundle_project(settings, false)?,
// note: don't restrict to windows as NSIS installers can be built in linux using cargo-xwin
PackageType::Nsis => windows::nsis::bundle_project(settings, false)?,
#[cfg(target_os = "linux")]

View File

@@ -27,13 +27,17 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
Arch::Armhf => "armhf",
target => {
return Err(crate::Error::ArchError(format!(
"Unsupported architecture: {:?}",
target
"Unsupported architecture: {target:?}"
)));
}
};
let tools_arch = settings.target().split('-').next().unwrap();
let tools_arch = if settings.binary_arch() == Arch::Armhf {
"armhf"
} else {
settings.target().split('-').next().unwrap()
};
let output_path = settings.project_out_directory().join("bundle/appimage");
if output_path.exists() {
fs::remove_dir_all(&output_path)?;
@@ -48,7 +52,11 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
fs::create_dir_all(&tools_path)?;
let linuxdeploy_path = prepare_tools(&tools_path, tools_arch)?;
let linuxdeploy_path = prepare_tools(
&tools_path,
tools_arch,
settings.log_level() != log::Level::Error,
)?;
let package_dir = settings.project_out_directory().join("bundle/appimage_deb");
@@ -141,7 +149,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
for file in [
"WebKitNetworkProcess",
"WebKitWebProcess",
"libwebkit2gtkinjectedbundle.so",
"injected-bundle/libwebkit2gtkinjectedbundle.so",
] {
for source in search_dirs.map(PathBuf::from) {
// TODO: Check if it's the same dir name on all systems
@@ -181,6 +189,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
let mut cmd = Command::new(linuxdeploy_path);
cmd.env("OUTPUT", &appimage_path);
cmd.env("ARCH", tools_arch);
cmd.args([
"--appimage-extract-and-run",
"--verbosity",
@@ -212,11 +221,11 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
}
// returns the linuxdeploy path to keep linuxdeploy_arch contained
fn prepare_tools(tools_path: &Path, arch: &str) -> crate::Result<PathBuf> {
fn prepare_tools(tools_path: &Path, arch: &str, verbose: bool) -> crate::Result<PathBuf> {
let apprun = tools_path.join(format!("AppRun-{arch}"));
if !apprun.exists() {
let data = download(&format!(
"https://github.com/AppImage/AppImageKit/releases/download/continuous/AppRun-{arch}"
"https://github.com/tauri-apps/binary-releases/releases/download/apprun-old/AppRun-{arch}"
))?;
write_and_make_executable(&apprun, data)?;
}
@@ -240,6 +249,21 @@ fn prepare_tools(tools_path: &Path, arch: &str) -> crate::Result<PathBuf> {
write_and_make_executable(&gstreamer, data)?;
}
let appimage = tools_path.join("linuxdeploy-plugin-appimage.AppImage");
if !appimage.exists() {
// This is optional, linuxdeploy will fall back to its built-in version if the download failed.
let data = download(&format!("https://github.com/linuxdeploy/linuxdeploy-plugin-appimage/releases/download/continuous/linuxdeploy-plugin-appimage-{arch}.AppImage"));
match data {
Ok(data) => write_and_make_executable(&appimage, data)?,
Err(err) => {
log::error!("Download of AppImage plugin failed. Using older built-in version instead.");
if verbose {
log::debug!("{err:?}");
}
}
}
}
// This should prevent linuxdeploy to be detected by appimage integration tools
let _ = Command::new("dd")
.args([

View File

@@ -46,10 +46,10 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
Arch::AArch64 => "arm64",
Arch::Armhf => "armhf",
Arch::Armel => "armel",
Arch::Riscv64 => "riscv64",
target => {
return Err(crate::Error::ArchError(format!(
"Unsupported architecture: {:?}",
target
"Unsupported architecture: {target:?}"
)));
}
};
@@ -163,7 +163,7 @@ fn generate_control_file(
let dest_path = control_dir.join("control");
let mut file = fs_utils::create_file(&dest_path)?;
let package = heck::AsKebabCase(settings.product_name());
writeln!(file, "Package: {}", package)?;
writeln!(file, "Package: {package}")?;
writeln!(file, "Version: {}", settings.version_string())?;
writeln!(file, "Architecture: {arch}")?;
// Installed-Size must be divided by 1024, see https://www.debian.org/doc/debian-policy/ch-controlfields.html#installed-size
@@ -182,16 +182,16 @@ fn generate_control_file(
writeln!(file, "Maintainer: {authors}")?;
if let Some(section) = &settings.deb().section {
writeln!(file, "Section: {}", section)?;
writeln!(file, "Section: {section}")?;
}
if let Some(priority) = &settings.deb().priority {
writeln!(file, "Priority: {}", priority)?;
writeln!(file, "Priority: {priority}")?;
} else {
writeln!(file, "Priority: optional")?;
}
if let Some(homepage) = settings.homepage_url() {
writeln!(file, "Homepage: {}", homepage)?;
writeln!(file, "Homepage: {homepage}")?;
}
let dependencies = settings.deb().depends.as_ref().cloned().unwrap_or_default();
@@ -304,7 +304,7 @@ fn generate_md5sums(control_dir: &Path, data_dir: &Path) -> crate::Result<()> {
let mut file = File::open(path)?;
let mut hash = md5::Context::new();
io::copy(&mut file, &mut hash)?;
for byte in hash.compute().iter() {
for byte in hash.finalize().iter() {
write!(md5sums_file, "{byte:02x}")?;
}
let rel_path = path.strip_prefix(data_dir)?;

View File

@@ -4,6 +4,7 @@ Categories={{categories}}
Comment={{comment}}
{{/if}}
Exec={{exec}}
StartupWMClass={{exec}}
Icon={{icon}}
Name={{name}}
Terminal=false

View File

@@ -7,3 +7,8 @@ pub mod appimage;
pub mod debian;
pub mod freedesktop;
pub mod rpm;
mod util;
#[cfg(target_os = "linux")]
pub use util::patch_binary;

View File

@@ -21,7 +21,10 @@ use super::freedesktop;
pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
let product_name = settings.product_name();
let version = settings.version_string();
let release = settings.rpm().release.as_str();
let release = match settings.rpm().release.as_str() {
"" => "1", // Considered the default. If left empty, you get file with "-.".
v => v,
};
let epoch = settings.rpm().epoch;
let arch = match settings.binary_arch() {
Arch::X86_64 => "x86_64",
@@ -29,10 +32,10 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
Arch::AArch64 => "aarch64",
Arch::Armhf => "armhfp",
Arch::Armel => "armel",
Arch::Riscv64 => "riscv64",
target => {
return Err(crate::Error::ArchError(format!(
"Unsupported architecture: {:?}",
target
"Unsupported architecture: {target:?}"
)));
}
};
@@ -186,10 +189,10 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
FileOptions::new(resource_dir.to_string_lossy()).mode(FileMode::Dir { permissions: 0o755 }),
)?;
// Then add the resources files in that directory
for src in settings.resource_files() {
let src = src?;
let dest = resource_dir.join(tauri_utils::resources::resource_relpath(&src));
builder = builder.with_file(&src, FileOptions::new(dest.to_string_lossy()))?;
for resource in settings.resource_files().iter() {
let resource = resource?;
let dest = resource_dir.join(resource.target());
builder = builder.with_file(resource.path(), FileOptions::new(dest.to_string_lossy()))?;
}
}
@@ -234,6 +237,5 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
let mut f = fs::File::create(&package_path)?;
pkg.write(&mut f)?;
Ok(vec![package_path])
}

View File

@@ -0,0 +1,59 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
/// Change value of __TAURI_BUNDLE_TYPE static variable to mark which package type it was bundled in
#[cfg(target_os = "linux")]
pub fn patch_binary(
binary_path: &std::path::PathBuf,
package_type: &crate::PackageType,
) -> crate::Result<()> {
let mut file_data = std::fs::read(binary_path).expect("Could not read binary file.");
let elf = match goblin::Object::parse(&file_data)? {
goblin::Object::Elf(elf) => elf,
_ => return Err(crate::Error::GenericError("Not an ELF file".to_owned())),
};
let offset = find_bundle_type_symbol(elf).ok_or(crate::Error::MissingBundleTypeVar)?;
let offset = offset as usize;
if offset + 3 <= file_data.len() {
let chars = &mut file_data[offset..offset + 3];
match package_type {
crate::PackageType::Deb => chars.copy_from_slice(b"DEB"),
crate::PackageType::Rpm => chars.copy_from_slice(b"RPM"),
crate::PackageType::AppImage => chars.copy_from_slice(b"APP"),
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"linux".to_owned(),
))
}
}
std::fs::write(binary_path, &file_data)
.map_err(|error| crate::Error::BinaryWriteError(error.to_string()))?;
} else {
return Err(crate::Error::BinaryOffsetOutOfRange);
}
Ok(())
}
/// Find address of a symbol in relocations table
#[cfg(target_os = "linux")]
fn find_bundle_type_symbol(elf: goblin::elf::Elf<'_>) -> Option<i64> {
for sym in elf.syms.iter() {
if let Some(name) = elf.strtab.get_at(sym.st_name) {
if name == "__TAURI_BUNDLE_TYPE" {
for reloc in elf.dynrelas.iter() {
if reloc.r_offset == sym.st_value {
return Some(reloc.r_addend.unwrap());
}
}
}
}
}
None
}

View File

@@ -24,7 +24,7 @@
use super::{
icon::create_icns_file,
sign::{notarize, notarize_auth, sign, NotarizeAuthError, SignTarget},
sign::{notarize, notarize_auth, notarize_without_stapling, sign, NotarizeAuthError, SignTarget},
};
use crate::{
utils::{fs_utils, CommandExt},
@@ -65,15 +65,11 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
if app_bundle_path.exists() {
fs::remove_dir_all(&app_bundle_path)
.with_context(|| format!("Failed to remove old {}", app_product_name))?;
.with_context(|| format!("Failed to remove old {app_product_name}"))?;
}
let bundle_directory = app_bundle_path.join("Contents");
fs::create_dir_all(&bundle_directory).with_context(|| {
format!(
"Failed to create bundle directory at {:?}",
bundle_directory
)
})?;
fs::create_dir_all(&bundle_directory)
.with_context(|| format!("Failed to create bundle directory at {bundle_directory:?}"))?;
let resources_dir = bundle_directory.join("Resources");
let bin_dir = bundle_directory.join("MacOS");
@@ -125,7 +121,11 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
// notarization is required for distribution
match notarize_auth() {
Ok(auth) => {
notarize(&keychain, app_bundle_path.clone(), &auth)?;
if settings.macos().skip_stapling {
notarize_without_stapling(&keychain, app_bundle_path.clone(), &auth)?;
} else {
notarize(&keychain, app_bundle_path.clone(), &auth)?;
}
}
Err(e) => {
if matches!(e, NotarizeAuthError::MissingTeamId) {
@@ -160,7 +160,7 @@ fn copy_binaries_to_bundle(
let bin_path = settings.binary_path(bin);
let dest_path = dest_dir.join(bin.name());
fs_utils::copy_file(&bin_path, &dest_path)
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
.with_context(|| format!("Failed to copy binary from {bin_path:?}"))?;
paths.push(dest_path);
}
Ok(paths)
@@ -176,10 +176,10 @@ fn copy_custom_files_to_bundle(bundle_directory: &Path, settings: &Settings) ->
};
if path.is_file() {
fs_utils::copy_file(path, &bundle_directory.join(contents_path))
.with_context(|| format!("Failed to copy file {:?} to {:?}", path, contents_path))?;
.with_context(|| format!("Failed to copy file {path:?} to {contents_path:?}"))?;
} else {
fs_utils::copy_dir(path, &bundle_directory.join(contents_path))
.with_context(|| format!("Failed to copy directory {:?} to {:?}", path, contents_path))?;
.with_context(|| format!("Failed to copy directory {path:?} to {contents_path:?}"))?;
}
}
Ok(())
@@ -191,12 +191,6 @@ fn create_info_plist(
bundle_icon_file: Option<PathBuf>,
settings: &Settings,
) -> crate::Result<()> {
let format = time::format_description::parse("[year][month][day].[hour][minute][second]")
.map_err(time::error::Error::from)?;
let build_number = time::OffsetDateTime::now_utc()
.format(&format)
.map_err(time::error::Error::from)?;
let mut plist = plist::Dictionary::new();
plist.insert("CFBundleDevelopmentRegion".into(), "English".into());
plist.insert("CFBundleDisplayName".into(), settings.product_name().into());
@@ -220,13 +214,29 @@ fn create_info_plist(
settings.bundle_identifier().into(),
);
plist.insert("CFBundleInfoDictionaryVersion".into(), "6.0".into());
plist.insert("CFBundleName".into(), settings.product_name().into());
if let Some(bundle_name) = settings
.macos()
.bundle_name
.as_deref()
.unwrap_or_else(|| settings.product_name())
.into()
{
plist.insert("CFBundleName".into(), bundle_name.into());
}
plist.insert("CFBundlePackageType".into(), "APPL".into());
plist.insert(
"CFBundleShortVersionString".into(),
settings.version_string().into(),
);
plist.insert("CFBundleVersion".into(), build_number.into());
plist.insert(
"CFBundleVersion".into(),
settings
.macos()
.bundle_version
.as_deref()
.unwrap_or_else(|| settings.version_string())
.into(),
);
plist.insert("CSResourcesFileMapped".into(), true.into());
if let Some(category) = settings.app_category() {
plist.insert(
@@ -269,6 +279,7 @@ fn create_info_plist(
"CFBundleTypeRole".into(),
association.role.to_string().into(),
);
dict.insert("LSHandlerRank".into(), association.rank.to_string().into());
plist::Value::Dictionary(dict)
})
.collect(),
@@ -348,7 +359,7 @@ fn create_info_plist(
// Copies the framework under `{src_dir}/{framework}.framework` to `{dest_dir}/{framework}.framework`.
fn copy_framework_from(dest_dir: &Path, framework: &str, src_dir: &Path) -> crate::Result<bool> {
let src_name = format!("{}.framework", framework);
let src_name = format!("{framework}.framework");
let src_path = src_dir.join(&src_name);
if src_path.exists() {
fs_utils::copy_dir(&src_path, &dest_dir.join(&src_name))?;
@@ -376,7 +387,7 @@ fn copy_frameworks_to_bundle(
}
let dest_dir = bundle_directory.join("Frameworks");
fs::create_dir_all(bundle_directory)
.with_context(|| format!("Failed to create Frameworks directory at {:?}", dest_dir))?;
.with_context(|| format!("Failed to create Frameworks directory at {dest_dir:?}"))?;
for framework in frameworks.iter() {
if framework.ends_with(".framework") {
let src_path = PathBuf::from(framework);
@@ -391,8 +402,7 @@ fn copy_frameworks_to_bundle(
let src_path = PathBuf::from(framework);
if !src_path.exists() {
return Err(crate::Error::GenericError(format!(
"Library not found: {}",
framework
"Library not found: {framework}"
)));
}
let src_name = src_path.file_name().expect("Couldn't get library filename");
@@ -405,8 +415,7 @@ fn copy_frameworks_to_bundle(
continue;
} else if framework.contains('/') {
return Err(crate::Error::GenericError(format!(
"Framework path should have .framework extension: {}",
framework
"Framework path should have .framework extension: {framework}"
)));
}
if let Some(home_dir) = dirs::home_dir() {
@@ -424,8 +433,7 @@ fn copy_frameworks_to_bundle(
continue;
}
return Err(crate::Error::GenericError(format!(
"Could not locate framework: {}",
framework
"Could not locate framework: {framework}"
)));
}
Ok(paths)

View File

@@ -49,8 +49,7 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
Arch::Universal => "universal",
target => {
return Err(crate::Error::ArchError(format!(
"Unsupported architecture: {:?}",
target
"Unsupported architecture: {target:?}"
)));
}
}
@@ -59,7 +58,7 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
let dmg_path = output_path.join(&dmg_name);
let product_name = settings.product_name();
let bundle_file_name = format!("{}.app", product_name);
let bundle_file_name = format!("{product_name}.app");
let bundle_dir = settings.project_out_directory().join("bundle/macos");
let support_directory_path = output_path
@@ -69,10 +68,10 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
for path in &[&support_directory_path, &output_path] {
if path.exists() {
fs::remove_dir_all(path).with_context(|| format!("Failed to remove old {}", dmg_name))?;
fs::remove_dir_all(path).with_context(|| format!("Failed to remove old {dmg_name}"))?;
}
fs::create_dir_all(path)
.with_context(|| format!("Failed to create output directory at {:?}", path))?;
.with_context(|| format!("Failed to create output directory at {path:?}"))?;
}
// create paths for script
@@ -194,16 +193,19 @@ pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<
fs::rename(bundle_dir.join(dmg_name), dmg_path.clone())?;
// Sign DMG if needed
if let Some(keychain) = super::sign::keychain(settings.macos().signing_identity.as_deref())? {
super::sign::sign(
&keychain,
vec![super::sign::SignTarget {
path: dmg_path.clone(),
is_an_executable: false,
}],
settings,
)?;
// skipping self-signing DMGs https://github.com/tauri-apps/tauri/issues/12288
let identity = settings.macos().signing_identity.as_deref();
if identity != Some("-") {
if let Some(keychain) = super::sign::keychain(identity)? {
super::sign::sign(
&keychain,
vec![super::sign::SignTarget {
path: dmg_path.clone(),
is_an_executable: false,
}],
settings,
)?;
}
}
Ok(Bundled {

View File

@@ -45,16 +45,16 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
if app_bundle_path.exists() {
fs::remove_dir_all(&app_bundle_path)
.with_context(|| format!("Failed to remove old {}", app_product_name))?;
.with_context(|| format!("Failed to remove old {app_product_name}"))?;
}
fs::create_dir_all(&app_bundle_path)
.with_context(|| format!("Failed to create bundle directory at {:?}", app_bundle_path))?;
.with_context(|| format!("Failed to create bundle directory at {app_bundle_path:?}"))?;
for src in settings.resource_files() {
let src = src?;
let dest = app_bundle_path.join(tauri_utils::resources::resource_relpath(&src));
fs_utils::copy_file(&src, &dest)
.with_context(|| format!("Failed to copy resource file {:?}", src))?;
.with_context(|| format!("Failed to copy resource file {src:?}"))?;
}
let icon_filenames = generate_icon_files(&app_bundle_path, settings)
@@ -65,7 +65,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
for bin in settings.binaries() {
let bin_path = settings.binary_path(bin);
fs_utils::copy_file(&bin_path, &app_bundle_path.join(bin.name()))
.with_context(|| format!("Failed to copy binary from {:?}", bin_path))?;
.with_context(|| format!("Failed to copy binary from {bin_path:?}"))?;
}
Ok(vec![app_bundle_path])
@@ -178,7 +178,11 @@ fn generate_info_plist(
writeln!(
file,
" <key>CFBundleVersion</key>\n <string>{}</string>",
settings.version_string()
settings
.ios()
.bundle_version
.as_deref()
.unwrap_or_else(|| settings.version_string())
)?;
writeln!(
file,
@@ -193,7 +197,7 @@ fn generate_info_plist(
if !icon_filenames.is_empty() {
writeln!(file, " <key>CFBundleIconFiles</key>\n <array>")?;
for filename in icon_filenames {
writeln!(file, " <string>{}</string>", filename)?;
writeln!(file, " <string>{filename}</string>")?;
}
writeln!(file, " </array>")?;
}

View File

@@ -48,9 +48,14 @@ pub fn sign(
log::info!(action = "Signing"; "with identity \"{}\"", keychain.signing_identity());
for target in targets {
let entitlements_path = if target.is_an_executable {
settings.macos().entitlements.as_ref().map(Path::new)
} else {
None
};
keychain.sign(
&target.path,
settings.macos().entitlements.as_ref().map(Path::new),
entitlements_path,
target.is_an_executable && settings.macos().hardened_runtime,
)?;
}
@@ -66,6 +71,15 @@ pub fn notarize(
tauri_macos_sign::notarize(keychain, &app_bundle_path, credentials).map_err(Into::into)
}
pub fn notarize_without_stapling(
keychain: &tauri_macos_sign::Keychain,
app_bundle_path: PathBuf,
credentials: &tauri_macos_sign::AppleNotarizationCredentials,
) -> crate::Result<()> {
tauri_macos_sign::notarize_without_stapling(keychain, &app_bundle_path, credentials)
.map_err(Into::into)
}
#[derive(Debug, thiserror::Error)]
pub enum NotarizeAuthError {
#[error(

View File

@@ -57,6 +57,8 @@ pub fn target_triple() -> Result<String, crate::Error> {
"armv7".into()
} else if cfg!(target_arch = "aarch64") {
"aarch64".into()
} else if cfg!(target_arch = "riscv64") {
"riscv64".into()
} else {
return Err(crate::Error::ArchError(String::from(
"Unable to determine target-architecture",

View File

@@ -12,6 +12,7 @@ use tauri_utils::{
BundleType, DeepLinkProtocol, FileAssociation, NSISInstallerMode, NsisCompression,
RpmCompression,
},
platform::Target as TargetPlatform,
resources::{external_binaries, ResourcePaths},
};
@@ -306,6 +307,13 @@ pub struct DmgSettings {
pub application_folder_position: Position,
}
/// The iOS bundle settings.
#[derive(Clone, Debug, Default)]
pub struct IosSettings {
/// The version of the build that identifies an iteration of the bundle.
pub bundle_version: Option<String>,
}
/// The macOS bundle settings.
#[derive(Clone, Debug, Default)]
pub struct MacOsSettings {
@@ -323,6 +331,12 @@ pub struct MacOsSettings {
/// List of custom files to add to the application bundle.
/// Maps the path in the Contents directory in the app to the path of the file to include (relative to the current working directory).
pub files: HashMap<PathBuf, PathBuf>,
/// The version of the build that identifies an iteration of the bundle.
pub bundle_version: Option<String>,
/// The name of the build that identifies a string of the bundle.
///
/// If not set, defaults to the package's product name.
pub bundle_name: Option<String>,
/// A version string indicating the minimum MacOS version that the bundled app supports (e.g. `"10.11"`).
/// If you are using this config field, you may also want have your `build.rs` script emit `cargo:rustc-env=MACOSX_DEPLOYMENT_TARGET=10.11`.
pub minimum_system_version: Option<String>,
@@ -332,6 +346,15 @@ pub struct MacOsSettings {
pub exception_domain: Option<String>,
/// Code signing identity.
pub signing_identity: Option<String>,
/// Whether to wait for notarization to finish and `staple` the ticket onto the app.
///
/// Gatekeeper will look for stapled tickets to tell whether your app was notarized without
/// reaching out to Apple's servers which is helpful in offline environments.
///
/// Enabling this option will also result in `tauri build` not waiting for notarization to finish
/// which is helpful for the very first time your app is notarized as this can take multiple hours.
/// On subsequent runs, it's recommended to disable this setting again.
pub skip_stapling: bool,
/// Preserve the hardened runtime version flag, see <https://developer.apple.com/documentation/security/hardened_runtime>
///
/// Settings this to `false` is useful when using an ad-hoc signature, making it less strict.
@@ -643,6 +666,8 @@ pub struct BundleSettings {
pub rpm: RpmSettings,
/// DMG-specific settings.
pub dmg: DmgSettings,
/// iOS-specific settings.
pub ios: IosSettings,
/// MacOS-specific settings.
pub macos: MacOsSettings,
/// Updater configuration.
@@ -723,6 +748,8 @@ pub enum Arch {
Armhf,
/// For the AArch32 / ARM32 instruction sets with soft-float (32 bits).
Armel,
/// For the RISC-V instruction sets (64 bits).
Riscv64,
/// For universal macOS applications.
Universal,
}
@@ -747,6 +774,8 @@ pub struct Settings {
bundle_settings: BundleSettings,
/// the binaries to bundle.
binaries: Vec<BundleBinary>,
/// The target platform.
target_platform: TargetPlatform,
/// The target triple.
target: String,
}
@@ -842,6 +871,7 @@ impl SettingsBuilder {
} else {
target_triple()?
};
let target_platform = TargetPlatform::from_triple(&target);
Ok(Settings {
log_level: self.log_level.unwrap_or(log::Level::Error),
@@ -859,9 +889,10 @@ impl SettingsBuilder {
.bundle_settings
.external_bin
.as_ref()
.map(|bins| external_binaries(bins, &target)),
.map(|bins| external_binaries(bins, &target, &target_platform)),
..self.bundle_settings
},
target_platform,
target,
})
}
@@ -888,6 +919,11 @@ impl Settings {
&self.target
}
/// Returns the [`TargetPlatform`].
pub fn target_platform(&self) -> &TargetPlatform {
&self.target_platform
}
/// Returns the architecture for the binary being bundled (e.g. "arm", "x86" or "x86_64").
pub fn binary_arch(&self) -> Arch {
if self.target.starts_with("x86_64") {
@@ -900,6 +936,8 @@ impl Settings {
Arch::Armel
} else if self.target.starts_with("aarch64") {
Arch::AArch64
} else if self.target.starts_with("riscv64") {
Arch::Riscv64
} else if self.target.starts_with("universal") {
Arch::Universal
} else {
@@ -940,19 +978,23 @@ impl Settings {
/// Returns the path to the specified binary.
pub fn binary_path(&self, binary: &BundleBinary) -> PathBuf {
let target_os = self
.target()
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS);
let target_os = self.target_platform();
let path = self.project_out_directory.join(binary.name());
let mut path = self.project_out_directory.join(binary.name());
if target_os == "windows" {
path.with_extension("exe")
} else {
path
}
if matches!(target_os, TargetPlatform::Windows) {
// Append the `.exe` extension without overriding the existing extensions
let extension = if let Some(extension) = path.extension() {
let mut extension = extension.to_os_string();
extension.push(".exe");
extension
} else {
"exe".into()
};
path.set_extension(extension);
};
path
}
/// Returns the list of binaries to bundle.
@@ -970,18 +1012,13 @@ impl Settings {
///
/// Fails if the host/target's native package type is not supported.
pub fn package_types(&self) -> crate::Result<Vec<PackageType>> {
let target_os = self
.target
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS)
.replace("darwin", "macos");
let target_os = self.target_platform();
let platform_types = match target_os.as_str() {
"macos" => vec![PackageType::MacOsBundle, PackageType::Dmg],
"ios" => vec![PackageType::IosBundle],
"linux" => vec![PackageType::Deb, PackageType::Rpm, PackageType::AppImage],
"windows" => vec![PackageType::WindowsMsi, PackageType::Nsis],
let platform_types = match target_os {
TargetPlatform::MacOS => vec![PackageType::MacOsBundle, PackageType::Dmg],
TargetPlatform::Ios => vec![PackageType::IosBundle],
TargetPlatform::Linux => vec![PackageType::Deb, PackageType::Rpm, PackageType::AppImage],
TargetPlatform::Windows => vec![PackageType::WindowsMsi, PackageType::Nsis],
os => {
return Err(crate::Error::GenericError(format!(
"Native {os} bundles not yet supported."
@@ -1186,6 +1223,11 @@ impl Settings {
&self.bundle_settings.dmg
}
/// Returns the iOS settings.
pub fn ios(&self) -> &IosSettings {
&self.bundle_settings.ios
}
/// Returns the MacOS settings.
pub fn macos(&self) -> &MacOsSettings {
&self.bundle_settings.macos

View File

@@ -14,7 +14,7 @@ use crate::{
utils::fs_utils,
Settings,
};
use tauri_utils::display_path;
use tauri_utils::{display_path, platform::Target as TargetPlatform};
use std::{
fs::{self, File},
@@ -27,14 +27,9 @@ use zip::write::SimpleFileOptions;
// Build update
pub fn bundle_project(settings: &Settings, bundles: &[Bundle]) -> crate::Result<Vec<PathBuf>> {
let target_os = settings
.target()
.split('-')
.nth(2)
.unwrap_or(std::env::consts::OS)
.replace("darwin", "macos");
let target_os = settings.target_platform();
if target_os == "windows" {
if matches!(target_os, TargetPlatform::Windows) {
return bundle_update_windows(settings, bundles);
}
@@ -193,7 +188,7 @@ fn bundle_update_windows(settings: &Settings, bundles: &[Bundle]) -> crate::Resu
p.push(c);
(p, b)
});
let archived_path = archived_path.with_extension(format!("{}.zip", bundle_name));
let archived_path = archived_path.with_extension(format!("{bundle_name}.zip"));
log::info!(action = "Bundling"; "{}", display_path(&archived_path));

View File

@@ -5,6 +5,7 @@
#[cfg(target_os = "windows")]
pub mod msi;
pub mod nsis;
pub mod sign;
@@ -13,3 +14,5 @@ pub use util::{
NSIS_OUTPUT_FOLDER_NAME, NSIS_UPDATER_OUTPUT_FOLDER_NAME, WIX_OUTPUT_FOLDER_NAME,
WIX_UPDATER_OUTPUT_FOLDER_NAME,
};
pub use util::patch_binary;

View File

@@ -70,9 +70,12 @@
<Property Id="ARPURLUPDATEINFO" Value="{{homepage}}"/>
{{/if}}
<!-- initialize with previous InstallDir -->
<Property Id="INSTALLDIR">
<RegistrySearch Id="PrevInstallDirReg" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw"/>
<!-- First attempt: Search for "InstallDir" -->
<RegistrySearch Id="PrevInstallDirWithName" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw" />
<!-- Second attempt: If the first fails, search for the default key value (this is how the nsis installer currently stores the path) -->
<RegistrySearch Id="PrevInstallDirNoName" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Type="raw" />
</Property>
<!-- launch app checkbox -->

View File

@@ -7,7 +7,7 @@ use crate::{
bundle::{
settings::{Arch, Settings},
windows::{
sign::try_sign,
sign::{should_sign, try_sign},
util::{
download_webview2_bootstrapper, download_webview2_offline_installer,
WIX_OUTPUT_FOLDER_NAME, WIX_UPDATER_OUTPUT_FOLDER_NAME,
@@ -177,7 +177,7 @@ impl ResourceDirectory {
directories.push_str(wix_string.as_str());
}
let wix_string = if self.name.is_empty() {
format!("{}{}", files, directories)
format!("{files}{directories}")
} else {
format!(
r#"<Directory Id="I{id}" Name="{name}">{files}{directories}</Directory>"#,
@@ -221,8 +221,7 @@ fn app_installer_output_path(
Arch::AArch64 => "arm64",
target => {
return Err(crate::Error::ArchError(format!(
"Unsupported architecture: {:?}",
target
"Unsupported architecture: {target:?}"
)))
}
};
@@ -352,8 +351,7 @@ fn run_candle(
Arch::AArch64 => "arm64",
target => {
return Err(crate::Error::ArchError(format!(
"unsupported architecture: {:?}",
target
"unsupported architecture: {target:?}"
)))
}
};
@@ -443,8 +441,7 @@ pub fn build_wix_app_installer(
Arch::AArch64 => "arm64",
target => {
return Err(crate::Error::ArchError(format!(
"unsupported architecture: {:?}",
target
"unsupported architecture: {target:?}"
)))
}
};
@@ -472,6 +469,16 @@ pub fn build_wix_app_installer(
}
fs::create_dir_all(&output_path)?;
// when we're performing code signing, we'll sign some WiX DLLs, so we make a local copy
let wix_toolset_path = if settings.can_sign() {
let wix_path = output_path.join("wix");
crate::utils::fs_utils::copy_dir(wix_toolset_path, &wix_path)
.context("failed to copy wix directory")?;
wix_path
} else {
wix_toolset_path.to_path_buf()
};
let mut data = BTreeMap::new();
let silent_webview_install = if let WebviewInstallMode::DownloadBootstrapper { silent }
@@ -763,7 +770,11 @@ pub fn build_wix_app_installer(
let fragment = fragment_handlebars.render_template(&fragment_content, &data)?;
let mut extensions = Vec::new();
for cap in extension_regex.captures_iter(&fragment) {
extensions.push(wix_toolset_path.join(format!("Wix{}.dll", &cap[1])));
let path = wix_toolset_path.join(format!("Wix{}.dll", &cap[1]));
if settings.can_sign() {
try_sign(&path, settings)?;
}
extensions.push(path);
}
candle_inputs.push((fragment_path, extensions));
}
@@ -773,11 +784,18 @@ pub fn build_wix_app_installer(
fragment_extensions.insert(wix_toolset_path.join("WixUIExtension.dll"));
fragment_extensions.insert(wix_toolset_path.join("WixUtilExtension.dll"));
// sign default extensions
if settings.can_sign() {
for path in &fragment_extensions {
try_sign(path, settings)?;
}
}
for (path, extensions) in candle_inputs {
for ext in &extensions {
fragment_extensions.insert(ext.clone());
}
run_candle(settings, wix_toolset_path, &output_path, path, extensions)?;
run_candle(settings, &wix_toolset_path, &output_path, path, extensions)?;
}
let mut output_paths = Vec::new();
@@ -824,7 +842,7 @@ pub fn build_wix_app_installer(
let locale_contents = locale_contents.replace(
"</WixLocalization>",
&format!("{}</WixLocalization>", unset_locale_strings),
&format!("{unset_locale_strings}</WixLocalization>"),
);
let locale_path = output_path.join("locale.wxl");
{
@@ -853,7 +871,7 @@ pub fn build_wix_app_installer(
log::info!(action = "Running"; "light to produce {}", display_path(&msi_path));
run_light(
wix_toolset_path,
&wix_toolset_path,
&output_path,
arguments,
&(fragment_extensions.clone().into_iter().collect()),
@@ -929,12 +947,11 @@ fn get_merge_modules(settings: &Settings) -> crate::Result<Vec<MergeModule>> {
let mut merge_modules = Vec::new();
let regex = Regex::new(r"[^\w\d\.]")?;
for msm in glob::glob(
settings
.project_out_directory()
.join("*.msm")
.to_string_lossy()
.to_string()
.as_str(),
&PathBuf::from(glob::Pattern::escape(
&settings.project_out_directory().to_string_lossy(),
))
.join("*.msm")
.to_string_lossy(),
)? {
let path = msm?;
let filename = path
@@ -969,9 +986,12 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourceMap> {
if added_resources.contains(&resource_path) {
continue;
}
added_resources.push(resource_path.clone());
if settings.can_sign() && should_sign(&resource_path)? {
try_sign(&resource_path, settings)?;
}
let resource_entry = ResourceFile {
id: format!("I{}", Uuid::new_v4().as_simple()),
guid: Uuid::new_v4().to_string(),
@@ -1041,8 +1061,13 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourceMap> {
let mut dlls = Vec::new();
// TODO: The bundler should not include all DLLs it finds. Instead it should only include WebView2Loader.dll if present and leave the rest to the resources config.
let out_dir = settings.project_out_directory();
for dll in glob::glob(out_dir.join("*.dll").to_string_lossy().to_string().as_str())? {
for dll in glob::glob(
&PathBuf::from(glob::Pattern::escape(&out_dir.to_string_lossy()))
.join("*.dll")
.to_string_lossy(),
)? {
let path = dll?;
let resource_path = dunce::simplified(&path);
let relative_path = path
@@ -1051,6 +1076,10 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourceMap> {
.to_string_lossy()
.into_owned();
if !added_resources.iter().any(|r| r.ends_with(&relative_path)) {
if settings.can_sign() {
try_sign(resource_path, settings)?;
}
dlls.push(ResourceFile {
id: format!("I{}", Uuid::new_v4().as_simple()),
guid: Uuid::new_v4().to_string(),
@@ -1060,15 +1089,15 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourceMap> {
}
if !dlls.is_empty() {
resources.insert(
"".to_string(),
ResourceDirectory {
resources
.entry("".to_string())
.and_modify(|r| r.files.append(&mut dlls))
.or_insert(ResourceDirectory {
path: "".to_string(),
name: "".to_string(),
directories: vec![],
files: dlls,
},
);
});
}
Ok(resources)

View File

@@ -47,7 +47,7 @@ ${StrLoc}
!define COPYRIGHT "{{copyright}}"
!define OUTFILE "{{out_file}}"
!define ARCH "{{arch}}"
!define PLUGINSPATH "{{additional_plugins_path}}"
!define ADDITIONALPLUGINSPATH "{{additional_plugins_path}}"
!define ALLOWDOWNGRADES "{{allow_downgrades}}"
!define DISPLAYLANGUAGESELECTOR "{{display_language_selector}}"
!define INSTALLWEBVIEW2MODE "{{install_webview2_mode}}"
@@ -56,7 +56,8 @@ ${StrLoc}
!define WEBVIEW2INSTALLERPATH "{{webview2_installer_path}}"
!define MINIMUMWEBVIEW2VERSION "{{minimum_webview2_version}}"
!define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}"
!define MANUPRODUCTKEY "Software\${MANUFACTURER}\${PRODUCTNAME}"
!define MANUKEY "Software\${MANUFACTURER}"
!define MANUPRODUCTKEY "${MANUKEY}\${PRODUCTNAME}"
!define UNINSTALLERSIGNCOMMAND "{{uninstaller_sign_cmd}}"
!define ESTIMATEDSIZE "{{estimated_size}}"
!define STARTMENUFOLDER "{{start_menu_folder}}"
@@ -84,10 +85,8 @@ VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
VIAddVersionKey "FileVersion" "${VERSION}"
VIAddVersionKey "ProductVersion" "${VERSION}"
; Plugins path, currently exists for linux only
!if "${PLUGINSPATH}" != ""
!addplugindir "${PLUGINSPATH}"
!endif
# additional plugins
!addplugindir "${ADDITIONALPLUGINSPATH}"
; Uninstaller signing command
!if "${UNINSTALLERSIGNCOMMAND}" != ""
@@ -96,7 +95,7 @@ VIAddVersionKey "ProductVersion" "${VERSION}"
; Handle install mode, `perUser`, `perMachine` or `both`
!if "${INSTALLMODE}" == "perMachine"
RequestExecutionLevel highest
RequestExecutionLevel admin
!endif
!if "${INSTALLMODE}" == "currentUser"
@@ -619,7 +618,7 @@ Section Install
!insertmacro NSIS_HOOK_PREINSTALL
!endif
!insertmacro CheckIfAppIsRunning
!insertmacro CheckIfAppIsRunning "${MAINBINARYNAME}.exe" "${PRODUCTNAME}"
; Copy main executable
File "${MAINBINARYSRCPATH}"
@@ -629,12 +628,12 @@ Section Install
CreateDirectory "$INSTDIR\\{{this}}"
{{/each}}
{{#each resources}}
File /a "/oname={{this.[1]}}" "{{@key}}"
File /a "/oname={{this.[1]}}" "{{no-escape @key}}"
{{/each}}
; Copy external binaries
{{#each binaries}}
File /a "/oname={{this}}" "{{@key}}"
File /a "/oname={{this}}" "{{no-escape @key}}"
{{/each}}
; Create file associations
@@ -756,7 +755,7 @@ Section Uninstall
!insertmacro NSIS_HOOK_PREUNINSTALL
!endif
!insertmacro CheckIfAppIsRunning
!insertmacro CheckIfAppIsRunning "${MAINBINARYNAME}.exe" "${PRODUCTNAME}"
; Delete the app directory and its content from disk
; Copy main executable
@@ -834,12 +833,27 @@ Section Uninstall
DeleteRegKey HKCU "${UNINSTKEY}"
!endif
DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language"
; Removes the Autostart entry for ${PRODUCTNAME} from the HKCU Run key if it exists.
; This ensures the program does not launch automatically after uninstallation if it exists.
; If it doesn't exist, it does nothing.
; We do this when not updating (to preserve the registry value on updates)
${If} $UpdateMode <> 1
DeleteRegValue HKCU "Software\Microsoft\Windows\CurrentVersion\Run" "${PRODUCTNAME}"
${EndIf}
; Delete app data if the checkbox is selected
; and if not updating
${If} $DeleteAppDataCheckboxState = 1
${AndIf} $UpdateMode <> 1
; Clear the install location $INSTDIR from registry
DeleteRegKey SHCTX "${MANUPRODUCTKEY}"
DeleteRegKey /ifempty SHCTX "${MANUKEY}"
; Clear the install language from registry
DeleteRegValue HKCU "${MANUPRODUCTKEY}" "Installer Language"
DeleteRegKey /ifempty HKCU "${MANUPRODUCTKEY}"
DeleteRegKey /ifempty HKCU "${MANUKEY}"
SetShellVarContext current
RmDir /r "$APPDATA\${BUNDLEID}"
RmDir /r "$LOCALAPPDATA\${BUNDLEID}"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_ARABIC} "إضافة أو إزالة المكونات"
LangString alreadyInstalled ${LANG_ARABIC} "التطبيق مثبت بالفعل"
LangString alreadyInstalledLong ${LANG_ARABIC} "${PRODUCTNAME} ${VERSION} مثبت بالفعل. قم باختيار العملية التى تريدها ثم اضغط على التالى."
LangString appRunning ${LANG_ARABIC} "${PRODUCTNAME} مازال يعمل! من فضلك، قم بإغلاق التطبيق أولاً ثم حاول مرة أخرى."
LangString appRunningOkKill ${LANG_ARABIC} "${PRODUCTNAME} مازال يعمل!$\nاضغط OK لإغلاقه"
LangString appRunning ${LANG_ARABIC} "{{product_name}} مازال يعمل! من فضلك، قم بإغلاق التطبيق أولاً ثم حاول مرة أخرى."
LangString appRunningOkKill ${LANG_ARABIC} "{{product_name}} مازال يعمل!$\nاضغط OK لإغلاقه"
LangString chooseMaintenanceOption ${LANG_ARABIC} "قم باختيار نوع الصيانة التى تريدها."
LangString choowHowToInstall ${LANG_ARABIC} "قم باختيار طريقة تنصيب ${PRODUCTNAME}."
LangString createDesktop ${LANG_ARABIC} "اضف اختصار على سطح المكتب"
LangString dontUninstall ${LANG_ARABIC} "عدم إزالة"
LangString dontUninstallDowngrade ${LANG_ARABIC} "عدم إزالة (التخفيض بدون إزالة غير مسموح لهذا المثبت)"
LangString failedToKillApp ${LANG_ARABIC} "فشل فى غلف ${PRODUCTNAME}. من فضلك، قم بإغلاق التطبيق أولاً ثم حاول مرة أخرى."
LangString failedToKillApp ${LANG_ARABIC} "فشل فى غلف {{product_name}}. من فضلك، قم بإغلاق التطبيق أولاً ثم حاول مرة أخرى."
LangString installingWebview2 ${LANG_ARABIC} "تنصيب WebView2..."
LangString newerVersionInstalled ${LANG_ARABIC} "يوجد نسخة جديدة من ${PRODUCTNAME} مثبتة بالغعل! لا ينصح بتنصيب نسخة اقدم من النسخة الحالية. اذا مازلت ترغب فى تنصيب النسخة الأقدم، فينصح بإزالة النسخة الحالية أولاً. قم باختيار العملية التى تريدها ثم اضغط على التالى للاستمرار."
LangString older ${LANG_ARABIC} "أقدم"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_BULGARIAN} "Добавяне/Преинсталиране на компоненти"
LangString alreadyInstalled ${LANG_BULGARIAN} "Вече инсталиран"
LangString alreadyInstalledLong ${LANG_BULGARIAN} "${PRODUCTNAME} ${VERSION} е вече е инсталиран. Изберете операцията, която искате да извършите и натиснете Напред, за да продължите."
LangString appRunning ${LANG_BULGARIAN} "${PRODUCTNAME} е отворен! Моля, затворете го първо и опитайте отново."
LangString appRunningOkKill ${LANG_BULGARIAN} "${PRODUCTNAME} е отворен!$\nНатиснете ОК, за да го затворите."
LangString appRunning ${LANG_BULGARIAN} "{{product_name}} е отворен! Моля, затворете го първо и опитайте отново."
LangString appRunningOkKill ${LANG_BULGARIAN} "{{product_name}} е отворен!$\nНатиснете ОК, за да го затворите."
LangString chooseMaintenanceOption ${LANG_BULGARIAN} "Изберете опция за поддръжка."
LangString choowHowToInstall ${LANG_BULGARIAN} "Изберете как искате да инсталирате ${PRODUCTNAME}."
LangString createDesktop ${LANG_BULGARIAN} "Създайте пряк път на работния плот"
LangString dontUninstall ${LANG_BULGARIAN} "Не деинсталирайте"
LangString dontUninstallDowngrade ${LANG_BULGARIAN} "Не деинсталирайте (Понижаването без деинсталация е забранено за този инсталатор)"
LangString failedToKillApp ${LANG_BULGARIAN} "Неуспешно прекратяване на ${PRODUCTNAME}. Моля, затворете го първо и опитайте отново."
LangString failedToKillApp ${LANG_BULGARIAN} "Неуспешно прекратяване на {{product_name}}. Моля, затворете го първо и опитайте отново."
LangString installingWebview2 ${LANG_BULGARIAN} "Инсталиране на WebView2..."
LangString newerVersionInstalled ${LANG_BULGARIAN} "Вече е инсталирана по-нова версия на ${PRODUCTNAME}! Не се препоръчва да инсталирате по-стара версия. Ако наистина желаете да инсталирате тази по-стара версия, по-добре е да деинсталирате текущата версия първо. Изберете операцията, която искате да извършите и натиснете Напред, за да продължите."
LangString older ${LANG_BULGARIAN} "по-стара"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_DUTCH} "(Her)installeer componenten"
LangString alreadyInstalled ${LANG_DUTCH} "Al geïnstalleerd"
LangString alreadyInstalledLong ${LANG_DUTCH} "${PRODUCTNAME} ${VERSION} is al geïnstalleerd. Kies een van de volgende opties en klik op Volgende om door te gaan."
LangString appRunning ${LANG_DUTCH} "${PRODUCTNAME} is geopend! Sluit het programma eerst en probeer het dan opnieuw."
LangString appRunningOkKill ${LANG_DUTCH} "${PRODUCTNAME} is geopend!$\nKlik op OK om het te stoppen."
LangString appRunning ${LANG_DUTCH} "{{product_name}} is geopend! Sluit het programma eerst en probeer het dan opnieuw."
LangString appRunningOkKill ${LANG_DUTCH} "{{product_name}} is geopend!$\nKlik op OK om het te stoppen."
LangString chooseMaintenanceOption ${LANG_DUTCH} "Kies de onderhoudsoptie die u wilt uitvoeren."
LangString choowHowToInstall ${LANG_DUTCH} "Kies hoe u ${PRODUCTNAME} wilt installeren."
LangString createDesktop ${LANG_DUTCH} "Maak een snelkoppeling aan op het bureaublad"
LangString dontUninstall ${LANG_DUTCH} "Deïnstalleer niet"
LangString dontUninstallDowngrade ${LANG_DUTCH} "Deïnstalleer niet (Downgraden zonder deïnstalleren is uitgeschakeld voor deze installer)"
LangString failedToKillApp ${LANG_DUTCH} "Het is niet gelukt ${PRODUCTNAME} te stoppen. Sluit het eerst zelf en probeer het dan nog een keer"
LangString failedToKillApp ${LANG_DUTCH} "Het is niet gelukt {{product_name}} te stoppen. Sluit het eerst zelf en probeer het dan nog een keer"
LangString installingWebview2 ${LANG_DUTCH} "WebView2 wordt geïnstalleerd..."
LangString newerVersionInstalled ${LANG_DUTCH} "Een nieuwere versie van ${PRODUCTNAME} is al geïnstalleerd! Het word niet aangeraden om een oudere versie te installeren. Als u echt deze oudere versie wilt installeren, kunt u beter de huidige versie eerst deïnstalleren. Kies een van de volgende opties en klik op Volgende om door te gaan."
LangString older ${LANG_DUTCH} "oudere"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_ENGLISH} "Add/Reinstall components"
LangString alreadyInstalled ${LANG_ENGLISH} "Already Installed"
LangString alreadyInstalledLong ${LANG_ENGLISH} "${PRODUCTNAME} ${VERSION} is already installed. Select the operation you want to perform and click Next to continue."
LangString appRunning ${LANG_ENGLISH} "${PRODUCTNAME} is running! Please close it first then try again."
LangString appRunningOkKill ${LANG_ENGLISH} "${PRODUCTNAME} is running!$\nClick OK to kill it"
LangString appRunning ${LANG_ENGLISH} "{{product_name}} is running! Please close it first then try again."
LangString appRunningOkKill ${LANG_ENGLISH} "{{product_name}} is running!$\nClick OK to kill it"
LangString chooseMaintenanceOption ${LANG_ENGLISH} "Choose the maintenance option to perform."
LangString choowHowToInstall ${LANG_ENGLISH} "Choose how you want to install ${PRODUCTNAME}."
LangString createDesktop ${LANG_ENGLISH} "Create desktop shortcut"
LangString dontUninstall ${LANG_ENGLISH} "Do not uninstall"
LangString dontUninstallDowngrade ${LANG_ENGLISH} "Do not uninstall (Downgrading without uninstall is disabled for this installer)"
LangString failedToKillApp ${LANG_ENGLISH} "Failed to kill ${PRODUCTNAME}. Please close it first then try again"
LangString failedToKillApp ${LANG_ENGLISH} "Failed to kill {{product_name}}. Please close it first then try again"
LangString installingWebview2 ${LANG_ENGLISH} "Installing WebView2..."
LangString newerVersionInstalled ${LANG_ENGLISH} "A newer version of ${PRODUCTNAME} is already installed! It is not recommended that you install an older version. If you really want to install this older version, it's better to uninstall the current version first. Select the operation you want to perform and click Next to continue."
LangString older ${LANG_ENGLISH} "older"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_FRENCH} "Ajouter/Réinstaller un composant."
LangString alreadyInstalled ${LANG_FRENCH} "Déja installé."
LangString alreadyInstalledLong ${LANG_FRENCH} "${PRODUCTNAME} ${VERSION} est déja installé. Sélectionnez l'opération que vous souhaitez effectuer, puis cliquez sur Suivant pour continuer."
LangString appRunning ${LANG_FRENCH} "${PRODUCTNAME} est en cours d'exécution. Veuillez fermer l'application avant de réessayer."
LangString appRunningOkKill ${LANG_FRENCH} "${PRODUCTNAME} est en cours d'exécution.$\nCliquez sur OK pour fermer l'application."
LangString appRunning ${LANG_FRENCH} "{{product_name}} est en cours d'exécution. Veuillez fermer l'application avant de réessayer."
LangString appRunningOkKill ${LANG_FRENCH} "{{product_name}} est en cours d'exécution.$\nCliquez sur OK pour fermer l'application."
LangString chooseMaintenanceOption ${LANG_FRENCH} "Veuillez choisir l'option de maintenance à effectuer."
LangString choowHowToInstall ${LANG_FRENCH} "Veuillez choisir l'emplacement d'installation de ${PRODUCTNAME}."
LangString createDesktop ${LANG_FRENCH} "Créer un raccourci sur le bureau."
LangString dontUninstall ${LANG_FRENCH} "Ne pas désinstaller"
LangString dontUninstallDowngrade ${LANG_FRENCH} "Ne pas désinstaller (revenir à une ancienne version sans désinstallation est désactivé pour cet installateur)"
LangString failedToKillApp ${LANG_FRENCH} "La fermeture de ${PRODUCTNAME} a échoué. Veuillez fermer l'application et réessayer."
LangString failedToKillApp ${LANG_FRENCH} "La fermeture de {{product_name}} a échoué. Veuillez fermer l'application et réessayer."
LangString installingWebview2 ${LANG_FRENCH} "Installation de WebView2..."
LangString newerVersionInstalled ${LANG_FRENCH} "Une version plus récente de ${PRODUCTNAME} est déja installée. Il n'est pas recommandé d'installer une ancienne version. Si vous souhaitez installer cette ancienne version, il est conseillé de désinstaller la version courante en premier. Veuillez sélectionner l'opération que vous souhaitez effectuer, puis cliquez sur Suivant pour continer."
LangString older ${LANG_FRENCH} "ancien"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_GERMAN} "Komponenten hinzufügen/neu installieren"
LangString alreadyInstalled ${LANG_GERMAN} "Bereits installiert"
LangString alreadyInstalledLong ${LANG_GERMAN} "${PRODUCTNAME} ${VERSION} ist bereits installiert. Wählen Sie den gewünschten Vorgang aus und klicken Sie auf Weiter, um fortzufahren."
LangString appRunning ${LANG_GERMAN} "${PRODUCTNAME} wird ausgeführt! Bitte schließen Sie es zuerst und versuchen Sie es dann erneut."
LangString appRunningOkKill ${LANG_GERMAN} "${PRODUCTNAME} läuft! $\nKlicken Sie auf OK, um es zu beenden"
LangString appRunning ${LANG_GERMAN} "{{product_name}} wird ausgeführt! Bitte schließen Sie es zuerst und versuchen Sie es dann erneut."
LangString appRunningOkKill ${LANG_GERMAN} "{{product_name}} läuft! $\nKlicken Sie auf OK, um es zu beenden"
LangString chooseMaintenanceOption ${LANG_GERMAN} "Wählen Sie die auszuführende Wartungsoption."
LangString choowHowToInstall ${LANG_GERMAN} "Wählen Sie, wie Sie ${PRODUCTNAME} installieren möchten."
LangString createDesktop ${LANG_GERMAN} "Desktop-Verknüpfung erstellen"
LangString dontUninstall ${LANG_GERMAN} "Nicht deinstallieren"
LangString dontUninstallDowngrade ${LANG_GERMAN} "Nicht deinstallieren (Downgrading ohne Deinstallation ist für dieses Installationsprogramm deaktiviert)"
LangString failedToKillApp ${LANG_GERMAN} "Failed to kill ${PRODUCTNAME}. Bitte schließen Sie es zuerst und versuchen Sie es dann erneut"
LangString failedToKillApp ${LANG_GERMAN} "Failed to kill {{product_name}}. Bitte schließen Sie es zuerst und versuchen Sie es dann erneut"
LangString installingWebview2 ${LANG_GERMAN} "Installiere WebView2..."
LangString newerVersionInstalled ${LANG_GERMAN} "Eine neuere Version von ${PRODUCTNAME} ist bereits installiert! Es wird nicht empfohlen, eine ältere Version zu installieren. Wenn Sie diese ältere Version wirklich installieren wollen, ist es besser, die aktuelle Version zuerst zu deinstallieren. Wählen Sie den gewünschten Vorgang aus und klicken Sie auf Weiter, um fortzufahren."
LangString älter ${LANG_GERMAN} "älter"

View File

@@ -0,0 +1,27 @@
LangString addOrReinstall ${LANG_HEBREW} "הוסף או התקן מחדש"
LangString alreadyInstalled ${LANG_HEBREW} "כבר מותקן"
LangString alreadyInstalledLong ${LANG_HEBREW} "${PRODUCTNAME} ${VERSION} כבר מותקן. בחר את הפעולה שברצונך לבצע ולחץ על הבא כדי להמשיך."
LangString appRunning ${LANG_HEBREW} "{{product_name}} פועל! נא לסגור אותו ולנסות שוב."
LangString appRunningOkKill ${LANG_HEBREW} "{{product_name}} פועל!$\nלחץ אישור כדי לסגור אותו."
LangString chooseMaintenanceOption ${LANG_HEBREW} "בחר את פעולת התחזוקה לביצוע"
LangString choowHowToInstall ${LANG_HEBREW} "בחר איך תרצה להתקין את ${PRODUCTNAME}."
LangString createDesktop ${LANG_HEBREW} "צור קיצור דרך בשולחן העבודה"
LangString dontUninstall ${LANG_HEBREW} "אל תסיר"
LangString dontUninstallDowngrade ${LANG_HEBREW} "אל תסיר (התקנת גרסה ישנה ללא הסרת הגרסה הנוכחית מושעית עבור התקנה זו)"
LangString failedToKillApp ${LANG_HEBREW} "עצירת {{product_name}} נכשלה. נא לסגור את היישום ולנסות שוב."
LangString installingWebview2 ${LANG_HEBREW} "מתקין את WebView2..."
LangString newerVersionInstalled ${LANG_HEBREW} "גרסה חדשה יותר של ${PRODUCTNAME} כבר מותקנת! לא מומלץ להתקין גרסה ישנה. אם בכל זאת תרצה להתקין את הגרסה הזו, מומלץ קודם להסיר את הגרסה הנוכחית. בחר את הפעולה שברצונך לבצע ולחץ הבא להמשך."
LangString older ${LANG_HEBREW} "ישנה"
LangString olderOrUnknownVersionInstalled ${LANG_HEBREW} "גרסה $R4 של ${PRODUCTNAME} מותקנת במערכת שלך. מומלץ להסיר את הגרסה הנוכחית לפני ההתקנה. בחר את הפעולה שברצונך לבצע ולחץ הבא להמשך."
LangString silentDowngrades ${LANG_HEBREW} "התקנת גרסה ישנה לא נתמכת בהתקנה זו, אין אפשרות להמשיך עם ההתקנה השקטה, נא להמשיך עם ההתקנה בממשק הגרפי.$\n"
LangString unableToUninstall ${LANG_HEBREW} "לא ניתן להסיר!"
LangString uninstallApp ${LANG_HEBREW} "הסר את ${PRODUCTNAME}"
LangString uninstallBeforeInstalling ${LANG_HEBREW} "הסר את הגרסה הנוכחית לפני התקנת גרסה זו"
LangString unknown ${LANG_HEBREW} "לא ידועה"
LangString webview2AbortError ${LANG_HEBREW} "התקנת WebView2 נכשלה! היישום אינו יכולה לפעול בלי זה. נסה להפעיל את ההתקנה שוב."
LangString webview2DownloadError ${LANG_HEBREW} "שגיאה: הורדת WebView2 נכשלה - $0"
LangString webview2DownloadSuccess ${LANG_HEBREW} "מאתחל WebView2 הורד בהצלחה"
LangString webview2Downloading ${LANG_HEBREW} "מוריד את מאתחל WebView2..."
LangString webview2InstallError ${LANG_HEBREW} "שגיאה: התקנת WebView2 נכשלה עם קוד שגיאה $1"
LangString webview2InstallSuccess ${LANG_HEBREW} "WebView2 הותקן בהצלחה"
LangString deleteAppData ${LANG_HEBREW} "מחק את נתוני היישום"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_ITALIAN} "Aggiungi/Reinstalla componenti"
LangString alreadyInstalled ${LANG_ITALIAN} "Già installato"
LangString alreadyInstalledLong ${LANG_ITALIAN} "${PRODUCTNAME} ${VERSION} è già installato. Seleziona l'operazione che vuoi eseguire e clicca Avanti per continuare."
LangString appRunning ${LANG_ITALIAN} "${PRODUCTNAME} è in esecuzione! Chiudi e poi riprova."
LangString appRunningOkKill ${LANG_ITALIAN} "${PRODUCTNAME} è in esecuzione!$\nSeleziona OK per chiuderlo"
LangString appRunning ${LANG_ITALIAN} "{{product_name}} è in esecuzione! Chiudi e poi riprova."
LangString appRunningOkKill ${LANG_ITALIAN} "{{product_name}} è in esecuzione!$\nSeleziona OK per chiuderlo"
LangString chooseMaintenanceOption ${LANG_ITALIAN} "Seleziona l'operazione di manutenzione da eseguire."
LangString choowHowToInstall ${LANG_ITALIAN} "Seleziona come vuoi installare ${PRODUCTNAME}."
LangString createDesktop ${LANG_ITALIAN} "Crea scorciatoia sul Desktop"
LangString dontUninstall ${LANG_ITALIAN} "Non disinstallare"
LangString dontUninstallDowngrade ${LANG_ITALIAN} "Non disinstallare (Il downgrade senza la disinstallazione è disabilitato per questo installer)"
LangString failedToKillApp ${LANG_ITALIAN} "Impossibile chiudere ${PRODUCTNAME}. Chiudi e poi riprova"
LangString failedToKillApp ${LANG_ITALIAN} "Impossibile chiudere {{product_name}}. Chiudi e poi riprova"
LangString installingWebview2 ${LANG_ITALIAN} "Installando WebView2..."
LangString newerVersionInstalled ${LANG_ITALIAN} "Una versione più recente di ${PRODUCTNAME} è già installata! Non è consigliato installare una versione più vecchia. Se vuoi comunque procedere, è meglio prima disinstallare la versione corrente. Seleziona l'operazione che vuoi eseguire e clicca Avanti per continuare."
LangString older ${LANG_ITALIAN} "più vecchia"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_JAPANESE} "コンポーネントの追加・再インストール"
LangString alreadyInstalled ${LANG_JAPANESE} "既にインストールされています"
LangString alreadyInstalledLong ${LANG_JAPANESE} "${PRODUCTNAME} ${VERSION} は既にインストールされています。実行したい操作を選択し、「次へ」をクリックして続行します。"
LangString appRunning ${LANG_JAPANESE} "${PRODUCTNAME} は動作中です。動作中のプログラムを終了し、もう一度やり直してください。"
LangString appRunningOkKill ${LANG_JAPANESE} "${PRODUCTNAME} は動作中です。$\n「OK」を押すと動作中のプログラムを終了します。"
LangString appRunning ${LANG_JAPANESE} "{{product_name}} は動作中です。動作中のプログラムを終了し、もう一度やり直してください。"
LangString appRunningOkKill ${LANG_JAPANESE} "{{product_name}} は動作中です。$\n「OK」を押すと動作中のプログラムを終了します。"
LangString chooseMaintenanceOption ${LANG_JAPANESE} "メンテナンスオプションを選択して実行します。"
LangString choowHowToInstall ${LANG_JAPANESE} "${PRODUCTNAME} のインストール方法を選択してください。"
LangString createDesktop ${LANG_JAPANESE} "デスクトップショートカットを作成する"
LangString dontUninstall ${LANG_JAPANESE} "アンインストールしない"
LangString dontUninstallDowngrade ${LANG_JAPANESE} "アンインストールしない (このインストーラーでは、アンインストールをせずにダウングレードすることはできません)"
LangString failedToKillApp ${LANG_JAPANESE} "${PRODUCTNAME} の終了に失敗しました。動作中のプログラムを終了し、もう一度やり直してください。"
LangString failedToKillApp ${LANG_JAPANESE} "{{product_name}} の終了に失敗しました。動作中のプログラムを終了し、もう一度やり直してください。"
LangString installingWebview2 ${LANG_JAPANESE} "WebView2 をインストール中です..."
LangString newerVersionInstalled ${LANG_JAPANESE} "既に新しいバージョンの ${PRODUCTNAME} がインストールされています。古いバージョンをインストールすることは推奨されません。どうしてもこの旧バージョンをインストールしたい場合は、先に現行バージョンをアンインストールしておく方がよいでしょう。実行したい操作を選択し、「次へ」をクリックして続行します。"
LangString older ${LANG_JAPANESE} ""

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_KOREAN} "컴포넌트 추가 및 재설치"
LangString alreadyInstalled ${LANG_KOREAN} "이미 설치되어 있습니다"
LangString alreadyInstalledLong ${LANG_KOREAN} "${PRODUCTNAME} ${VERSION}이(가) 이미 설치되어 있습니다. 수행하고자 하는 작업을 선택하고 '다음'을 클릭하여 계속합니다."
LangString appRunning ${LANG_KOREAN} "${PRODUCTNAME}이(가) 실행 중입니다! 먼저 닫은 후 다시 시도하세요."
LangString appRunningOkKill ${LANG_KOREAN} "${PRODUCTNAME}이(가) 실행 중입니다!$\n'OK'를 누르면 실행 중인 프로그램을 종료합니다."
LangString appRunning ${LANG_KOREAN} "{{product_name}}이(가) 실행 중입니다! 먼저 닫은 후 다시 시도하세요."
LangString appRunningOkKill ${LANG_KOREAN} "{{product_name}}이(가) 실행 중입니다!$\n'OK'를 누르면 실행 중인 프로그램을 종료합니다."
LangString chooseMaintenanceOption ${LANG_KOREAN} "수행하려는 관리 옵션을 선택합니다."
LangString choowHowToInstall ${LANG_KOREAN} "${PRODUCTNAME}의 설치 방법을 선택하세요.."
LangString createDesktop ${LANG_KOREAN} "바탕화면 바로가기 만들기"
LangString dontUninstall ${LANG_KOREAN} "제거하지 않기"
LangString dontUninstallDowngrade ${LANG_KOREAN} "제거하지 않기 (이 설치 프로그램에서는 제거하지 않고 다운그레이드할 수 없습니다.)"
LangString failedToKillApp ${LANG_KOREAN} "${PRODUCTNAME}을(를) 종료하지 못했습니다. 먼저 닫은 후 다시 시도하세요."
LangString failedToKillApp ${LANG_KOREAN} "{{product_name}}을(를) 종료하지 못했습니다. 먼저 닫은 후 다시 시도하세요."
LangString installingWebview2 ${LANG_KOREAN} "WebView2를 설치하는 중입니다..."
LangString newerVersionInstalled ${LANG_KOREAN} "${PRODUCTNAME}의 최신 버전이 이미 설치되어 있습니다! 이전 버전을 설치하지 않는 것이 좋습니다. 이 이전 버전을 꼭 설치하려면 먼저 현재 버전을 제거하는 것이 좋습니다. 수행하려는 작업을 선택하고 '다음'을 클릭하여 계속합니다."
LangString older ${LANG_KOREAN} ""

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_PERSIAN} "اضافه کردن/نصب مجدد کامپونتت"
LangString alreadyInstalled ${LANG_PERSIAN} "قبلا نصب شده است"
LangString alreadyInstalledLong ${LANG_PERSIAN} "${PRODUCTNAME} ${VERSION} قبلا نصب شده است. عملیات مدنظر را انتخاب کنید و بروی بعدی کلیک کنید."
LangString appRunning ${LANG_PERSIAN} "${PRODUCTNAME} در حال اجر می باشد ! لطفا اول الان را ببندید و دوباره تلاش کنید"
LangString appRunningOkKill ${LANG_PERSIAN} "${PRODUCTNAME} در حال اجرا می باشد!$\nبرای از بین بردن اوکی را انتخاب کنید"
LangString appRunning ${LANG_PERSIAN} "{{product_name}} در حال اجر می باشد ! لطفا اول الان را ببندید و دوباره تلاش کنید"
LangString appRunningOkKill ${LANG_PERSIAN} "{{product_name}} در حال اجرا می باشد!$\nبرای از بین بردن اوکی را انتخاب کنید"
LangString chooseMaintenanceOption ${LANG_PERSIAN} "عملیات نگهداری مدنظر را برای اجرا انتخاب کنید"
LangString choowHowToInstall ${LANG_PERSIAN} "نحوه نصب ${PRODUCTNAME} را انتخاب کنید"
LangString createDesktop ${LANG_PERSIAN} "ایجاد میانبر دسکتاپ"
LangString dontUninstall ${LANG_PERSIAN} "حذف نکنید"
LangString dontUninstallDowngrade ${LANG_PERSIAN} "حذف نکنید (تنزل ورژن بدون حذف برای نصب کننده غیرفعال است)"
LangString failedToKillApp ${LANG_PERSIAN} "${PRODUCTNAME} قابل کشته شدن نیست. اول آن را ببندید و دوباره تلاش کنید"
LangString failedToKillApp ${LANG_PERSIAN} "{{product_name}} قابل کشته شدن نیست. اول آن را ببندید و دوباره تلاش کنید"
LangString installingWebview2 ${LANG_PERSIAN} "در حال نصب WebView2 ..."
LangString newerVersionInstalled ${LANG_PERSIAN} "ورژن جدید ${PRODUCTNAME} قبلا نصب شده است! نصب ورژن قدیمی تر به هیچ عنوان پیشنهاد نمی شود. اگر از این بابت اطمینان دارید , بهتر است ورژن فعلی را حذف کنید. عملیات مدنظر را انتخاب کنید و بروی بعدی کلیک کنید."
LangString older ${LANG_PERSIAN} "قدیمی تر"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_PORTUGUESE} "Adicionar/Reinstalar componentes"
LangString alreadyInstalled ${LANG_PORTUGUESE} "Já instalado"
LangString alreadyInstalledLong ${LANG_PORTUGUESE} "${PRODUCTNAME} ${VERSION} já está instalado. Selecione a operação que deseja realizar e clique em Seguinte para continuar."
LangString appRunning ${LANG_PORTUGUESE} "${PRODUCTNAME} está em execução! Por favor, feche-o primeiro e tente novamente."
LangString appRunningOkKill ${LANG_PORTUGUESE} "${PRODUCTNAME} está em execução!$\nClique em OK para encerrá-lo."
LangString appRunning ${LANG_PORTUGUESE} "{{product_name}} está em execução! Por favor, feche-o primeiro e tente novamente."
LangString appRunningOkKill ${LANG_PORTUGUESE} "{{product_name}} está em execução!$\nClique em OK para encerrá-lo."
LangString chooseMaintenanceOption ${LANG_PORTUGUESE} "Escolha a opção de manutenção a realizar."
LangString choowHowToInstall ${LANG_PORTUGUESE} "Escolha como deseja instalar o ${PRODUCTNAME}."
LangString createDesktop ${LANG_PORTUGUESE} "Criar atalho no ambiente de trabalho"
LangString dontUninstall ${LANG_PORTUGUESE} "Não desinstalar"
LangString dontUninstallDowngrade ${LANG_PORTUGUESE} "Não desinstalar (Instalar uma versão anterior sem desinstalar está desativado neste instalador)"
LangString failedToKillApp ${LANG_PORTUGUESE} "Falha ao encerrar ${PRODUCTNAME}. Por favor, feche-o primeiro e tente novamente."
LangString failedToKillApp ${LANG_PORTUGUESE} "Falha ao encerrar {{product_name}}. Por favor, feche-o primeiro e tente novamente."
LangString installingWebview2 ${LANG_PORTUGUESE} "A instalar WebView2..."
LangString newerVersionInstalled ${LANG_PORTUGUESE} "Uma versão mais recente do ${PRODUCTNAME} já está instalada! Não é recomendada a instalação de uma versão mais antiga. Se realmente deseja instalar esta versão mais antiga, é melhor desinstalar a versão atual primeiro. Selecione a operação que deseja realizar e clique em Seguinte para continuar."
LangString older ${LANG_PORTUGUESE} "mais antiga"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_PORTUGUESEBR} "Adicionar/Reinstalar componentes"
LangString alreadyInstalled ${LANG_PORTUGUESEBR} "Já instalado"
LangString alreadyInstalledLong ${LANG_PORTUGUESEBR} "${PRODUCTNAME} ${VERSION} já está instalado. Selecione a operação que deseja realizar e clique Próximo para continuar."
LangString appRunning ${LANG_PORTUGUESEBR} "${PRODUCTNAME} está aberto! Por favor feche a janela dele e tente novamente."
LangString appRunningOkKill ${LANG_PORTUGUESEBR} "${PRODUCTNAME} está aberto!$\nClique OK para fechar ele."
LangString appRunning ${LANG_PORTUGUESEBR} "{{product_name}} está aberto! Por favor feche a janela dele e tente novamente."
LangString appRunningOkKill ${LANG_PORTUGUESEBR} "{{product_name}} está aberto!$\nClique OK para fechar ele."
LangString chooseMaintenanceOption ${LANG_PORTUGUESEBR} "Escolha a opção de manutenção a realizar."
LangString choowHowToInstall ${LANG_PORTUGUESEBR} "Escolha como deseja instalar ${PRODUCTNAME}."
LangString createDesktop ${LANG_PORTUGUESEBR} "Criar atalho na área de trabalho"
LangString dontUninstall ${LANG_PORTUGUESEBR} "Não desinstalar"
LangString dontUninstallDowngrade ${LANG_PORTUGUESEBR} "Não desinstalar (Instalar versão anterior sem desinstalar está desabilitado nesse instalador)"
LangString failedToKillApp ${LANG_PORTUGUESEBR} "Falha ao fechar ${PRODUCTNAME}. Por favor feche a janela dele primeiro e tente novamente"
LangString failedToKillApp ${LANG_PORTUGUESEBR} "Falha ao fechar {{product_name}}. Por favor feche a janela dele primeiro e tente novamente"
LangString installingWebview2 ${LANG_PORTUGUESEBR} "Instalando WebView2..."
LangString newerVersionInstalled ${LANG_PORTUGUESEBR} "Uma nova versão do ${PRODUCTNAME} já está instalado! Não é recomendado instalar uma versão anterior. Se realmente deseja instalar essa versão antiga, é recomendado desinstalar a versão atual primeirl. Selecione a operação que deseja executare clique Próximo para continuar."
LangString older ${LANG_PORTUGUESEBR} "mais antiga"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_RUSSIAN} "Добавить/Переустановить компоненты"
LangString alreadyInstalled ${LANG_RUSSIAN} "Уже установлено"
LangString alreadyInstalledLong ${LANG_RUSSIAN} "${PRODUCTNAME} ${VERSION} уже установлен. Выберите действие, которое вы хотите выполнить и нажмите Далее для продолжения."
LangString appRunning ${LANG_RUSSIAN} "${PRODUCTNAME} запущен! Пожалуйста, закройте приложение и попробуйте еще раз."
LangString appRunningOkKill ${LANG_RUSSIAN} "${PRODUCTNAME} запущен!$\nНажмите OK чтобы закрыть приложение"
LangString appRunning ${LANG_RUSSIAN} "{{product_name}} запущен! Пожалуйста, закройте приложение и попробуйте еще раз."
LangString appRunningOkKill ${LANG_RUSSIAN} "{{product_name}} запущен!$\nНажмите OK чтобы закрыть приложение"
LangString chooseMaintenanceOption ${LANG_RUSSIAN} "Выберите действие, которое вы хотите выполнить."
LangString choowHowToInstall ${LANG_RUSSIAN} "Выберите, как вы хотите установить ${PRODUCTNAME}."
LangString createDesktop ${LANG_RUSSIAN} "Добавить ярлык на рабочий стол"
LangString dontUninstall ${LANG_RUSSIAN} "Не удалять"
LangString dontUninstallDowngrade ${LANG_RUSSIAN} "Не удалять (Установка более ранних версий без удаления невозможна)"
LangString failedToKillApp ${LANG_RUSSIAN} "Не удалось закрыть ${PRODUCTNAME}. Пожалуйста, закройте приложение и попробуйте еще раз"
LangString failedToKillApp ${LANG_RUSSIAN} "Не удалось закрыть {{product_name}}. Пожалуйста, закройте приложение и попробуйте еще раз"
LangString installingWebview2 ${LANG_RUSSIAN} "Установка WebView2..."
LangString newerVersionInstalled ${LANG_RUSSIAN} "Более новая версия ${PRODUCTNAME} уже установлена! Не рекомендуется устанавливать более раннюю версию. Если вы действительно хотите установить эту версию, рекомендуется сначала удалить текущую. Выберите действие, которое вы хотите выполнить и нажмите Далее для продолжения."
LangString older ${LANG_RUSSIAN} "Более ранняя"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_SIMPCHINESE} "添加/重新安装组件"
LangString alreadyInstalled ${LANG_SIMPCHINESE} "已安装"
LangString alreadyInstalledLong ${LANG_SIMPCHINESE} "${PRODUCTNAME} ${VERSION} 已经安装了。选择你想要执行的操作后点击下一步以继续。"
LangString appRunning ${LANG_SIMPCHINESE} "${PRODUCTNAME} 正在运行!请关闭后再试。"
LangString appRunningOkKill ${LANG_SIMPCHINESE} "${PRODUCTNAME} 正在运行!$\n点击确定以终止运行。"
LangString appRunning ${LANG_SIMPCHINESE} "{{product_name}} 正在运行!请关闭后再试。"
LangString appRunningOkKill ${LANG_SIMPCHINESE} "{{product_name}} 正在运行!$\n点击确定以终止运行。"
LangString chooseMaintenanceOption ${LANG_SIMPCHINESE} "选择要执行的维护操作。"
LangString choowHowToInstall ${LANG_SIMPCHINESE} "选择你想要安装 ${PRODUCTNAME} 的方式。"
LangString createDesktop ${LANG_SIMPCHINESE} "创建桌面快捷方式"
LangString dontUninstall ${LANG_SIMPCHINESE} "请勿卸载"
LangString dontUninstallDowngrade ${LANG_SIMPCHINESE} "请勿卸载(此安装程序禁止未卸载就进行版本降级的操作)"
LangString failedToKillApp ${LANG_SIMPCHINESE} "无法终止 ${PRODUCTNAME}。请关闭后再试。"
LangString failedToKillApp ${LANG_SIMPCHINESE} "无法终止 {{product_name}}。请关闭后再试。"
LangString installingWebview2 ${LANG_SIMPCHINESE} "正在安装 WebView2..."
LangString newerVersionInstalled ${LANG_SIMPCHINESE} "有一个更新版本的 ${PRODUCTNAME} 已经安装了!不推荐你安装旧的版本。如果你真的想要安装这个旧的版本,推荐先卸载当前版本。选择你想要执行的操作后点击下一步以继续。"
LangString older ${LANG_SIMPCHINESE} "旧的"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_SPANISH} "Añadir o reinstalar componentes"
LangString alreadyInstalled ${LANG_SPANISH} "Ya está instalado"
LangString alreadyInstalledLong ${LANG_SPANISH} "${PRODUCTNAME} ${VERSION} ya está instalado. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString appRunning ${LANG_SPANISH} "¡${PRODUCTNAME} está abierto! Por favor ciérrelo e intente de nuevo."
LangString appRunningOkKill ${LANG_SPANISH} "¡${PRODUCTNAME} está abierto!$\nPulse Aceptar para cerrarlo."
LangString appRunning ${LANG_SPANISH} "¡{{product_name}} está abierto! Por favor ciérrelo e intente de nuevo."
LangString appRunningOkKill ${LANG_SPANISH} "¡{{product_name}} está abierto!$\nPulse Aceptar para cerrarlo."
LangString chooseMaintenanceOption ${LANG_SPANISH} "Elija la operación de mantenimiento que desee realizar."
LangString choowHowToInstall ${LANG_SPANISH} "Elija cómo desea instalar ${PRODUCTNAME}."
LangString createDesktop ${LANG_SPANISH} "Crear acceso directo en el escritorio"
LangString dontUninstall ${LANG_SPANISH} "No desinstalar"
LangString dontUninstallDowngrade ${LANG_SPANISH} "No desinstalar (Disminuir la versión sin desinstalar está deshabilitado para este instalador)"
LangString failedToKillApp ${LANG_SPANISH} "No se ha podido cerrar ${PRODUCTNAME}. Por favor ciérrelo e intente de nuevo."
LangString failedToKillApp ${LANG_SPANISH} "No se ha podido cerrar {{product_name}}. Por favor ciérrelo e intente de nuevo."
LangString installingWebview2 ${LANG_SPANISH} "Instalando WebView2..."
LangString newerVersionInstalled ${LANG_SPANISH} "Ya está instalada una versión más reciente de ${PRODUCTNAME}. No se recomienda que instale una versión anterior. Si realmente desea instalar esta versión anterior, es recomendable desinstalar la versión actual antes de continuar. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString older ${LANG_SPANISH} "anterior"

View File

@@ -1,27 +1,27 @@
LangString addOrReinstall ${LANG_SPANISH} "Añadir o reinstalar componentes"
LangString alreadyInstalled ${LANG_SPANISH} "Ya está instalado"
LangString alreadyInstalledLong ${LANG_SPANISH} "${PRODUCTNAME} ${VERSION} ya está instalado. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString appRunning ${LANG_SPANISH} "¡${PRODUCTNAME} está abierto! Por favor ciérrelo e intente de nuevo."
LangString appRunningOkKill ${LANG_SPANISH} "¡${PRODUCTNAME} está abierto!$\nPulse Aceptar para cerrarlo."
LangString chooseMaintenanceOption ${LANG_SPANISH} "Elija la operación de mantenimiento que desee realizar."
LangString choowHowToInstall ${LANG_SPANISH} "Elija cómo desea instalar ${PRODUCTNAME}."
LangString createDesktop ${LANG_SPANISH} "Crear acceso directo en el escritorio"
LangString dontUninstall ${LANG_SPANISH} "No desinstalar"
LangString dontUninstallDowngrade ${LANG_SPANISH} "No desinstalar (Disminuir la versión sin desinstalar está deshabilitado para este instalador)"
LangString failedToKillApp ${LANG_SPANISH} "No se ha podido cerrar ${PRODUCTNAME}. Por favor ciérrelo e intente de nuevo."
LangString installingWebview2 ${LANG_SPANISH} "Instalando WebView2..."
LangString newerVersionInstalled ${LANG_SPANISH} "Ya está instalada una versión más reciente de ${PRODUCTNAME}. No se recomienda que instale una versión anterior. Si realmente desea instalar esta versión anterior, es recomendable desinstalar la versión actual antes de continuar. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString older ${LANG_SPANISH} "anterior"
LangString olderOrUnknownVersionInstalled ${LANG_SPANISH} "Una versión $R4 de ${PRODUCTNAME} está instalada en su sistema. Es recomendable desinstalar la versión actual antes de continuar. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString silentDowngrades ${LANG_SPANISH} "Disminuir la versión está deshabilitado para este instalador. No se puede continuar con el instalador silencioso, por favor use el instalador de interfaz gráfica.$\n"
LangString unableToUninstall ${LANG_SPANISH} "No se ha podido desinstalar."
LangString uninstallApp ${LANG_SPANISH} "Desinstalar ${PRODUCTNAME}"
LangString uninstallBeforeInstalling ${LANG_SPANISH} "Desinstalar antes de instalar"
LangString unknown ${LANG_SPANISH} "desconocida"
LangString webview2AbortError ${LANG_SPANISH} "No se ha podido instalar WebView2. Intente reiniciar el instalador."
LangString webview2DownloadError ${LANG_SPANISH} "Error: No se ha podido descargar WebView2 - $0"
LangString webview2DownloadSuccess ${LANG_SPANISH} "El bootstrapper de WebView2 fue descargado con éxito."
LangString webview2Downloading ${LANG_SPANISH} "Descargando el bootstrapper de WebView2..."
LangString webview2InstallError ${LANG_SPANISH} "Error: La instalación de WebView2 falló con el código $1."
LangString webview2InstallSuccess ${LANG_SPANISH} "WebView2 fue instalado con éxito."
LangString deleteAppData ${LANG_SPANISH} "Eliminar los datos de aplicación"
LangString addOrReinstall ${LANG_SPANISHINTERNATIONAL} "Añadir o reinstalar componentes"
LangString alreadyInstalled ${LANG_SPANISHINTERNATIONAL} "Ya está instalado"
LangString alreadyInstalledLong ${LANG_SPANISHINTERNATIONAL} "${PRODUCTNAME} ${VERSION} ya está instalado. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString appRunning ${LANG_SPANISHINTERNATIONAL} "¡{{product_name}} está abierto! Por favor ciérrelo e intente de nuevo."
LangString appRunningOkKill ${LANG_SPANISHINTERNATIONAL} "¡{{product_name}} está abierto!$\nPulse Aceptar para cerrarlo."
LangString chooseMaintenanceOption ${LANG_SPANISHINTERNATIONAL} "Elija la operación de mantenimiento que desee realizar."
LangString choowHowToInstall ${LANG_SPANISHINTERNATIONAL} "Elija cómo desea instalar ${PRODUCTNAME}."
LangString createDesktop ${LANG_SPANISHINTERNATIONAL} "Crear acceso directo en el escritorio"
LangString dontUninstall ${LANG_SPANISHINTERNATIONAL} "No desinstalar"
LangString dontUninstallDowngrade ${LANG_SPANISHINTERNATIONAL} "No desinstalar (Disminuir la versión sin desinstalar está deshabilitado para este instalador)"
LangString failedToKillApp ${LANG_SPANISHINTERNATIONAL} "No se ha podido cerrar {{product_name}}. Por favor ciérrelo e intente de nuevo."
LangString installingWebview2 ${LANG_SPANISHINTERNATIONAL} "Instalando WebView2..."
LangString newerVersionInstalled ${LANG_SPANISHINTERNATIONAL} "Ya está instalada una versión más reciente de ${PRODUCTNAME}. No se recomienda que instale una versión anterior. Si realmente desea instalar esta versión anterior, es recomendable desinstalar la versión actual antes de continuar. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString older ${LANG_SPANISHINTERNATIONAL} "anterior"
LangString olderOrUnknownVersionInstalled ${LANG_SPANISHINTERNATIONAL} "Una versión $R4 de ${PRODUCTNAME} está instalada en su sistema. Es recomendable desinstalar la versión actual antes de continuar. Seleccione la operación que desee realizar y pulse Siguiente para continuar."
LangString silentDowngrades ${LANG_SPANISHINTERNATIONAL} "Disminuir la versión está deshabilitado para este instalador. No se puede continuar con el instalador silencioso, por favor use el instalador de interfaz gráfica.$\n"
LangString unableToUninstall ${LANG_SPANISHINTERNATIONAL} "No se ha podido desinstalar."
LangString uninstallApp ${LANG_SPANISHINTERNATIONAL} "Desinstalar ${PRODUCTNAME}"
LangString uninstallBeforeInstalling ${LANG_SPANISHINTERNATIONAL} "Desinstalar antes de instalar"
LangString unknown ${LANG_SPANISHINTERNATIONAL} "desconocida"
LangString webview2AbortError ${LANG_SPANISHINTERNATIONAL} "No se ha podido instalar WebView2. Intente reiniciar el instalador."
LangString webview2DownloadError ${LANG_SPANISHINTERNATIONAL} "Error: No se ha podido descargar WebView2 - $0"
LangString webview2DownloadSuccess ${LANG_SPANISHINTERNATIONAL} "El bootstrapper de WebView2 fue descargado con éxito."
LangString webview2Downloading ${LANG_SPANISHINTERNATIONAL} "Descargando el bootstrapper de WebView2..."
LangString webview2InstallError ${LANG_SPANISHINTERNATIONAL} "Error: La instalación de WebView2 falló con el código $1."
LangString webview2InstallSuccess ${LANG_SPANISHINTERNATIONAL} "WebView2 fue instalado con éxito."
LangString deleteAppData ${LANG_SPANISHINTERNATIONAL} "Eliminar los datos de aplicación"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_SWEDISH} "Lägg till/Installera om komponenter"
LangString alreadyInstalled ${LANG_SWEDISH}} "Redan installerad"
LangString alreadyInstalledLong ${LANG_SWEDISH}} "${PRODUCTNAME} ${VERSION} är redan installerad. Välj åtgärd och klicka på Nästa för att fortsätta."
LangString appRunning ${LANG_SWEDISH} "${PRODUCTNAME} körs! Stäng det först och försök igen."
LangString appRunningOkKill ${LANG_SWEDISH} "${PRODUCTNAME} körs!$\nKlicka på OK för att avsluta det."
LangString appRunning ${LANG_SWEDISH} "{{product_name}} körs! Stäng det först och försök igen."
LangString appRunningOkKill ${LANG_SWEDISH} "{{product_name}} körs!$\nKlicka på OK för att avsluta det."
LangString chooseMaintenanceOption ${LANG_SWEDISH} "Välj underhållsåtgärd."
LangString choowHowToInstall ${LANG_SWEDISH} "Välj hur du vill installera ${PRODUCTNAME}."
LangString createDesktop ${LANG_SWEDISH} "Skapa genväg på skrivbordet"
LangString dontUninstall ${LANG_SWEDISH} "Avinstallera inte"
LangString dontUninstallDowngrade ${LANG_SWEDISH} "Avinstallera inte (nedgradering utan avinstallation är inaktiverad för den här installationsprogrammet)"
LangString failedToKillApp ${LANG_SWEDISH} "Kunde inte avsluta ${PRODUCTNAME}. Stäng det först och försök igen."
LangString failedToKillApp ${LANG_SWEDISH} "Kunde inte avsluta {{product_name}}. Stäng det först och försök igen."
LangString installingWebview2 ${LANG_SWEDISH} "Installerar WebView2..."
LangString newerVersionInstalled ${LANG_SWEDISH} "En nyare version av ${PRODUCTNAME} är redan installerad! Det rekommenderas inte att installera en äldre version. Om du verkligen vill installera denna äldre version är det bättre att avinstallera den nuvarande versionen först. Välj åtgärd och klicka på Nästa för att fortsätta."
LangString older ${LANG_SWEDISH} "äldre"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_TRADCHINESE} "增加或重新安裝元件"
LangString alreadyInstalled ${LANG_TRADCHINESE} "已安裝"
LangString alreadyInstalledLong ${LANG_TRADCHINESE} "${PRODUCTNAME} ${VERSION} 已經安裝了。選擇你想要進行的操作並且點選下一步。"
LangString appRunning ${LANG_TRADCHINESE} "${PRODUCTNAME} 正在執行中!請先關閉再進行嘗試。"
LangString appRunningOkKill ${LANG_TRADCHINESE} "${PRODUCTNAME} 正在執行中!點選確定後終止。"
LangString appRunning ${LANG_TRADCHINESE} "{{product_name}} 正在執行中!請先關閉再進行嘗試。"
LangString appRunningOkKill ${LANG_TRADCHINESE} "{{product_name}} 正在執行中!點選確定後終止。"
LangString chooseMaintenanceOption ${LANG_TRADCHINESE} "請選擇你要進行的維護選項。"
LangString choowHowToInstall ${LANG_TRADCHINESE} "選擇你要如何安裝 ${PRODUCTNAME}。"
LangString createDesktop ${LANG_TRADCHINESE} "建立桌面捷徑"
LangString dontUninstall ${LANG_TRADCHINESE} "請勿解除安裝"
LangString dontUninstallDowngrade ${LANG_TRADCHINESE} "請勿解除安裝(本安裝程式不允許未解除安裝就進行版本降低的操作)"
LangString failedToKillApp ${LANG_TRADCHINESE} "無法終止 ${PRODUCTNAME}。請先關閉再進行嘗試。"
LangString failedToKillApp ${LANG_TRADCHINESE} "無法終止 {{product_name}}。請先關閉再進行嘗試。"
LangString installingWebview2 ${LANG_TRADCHINESE} "WebView2 安裝中..."
LangString newerVersionInstalled ${LANG_TRADCHINESE} "已安裝更新版本的 ${PRODUCTNAME}!不建議安裝舊版。如果真的想要安裝舊版的話,最好先解除安裝現在的版本。選擇你想要進行的操作後再進行下一步。"
LangString older ${LANG_TRADCHINESE} "舊版"

View File

@@ -1,14 +1,14 @@
LangString addOrReinstall ${LANG_TURKISH} "Bileşen Ekle/Yeniden Yükle"
LangString alreadyInstalled ${LANG_TURKISH} "Daha Önceden Yüklenmiş"
LangString alreadyInstalledLong ${LANG_TURKISH} "${PRODUCTNAME} ${VERSION} daha önceden yüklenmiş. Gerçekleştirmek istediğiniz işlemi seçin ve devam etmek için İleri'ye tıklayın."
LangString appRunning ${LANG_TURKISH} "${PRODUCTNAME} çalışır durumda! Lütfen önce uygulamayı kapatın ve sonra tekrar deneyin."
LangString appRunningOkKill ${LANG_TURKISH} "${PRODUCTNAME} çalışır durumda!$\nUygulamayı sonlandırmak için Tamam'a tıklayın."
LangString appRunning ${LANG_TURKISH} "{{product_name}} çalışır durumda! Lütfen önce uygulamayı kapatın ve sonra tekrar deneyin."
LangString appRunningOkKill ${LANG_TURKISH} "{{product_name}} çalışır durumda!$\nUygulamayı sonlandırmak için Tamam'a tıklayın."
LangString chooseMaintenanceOption ${LANG_TURKISH} "Gerçekleştirmek istediğiniz bakım seçeneğini belirleyin."
LangString choowHowToInstall ${LANG_TURKISH} "${PRODUCTNAME} uygulamasını nasıl yüklemek istediğinizi seçin."
LangString createDesktop ${LANG_TURKISH} "Masaüstü kısayolu oluştur"
LangString dontUninstall ${LANG_TURKISH} "Kaldırma işlemini gerçekleştirme"
LangString dontUninstallDowngrade ${LANG_TURKISH} "Kaldırma işlemini gerçekleştirme (Kaldırma işlemi yapmadan sürüm düşürme bu yükleyici için devre dışı bırakılmıştır)"
LangString failedToKillApp ${LANG_TURKISH} "${PRODUCTNAME} sonlandırılamadı. Lütfen önce kapatın sonra tekrar deneyin."
LangString failedToKillApp ${LANG_TURKISH} "{{product_name}} sonlandırılamadı. Lütfen önce kapatın sonra tekrar deneyin."
LangString installingWebview2 ${LANG_TURKISH} "WebView2 yükleniyor..."
LangString newerVersionInstalled ${LANG_TURKISH} "${PRODUCTNAME} uygulamasının daha yeni bir sürümü zaten yüklü! Daha eski bir sürümü yüklemeniz önerilmez. Bu eski sürümü gerçekten yüklemek istiyorsanız, önce mevcut sürümü kaldırmanız daha uygundur. Gerçekleştirmek istediğiniz işlemi seçin ve devam etmek için İleri'ye tıklayın."
LangString older ${LANG_TURKISH} "daha eski"

View File

@@ -0,0 +1,27 @@
LangString addOrReinstall ${LANG_UKRAINIAN} "Додати/Перевстановити компоненти"
LangString alreadyInstalled ${LANG_UKRAINIAN} "Вже встановлено"
LangString alreadyInstalledLong ${LANG_UKRAINIAN} "${PRODUCTNAME} ${VERSION} вже встановлено. Виберіть дію, яку ви хочете виконати, і натисніть Далі, щоб продовжити."
LangString appRunning ${LANG_UKRAINIAN} "{{product_name}} запущено! Будь ласка, спочатку закрийте його, а потім спробуйте ще раз."
LangString appRunningOkKill ${LANG_UKRAINIAN} "{{product_name}} запущено!$\nНатисніть ОК, щоб примусово закрити його"
LangString chooseMaintenanceOption ${LANG_UKRAINIAN} "Виберіть дію, яку треба виконати."
LangString choowHowToInstall ${LANG_UKRAINIAN} "Виберіть, як ви хочете встановити ${PRODUCTNAME}."
LangString createDesktop ${LANG_UKRAINIAN} "Створити ярлик на робочому столі"
LangString dontUninstall ${LANG_UKRAINIAN} "Не видаляти"
LangString dontUninstallDowngrade ${LANG_UKRAINIAN} "Не видаляти (для цього встановлювача вимкнено зниження версії без видалення)"
LangString failedToKillApp ${LANG_UKRAINIAN} "Не вдалося примусово закрити {{product_name}}. Будь ласка, спочатку закрийте його, а потім спробуйте ще раз"
LangString installingWebview2 ${LANG_UKRAINIAN} "Встановлення WebView2..."
LangString newerVersionInstalled ${LANG_UKRAINIAN} "Новіша версія ${PRODUCTNAME} вже встановлена! Встановлювати старішу версію не рекомендується. Якщо ви дійсно хочете встановити цю версію, краще спочатку видаліть поточну. Виберіть дію, яку ви хочете виконати, і натисніть Далі, щоб продовжити."
LangString older ${LANG_UKRAINIAN} "старішу"
LangString olderOrUnknownVersionInstalled ${LANG_UKRAINIAN} "У вашій системі вже встановлено $R4 версію ${PRODUCTNAME}. Рекомендується видалити поточну версію перед встановленням. Виберіть дію, яку ви хочете виконати, і натисніть Далі, щоб продовжити."
LangString silentDowngrades ${LANG_UKRAINIAN} "Для цього встановлювача вимкнено зниження версій. Неможливо продовжити роботу з фоновим встановлювачем. Будь ласка, скористайтеся встановлювачем з графічним інтерфейсом.$\n"
LangString unableToUninstall ${LANG_UKRAINIAN} "Не вдалося видалити!"
LangString uninstallApp ${LANG_UKRAINIAN} "Видалити ${PRODUCTNAME}"
LangString uninstallBeforeInstalling ${LANG_UKRAINIAN} "Видалити перед встановленням"
LangString unknown ${LANG_UKRAINIAN} "невідому"
LangString webview2AbortError ${LANG_UKRAINIAN} "Не вдалося встановити WebView2! Без нього програма не може працювати. Спробуйте перезапустити встановлювач."
LangString webview2DownloadError ${LANG_UKRAINIAN} "Помилка: не вдалося завантажити WebView2 - $0"
LangString webview2DownloadSuccess ${LANG_UKRAINIAN} "WebView2 успішно завантажено"
LangString webview2Downloading ${LANG_UKRAINIAN} "Завантаження WebView2..."
LangString webview2InstallError ${LANG_UKRAINIAN} "Помилка: не вдалося встановити WebView2, код виходу - $1"
LangString webview2InstallSuccess ${LANG_UKRAINIAN} "WebView2 успішно встановлено "
LangString deleteAppData ${LANG_UKRAINIAN} "Видалити дані програми"

View File

@@ -6,7 +6,7 @@ use crate::{
bundle::{
settings::Arch,
windows::{
sign::{sign_command, try_sign},
sign::{should_sign, sign_command, try_sign},
util::{
download_webview2_bootstrapper, download_webview2_offline_installer,
NSIS_OUTPUT_FOLDER_NAME, NSIS_UPDATER_OUTPUT_FOLDER_NAME,
@@ -39,8 +39,8 @@ const NSIS_URL: &str =
#[cfg(target_os = "windows")]
const NSIS_SHA1: &str = "057e83c7d82462ec394af76c87d06733605543d4";
const NSIS_TAURI_UTILS_URL: &str =
"https://github.com/tauri-apps/nsis-tauri-utils/releases/download/nsis_tauri_utils-v0.4.1/nsis_tauri_utils.dll";
const NSIS_TAURI_UTILS_SHA1: &str = "F99A50209A345185A84D34D0E5F66D04C75FF52F";
"https://github.com/tauri-apps/nsis-tauri-utils/releases/download/nsis_tauri_utils-v0.5.1/nsis_tauri_utils.dll";
const NSIS_TAURI_UTILS_SHA1: &str = "B053B2E5FDB97257954C8F935D80964F056520AE";
#[cfg(target_os = "windows")]
const NSIS_REQUIRED_FILES: &[&str] = &[
@@ -48,18 +48,25 @@ const NSIS_REQUIRED_FILES: &[&str] = &[
"Bin/makensis.exe",
"Stubs/lzma-x86-unicode",
"Stubs/lzma_solid-x86-unicode",
"Plugins/x86-unicode/nsis_tauri_utils.dll",
"Plugins/x86-unicode/additional/nsis_tauri_utils.dll",
"Include/MUI2.nsh",
"Include/FileFunc.nsh",
"Include/x64.nsh",
"Include/nsDialogs.nsh",
"Include/WinMessages.nsh",
];
const NSIS_PLUGIN_FILES: &[&str] = &[
"NSISdl.dll",
"StartMenu.dll",
"System.dll",
"nsDialogs.dll",
"additional/nsis_tauri_utils.dll",
];
#[cfg(not(target_os = "windows"))]
const NSIS_REQUIRED_FILES: &[&str] = &["Plugins/x86-unicode/nsis_tauri_utils.dll"];
const NSIS_REQUIRED_FILES: &[&str] = &["Plugins/x86-unicode/additional/nsis_tauri_utils.dll"];
const NSIS_REQUIRED_FILES_HASH: &[(&str, &str, &str, HashAlgorithm)] = &[(
"Plugins/x86-unicode/nsis_tauri_utils.dll",
"Plugins/x86-unicode/additional/nsis_tauri_utils.dll",
NSIS_TAURI_UTILS_URL,
NSIS_TAURI_UTILS_SHA1,
HashAlgorithm::Sha1,
@@ -96,7 +103,10 @@ pub fn bundle_project(settings: &Settings, updater: bool) -> crate::Result<Vec<P
log::warn!("NSIS directory contains mis-hashed files. Redownloading them.");
for (path, url, hash, hash_algorithm) in mismatched {
let data = download_and_verify(url, hash, *hash_algorithm)?;
fs::write(nsis_toolset_path.join(path), data)?;
let out_path = nsis_toolset_path.join(path);
std::fs::create_dir_all(out_path.parent().context("output path has no parent")?)
.context("failed to create file output directory")?;
fs::write(out_path, data).with_context(|| format!("failed to save {path}"))?;
}
}
}
@@ -116,6 +126,7 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c
fs::rename(_tauri_tools_path.join("nsis-3.08"), nsis_toolset_path)?;
}
// download additional plugins
let nsis_plugins = nsis_toolset_path.join("Plugins");
let data = download_and_verify(
@@ -124,14 +135,14 @@ fn get_and_extract_nsis(nsis_toolset_path: &Path, _tauri_tools_path: &Path) -> c
HashAlgorithm::Sha1,
)?;
let target_folder = nsis_plugins.join("x86-unicode");
let target_folder = nsis_plugins.join("x86-unicode").join("additional");
fs::create_dir_all(&target_folder)?;
fs::write(target_folder.join("nsis_tauri_utils.dll"), data)?;
Ok(())
}
fn add_build_number_if_needed(version_str: &str) -> anyhow::Result<String> {
fn try_add_numeric_build_number(version_str: &str) -> anyhow::Result<String> {
let version = semver::Version::parse(version_str).context("invalid app version")?;
if !version.build.is_empty() {
let build = version.build.parse::<u64>();
@@ -141,7 +152,10 @@ fn add_build_number_if_needed(version_str: &str) -> anyhow::Result<String> {
version.major, version.minor, version.patch, version.build
));
} else {
anyhow::bail!("optional build metadata in app version must be numeric-only");
log::warn!(
"Unable to parse version build metadata. Numeric value expected, received: `{}`. This will be replaced with `0` in `VIProductVersion` because Windows requires this field to be numeric.",
version.build
);
}
}
@@ -150,9 +164,10 @@ fn add_build_number_if_needed(version_str: &str) -> anyhow::Result<String> {
version.major, version.minor, version.patch,
))
}
fn build_nsis_app_installer(
settings: &Settings,
_nsis_toolset_path: &Path,
#[allow(unused_variables)] nsis_toolset_path: &Path,
tauri_tools_path: &Path,
updater: bool,
) -> crate::Result<Vec<PathBuf>> {
@@ -162,8 +177,7 @@ fn build_nsis_app_installer(
Arch::AArch64 => "arm64",
target => {
return Err(crate::Error::ArchError(format!(
"unsupported architecture: {:?}",
target
"unsupported architecture: {target:?}"
)))
}
};
@@ -176,6 +190,65 @@ fn build_nsis_app_installer(
}
fs::create_dir_all(&output_path)?;
// we make a copy of the NSIS directory if we're going to sign its DLLs
// because we don't want to change the DLL hashes so the cache can reuse it
let maybe_plugin_copy_path = if settings.can_sign() {
// find nsis path
#[cfg(target_os = "linux")]
let system_nsis_toolset_path = std::env::var_os("NSIS_PATH")
.map(PathBuf::from)
.unwrap_or_else(|| PathBuf::from("/usr/share/nsis"));
#[cfg(target_os = "macos")]
let system_nsis_toolset_path = std::env::var_os("NSIS_PATH")
.map(PathBuf::from)
.ok_or_else(|| anyhow::anyhow!("failed to resolve NSIS path"))
.or_else(|_| {
let mut makensis_path =
which::which("makensis").context("failed to resolve `makensis`; did you install nsis? See https://tauri.app/distribute/windows-installer/#install-nsis for more information")?;
// homebrew installs it as a symlink
if makensis_path.is_symlink() {
// read_link might return a path relative to makensis_path so we must use join() and canonicalize
makensis_path = makensis_path
.parent()
.context("missing makensis parent")?
.join(std::fs::read_link(&makensis_path).context("failed to resolve makensis symlink")?)
.canonicalize()
.context("failed to resolve makensis path")?;
}
// file structure:
// ├── bin
// │ ├── makensis
// ├── share
// │ ├── nsis
let bin_folder = makensis_path.parent().context("missing makensis parent")?;
let root_folder = bin_folder.parent().context("missing makensis root")?;
crate::Result::Ok(root_folder.join("share").join("nsis"))
})?;
#[cfg(windows)]
let system_nsis_toolset_path = nsis_toolset_path.to_path_buf();
let plugins_path = output_path.join("Plugins");
// copy system plugins (we don't want to modify system installed DLLs, and on some systems there will even be permission errors if we try)
crate::utils::fs_utils::copy_dir(
&system_nsis_toolset_path.join("Plugins").join("x86-unicode"),
&plugins_path.join("x86-unicode"),
)
.context("failed to copy system NSIS Plugins folder to local copy")?;
// copy our downloaded DLLs
crate::utils::fs_utils::copy_dir(
&nsis_toolset_path
.join("Plugins")
.join("x86-unicode")
.join("additional"),
&plugins_path.join("x86-unicode").join("additional"),
)
.context("failed to copy additional NSIS Plugins folder to local copy")?;
Some(plugins_path)
} else {
// in this case plugin_copy_path can be None, we'll use the system default path
None
};
let mut data = BTreeMap::new();
let bundle_id = settings.bundle_identifier();
@@ -183,12 +256,17 @@ fn build_nsis_app_installer(
.publisher()
.unwrap_or_else(|| bundle_id.split('.').nth(1).unwrap_or(bundle_id));
#[cfg(not(target_os = "windows"))]
{
let mut dir = dirs::cache_dir().unwrap();
dir.extend(["tauri", "NSIS", "Plugins", "x86-unicode"]);
data.insert("additional_plugins_path", to_json(dir));
}
let additional_plugins_path = maybe_plugin_copy_path
.clone()
.unwrap_or_else(|| nsis_toolset_path.join("Plugins"))
.join("x86-unicode")
.join("additional");
data.insert(
"additional_plugins_path",
// either our Plugins copy (when signing) or the cache/Plugins/x86-unicode path
to_json(&additional_plugins_path),
);
data.insert("arch", to_json(arch));
data.insert("bundle_id", to_json(bundle_id));
@@ -214,7 +292,7 @@ fn build_nsis_app_installer(
data.insert("version", to_json(version));
data.insert(
"version_with_build",
to_json(add_build_number_if_needed(version)?),
to_json(try_add_numeric_build_number(version)?),
);
data.insert(
@@ -463,6 +541,7 @@ fn build_nsis_app_installer(
let mut handlebars = Handlebars::new();
handlebars.register_helper("or", Box::new(handlebars_or));
handlebars.register_helper("association-description", Box::new(association_description));
handlebars.register_helper("no-escape", Box::new(handlebars_no_escape));
handlebars.register_escape_fn(|s| {
let mut output = String::new();
for c in s.chars() {
@@ -521,13 +600,29 @@ fn build_nsis_app_installer(
));
fs::create_dir_all(nsis_installer_path.parent().unwrap())?;
log::info!(action = "Running"; "makensis.exe to produce {}", display_path(&nsis_installer_path));
if settings.can_sign() {
log::info!("Signing NSIS plugins");
for dll in NSIS_PLUGIN_FILES {
let path = additional_plugins_path.join(dll);
if path.exists() {
try_sign(&path, settings)?;
} else {
log::warn!("Could not find {}, skipping signing", path.display());
}
}
}
log::info!(action = "Running"; "makensis to produce {}", display_path(&nsis_installer_path));
#[cfg(target_os = "windows")]
let mut nsis_cmd = Command::new(_nsis_toolset_path.join("makensis.exe"));
let mut nsis_cmd = Command::new(nsis_toolset_path.join("makensis.exe"));
#[cfg(not(target_os = "windows"))]
let mut nsis_cmd = Command::new("makensis");
if let Some(plugins_path) = &maybe_plugin_copy_path {
nsis_cmd.env("NSISPLUGINS", plugins_path);
}
nsis_cmd
.args(["-INPUTCHARSET", "UTF8", "-OUTPUTCHARSET", "UTF8"])
.arg(match settings.log_level() {
@@ -591,14 +686,49 @@ fn association_description(
Ok(())
}
fn handlebars_no_escape(
h: &handlebars::Helper<'_>,
_: &Handlebars<'_>,
_: &handlebars::Context,
_: &mut handlebars::RenderContext<'_, '_>,
out: &mut dyn handlebars::Output,
) -> handlebars::HelperResult {
// get parameter from helper or throw an error
let param = h
.param(0)
.ok_or(handlebars::RenderErrorReason::ParamNotFoundForIndex(
"no-escape",
0,
))?;
write!(out, "{}", param.render())?;
Ok(())
}
/// BTreeMap<OriginalPath, (ParentOfTargetPath, TargetPath)>
type ResourcesMap = BTreeMap<PathBuf, (PathBuf, PathBuf)>;
fn generate_resource_data(settings: &Settings) -> crate::Result<ResourcesMap> {
let mut resources = ResourcesMap::new();
let cwd = std::env::current_dir()?;
let mut added_resources = Vec::new();
// Adding WebViewer2Loader.dll in case windows-gnu toolchain is used
if settings.target().ends_with("-gnu") {
let loader_path =
dunce::simplified(&settings.project_out_directory().join("WebView2Loader.dll")).to_path_buf();
if loader_path.exists() {
if settings.can_sign() {
try_sign(&loader_path, settings)?;
}
added_resources.push(loader_path.clone());
resources.insert(
loader_path,
(PathBuf::new(), PathBuf::from("WebView2Loader.dll")),
);
}
}
for resource in settings.resource_files().iter() {
let resource = resource?;
@@ -613,6 +743,10 @@ fn generate_resource_data(settings: &Settings) -> crate::Result<ResourcesMap> {
}
added_resources.push(resource_path.clone());
if settings.can_sign() && should_sign(&resource_path)? {
try_sign(&resource_path, settings)?;
}
let target_path = resource.target();
resources.insert(
resource_path,
@@ -702,6 +836,7 @@ fn get_lang_data(lang: &str) -> Option<(String, &[u8])> {
"turkish" => include_bytes!("./languages/Turkish.nsh"),
"swedish" => include_bytes!("./languages/Swedish.nsh"),
"portuguese" => include_bytes!("./languages/Portuguese.nsh"),
"ukrainian" => include_bytes!("./languages/Ukrainian.nsh"),
_ => return None,
};
Some((path, content))

View File

@@ -19,43 +19,54 @@
!macroend
; Checks whether app is running or not and prompts to kill it.
!macro CheckIfAppIsRunning
!macro CheckIfAppIsRunning executableName productName
!define UniqueID ${__LINE__}
; Replace {{product_name}} placeholder in the messages with the passed product name
nsis_tauri_utils::StrReplace "$(appRunning)" "{{product_name}}" "${productName}"
Pop $R1
nsis_tauri_utils::StrReplace "$(appRunningOkKill)" "{{product_name}}" "${productName}"
Pop $R2
nsis_tauri_utils::StrReplace "$(failedToKillApp)" "{{product_name}}" "${productName}"
Pop $R3
!if "${INSTALLMODE}" == "currentUser"
nsis_tauri_utils::FindProcessCurrentUser "${MAINBINARYNAME}.exe"
nsis_tauri_utils::FindProcessCurrentUser "${executableName}"
!else
nsis_tauri_utils::FindProcess "${MAINBINARYNAME}.exe"
nsis_tauri_utils::FindProcess "${executableName}"
!endif
Pop $R0
${If} $R0 = 0
IfSilent kill 0
${IfThen} $PassiveMode != 1 ${|} MessageBox MB_OKCANCEL "$(appRunningOkKill)" IDOK kill IDCANCEL cancel ${|}
kill:
IfSilent kill_${UniqueID} 0
${IfThen} $PassiveMode != 1 ${|} MessageBox MB_OKCANCEL $R2 IDOK kill_${UniqueID} IDCANCEL cancel_${UniqueID} ${|}
kill_${UniqueID}:
!if "${INSTALLMODE}" == "currentUser"
nsis_tauri_utils::KillProcessCurrentUser "${MAINBINARYNAME}.exe"
nsis_tauri_utils::KillProcessCurrentUser "${executableName}"
!else
nsis_tauri_utils::KillProcess "${MAINBINARYNAME}.exe"
nsis_tauri_utils::KillProcess "${executableName}"
!endif
Pop $R0
Sleep 500
${If} $R0 = 0
Goto app_check_done
Goto app_check_done_${UniqueID}
${Else}
IfSilent silent ui
silent:
IfSilent silent_${UniqueID} ui_${UniqueID}
silent_${UniqueID}:
System::Call 'kernel32::AttachConsole(i -1)i.r0'
${If} $0 != 0
System::Call 'kernel32::GetStdHandle(i -11)i.r0'
System::call 'kernel32::SetConsoleTextAttribute(i r0, i 0x0004)' ; set red color
FileWrite $0 "$(appRunning)$\n"
FileWrite $0 "$R1$\n"
${EndIf}
Abort
ui:
Abort "$(failedToKillApp)"
ui_${UniqueID}:
Abort $R3
${EndIf}
cancel:
Abort "$(appRunning)"
cancel_${UniqueID}:
Abort $R1
${EndIf}
app_check_done:
app_check_done_${UniqueID}:
!undef UniqueID
!macroend
; Sets AppUserModelId on a shortcut

View File

@@ -142,12 +142,21 @@ pub fn sign_command_custom<P: AsRef<Path>>(
) -> crate::Result<Command> {
let path = path.as_ref();
let cwd = std::env::current_dir()?;
let mut cmd = Command::new(&command.cmd);
for arg in &command.args {
if arg == "%1" {
cmd.arg(path);
} else {
cmd.arg(arg);
let path = Path::new(arg);
// turn relative paths into absolute paths - so the uninstall command can use them
// since the !uninstfinalize NSIS hook runs in a different directory
if path.exists() && path.is_relative() {
cmd.arg(cwd.join(path));
} else {
cmd.arg(arg);
}
}
}
Ok(cmd)
@@ -205,7 +214,7 @@ pub fn sign_custom<P: AsRef<Path>>(
let output = cmd.output_ok()?;
let stdout = String::from_utf8_lossy(output.stdout.as_slice()).into_owned();
log::info!("{:?}", stdout);
log::info!(action = "Signing";"Output of signing command:\n{}", stdout.trim());
Ok(())
}
@@ -224,7 +233,7 @@ pub fn sign_default<P: AsRef<Path>>(path: P, params: &SignParams) -> crate::Resu
let output = cmd.output_ok()?;
let stdout = String::from_utf8_lossy(output.stdout.as_slice()).into_owned();
log::info!("{:?}", stdout);
log::info!(action = "Signing";"Output of signing command:\n{}", stdout.trim());
Ok(())
}
@@ -241,10 +250,33 @@ pub fn sign<P: AsRef<Path>>(path: P, params: &SignParams) -> crate::Result<()> {
}
}
pub fn try_sign(file_path: &std::path::PathBuf, settings: &Settings) -> crate::Result<()> {
pub fn try_sign<P: AsRef<Path>>(file_path: P, settings: &Settings) -> crate::Result<()> {
if settings.can_sign() {
log::info!(action = "Signing"; "{}", tauri_utils::display_path(file_path));
log::info!(action = "Signing"; "{}", tauri_utils::display_path(file_path.as_ref()));
sign(file_path, &settings.sign_params())?;
}
Ok(())
}
/// If the file is signable (is a binary file) and not signed already
/// (will skip the verification if not on Windows since we can't verify it)
pub fn should_sign(file_path: &Path) -> crate::Result<bool> {
let is_binary = file_path
.extension()
.and_then(|extension| extension.to_str())
.is_some_and(|extension| matches!(extension, "exe" | "dll"));
if !is_binary {
return Ok(false);
}
#[cfg(windows)]
{
let already_signed = verify(file_path)?;
Ok(!already_signed)
}
// Skip verification if not on Windows since we can't verify it
#[cfg(not(windows))]
{
Ok(true)
}
}

View File

@@ -6,8 +6,9 @@ use std::{
fs::create_dir_all,
path::{Path, PathBuf},
};
use ureq::ResponseExt;
use crate::utils::http_utils::download;
use crate::utils::http_utils::{base_ureq_agent, download};
pub const WEBVIEW2_BOOTSTRAPPER_URL: &str = "https://go.microsoft.com/fwlink/p/?LinkId=2124703";
pub const WEBVIEW2_OFFLINE_INSTALLER_X86_URL: &str =
@@ -22,9 +23,9 @@ pub const WIX_OUTPUT_FOLDER_NAME: &str = "msi";
pub const WIX_UPDATER_OUTPUT_FOLDER_NAME: &str = "msi-updater";
pub fn webview2_guid_path(url: &str) -> crate::Result<(String, String)> {
let agent = ureq::AgentBuilder::new().try_proxy_from_env(true).build();
let agent = base_ureq_agent();
let response = agent.head(url).call().map_err(Box::new)?;
let final_url = response.get_url();
let final_url = response.get_uri().to_string();
let remaining_url = final_url.strip_prefix(WEBVIEW2_URL_PREFIX).ok_or_else(|| {
anyhow::anyhow!(
"WebView2 URL prefix mismatch. Expected `{}`, found `{}`.",
@@ -79,3 +80,78 @@ pub fn os_bitness<'a>() -> Option<&'a str> {
_ => None,
}
}
pub fn patch_binary(binary_path: &PathBuf, package_type: &crate::PackageType) -> crate::Result<()> {
let mut file_data = std::fs::read(binary_path)?;
let pe = match goblin::Object::parse(&file_data)? {
goblin::Object::PE(pe) => pe,
_ => {
return Err(crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidInput, "binary is not a PE file").into(),
));
}
};
let tauri_bundle_section = pe
.sections
.iter()
.find(|s| s.name().unwrap_or_default() == ".taubndl")
.ok_or(crate::Error::MissingBundleTypeVar)?;
let data_offset = tauri_bundle_section.pointer_to_raw_data as usize;
if data_offset + 8 > file_data.len() {
return Err(crate::Error::BinaryOffsetOutOfRange);
}
let ptr_bytes = &file_data[data_offset..data_offset + 8];
let ptr_value = u64::from_le_bytes(ptr_bytes.try_into().map_err(|_| {
crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid pointer bytes").into(),
)
})?);
let rdata_section = pe
.sections
.iter()
.find(|s| s.name().unwrap_or_default() == ".rdata")
.ok_or_else(|| {
crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidInput, ".rdata section not found").into(),
)
})?;
let rva = ptr_value.checked_sub(pe.image_base as u64).ok_or_else(|| {
crate::Error::BinaryParseError(
std::io::Error::new(std::io::ErrorKind::InvalidData, "invalid RVA offset").into(),
)
})?;
// see "Relative virtual address (RVA)" for explanation of offset arithmetic here:
// https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#general-concepts
let file_offset = rdata_section.pointer_to_raw_data as usize
+ (rva as usize).saturating_sub(rdata_section.virtual_address as usize);
if file_offset + 3 > file_data.len() {
return Err(crate::Error::BinaryOffsetOutOfRange);
}
// Overwrite the string at that offset
let string_bytes = &mut file_data[file_offset..file_offset + 3];
match package_type {
crate::PackageType::Nsis => string_bytes.copy_from_slice(b"NSS"),
crate::PackageType::WindowsMsi => string_bytes.copy_from_slice(b"MSI"),
_ => {
return Err(crate::Error::InvalidPackageType(
package_type.short_name().to_owned(),
"windows".to_owned(),
));
}
}
std::fs::write(binary_path, &file_data)
.map_err(|e| crate::Error::BinaryWriteError(e.to_string()))?;
Ok(())
}

View File

@@ -64,6 +64,21 @@ pub enum Error {
/// Failed to validate downloaded file hash.
#[error("hash mismatch of downloaded file")]
HashError,
/// Failed to parse binary
#[error("Binary parse error: `{0}`")]
BinaryParseError(#[from] goblin::error::Error),
/// Package type is not supported by target platform
#[error("Wrong package type {0} for platform {1}")]
InvalidPackageType(String, String),
/// Bundle type symbol missing in binary
#[error("__TAURI_BUNDLE_TYPE variable not found in binary. Make sure tauri crate and tauri-cli are up to date")]
MissingBundleTypeVar,
/// Failed to write binary file changed
#[error("Failed to write binary file changes: `{0}`")]
BinaryWriteError(String),
/// Invalid offset while patching binary file
#[error("Invalid offset while patching binary file")]
BinaryOffsetOutOfRange,
/// Unsupported architecture.
#[error("Architecture Error: `{0}`")]
ArchError(String),

View File

@@ -111,9 +111,6 @@ pub fn copy_dir(from: &Path, to: &Path) -> crate::Result<()> {
"{from:?} is not a Directory"
)));
}
if to.exists() {
return Err(crate::Error::GenericError(format!("{to:?} already exists")));
}
let parent = to.parent().expect("No data in parent");
fs::create_dir_all(parent)?;
for entry in walkdir::WalkDir::new(from) {
@@ -129,7 +126,7 @@ pub fn copy_dir(from: &Path, to: &Path) -> crate::Result<()> {
symlink_file(&target, &dest_path)?;
}
} else if entry.file_type().is_dir() {
fs::create_dir(dest_path)?;
fs::create_dir_all(dest_path)?;
} else {
fs::copy(entry.path(), dest_path)?;
}

View File

@@ -47,14 +47,30 @@ fn generate_github_alternative_url(url: &str) -> Option<(ureq::Agent, String)> {
generate_github_mirror_url_from_template(url)
.or_else(|| generate_github_mirror_url_from_base(url))
.map(|alt_url| (ureq::AgentBuilder::new().build(), alt_url))
.map(|alt_url| (ureq::agent(), alt_url))
}
fn create_agent_and_url(url: &str) -> (ureq::Agent, String) {
generate_github_alternative_url(url).unwrap_or((
ureq::AgentBuilder::new().try_proxy_from_env(true).build(),
url.to_owned(),
))
generate_github_alternative_url(url).unwrap_or((base_ureq_agent(), url.to_owned()))
}
pub(crate) fn base_ureq_agent() -> ureq::Agent {
#[cfg(feature = "platform-certs")]
let agent: ureq::Agent = ureq::Agent::config_builder()
.tls_config(
ureq::tls::TlsConfig::builder()
.root_certs(ureq::tls::RootCerts::PlatformVerifier)
.build(),
)
.proxy(ureq::Proxy::try_from_env())
.build()
.into();
#[cfg(not(feature = "platform-certs"))]
let agent: ureq::Agent = ureq::Agent::config_builder()
.proxy(ureq::Proxy::try_from_env())
.build()
.into();
agent
}
#[allow(dead_code)]
@@ -65,7 +81,7 @@ pub fn download(url: &str) -> crate::Result<Vec<u8>> {
let response = agent.get(&final_url).call().map_err(Box::new)?;
let mut bytes = Vec::new();
response.into_reader().read_to_end(&mut bytes)?;
response.into_body().into_reader().read_to_end(&mut bytes)?;
Ok(bytes)
}

View File

@@ -42,7 +42,7 @@ impl CommandExt for Command {
let program = self.get_program().to_string_lossy().into_owned();
log::debug!(action = "Running"; "Command `{} {}`", program, self.get_args().map(|arg| arg.to_string_lossy()).fold(String::new(), |acc, arg| format!("{acc} {arg}")));
self.status().map_err(Into::into)
self.status()
}
fn output_ok(&mut self) -> crate::Result<Output> {

View File

@@ -1,5 +1,243 @@
# Changelog
## \[2.8.0]
### New Features
- [`91508c0b8`](https://www.github.com/tauri-apps/tauri/commit/91508c0b8d16ec61c7706e93b711c5a85aaffb4a) ([#13881](https://www.github.com/tauri-apps/tauri/pull/13881) by [@pepperoni505](https://www.github.com/tauri-apps/tauri/../../pepperoni505)) Introduces a new configuration option that allows you to specify custom folders to watch for changes when running `tauri dev`.
- [`bc4afe7dd`](https://www.github.com/tauri-apps/tauri/commit/bc4afe7dd4780f02c2d4b1f07d97185fbc5d2bba) ([#13993](https://www.github.com/tauri-apps/tauri/pull/13993) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Check installed plugin NPM/crate versions for incompatible releases.
- [`a9ec12843`](https://www.github.com/tauri-apps/tauri/commit/a9ec12843aa7d0eb774bd3a53e2e63da12cfa77b) ([#13521](https://www.github.com/tauri-apps/tauri/pull/13521) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added a `--skip-stapling` option to make `tauri build|bundle` *not* wait for notarization to finish on macOS.
- [`0c402bfb6`](https://www.github.com/tauri-apps/tauri/commit/0c402bfb6bd0bec24d928fcabe2ffef1f5cff19a) ([#13997](https://www.github.com/tauri-apps/tauri/pull/13997) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Increase default iOS deployment target iOS to 14.0.
- [`d6d5f3707`](https://www.github.com/tauri-apps/tauri/commit/d6d5f3707768a094ff7e961ae75ba0398d772655) ([#13358](https://www.github.com/tauri-apps/tauri/pull/13358) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Added `--root-certificate-path` option to `android dev` and `ios dev` to be able to connect to HTTPS dev servers.
### Enhancements
- [`8b465a12b`](https://www.github.com/tauri-apps/tauri/commit/8b465a12ba73e94d7a3995defd9cc362d15eeebe) ([#13913](https://www.github.com/tauri-apps/tauri/pull/13913) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler now pulls the latest AppImage linuxdeploy plugin instead of using the built-in one. This should remove the libfuse requirement.
- [`390cb9c36`](https://www.github.com/tauri-apps/tauri/commit/390cb9c36a4e2416891b64514e7ad5fc0a85ccf2) ([#13953](https://www.github.com/tauri-apps/tauri/pull/13953) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Reduced the log level of the binary patcher crate `goblin` to only show its debug logs in `-vv` and above.
- [`4475e93e1`](https://www.github.com/tauri-apps/tauri/commit/4475e93e136e9e2bd5f3c7817fa2040924f630f6) ([#13824](https://www.github.com/tauri-apps/tauri/pull/13824) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The bundler and cli will now read TLS Certificates installed on the system when downloading tools and checking versions.
### Bug Fixes
- [`f0dcf9637`](https://www.github.com/tauri-apps/tauri/commit/f0dcf9637cc0d42eda05fed7dd6c5ff98bbf19ae) ([#13980](https://www.github.com/tauri-apps/tauri/pull/13980) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix the generated plugin init code of `tauri add` for `tauri-plugin-autostart` and `tauri-plugin-single-instance`
- [`4d270a96a`](https://www.github.com/tauri-apps/tauri/commit/4d270a96a891ae83f7df751abcbe12b7072212d5) ([#13943](https://www.github.com/tauri-apps/tauri/pull/13943) by [@acx0](https://www.github.com/tauri-apps/tauri/../../acx0)) Fix codesigning verification failures caused by binary-patching during bundling
- [`b21d86a8a`](https://www.github.com/tauri-apps/tauri/commit/b21d86a8a3ef29f16628b7d4de17ce1214e9bf49) ([#13981](https://www.github.com/tauri-apps/tauri/pull/13981) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `tauri permission add` could add duplicated permissions to the capability files
- [`9c938be45`](https://www.github.com/tauri-apps/tauri/commit/9c938be4520fce9204361f3b59439844bc5c91e8) ([#13912](https://www.github.com/tauri-apps/tauri/pull/13912) by [@takecchi](https://www.github.com/tauri-apps/tauri/../../takecchi)) Properly migrate svelte to v5 in the plugin example template
### Dependencies
- Upgraded to `tauri-utils@2.7.0`
- Upgraded to `tauri-bundler@2.6.0`
- Upgraded to `tauri-macos-sign@2.2.0`
## \[2.7.1]
### Dependencies
- Upgraded to `tauri-bundler@2.5.2`
## \[2.7.0]
### New Features
- [`33d079392`](https://www.github.com/tauri-apps/tauri/commit/33d079392ac4a5a153b7d8a6d82fefd6f54a2bdf) ([#13811](https://www.github.com/tauri-apps/tauri/pull/13811) by [@mhbagheri-99](https://www.github.com/tauri-apps/tauri/../../mhbagheri-99)) Allow runner configuration to be an object with cmd, cwd, and args properties. The runner can now be configured as `{ "cmd": "my_runner", "cwd": "/path", "args": ["--quiet"] }` while maintaining backwards compatibility with the existing string format.
### Enhancements
- [`232265c70`](https://www.github.com/tauri-apps/tauri/commit/232265c70e1c213bbb3f84b5541ddc07d330fce1) ([#13209](https://www.github.com/tauri-apps/tauri/pull/13209) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Binaries are patched before bundling to add the type of a bundle they will placed in. This information will be used during update process to select the correct target.
### Bug Fixes
- [`916aeaa48`](https://www.github.com/tauri-apps/tauri/commit/916aeaa48646a483a78e51cfe1633800ee62c37c) ([#13781](https://www.github.com/tauri-apps/tauri/pull/13781) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes Android dev and build commands reading `tauri.ios.conf.json` instead of `tauri.android.conf.json` to merge platform-specific configuration.
- [`acd757428`](https://www.github.com/tauri-apps/tauri/commit/acd7574284056f9c00894cdce6c07f948fd80c87) ([#13743](https://www.github.com/tauri-apps/tauri/pull/13743) by [@owjs3901](https://www.github.com/tauri-apps/tauri/../../owjs3901)) Fix type of CFBundleVersion generated by `tauri ios init` when `bundleVersion` is a single number (for example `1` instead of `1.0.0`).
- [`0f248b111`](https://www.github.com/tauri-apps/tauri/commit/0f248b111ffb8af934eaf64bd8f4591e628da786) ([#13799](https://www.github.com/tauri-apps/tauri/pull/13799) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Install iOS dependencies when needed.
- [`7a6fd5b75`](https://www.github.com/tauri-apps/tauri/commit/7a6fd5b75d61071e2771f6277c0376ec206d302a) ([#13863](https://www.github.com/tauri-apps/tauri/pull/13863) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The AppImage bundler now pulls the AppRun binaries from our GitHub mirror, fixing 404 errors.
- [`bda830410`](https://www.github.com/tauri-apps/tauri/commit/bda8304107da7ca60caaba5674faa793491898c6) ([#13833](https://www.github.com/tauri-apps/tauri/pull/13833) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fail with an error when trying to migrate from v2 alpha
- [`bda830410`](https://www.github.com/tauri-apps/tauri/commit/bda8304107da7ca60caaba5674faa793491898c6) ([#13833](https://www.github.com/tauri-apps/tauri/pull/13833) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Use v2 stable instead of v2-rc when migrating from v2-beta
### What's Changed
- [`cfc5bb819`](https://www.github.com/tauri-apps/tauri/commit/cfc5bb819637a97141cbda3285c5d772cfc0ebca) ([#13780](https://www.github.com/tauri-apps/tauri/pull/13780) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Enable edge to edge in `tauri android init` template
- [`12e359061`](https://www.github.com/tauri-apps/tauri/commit/12e3590613c7b4370aeddc16db7e29335e3a7684) ([#13759](https://www.github.com/tauri-apps/tauri/pull/13759) by [@owjs3901](https://www.github.com/tauri-apps/tauri/../../owjs3901)) Update compileSdk, targetSdk in android template to 36
### Dependencies
- Upgraded to `tauri-bundler@2.5.1`
- Upgraded to `tauri-utils@2.6.0`
## \[2.6.2]
### Bug Fixes
- [`cbd962972`](https://www.github.com/tauri-apps/tauri/commit/cbd9629729ed6eb208ba2234d014c11c4e9f1c8c) ([#13730](https://www.github.com/tauri-apps/tauri/pull/13730) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Load `--config` arguments when running the Xcode and Android Studio build scripts.
## \[2.6.1]
### Bug Fixes
- [`4b7370e9e`](https://www.github.com/tauri-apps/tauri/commit/4b7370e9e0ba299361c8ad96c08882337e44f091) ([#13710](https://www.github.com/tauri-apps/tauri/pull/13710) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue in the plugin template (`tauri plugin init`) that prevented the js build command to fail.
## \[2.6.0]
### New Features
- [`414619c36`](https://www.github.com/tauri-apps/tauri/commit/414619c36e94e21939534dd72c0438b93da75546) ([#13536](https://www.github.com/tauri-apps/tauri/pull/13536) by [@Tunglies](https://www.github.com/tauri-apps/tauri/../../Tunglies)) Added support for the `bundleName` property in the macOS bundler configuration. This allows specifying the `CFBundleName` value for generated macOS bundles.
- [`3242e1c94`](https://www.github.com/tauri-apps/tauri/commit/3242e1c946c441b58665ba5d612f3a3f1eafe0b6) ([#13659](https://www.github.com/tauri-apps/tauri/pull/13659) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow passing Cargo arguments to mobile dev and build commands.
- [`d1ce9af62`](https://www.github.com/tauri-apps/tauri/commit/d1ce9af62881e3f7d86a495c9c40df5b7f9d1c04) ([#13660](https://www.github.com/tauri-apps/tauri/pull/13660) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow passing `--config` arguments to the `ios init` and `android init` commands to tweak the configuration used to initialize the mobile projects.
- [`7322f0579`](https://www.github.com/tauri-apps/tauri/commit/7322f057923aaec88960ad5556776774b745762f) ([#13502](https://www.github.com/tauri-apps/tauri/pull/13502) by [@amrbashir](https://www.github.com/tauri-apps/tauri/../../amrbashir)) Allow using `CheckIfAppIsRunning` macro inside NSIS hooks, for example `!insertmacro CheckIfAppIsRunning "another-executable.exe" "Another Executable"`.
- [`4a880ca69`](https://www.github.com/tauri-apps/tauri/commit/4a880ca697bab6d63a2a51ea94e1988cc8c4ea4a) ([#13658](https://www.github.com/tauri-apps/tauri/pull/13658) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Synchronize Tauri config productName changes with the iOS Xcode project.
- [`8ee14a864`](https://www.github.com/tauri-apps/tauri/commit/8ee14a86480510c15823586cf28084e615cb7a9c) ([#13618](https://www.github.com/tauri-apps/tauri/pull/13618) by [@Sky-walkerX](https://www.github.com/tauri-apps/tauri/../../Sky-walkerX)) Warn the user that the app id shouldn't end in `.app` because it conflicts with the application bundle extension on macOS
### Bug Fixes
- [`574a4d4d3`](https://www.github.com/tauri-apps/tauri/commit/574a4d4d36762b5b09dc3fcfcbcae3a0df0b6d89) ([#13426](https://www.github.com/tauri-apps/tauri/pull/13426) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `dev`, `build` and `bundle` commands always take 2 seconds to start
- [`35aa7e121`](https://www.github.com/tauri-apps/tauri/commit/35aa7e1218f34d0805e280e3ec32529d0cb0d733) ([#13294](https://www.github.com/tauri-apps/tauri/pull/13294) by [@kingsword09](https://www.github.com/tauri-apps/tauri/../../kingsword09)) fix: allow the target directory to be inside frontendDir as long as it is not the Rust target directory inside frontendDir.
- [`ec6065fa4`](https://www.github.com/tauri-apps/tauri/commit/ec6065fa4a6427266ecfb0c0f62f008574bb7880) ([#13625](https://www.github.com/tauri-apps/tauri/pull/13625) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fixes Android and iOS dev/build commands not working when the app identifier is being modified by the `--config` option.
- [`5a5291d66`](https://www.github.com/tauri-apps/tauri/commit/5a5291d66cb8a955c9d4f8e975782646ac0cc6e7) ([#13483](https://www.github.com/tauri-apps/tauri/pull/13483) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix simulator build detection on Xcode.
### Dependencies
- Upgraded to `tauri-bundler@2.5.0`
- Upgraded to `tauri-utils@2.5.0`
- [`9c16eefa3`](https://www.github.com/tauri-apps/tauri/commit/9c16eefa319b4697bac1d1019bbb5f93eca63173) ([#13629](https://www.github.com/tauri-apps/tauri/pull/13629) by [@sftse](https://www.github.com/tauri-apps/tauri/../../sftse)) Update html5ever to 0.29 and kuchikiki to version 0.8.8-speedreader.
## \[2.5.0]
### New Features
- [`0aa48fb9e`](https://www.github.com/tauri-apps/tauri/commit/0aa48fb9e4b9d7b5bf3522000a76ebc1836394ed) ([#13030](https://www.github.com/tauri-apps/tauri/pull/13030)) Added `bundleVersion` to iOS and macOS configuration to support specifying a `CFBundleVersion`.
### Enhancements
- [`ad3fd3890`](https://www.github.com/tauri-apps/tauri/commit/ad3fd3890f1fa26a9f9be04ff1bc156d6dd2a8bc) ([#13152](https://www.github.com/tauri-apps/tauri/pull/13152)) Detect package manager from environment variable `npm_config_user_agent` first
- [`82406c61e`](https://www.github.com/tauri-apps/tauri/commit/82406c61e0fbb775ef00791ccab45349325bdd45) ([#13231](https://www.github.com/tauri-apps/tauri/pull/13231)) Improve iOS simulator usage, checking if Xcode iOS SDK is installed and allowing usage of Simulator for older iOS releases (previously only supported when running on Xcode via `ios dev --open`).
### Bug Fixes
- [`2dccfab53`](https://www.github.com/tauri-apps/tauri/commit/2dccfab5321fef55d45f3a4c674b6151b1c4424a) ([#13236](https://www.github.com/tauri-apps/tauri/pull/13236)) Fix `fileAssociations` missing `LSHandlerRank` on macOS.
- [`080252903`](https://www.github.com/tauri-apps/tauri/commit/0802529031c4fd309edff374a8694e93ddec161d) ([#13210](https://www.github.com/tauri-apps/tauri/pull/13210)) Fixes iOS dev not working on Xcode 16.3 simulators. To apply the fix, either regenerate the Xcode project with `rm -r src-tauri/gen/apple && tauri ios init` or remove the `arm64-sim` architecture from the Xcode project.
### Dependencies
- Upgraded to `tauri-utils@2.4.0`
- Upgraded to `tauri-bundler@2.4.0`
## \[2.4.1]
### Enhancements
- [`f805061d1`](https://www.github.com/tauri-apps/tauri/commit/f805061d1152bc4790dbdb9475a506afcdd1de75) ([#13079](https://www.github.com/tauri-apps/tauri/pull/13079) by [@Pietagorh](https://www.github.com/tauri-apps/tauri/../../Pietagorh)) Add support for passing TOML and JSON5 config files to `--config` arg
### Bug Fixes
- [`30beb6fee`](https://www.github.com/tauri-apps/tauri/commit/30beb6fee7b052e588ee72c238e315a557b5d6f2) ([#13096](https://www.github.com/tauri-apps/tauri/pull/13096) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `tauri info` can't find the latest version for rust crates
- [`30beb6fee`](https://www.github.com/tauri-apps/tauri/commit/30beb6fee7b052e588ee72c238e315a557b5d6f2) ([#13096](https://www.github.com/tauri-apps/tauri/pull/13096) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix `tauri info` logging network operations in `info` level instead of `debug`
- [`794af778e`](https://www.github.com/tauri-apps/tauri/commit/794af778e4915ffb6a4fe9bae8fba04bc880503d) ([#13117](https://www.github.com/tauri-apps/tauri/pull/13117) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Fix setting merge config value to null with `--config` arg no longer works
### Dependencies
- Upgraded to `tauri-bundler@2.3.1`
- Upgraded to `tauri-utils@2.3.1`
## \[2.4.0]
### New Features
- [`d91bfa5cb`](https://www.github.com/tauri-apps/tauri/commit/d91bfa5cb921a078758edd45ef3eaff71358d1eb) ([#12970](https://www.github.com/tauri-apps/tauri/pull/12970) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Allow merging multiple configuration values on `tauri dev`, `tauri build`, `tauri bundle`, `tauri android dev`, `tauri android build`, `tauri ios dev` and `tauri ios build`.
- [`013f8f652`](https://www.github.com/tauri-apps/tauri/commit/013f8f652302f2d49c5ec0a075582033d8b074fb) ([#12890](https://www.github.com/tauri-apps/tauri/pull/12890) by [@Legend-Master](https://www.github.com/tauri-apps/tauri/../../Legend-Master)) Reads `build > removeUnusedCommands` from the config file and pass in the environment variables on the build command to trigger the build scripts and macros to remove unused commands based on the capabilities you defined. For this to work on inlined plugins you must add a `#![plugin(<insert_plugin_name>)]` inside the `tauri::generate_handler![]` usage and the app manifest must be set.
- [`30f5a1553`](https://www.github.com/tauri-apps/tauri/commit/30f5a1553d3c0ce460c9006764200a9210915a44) ([#12366](https://www.github.com/tauri-apps/tauri/pull/12366) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Added `trafficLightPosition` window configuration to set the traffic light buttons position on macOS.
### Enhancements
- [`f981a5ee8`](https://www.github.com/tauri-apps/tauri/commit/f981a5ee8b292b9ea09329f60cecc7f688dda734) ([#12602](https://www.github.com/tauri-apps/tauri/pull/12602) by [@kxxt](https://www.github.com/tauri-apps/tauri/../../kxxt)) Add basic support for linux riscv64 platform.
### Bug Fixes
- [`0c4700e99`](https://www.github.com/tauri-apps/tauri/commit/0c4700e9907f242eabe579eb6149a1d75174185c) ([#12985](https://www.github.com/tauri-apps/tauri/pull/12985) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) The cli will now accept `--bundles updater` again. It's still no-op as it has been for all v2 versions. If you want to build updater artifacts, enable `createUpdaterArtifacts` in `tauri.conf.json`.
- [`eec08a18b`](https://www.github.com/tauri-apps/tauri/commit/eec08a18b66525f5544cd30144d0553260ee3a70) ([#12998](https://www.github.com/tauri-apps/tauri/pull/12998) by [@jason89521](https://www.github.com/tauri-apps/tauri/../../jason89521)) For bun's lockfile, check both `bun.lock` and `bun.lockb`.
- [`b83921226`](https://www.github.com/tauri-apps/tauri/commit/b83921226cb3084992bb5357e7e39a09ea97843e) ([#12977](https://www.github.com/tauri-apps/tauri/pull/12977) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix `tauri ios` commands using the wrong working directory with `bun@>1.2`.
- [`f268b3dbd`](https://www.github.com/tauri-apps/tauri/commit/f268b3dbdf313484c85b4a1f69cd7cec63049f35) ([#12871](https://www.github.com/tauri-apps/tauri/pull/12871) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Ignore parent .gitignore files on the Tauri project path detection.
### Dependencies
- Upgraded to `tauri-utils@2.3.0`
- Upgraded to `tauri-bundler@2.3.0`
## \[2.3.1]
### Bug Fixes
- [`22e9bf74a`](https://www.github.com/tauri-apps/tauri/commit/22e9bf74a4684c827279a85bb66548e83c1ea5cf) ([#12538](https://www.github.com/tauri-apps/tauri/pull/12538) by [@DeTeam](https://www.github.com/tauri-apps/tauri/../../DeTeam)) Set initialViewController for LaunchScreen (iOS).
## \[2.3.0]
### Enhancements
- [`a2d36b8c3`](https://www.github.com/tauri-apps/tauri/commit/a2d36b8c34a8dcfc6736797ca5cd4665faf75e7e) ([#12181](https://www.github.com/tauri-apps/tauri/pull/12181) by [@bastiankistner](https://www.github.com/tauri-apps/tauri/../../bastiankistner)) Add an option to change the default background throttling policy (currently for WebKit only).
- [`6e417c943`](https://www.github.com/tauri-apps/tauri/commit/6e417c9435d8fae0eca9e8d42d6215e887a28d98) ([#12786](https://www.github.com/tauri-apps/tauri/pull/12786) by [@kandrelczyk](https://www.github.com/tauri-apps/tauri/../../kandrelczyk)) Added RPM to the list of package types for which signature file will be generated.
### Dependencies
- Upgraded to `tauri-utils@2.2.0`
- Upgraded to `tauri-bundler@2.2.4`
- Upgraded to `tauri-macos-sign@2.1.0`
## \[2.2.7]
### Bug Fixes
- [`8e9134c4a`](https://www.github.com/tauri-apps/tauri/commit/8e9134c4a2047329be0dbb868b7ae061a9d3f190) ([#12511](https://www.github.com/tauri-apps/tauri/pull/12511) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused `tauri dev` to fail because of an incorrect `--bins` flag.
## \[2.2.6]
### Enhancements
- [`1a86974aa`](https://www.github.com/tauri-apps/tauri/commit/1a86974aa3d09957c6b1142a17bbfed9998798fd) ([#12406](https://www.github.com/tauri-apps/tauri/pull/12406) by [@bradleat](https://www.github.com/tauri-apps/tauri/../../bradleat)) `ios build --open` will now let xcode start the rust build process.
- [`9a30bed98`](https://www.github.com/tauri-apps/tauri/commit/9a30bed98c2d8501328006fad5840eb9d533e1c2) ([#12423](https://www.github.com/tauri-apps/tauri/pull/12423) by [@tr3ysmith](https://www.github.com/tauri-apps/tauri/../../tr3ysmith)) Added conditional logic to MacOS codesigning where only executables get the entitlements file when being signed. This solves an issue where the app may not launch when using 3rd party frameworks if certain entitlements are added. Ex: multicast support (must be applied for through apple developer, and the framework would not have that capability).
- [`0b79af711`](https://www.github.com/tauri-apps/tauri/commit/0b79af711430934362602fb950c3e4cb5b59cf9c) ([#12438](https://www.github.com/tauri-apps/tauri/pull/12438) by [@3lpsy](https://www.github.com/tauri-apps/tauri/../../3lpsy)) Log the command used to start the rust app in development.
### Bug Fixes
- [`bc43c738b`](https://www.github.com/tauri-apps/tauri/commit/bc43c738baf686353690d3d9259b4976881718c8) ([#12442](https://www.github.com/tauri-apps/tauri/pull/12442) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that prevented `tauri add` to work for the `clipboard-manager` plugin.
- [`27096cdc0`](https://www.github.com/tauri-apps/tauri/commit/27096cdc05d89b61b2372b4e4a3018c87f240ab8) ([#12445](https://www.github.com/tauri-apps/tauri/pull/12445) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused Tauri's CLI to enable tauri's `native-tls` feature even though it wasn't needed. Moved `reqwest` to a mobile-only dependency in `tauri` and enabled its `rustls-tls` feature flag.
### Dependencies
- Upgraded to `tauri-bundler@2.2.3`
## \[2.2.5]
### Dependencies
- Upgraded to `tauri-bundler@2.2.2`
## \[2.2.4]
### Bug Fixes
- [`cad550445`](https://www.github.com/tauri-apps/tauri/commit/cad5504455ffa53e297cebff473c113b1afa5d29) ([#12354](https://www.github.com/tauri-apps/tauri/pull/12354) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed and issue that caused `tauri add` to try to install incorrect npm packages.
## \[2.2.3]
### Enhancements
- [`a0f2c84d5`](https://www.github.com/tauri-apps/tauri/commit/a0f2c84d51f5086c5055867d6f61ea90c463a26c) ([#12204](https://www.github.com/tauri-apps/tauri/pull/12204) by [@pjf-dev](https://www.github.com/tauri-apps/tauri/../../pjf-dev)) Enhance `tauri icon` command by including 64x64 png size in default icon sizes.
### Bug Fixes
- [`98f62e65a`](https://www.github.com/tauri-apps/tauri/commit/98f62e65a27a375272c6b4d9f34c23e142b9d3a6) ([#12246](https://www.github.com/tauri-apps/tauri/pull/12246) by [@marcomq](https://www.github.com/tauri-apps/tauri/../../marcomq)) Properly add NPM packages for community plugins when using the `tauri add` command.
- [`b9a99a5c6`](https://www.github.com/tauri-apps/tauri/commit/b9a99a5c69d8a2a1a3ff30e500b46872258dca15) ([#12297](https://www.github.com/tauri-apps/tauri/pull/12297) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the built-in dev server to constantly refresh on Linux. This only affected users who do not have `devUrl` point to a URL.
- [`ef21ed9ac`](https://www.github.com/tauri-apps/tauri/commit/ef21ed9ac1c045c38b0c04e3d71a441694abc257) ([#12290](https://www.github.com/tauri-apps/tauri/pull/12290) by [@lucasfernog](https://www.github.com/tauri-apps/tauri/../../lucasfernog)) Fix iOS build failing when the development team contains spaces.
### Dependencies
- Upgraded to `tauri-bundler@2.2.1`
## \[2.2.2]
### Bug Fixes
- [`26fc9558f`](https://www.github.com/tauri-apps/tauri/commit/26fc9558fe7b2fe649f61926da88f36110dd5707) ([#12178](https://www.github.com/tauri-apps/tauri/pull/12178) by [@FabianLars](https://www.github.com/tauri-apps/tauri/../../FabianLars)) Fixed an issue that caused the `tauri dev` file watcher to exit after detecting file changes.
## \[2.2.1]
### Bug Fixes

View File

@@ -1,6 +1,6 @@
[package]
name = "tauri-cli"
version = "2.2.1"
version = "2.8.0"
authors = ["Tauri Programme within The Commons Conservancy"]
edition = "2021"
rust-version = "1.77.2"
@@ -36,7 +36,7 @@ name = "cargo-tauri"
path = "src/main.rs"
[target."cfg(any(target_os = \"linux\", target_os = \"dragonfly\", target_os = \"freebsd\", target_os = \"openbsd\", target_os = \"netbsd\", target_os = \"windows\", target_os = \"macos\"))".dependencies]
cargo-mobile2 = { version = "0.17", default-features = false }
cargo-mobile2 = { version = "0.20.2", default-features = false }
[dependencies]
jsonrpsee = { version = "0.24", features = ["server"] }
@@ -47,35 +47,31 @@ sublime_fuzzy = "0.7"
clap_complete = "4"
clap = { version = "4", features = ["derive", "env"] }
anyhow = "1"
tauri-bundler = { version = "2.2.0", default-features = false, path = "../tauri-bundler" }
tauri-bundler = { version = "2.6.0", default-features = false, path = "../tauri-bundler" }
colored = "2"
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1", features = ["preserve_order"] }
notify = "7"
notify-debouncer-full = "0.4"
json5 = "0.4"
notify = "8"
notify-debouncer-full = "0.6"
shared_child = "1"
duct = "0.13"
toml_edit = { version = "0.22", features = ["serde"] }
duct = "1.0"
toml_edit = { version = "0.23", features = ["serde"] }
json-patch = "3"
tauri-utils = { version = "2.1.1", path = "../tauri-utils", features = [
tauri-utils = { version = "2.7.0", path = "../tauri-utils", features = [
"isolation",
"schema",
"config-json5",
"config-toml",
"html-manipulation",
] }
tauri-utils-v1 = { version = "1", package = "tauri-utils", features = [
"isolation",
"schema",
"config-json5",
"config-toml",
] }
toml = "0.8"
jsonschema = "0.28"
toml = "0.9"
jsonschema = "0.32"
handlebars = "6"
include_dir = "0.7"
minisign = "=0.7.3"
base64 = "0.22"
ureq = { version = "2", default-features = false, features = ["gzip"] }
ureq = { version = "3", default-features = false, features = ["gzip"] }
os_info = "3"
semver = "1"
regex = "1"
@@ -89,16 +85,16 @@ log = { version = "0.4.21", features = ["kv", "kv_std"] }
env_logger = "0.11"
icns = { package = "tauri-icns", version = "0.1" }
image = { version = "0.25", default-features = false, features = ["ico"] }
axum = { version = "0.7", features = ["ws"] }
html5ever = "0.26"
kuchiki = { package = "kuchikiki", version = "0.8" }
axum = { version = "0.8", features = ["ws"] }
html5ever = "0.29"
kuchiki = { package = "kuchikiki", version = "=0.8.8-speedreader" }
tokio = { version = "1", features = ["macros", "sync"] }
common-path = "1"
serde-value = "0.7"
itertools = "0.13"
local-ip-address = "0.6"
css-color = "0.2"
resvg = "0.44.0"
resvg = "0.45.0"
dunce = "1"
glob = "0.3"
# 0.39 raised msrv to above 1.78 but 0.37+ can't compile on 1.77.2 either.
@@ -113,15 +109,16 @@ elf = "0.7"
memchr = "2"
tempfile = "3"
uuid = { version = "1", features = ["v5"] }
rand = "0.8"
rand = "0.9"
[dev-dependencies]
insta = "1"
pretty_assertions = "1"
[target."cfg(windows)".dependencies.windows-sys]
version = "0.59"
version = "0.60"
features = [
"Win32_Security",
"Win32_Storage_FileSystem",
"Win32_System_IO",
"Win32_System_Console",
@@ -132,7 +129,7 @@ libc = "0.2"
[target."cfg(target_os = \"macos\")".dependencies]
plist = "1"
tauri-macos-sign = { version = "2.0.1", path = "../tauri-macos-sign" }
tauri-macos-sign = { version = "2.2.0", path = "../tauri-macos-sign" }
object = { version = "0.36", default-features = false, features = [
"macho",
"read_core",
@@ -141,11 +138,12 @@ object = { version = "0.36", default-features = false, features = [
ar = "0.9"
[features]
default = ["rustls"]
default = ["rustls", "platform-certs"]
native-tls = [
"tauri-bundler/native-tls",
"cargo-mobile2/native-tls",
"ureq/native-tls",
]
native-tls-vendored = ["native-tls", "tauri-bundler/native-tls-vendored"]
rustls = ["tauri-bundler/rustls", "cargo-mobile2/rustls", "ureq/tls"]
rustls = ["tauri-bundler/rustls", "cargo-mobile2/rustls", "ureq/rustls"]
platform-certs = ["tauri-bundler/platform-certs", "ureq/platform-verifier"]

View File

@@ -40,28 +40,3 @@ MIT or MIT/Apache 2.0 where applicable.
Logo: CC-BY-NC-ND
- Original Tauri Logo Designs by [Daniel Thompson-Yvetot](https://github.com/nothingismagick) and [Guillaume Chau](https://github.com/akryum)
## Licensing Errata:
Because of publishing issues upstream, we soft-forked (and patched) both [`console`](https://github.com/mitsuhiko/console/blob/278de9dc2bf0fa28db69adee351072f668beec8f/Cargo.toml#L7) and [`dialoguer`](https://github.com/mitsuhiko/dialoguer/blob/2c3fe6b64641cfb57eb0e1d428274f63976ec150/Cargo.toml#L12) crates because of untenable issues surrounding expected use on Windows.
This soft fork was introduced to the Tauri Codebase [here](https://github.com/tauri-apps/tauri/pull/1610).
`console`
```
license = "MIT"
authors = [
"Armin Ronacher <armin.ronacher@active-4.com>"
]
```
`dialoguer`
```
license = "MIT"
authors = [
"Armin Ronacher <armin.ronacher@active-4.com>",
"Pavan Kumar Sunkara <pavan.sss1991@gmail.com>"
]
```

View File

@@ -1,8 +1,8 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://schema.tauri.app/config/2.2.0",
"$id": "https://schema.tauri.app/config/2.8.2",
"title": "Config",
"description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://v2.tauri.app/reference/cli/#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n Example tauri.config.json file:\n\n ```json\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"../dist\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```",
"description": "The Tauri configuration object.\n It is read from a file where you can define your frontend assets,\n configure the bundler and define a tray icon.\n\n The configuration file is generated by the\n [`tauri init`](https://v2.tauri.app/reference/cli/#init) command that lives in\n your Tauri application source directory (src-tauri).\n\n Once generated, you may modify it at will to customize your Tauri application.\n\n ## File Formats\n\n By default, the configuration is defined as a JSON file named `tauri.conf.json`.\n\n Tauri also supports JSON5 and TOML files via the `config-json5` and `config-toml` Cargo features, respectively.\n The JSON5 file name must be either `tauri.conf.json` or `tauri.conf.json5`.\n The TOML file name is `Tauri.toml`.\n\n ## Platform-Specific Configuration\n\n In addition to the default configuration file, Tauri can\n read a platform-specific configuration from `tauri.linux.conf.json`,\n `tauri.windows.conf.json`, `tauri.macos.conf.json`, `tauri.android.conf.json` and `tauri.ios.conf.json`\n (or `Tauri.linux.toml`, `Tauri.windows.toml`, `Tauri.macos.toml`, `Tauri.android.toml` and `Tauri.ios.toml` if the `Tauri.toml` format is used),\n which gets merged with the main configuration object.\n\n ## Configuration Structure\n\n The configuration is composed of the following objects:\n\n - [`app`](#appconfig): The Tauri configuration\n - [`build`](#buildconfig): The build configuration\n - [`bundle`](#bundleconfig): The bundle configurations\n - [`plugins`](#pluginconfig): The plugins configuration\n\n Example tauri.config.json file:\n\n ```json\n {\n \"productName\": \"tauri-app\",\n \"version\": \"0.1.0\",\n \"build\": {\n \"beforeBuildCommand\": \"\",\n \"beforeDevCommand\": \"\",\n \"devUrl\": \"http://localhost:3000\",\n \"frontendDist\": \"../dist\"\n },\n \"app\": {\n \"security\": {\n \"csp\": null\n },\n \"windows\": [\n {\n \"fullscreen\": false,\n \"height\": 600,\n \"resizable\": true,\n \"title\": \"Tauri App\",\n \"width\": 800\n }\n ]\n },\n \"bundle\": {},\n \"plugins\": {}\n }\n ```",
"type": "object",
"required": [
"identifier"
@@ -24,14 +24,14 @@
"pattern": "^[^/\\:*?\"<>|]+$"
},
"mainBinaryName": {
"description": "App main binary filename. Defaults to the name of your cargo crate.",
"description": "Overrides app's main binary filename.\n\n By default, Tauri uses the output binary from `cargo`, by setting this, we will rename that binary in `tauri-cli`'s\n `tauri build` command, and target `tauri bundle` to it\n\n If possible, change the [`package name`] or set the [`name field`] instead,\n and if that's not enough and you're using nightly, consider using the [`different-binary-name`] feature instead\n\n Note: this config should not include the binary extension (e.g. `.exe`), we'll add that for you\n\n [`package name`]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field\n [`name field`]: https://doc.rust-lang.org/cargo/reference/cargo-targets.html#the-name-field\n [`different-binary-name`]: https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#different-binary-name",
"type": [
"string",
"null"
]
},
"version": {
"description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field. If removed the version number from `Cargo.toml` is used.\n\n By default version 1.0 is used on Android.",
"description": "App version. It is a semver version number or a path to a `package.json` file containing the `version` field.\n\n If removed the version number from `Cargo.toml` is used.\n It's recommended to manage the app versioning in the Tauri config.\n\n ## Platform-specific\n\n - **macOS**: Translates to the bundle's CFBundleShortVersionString property and is used as the default CFBundleVersion.\n You can set an specific bundle version using [`bundle > macOS > bundleVersion`](MacConfig::bundle_version).\n - **iOS**: Translates to the bundle's CFBundleShortVersionString property and is used as the default CFBundleVersion.\n You can set an specific bundle version using [`bundle > iOS > bundleVersion`](IosConfig::bundle_version).\n The `tauri ios build` CLI command has a `--build-number <number>` option that lets you append a build number to the app version.\n - **Android**: By default version 1.0 is used. You can set a version code using [`bundle > android > versionCode`](AndroidConfig::version_code).\n\n By default version 1.0 is used on Android.",
"type": [
"string",
"null"
@@ -69,7 +69,10 @@
},
"build": {
"description": "The build configuration.",
"default": {},
"default": {
"additionalWatchFolders": [],
"removeUnusedCommands": false
},
"allOf": [
{
"$ref": "#/definitions/BuildConfig"
@@ -85,7 +88,7 @@
},
"createUpdaterArtifacts": false,
"iOS": {
"minimumSystemVersion": "13.0"
"minimumSystemVersion": "14.0"
},
"icon": [],
"linux": {
@@ -227,7 +230,7 @@
"type": "string"
},
"create": {
"description": "Whether Tauri should create this window at app startup or not.\n\n When this is set to `false` you must manually grab the config object via `app.config().app.windows`\n and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2.0.0-rc/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).",
"description": "Whether Tauri should create this window at app startup or not.\n\n When this is set to `false` you must manually grab the config object via `app.config().app.windows`\n and create it with [`WebviewWindowBuilder::from_config`](https://docs.rs/tauri/2/tauri/webview/struct.WebviewWindowBuilder.html#method.from_config).",
"default": true,
"type": "boolean"
},
@@ -317,6 +320,17 @@
],
"format": "double"
},
"preventOverflow": {
"description": "Whether or not to prevent the window from overflowing the workarea\n\n ## Platform-specific\n\n - **iOS / Android:** Unsupported.",
"anyOf": [
{
"$ref": "#/definitions/PreventOverflowConfig"
},
{
"type": "null"
}
]
},
"resizable": {
"description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.",
"default": true,
@@ -352,6 +366,11 @@
"default": true,
"type": "boolean"
},
"focusable": {
"description": "Whether the window will be focusable or not.",
"default": true,
"type": "boolean"
},
"transparent": {
"description": "Whether the window is transparent or not.\n\n Note that on `macOS` this requires the `macos-private-api` feature flag, enabled under `tauri > macOSPrivateApi`.\n WARNING: Using private APIs on `macOS` prevents your application from being accepted to the `App Store`.",
"default": false,
@@ -424,6 +443,17 @@
}
]
},
"trafficLightPosition": {
"description": "The position of the window controls on macOS.\n\n Requires titleBarStyle: Overlay and decorations: true.",
"anyOf": [
{
"$ref": "#/definitions/LogicalPosition"
},
{
"type": "null"
}
]
},
"hiddenTitle": {
"description": "If `true`, sets the window title to be hidden on macOS.",
"default": false,
@@ -516,6 +546,32 @@
"type": "null"
}
]
},
"backgroundThrottling": {
"description": "Change the default background throttling behaviour.\n\n By default, browsers use a suspend policy that will throttle timers and even unload\n the whole tab (view) to free resources after roughly 5 minutes when a view became\n minimized or hidden. This will pause all tasks until the documents visibility state\n changes back from hidden to visible by bringing the view back to the foreground.\n\n ## Platform-specific\n\n - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice.\n - **iOS**: Supported since version 17.0+.\n - **macOS**: Supported since version 14.0+.\n\n see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578",
"anyOf": [
{
"$ref": "#/definitions/BackgroundThrottlingPolicy"
},
{
"type": "null"
}
]
},
"javascriptDisabled": {
"description": "Whether we should disable JavaScript code execution on the webview or not.",
"default": false,
"type": "boolean"
},
"allowLinkPreview": {
"description": "on macOS and iOS there is a link preview on long pressing links, this is enabled by default.\n see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview",
"default": true,
"type": "boolean"
},
"disableInputAccessoryView": {
"description": "Allows disabling the input accessory view on iOS.\n\n The accessory view is the view that appears above the keyboard when a text input element is focused.\n It usually displays a view with \"Done\", \"Next\" buttons.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
@@ -539,6 +595,46 @@
}
]
},
"PreventOverflowConfig": {
"description": "Prevent overflow with a margin",
"anyOf": [
{
"description": "Enable prevent overflow or not",
"type": "boolean"
},
{
"description": "Enable prevent overflow with a margin\n so that the window's size + this margin won't overflow the workarea",
"allOf": [
{
"$ref": "#/definitions/PreventOverflowMargin"
}
]
}
]
},
"PreventOverflowMargin": {
"description": "Enable prevent overflow with a margin\n so that the window's size + this margin won't overflow the workarea",
"type": "object",
"required": [
"height",
"width"
],
"properties": {
"width": {
"description": "Horizontal margin in physical unit",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"height": {
"description": "Vertical margin in physical unit",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"Theme": {
"description": "System theme.",
"oneOf": [
@@ -584,6 +680,27 @@
}
]
},
"LogicalPosition": {
"description": "Position coordinates struct.",
"type": "object",
"required": [
"x",
"y"
],
"properties": {
"x": {
"description": "X coordinate.",
"type": "number",
"format": "double"
},
"y": {
"description": "Y coordinate.",
"type": "number",
"format": "double"
}
},
"additionalProperties": false
},
"WindowEffectsConfig": {
"description": "The window effects configuration object",
"type": "object",
@@ -948,6 +1065,32 @@
}
]
},
"BackgroundThrottlingPolicy": {
"description": "Background throttling policy.",
"oneOf": [
{
"description": "A policy where background throttling is disabled",
"type": "string",
"enum": [
"disabled"
]
},
{
"description": "A policy where a web view that's not in a window fully suspends tasks. This is usually the default behavior in case no policy is set.",
"type": "string",
"enum": [
"suspend"
]
},
{
"description": "A policy where a web view that's not in a window limits processing, but does not fully suspend tasks.",
"type": "string",
"enum": [
"throttle"
]
}
]
},
"SecurityConfig": {
"description": "Security configuration.\n\n See more: <https://v2.tauri.app/reference/config/#securityconfig>",
"type": "object",
@@ -1012,7 +1155,7 @@
]
},
"capabilities": {
"description": "List of capabilities that are enabled on the application.\n\n If the list is empty, all capabilities are included.",
"description": "List of capabilities that are enabled on the application.\n\n By default (not set or empty list), all capability files from `./capabilities/` are included,\n by setting values in this entry, you have fine grained control over which capabilities are included\n\n You can either reference a capability file defined in `./capabilities/` with its identifier or inline a [`Capability`]\n\n ### Example\n\n ```json\n {\n \"app\": {\n \"capabilities\": [\n \"main-window\",\n {\n \"identifier\": \"drag-window\",\n \"permissions\": [\"core:window:allow-start-dragging\"]\n }\n ]\n }\n }\n ```",
"default": [],
"type": "array",
"items": {
@@ -1209,7 +1352,7 @@
]
},
"Capability": {
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows fine grained access to the Tauri core, application, or plugin commands.\n If a window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"description": "A grouping and boundary mechanism developers can use to isolate access to the IPC layer.\n\n It controls application windows' and webviews' fine grained access\n to the Tauri core, application, or plugin commands.\n If a webview or its window is not matching any capability then it has no access to the IPC layer at all.\n\n This can be done to create groups of windows, based on their required system access, which can reduce\n impact of frontend vulnerabilities in less privileged windows.\n Windows can be added to a capability by exact name (e.g. `main-window`) or glob patterns like `*` or `admin-*`.\n A Window can have none, one, or multiple associated capabilities.\n\n ## Example\n\n ```json\n {\n \"identifier\": \"main-user-files-write\",\n \"description\": \"This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.\",\n \"windows\": [\n \"main\"\n ],\n \"permissions\": [\n \"core:default\",\n \"dialog:open\",\n {\n \"identifier\": \"fs:allow-write-text-file\",\n \"allow\": [{ \"path\": \"$HOME/test.txt\" }]\n },\n ],\n \"platforms\": [\"macOS\",\"windows\"]\n }\n ```",
"type": "object",
"required": [
"identifier",
@@ -1221,7 +1364,7 @@
"type": "string"
},
"description": {
"description": "Description of what the capability is intended to allow on associated windows.\n\n It should contain a description of what the grouped permissions should allow.\n\n ## Example\n\n This capability allows the `main` window access to `filesystem` write related\n commands and `dialog` commands to enable programatic access to files selected by the user.",
"description": "Description of what the capability is intended to allow on associated windows.\n\n It should contain a description of what the grouped permissions should allow.\n\n ## Example\n\n This capability allows the `main` window access to `filesystem` write related\n commands and `dialog` commands to enable programmatic access to files selected by the user.",
"default": "",
"type": "string"
},
@@ -1242,14 +1385,14 @@
"type": "boolean"
},
"windows": {
"description": "List of windows that are affected by this capability. Can be a glob pattern.\n\n On multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.\n\n ## Example\n\n `[\"main\"]`",
"description": "List of windows that are affected by this capability. Can be a glob pattern.\n\n If a window label matches any of the patterns in this list,\n the capability will be enabled on all the webviews of that window,\n regardless of the value of [`Self::webviews`].\n\n On multiwebview windows, prefer specifying [`Self::webviews`] and omitting [`Self::windows`]\n for a fine grained access control.\n\n ## Example\n\n `[\"main\"]`",
"type": "array",
"items": {
"type": "string"
}
},
"webviews": {
"description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\n This is only required when using on multiwebview contexts, by default\n all child webviews of a window that matches [`Self::windows`] are linked.\n\n ## Example\n\n `[\"sub-webview-one\", \"sub-webview-two\"]`",
"description": "List of webviews that are affected by this capability. Can be a glob pattern.\n\n The capability will be enabled on all the webviews\n whose label matches any of the patterns in this list,\n regardless of whether the webview's window label matches a pattern in [`Self::windows`].\n\n ## Example\n\n `[\"sub-webview-one\", \"sub-webview-two\"]`",
"type": "array",
"items": {
"type": "string"
@@ -1439,7 +1582,7 @@
]
},
"HeaderConfig": {
"description": "A struct, where the keys are some specific http header names.\n If the values to those keys are defined, then they will be send as part of a response message.\n This does not include error messages and ipc messages\n\n ## Example configuration\n ```javascript\n {\n //..\n app:{\n //..\n security: {\n headers: {\n \"Cross-Origin-Opener-Policy\": \"same-origin\",\n \"Cross-Origin-Embedder-Policy\": \"require-corp\",\n \"Timing-Allow-Origin\": [\n \"https://developer.mozilla.org\",\n \"https://example.com\",\n ],\n \"Access-Control-Expose-Headers\": \"Tauri-Custom-Header\",\n \"Tauri-Custom-Header\": {\n \"key1\": \"'value1' 'value2'\",\n \"key2\": \"'value3'\"\n }\n },\n csp: \"default-src 'self'; connect-src ipc: http://ipc.localhost\",\n }\n //..\n }\n //..\n }\n ```\n In this example `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` are set to allow for the use of [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer).\n The result is, that those headers are then set on every response sent via the `get_response` function in crates/tauri/src/protocol/tauri.rs.\n The Content-Security-Policy header is defined separately, because it is also handled separately.\n\n For the helloworld example, this config translates into those response headers:\n ```http\n access-control-allow-origin: http://tauri.localhost\n access-control-expose-headers: Tauri-Custom-Header\n content-security-policy: default-src 'self'; connect-src ipc: http://ipc.localhost; script-src 'self' 'sha256-Wjjrs6qinmnr+tOry8x8PPwI77eGpUFR3EEGZktjJNs='\n content-type: text/html\n cross-origin-embedder-policy: require-corp\n cross-origin-opener-policy: same-origin\n tauri-custom-header: key1 'value1' 'value2'; key2 'value3'\n timing-allow-origin: https://developer.mozilla.org, https://example.com\n ```\n Since the resulting header values are always 'string-like'. So depending on the what data type the HeaderSource is, they need to be converted.\n - `String`(JS/Rust): stay the same for the resulting header value\n - `Array`(JS)/`Vec\\<String\\>`(Rust): Item are joined by \", \" for the resulting header value\n - `Object`(JS)/ `Hashmap\\<String,String\\>`(Rust): Items are composed from: key + space + value. Item are then joined by \"; \" for the resulting header value",
"description": "A struct, where the keys are some specific http header names.\n\n If the values to those keys are defined, then they will be send as part of a response message.\n This does not include error messages and ipc messages\n\n ## Example configuration\n ```javascript\n {\n //..\n app:{\n //..\n security: {\n headers: {\n \"Cross-Origin-Opener-Policy\": \"same-origin\",\n \"Cross-Origin-Embedder-Policy\": \"require-corp\",\n \"Timing-Allow-Origin\": [\n \"https://developer.mozilla.org\",\n \"https://example.com\",\n ],\n \"Access-Control-Expose-Headers\": \"Tauri-Custom-Header\",\n \"Tauri-Custom-Header\": {\n \"key1\": \"'value1' 'value2'\",\n \"key2\": \"'value3'\"\n }\n },\n csp: \"default-src 'self'; connect-src ipc: http://ipc.localhost\",\n }\n //..\n }\n //..\n }\n ```\n In this example `Cross-Origin-Opener-Policy` and `Cross-Origin-Embedder-Policy` are set to allow for the use of [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer).\n The result is, that those headers are then set on every response sent via the `get_response` function in crates/tauri/src/protocol/tauri.rs.\n The Content-Security-Policy header is defined separately, because it is also handled separately.\n\n For the helloworld example, this config translates into those response headers:\n ```http\n access-control-allow-origin: http://tauri.localhost\n access-control-expose-headers: Tauri-Custom-Header\n content-security-policy: default-src 'self'; connect-src ipc: http://ipc.localhost; script-src 'self' 'sha256-Wjjrs6qinmnr+tOry8x8PPwI77eGpUFR3EEGZktjJNs='\n content-type: text/html\n cross-origin-embedder-policy: require-corp\n cross-origin-opener-policy: same-origin\n tauri-custom-header: key1 'value1' 'value2'; key2 'value3'\n timing-allow-origin: https://developer.mozilla.org, https://example.com\n ```\n Since the resulting header values are always 'string-like'. So depending on the what data type the HeaderSource is, they need to be converted.\n - `String`(JS/Rust): stay the same for the resulting header value\n - `Array`(JS)/`Vec\\<String\\>`(Rust): Item are joined by \", \" for the resulting header value\n - `Object`(JS)/ `Hashmap\\<String,String\\>`(Rust): Items are composed from: key + space + value. Item are then joined by \"; \" for the resulting header value",
"type": "object",
"properties": {
"Access-Control-Allow-Credentials": {
@@ -1541,6 +1684,17 @@
}
]
},
"Service-Worker-Allowed": {
"description": "The HTTP Service-Worker-Allowed response header is used to broaden the path restriction for a\n service worker's default scope.\n\n By default, the scope for a service worker registration is the directory where the service\n worker script is located. For example, if the script `sw.js` is located in `/js/sw.js`,\n it can only control URLs under `/js/` by default. Servers can use the `Service-Worker-Allowed`\n header to allow a service worker to control URLs outside of its own directory.\n\n See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Service-Worker-Allowed>",
"anyOf": [
{
"$ref": "#/definitions/HeaderSource"
},
{
"type": "null"
}
]
},
"Timing-Allow-Origin": {
"description": "The Timing-Allow-Origin response header specifies origins that are allowed to see values\n of attributes retrieved via features of the Resource Timing API, which would otherwise be\n reported as zero due to cross-origin restrictions.\n\n See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin>",
"anyOf": [
@@ -1657,13 +1811,17 @@
"properties": {
"runner": {
"description": "The binary used to build and run the application.",
"type": [
"string",
"null"
"anyOf": [
{
"$ref": "#/definitions/RunnerConfig"
},
{
"type": "null"
}
]
},
"devUrl": {
"description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [vite](https://vitejs.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.",
"description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [Vite](https://vite.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.",
"type": [
"string",
"null"
@@ -1723,10 +1881,62 @@
"items": {
"type": "string"
}
},
"removeUnusedCommands": {
"description": "Try to remove unused commands registered from plugins base on the ACL list during `tauri build`,\n the way it works is that tauri-cli will read this and set the environment variables for the build script and macros,\n and they'll try to get all the allowed commands and remove the rest\n\n Note:\n - This won't be accounting for dynamically added ACLs when you use features from the `dynamic-acl` (currently enabled by default) feature flag, so make sure to check it when using this\n - This feature requires tauri-plugin 2.1 and tauri 2.4",
"default": false,
"type": "boolean"
},
"additionalWatchFolders": {
"description": "Additional paths to watch for changes when running `tauri dev`.",
"default": [],
"type": "array",
"items": {
"type": "string"
}
}
},
"additionalProperties": false
},
"RunnerConfig": {
"description": "The runner configuration.",
"anyOf": [
{
"description": "A string specifying the binary to run.",
"type": "string"
},
{
"description": "An object with advanced configuration options.",
"type": "object",
"required": [
"cmd"
],
"properties": {
"cmd": {
"description": "The binary to run.",
"type": "string"
},
"cwd": {
"description": "The current working directory to run the command from.",
"type": [
"string",
"null"
]
},
"args": {
"description": "Arguments to pass to the command.",
"type": [
"array",
"null"
],
"items": {
"type": "string"
}
}
}
}
]
},
"FrontendDist": {
"description": "Defines the URL or assets to embed in the application.",
"anyOf": [
@@ -1924,7 +2134,7 @@
]
},
"useLocalToolsDir": {
"description": "Whether to use the project's `target` directory, for caching build tools (e.g., Wix and NSIS) when building this application. Defaults to `false`.\n\n If true, tools will be cached in `target\\.tauri-tools`.\n If false, tools will be cached in the current user's platform-specific cache directory.\n\n An example where it can be appropriate to set this to `true` is when building this application as a Windows System user (e.g., AWS EC2 workloads),\n because the Window system's app data directory is restricted.",
"description": "Whether to use the project's `target` directory, for caching build tools (e.g., Wix and NSIS) when building this application. Defaults to `false`.\n\n If true, tools will be cached in `target/.tauri/`.\n If false, tools will be cached in the current user's platform-specific cache directory.\n\n An example where it can be appropriate to set this to `true` is when building this application as a Windows System user (e.g., AWS EC2 workloads),\n because the Window system's app data directory is restricted.",
"default": false,
"type": "boolean"
},
@@ -2012,7 +2222,7 @@
"iOS": {
"description": "iOS configuration.",
"default": {
"minimumSystemVersion": "13.0"
"minimumSystemVersion": "14.0"
},
"allOf": [
{
@@ -2116,7 +2326,7 @@
"description": "Updater type",
"anyOf": [
{
"description": "Generates lagacy zipped v1 compatible updaters",
"description": "Generates legacy zipped v1 compatible updaters",
"allOf": [
{
"$ref": "#/definitions/V1Compatible"
@@ -2130,10 +2340,10 @@
]
},
"V1Compatible": {
"description": "Generates lagacy zipped v1 compatible updaters",
"description": "Generates legacy zipped v1 compatible updaters",
"oneOf": [
{
"description": "Generates lagacy zipped v1 compatible updaters",
"description": "Generates legacy zipped v1 compatible updaters",
"type": "string",
"enum": [
"v1Compatible"
@@ -2203,6 +2413,15 @@
"string",
"null"
]
},
"rank": {
"description": "The ranking of this app among apps that declare themselves as editors or viewers of the given file type. Maps to `LSHandlerRank` on macOS.",
"default": "Default",
"allOf": [
{
"$ref": "#/definitions/HandlerRank"
}
]
}
},
"additionalProperties": false
@@ -2251,6 +2470,39 @@
}
]
},
"HandlerRank": {
"description": "Corresponds to LSHandlerRank",
"oneOf": [
{
"description": "LSHandlerRank.Default. This app is an opener of files of this type; this value is also used if no rank is specified.",
"type": "string",
"enum": [
"Default"
]
},
{
"description": "LSHandlerRank.Owner. This app is the primary creator of files of this type.",
"type": "string",
"enum": [
"Owner"
]
},
{
"description": "LSHandlerRank.Alternate. This app is a secondary viewer of files of this type.",
"type": "string",
"enum": [
"Alternate"
]
},
{
"description": "LSHandlerRank.None. This app is never selected to open files of this type, but it accepts drops of files of this type.",
"type": "string",
"enum": [
"None"
]
}
]
},
"WindowsConfig": {
"description": "Windows bundler configuration.\n\n See more: <https://v2.tauri.app/reference/config/#windowsconfig>",
"type": "object",
@@ -2540,6 +2792,11 @@
"string",
"null"
]
},
"fipsCompliant": {
"description": "Enables FIPS compliant algorithms.\n Can also be enabled via the `TAURI_BUNDLER_WIX_FIPS_COMPLIANT` env var.",
"default": false,
"type": "boolean"
}
},
"additionalProperties": false
@@ -3211,6 +3468,20 @@
"type": "string"
}
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.\n\n Translates to the bundle's CFBundleVersion property.",
"type": [
"string",
"null"
]
},
"bundleName": {
"description": "The name of the builder that built the bundle.\n\n Translates to the bundle's CFBundleName property.\n\n If not set, defaults to the package's product name.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum macOS X version that the bundled application supports. Defaults to `10.13`.\n\n Setting it to `null` completely removes the `LSMinimumSystemVersion` field on the bundle's `Info.plist`\n and the `MACOSX_DEPLOYMENT_TARGET` environment variable.\n\n An empty string is considered an invalid value so the default value is used.",
"default": "10.13",
@@ -3234,7 +3505,7 @@
]
},
"hardenedRuntime": {
"description": "Whether the codesign should enable [hardened runtime] (for executables) or not.\n\n [hardened runtime]: <https://developer.apple.com/documentation/security/hardened_runtime>",
"description": "Whether the codesign should enable [hardened runtime](https://developer.apple.com/documentation/security/hardened_runtime) (for executables) or not.",
"default": true,
"type": "boolean"
},
@@ -3412,9 +3683,16 @@
"null"
]
},
"bundleVersion": {
"description": "The version of the build that identifies an iteration of the bundle.\n\n Translates to the bundle's CFBundleVersion property.",
"type": [
"string",
"null"
]
},
"minimumSystemVersion": {
"description": "A version string indicating the minimum iOS version that the bundled application supports. Defaults to `13.0`.\n\n Maps to the IPHONEOS_DEPLOYMENT_TARGET value.",
"default": "13.0",
"default": "14.0",
"type": "string"
}
},

View File

@@ -1,9 +1,9 @@
{
"cli.js": {
"version": "2.2.1",
"version": "2.8.1",
"node": ">= 10.0.0"
},
"tauri": "2.2.0",
"tauri-build": "2.0.3",
"tauri-plugin": "2.0.3"
"tauri": "2.8.2",
"tauri-build": "2.4.0",
"tauri-plugin": "2.4.0"
}

View File

@@ -301,6 +301,17 @@
],
"format": "double"
},
"preventOverflow": {
"description": "Whether or not to prevent window overflow",
"anyOf": [
{
"$ref": "#/definitions/PreventOverflowMarginConfig"
},
{
"type": "null"
}
]
},
"resizable": {
"description": "Whether the window is resizable or not. When resizable is set to false, native window's maximize button is automatically disabled.",
"default": true,
@@ -465,6 +476,15 @@
"description": "Whether page zooming by hotkeys is enabled\n\n ## Platform-specific:\n\n - **Windows**: Controls WebView2's [`IsZoomControlEnabled`](https://learn.microsoft.com/en-us/microsoft-edge/webview2/reference/winrt/microsoft_web_webview2_core/corewebview2settings?view=webview2-winrt-1.0.2420.47#iszoomcontrolenabled) setting.\n - **MacOS / Linux**: Injects a polyfill that zooms in and out with `ctrl/command` + `-/=`,\n 20% in each step, ranging from 20% to 1000%. Requires `webview:allow-set-webview-zoom` permission\n\n - **Android / iOS**: Unsupported.",
"default": false,
"type": "boolean"
},
"backgroundThrottling": {
"description": "Change the default background throttling behaviour.\n\n By default, browsers use a suspend policy that will throttle timers and even unload\n the whole tab (view) to free resources after roughly 5 minutes when a view became\n minimized or hidden. This will pause all tasks until the documents visibility state\n changes back from hidden to visible by bringing the view back to the foreground.\n\n ## Platform-specific\n\n - **Linux / Windows / Android**: Unsupported. Workarounds like a pending WebLock transaction might suffice.\n - **iOS**: Supported since version 17.0+.\n - **macOS**: Supported since version 14.0+.\n\n see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578",
"type": "string",
"enum": [
"disabled",
"throttle",
"suspend"
]
}
},
"additionalProperties": false
@@ -488,6 +508,46 @@
}
]
},
"PreventOverflowMarginConfig": {
"description": "Prevent overflow with a margin",
"anyOf": [
{
"description": "Enable prevent overflow or not",
"type": "boolean"
},
{
"description": "Enable prevent overflow with a margin",
"allOf": [
{
"$ref": "#/definitions/PreventOverflowMargin"
}
]
}
]
},
"PreventOverflowMargin": {
"description": "Enable prevent overflow with a margin",
"type": "object",
"required": [
"height",
"width"
],
"properties": {
"width": {
"description": "Horizontal margin in physical unit",
"type": "integer",
"format": "uint32",
"minimum": 0.0
},
"height": {
"description": "Vertical margin in physical unit",
"type": "integer",
"format": "uint32",
"minimum": 0.0
}
},
"additionalProperties": false
},
"Theme": {
"description": "System theme.",
"oneOf": [
@@ -1369,7 +1429,7 @@
]
},
"devUrl": {
"description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [vite](https://vitejs.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.",
"description": "The URL to load in development.\n\n This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR.\n Most modern JavaScript bundlers like [Vite](https://vite.dev/guide/) provides a way to start a dev server by default.\n\n If you don't have a dev server or don't want to use one, ignore this option and use [`frontendDist`](BuildConfig::frontend_dist)\n and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.",
"type": [
"string",
"null"
@@ -1906,6 +1966,15 @@
"string",
"null"
]
},
"rank": {
"description": "The ranking of this app among apps that declare themselves as editors or viewers of the given file type. Maps to `LSHandlerRank` on macOS.",
"default": "Default",
"allOf": [
{
"$ref": "#/definitions/HandlerRank"
}
]
}
},
"additionalProperties": false
@@ -1954,6 +2023,39 @@
}
]
},
"HandlerRank": {
"description": "Corresponds to LSHandlerRank",
"oneOf": [
{
"description": "LSHandlerRank.Default. This app is an opener of files of this type; this value is also used if no rank is specified.",
"type": "string",
"enum": [
"Default"
]
},
{
"description": "LSHandlerRank.Owner. This app is the primary creator of files of this type.",
"type": "string",
"enum": [
"Owner"
]
},
{
"description": "LSHandlerRank.Alternate. This app is a secondary viewer of files of this type.",
"type": "string",
"enum": [
"Alternate"
]
},
{
"description": "LSHandlerRank.None. This app is never selected to open files of this type, but it accepts drops of files of this type.",
"type": "string",
"enum": [
"None"
]
}
]
},
"WindowsConfig": {
"description": "Windows bundler configuration.\n\n See more: <https://tauri.app/v1/api/config#windowsconfig>",
"type": "object",
@@ -2228,6 +2330,14 @@
"string",
"null"
]
},
"fipsCompliant": {
"description": "Enables FIPS compliant algorithms.",
"default": null,
"type": [
"boolean",
"null"
]
}
},
"additionalProperties": false

View File

@@ -98,7 +98,7 @@ pub fn command(options: Options) -> Result<()> {
PermissionEntry::PermissionRef(
p.clone()
.try_into()
.unwrap_or_else(|_| panic!("invalid permission {}", p)),
.unwrap_or_else(|_| panic!("invalid permission {p}")),
)
})
.collect(),

View File

@@ -77,6 +77,26 @@ impl TomlOrJson {
};
}
fn has_permission(&self, identifier: &str) -> bool {
(|| {
Some(match self {
TomlOrJson::Toml(t) => t
.get("permissions")?
.as_array()?
.iter()
.any(|value| value.as_str() == Some(identifier)),
TomlOrJson::Json(j) => j
.as_object()?
.get("permissions")?
.as_array()?
.iter()
.any(|value| value.as_str() == Some(identifier)),
})
})()
.unwrap_or_default()
}
fn to_string(&self) -> Result<String> {
Ok(match self {
TomlOrJson::Toml(t) => t.to_string(),
@@ -166,16 +186,15 @@ pub fn command(options: Options) -> Result<()> {
let capabilities = if let Some((expected_platforms, target_name)) = expected_capability_config {
let mut capabilities = capabilities_iter
.filter(|(capability, _path)| {
capability.platforms().map_or(
false, /* allows any target, so we should skip it since we're adding a target-specific plugin */
|platforms| {
// all platforms must be in the expected platforms list
platforms.iter().all(|p| expected_platforms.contains(&p.to_string()))
},
)
.filter(|(capability, _path)| {
capability.platforms().is_some_and(|platforms| {
// all platforms must be in the expected platforms list
platforms
.iter()
.all(|p| expected_platforms.contains(&p.to_string()))
})
.collect::<Vec<_>>();
})
.collect::<Vec<_>>();
if capabilities.is_empty() {
let identifier = format!("{target_name}-capability");
@@ -237,9 +256,18 @@ pub fn command(options: Options) -> Result<()> {
}
for (capability, path) in &mut capabilities {
capability.insert_permission(options.identifier.clone());
std::fs::write(&*path, capability.to_string()?)?;
log::info!(action = "Added"; "permission `{}` to `{}` at {}", options.identifier, capability.identifier(), dunce::simplified(path).display());
if capability.has_permission(&options.identifier) {
log::info!(
"Permission `{}` already found in `{}` at {}",
options.identifier,
capability.identifier(),
dunce::simplified(path).display()
);
} else {
capability.insert_permission(options.identifier.clone());
std::fs::write(&*path, capability.to_string()?)?;
log::info!(action = "Added"; "permission `{}` to `{}` at {}", options.identifier, capability.identifier(), dunce::simplified(path).display());
}
}
Ok(())

View File

@@ -49,12 +49,25 @@ pub fn run(options: Options) -> Result<()> {
.map(|(p, v)| (p, Some(v)))
.unwrap_or((&options.plugin, None));
let mut plugins = crate::helpers::plugins::known_plugins();
let (metadata, is_known) = plugins
.remove(plugin)
.map(|metadata| (metadata, true))
.unwrap_or_default();
let plugin_snake_case = plugin.replace('-', "_");
let crate_name = format!("tauri-plugin-{plugin}");
let npm_name = format!("@tauri-apps/plugin-{plugin}");
let npm_name = if is_known {
format!("@tauri-apps/plugin-{plugin}")
} else {
format!("tauri-plugin-{plugin}-api")
};
let mut plugins = crate::helpers::plugins::known_plugins();
let metadata = plugins.remove(plugin).unwrap_or_default();
if !is_known && (options.tag.is_some() || options.rev.is_some() || options.branch.is_some()) {
anyhow::bail!(
"Git options --tag, --rev and --branch can only be used with official Tauri plugins"
);
}
let frontend_dir = resolve_frontend_dir();
let tauri_dir = tauri_dir();
@@ -117,6 +130,8 @@ pub fn run(options: Options) -> Result<()> {
"Builder::new(|pass| todo!()).build()"
} else if plugin == "localhost" {
"Builder::new(todo!()).build()"
} else if plugin == "single-instance" {
"init(|app, args, cwd| {})"
} else if metadata.builder {
"Builder::new().build()"
} else {

View File

@@ -6,15 +6,17 @@ use crate::{
bundle::BundleFormat,
helpers::{
self,
app_paths::tauri_dir,
app_paths::{frontend_dir, tauri_dir},
config::{get as get_config, ConfigHandle, FrontendDist},
},
interface::{AppInterface, Interface},
info::plugins::check_mismatched_packages,
interface::{rust::get_cargo_target_dir, AppInterface, Interface},
ConfigValue, Result,
};
use anyhow::Context;
use clap::{ArgAction, Parser};
use std::env::set_current_dir;
use tauri_utils::config::RunnerConfig;
use tauri_utils::platform::Target;
#[derive(Debug, Clone, Parser)]
@@ -25,7 +27,7 @@ use tauri_utils::platform::Target;
pub struct Options {
/// Binary to use to build the application, defaults to `cargo`
#[clap(short, long)]
pub runner: Option<String>,
pub runner: Option<RunnerConfig>,
/// Builds with the debug flag
#[clap(short, long)]
pub debug: bool,
@@ -40,21 +42,40 @@ pub struct Options {
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
pub features: Option<Vec<String>>,
/// Space or comma separated list of bundles to package.
///
/// Note that the `updater` bundle is not automatically added so you must specify it if the updater is enabled.
#[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')]
pub bundles: Option<Vec<BundleFormat>>,
/// Skip the bundling step even if `bundle > active` is `true` in tauri config.
#[clap(long)]
pub no_bundle: bool,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments.
pub args: Vec<String>,
/// Skip prompting for values
#[clap(long, env = "CI")]
pub ci: bool,
/// Whether to wait for notarization to finish and `staple` the ticket onto the app.
///
/// Gatekeeper will look for stapled tickets to tell whether your app was notarized without
/// reaching out to Apple's servers which is helpful in offline environments.
///
/// Enabling this option will also result in `tauri build` not waiting for notarization to finish
/// which is helpful for the very first time your app is notarized as this can take multiple hours.
/// On subsequent runs, it's recommended to disable this setting again.
#[clap(long)]
pub skip_stapling: bool,
/// Do not error out if a version mismatch is detected on a Tauri package.
///
/// Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.
#[clap(long)]
pub ignore_version_mismatches: bool,
}
pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
@@ -68,7 +89,10 @@ pub fn command(mut options: Options, verbosity: u8) -> Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);
let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;
let mut interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
@@ -113,6 +137,18 @@ pub fn setup(
mobile: bool,
) -> Result<()> {
let tauri_path = tauri_dir();
// TODO: Maybe optimize this to run in parallel in the future
// see https://github.com/tauri-apps/tauri/pull/13993#discussion_r2280697117
log::info!("Looking up installed tauri packages to check mismatched versions...");
if let Err(error) = check_mismatched_packages(frontend_dir(), tauri_path) {
if options.ignore_version_mismatches {
log::error!("{error}");
} else {
return Err(error);
}
}
set_current_dir(tauri_path).with_context(|| "failed to change current working directory")?;
let config_guard = config.lock().unwrap();
@@ -123,11 +159,9 @@ pub fn setup(
.unwrap_or_else(|| "tauri.conf.json".into());
if config_.identifier == "com.tauri.dev" {
log::error!(
"You must change the bundle identifier in `{} identifier`. The default value `com.tauri.dev` is not allowed as it must be unique across applications.",
bundle_identifier_source
anyhow::bail!(
"You must change the bundle identifier in `{bundle_identifier_source} identifier`. The default value `com.tauri.dev` is not allowed as it must be unique across applications.",
);
std::process::exit(1);
}
if config_
@@ -135,12 +169,19 @@ pub fn setup(
.chars()
.any(|ch| !(ch.is_alphanumeric() || ch == '-' || ch == '.'))
{
log::error!(
anyhow::bail!(
"The bundle identifier \"{}\" set in `{} identifier`. The bundle identifier string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).",
config_.identifier,
bundle_identifier_source
);
std::process::exit(1);
}
if config_.identifier.ends_with(".app") {
log::warn!(
"The bundle identifier \"{}\" set in `{} identifier` ends with `.app`. This is not recommended because it conflicts with the application bundle extension on macOS.",
config_.identifier,
bundle_identifier_source
);
}
if let Some(before_build) = config_.build.before_build_command.clone() {
@@ -165,24 +206,37 @@ pub fn setup(
));
}
// Issue #13287 - Allow the use of target dir inside frontendDist/distDir
// https://github.com/tauri-apps/tauri/issues/13287
let target_path = get_cargo_target_dir(&options.args)?;
let mut out_folders = Vec::new();
for folder in &["node_modules", "src-tauri", "target"] {
if web_asset_path.join(folder).is_dir() {
out_folders.push(folder.to_string());
if let Ok(web_asset_canonical) = dunce::canonicalize(web_asset_path) {
if let Ok(relative_path) = target_path.strip_prefix(&web_asset_canonical) {
let relative_str = relative_path.to_string_lossy();
if !relative_str.is_empty() {
out_folders.push(relative_str.to_string());
}
}
for folder in &["node_modules", "src-tauri"] {
let sub_path = web_asset_canonical.join(folder);
if sub_path.is_dir() {
out_folders.push(folder.to_string());
}
}
}
if !out_folders.is_empty() {
return Err(anyhow::anyhow!(
"The configured frontendDist includes the `{:?}` {}. Please isolate your web assets on a separate folder and update `tauri.conf.json > build > frontendDist`.",
out_folders,
if out_folders.len() == 1 { "folder" }else { "folders" }
)
);
"The configured frontendDist includes the `{:?}` {}. Please isolate your web assets on a separate folder and update `tauri.conf.json > build > frontendDist`.",
out_folders,
if out_folders.len() == 1 { "folder" } else { "folders" }
));
}
}
if options.runner.is_none() {
options.runner.clone_from(&config_.build.runner);
options.runner = config_.build.runner.clone();
}
options

View File

@@ -43,7 +43,8 @@ impl ValueEnum for BundleFormat {
}
fn to_possible_value(&self) -> Option<PossibleValue> {
Some(PossibleValue::new(self.0.short_name()))
let hide = self.0 == PackageType::Updater;
Some(PossibleValue::new(self.0.short_name()).hide(hide))
}
}
@@ -57,13 +58,17 @@ pub struct Options {
#[clap(short, long)]
pub debug: bool,
/// Space or comma separated list of bundles to package.
///
/// Note that the `updater` bundle is not automatically added so you must specify it if the updater is enabled.
#[clap(short, long, action = ArgAction::Append, num_args(0..), value_delimiter = ',')]
pub bundles: Option<Vec<BundleFormat>>,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Space or comma separated list of features, should be the same features passed to `tauri build` if any.
#[clap(short, long, action = ArgAction::Append, num_args(0..))]
pub features: Option<Vec<String>>,
@@ -77,6 +82,16 @@ pub struct Options {
/// Skip prompting for values
#[clap(long, env = "CI")]
pub ci: bool,
/// Whether to wait for notarization to finish and `staple` the ticket onto the app.
///
/// Gatekeeper will look for stapled tickets to tell whether your app was notarized without
/// reaching out to Apple's servers which is helpful in offline environments.
///
/// Enabling this option will also result in `tauri build` not waiting for notarization to finish
/// which is helpful for the very first time your app is notarized as this can take multiple hours.
/// On subsequent runs, it's recommended to disable this setting again.
#[clap(long)]
pub skip_stapling: bool,
}
impl From<crate::build::Options> for Options {
@@ -88,6 +103,7 @@ impl From<crate::build::Options> for Options {
debug: value.debug,
ci: value.ci,
config: value.config,
skip_stapling: value.skip_stapling,
}
}
}
@@ -103,7 +119,10 @@ pub fn command(options: Options, verbosity: u8) -> crate::Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);
let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;
let interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
@@ -213,6 +232,7 @@ fn sign_updaters(
| PackageType::WindowsMsi
| PackageType::AppImage
| PackageType::Deb
| PackageType::Rpm
)
})
.collect();

View File

@@ -10,6 +10,7 @@ use crate::{
get as get_config, reload as reload_config, BeforeDevCommand, ConfigHandle, FrontendDist,
},
},
info::plugins::check_mismatched_packages,
interface::{AppInterface, ExitReason, Interface},
CommandExt, ConfigValue, Result,
};
@@ -17,11 +18,12 @@ use crate::{
use anyhow::{bail, Context};
use clap::{ArgAction, Parser};
use shared_child::SharedChild;
use tauri_utils::platform::Target;
use tauri_utils::{config::RunnerConfig, platform::Target};
use std::{
env::set_current_dir,
net::{IpAddr, Ipv4Addr},
path::PathBuf,
process::{exit, Command, Stdio},
sync::{
atomic::{AtomicBool, Ordering},
@@ -49,7 +51,7 @@ pub const TAURI_CLI_BUILTIN_WATCHER_IGNORE_FILE: &[u8] =
pub struct Options {
/// Binary to use to run the application
#[clap(short, long)]
pub runner: Option<String>,
pub runner: Option<RunnerConfig>,
/// Target triple to build against
#[clap(short, long)]
pub target: Option<String>,
@@ -59,9 +61,15 @@ pub struct Options {
/// Exit on panic
#[clap(short, long)]
pub exit_on_panic: bool,
/// JSON string or path to JSON file to merge with tauri.conf.json
/// JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file
///
/// Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.
///
/// Note that a platform-specific file is looked up and merged with the default file by default
/// (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json)
/// but you can use this for more specific use cases such as different build flavors.
#[clap(short, long)]
pub config: Option<ConfigValue>,
pub config: Vec<ConfigValue>,
/// Run the code in release mode
#[clap(long = "release")]
pub release_mode: bool,
@@ -75,6 +83,9 @@ pub struct Options {
/// Disable the file watcher.
#[clap(long)]
pub no_watch: bool,
/// Additional paths to watch for changes.
#[clap(long)]
pub additional_watch_folders: Vec<PathBuf>,
/// Disable the built-in dev server for static files.
#[clap(long)]
@@ -104,7 +115,10 @@ fn command_internal(mut options: Options) -> Result<()> {
.map(Target::from_triple)
.unwrap_or_else(Target::current);
let config = get_config(target, options.config.as_ref().map(|c| &c.0))?;
let config = get_config(
target,
&options.config.iter().map(|c| &c.0).collect::<Vec<_>>(),
)?;
let mut interface = AppInterface::new(
config.lock().unwrap().as_ref().unwrap(),
@@ -122,6 +136,13 @@ fn command_internal(mut options: Options) -> Result<()> {
pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHandle) -> Result<()> {
let tauri_path = tauri_dir();
std::thread::spawn(|| {
if let Err(error) = check_mismatched_packages(frontend_dir(), tauri_path) {
log::error!("{error}");
}
});
set_current_dir(tauri_path).with_context(|| "failed to change current working directory")?;
if let Some(before_dev) = config
@@ -215,9 +236,14 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
}
if options.runner.is_none() {
options
options.runner = config
.lock()
.unwrap()
.as_ref()
.unwrap()
.build
.runner
.clone_from(&config.lock().unwrap().as_ref().unwrap().build.runner);
.clone();
}
let mut cargo_features = config
@@ -262,26 +288,13 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
let server_url = format!("http://{server_url}");
dev_url = Some(server_url.parse().unwrap());
if let Some(c) = &mut options.config {
if let Some(build) = c
.0
.as_object_mut()
.and_then(|root| root.get_mut("build"))
.and_then(|build| build.as_object_mut())
{
build.insert("devUrl".into(), server_url.into());
options.config.push(crate::ConfigValue(serde_json::json!({
"build": {
"devUrl": server_url
}
} else {
options
.config
.replace(crate::ConfigValue(serde_json::json!({
"build": {
"devUrl": server_url
}
})));
}
})));
reload_config(options.config.as_ref().map(|c| &c.0))?;
reload_config(&options.config.iter().map(|c| &c.0).collect::<Vec<_>>())?;
}
}
}
@@ -335,11 +348,27 @@ pub fn setup(interface: &AppInterface, options: &mut Options, config: ConfigHand
}
}
if options.additional_watch_folders.is_empty() {
options.additional_watch_folders.extend(
config
.lock()
.unwrap()
.as_ref()
.unwrap()
.build
.additional_watch_folders
.clone(),
);
}
Ok(())
}
pub fn on_app_exit(code: Option<i32>, reason: ExitReason, exit_on_panic: bool, no_watch: bool) {
if no_watch || exit_on_panic || matches!(reason, ExitReason::NormalExit) {
if no_watch
|| (!matches!(reason, ExitReason::TriggeredKill)
&& (exit_on_panic || matches!(reason, ExitReason::NormalExit)))
{
kill_before_dev_process();
exit(code.unwrap_or(0));
}

View File

@@ -79,7 +79,7 @@ pub fn start<P: AsRef<Path>>(dir: P, ip: IpAddr, port: Option<u16>) -> crate::Re
}
async fn handler(uri: Uri, state: State<ServerState>) -> impl IntoResponse {
// Frontend files should not contain query parameters. This seems to be how vite handles it.
// Frontend files should not contain query parameters. This seems to be how Vite handles it.
let uri = uri.path();
let uri = if uri == "/" {
@@ -116,7 +116,7 @@ async fn ws_handler(ws: WebSocketUpgrade, state: State<ServerState>) -> Response
_ = ws.recv() => return,
fs_reload_event = rx.recv() => fs_reload_event.is_ok(),
} {
let msg = ws::Message::Text(r#"{"reload": true}"#.to_owned());
let msg = ws::Message::Text(r#"{"reload": true}"#.into());
if ws.send(msg).await.is_err() {
break;
}
@@ -138,7 +138,9 @@ fn inject_address(html_bytes: Vec<u8>, address: &SocketAddr) -> Vec<u8> {
}
}
let mut document = kuchiki::parse_html().one(String::from_utf8_lossy(&html_bytes).into_owned());
let mut document = kuchiki::parse_html()
.one(String::from_utf8_lossy(&html_bytes).into_owned())
.document_node;
with_html_head(&mut document, |head| {
let script = RELOAD_SCRIPT.replace("{{reload_url}}", &format!("ws://{address}/__tauri_cli"));
let script_el = NodeRef::new_element(QualName::new(None, ns!(html), "script".into()), None);
@@ -170,8 +172,12 @@ fn watch<F: Fn() + Send + 'static>(dir: PathBuf, handler: F) {
.expect("builtin server failed to watch dir");
loop {
if rx.recv().is_ok() {
handler();
if let Ok(Ok(event)) = rx.recv() {
if let Some(event) = event.first() {
if !event.kind.is_access() {
handler();
}
}
}
}
});

View File

@@ -39,6 +39,7 @@ pub fn walk_builder(path: &Path) -> WalkBuilder {
let mut builder = WalkBuilder::new(path);
builder.add_custom_ignore_filename(".taurignore");
builder.git_global(false);
builder.parents(false);
let _ = builder.add_ignore(default_gitignore);
builder
}
@@ -94,20 +95,36 @@ fn env_tauri_frontend_path() -> Option<PathBuf> {
pub fn resolve_tauri_dir() -> Option<PathBuf> {
let src_dir = env_tauri_app_path().or_else(|| current_dir().ok())?;
if src_dir.join(ConfigFormat::Json.into_file_name()).exists()
|| src_dir.join(ConfigFormat::Json5.into_file_name()).exists()
|| src_dir.join(ConfigFormat::Toml.into_file_name()).exists()
{
return Some(src_dir);
for standard_tauri_path in [src_dir.clone(), src_dir.join("src-tauri")] {
if standard_tauri_path
.join(ConfigFormat::Json.into_file_name())
.exists()
|| standard_tauri_path
.join(ConfigFormat::Json5.into_file_name())
.exists()
|| standard_tauri_path
.join(ConfigFormat::Toml.into_file_name())
.exists()
{
log::debug!(
"Found Tauri project inside {} on early lookup",
standard_tauri_path.display()
);
return Some(standard_tauri_path);
}
}
log::debug!("resolving Tauri directory from {}", src_dir.display());
lookup(&src_dir, |path| {
folder_has_configuration_file(Target::Linux, path) || is_configuration_file(Target::Linux, path)
})
.map(|p| {
if p.is_dir() {
log::debug!("Found Tauri project directory {}", p.display());
p
} else {
log::debug!("Found Tauri project configuration file {}", p.display());
p.parent().unwrap().to_path_buf()
}
})
@@ -142,6 +159,11 @@ pub fn resolve_frontend_dir() -> Option<PathBuf> {
return Some(frontend_dir);
}
log::debug!(
"resolving frontend directory from {}",
frontend_dir.display()
);
lookup(&frontend_dir, |path| {
if let Some(file_name) = path.file_name() {
file_name == OsStr::new("package.json")

View File

@@ -10,6 +10,8 @@ use std::{
path::{Path, PathBuf},
};
use crate::interface::rust::get_workspace_dir;
#[derive(Clone, Deserialize)]
pub struct CargoLockPackage {
pub name: String,
@@ -49,6 +51,18 @@ pub struct CargoManifest {
pub dependencies: HashMap<String, CargoManifestDependency>,
}
pub fn cargo_manifest_and_lock(tauri_dir: &Path) -> (Option<CargoManifest>, Option<CargoLock>) {
let manifest: Option<CargoManifest> = fs::read_to_string(tauri_dir.join("Cargo.toml"))
.ok()
.and_then(|manifest_contents| toml::from_str(&manifest_contents).ok());
let lock: Option<CargoLock> = get_workspace_dir()
.ok()
.and_then(|p| fs::read_to_string(p.join("Cargo.lock")).ok())
.and_then(|s| toml::from_str(&s).ok());
(manifest, lock)
}
#[derive(Default)]
pub struct CrateVersion {
pub version: Option<String>,
@@ -97,15 +111,43 @@ impl std::fmt::Display for CrateVersion {
}
}
// Reference: https://github.com/rust-lang/crates.io/blob/98c83c8231cbcd15d6b8f06d80a00ad462f71585/src/views.rs#L274
#[derive(serde::Deserialize)]
struct CrateMetadata {
/// The "default" version of this crate.
///
/// This version will be displayed by default on the crate's page.
pub default_version: Option<String>,
}
// Reference: https://github.com/rust-lang/crates.io/blob/98c83c8231cbcd15d6b8f06d80a00ad462f71585/src/controllers/krate/metadata.rs#L44
#[derive(serde::Deserialize)]
struct CrateIoGetResponse {
/// The crate metadata.
#[serde(rename = "crate")]
krate: CrateMetadata,
}
pub fn crate_latest_version(name: &str) -> Option<String> {
let url = format!("https://docs.rs/crate/{name}/");
match ureq::get(&url).call() {
Ok(response) => match (response.status(), response.header("location")) {
(302, Some(location)) => Some(location.replace(&url, "")),
_ => None,
},
Err(_) => None,
}
// Reference: https://github.com/rust-lang/crates.io/blob/98c83c8231cbcd15d6b8f06d80a00ad462f71585/src/controllers/krate/metadata.rs#L88
let url = format!("https://crates.io/api/v1/crates/{name}?include");
#[cfg(feature = "platform-certs")]
let mut response = {
let agent = ureq::Agent::config_builder()
.tls_config(
ureq::tls::TlsConfig::builder()
.root_certs(ureq::tls::RootCerts::PlatformVerifier)
.build(),
)
.build()
.new_agent();
agent.get(&url).call().ok()?
};
#[cfg(not(feature = "platform-certs"))]
let mut response = ureq::get(&url).call().ok()?;
let metadata: CrateIoGetResponse =
serde_json::from_reader(response.body_mut().as_reader()).unwrap();
metadata.krate.default_version
}
pub fn crate_version(

View File

@@ -1,4 +1,4 @@
// Copyright 2019-2024 Tauri Programme within The Commons Conservancy
// Copyright 2019-2025 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
@@ -6,11 +6,12 @@ use itertools::Itertools;
use json_patch::merge;
use serde_json::Value as JsonValue;
use tauri_utils::acl::REMOVE_UNUSED_COMMANDS_ENV_VAR;
pub use tauri_utils::{config::*, platform::Target};
use std::{
collections::HashMap,
env::{current_dir, set_current_dir, set_var, var_os},
env::{current_dir, set_current_dir, set_var},
ffi::OsStr,
process::exit,
sync::{Arc, Mutex, OnceLock},
@@ -21,6 +22,8 @@ pub const MERGE_CONFIG_EXTENSION_NAME: &str = "--config";
pub struct ConfigMetadata {
/// The current target.
target: Target,
original_identifier: Option<String>,
/// The actual configuration, merged with any extension.
inner: Config,
/// The config extensions (platform-specific config files or the config CLI argument).
@@ -38,15 +41,17 @@ impl std::ops::Deref for ConfigMetadata {
}
impl ConfigMetadata {
/// The original bundle identifier from the config file.
/// This does not take any extensions into account.
pub fn original_identifier(&self) -> Option<&str> {
self.original_identifier.as_deref()
}
/// Checks which config is overwriting the bundle identifier.
pub fn find_bundle_identifier_overwriter(&self) -> Option<String> {
for (ext, config) in &self.extensions {
if let Some(identifier) = config
.as_object()
.and_then(|config| config.get("tauri"))
.and_then(|tauri_config| tauri_config.as_object())
.and_then(|tauri_config| tauri_config.get("bundle"))
.and_then(|bundle_config| bundle_config.as_object())
.and_then(|bundle_config| bundle_config.get("identifier"))
.and_then(|id| id.as_str())
{
@@ -65,6 +70,10 @@ pub fn wix_settings(config: WixConfig) -> tauri_bundler::WixSettings {
tauri_bundler::WixSettings {
version: config.version,
upgrade_code: config.upgrade_code,
fips_compliant: std::env::var("TAURI_BUNDLER_WIX_FIPS_COMPLIANT")
.ok()
.map(|v| v == "true")
.unwrap_or(config.fips_compliant),
language: tauri_bundler::WixLanguage(match config.language {
WixLanguage::One(lang) => vec![(lang, Default::default())],
WixLanguage::List(languages) => languages
@@ -93,7 +102,6 @@ pub fn wix_settings(config: WixConfig) -> tauri_bundler::WixSettings {
enable_elevated_update_task: config.enable_elevated_update_task,
banner_path: config.banner_path,
dialog_image_path: config.dialog_image_path,
fips_compliant: var_os("TAURI_BUNDLER_WIX_FIPS_COMPLIANT").map_or(false, |v| v == "true"),
}
}
@@ -138,7 +146,7 @@ fn config_handle() -> &'static ConfigHandle {
/// Gets the static parsed config from `tauri.conf.json`.
fn get_internal(
merge_config: Option<&serde_json::Value>,
merge_configs: &[&serde_json::Value],
reload: bool,
target: Target,
) -> crate::Result<ConfigHandle> {
@@ -152,8 +160,14 @@ fn get_internal(
let config_file_name = config_path.file_name().unwrap().to_string_lossy();
let mut extensions = HashMap::new();
let original_identifier = config
.as_object()
.and_then(|config| config.get("identifier"))
.and_then(|id| id.as_str())
.map(ToString::to_string);
if let Some((platform_config, config_path)) =
tauri_utils::config::parse::read_platform(target, tauri_dir.to_path_buf())?
tauri_utils::config::parse::read_platform(target, tauri_dir)?
{
merge(&mut config, &platform_config);
extensions.insert(
@@ -162,12 +176,17 @@ fn get_internal(
);
}
if let Some(merge_config) = merge_config {
if !merge_configs.is_empty() {
let mut merge_config = serde_json::Value::Object(Default::default());
for conf in merge_configs {
merge_patches(&mut merge_config, conf);
}
let merge_config_str = serde_json::to_string(&merge_config).unwrap();
set_var("TAURI_CONFIG", merge_config_str);
merge(&mut config, merge_config);
extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config.clone());
};
merge(&mut config, &merge_config);
extensions.insert(MERGE_CONFIG_EXTENSION_NAME.into(), merge_config);
}
if config_path.extension() == Some(OsStr::new("json"))
|| config_path.extension() == Some(OsStr::new("json5"))
@@ -208,8 +227,13 @@ fn get_internal(
);
}
if config.build.remove_unused_commands {
std::env::set_var(REMOVE_UNUSED_COMMANDS_ENV_VAR, tauri_dir);
}
*config_handle().lock().unwrap() = Some(ConfigMetadata {
target,
original_identifier,
inner: config,
extensions,
});
@@ -217,35 +241,42 @@ fn get_internal(
Ok(config_handle().clone())
}
pub fn get(
target: Target,
merge_config: Option<&serde_json::Value>,
) -> crate::Result<ConfigHandle> {
get_internal(merge_config, false, target)
pub fn get(target: Target, merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
get_internal(merge_configs, false, target)
}
pub fn reload(merge_config: Option<&serde_json::Value>) -> crate::Result<ConfigHandle> {
pub fn reload(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
let target = config_handle()
.lock()
.unwrap()
.as_ref()
.map(|conf| conf.target);
if let Some(target) = target {
get_internal(merge_config, true, target)
get_internal(merge_configs, true, target)
} else {
Err(anyhow::anyhow!("config not loaded"))
}
}
/// merges the loaded config with the given value
pub fn merge_with(merge_config: &serde_json::Value) -> crate::Result<ConfigHandle> {
pub fn merge_with(merge_configs: &[&serde_json::Value]) -> crate::Result<ConfigHandle> {
let handle = config_handle();
if merge_configs.is_empty() {
return Ok(handle.clone());
}
if let Some(config_metadata) = &mut *handle.lock().unwrap() {
let merge_config_str = serde_json::to_string(merge_config).unwrap();
let mut merge_config = serde_json::Value::Object(Default::default());
for conf in merge_configs {
merge_patches(&mut merge_config, conf);
}
let merge_config_str = serde_json::to_string(&merge_config).unwrap();
set_var("TAURI_CONFIG", merge_config_str);
let mut value = serde_json::to_value(config_metadata.inner.clone())?;
merge(&mut value, merge_config);
merge(&mut value, &merge_config);
config_metadata.inner = serde_json::from_value(value)?;
Ok(handle.clone())
@@ -253,3 +284,87 @@ pub fn merge_with(merge_config: &serde_json::Value) -> crate::Result<ConfigHandl
Err(anyhow::anyhow!("config not loaded"))
}
}
/// Same as [`json_patch::merge`] but doesn't delete the key when the patch's value is `null`
fn merge_patches(doc: &mut serde_json::Value, patch: &serde_json::Value) {
use serde_json::{Map, Value};
if !patch.is_object() {
*doc = patch.clone();
return;
}
if !doc.is_object() {
*doc = Value::Object(Map::new());
}
let map = doc.as_object_mut().unwrap();
for (key, value) in patch.as_object().unwrap() {
merge_patches(map.entry(key.as_str()).or_insert(Value::Null), value);
}
}
#[cfg(test)]
mod tests {
#[test]
fn merge_patches() {
let mut json = serde_json::Value::Object(Default::default());
super::merge_patches(
&mut json,
&serde_json::json!({
"app": {
"withGlobalTauri": true,
"windows": []
},
"plugins": {
"test": "tauri"
},
"build": {
"devUrl": "http://localhost:8080"
}
}),
);
super::merge_patches(
&mut json,
&serde_json::json!({
"app": { "withGlobalTauri": null }
}),
);
super::merge_patches(
&mut json,
&serde_json::json!({
"app": { "windows": null }
}),
);
super::merge_patches(
&mut json,
&serde_json::json!({
"plugins": { "updater": {
"endpoints": ["https://tauri.app"]
} }
}),
);
assert_eq!(
json,
serde_json::json!({
"app": {
"withGlobalTauri": null,
"windows": null
},
"plugins": {
"test": "tauri",
"updater": {
"endpoints": ["https://tauri.app"]
}
},
"build": {
"devUrl": "http://localhost:8080"
}
})
)
}
}

View File

@@ -267,7 +267,7 @@ mod sys {
}
pub(super) fn error_contended(err: &Error) -> bool {
err.raw_os_error().map_or(false, |x| x == libc::EWOULDBLOCK)
err.raw_os_error() == Some(libc::EWOULDBLOCK)
}
pub(super) fn error_unsupported(err: &Error) -> bool {
@@ -327,15 +327,11 @@ mod sys {
}
pub(super) fn error_contended(err: &Error) -> bool {
err
.raw_os_error()
.map_or(false, |x| x == ERROR_LOCK_VIOLATION as i32)
err.raw_os_error() == Some(ERROR_LOCK_VIOLATION as i32)
}
pub(super) fn error_unsupported(err: &Error) -> bool {
err
.raw_os_error()
.map_or(false, |x| x == ERROR_INVALID_FUNCTION as i32)
err.raw_os_error() == Some(ERROR_INVALID_FUNCTION as i32)
}
pub(super) fn unlock(file: &File) -> Result<()> {

View File

@@ -97,7 +97,7 @@ pub fn run_hook(
.current_dir(cwd)
.envs(env)
.piped()
.with_context(|| format!("failed to run `{}` with `cmd /C`", script))?;
.with_context(|| format!("failed to run `{script}` with `cmd /C`"))?;
#[cfg(not(target_os = "windows"))]
let status = Command::new("sh")
.arg("-c")
@@ -119,3 +119,23 @@ pub fn run_hook(
Ok(())
}
#[cfg(target_os = "macos")]
pub fn strip_semver_prerelease_tag(version: &mut semver::Version) -> crate::Result<()> {
if !version.pre.is_empty() {
if let Some((_prerelease_tag, number)) = version.pre.as_str().to_string().split_once('.') {
version.pre = semver::Prerelease::EMPTY;
version.build = semver::BuildMetadata::new(&format!(
"{prefix}{number}",
prefix = if version.build.is_empty() {
"".to_string()
} else {
format!(".{}", version.build.as_str())
}
))
.with_context(|| format!("bundle version {number:?} prerelease is invalid"))?;
}
}
Ok(())
}

View File

@@ -3,9 +3,10 @@
// SPDX-License-Identifier: MIT
use anyhow::Context;
use serde::Deserialize;
use crate::helpers::cross_command;
use std::{fmt::Display, path::Path, process::Command};
use std::{collections::HashMap, fmt::Display, path::Path, process::Command};
pub fn manager_version(package_manager: &str) -> Option<String> {
cross_command(package_manager)
@@ -23,6 +24,17 @@ pub fn manager_version(package_manager: &str) -> Option<String> {
.unwrap_or_default()
}
fn detect_yarn_or_berry() -> PackageManager {
if manager_version("yarn")
.map(|v| v.chars().next().map(|c| c > '1').unwrap_or_default())
.unwrap_or(false)
{
PackageManager::YarnBerry
} else {
PackageManager::Yarn
}
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PackageManager {
Npm,
@@ -59,32 +71,38 @@ impl PackageManager {
.unwrap_or(Self::Npm)
}
/// Detects package manager from the `npm_config_user_agent` environment variable
fn from_environment_variable() -> Option<Self> {
let npm_config_user_agent = std::env::var("npm_config_user_agent").ok()?;
match npm_config_user_agent {
user_agent if user_agent.starts_with("pnpm/") => Some(Self::Pnpm),
user_agent if user_agent.starts_with("deno/") => Some(Self::Deno),
user_agent if user_agent.starts_with("bun/") => Some(Self::Bun),
user_agent if user_agent.starts_with("yarn/") => Some(detect_yarn_or_berry()),
user_agent if user_agent.starts_with("npm/") => Some(Self::Npm),
_ => None,
}
}
/// Detects all possible package managers from the given directory.
pub fn all_from_project<P: AsRef<Path>>(path: P) -> Vec<Self> {
if let Some(from_env) = Self::from_environment_variable() {
return vec![from_env];
}
let mut found = Vec::new();
if let Ok(entries) = std::fs::read_dir(path) {
for entry in entries.flatten() {
let path = entry.path();
let name = path.file_name().unwrap().to_string_lossy();
if name.as_ref() == "package-lock.json" {
found.push(PackageManager::Npm);
} else if name.as_ref() == "pnpm-lock.yaml" {
found.push(PackageManager::Pnpm);
} else if name.as_ref() == "yarn.lock" {
let yarn = if manager_version("yarn")
.map(|v| v.chars().next().map(|c| c > '1').unwrap_or_default())
.unwrap_or(false)
{
PackageManager::YarnBerry
} else {
PackageManager::Yarn
};
found.push(yarn);
} else if name.as_ref() == "bun.lockb" {
found.push(PackageManager::Bun);
} else if name.as_ref() == "deno.lock" {
found.push(PackageManager::Deno);
match name.as_ref() {
"package-lock.json" => found.push(PackageManager::Npm),
"pnpm-lock.yaml" => found.push(PackageManager::Pnpm),
"yarn.lock" => found.push(detect_yarn_or_berry()),
"bun.lock" | "bun.lockb" => found.push(PackageManager::Bun),
"deno.lock" => found.push(PackageManager::Deno),
_ => (),
}
}
}
@@ -180,6 +198,7 @@ impl PackageManager {
Ok(())
}
// TODO: Use `current_package_versions` as much as possible for better speed
pub fn current_package_version<P: AsRef<Path>>(
&self,
name: &str,
@@ -237,4 +256,157 @@ impl PackageManager {
Ok(None)
}
}
pub fn current_package_versions(
&self,
packages: &[String],
frontend_dir: &Path,
) -> crate::Result<HashMap<String, semver::Version>> {
let output = match self {
PackageManager::Yarn => return yarn_package_versions(packages, frontend_dir),
PackageManager::YarnBerry => return yarn_berry_package_versions(packages, frontend_dir),
PackageManager::Pnpm => cross_command("pnpm")
.arg("list")
.args(packages)
.args(["--json", "--depth", "0"])
.current_dir(frontend_dir)
.output()?,
// Bun and Deno don't support `list` command
PackageManager::Npm | PackageManager::Bun | PackageManager::Deno => cross_command("npm")
.arg("list")
.args(packages)
.args(["--json", "--depth", "0"])
.current_dir(frontend_dir)
.output()?,
};
let mut versions = HashMap::new();
let stdout = String::from_utf8_lossy(&output.stdout);
if !output.status.success() {
return Ok(versions);
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ListOutput {
#[serde(default)]
dependencies: HashMap<String, ListDependency>,
#[serde(default)]
dev_dependencies: HashMap<String, ListDependency>,
}
#[derive(Deserialize)]
struct ListDependency {
version: String,
}
let json: ListOutput = serde_json::from_str(&stdout)?;
for (package, dependency) in json.dependencies.into_iter().chain(json.dev_dependencies) {
let version = dependency.version;
if let Ok(version) = semver::Version::parse(&version) {
versions.insert(package, version);
} else {
log::error!("Failed to parse version `{version}` for NPM package `{package}`");
}
}
Ok(versions)
}
}
fn yarn_package_versions(
packages: &[String],
frontend_dir: &Path,
) -> crate::Result<HashMap<String, semver::Version>> {
let output = cross_command("yarn")
.arg("list")
.args(packages)
.args(["--json", "--depth", "0"])
.current_dir(frontend_dir)
.output()?;
let mut versions = HashMap::new();
let stdout = String::from_utf8_lossy(&output.stdout);
if !output.status.success() {
return Ok(versions);
}
#[derive(Deserialize)]
struct YarnListOutput {
data: YarnListOutputData,
}
#[derive(Deserialize)]
struct YarnListOutputData {
trees: Vec<YarnListOutputDataTree>,
}
#[derive(Deserialize)]
struct YarnListOutputDataTree {
name: String,
}
for line in stdout.lines() {
if let Ok(tree) = serde_json::from_str::<YarnListOutput>(line) {
for tree in tree.data.trees {
let Some((name, version)) = tree.name.rsplit_once('@') else {
continue;
};
if let Ok(version) = semver::Version::parse(version) {
versions.insert(name.to_owned(), version);
} else {
log::error!("Failed to parse version `{version}` for NPM package `{name}`");
}
}
return Ok(versions);
}
}
Ok(versions)
}
fn yarn_berry_package_versions(
packages: &[String],
frontend_dir: &Path,
) -> crate::Result<HashMap<String, semver::Version>> {
let output = cross_command("yarn")
.args(["info", "--json"])
.current_dir(frontend_dir)
.output()?;
let mut versions = HashMap::new();
let stdout = String::from_utf8_lossy(&output.stdout);
if !output.status.success() {
return Ok(versions);
}
#[derive(Deserialize)]
struct YarnBerryInfoOutput {
value: String,
children: YarnBerryInfoOutputChildren,
}
#[derive(Deserialize)]
#[serde(rename_all = "PascalCase")]
struct YarnBerryInfoOutputChildren {
version: String,
}
for line in stdout.lines() {
if let Ok(info) = serde_json::from_str::<YarnBerryInfoOutput>(line) {
let Some((name, _)) = info.value.rsplit_once('@') else {
continue;
};
if !packages.iter().any(|package| package == name) {
continue;
}
let version = info.children.version;
if let Ok(version) = semver::Version::parse(&version) {
versions.insert(name.to_owned(), version);
} else {
log::error!("Failed to parse version `{version}` for NPM package `{name}`");
}
}
}
Ok(versions)
}

View File

@@ -52,7 +52,7 @@ pub fn parse<P: AsRef<Path>>(path: P) -> crate::Result<Pbxproj> {
State::XCBuildConfigurationObject { id } => {
if line.contains("buildSettings") {
state = State::XCBuildConfigurationObjectBuildSettings { id: id.clone() };
} else if split_at_identation(line).map_or(false, |(_ident, token)| token == "};") {
} else if split_at_identation(line).is_some_and(|(_ident, token)| token == "};") {
state = State::XCBuildConfiguration;
}
}
@@ -122,7 +122,7 @@ pub fn parse<P: AsRef<Path>>(path: P) -> crate::Result<Pbxproj> {
State::XCConfigurationListObject { id } => {
if line.contains("buildConfigurations") {
state = State::XCConfigurationListObjectBuildConfigurations { id: id.clone() };
} else if split_at_identation(line).map_or(false, |(_ident, token)| token == "};") {
} else if split_at_identation(line).is_some_and(|(_ident, token)| token == "};") {
state = State::XCConfigurationList;
}
}

View File

@@ -38,6 +38,7 @@ pub fn known_plugins() -> HashMap<&'static str, PluginMetadata> {
// uses builder pattern
for p in [
"autostart",
"global-shortcut",
"localhost",
"log",
@@ -69,6 +70,8 @@ pub fn known_plugins() -> HashMap<&'static str, PluginMetadata> {
"shell",
"upload",
"websocket",
"opener",
"clipboard-manager",
] {
plugins.entry(p).or_default();
}

Some files were not shown because too many files have changed in this diff Show More