diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..8d10b1c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,69 @@ +# Changelog + +All notable changes to this project are documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.1.0] - 2026-08-24 + +### Added + +- **Reactive Watch API** — subscribe to a kind of device information and receive + a callback whenever the value changes, instead of polling a getter yourself. + The current value is delivered immediately, then on every change. + - `watchBattery`, `watchNetwork`, `watchStorage`, `watchDisplay`, and + `watchDevice`, each returning a `Promise`. + - `WatchOptions` (`intervalMs`) and `UnwatchFn` types, exported for consumers. + - `start_watching` / `stop_watching` commands, with matching + `allow-start-watching` and `allow-stop-watching` permissions (included in + `device-info:default`). +- **Native, event-driven monitors on macOS** — battery via IOKit power + notifications, display via Core Graphics reconfiguration callbacks, and + network via SystemConfiguration reachability. The CPU stays idle between + changes and updates arrive the instant the OS reports them. +- **Change-detecting polling fallback** for kinds/platforms without a native + event source (`storage` and `device` everywhere; all kinds off macOS). Events + are emitted only when the value actually changes. +- Reference-counted monitors: subscribers to the same kind share a single + monitor that starts on the first subscriber and is torn down on the last. +- Documentation for the watch API (API reference page, guide section, examples) + and unit tests covering the monitor lifecycle for every kind. + +### Performance + +- Per-kind polling defaults and floors so expensive getters are not polled + aggressively: `device` defaults to 60000 ms (min 10000 ms), `storage` to + 10000 ms (min 1000 ms), others to 2000 ms (min 250 ms). Notably, `device` + (which shells out to `system_profiler` on macOS and rarely changes) is no + longer read every couple of seconds. +- The poller now sleeps for the full interval on a condition variable and wakes + immediately on stop, instead of busy-waking every 100 ms — letting the CPU + idle and cooperating with power-saving. +- Change events are emitted by reference, avoiding a deep clone of each snapshot. + +### Fixed + +- Removed a run-loop teardown race on macOS that could hang `stop_watching` + indefinitely when a watcher was stopped just after starting; stop is now + signalled through the run loop itself and is race-free. +- `stop_watching` no longer holds the shared watcher lock while tearing down a + monitor, so a slow teardown can't block subscribe/unsubscribe for other kinds. +- Contained panics inside the macOS OS callbacks so they can no longer unwind + across the C ABI boundary and abort the process. +- The example app surfaces watcher start failures instead of leaving an + unhandled promise rejection. + +## [1.0.1] + +- Documentation updates, crates.io metadata, and a Tests CI badge. + +## [1.0.0] + +- Initial release: `getDeviceInfo`, `getBatteryInfo`, `getNetworkInfo`, + `getStorageInfo`, and `getDisplayInfo` across Windows, macOS, Linux, iOS, and + Android. + +[1.1.0]: https://github.com/edisdev/tauri-plugin-device-info/releases/tag/v1.1.0 +[1.0.1]: https://github.com/edisdev/tauri-plugin-device-info/releases/tag/v1.0.1 +[1.0.0]: https://github.com/edisdev/tauri-plugin-device-info/releases/tag/v1.0.0 diff --git a/Cargo.toml b/Cargo.toml index e56b20a..f17041e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tauri-plugin-device-info" -version = "1.0.1" +version = "1.1.0" authors = ["edisdev "] description = "A Tauri plugin to access device information." license = "MIT" @@ -38,3 +38,10 @@ battery = "0.7.8" [build-dependencies] tauri-plugin = { version = "2.5.2", features = ["build"] } + +# Tauri's `test` feature (the mock runtime) fails to load on Windows CI with +# STATUS_ENTRYPOINT_NOT_FOUND (0xc0000139), so enable it only off Windows. The +# mock-based watcher tests are gated to match; the pure-logic tests still run +# on every platform. +[target.'cfg(not(target_os = "windows"))'.dev-dependencies] +tauri = { version = "2.7.0", features = ["test"] } diff --git a/README.md b/README.md index c63262f..eebe4d5 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ A comprehensive Tauri plugin to access device information including Battery, Net - 💾 **Storage** — total/free space and storage type - 🖥️ **Display** — resolution, scale factor, and refresh rate - 🆔 **Device** — manufacturer, model, serial, and device name +- 🔔 **Reactive** — `watch*` APIs push updates on change (native event-driven on macOS, polling fallback elsewhere) - 📱 **Truly cross-platform** — Windows, macOS, Linux, iOS, and Android - 🛡️ **Type-safe** — full TypeScript types and granular Tauri permissions - ✅ **Tested** — unit-tested core with CI across all desktop platforms @@ -193,6 +194,49 @@ console.log(display); } ``` +### Reactive Watch API + +Subscribe to a kind and get a callback whenever the value changes, instead of +polling a getter yourself. The current value is delivered immediately, then on +every change. On macOS these are native and event-driven (IOKit / Core Graphics +/ SystemConfiguration); elsewhere they fall back to change-detecting polling. + +```typescript +import { + watchBattery, + watchNetwork, + watchStorage, + watchDisplay, + watchDevice, +} from "tauri-plugin-device-info-api"; +import type { UnwatchFn } from "tauri-plugin-device-info-api"; + +// Called immediately with the current value, then on every change. +const unwatch = await watchBattery((battery) => { + console.log(`Battery: ${battery.level}% (charging: ${battery.isCharging})`); +}); + +// Stop watching and remove the listener when you're done. +await unwatch(); +``` + +Cleaning up several watchers at once (e.g. on component teardown): + +```typescript +const unwatchers: UnwatchFn[] = []; +unwatchers.push(await watchNetwork((info) => console.log(info.networkType))); +unwatchers.push(await watchDisplay((info) => console.log(info.width, info.height))); + +// Later: +await Promise.all(unwatchers.map((unwatch) => unwatch())); +``` + +`watch*` accepts an optional `{ intervalMs }` that applies **only to polled +kinds** (native kinds ignore it). Defaults and minimums are per kind: `device` +defaults to 60000 ms (floored at 10000 ms), `storage` to 10000 ms (floored at +1000 ms), and others to 2000 ms (floored at 250 ms). Subscribers to the same +kind share one monitor, so only the first subscriber's interval takes effect. + ## API Reference ### getDeviceInfo() @@ -249,6 +293,26 @@ Returns display/screen information. | `scaleFactor` | `number?` | Display scale factor (e.g., 2.0 for Retina) | | `refreshRate` | `number?` | Screen refresh rate in Hz | +### watch\*(callback, options?) + +Subscribes to a kind and invokes `callback` with the current value immediately, +then on every change. Returns a `Promise`; call the returned function +to stop watching and remove the listener. + +| Function | Callback payload | +| ----------------- | -------------------- | +| `watchDevice()` | `DeviceInfoResponse` | +| `watchBattery()` | `BatteryInfo` | +| `watchNetwork()` | `NetworkInfo` | +| `watchStorage()` | `StorageInfo` | +| `watchDisplay()` | `DisplayInfo` | + +**Options** + +| Field | Type | Description | +| ------------ | --------- | -------------------------------------------------------------------------------------------- | +| `intervalMs` | `number?` | Polling interval for polled kinds only (native kinds ignore it). Per-kind defaults/minimums. | + ## TypeScript Types All types are exported and can be imported: @@ -260,6 +324,8 @@ import type { NetworkInfo, StorageInfo, DisplayInfo, + WatchOptions, + UnwatchFn, } from "tauri-plugin-device-info-api"; ``` @@ -289,6 +355,8 @@ Add the required permissions in your `capabilities` configuration. | `device-info:allow-get-network-info` | Allows getting network details | | `device-info:allow-get-storage-info` | Allows getting storage info | | `device-info:allow-get-display-info` | Allows getting display info | +| `device-info:allow-start-watching` | Allows starting a reactive watch | +| `device-info:allow-stop-watching` | Allows stopping a reactive watch | ### Individual Permissions Example @@ -352,6 +420,10 @@ cargo clippy -- -D warnings yarn tsc --noEmit ``` +## Changelog + +See [CHANGELOG.md](CHANGELOG.md) for the release history and notable changes. + ## Contributing Contributions are welcome! Please read the [Contributing Guide](CONTRIBUTING.md) diff --git a/build.rs b/build.rs index c49362a..1f0c7d1 100644 --- a/build.rs +++ b/build.rs @@ -4,6 +4,8 @@ const COMMANDS: &[&str] = &[ "get_network_info", "get_storage_info", "get_display_info", + "start_watching", + "stop_watching", ]; fn main() { diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 8268c84..a359e03 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -45,7 +45,8 @@ export default defineConfig({ { text: 'Battery Info', link: '/api/battery-info' }, { text: 'Network Info', link: '/api/network-info' }, { text: 'Storage Info', link: '/api/storage-info' }, - { text: 'Display Info', link: '/api/display-info' } + { text: 'Display Info', link: '/api/display-info' }, + { text: 'Reactive Watch', link: '/api/watch' } ] }, { diff --git a/docs/api/index.md b/docs/api/index.md index ad5e4d6..ea48eb9 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -1,6 +1,7 @@ # API Reference -This plugin provides 5 main functions to access device information. +This plugin provides 5 getters to read device information, plus a +[reactive watch API](/api/watch) to subscribe to changes. ## Functions Overview @@ -11,6 +12,7 @@ This plugin provides 5 main functions to access device information. | [`getNetworkInfo()`](/api/network-info) | Network connection details | | [`getStorageInfo()`](/api/storage-info) | Storage capacity information | | [`getDisplayInfo()`](/api/display-info) | Display properties and capabilities | +| [`watch*()`](/api/watch) | Subscribe to changes for any of the above kinds | ## Quick Reference @@ -20,7 +22,14 @@ import { getBatteryInfo, // → BatteryInfo getNetworkInfo, // → NetworkInfo getStorageInfo, // → StorageInfo - getDisplayInfo // → DisplayInfo + getDisplayInfo, // → DisplayInfo + + // Reactive watch API → Promise + watchDevice, + watchBattery, + watchNetwork, + watchStorage, + watchDisplay } from 'tauri-plugin-device-info-api'; ``` @@ -34,7 +43,9 @@ import type { BatteryInfo, NetworkInfo, StorageInfo, - DisplayInfo + DisplayInfo, + WatchOptions, + UnwatchFn } from 'tauri-plugin-device-info-api'; ``` diff --git a/docs/api/watch.md b/docs/api/watch.md new file mode 100644 index 0000000..0ad4394 --- /dev/null +++ b/docs/api/watch.md @@ -0,0 +1,154 @@ +# Reactive Watch API + +Instead of calling a getter on a timer, you can **subscribe** to a kind of +device information and receive a callback whenever the value changes. + +Each `watch*` function delivers the **current value immediately**, then invokes +your callback again on every subsequent change. It returns an async `unwatch` +function that stops watching and removes the listener. + +## Functions + +| Function | Delivers | Watches for | +|----------|----------|-------------| +| `watchBattery()` | `BatteryInfo` | Charge level, charging state, health | +| `watchNetwork()` | `NetworkInfo` | Connectivity changes (Wi-Fi ↔ offline, IP, MAC) | +| `watchStorage()` | `StorageInfo` | Total / free space | +| `watchDisplay()` | `DisplayInfo` | Resolution, scale, refresh rate (e.g. plugging in a monitor) | +| `watchDevice()` | `DeviceInfoResponse` | Device identity fields (rarely changes) | + +## Signatures + +```typescript +function watchBattery(callback: (info: BatteryInfo) => void, options?: WatchOptions): Promise +function watchNetwork(callback: (info: NetworkInfo) => void, options?: WatchOptions): Promise +function watchStorage(callback: (info: StorageInfo) => void, options?: WatchOptions): Promise +function watchDisplay(callback: (info: DisplayInfo) => void, options?: WatchOptions): Promise +function watchDevice(callback: (info: DeviceInfoResponse) => void, options?: WatchOptions): Promise +``` + +## Options & return type + +```typescript +interface WatchOptions { + /** + * Polling interval in milliseconds, used only for kinds that fall back to + * polling (native event-driven kinds ignore it). Only the first subscriber + * for a given kind sets the interval. + */ + intervalMs?: number; +} + +/** Stops a watcher and removes its listener. Returned by every `watch*` function. */ +type UnwatchFn = () => Promise; +``` + +## Basic usage + +```typescript +import { watchBattery } from 'tauri-plugin-device-info-api'; + +// Called immediately with the current value, then on every change. +const unwatch = await watchBattery((battery) => { + console.log(`Battery: ${battery.level}% (charging: ${battery.isCharging})`); +}); + +// Later, when you no longer need updates: +await unwatch(); +``` + +### Cleaning up multiple watchers + +Always stop watchers when the component/view is torn down, otherwise the +backend monitor stays alive. + +```typescript +import { watchBattery, watchNetwork, watchDisplay } from 'tauri-plugin-device-info-api'; +import type { UnwatchFn } from 'tauri-plugin-device-info-api'; + +const unwatchers: UnwatchFn[] = []; + +unwatchers.push(await watchBattery((info) => { /* ... */ })); +unwatchers.push(await watchNetwork((info) => { /* ... */ })); +unwatchers.push(await watchDisplay((info) => { /* ... */ })); + +// On teardown: +await Promise.all(unwatchers.map((unwatch) => unwatch())); +``` + +## How updates are detected + +The public API and the emitted events are identical across platforms, but the +engine behind each kind differs: + +- Where the OS exposes a **native, event-driven** source, updates are delivered + the instant the OS reports a change and the CPU stays idle in between. +- Otherwise a **change-detecting poller** reads the value on an interval and + emits only when it actually changed. + +| Kind | macOS | Windows / Linux | +|------|-------|-----------------| +| `battery` | Native — IOKit power notifications | Polled | +| `display` | Native — Core Graphics reconfiguration callback | Polled | +| `network` | Native — SystemConfiguration reachability | Polled | +| `storage` | Polled (no OS change event) | Polled | +| `device` | Polled (rarely changes) | Polled | + +### Polling intervals + +`intervalMs` only applies to polled kinds. Defaults and minimums are **per +kind**, because some getters are expensive and some values rarely change: + +| Kind | Default | Minimum | +|------|---------|---------| +| `device` | 60000 ms | 10000 ms | +| `storage` | 10000 ms | 1000 ms | +| others (when polled) | 2000 ms | 250 ms | + +```typescript +// Poll storage a little more eagerly (still floored at 1000 ms): +const unwatch = await watchStorage((info) => console.log(info.freeSpace), { + intervalMs: 2000, +}); +``` + +::: tip Reference counting +Subscribers to the same kind share a single monitor. It starts on the first +subscriber and is torn down once the last one calls `unwatch()`. Only the first +subscriber's `intervalMs` takes effect. +::: + +## Permissions + +The watch API requires the `start-watching` and `stop-watching` commands. +`device-info:default` already includes them; to grant them individually: + +```json +{ + "permissions": [ + "device-info:allow-start-watching", + "device-info:allow-stop-watching" + ] +} +``` + +## Example output + +`watchBattery` delivers the same shape as `getBatteryInfo`: + +```json +{ + "level": 85, + "isCharging": true, + "health": "Good" +} +``` + +## Notes + +- The current value is always delivered once, immediately, so you don't need a + separate `getBatteryInfo()` call to seed initial state. +- `unwatch()` is async — `await` it if you need the backend monitor fully torn + down before continuing. +- On a kind with a native source (e.g. `battery` on macOS), `intervalMs` is + ignored. diff --git a/docs/examples.md b/docs/examples.md index 58982f6..b28cb90 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -125,32 +125,30 @@ function formatBytes(bytes: number): string { {/if} ``` -## Polling for Updates +## Reactive Updates -For real-time battery monitoring: +Prefer the [`watch*` API](/api/watch) over manual polling — it pushes updates on +change (native event-driven on macOS, polling fallback elsewhere) and delivers +the current value immediately. ```typescript -import { getBatteryInfo } from 'tauri-plugin-device-info-api'; +import { watchBattery } from 'tauri-plugin-device-info-api'; -function startBatteryMonitor(callback: (level: number) => void) { - const interval = setInterval(async () => { - const battery = await getBatteryInfo(); - if (battery.level !== null) { - callback(battery.level); - } - }, 30000); // Update every 30 seconds - - return () => clearInterval(interval); -} - -// Usage -const stopMonitor = startBatteryMonitor((level) => { - console.log(`Battery level: ${level}%`); +// Called immediately with the current value, then on every change. +const stopMonitor = await watchBattery((battery) => { + console.log(`Battery level: ${battery.level}%`); }); -// Later: stopMonitor(); +// Later, when you no longer need updates: +await stopMonitor(); ``` +::: tip +Only reach for a manual `setInterval` + `getBatteryInfo()` loop if you need a +fixed cadence regardless of change. For "notify me when it changes", `watch*` is +both simpler and cheaper. +::: + ## Error Handling ```typescript diff --git a/docs/getting-started.md b/docs/getting-started.md index b9d072c..f3b33a6 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -56,6 +56,8 @@ Or add individual permissions: - `device-info:allow-get-network-info` - `device-info:allow-get-storage-info` - `device-info:allow-get-display-info` +- `device-info:allow-start-watching` +- `device-info:allow-stop-watching` ## Basic Usage @@ -96,6 +98,26 @@ async function loadDeviceInfo() { } ``` +## Reactive Updates + +Instead of calling a getter on a timer, subscribe to a kind and get a callback +whenever the value changes. The current value is delivered immediately, then on +every change. On macOS these are native and event-driven; elsewhere they fall +back to change-detecting polling. + +```typescript +import { watchBattery } from "tauri-plugin-device-info-api"; + +const unwatch = await watchBattery((battery) => { + console.log(`Battery: ${battery.level}% (charging: ${battery.isCharging})`); +}); + +// Stop watching when you're done (e.g. on component teardown): +await unwatch(); +``` + +See the [Reactive Watch API](/api/watch) for all `watch*` functions and options. + ## TypeScript Types All types are exported and can be imported: @@ -107,6 +129,8 @@ import type { NetworkInfo, StorageInfo, DisplayInfo, + WatchOptions, + UnwatchFn, } from "tauri-plugin-device-info-api"; ``` diff --git a/docs/index.md b/docs/index.md index 89221a1..7f2d504 100644 --- a/docs/index.md +++ b/docs/index.md @@ -29,6 +29,9 @@ features: - icon: 🖥️ title: Display Info details: Resolution, scale factor, and refresh rate + - icon: 🔔 + title: Reactive Watch + details: Subscribe to changes — native event-driven on macOS, polling fallback elsewhere - icon: 🌍 title: Cross-platform details: Works on Windows, macOS, Linux, iOS, and Android @@ -77,3 +80,13 @@ console.log(`Battery: ${battery.level}%`); const network = await getNetworkInfo(); console.log(`IP: ${network.ipAddress}`); ``` + +Prefer push over polling? Subscribe to changes with the +[reactive watch API](/api/watch): + +```typescript +import { watchBattery } from 'tauri-plugin-device-info-api'; + +const unwatch = await watchBattery((b) => console.log(`Battery: ${b.level}%`)); +// await unwatch(); // stop when done +``` diff --git a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json index 099b57f..899e8e9 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json +++ b/examples/tauri-app/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"device-info":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-get-device-info","allow-get-battery-info","allow-get-network-info","allow-get-storage-info","allow-get-display-info"]},"permissions":{"allow-get-battery-info":{"identifier":"allow-get-battery-info","description":"Enables the get_battery_info command without any pre-configured scope.","commands":{"allow":["get_battery_info"],"deny":[]}},"allow-get-device-info":{"identifier":"allow-get-device-info","description":"Enables the get_device_info command without any pre-configured scope.","commands":{"allow":["get_device_info"],"deny":[]}},"allow-get-display-info":{"identifier":"allow-get-display-info","description":"Enables the get_display_info command without any pre-configured scope.","commands":{"allow":["get_display_info"],"deny":[]}},"allow-get-network-info":{"identifier":"allow-get-network-info","description":"Enables the get_network_info command without any pre-configured scope.","commands":{"allow":["get_network_info"],"deny":[]}},"allow-get-storage-info":{"identifier":"allow-get-storage-info","description":"Enables the get_storage_info command without any pre-configured scope.","commands":{"allow":["get_storage_info"],"deny":[]}},"deny-get-battery-info":{"identifier":"deny-get-battery-info","description":"Denies the get_battery_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_battery_info"]}},"deny-get-device-info":{"identifier":"deny-get-device-info","description":"Denies the get_device_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_device_info"]}},"deny-get-display-info":{"identifier":"deny-get-display-info","description":"Denies the get_display_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_display_info"]}},"deny-get-network-info":{"identifier":"deny-get-network-info","description":"Denies the get_network_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_network_info"]}},"deny-get-storage-info":{"identifier":"deny-get-storage-info","description":"Denies the get_storage_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_storage_info"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"core":{"default_permission":{"identifier":"default","description":"Default core plugins set.","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier","allow-bundle-type","allow-register-listener","allow-remove-listener","allow-supports-multiple-windows"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-bundle-type":{"identifier":"allow-bundle-type","description":"Enables the bundle_type command without any pre-configured scope.","commands":{"allow":["bundle_type"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-register-listener":{"identifier":"allow-register-listener","description":"Enables the register_listener command without any pre-configured scope.","commands":{"allow":["register_listener"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-remove-listener":{"identifier":"allow-remove-listener","description":"Enables the remove_listener command without any pre-configured scope.","commands":{"allow":["remove_listener"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-set-dock-visibility":{"identifier":"allow-set-dock-visibility","description":"Enables the set_dock_visibility command without any pre-configured scope.","commands":{"allow":["set_dock_visibility"],"deny":[]}},"allow-supports-multiple-windows":{"identifier":"allow-supports-multiple-windows","description":"Enables the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":["supports_multiple_windows"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-bundle-type":{"identifier":"deny-bundle-type","description":"Denies the bundle_type command without any pre-configured scope.","commands":{"allow":[],"deny":["bundle_type"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-register-listener":{"identifier":"deny-register-listener","description":"Denies the register_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["register_listener"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-remove-listener":{"identifier":"deny-remove-listener","description":"Denies the remove_listener command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_listener"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-set-dock-visibility":{"identifier":"deny-set-dock-visibility","description":"Denies the set_dock_visibility command without any pre-configured scope.","commands":{"allow":[],"deny":["set_dock_visibility"]}},"deny-supports-multiple-windows":{"identifier":"deny-supports-multiple-windows","description":"Denies the supports_multiple_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["supports_multiple_windows"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin, which enables all commands.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-icon-with-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-icon-with-as-template":{"identifier":"allow-set-icon-with-as-template","description":"Enables the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_with_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-icon-with-as-template":{"identifier":"deny-set-icon-with-as-template","description":"Denies the set_icon_with_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_with_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-auto-resize":{"identifier":"allow-set-webview-auto-resize","description":"Enables the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":["set_webview_auto_resize"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-auto-resize":{"identifier":"deny-set-webview-auto-resize","description":"Denies the set_webview_auto_resize command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_auto_resize"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-activity-name","allow-scene-identifier","allow-internal-toggle-maximize"]},"permissions":{"allow-activity-name":{"identifier":"allow-activity-name","description":"Enables the activity_name command without any pre-configured scope.","commands":{"allow":["activity_name"],"deny":[]}},"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-scene-identifier":{"identifier":"allow-scene-identifier","description":"Enables the scene_identifier command without any pre-configured scope.","commands":{"allow":["scene_identifier"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-focusable":{"identifier":"allow-set-focusable","description":"Enables the set_focusable command without any pre-configured scope.","commands":{"allow":["set_focusable"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-simple-fullscreen":{"identifier":"allow-set-simple-fullscreen","description":"Enables the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":["set_simple_fullscreen"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-activity-name":{"identifier":"deny-activity-name","description":"Denies the activity_name command without any pre-configured scope.","commands":{"allow":[],"deny":["activity_name"]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-scene-identifier":{"identifier":"deny-scene-identifier","description":"Denies the scene_identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["scene_identifier"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-focusable":{"identifier":"deny-set-focusable","description":"Denies the set_focusable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focusable"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-simple-fullscreen":{"identifier":"deny-set-simple-fullscreen","description":"Denies the set_simple_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_simple_fullscreen"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"device-info":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-get-device-info","allow-get-battery-info","allow-get-network-info","allow-get-storage-info","allow-get-display-info","allow-start-watching","allow-stop-watching"]},"permissions":{"allow-get-battery-info":{"identifier":"allow-get-battery-info","description":"Enables the get_battery_info command without any pre-configured scope.","commands":{"allow":["get_battery_info"],"deny":[]}},"allow-get-device-info":{"identifier":"allow-get-device-info","description":"Enables the get_device_info command without any pre-configured scope.","commands":{"allow":["get_device_info"],"deny":[]}},"allow-get-display-info":{"identifier":"allow-get-display-info","description":"Enables the get_display_info command without any pre-configured scope.","commands":{"allow":["get_display_info"],"deny":[]}},"allow-get-network-info":{"identifier":"allow-get-network-info","description":"Enables the get_network_info command without any pre-configured scope.","commands":{"allow":["get_network_info"],"deny":[]}},"allow-get-storage-info":{"identifier":"allow-get-storage-info","description":"Enables the get_storage_info command without any pre-configured scope.","commands":{"allow":["get_storage_info"],"deny":[]}},"allow-start-watching":{"identifier":"allow-start-watching","description":"Enables the start_watching command without any pre-configured scope.","commands":{"allow":["start_watching"],"deny":[]}},"allow-stop-watching":{"identifier":"allow-stop-watching","description":"Enables the stop_watching command without any pre-configured scope.","commands":{"allow":["stop_watching"],"deny":[]}},"deny-get-battery-info":{"identifier":"deny-get-battery-info","description":"Denies the get_battery_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_battery_info"]}},"deny-get-device-info":{"identifier":"deny-get-device-info","description":"Denies the get_device_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_device_info"]}},"deny-get-display-info":{"identifier":"deny-get-display-info","description":"Denies the get_display_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_display_info"]}},"deny-get-network-info":{"identifier":"deny-get-network-info","description":"Denies the get_network_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_network_info"]}},"deny-get-storage-info":{"identifier":"deny-get-storage-info","description":"Denies the get_storage_info command without any pre-configured scope.","commands":{"allow":[],"deny":["get_storage_info"]}},"deny-start-watching":{"identifier":"deny-start-watching","description":"Denies the start_watching command without any pre-configured scope.","commands":{"allow":[],"deny":["start_watching"]}},"deny-stop-watching":{"identifier":"deny-stop-watching","description":"Denies the stop_watching command without any pre-configured scope.","commands":{"allow":[],"deny":["stop_watching"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json b/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json index 37fe584..fa7587d 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json +++ b/examples/tauri-app/src-tauri/gen/schemas/desktop-schema.json @@ -183,10 +183,10 @@ "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" }, { - "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`", "type": "string", "const": "core:app:default", - "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`" }, { "description": "Enables the app_hide command without any pre-configured scope.", @@ -260,6 +260,12 @@ "const": "core:app:allow-set-dock-visibility", "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." }, + { + "description": "Enables the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-supports-multiple-windows", + "markdownDescription": "Enables the supports_multiple_windows command without any pre-configured scope." + }, { "description": "Enables the tauri_version command without any pre-configured scope.", "type": "string", @@ -344,6 +350,12 @@ "const": "core:app:deny-set-dock-visibility", "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." }, + { + "description": "Denies the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-supports-multiple-windows", + "markdownDescription": "Denies the supports_multiple_windows command without any pre-configured scope." + }, { "description": "Denies the tauri_version command without any pre-configured scope.", "type": "string", @@ -867,10 +879,10 @@ "markdownDescription": "Denies the close command without any pre-configured scope." }, { - "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`", + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`", "type": "string", "const": "core:tray:default", - "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`" + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`" }, { "description": "Enables the get_by_id command without any pre-configured scope.", @@ -902,6 +914,12 @@ "const": "core:tray:allow-set-icon-as-template", "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." }, + { + "description": "Enables the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-with-as-template", + "markdownDescription": "Enables the set_icon_with_as_template command without any pre-configured scope." + }, { "description": "Enables the set_menu command without any pre-configured scope.", "type": "string", @@ -968,6 +986,12 @@ "const": "core:tray:deny-set-icon-as-template", "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." }, + { + "description": "Denies the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-with-as-template", + "markdownDescription": "Denies the set_icon_with_as_template command without any pre-configured scope." + }, { "description": "Denies the set_menu command without any pre-configured scope.", "type": "string", @@ -1227,10 +1251,16 @@ "markdownDescription": "Denies the webview_size command without any pre-configured scope." }, { - "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`", + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`", "type": "string", "const": "core:window:default", - "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`" + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-activity-name", + "markdownDescription": "Enables the activity_name command without any pre-configured scope." }, { "description": "Enables the available_monitors command without any pre-configured scope.", @@ -1424,6 +1454,12 @@ "const": "core:window:allow-scale-factor", "markdownDescription": "Enables the scale_factor command without any pre-configured scope." }, + { + "description": "Enables the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scene-identifier", + "markdownDescription": "Enables the scene_identifier command without any pre-configured scope." + }, { "description": "Enables the set_always_on_bottom command without any pre-configured scope.", "type": "string", @@ -1688,6 +1724,12 @@ "const": "core:window:allow-unminimize", "markdownDescription": "Enables the unminimize command without any pre-configured scope." }, + { + "description": "Denies the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-activity-name", + "markdownDescription": "Denies the activity_name command without any pre-configured scope." + }, { "description": "Denies the available_monitors command without any pre-configured scope.", "type": "string", @@ -1880,6 +1922,12 @@ "const": "core:window:deny-scale-factor", "markdownDescription": "Denies the scale_factor command without any pre-configured scope." }, + { + "description": "Denies the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scene-identifier", + "markdownDescription": "Denies the scene_identifier command without any pre-configured scope." + }, { "description": "Denies the set_always_on_bottom command without any pre-configured scope.", "type": "string", @@ -2145,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`", + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`", "type": "string", "const": "device-info:default", - "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`" + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`" }, { "description": "Enables the get_battery_info command without any pre-configured scope.", @@ -2180,6 +2228,18 @@ "const": "device-info:allow-get-storage-info", "markdownDescription": "Enables the get_storage_info command without any pre-configured scope." }, + { + "description": "Enables the start_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:allow-start-watching", + "markdownDescription": "Enables the start_watching command without any pre-configured scope." + }, + { + "description": "Enables the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:allow-stop-watching", + "markdownDescription": "Enables the stop_watching command without any pre-configured scope." + }, { "description": "Denies the get_battery_info command without any pre-configured scope.", "type": "string", @@ -2209,6 +2269,18 @@ "type": "string", "const": "device-info:deny-get-storage-info", "markdownDescription": "Denies the get_storage_info command without any pre-configured scope." + }, + { + "description": "Denies the start_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:deny-start-watching", + "markdownDescription": "Denies the start_watching command without any pre-configured scope." + }, + { + "description": "Denies the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:deny-stop-watching", + "markdownDescription": "Denies the stop_watching command without any pre-configured scope." } ] }, diff --git a/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json b/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json index 37fe584..fa7587d 100644 --- a/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json +++ b/examples/tauri-app/src-tauri/gen/schemas/macOS-schema.json @@ -183,10 +183,10 @@ "markdownDescription": "Default core plugins set.\n#### This default permission set includes:\n\n- `core:path:default`\n- `core:event:default`\n- `core:window:default`\n- `core:webview:default`\n- `core:app:default`\n- `core:image:default`\n- `core:resources:default`\n- `core:menu:default`\n- `core:tray:default`" }, { - "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`", + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`", "type": "string", "const": "core:app:default", - "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`" + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-version`\n- `allow-name`\n- `allow-tauri-version`\n- `allow-identifier`\n- `allow-bundle-type`\n- `allow-register-listener`\n- `allow-remove-listener`\n- `allow-supports-multiple-windows`" }, { "description": "Enables the app_hide command without any pre-configured scope.", @@ -260,6 +260,12 @@ "const": "core:app:allow-set-dock-visibility", "markdownDescription": "Enables the set_dock_visibility command without any pre-configured scope." }, + { + "description": "Enables the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:allow-supports-multiple-windows", + "markdownDescription": "Enables the supports_multiple_windows command without any pre-configured scope." + }, { "description": "Enables the tauri_version command without any pre-configured scope.", "type": "string", @@ -344,6 +350,12 @@ "const": "core:app:deny-set-dock-visibility", "markdownDescription": "Denies the set_dock_visibility command without any pre-configured scope." }, + { + "description": "Denies the supports_multiple_windows command without any pre-configured scope.", + "type": "string", + "const": "core:app:deny-supports-multiple-windows", + "markdownDescription": "Denies the supports_multiple_windows command without any pre-configured scope." + }, { "description": "Denies the tauri_version command without any pre-configured scope.", "type": "string", @@ -867,10 +879,10 @@ "markdownDescription": "Denies the close command without any pre-configured scope." }, { - "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`", + "description": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`", "type": "string", "const": "core:tray:default", - "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-show-menu-on-left-click`" + "markdownDescription": "Default permissions for the plugin, which enables all commands.\n#### This default permission set includes:\n\n- `allow-new`\n- `allow-get-by-id`\n- `allow-remove-by-id`\n- `allow-set-icon`\n- `allow-set-menu`\n- `allow-set-tooltip`\n- `allow-set-title`\n- `allow-set-visible`\n- `allow-set-temp-dir-path`\n- `allow-set-icon-as-template`\n- `allow-set-icon-with-as-template`\n- `allow-set-show-menu-on-left-click`" }, { "description": "Enables the get_by_id command without any pre-configured scope.", @@ -902,6 +914,12 @@ "const": "core:tray:allow-set-icon-as-template", "markdownDescription": "Enables the set_icon_as_template command without any pre-configured scope." }, + { + "description": "Enables the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:allow-set-icon-with-as-template", + "markdownDescription": "Enables the set_icon_with_as_template command without any pre-configured scope." + }, { "description": "Enables the set_menu command without any pre-configured scope.", "type": "string", @@ -968,6 +986,12 @@ "const": "core:tray:deny-set-icon-as-template", "markdownDescription": "Denies the set_icon_as_template command without any pre-configured scope." }, + { + "description": "Denies the set_icon_with_as_template command without any pre-configured scope.", + "type": "string", + "const": "core:tray:deny-set-icon-with-as-template", + "markdownDescription": "Denies the set_icon_with_as_template command without any pre-configured scope." + }, { "description": "Denies the set_menu command without any pre-configured scope.", "type": "string", @@ -1227,10 +1251,16 @@ "markdownDescription": "Denies the webview_size command without any pre-configured scope." }, { - "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`", + "description": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`", "type": "string", "const": "core:window:default", - "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-internal-toggle-maximize`" + "markdownDescription": "Default permissions for the plugin.\n#### This default permission set includes:\n\n- `allow-get-all-windows`\n- `allow-scale-factor`\n- `allow-inner-position`\n- `allow-outer-position`\n- `allow-inner-size`\n- `allow-outer-size`\n- `allow-is-fullscreen`\n- `allow-is-minimized`\n- `allow-is-maximized`\n- `allow-is-focused`\n- `allow-is-decorated`\n- `allow-is-resizable`\n- `allow-is-maximizable`\n- `allow-is-minimizable`\n- `allow-is-closable`\n- `allow-is-visible`\n- `allow-is-enabled`\n- `allow-title`\n- `allow-current-monitor`\n- `allow-primary-monitor`\n- `allow-monitor-from-point`\n- `allow-available-monitors`\n- `allow-cursor-position`\n- `allow-theme`\n- `allow-is-always-on-top`\n- `allow-activity-name`\n- `allow-scene-identifier`\n- `allow-internal-toggle-maximize`" + }, + { + "description": "Enables the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-activity-name", + "markdownDescription": "Enables the activity_name command without any pre-configured scope." }, { "description": "Enables the available_monitors command without any pre-configured scope.", @@ -1424,6 +1454,12 @@ "const": "core:window:allow-scale-factor", "markdownDescription": "Enables the scale_factor command without any pre-configured scope." }, + { + "description": "Enables the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:allow-scene-identifier", + "markdownDescription": "Enables the scene_identifier command without any pre-configured scope." + }, { "description": "Enables the set_always_on_bottom command without any pre-configured scope.", "type": "string", @@ -1688,6 +1724,12 @@ "const": "core:window:allow-unminimize", "markdownDescription": "Enables the unminimize command without any pre-configured scope." }, + { + "description": "Denies the activity_name command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-activity-name", + "markdownDescription": "Denies the activity_name command without any pre-configured scope." + }, { "description": "Denies the available_monitors command without any pre-configured scope.", "type": "string", @@ -1880,6 +1922,12 @@ "const": "core:window:deny-scale-factor", "markdownDescription": "Denies the scale_factor command without any pre-configured scope." }, + { + "description": "Denies the scene_identifier command without any pre-configured scope.", + "type": "string", + "const": "core:window:deny-scene-identifier", + "markdownDescription": "Denies the scene_identifier command without any pre-configured scope." + }, { "description": "Denies the set_always_on_bottom command without any pre-configured scope.", "type": "string", @@ -2145,10 +2193,10 @@ "markdownDescription": "Denies the unminimize command without any pre-configured scope." }, { - "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`", + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`", "type": "string", "const": "device-info:default", - "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`" + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`" }, { "description": "Enables the get_battery_info command without any pre-configured scope.", @@ -2180,6 +2228,18 @@ "const": "device-info:allow-get-storage-info", "markdownDescription": "Enables the get_storage_info command without any pre-configured scope." }, + { + "description": "Enables the start_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:allow-start-watching", + "markdownDescription": "Enables the start_watching command without any pre-configured scope." + }, + { + "description": "Enables the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:allow-stop-watching", + "markdownDescription": "Enables the stop_watching command without any pre-configured scope." + }, { "description": "Denies the get_battery_info command without any pre-configured scope.", "type": "string", @@ -2209,6 +2269,18 @@ "type": "string", "const": "device-info:deny-get-storage-info", "markdownDescription": "Denies the get_storage_info command without any pre-configured scope." + }, + { + "description": "Denies the start_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:deny-start-watching", + "markdownDescription": "Denies the start_watching command without any pre-configured scope." + }, + { + "description": "Denies the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "device-info:deny-stop-watching", + "markdownDescription": "Denies the stop_watching command without any pre-configured scope." } ] }, diff --git a/examples/tauri-app/src/App.svelte b/examples/tauri-app/src/App.svelte index 195e23d..28c5b7d 100644 --- a/examples/tauri-app/src/App.svelte +++ b/examples/tauri-app/src/App.svelte @@ -5,6 +5,9 @@ getNetworkInfo, getStorageInfo, getDisplayInfo, + watchBattery, + watchNetwork, + watchDisplay, } from "tauri-plugin-device-info-api"; import type { @@ -13,6 +16,7 @@ NetworkInfo, StorageInfo, DisplayInfo, + UnwatchFn, } from "tauri-plugin-device-info-api"; import { onMount, onDestroy } from "svelte"; @@ -34,7 +38,8 @@ let showChargingIcon = $state(false); let lastChargingState = false; - let pollingInterval: number | undefined; + let batteryInitialized = false; + let unwatchers: UnwatchFn[] = []; async function fetchData() { loading = true; @@ -45,11 +50,6 @@ networkInfo = await getNetworkInfo(); storageInfo = await getStorageInfo(); displayInfo = await getDisplayInfo(); - - // Initialize tracking state - if (batteryInfo) { - lastChargingState = batteryInfo.isCharging || false; - } } catch (e: any) { error = e.toString(); } finally { @@ -57,34 +57,41 @@ } } - function startBatteryPolling() { - pollingInterval = setInterval(async () => { - try { - const info = await getBatteryInfo(); - - // Check if charging started (transition from false to true) - if (info.isCharging && !lastChargingState) { + // Reactive watchers replace manual setInterval polling. + // On macOS these are native event-driven (IOKit / Core Graphics / + // SystemConfiguration); elsewhere they fall back to change-detecting polling. + async function startWatchers() { + unwatchers.push( + await watchBattery((info) => { + // Show the overlay only on a real false → true charging transition, + // never on the initial value delivered when the watcher starts. + if (batteryInitialized && info.isCharging && !lastChargingState) { showChargingIcon = true; setTimeout(() => { showChargingIcon = false; }, 5000); } - + batteryInitialized = true; lastChargingState = info.isCharging || false; - batteryInfo = info; // Update UI with latest info - } catch (e) { - console.error("Battery polling error:", e); - } - }, 1000); // Check every 1 second + batteryInfo = info; + }), + ); + unwatchers.push(await watchNetwork((info) => (networkInfo = info))); + unwatchers.push(await watchDisplay((info) => (displayInfo = info))); } onMount(() => { fetchData(); - startBatteryPolling(); + // startWatchers is async; surface a failed start instead of leaving an + // unhandled rejection (e.g. missing permission or backend error). + startWatchers().catch((e) => { + error = e?.toString?.() ?? String(e); + }); }); onDestroy(() => { - if (pollingInterval) clearInterval(pollingInterval); + unwatchers.forEach((unwatch) => unwatch()); + unwatchers = []; }); diff --git a/guest-js/index.ts b/guest-js/index.ts index 3deb235..e824e01 100644 --- a/guest-js/index.ts +++ b/guest-js/index.ts @@ -1,9 +1,10 @@ import { invoke } from '@tauri-apps/api/core' +import { listen } from '@tauri-apps/api/event' -import type { DeviceInfoResponse, BatteryInfo, NetworkInfo, StorageInfo, DisplayInfo } from './type' +import type { DeviceInfoResponse, BatteryInfo, NetworkInfo, StorageInfo, DisplayInfo, WatchOptions, UnwatchFn } from './type' // Re-export types for consumers -export type { DeviceInfoResponse, DeviceInfoResponse as DeviceInfo, BatteryInfo, NetworkInfo, StorageInfo, DisplayInfo } from './type' +export type { DeviceInfoResponse, DeviceInfoResponse as DeviceInfo, BatteryInfo, NetworkInfo, StorageInfo, DisplayInfo, WatchOptions, UnwatchFn } from './type' /** * Get comprehensive device information including UUID, manufacturer, model, etc. @@ -39,3 +40,62 @@ export async function getStorageInfo(): Promise { export async function getDisplayInfo(): Promise { return await invoke('plugin:device-info|get_display_info') } + +// ============================================================================ +// Reactive watch API +// ============================================================================ + +type WatchKind = 'battery' | 'network' | 'storage' | 'display' | 'device' + +/** + * Subscribes to a device-info kind and invokes `callback` whenever the value changes. + * The current value is delivered immediately, then on every change. + * Returns a function that stops watching and removes the listener. + */ +async function watch( + kind: WatchKind, + callback: (value: T) => void, + options?: WatchOptions +): Promise { + const unlisten = await listen(`device-info://${kind}-changed`, (event) => { + callback(event.payload) + }) + + try { + await invoke('plugin:device-info|start_watching', { kind, intervalMs: options?.intervalMs }) + } catch (error) { + // Don't leak the event listener if the backend failed to start the watcher. + unlisten() + throw error + } + + return async () => { + unlisten() + await invoke('plugin:device-info|stop_watching', { kind }) + } +} + +/** Watch battery status (level, charging state, health) for changes. */ +export function watchBattery(callback: (info: BatteryInfo) => void, options?: WatchOptions): Promise { + return watch('battery', callback, options) +} + +/** Watch network connectivity (IP, type, MAC) for changes — e.g. Wi-Fi ↔ offline. */ +export function watchNetwork(callback: (info: NetworkInfo) => void, options?: WatchOptions): Promise { + return watch('network', callback, options) +} + +/** Watch storage capacity (total/free space) for changes. */ +export function watchStorage(callback: (info: StorageInfo) => void, options?: WatchOptions): Promise { + return watch('storage', callback, options) +} + +/** Watch display properties (resolution, scale, refresh rate) for changes — e.g. plugging in a monitor. */ +export function watchDisplay(callback: (info: DisplayInfo) => void, options?: WatchOptions): Promise { + return watch('display', callback, options) +} + +/** Watch device identity fields for changes (rarely changes; useful on mobile). */ +export function watchDevice(callback: (info: DeviceInfoResponse) => void, options?: WatchOptions): Promise { + return watch('device', callback, options) +} diff --git a/guest-js/type.ts b/guest-js/type.ts index e397433..c6e2f25 100644 --- a/guest-js/type.ts +++ b/guest-js/type.ts @@ -30,4 +30,24 @@ export interface DisplayInfo { height?: number; scaleFactor?: number; refreshRate?: number; -} \ No newline at end of file +} + +/** Options for the reactive `watch*` APIs. */ +export interface WatchOptions { + /** + * Polling interval in milliseconds used to detect changes (only applies to + * kinds that fall back to polling; native event-driven kinds ignore it). + * + * Defaults and minimums are per kind, because some getters are expensive and + * some values rarely change: + * - `device`: defaults to 60000ms, floored at 10000ms (reads are costly and it barely changes) + * - `storage`: defaults to 10000ms, floored at 1000ms + * - others: default 2000ms, floored at 250ms + * + * Only the first subscriber for a given kind sets the interval. + */ + intervalMs?: number; +} + +/** Stops a watcher and removes its listener. Returned by every `watch*` function. */ +export type UnwatchFn = () => Promise; \ No newline at end of file diff --git a/package.json b/package.json index 256b678..73608b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "tauri-plugin-device-info-api", - "version": "1.0.1", + "version": "1.1.0", "author": "edisdev", "description": "A Tauri plugin to access device information.", "license": "MIT", diff --git a/permissions/autogenerated/commands/start_watching.toml b/permissions/autogenerated/commands/start_watching.toml new file mode 100644 index 0000000..1e92b4c --- /dev/null +++ b/permissions/autogenerated/commands/start_watching.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-start-watching" +description = "Enables the start_watching command without any pre-configured scope." +commands.allow = ["start_watching"] + +[[permission]] +identifier = "deny-start-watching" +description = "Denies the start_watching command without any pre-configured scope." +commands.deny = ["start_watching"] diff --git a/permissions/autogenerated/commands/stop_watching.toml b/permissions/autogenerated/commands/stop_watching.toml new file mode 100644 index 0000000..6d7d27f --- /dev/null +++ b/permissions/autogenerated/commands/stop_watching.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-stop-watching" +description = "Enables the stop_watching command without any pre-configured scope." +commands.allow = ["stop_watching"] + +[[permission]] +identifier = "deny-stop-watching" +description = "Denies the stop_watching command without any pre-configured scope." +commands.deny = ["stop_watching"] diff --git a/permissions/autogenerated/reference.md b/permissions/autogenerated/reference.md index 179f913..8ba9387 100644 --- a/permissions/autogenerated/reference.md +++ b/permissions/autogenerated/reference.md @@ -9,6 +9,8 @@ Default permissions for the plugin - `allow-get-network-info` - `allow-get-storage-info` - `allow-get-display-info` +- `allow-start-watching` +- `allow-stop-watching` ## Permission Table @@ -146,6 +148,58 @@ Enables the get_storage_info command without any pre-configured scope. Denies the get_storage_info command without any pre-configured scope. + + + + + + +`device-info:allow-start-watching` + + + + +Enables the start_watching command without any pre-configured scope. + + + + + + + +`device-info:deny-start-watching` + + + + +Denies the start_watching command without any pre-configured scope. + + + + + + + +`device-info:allow-stop-watching` + + + + +Enables the stop_watching command without any pre-configured scope. + + + + + + + +`device-info:deny-stop-watching` + + + + +Denies the stop_watching command without any pre-configured scope. + diff --git a/permissions/default.toml b/permissions/default.toml index 1d3f618..c62a36c 100644 --- a/permissions/default.toml +++ b/permissions/default.toml @@ -1,3 +1,3 @@ [default] description = "Default permissions for the plugin" -permissions = ["allow-get-device-info", "allow-get-battery-info", "allow-get-network-info", "allow-get-storage-info", "allow-get-display-info"] +permissions = ["allow-get-device-info", "allow-get-battery-info", "allow-get-network-info", "allow-get-storage-info", "allow-get-display-info", "allow-start-watching", "allow-stop-watching"] diff --git a/permissions/schemas/schema.json b/permissions/schemas/schema.json index 4ac91ce..4df78cd 100644 --- a/permissions/schemas/schema.json +++ b/permissions/schemas/schema.json @@ -355,10 +355,34 @@ "markdownDescription": "Denies the get_storage_info command without any pre-configured scope." }, { - "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`", + "description": "Enables the start_watching command without any pre-configured scope.", + "type": "string", + "const": "allow-start-watching", + "markdownDescription": "Enables the start_watching command without any pre-configured scope." + }, + { + "description": "Denies the start_watching command without any pre-configured scope.", + "type": "string", + "const": "deny-start-watching", + "markdownDescription": "Denies the start_watching command without any pre-configured scope." + }, + { + "description": "Enables the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "allow-stop-watching", + "markdownDescription": "Enables the stop_watching command without any pre-configured scope." + }, + { + "description": "Denies the stop_watching command without any pre-configured scope.", + "type": "string", + "const": "deny-stop-watching", + "markdownDescription": "Denies the stop_watching command without any pre-configured scope." + }, + { + "description": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`", "type": "string", "const": "default", - "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`" + "markdownDescription": "Default permissions for the plugin\n#### This default permission set includes:\n\n- `allow-get-device-info`\n- `allow-get-battery-info`\n- `allow-get-network-info`\n- `allow-get-storage-info`\n- `allow-get-display-info`\n- `allow-start-watching`\n- `allow-stop-watching`" } ] } diff --git a/src/commands.rs b/src/commands.rs index b622687..39b92fa 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -28,3 +28,17 @@ pub(crate) async fn get_storage_info(app: AppHandle) -> Result(app: AppHandle) -> Result { app.device_info().get_display_info() } + +#[command] +pub(crate) async fn start_watching( + app: AppHandle, + kind: String, + interval_ms: Option, +) -> Result<()> { + crate::watcher::start(&app, &kind, interval_ms) +} + +#[command] +pub(crate) async fn stop_watching(app: AppHandle, kind: String) -> Result<()> { + crate::watcher::stop(&app, &kind) +} diff --git a/src/lib.rs b/src/lib.rs index 725f157..54e49fd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,6 +61,7 @@ mod mobile; mod commands; mod error; mod models; +mod watcher; pub use error::{Error, Result}; @@ -88,7 +89,9 @@ pub fn init() -> TauriPlugin { commands::get_battery_info, commands::get_network_info, commands::get_storage_info, - commands::get_display_info + commands::get_display_info, + commands::start_watching, + commands::stop_watching ]) .setup(|app, api| { #[cfg(mobile)] @@ -96,6 +99,7 @@ pub fn init() -> TauriPlugin { #[cfg(desktop)] let device_info = desktop::init(app, api)?; app.manage(device_info); + app.manage(watcher::WatcherState::default()); Ok(()) }) .build() diff --git a/src/watcher.rs b/src/watcher.rs new file mode 100644 index 0000000..138c798 --- /dev/null +++ b/src/watcher.rs @@ -0,0 +1,232 @@ +//! Reactive watch API for the device-info plugin. +//! +//! Consumers *subscribe* to a kind of device information and receive a Tauri +//! event whenever the value changes, instead of polling a getter on a timer. +//! +//! ## Architecture +//! +//! Each watch `kind` is backed by a [`MonitorHandle`]: +//! +//! - When the platform exposes a **native, event-driven** source for a kind +//! (e.g. IOKit power notifications on macOS), that is used — the CPU stays +//! idle between changes and updates are delivered the instant they happen. +//! - Otherwise we fall back to a **change-detecting poller** (see [`polling`]). +//! +//! Either way the public API and the emitted event names are identical, so the +//! engine can be upgraded per platform/kind without affecting consumers. +//! +//! Subscribers are reference-counted: the monitor for a kind starts on the +//! first subscriber and is torn down once the last one unsubscribes. + +use std::collections::HashMap; +use std::sync::Mutex; + +use tauri::{AppHandle, Emitter, Manager, Runtime}; + +use crate::DeviceInfoExt; + +mod native; +mod polling; + +/// The kinds of device information that can be watched. +pub(crate) const WATCH_KINDS: &[&str] = &["battery", "network", "storage", "display", "device"]; + +/// A running change-event source for one kind. +/// +/// `stop` must tear down whatever the monitor set up — OS callbacks, run loops, +/// D-Bus connections, or polling threads. +pub(crate) trait MonitorHandle: Send { + fn stop(self: Box); +} + +/// One active monitor plus its subscriber count. +struct Subscription { + handle: Box, + refs: usize, +} + +/// Shared state holding at most one monitor per active watch kind. +#[derive(Default)] +pub(crate) struct WatcherState { + subs: Mutex>, +} + +/// The event name emitted for a given watch kind, e.g. `device-info://battery-changed`. +pub(crate) fn event_name(kind: &str) -> String { + format!("device-info://{kind}-changed") +} + +/// Reads the current value for `kind` as a JSON value, for change comparison and emission. +/// +/// Shared by the poller and by native monitors (which read the fresh value when +/// the OS signals a change). +pub(crate) fn read_snapshot( + app: &AppHandle, + kind: &str, +) -> crate::Result { + let di = app.device_info(); + let value = match kind { + "battery" => serde_json::to_value(di.get_battery_info()?), + "network" => serde_json::to_value(di.get_network_info()?), + "storage" => serde_json::to_value(di.get_storage_info()?), + "display" => serde_json::to_value(di.get_display_info()?), + "device" => serde_json::to_value(di.get_device_info()?), + other => { + return Err(crate::Error::DeviceInfo(format!( + "unknown watch kind: {other}" + ))) + } + }; + value.map_err(|e| crate::Error::DeviceInfo(e.to_string())) +} + +/// Reads the current value for `kind` and emits `event` only if it differs from +/// `last`, updating `last` on emit. +/// +/// This is the single change-detection + emission path shared by the poller and +/// the native monitors, so both stay in lockstep. The payload is emitted by +/// reference to avoid a deep clone of the value also stored in `last`. +pub(crate) fn emit_if_changed( + app: &AppHandle, + event: &str, + kind: &str, + last: &mut Option, +) { + if let Ok(snapshot) = read_snapshot(app, kind) { + if last.as_ref() != Some(&snapshot) { + let _ = app.emit(event, &snapshot); + *last = Some(snapshot); + } + } +} + +/// Subscribes to a watch `kind`, starting a monitor if one isn't already running. +/// +/// A native event-driven monitor is preferred; if the platform has none for this +/// kind, a change-detecting poller is used (`interval_ms` applies only then, and +/// only for the first subscriber). +pub(crate) fn start( + app: &AppHandle, + kind: &str, + interval_ms: Option, +) -> crate::Result<()> { + if !WATCH_KINDS.contains(&kind) { + return Err(crate::Error::DeviceInfo(format!( + "unknown watch kind: {kind}" + ))); + } + + let state = app.state::(); + let mut subs = state.subs.lock().map_err(poisoned)?; + + // A monitor is already running for this kind: just add a subscriber. + if let Some(sub) = subs.get_mut(kind) { + sub.refs += 1; + return Ok(()); + } + + // Prefer a native event-driven monitor; fall back to the poller. + let handle = match native::try_spawn(app, kind)? { + Some(handle) => handle, + None => polling::spawn(app, kind, interval_ms), + }; + + subs.insert(kind.to_string(), Subscription { handle, refs: 1 }); + Ok(()) +} + +/// Unsubscribes from a watch `kind`, stopping the monitor once the last subscriber leaves. +pub(crate) fn stop(app: &AppHandle, kind: &str) -> crate::Result<()> { + let state = app.state::(); + + // Take the handle out from under the lock, then tear it down *after* releasing + // it: `handle.stop()` can block (it joins the monitor thread), and holding the + // subs mutex across that would serialize every other kind's subscribe/unsubscribe. + let handle = { + let mut subs = state.subs.lock().map_err(poisoned)?; + match subs.get_mut(kind) { + Some(sub) => { + sub.refs = sub.refs.saturating_sub(1); + if sub.refs == 0 { + subs.remove(kind).map(|sub| sub.handle) + } else { + None + } + } + None => None, + } + }; + + if let Some(handle) = handle { + handle.stop(); + } + Ok(()) +} + +/// Maps a poisoned-lock error into the plugin's error type. +fn poisoned(e: E) -> crate::Error { + crate::Error::DeviceInfo(format!("watcher state poisoned: {e}")) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn event_name_follows_convention() { + assert_eq!(event_name("battery"), "device-info://battery-changed"); + assert_eq!(event_name("network"), "device-info://network-changed"); + } + + #[test] + fn watch_kinds_cover_all_getters() { + for kind in ["battery", "network", "storage", "display", "device"] { + assert!(WATCH_KINDS.contains(&kind), "missing watch kind: {kind}"); + } + } + + // The tests below use Tauri's mock runtime, which is only available off + // Windows here (see the target-gated dev-dependency in Cargo.toml). + + #[cfg(not(target_os = "windows"))] + #[test] + fn unknown_kind_is_rejected() { + let app = mock_app(); + let err = start(app.handle(), "gpu", None).unwrap_err(); + assert!(err.to_string().contains("unknown watch kind")); + } + + /// Exercises the full monitor lifecycle (spawn → emit → stop → join → free) + /// for every kind, including the native macOS event-driven paths. Catches + /// FFI signature mistakes, use-after-free, and stop deadlocks at runtime. + #[cfg(not(target_os = "windows"))] + #[test] + fn start_and_stop_every_kind_does_not_crash() { + let app = mock_app(); + for kind in WATCH_KINDS { + start(app.handle(), kind, Some(250)).unwrap(); + std::thread::sleep(std::time::Duration::from_millis(60)); + stop(app.handle(), kind).unwrap(); + } + } + + #[cfg(not(target_os = "windows"))] + #[test] + fn reference_counting_keeps_monitor_until_last_unsubscribe() { + let app = mock_app(); + start(app.handle(), "battery", None).unwrap(); + start(app.handle(), "battery", None).unwrap(); + stop(app.handle(), "battery").unwrap(); // one subscriber left + stop(app.handle(), "battery").unwrap(); // last subscriber → tears down + // Extra stop on an already-removed kind must be a no-op, not a panic. + stop(app.handle(), "battery").unwrap(); + } + + #[cfg(not(target_os = "windows"))] + fn mock_app() -> tauri::App { + tauri::test::mock_builder() + .plugin(crate::init()) + .build(tauri::test::mock_context(tauri::test::noop_assets())) + .expect("failed to build mock app") + } +} diff --git a/src/watcher/native.rs b/src/watcher/native.rs new file mode 100644 index 0000000..9d37f20 --- /dev/null +++ b/src/watcher/native.rs @@ -0,0 +1,39 @@ +//! Native, OS-event-driven monitors. +//! +//! [`try_spawn`] returns `Ok(Some(handle))` when the current platform has a +//! native event source for `kind`, or `Ok(None)` to fall back to polling. +//! +//! ## Roadmap (each entry requires on-device verification) +//! +//! | Kind | macOS | Windows | Linux | +//! |---------|-----------------------------------------|--------------------------------------|--------------------------------| +//! | battery | IOKit `IOPSNotificationCreateRunLoopSource` ✅ | `RegisterPowerSettingNotification` | UPower / D-Bus | +//! | display | `CGDisplayRegisterReconfigurationCallback` ✅ | `WM_DISPLAYCHANGE` | XRandR | +//! | network | `SCNetworkReachability` | `NotifyUnicastIpAddressChange` | netlink / NetworkManager | +//! | storage | *(no OS event — always polled)* | *(polled)* | *(polled)* | +//! | device | *(rarely changes — polled)* | *(polled)* | *(polled)* | + +use tauri::{AppHandle, Runtime}; + +use super::MonitorHandle; + +#[cfg(target_os = "macos")] +mod macos; + +/// Returns a native event-driven monitor for `kind` if this platform supports +/// one, else `Ok(None)` so the caller falls back to polling. +pub(super) fn try_spawn( + app: &AppHandle, + kind: &str, +) -> crate::Result>> { + #[cfg(target_os = "macos")] + { + macos::try_spawn(app, kind) + } + + #[cfg(not(target_os = "macos"))] + { + let _ = (app, kind); + Ok(None) + } +} diff --git a/src/watcher/native/macos.rs b/src/watcher/native/macos.rs new file mode 100644 index 0000000..1c6cb7a --- /dev/null +++ b/src/watcher/native/macos.rs @@ -0,0 +1,489 @@ +//! macOS native monitors — event-driven via Core Foundation run loops. +//! +//! Each monitor runs a dedicated thread with its own `CFRunLoop` and registers +//! an OS notification source: +//! +//! - **battery** — IOKit `IOPSNotificationCreateRunLoopSource` +//! - **display** — Core Graphics `CGDisplayRegisterReconfigurationCallback` +//! - **network** — SystemConfiguration `SCNetworkReachability` +//! +//! The OS invokes our callback only when state changes, so the CPU stays idle in +//! between. A no-op keep-alive timer is added so `CFRunLoopRun` does not return +//! before `stop` asks it to. Storage and device have no OS change event and fall +//! back to polling. + +#![allow(non_snake_case, non_upper_case_globals, dead_code)] + +use std::ffi::c_void; +use std::ptr; +use std::sync::{Arc, Condvar, Mutex}; +use std::thread::JoinHandle; + +use tauri::{AppHandle, Runtime}; + +use crate::watcher::{emit_if_changed, event_name, MonitorHandle}; + +// ---- Core Foundation FFI ---------------------------------------------------- + +type CFRunLoopRef = *mut c_void; +type CFRunLoopSourceRef = *mut c_void; +type CFRunLoopTimerRef = *mut c_void; +type CFStringRef = *const c_void; +type CFAllocatorRef = *const c_void; + +type CFRunLoopTimerCallBack = unsafe extern "C" fn(timer: CFRunLoopTimerRef, info: *mut c_void); +type CFRunLoopPerformCallBack = unsafe extern "C" fn(info: *mut c_void); + +/// Context for a version-0 `CFRunLoopSource`. Only `perform` is used; the other +/// callbacks are left null (matching how [`SCNetworkReachabilityContext`] is set up). +#[repr(C)] +struct CFRunLoopSourceContext { + version: isize, + info: *mut c_void, + retain: *const c_void, + release: *const c_void, + copyDescription: *const c_void, + equal: *const c_void, + hash: *const c_void, + schedule: *const c_void, + cancel: *const c_void, + perform: CFRunLoopPerformCallBack, +} + +#[link(name = "CoreFoundation", kind = "framework")] +extern "C" { + static kCFRunLoopDefaultMode: CFStringRef; + fn CFRunLoopGetCurrent() -> CFRunLoopRef; + fn CFRunLoopRun(); + fn CFRunLoopStop(rl: CFRunLoopRef); + fn CFRunLoopWakeUp(rl: CFRunLoopRef); + fn CFRunLoopAddSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef); + fn CFRunLoopRemoveSource(rl: CFRunLoopRef, source: CFRunLoopSourceRef, mode: CFStringRef); + fn CFRunLoopSourceCreate( + allocator: CFAllocatorRef, + order: isize, + context: *mut CFRunLoopSourceContext, + ) -> CFRunLoopSourceRef; + fn CFRunLoopSourceSignal(source: CFRunLoopSourceRef); + fn CFRunLoopAddTimer(rl: CFRunLoopRef, timer: CFRunLoopTimerRef, mode: CFStringRef); + fn CFRunLoopTimerCreate( + allocator: CFAllocatorRef, + fireDate: f64, + interval: f64, + flags: usize, + order: isize, + callout: CFRunLoopTimerCallBack, + context: *mut c_void, + ) -> CFRunLoopTimerRef; + fn CFAbsoluteTimeGetCurrent() -> f64; + fn CFRelease(cf: *const c_void); +} + +// ---- IOKit (battery) FFI ---------------------------------------------------- + +type IOPSCallback = unsafe extern "C" fn(context: *mut c_void); + +#[link(name = "IOKit", kind = "framework")] +extern "C" { + fn IOPSNotificationCreateRunLoopSource( + callback: IOPSCallback, + context: *mut c_void, + ) -> CFRunLoopSourceRef; +} + +// ---- Core Graphics (display) FFI -------------------------------------------- + +type CGDirectDisplayID = u32; +type CGDisplayChangeSummaryFlags = u32; +type CGDisplayReconfigurationCallBack = unsafe extern "C" fn( + display: CGDirectDisplayID, + flags: CGDisplayChangeSummaryFlags, + userInfo: *mut c_void, +); + +#[link(name = "CoreGraphics", kind = "framework")] +extern "C" { + fn CGDisplayRegisterReconfigurationCallback( + callback: CGDisplayReconfigurationCallBack, + userInfo: *mut c_void, + ) -> i32; + fn CGDisplayRemoveReconfigurationCallback( + callback: CGDisplayReconfigurationCallBack, + userInfo: *mut c_void, + ) -> i32; +} + +// ---- SystemConfiguration (network) FFI -------------------------------------- + +type SCNetworkReachabilityRef = *mut c_void; +type SCNetworkReachabilityFlags = u32; +type SCNetworkReachabilityCallBack = unsafe extern "C" fn( + target: SCNetworkReachabilityRef, + flags: SCNetworkReachabilityFlags, + info: *mut c_void, +); + +#[repr(C)] +struct SCNetworkReachabilityContext { + version: isize, + info: *mut c_void, + retain: *const c_void, + release: *const c_void, + copyDescription: *const c_void, +} + +/// Minimal `sockaddr_in` for a zeroed address ("general internet reachability"). +#[repr(C)] +struct SockaddrIn { + sin_len: u8, + sin_family: u8, + sin_port: u16, + sin_addr: u32, + sin_zero: [u8; 8], +} + +#[link(name = "SystemConfiguration", kind = "framework")] +extern "C" { + fn SCNetworkReachabilityCreateWithAddress( + allocator: CFAllocatorRef, + address: *const c_void, + ) -> SCNetworkReachabilityRef; + fn SCNetworkReachabilitySetCallback( + target: SCNetworkReachabilityRef, + callout: SCNetworkReachabilityCallBack, + context: *mut SCNetworkReachabilityContext, + ) -> u8; + fn SCNetworkReachabilityScheduleWithRunLoop( + target: SCNetworkReachabilityRef, + runLoop: CFRunLoopRef, + runLoopMode: CFStringRef, + ) -> u8; + fn SCNetworkReachabilityUnscheduleFromRunLoop( + target: SCNetworkReachabilityRef, + runLoop: CFRunLoopRef, + runLoopMode: CFStringRef, + ) -> u8; +} + +/// Keep-alive timer firing far in the future, only to keep the run loop alive. +const KEEPALIVE_INTERVAL: f64 = 1.0e10; + +// ---- Type-erased emit context ----------------------------------------------- + +/// Type-erases the generic `AppHandle` so the context can travel through a C `void*`. +trait Fire: Send + Sync { + fn fire(&self); +} + +/// Reads the current value for a kind and emits an event only when it changed. +struct EmitCtx { + app: AppHandle, + kind: String, + event: String, + last: Mutex>, +} + +impl Fire for EmitCtx { + fn fire(&self) { + let Ok(mut last) = self.last.lock() else { + return; + }; + emit_if_changed(&self.app, &self.event, &self.kind, &mut last); + } +} + +/// Dereferences a C `void*` back into the boxed [`Fire`] context and fires it. +/// +/// # Safety +/// `context` must be the `*mut Box` handed to the OS during +/// registration; it stays valid until the monitor thread frees it after the run +/// loop stops. +unsafe fn fire_ctx(context: *mut c_void) { + let ctx = &*(context as *const Box); + // The platform callbacks below are `extern "C"`; a panic unwinding across that + // ABI boundary aborts the whole process, so contain it here. + let _ = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| ctx.fire())); +} + +unsafe extern "C" fn battery_callback(context: *mut c_void) { + fire_ctx(context); +} + +unsafe extern "C" fn display_callback( + _display: CGDirectDisplayID, + _flags: CGDisplayChangeSummaryFlags, + user_info: *mut c_void, +) { + fire_ctx(user_info); +} + +unsafe extern "C" fn network_callback( + _target: SCNetworkReachabilityRef, + _flags: SCNetworkReachabilityFlags, + info: *mut c_void, +) { + fire_ctx(info); +} + +unsafe extern "C" fn noop_timer(_timer: CFRunLoopTimerRef, _info: *mut c_void) {} + +/// Performed on the monitor thread when `stop` signals the stop source. Because +/// it runs *inside* the run loop it can stop it race-free — even a signal that +/// arrives before `CFRunLoopRun` starts is honored the moment the loop runs. +unsafe extern "C" fn stop_perform(_info: *mut c_void) { + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +// ---- Run-loop monitor handle ------------------------------------------------ + +/// Tracks the state of the monitor thread's run loop. +enum LoopState { + /// The thread has not finished setting up yet. + Pending, + /// The run loop is live; holds the `CFRunLoopRef` and the stop-source ref as + /// `usize`s (so they are `Send`) for `stop` to signal. + Running { run_loop: usize, stop_source: usize }, +} + +/// Handle to a macOS run-loop monitor. +struct MacRunLoopHandle { + state: Arc<(Mutex, Condvar)>, + join: Option>, +} + +impl MonitorHandle for MacRunLoopHandle { + fn stop(mut self: Box) { + let (lock, cvar) = &*self.state; + let mut guard = lock.lock().unwrap_or_else(|e| e.into_inner()); + while matches!(*guard, LoopState::Pending) { + guard = cvar.wait(guard).unwrap_or_else(|e| e.into_inner()); + } + if let LoopState::Running { + run_loop, + stop_source, + } = *guard + { + // SAFETY: signaling the stop source and waking the loop are thread-safe. + // The source performs on the monitor thread and calls `CFRunLoopStop` + // there, which is race-free even if the loop has not started running yet + // (a signaled version-0 source is serviced the moment the loop runs). + unsafe { + CFRunLoopSourceSignal(stop_source as CFRunLoopSourceRef); + CFRunLoopWakeUp(run_loop as CFRunLoopRef); + } + } + drop(guard); + + if let Some(join) = self.join.take() { + let _ = join.join(); + } + } +} + +// ---- Platform registration -------------------------------------------------- + +/// Undoes a registration; called on the monitor thread after the run loop stops. +type Teardown = Box; + +fn register_battery(run_loop: CFRunLoopRef, ctx: *mut c_void) -> Teardown { + // SAFETY: valid C callback and context; the source is removed and released in teardown. + let source = unsafe { IOPSNotificationCreateRunLoopSource(battery_callback, ctx) }; + if source.is_null() { + return Box::new(|| {}); + } + // SAFETY: adding our source to this thread's run loop in the default mode. + unsafe { CFRunLoopAddSource(run_loop, source, kCFRunLoopDefaultMode) }; + + let rl = run_loop as usize; + let src = source as usize; + Box::new(move || unsafe { + CFRunLoopRemoveSource( + rl as CFRunLoopRef, + src as CFRunLoopSourceRef, + kCFRunLoopDefaultMode, + ); + CFRelease(src as *const c_void); + }) +} + +fn register_display(_run_loop: CFRunLoopRef, ctx: *mut c_void) -> Teardown { + // SAFETY: registering a callback with our context; removed in teardown. + unsafe { CGDisplayRegisterReconfigurationCallback(display_callback, ctx) }; + let ctx_us = ctx as usize; + Box::new(move || unsafe { + CGDisplayRemoveReconfigurationCallback(display_callback, ctx_us as *mut c_void); + }) +} + +fn register_network(run_loop: CFRunLoopRef, ctx: *mut c_void) -> Teardown { + // Zeroed IPv4 address = general internet reachability; fires on route changes. + let addr = SockaddrIn { + sin_len: core::mem::size_of::() as u8, + sin_family: 2, // AF_INET + sin_port: 0, + sin_addr: 0, + sin_zero: [0; 8], + }; + + // SAFETY: passing a valid, stack-allocated sockaddr by const pointer. + let reach = unsafe { + SCNetworkReachabilityCreateWithAddress( + ptr::null(), + &addr as *const SockaddrIn as *const c_void, + ) + }; + if reach.is_null() { + eprintln!( + "device-info: SCNetworkReachabilityCreateWithAddress failed; \ + network watch will report the initial value only" + ); + return Box::new(|| {}); + } + + let mut context = SCNetworkReachabilityContext { + version: 0, + info: ctx, + retain: ptr::null(), + release: ptr::null(), + copyDescription: ptr::null(), + }; + + // SAFETY: `SetCallback` copies the context struct; scheduling on our run loop. + // Both return a boolean (0 = failure); a failed setup means no change events, + // so surface it rather than silently degrading to a one-shot value. + let ok = unsafe { + let set = SCNetworkReachabilitySetCallback(reach, network_callback, &mut context); + let sched = + SCNetworkReachabilityScheduleWithRunLoop(reach, run_loop, kCFRunLoopDefaultMode); + set != 0 && sched != 0 + }; + if !ok { + eprintln!( + "device-info: failed to schedule SCNetworkReachability callback; \ + network watch will report the initial value only" + ); + } + + let reach_us = reach as usize; + let rl = run_loop as usize; + Box::new(move || unsafe { + SCNetworkReachabilityUnscheduleFromRunLoop( + reach_us as SCNetworkReachabilityRef, + rl as CFRunLoopRef, + kCFRunLoopDefaultMode, + ); + CFRelease(reach_us as *const c_void); + }) +} + +// ---- Public entry point ----------------------------------------------------- + +/// Returns a native monitor for `kind` if macOS has one, else `Ok(None)` to poll. +pub(super) fn try_spawn( + app: &AppHandle, + kind: &str, +) -> crate::Result>> { + let register: fn(CFRunLoopRef, *mut c_void) -> Teardown = match kind { + "battery" => register_battery, + "display" => register_display, + "network" => register_network, + // storage and device have no OS change event; poll them. + _ => return Ok(None), + }; + Ok(Some(spawn_runloop(app, kind, register))) +} + +/// Spawns a dedicated run-loop thread, registers the OS source, and returns its handle. +fn spawn_runloop( + app: &AppHandle, + kind: &str, + register: fn(CFRunLoopRef, *mut c_void) -> Teardown, +) -> Box { + let ctx: Box = Box::new(EmitCtx { + app: app.clone(), + kind: kind.to_string(), + event: event_name(kind), + last: Mutex::new(None), + }); + // A thin pointer to the fat trait-object pointer, so it fits in a C `void*`. + let ctx_ptr = Box::into_raw(Box::new(ctx)) as usize; + + let state = Arc::new((Mutex::new(LoopState::Pending), Condvar::new())); + let state_thread = state.clone(); + + let join = std::thread::spawn(move || { + let ctx_void = ctx_ptr as *mut c_void; + let run_loop = unsafe { CFRunLoopGetCurrent() }; + + // Keep-alive timer so `CFRunLoopRun` does not exit when a source is idle. + // SAFETY: no-op callout, null context; timer is released after the run loop stops. + let timer = unsafe { + CFRunLoopTimerCreate( + ptr::null(), + CFAbsoluteTimeGetCurrent() + KEEPALIVE_INTERVAL, + KEEPALIVE_INTERVAL, + 0, + 0, + noop_timer, + ptr::null_mut(), + ) + }; + unsafe { CFRunLoopAddTimer(run_loop, timer, kCFRunLoopDefaultMode) }; + + // Stop source: `stop` signals this to make the loop stop *itself* from + // inside, which is race-free even if `stop` fires before `CFRunLoopRun`. + // SAFETY: version-0 source with a valid `perform`; removed and released below. + let mut src_ctx = CFRunLoopSourceContext { + version: 0, + info: ptr::null_mut(), + retain: ptr::null(), + release: ptr::null(), + copyDescription: ptr::null(), + equal: ptr::null(), + hash: ptr::null(), + schedule: ptr::null(), + cancel: ptr::null(), + perform: stop_perform, + }; + let stop_source = unsafe { CFRunLoopSourceCreate(ptr::null(), 0, &mut src_ctx) }; + unsafe { CFRunLoopAddSource(run_loop, stop_source, kCFRunLoopDefaultMode) }; + + // Platform-specific registration (returns its teardown). + let teardown = register(run_loop, ctx_void); + + // Publish the run loop + stop source so `stop` can wake it. + { + let (lock, cvar) = &*state_thread; + *lock.lock().unwrap_or_else(|e| e.into_inner()) = LoopState::Running { + run_loop: run_loop as usize, + stop_source: stop_source as usize, + }; + cvar.notify_all(); + } + + // Emit the current value immediately so a fresh subscriber gets initial state. + // SAFETY: `ctx_ptr` is valid until freed below, after the run loop stops. + unsafe { fire_ctx(ctx_void) }; + + // Blocks until the stop source performs and calls `CFRunLoopStop`. + unsafe { CFRunLoopRun() }; + + // Tear down OS registration, remove/release the stop source and timer, + // then free the context. + teardown(); + // SAFETY: the source and timer were created above and are no longer needed + // once the run loop has stopped. + unsafe { + CFRunLoopRemoveSource(run_loop, stop_source, kCFRunLoopDefaultMode); + CFRelease(stop_source); + CFRelease(timer); + }; + // SAFETY: `ctx_ptr` is no longer referenced by any OS callback after teardown. + unsafe { drop(Box::from_raw(ctx_ptr as *mut Box)) }; + }); + + Box::new(MacRunLoopHandle { + state, + join: Some(join), + }) +} diff --git a/src/watcher/polling.rs b/src/watcher/polling.rs new file mode 100644 index 0000000..6827764 --- /dev/null +++ b/src/watcher/polling.rs @@ -0,0 +1,104 @@ +//! Change-detecting poller. +//! +//! Reads the value on an interval and emits an event only when it differs from +//! the last emitted value. Used as the universal fallback for kinds/platforms +//! that have no native event source (storage always; anything not yet wired up +//! natively). +//! +//! The interval defaults are chosen **per kind**: some getters are far more +//! expensive than others (on macOS `device` shells out to `system_profiler`, +//! ~1-2s of CPU) and some values barely ever change. Polling those aggressively +//! would spawn a subprocess every couple of seconds for data that is effectively +//! static, so they default to — and are floored at — much longer intervals. + +use std::sync::{Arc, Condvar, Mutex}; +use std::time::Duration; + +use tauri::{AppHandle, Runtime}; + +use super::{emit_if_changed, event_name, MonitorHandle}; + +/// Default polling interval for a kind when the caller does not specify one. +/// +/// `device` almost never changes and is very expensive to read; `storage` +/// changes slowly. Everything else uses a responsive 2s default. +fn default_interval_ms(kind: &str) -> u64 { + match kind { + "device" => 60_000, + "storage" => 10_000, + _ => 2_000, + } +} + +/// Lower bound on the polling interval for a kind, so a caller cannot pin an +/// expensive getter to a tiny interval and peg a CPU core. +fn min_interval_ms(kind: &str) -> u64 { + match kind { + "device" => 10_000, + "storage" => 1_000, + _ => 250, + } +} + +/// Shared stop flag: the boolean guards the condition, the condvar lets `stop` +/// wake the sleeping poller immediately instead of it polling the flag. +type StopSignal = Arc<(Mutex, Condvar)>; + +/// Handle to a running poller thread. +pub(super) struct PollingHandle { + stop: StopSignal, +} + +impl MonitorHandle for PollingHandle { + fn stop(self: Box) { + let (lock, cvar) = &*self.stop; + *lock.lock().unwrap_or_else(|e| e.into_inner()) = true; + cvar.notify_all(); + } +} + +/// Spawns a poller thread for `kind` and returns its handle. +/// +/// The current value is emitted on the first iteration so a fresh subscriber +/// gets the initial state without waiting a full interval. +pub(super) fn spawn( + app: &AppHandle, + kind: &str, + interval_ms: Option, +) -> Box { + let interval = interval_ms + .unwrap_or_else(|| default_interval_ms(kind)) + .max(min_interval_ms(kind)); + let stop: StopSignal = Arc::new((Mutex::new(false), Condvar::new())); + + let app = app.clone(); + let kind = kind.to_string(); + let stop_flag = stop.clone(); + + std::thread::spawn(move || { + let event = event_name(&kind); + let interval = Duration::from_millis(interval); + let (lock, cvar) = &*stop_flag; + let mut last: Option = None; + + loop { + emit_if_changed(&app, &event, &kind, &mut last); + + // Sleep for the full interval, but wake the instant `stop` is called. + let guard = lock.lock().unwrap_or_else(|e| e.into_inner()); + if *guard { + break; + } + let (guard, _) = cvar + .wait_timeout(guard, interval) + .unwrap_or_else(|e| e.into_inner()); + let stopped = *guard; + drop(guard); + if stopped { + break; + } + } + }); + + Box::new(PollingHandle { stop }) +}