diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea9d0ee1..a66e057a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -36,11 +36,11 @@ jobs: if: matrix.platform == 'ubuntu-22.04' # This must match the platform value defined above. run: | sudo apt-get update - sudo apt-get install -y libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - # webkitgtk 4.0 is for Tauri v1 - webkitgtk 4.1 is for Tauri v2. - # You can remove the one that doesn't apply to your app to speed up the workflow a bit. + sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf - name: Install dependencies run: npm ci + - name: Run lint + run: npm run lint - name: Run tests run: npm test - uses: tauri-apps/tauri-action@v0 diff --git a/package-lock.json b/package-lock.json index cfb94dde..8f4e3832 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.0", "dependencies": { "@codemirror/commands": "^6.2.1", - "@codemirror/lang-javascript": "^6.1.4", + "@codemirror/lang-javascript": "^6.2.2", "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-xml": "^6.0.2", "@codemirror/language": "^6.6.0", diff --git a/package.json b/package.json index 96c56421..c92acf17 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ }, "dependencies": { "@codemirror/commands": "^6.2.1", - "@codemirror/lang-javascript": "^6.1.4", + "@codemirror/lang-javascript": "^6.2.2", "@codemirror/lang-json": "^6.0.1", "@codemirror/lang-xml": "^6.0.2", "@codemirror/language": "^6.6.0", diff --git a/src-tauri/.sqlx/query-48ec5fdf20f34add763c540061caa25054545503704e19f149987f99b1a0e4f0.json b/src-tauri/.sqlx/query-48ec5fdf20f34add763c540061caa25054545503704e19f149987f99b1a0e4f0.json deleted file mode 100644 index a959caf8..00000000 --- a/src-tauri/.sqlx/query-48ec5fdf20f34add763c540061caa25054545503704e19f149987f99b1a0e4f0.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "db_name": "SQLite", - "query": "\n UPDATE settings SET (\n theme, appearance, update_channel\n ) = (?, ?, ?) WHERE id = 'default';\n ", - "describe": { - "columns": [], - "parameters": { - "Right": 3 - }, - "nullable": [] - }, - "hash": "48ec5fdf20f34add763c540061caa25054545503704e19f149987f99b1a0e4f0" -} diff --git a/src-tauri/.sqlx/query-8e88c7070a34a6e151da66f521deeafaea9a12e2aa68081daaf235d2003b513d.json b/src-tauri/.sqlx/query-8e88c7070a34a6e151da66f521deeafaea9a12e2aa68081daaf235d2003b513d.json new file mode 100644 index 00000000..9fa18228 --- /dev/null +++ b/src-tauri/.sqlx/query-8e88c7070a34a6e151da66f521deeafaea9a12e2aa68081daaf235d2003b513d.json @@ -0,0 +1,12 @@ +{ + "db_name": "SQLite", + "query": "\n UPDATE settings SET (\n theme, appearance, theme_dark, theme_light, update_channel\n ) = (?, ?, ?, ?, ?) WHERE id = 'default';\n ", + "describe": { + "columns": [], + "parameters": { + "Right": 5 + }, + "nullable": [] + }, + "hash": "8e88c7070a34a6e151da66f521deeafaea9a12e2aa68081daaf235d2003b513d" +} diff --git a/src-tauri/.sqlx/query-b32994b09ae7a06eb0f031069d327e55127a5bce60cbb499b83d1701386a23cb.json b/src-tauri/.sqlx/query-cae02809532d086fbde12a246d12e3839ec8610b66e08315106dbdbf25d8699c.json similarity index 67% rename from src-tauri/.sqlx/query-b32994b09ae7a06eb0f031069d327e55127a5bce60cbb499b83d1701386a23cb.json rename to src-tauri/.sqlx/query-cae02809532d086fbde12a246d12e3839ec8610b66e08315106dbdbf25d8699c.json index aed140c8..eae379e3 100644 --- a/src-tauri/.sqlx/query-b32994b09ae7a06eb0f031069d327e55127a5bce60cbb499b83d1701386a23cb.json +++ b/src-tauri/.sqlx/query-cae02809532d086fbde12a246d12e3839ec8610b66e08315106dbdbf25d8699c.json @@ -1,6 +1,6 @@ { "db_name": "SQLite", - "query": "\n SELECT\n id, model, created_at, updated_at, theme, appearance, update_channel\n FROM settings\n WHERE id = 'default'\n ", + "query": "\n SELECT\n id, model, created_at, updated_at, theme, appearance,\n theme_dark, theme_light, update_channel\n FROM settings\n WHERE id = 'default'\n ", "describe": { "columns": [ { @@ -34,9 +34,19 @@ "type_info": "Text" }, { - "name": "update_channel", + "name": "theme_dark", "ordinal": 6, "type_info": "Text" + }, + { + "name": "theme_light", + "ordinal": 7, + "type_info": "Text" + }, + { + "name": "update_channel", + "ordinal": 8, + "type_info": "Text" } ], "parameters": { @@ -49,8 +59,10 @@ false, false, false, + false, + false, false ] }, - "hash": "b32994b09ae7a06eb0f031069d327e55127a5bce60cbb499b83d1701386a23cb" + "hash": "cae02809532d086fbde12a246d12e3839ec8610b66e08315106dbdbf25d8699c" } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 17b82503..1463da8c 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -2350,6 +2350,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hex_color" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d37f101bf4c633f7ca2e4b5e136050314503dd198e78e325ea602c327c484ef0" +dependencies = [ + "rand 0.8.5", +] + [[package]] name = "hkdf" version = "0.12.3" @@ -7650,6 +7659,7 @@ dependencies = [ "cocoa", "datetime", "grpc", + "hex_color", "http 0.2.10", "log", "objc", @@ -7674,6 +7684,7 @@ dependencies = [ "tokio", "tokio-stream", "uuid", + "windows 0.56.0", ] [[package]] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index ef7c3d2e..541f67ab 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -20,6 +20,13 @@ tauri-build = { version = "2.0.0-beta", features = [] } objc = "0.2.7" cocoa = "0.25.0" +[target.'cfg(target_os = "windows")'.dependencies] +windows = { version = "0.56.0", features = [ + "Win32_Graphics_Dwm", + "Win32_Foundation", + "Win32_UI_Controls", +] } + [target.'cfg(target_os = "linux")'.dependencies] openssl-sys = { version = "0.9", features = ["vendored"] } # For Ubuntu installation to work @@ -51,3 +58,4 @@ reqwest_cookie_store = "0.6.0" grpc = { path = "./grpc" } tokio-stream = "0.1.15" regex = "1.10.2" +hex_color = "3.0.0" diff --git a/src-tauri/gen/schemas/windows-schema.json b/src-tauri/gen/schemas/windows-schema.json new file mode 100644 index 00000000..e35feebf --- /dev/null +++ b/src-tauri/gen/schemas/windows-schema.json @@ -0,0 +1,6791 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "CapabilityFile", + "description": "Capability formats accepted in a capability file.", + "anyOf": [ + { + "description": "A single capability.", + "allOf": [ + { + "$ref": "#/definitions/Capability" + } + ] + }, + { + "description": "A list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + }, + { + "description": "A list of capabilities.", + "type": "object", + "required": [ + "capabilities" + ], + "properties": { + "capabilities": { + "description": "The list of capabilities.", + "type": "array", + "items": { + "$ref": "#/definitions/Capability" + } + } + } + } + ], + "definitions": { + "Capability": { + "description": "a grouping and boundary mechanism developers can use to separate windows or plugins functionality from each other at runtime.\n\nIf a window is not matching any capability then it has no access to the IPC layer at all.\n\nThis can be done to create trust groups and reduce impact of vulnerabilities in certain plugins or windows. Windows can be added to a capability by exact name or glob patterns like *, admin-* or main-window.", + "type": "object", + "required": [ + "identifier", + "permissions" + ], + "properties": { + "identifier": { + "description": "Identifier of the capability.", + "type": "string" + }, + "description": { + "description": "Description of the capability.", + "default": "", + "type": "string" + }, + "remote": { + "description": "Configure remote URLs that can use the capability permissions.", + "anyOf": [ + { + "$ref": "#/definitions/CapabilityRemote" + }, + { + "type": "null" + } + ] + }, + "local": { + "description": "Whether this capability is enabled for local app URLs or not. Defaults to `true`.", + "default": true, + "type": "boolean" + }, + "windows": { + "description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.", + "type": "array", + "items": { + "type": "string" + } + }, + "webviews": { + "description": "List of webviews that uses this capability. Can be a glob pattern.\n\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.", + "type": "array", + "items": { + "type": "string" + } + }, + "permissions": { + "description": "List of permissions attached to this capability. Must include the plugin name as prefix in the form of `${plugin-name}:${permission-name}`.", + "type": "array", + "items": { + "$ref": "#/definitions/PermissionEntry" + } + }, + "platforms": { + "description": "Target platforms this capability applies. By default all platforms are affected by this capability.", + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/definitions/Target" + } + } + } + }, + "CapabilityRemote": { + "description": "Configuration for remote URLs that are associated with the capability.", + "type": "object", + "required": [ + "urls" + ], + "properties": { + "urls": { + "description": "Remote domains this capability refers to using the [URLPattern standard](https://urlpattern.spec.whatwg.org/).\n\n# Examples\n\n- \"https://*.mydomain.dev\": allows subdomains of mydomain.dev - \"https://mydomain.dev/api/*\": allows any subpath of mydomain.dev/api", + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "PermissionEntry": { + "description": "An entry for a permission value in a [`Capability`] can be either a raw permission [`Identifier`] or an object that references a permission and extends its scope.", + "anyOf": [ + { + "description": "Reference a permission or permission set by identifier.", + "allOf": [ + { + "$ref": "#/definitions/Identifier" + } + ] + }, + { + "description": "Reference a permission or permission set by identifier and extends its scope.", + "type": "object", + "oneOf": [ + { + "type": "object", + "required": [ + "identifier" + ], + "properties": { + "identifier": { + "oneOf": [ + { + "description": "fs:default -> # Tauri `fs` default permissions\n\nThis configuration file defines the default permissions granted\nto the filesystem.\n\n### Granted Permissions\n\nThis default permission set enables all read-related commands and\nallows access to the `$APP` folder and sub directories created in it.\nThe location of the `$APP` folder depends on the operating system,\nwhere the application is run.\n\nIn general the `$APP` folder needs to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\n### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "type": "string", + "enum": [ + "fs:default" + ] + }, + { + "description": "fs:allow-app-meta -> This allows non-recursive read access to metadata of the `$APP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-app-meta" + ] + }, + { + "description": "fs:allow-app-meta-recursive -> This allows full recursive read access to metadata of the `$APP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-app-meta-recursive" + ] + }, + { + "description": "fs:allow-app-read -> This allows non-recursive read access to the `$APP` folder.", + "type": "string", + "enum": [ + "fs:allow-app-read" + ] + }, + { + "description": "fs:allow-app-read-recursive -> This allows full recursive read access to the complete `$APP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-app-read-recursive" + ] + }, + { + "description": "fs:allow-app-write -> This allows non-recursive write access to the `$APP` folder.", + "type": "string", + "enum": [ + "fs:allow-app-write" + ] + }, + { + "description": "fs:allow-app-write-recursive -> This allows full recursive write access to the complete `$APP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-app-write-recursive" + ] + }, + { + "description": "fs:allow-appcache-meta -> This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appcache-meta" + ] + }, + { + "description": "fs:allow-appcache-meta-recursive -> This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appcache-meta-recursive" + ] + }, + { + "description": "fs:allow-appcache-read -> This allows non-recursive read access to the `$APPCACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-appcache-read" + ] + }, + { + "description": "fs:allow-appcache-read-recursive -> This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appcache-read-recursive" + ] + }, + { + "description": "fs:allow-appcache-write -> This allows non-recursive write access to the `$APPCACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-appcache-write" + ] + }, + { + "description": "fs:allow-appcache-write-recursive -> This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appcache-write-recursive" + ] + }, + { + "description": "fs:allow-appconfig-meta -> This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appconfig-meta" + ] + }, + { + "description": "fs:allow-appconfig-meta-recursive -> This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appconfig-meta-recursive" + ] + }, + { + "description": "fs:allow-appconfig-read -> This allows non-recursive read access to the `$APPCONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-appconfig-read" + ] + }, + { + "description": "fs:allow-appconfig-read-recursive -> This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appconfig-read-recursive" + ] + }, + { + "description": "fs:allow-appconfig-write -> This allows non-recursive write access to the `$APPCONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-appconfig-write" + ] + }, + { + "description": "fs:allow-appconfig-write-recursive -> This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appconfig-write-recursive" + ] + }, + { + "description": "fs:allow-appdata-meta -> This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appdata-meta" + ] + }, + { + "description": "fs:allow-appdata-meta-recursive -> This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appdata-meta-recursive" + ] + }, + { + "description": "fs:allow-appdata-read -> This allows non-recursive read access to the `$APPDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-appdata-read" + ] + }, + { + "description": "fs:allow-appdata-read-recursive -> This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appdata-read-recursive" + ] + }, + { + "description": "fs:allow-appdata-write -> This allows non-recursive write access to the `$APPDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-appdata-write" + ] + }, + { + "description": "fs:allow-appdata-write-recursive -> This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appdata-write-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-meta -> This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-meta" + ] + }, + { + "description": "fs:allow-applocaldata-meta-recursive -> This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-meta-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-read -> This allows non-recursive read access to the `$APPLOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-read" + ] + }, + { + "description": "fs:allow-applocaldata-read-recursive -> This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-read-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-write -> This allows non-recursive write access to the `$APPLOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-write" + ] + }, + { + "description": "fs:allow-applocaldata-write-recursive -> This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-write-recursive" + ] + }, + { + "description": "fs:allow-applog-meta -> This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applog-meta" + ] + }, + { + "description": "fs:allow-applog-meta-recursive -> This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applog-meta-recursive" + ] + }, + { + "description": "fs:allow-applog-read -> This allows non-recursive read access to the `$APPLOG` folder.", + "type": "string", + "enum": [ + "fs:allow-applog-read" + ] + }, + { + "description": "fs:allow-applog-read-recursive -> This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applog-read-recursive" + ] + }, + { + "description": "fs:allow-applog-write -> This allows non-recursive write access to the `$APPLOG` folder.", + "type": "string", + "enum": [ + "fs:allow-applog-write" + ] + }, + { + "description": "fs:allow-applog-write-recursive -> This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applog-write-recursive" + ] + }, + { + "description": "fs:allow-audio-meta -> This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-audio-meta" + ] + }, + { + "description": "fs:allow-audio-meta-recursive -> This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-audio-meta-recursive" + ] + }, + { + "description": "fs:allow-audio-read -> This allows non-recursive read access to the `$AUDIO` folder.", + "type": "string", + "enum": [ + "fs:allow-audio-read" + ] + }, + { + "description": "fs:allow-audio-read-recursive -> This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-audio-read-recursive" + ] + }, + { + "description": "fs:allow-audio-write -> This allows non-recursive write access to the `$AUDIO` folder.", + "type": "string", + "enum": [ + "fs:allow-audio-write" + ] + }, + { + "description": "fs:allow-audio-write-recursive -> This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-audio-write-recursive" + ] + }, + { + "description": "fs:allow-cache-meta -> This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-cache-meta" + ] + }, + { + "description": "fs:allow-cache-meta-recursive -> This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-cache-meta-recursive" + ] + }, + { + "description": "fs:allow-cache-read -> This allows non-recursive read access to the `$CACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-cache-read" + ] + }, + { + "description": "fs:allow-cache-read-recursive -> This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-cache-read-recursive" + ] + }, + { + "description": "fs:allow-cache-write -> This allows non-recursive write access to the `$CACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-cache-write" + ] + }, + { + "description": "fs:allow-cache-write-recursive -> This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-cache-write-recursive" + ] + }, + { + "description": "fs:allow-config-meta -> This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-config-meta" + ] + }, + { + "description": "fs:allow-config-meta-recursive -> This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-config-meta-recursive" + ] + }, + { + "description": "fs:allow-config-read -> This allows non-recursive read access to the `$CONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-config-read" + ] + }, + { + "description": "fs:allow-config-read-recursive -> This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-config-read-recursive" + ] + }, + { + "description": "fs:allow-config-write -> This allows non-recursive write access to the `$CONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-config-write" + ] + }, + { + "description": "fs:allow-config-write-recursive -> This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-config-write-recursive" + ] + }, + { + "description": "fs:allow-data-meta -> This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-data-meta" + ] + }, + { + "description": "fs:allow-data-meta-recursive -> This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-data-meta-recursive" + ] + }, + { + "description": "fs:allow-data-read -> This allows non-recursive read access to the `$DATA` folder.", + "type": "string", + "enum": [ + "fs:allow-data-read" + ] + }, + { + "description": "fs:allow-data-read-recursive -> This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-data-read-recursive" + ] + }, + { + "description": "fs:allow-data-write -> This allows non-recursive write access to the `$DATA` folder.", + "type": "string", + "enum": [ + "fs:allow-data-write" + ] + }, + { + "description": "fs:allow-data-write-recursive -> This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-data-write-recursive" + ] + }, + { + "description": "fs:allow-desktop-meta -> This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-desktop-meta" + ] + }, + { + "description": "fs:allow-desktop-meta-recursive -> This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-desktop-meta-recursive" + ] + }, + { + "description": "fs:allow-desktop-read -> This allows non-recursive read access to the `$DESKTOP` folder.", + "type": "string", + "enum": [ + "fs:allow-desktop-read" + ] + }, + { + "description": "fs:allow-desktop-read-recursive -> This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-desktop-read-recursive" + ] + }, + { + "description": "fs:allow-desktop-write -> This allows non-recursive write access to the `$DESKTOP` folder.", + "type": "string", + "enum": [ + "fs:allow-desktop-write" + ] + }, + { + "description": "fs:allow-desktop-write-recursive -> This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-desktop-write-recursive" + ] + }, + { + "description": "fs:allow-document-meta -> This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-document-meta" + ] + }, + { + "description": "fs:allow-document-meta-recursive -> This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-document-meta-recursive" + ] + }, + { + "description": "fs:allow-document-read -> This allows non-recursive read access to the `$DOCUMENT` folder.", + "type": "string", + "enum": [ + "fs:allow-document-read" + ] + }, + { + "description": "fs:allow-document-read-recursive -> This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-document-read-recursive" + ] + }, + { + "description": "fs:allow-document-write -> This allows non-recursive write access to the `$DOCUMENT` folder.", + "type": "string", + "enum": [ + "fs:allow-document-write" + ] + }, + { + "description": "fs:allow-document-write-recursive -> This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-document-write-recursive" + ] + }, + { + "description": "fs:allow-download-meta -> This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-download-meta" + ] + }, + { + "description": "fs:allow-download-meta-recursive -> This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-download-meta-recursive" + ] + }, + { + "description": "fs:allow-download-read -> This allows non-recursive read access to the `$DOWNLOAD` folder.", + "type": "string", + "enum": [ + "fs:allow-download-read" + ] + }, + { + "description": "fs:allow-download-read-recursive -> This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-download-read-recursive" + ] + }, + { + "description": "fs:allow-download-write -> This allows non-recursive write access to the `$DOWNLOAD` folder.", + "type": "string", + "enum": [ + "fs:allow-download-write" + ] + }, + { + "description": "fs:allow-download-write-recursive -> This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-download-write-recursive" + ] + }, + { + "description": "fs:allow-exe-meta -> This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-exe-meta" + ] + }, + { + "description": "fs:allow-exe-meta-recursive -> This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-exe-meta-recursive" + ] + }, + { + "description": "fs:allow-exe-read -> This allows non-recursive read access to the `$EXE` folder.", + "type": "string", + "enum": [ + "fs:allow-exe-read" + ] + }, + { + "description": "fs:allow-exe-read-recursive -> This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-exe-read-recursive" + ] + }, + { + "description": "fs:allow-exe-write -> This allows non-recursive write access to the `$EXE` folder.", + "type": "string", + "enum": [ + "fs:allow-exe-write" + ] + }, + { + "description": "fs:allow-exe-write-recursive -> This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-exe-write-recursive" + ] + }, + { + "description": "fs:allow-font-meta -> This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-font-meta" + ] + }, + { + "description": "fs:allow-font-meta-recursive -> This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-font-meta-recursive" + ] + }, + { + "description": "fs:allow-font-read -> This allows non-recursive read access to the `$FONT` folder.", + "type": "string", + "enum": [ + "fs:allow-font-read" + ] + }, + { + "description": "fs:allow-font-read-recursive -> This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-font-read-recursive" + ] + }, + { + "description": "fs:allow-font-write -> This allows non-recursive write access to the `$FONT` folder.", + "type": "string", + "enum": [ + "fs:allow-font-write" + ] + }, + { + "description": "fs:allow-font-write-recursive -> This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-font-write-recursive" + ] + }, + { + "description": "fs:allow-home-meta -> This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-home-meta" + ] + }, + { + "description": "fs:allow-home-meta-recursive -> This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-home-meta-recursive" + ] + }, + { + "description": "fs:allow-home-read -> This allows non-recursive read access to the `$HOME` folder.", + "type": "string", + "enum": [ + "fs:allow-home-read" + ] + }, + { + "description": "fs:allow-home-read-recursive -> This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-home-read-recursive" + ] + }, + { + "description": "fs:allow-home-write -> This allows non-recursive write access to the `$HOME` folder.", + "type": "string", + "enum": [ + "fs:allow-home-write" + ] + }, + { + "description": "fs:allow-home-write-recursive -> This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-home-write-recursive" + ] + }, + { + "description": "fs:allow-localdata-meta -> This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-localdata-meta" + ] + }, + { + "description": "fs:allow-localdata-meta-recursive -> This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-localdata-meta-recursive" + ] + }, + { + "description": "fs:allow-localdata-read -> This allows non-recursive read access to the `$LOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-localdata-read" + ] + }, + { + "description": "fs:allow-localdata-read-recursive -> This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-localdata-read-recursive" + ] + }, + { + "description": "fs:allow-localdata-write -> This allows non-recursive write access to the `$LOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-localdata-write" + ] + }, + { + "description": "fs:allow-localdata-write-recursive -> This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-localdata-write-recursive" + ] + }, + { + "description": "fs:allow-log-meta -> This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-log-meta" + ] + }, + { + "description": "fs:allow-log-meta-recursive -> This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-log-meta-recursive" + ] + }, + { + "description": "fs:allow-log-read -> This allows non-recursive read access to the `$LOG` folder.", + "type": "string", + "enum": [ + "fs:allow-log-read" + ] + }, + { + "description": "fs:allow-log-read-recursive -> This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-log-read-recursive" + ] + }, + { + "description": "fs:allow-log-write -> This allows non-recursive write access to the `$LOG` folder.", + "type": "string", + "enum": [ + "fs:allow-log-write" + ] + }, + { + "description": "fs:allow-log-write-recursive -> This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-log-write-recursive" + ] + }, + { + "description": "fs:allow-picture-meta -> This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-picture-meta" + ] + }, + { + "description": "fs:allow-picture-meta-recursive -> This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-picture-meta-recursive" + ] + }, + { + "description": "fs:allow-picture-read -> This allows non-recursive read access to the `$PICTURE` folder.", + "type": "string", + "enum": [ + "fs:allow-picture-read" + ] + }, + { + "description": "fs:allow-picture-read-recursive -> This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-picture-read-recursive" + ] + }, + { + "description": "fs:allow-picture-write -> This allows non-recursive write access to the `$PICTURE` folder.", + "type": "string", + "enum": [ + "fs:allow-picture-write" + ] + }, + { + "description": "fs:allow-picture-write-recursive -> This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-picture-write-recursive" + ] + }, + { + "description": "fs:allow-public-meta -> This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-public-meta" + ] + }, + { + "description": "fs:allow-public-meta-recursive -> This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-public-meta-recursive" + ] + }, + { + "description": "fs:allow-public-read -> This allows non-recursive read access to the `$PUBLIC` folder.", + "type": "string", + "enum": [ + "fs:allow-public-read" + ] + }, + { + "description": "fs:allow-public-read-recursive -> This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-public-read-recursive" + ] + }, + { + "description": "fs:allow-public-write -> This allows non-recursive write access to the `$PUBLIC` folder.", + "type": "string", + "enum": [ + "fs:allow-public-write" + ] + }, + { + "description": "fs:allow-public-write-recursive -> This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-public-write-recursive" + ] + }, + { + "description": "fs:allow-resource-meta -> This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-resource-meta" + ] + }, + { + "description": "fs:allow-resource-meta-recursive -> This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-resource-meta-recursive" + ] + }, + { + "description": "fs:allow-resource-read -> This allows non-recursive read access to the `$RESOURCE` folder.", + "type": "string", + "enum": [ + "fs:allow-resource-read" + ] + }, + { + "description": "fs:allow-resource-read-recursive -> This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-resource-read-recursive" + ] + }, + { + "description": "fs:allow-resource-write -> This allows non-recursive write access to the `$RESOURCE` folder.", + "type": "string", + "enum": [ + "fs:allow-resource-write" + ] + }, + { + "description": "fs:allow-resource-write-recursive -> This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-resource-write-recursive" + ] + }, + { + "description": "fs:allow-runtime-meta -> This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-runtime-meta" + ] + }, + { + "description": "fs:allow-runtime-meta-recursive -> This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-runtime-meta-recursive" + ] + }, + { + "description": "fs:allow-runtime-read -> This allows non-recursive read access to the `$RUNTIME` folder.", + "type": "string", + "enum": [ + "fs:allow-runtime-read" + ] + }, + { + "description": "fs:allow-runtime-read-recursive -> This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-runtime-read-recursive" + ] + }, + { + "description": "fs:allow-runtime-write -> This allows non-recursive write access to the `$RUNTIME` folder.", + "type": "string", + "enum": [ + "fs:allow-runtime-write" + ] + }, + { + "description": "fs:allow-runtime-write-recursive -> This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-runtime-write-recursive" + ] + }, + { + "description": "fs:allow-temp-meta -> This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-temp-meta" + ] + }, + { + "description": "fs:allow-temp-meta-recursive -> This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-temp-meta-recursive" + ] + }, + { + "description": "fs:allow-temp-read -> This allows non-recursive read access to the `$TEMP` folder.", + "type": "string", + "enum": [ + "fs:allow-temp-read" + ] + }, + { + "description": "fs:allow-temp-read-recursive -> This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-temp-read-recursive" + ] + }, + { + "description": "fs:allow-temp-write -> This allows non-recursive write access to the `$TEMP` folder.", + "type": "string", + "enum": [ + "fs:allow-temp-write" + ] + }, + { + "description": "fs:allow-temp-write-recursive -> This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-temp-write-recursive" + ] + }, + { + "description": "fs:allow-template-meta -> This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-template-meta" + ] + }, + { + "description": "fs:allow-template-meta-recursive -> This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-template-meta-recursive" + ] + }, + { + "description": "fs:allow-template-read -> This allows non-recursive read access to the `$TEMPLATE` folder.", + "type": "string", + "enum": [ + "fs:allow-template-read" + ] + }, + { + "description": "fs:allow-template-read-recursive -> This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-template-read-recursive" + ] + }, + { + "description": "fs:allow-template-write -> This allows non-recursive write access to the `$TEMPLATE` folder.", + "type": "string", + "enum": [ + "fs:allow-template-write" + ] + }, + { + "description": "fs:allow-template-write-recursive -> This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-template-write-recursive" + ] + }, + { + "description": "fs:allow-video-meta -> This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-video-meta" + ] + }, + { + "description": "fs:allow-video-meta-recursive -> This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-video-meta-recursive" + ] + }, + { + "description": "fs:allow-video-read -> This allows non-recursive read access to the `$VIDEO` folder.", + "type": "string", + "enum": [ + "fs:allow-video-read" + ] + }, + { + "description": "fs:allow-video-read-recursive -> This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-video-read-recursive" + ] + }, + { + "description": "fs:allow-video-write -> This allows non-recursive write access to the `$VIDEO` folder.", + "type": "string", + "enum": [ + "fs:allow-video-write" + ] + }, + { + "description": "fs:allow-video-write-recursive -> This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-video-write-recursive" + ] + }, + { + "description": "fs:deny-default -> This denies access to dangerous Tauri relevant files and folders by default.", + "type": "string", + "enum": [ + "fs:deny-default" + ] + }, + { + "description": "fs:allow-copy-file -> Enables the copy_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-copy-file" + ] + }, + { + "description": "fs:allow-create -> Enables the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-create" + ] + }, + { + "description": "fs:allow-exists -> Enables the exists command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-exists" + ] + }, + { + "description": "fs:allow-fstat -> Enables the fstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-fstat" + ] + }, + { + "description": "fs:allow-ftruncate -> Enables the ftruncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-ftruncate" + ] + }, + { + "description": "fs:allow-lstat -> Enables the lstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-lstat" + ] + }, + { + "description": "fs:allow-mkdir -> Enables the mkdir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-mkdir" + ] + }, + { + "description": "fs:allow-open -> Enables the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-open" + ] + }, + { + "description": "fs:allow-read -> Enables the read command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read" + ] + }, + { + "description": "fs:allow-read-dir -> Enables the read_dir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-dir" + ] + }, + { + "description": "fs:allow-read-file -> Enables the read_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-file" + ] + }, + { + "description": "fs:allow-read-text-file -> Enables the read_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file" + ] + }, + { + "description": "fs:allow-read-text-file-lines -> Enables the read_text_file_lines command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file-lines" + ] + }, + { + "description": "fs:allow-read-text-file-lines-next -> Enables the read_text_file_lines_next command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file-lines-next" + ] + }, + { + "description": "fs:allow-remove -> Enables the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-remove" + ] + }, + { + "description": "fs:allow-rename -> Enables the rename command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-rename" + ] + }, + { + "description": "fs:allow-seek -> Enables the seek command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-seek" + ] + }, + { + "description": "fs:allow-stat -> Enables the stat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-stat" + ] + }, + { + "description": "fs:allow-truncate -> Enables the truncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-truncate" + ] + }, + { + "description": "fs:allow-unwatch -> Enables the unwatch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-unwatch" + ] + }, + { + "description": "fs:allow-watch -> Enables the watch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-watch" + ] + }, + { + "description": "fs:allow-write -> Enables the write command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write" + ] + }, + { + "description": "fs:allow-write-file -> Enables the write_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write-file" + ] + }, + { + "description": "fs:allow-write-text-file -> Enables the write_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write-text-file" + ] + }, + { + "description": "fs:deny-copy-file -> Denies the copy_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-copy-file" + ] + }, + { + "description": "fs:deny-create -> Denies the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-create" + ] + }, + { + "description": "fs:deny-exists -> Denies the exists command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-exists" + ] + }, + { + "description": "fs:deny-fstat -> Denies the fstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-fstat" + ] + }, + { + "description": "fs:deny-ftruncate -> Denies the ftruncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-ftruncate" + ] + }, + { + "description": "fs:deny-lstat -> Denies the lstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-lstat" + ] + }, + { + "description": "fs:deny-mkdir -> Denies the mkdir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-mkdir" + ] + }, + { + "description": "fs:deny-open -> Denies the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-open" + ] + }, + { + "description": "fs:deny-read -> Denies the read command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read" + ] + }, + { + "description": "fs:deny-read-dir -> Denies the read_dir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-dir" + ] + }, + { + "description": "fs:deny-read-file -> Denies the read_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-file" + ] + }, + { + "description": "fs:deny-read-text-file -> Denies the read_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file" + ] + }, + { + "description": "fs:deny-read-text-file-lines -> Denies the read_text_file_lines command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file-lines" + ] + }, + { + "description": "fs:deny-read-text-file-lines-next -> Denies the read_text_file_lines_next command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file-lines-next" + ] + }, + { + "description": "fs:deny-remove -> Denies the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-remove" + ] + }, + { + "description": "fs:deny-rename -> Denies the rename command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-rename" + ] + }, + { + "description": "fs:deny-seek -> Denies the seek command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-seek" + ] + }, + { + "description": "fs:deny-stat -> Denies the stat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-stat" + ] + }, + { + "description": "fs:deny-truncate -> Denies the truncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-truncate" + ] + }, + { + "description": "fs:deny-unwatch -> Denies the unwatch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-unwatch" + ] + }, + { + "description": "fs:deny-watch -> Denies the watch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-watch" + ] + }, + { + "description": "fs:deny-webview-data-linux -> This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.", + "type": "string", + "enum": [ + "fs:deny-webview-data-linux" + ] + }, + { + "description": "fs:deny-webview-data-windows -> This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.", + "type": "string", + "enum": [ + "fs:deny-webview-data-windows" + ] + }, + { + "description": "fs:deny-write -> Denies the write command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write" + ] + }, + { + "description": "fs:deny-write-file -> Denies the write_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write-file" + ] + }, + { + "description": "fs:deny-write-text-file -> Denies the write_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write-text-file" + ] + }, + { + "description": "fs:read-all -> This enables all read related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-all" + ] + }, + { + "description": "fs:read-dirs -> This enables directory read and file metadata related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-dirs" + ] + }, + { + "description": "fs:read-files -> This enables file read related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-files" + ] + }, + { + "description": "fs:read-meta -> This enables all index or metadata related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-meta" + ] + }, + { + "description": "fs:scope -> An empty permission you can use to modify the global scope.", + "type": "string", + "enum": [ + "fs:scope" + ] + }, + { + "description": "fs:scope-app -> This scope permits access to all files and list content of top level directories in the `$APP`folder.", + "type": "string", + "enum": [ + "fs:scope-app" + ] + }, + { + "description": "fs:scope-app-index -> This scope permits to list all files and folders in the `$APP`folder.", + "type": "string", + "enum": [ + "fs:scope-app-index" + ] + }, + { + "description": "fs:scope-app-recursive -> This scope recursive access to the complete `$APP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-app-recursive" + ] + }, + { + "description": "fs:scope-appcache -> This scope permits access to all files and list content of top level directories in the `$APPCACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-appcache" + ] + }, + { + "description": "fs:scope-appcache-index -> This scope permits to list all files and folders in the `$APPCACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-appcache-index" + ] + }, + { + "description": "fs:scope-appcache-recursive -> This scope recursive access to the complete `$APPCACHE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appcache-recursive" + ] + }, + { + "description": "fs:scope-appconfig -> This scope permits access to all files and list content of top level directories in the `$APPCONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-appconfig" + ] + }, + { + "description": "fs:scope-appconfig-index -> This scope permits to list all files and folders in the `$APPCONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-appconfig-index" + ] + }, + { + "description": "fs:scope-appconfig-recursive -> This scope recursive access to the complete `$APPCONFIG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appconfig-recursive" + ] + }, + { + "description": "fs:scope-appdata -> This scope permits access to all files and list content of top level directories in the `$APPDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-appdata" + ] + }, + { + "description": "fs:scope-appdata-index -> This scope permits to list all files and folders in the `$APPDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-appdata-index" + ] + }, + { + "description": "fs:scope-appdata-recursive -> This scope recursive access to the complete `$APPDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appdata-recursive" + ] + }, + { + "description": "fs:scope-applocaldata -> This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-applocaldata" + ] + }, + { + "description": "fs:scope-applocaldata-index -> This scope permits to list all files and folders in the `$APPLOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-applocaldata-index" + ] + }, + { + "description": "fs:scope-applocaldata-recursive -> This scope recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-applocaldata-recursive" + ] + }, + { + "description": "fs:scope-applog -> This scope permits access to all files and list content of top level directories in the `$APPLOG`folder.", + "type": "string", + "enum": [ + "fs:scope-applog" + ] + }, + { + "description": "fs:scope-applog-index -> This scope permits to list all files and folders in the `$APPLOG`folder.", + "type": "string", + "enum": [ + "fs:scope-applog-index" + ] + }, + { + "description": "fs:scope-applog-recursive -> This scope recursive access to the complete `$APPLOG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-applog-recursive" + ] + }, + { + "description": "fs:scope-audio -> This scope permits access to all files and list content of top level directories in the `$AUDIO`folder.", + "type": "string", + "enum": [ + "fs:scope-audio" + ] + }, + { + "description": "fs:scope-audio-index -> This scope permits to list all files and folders in the `$AUDIO`folder.", + "type": "string", + "enum": [ + "fs:scope-audio-index" + ] + }, + { + "description": "fs:scope-audio-recursive -> This scope recursive access to the complete `$AUDIO` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-audio-recursive" + ] + }, + { + "description": "fs:scope-cache -> This scope permits access to all files and list content of top level directories in the `$CACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-cache" + ] + }, + { + "description": "fs:scope-cache-index -> This scope permits to list all files and folders in the `$CACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-cache-index" + ] + }, + { + "description": "fs:scope-cache-recursive -> This scope recursive access to the complete `$CACHE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-cache-recursive" + ] + }, + { + "description": "fs:scope-config -> This scope permits access to all files and list content of top level directories in the `$CONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-config" + ] + }, + { + "description": "fs:scope-config-index -> This scope permits to list all files and folders in the `$CONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-config-index" + ] + }, + { + "description": "fs:scope-config-recursive -> This scope recursive access to the complete `$CONFIG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-config-recursive" + ] + }, + { + "description": "fs:scope-data -> This scope permits access to all files and list content of top level directories in the `$DATA`folder.", + "type": "string", + "enum": [ + "fs:scope-data" + ] + }, + { + "description": "fs:scope-data-index -> This scope permits to list all files and folders in the `$DATA`folder.", + "type": "string", + "enum": [ + "fs:scope-data-index" + ] + }, + { + "description": "fs:scope-data-recursive -> This scope recursive access to the complete `$DATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-data-recursive" + ] + }, + { + "description": "fs:scope-desktop -> This scope permits access to all files and list content of top level directories in the `$DESKTOP`folder.", + "type": "string", + "enum": [ + "fs:scope-desktop" + ] + }, + { + "description": "fs:scope-desktop-index -> This scope permits to list all files and folders in the `$DESKTOP`folder.", + "type": "string", + "enum": [ + "fs:scope-desktop-index" + ] + }, + { + "description": "fs:scope-desktop-recursive -> This scope recursive access to the complete `$DESKTOP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-desktop-recursive" + ] + }, + { + "description": "fs:scope-document -> This scope permits access to all files and list content of top level directories in the `$DOCUMENT`folder.", + "type": "string", + "enum": [ + "fs:scope-document" + ] + }, + { + "description": "fs:scope-document-index -> This scope permits to list all files and folders in the `$DOCUMENT`folder.", + "type": "string", + "enum": [ + "fs:scope-document-index" + ] + }, + { + "description": "fs:scope-document-recursive -> This scope recursive access to the complete `$DOCUMENT` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-document-recursive" + ] + }, + { + "description": "fs:scope-download -> This scope permits access to all files and list content of top level directories in the `$DOWNLOAD`folder.", + "type": "string", + "enum": [ + "fs:scope-download" + ] + }, + { + "description": "fs:scope-download-index -> This scope permits to list all files and folders in the `$DOWNLOAD`folder.", + "type": "string", + "enum": [ + "fs:scope-download-index" + ] + }, + { + "description": "fs:scope-download-recursive -> This scope recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-download-recursive" + ] + }, + { + "description": "fs:scope-exe -> This scope permits access to all files and list content of top level directories in the `$EXE`folder.", + "type": "string", + "enum": [ + "fs:scope-exe" + ] + }, + { + "description": "fs:scope-exe-index -> This scope permits to list all files and folders in the `$EXE`folder.", + "type": "string", + "enum": [ + "fs:scope-exe-index" + ] + }, + { + "description": "fs:scope-exe-recursive -> This scope recursive access to the complete `$EXE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-exe-recursive" + ] + }, + { + "description": "fs:scope-font -> This scope permits access to all files and list content of top level directories in the `$FONT`folder.", + "type": "string", + "enum": [ + "fs:scope-font" + ] + }, + { + "description": "fs:scope-font-index -> This scope permits to list all files and folders in the `$FONT`folder.", + "type": "string", + "enum": [ + "fs:scope-font-index" + ] + }, + { + "description": "fs:scope-font-recursive -> This scope recursive access to the complete `$FONT` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-font-recursive" + ] + }, + { + "description": "fs:scope-home -> This scope permits access to all files and list content of top level directories in the `$HOME`folder.", + "type": "string", + "enum": [ + "fs:scope-home" + ] + }, + { + "description": "fs:scope-home-index -> This scope permits to list all files and folders in the `$HOME`folder.", + "type": "string", + "enum": [ + "fs:scope-home-index" + ] + }, + { + "description": "fs:scope-home-recursive -> This scope recursive access to the complete `$HOME` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-home-recursive" + ] + }, + { + "description": "fs:scope-localdata -> This scope permits access to all files and list content of top level directories in the `$LOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-localdata" + ] + }, + { + "description": "fs:scope-localdata-index -> This scope permits to list all files and folders in the `$LOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-localdata-index" + ] + }, + { + "description": "fs:scope-localdata-recursive -> This scope recursive access to the complete `$LOCALDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-localdata-recursive" + ] + }, + { + "description": "fs:scope-log -> This scope permits access to all files and list content of top level directories in the `$LOG`folder.", + "type": "string", + "enum": [ + "fs:scope-log" + ] + }, + { + "description": "fs:scope-log-index -> This scope permits to list all files and folders in the `$LOG`folder.", + "type": "string", + "enum": [ + "fs:scope-log-index" + ] + }, + { + "description": "fs:scope-log-recursive -> This scope recursive access to the complete `$LOG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-log-recursive" + ] + }, + { + "description": "fs:scope-picture -> This scope permits access to all files and list content of top level directories in the `$PICTURE`folder.", + "type": "string", + "enum": [ + "fs:scope-picture" + ] + }, + { + "description": "fs:scope-picture-index -> This scope permits to list all files and folders in the `$PICTURE`folder.", + "type": "string", + "enum": [ + "fs:scope-picture-index" + ] + }, + { + "description": "fs:scope-picture-recursive -> This scope recursive access to the complete `$PICTURE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-picture-recursive" + ] + }, + { + "description": "fs:scope-public -> This scope permits access to all files and list content of top level directories in the `$PUBLIC`folder.", + "type": "string", + "enum": [ + "fs:scope-public" + ] + }, + { + "description": "fs:scope-public-index -> This scope permits to list all files and folders in the `$PUBLIC`folder.", + "type": "string", + "enum": [ + "fs:scope-public-index" + ] + }, + { + "description": "fs:scope-public-recursive -> This scope recursive access to the complete `$PUBLIC` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-public-recursive" + ] + }, + { + "description": "fs:scope-resource -> This scope permits access to all files and list content of top level directories in the `$RESOURCE`folder.", + "type": "string", + "enum": [ + "fs:scope-resource" + ] + }, + { + "description": "fs:scope-resource-index -> This scope permits to list all files and folders in the `$RESOURCE`folder.", + "type": "string", + "enum": [ + "fs:scope-resource-index" + ] + }, + { + "description": "fs:scope-resource-recursive -> This scope recursive access to the complete `$RESOURCE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-resource-recursive" + ] + }, + { + "description": "fs:scope-runtime -> This scope permits access to all files and list content of top level directories in the `$RUNTIME`folder.", + "type": "string", + "enum": [ + "fs:scope-runtime" + ] + }, + { + "description": "fs:scope-runtime-index -> This scope permits to list all files and folders in the `$RUNTIME`folder.", + "type": "string", + "enum": [ + "fs:scope-runtime-index" + ] + }, + { + "description": "fs:scope-runtime-recursive -> This scope recursive access to the complete `$RUNTIME` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-runtime-recursive" + ] + }, + { + "description": "fs:scope-temp -> This scope permits access to all files and list content of top level directories in the `$TEMP`folder.", + "type": "string", + "enum": [ + "fs:scope-temp" + ] + }, + { + "description": "fs:scope-temp-index -> This scope permits to list all files and folders in the `$TEMP`folder.", + "type": "string", + "enum": [ + "fs:scope-temp-index" + ] + }, + { + "description": "fs:scope-temp-recursive -> This scope recursive access to the complete `$TEMP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-temp-recursive" + ] + }, + { + "description": "fs:scope-template -> This scope permits access to all files and list content of top level directories in the `$TEMPLATE`folder.", + "type": "string", + "enum": [ + "fs:scope-template" + ] + }, + { + "description": "fs:scope-template-index -> This scope permits to list all files and folders in the `$TEMPLATE`folder.", + "type": "string", + "enum": [ + "fs:scope-template-index" + ] + }, + { + "description": "fs:scope-template-recursive -> This scope recursive access to the complete `$TEMPLATE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-template-recursive" + ] + }, + { + "description": "fs:scope-video -> This scope permits access to all files and list content of top level directories in the `$VIDEO`folder.", + "type": "string", + "enum": [ + "fs:scope-video" + ] + }, + { + "description": "fs:scope-video-index -> This scope permits to list all files and folders in the `$VIDEO`folder.", + "type": "string", + "enum": [ + "fs:scope-video-index" + ] + }, + { + "description": "fs:scope-video-recursive -> This scope recursive access to the complete `$VIDEO` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-video-recursive" + ] + }, + { + "description": "fs:write-all -> This enables all write related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:write-all" + ] + }, + { + "description": "fs:write-files -> This enables all file write related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:write-files" + ] + } + ] + }, + "allow": { + "items": { + "title": "FsScopeEntry", + "description": "FS scope entry.", + "anyOf": [ + { + "description": "FS scope path.", + "type": "string" + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "FS scope path.", + "type": "string" + } + } + } + ] + } + }, + "deny": { + "items": { + "title": "FsScopeEntry", + "description": "FS scope entry.", + "anyOf": [ + { + "description": "FS scope path.", + "type": "string" + }, + { + "type": "object", + "required": [ + "path" + ], + "properties": { + "path": { + "description": "FS scope path.", + "type": "string" + } + } + } + ] + } + } + } + }, + { + "type": "object", + "required": [ + "identifier" + ], + "properties": { + "identifier": { + "oneOf": [ + { + "type": "string", + "enum": [ + "shell:default" + ] + }, + { + "description": "shell:allow-execute -> Enables the execute command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-execute" + ] + }, + { + "description": "shell:allow-kill -> Enables the kill command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-kill" + ] + }, + { + "description": "shell:allow-open -> Enables the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-open" + ] + }, + { + "description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-stdin-write" + ] + }, + { + "description": "shell:deny-execute -> Denies the execute command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-execute" + ] + }, + { + "description": "shell:deny-kill -> Denies the kill command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-kill" + ] + }, + { + "description": "shell:deny-open -> Denies the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-open" + ] + }, + { + "description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-stdin-write" + ] + } + ] + }, + "allow": { + "items": { + "title": "Entry", + "description": "A command allowed to be executed by the webview API.", + "type": "object", + "required": [ + "args", + "cmd", + "name", + "sidecar" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellAllowedArgs" + } + ] + }, + "cmd": { + "description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + }, + "sidecar": { + "description": "If this command is a sidecar command.", + "type": "boolean" + } + } + } + }, + "deny": { + "items": { + "title": "Entry", + "description": "A command allowed to be executed by the webview API.", + "type": "object", + "required": [ + "args", + "cmd", + "name", + "sidecar" + ], + "properties": { + "args": { + "description": "The allowed arguments for the command execution.", + "allOf": [ + { + "$ref": "#/definitions/ShellAllowedArgs" + } + ] + }, + "cmd": { + "description": "The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.", + "type": "string" + }, + "name": { + "description": "The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.", + "type": "string" + }, + "sidecar": { + "description": "If this command is a sidecar command.", + "type": "boolean" + } + } + } + } + } + } + ] + } + ] + }, + "Identifier": { + "oneOf": [ + { + "description": "app:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "app:default" + ] + }, + { + "description": "app:allow-app-hide -> Enables the app_hide command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:allow-app-hide" + ] + }, + { + "description": "app:allow-app-show -> Enables the app_show command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:allow-app-show" + ] + }, + { + "description": "app:allow-name -> Enables the name command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:allow-name" + ] + }, + { + "description": "app:allow-tauri-version -> Enables the tauri_version command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:allow-tauri-version" + ] + }, + { + "description": "app:allow-version -> Enables the version command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:allow-version" + ] + }, + { + "description": "app:deny-app-hide -> Denies the app_hide command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:deny-app-hide" + ] + }, + { + "description": "app:deny-app-show -> Denies the app_show command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:deny-app-show" + ] + }, + { + "description": "app:deny-name -> Denies the name command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:deny-name" + ] + }, + { + "description": "app:deny-tauri-version -> Denies the tauri_version command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:deny-tauri-version" + ] + }, + { + "description": "app:deny-version -> Denies the version command without any pre-configured scope.", + "type": "string", + "enum": [ + "app:deny-version" + ] + }, + { + "type": "string", + "enum": [ + "clipboard-manager:default" + ] + }, + { + "description": "clipboard-manager:allow-clear -> Enables the clear command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-clear" + ] + }, + { + "description": "clipboard-manager:allow-read-image -> Enables the read_image command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-read-image" + ] + }, + { + "description": "clipboard-manager:allow-read-text -> Enables the read_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-read-text" + ] + }, + { + "description": "clipboard-manager:allow-write-html -> Enables the write_html command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-write-html" + ] + }, + { + "description": "clipboard-manager:allow-write-image -> Enables the write_image command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-write-image" + ] + }, + { + "description": "clipboard-manager:allow-write-text -> Enables the write_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:allow-write-text" + ] + }, + { + "description": "clipboard-manager:deny-clear -> Denies the clear command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-clear" + ] + }, + { + "description": "clipboard-manager:deny-read-image -> Denies the read_image command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-read-image" + ] + }, + { + "description": "clipboard-manager:deny-read-text -> Denies the read_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-read-text" + ] + }, + { + "description": "clipboard-manager:deny-write-html -> Denies the write_html command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-write-html" + ] + }, + { + "description": "clipboard-manager:deny-write-image -> Denies the write_image command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-write-image" + ] + }, + { + "description": "clipboard-manager:deny-write-text -> Denies the write_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "clipboard-manager:deny-write-text" + ] + }, + { + "type": "string", + "enum": [ + "dialog:default" + ] + }, + { + "description": "dialog:allow-ask -> Enables the ask command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:allow-ask" + ] + }, + { + "description": "dialog:allow-confirm -> Enables the confirm command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:allow-confirm" + ] + }, + { + "description": "dialog:allow-message -> Enables the message command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:allow-message" + ] + }, + { + "description": "dialog:allow-open -> Enables the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:allow-open" + ] + }, + { + "description": "dialog:allow-save -> Enables the save command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:allow-save" + ] + }, + { + "description": "dialog:deny-ask -> Denies the ask command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:deny-ask" + ] + }, + { + "description": "dialog:deny-confirm -> Denies the confirm command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:deny-confirm" + ] + }, + { + "description": "dialog:deny-message -> Denies the message command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:deny-message" + ] + }, + { + "description": "dialog:deny-open -> Denies the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:deny-open" + ] + }, + { + "description": "dialog:deny-save -> Denies the save command without any pre-configured scope.", + "type": "string", + "enum": [ + "dialog:deny-save" + ] + }, + { + "description": "event:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "event:default" + ] + }, + { + "description": "event:allow-emit -> Enables the emit command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:allow-emit" + ] + }, + { + "description": "event:allow-emit-to -> Enables the emit_to command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:allow-emit-to" + ] + }, + { + "description": "event:allow-listen -> Enables the listen command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:allow-listen" + ] + }, + { + "description": "event:allow-unlisten -> Enables the unlisten command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:allow-unlisten" + ] + }, + { + "description": "event:deny-emit -> Denies the emit command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:deny-emit" + ] + }, + { + "description": "event:deny-emit-to -> Denies the emit_to command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:deny-emit-to" + ] + }, + { + "description": "event:deny-listen -> Denies the listen command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:deny-listen" + ] + }, + { + "description": "event:deny-unlisten -> Denies the unlisten command without any pre-configured scope.", + "type": "string", + "enum": [ + "event:deny-unlisten" + ] + }, + { + "description": "fs:allow-app-meta -> This allows non-recursive read access to metadata of the `$APP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-app-meta" + ] + }, + { + "description": "fs:allow-app-meta-recursive -> This allows full recursive read access to metadata of the `$APP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-app-meta-recursive" + ] + }, + { + "description": "fs:allow-app-read -> This allows non-recursive read access to the `$APP` folder.", + "type": "string", + "enum": [ + "fs:allow-app-read" + ] + }, + { + "description": "fs:allow-app-read-recursive -> This allows full recursive read access to the complete `$APP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-app-read-recursive" + ] + }, + { + "description": "fs:allow-app-write -> This allows non-recursive write access to the `$APP` folder.", + "type": "string", + "enum": [ + "fs:allow-app-write" + ] + }, + { + "description": "fs:allow-app-write-recursive -> This allows full recursive write access to the complete `$APP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-app-write-recursive" + ] + }, + { + "description": "fs:allow-appcache-meta -> This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appcache-meta" + ] + }, + { + "description": "fs:allow-appcache-meta-recursive -> This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appcache-meta-recursive" + ] + }, + { + "description": "fs:allow-appcache-read -> This allows non-recursive read access to the `$APPCACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-appcache-read" + ] + }, + { + "description": "fs:allow-appcache-read-recursive -> This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appcache-read-recursive" + ] + }, + { + "description": "fs:allow-appcache-write -> This allows non-recursive write access to the `$APPCACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-appcache-write" + ] + }, + { + "description": "fs:allow-appcache-write-recursive -> This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appcache-write-recursive" + ] + }, + { + "description": "fs:allow-appconfig-meta -> This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appconfig-meta" + ] + }, + { + "description": "fs:allow-appconfig-meta-recursive -> This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appconfig-meta-recursive" + ] + }, + { + "description": "fs:allow-appconfig-read -> This allows non-recursive read access to the `$APPCONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-appconfig-read" + ] + }, + { + "description": "fs:allow-appconfig-read-recursive -> This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appconfig-read-recursive" + ] + }, + { + "description": "fs:allow-appconfig-write -> This allows non-recursive write access to the `$APPCONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-appconfig-write" + ] + }, + { + "description": "fs:allow-appconfig-write-recursive -> This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appconfig-write-recursive" + ] + }, + { + "description": "fs:allow-appdata-meta -> This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appdata-meta" + ] + }, + { + "description": "fs:allow-appdata-meta-recursive -> This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-appdata-meta-recursive" + ] + }, + { + "description": "fs:allow-appdata-read -> This allows non-recursive read access to the `$APPDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-appdata-read" + ] + }, + { + "description": "fs:allow-appdata-read-recursive -> This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appdata-read-recursive" + ] + }, + { + "description": "fs:allow-appdata-write -> This allows non-recursive write access to the `$APPDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-appdata-write" + ] + }, + { + "description": "fs:allow-appdata-write-recursive -> This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-appdata-write-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-meta -> This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-meta" + ] + }, + { + "description": "fs:allow-applocaldata-meta-recursive -> This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-meta-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-read -> This allows non-recursive read access to the `$APPLOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-read" + ] + }, + { + "description": "fs:allow-applocaldata-read-recursive -> This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-read-recursive" + ] + }, + { + "description": "fs:allow-applocaldata-write -> This allows non-recursive write access to the `$APPLOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-write" + ] + }, + { + "description": "fs:allow-applocaldata-write-recursive -> This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applocaldata-write-recursive" + ] + }, + { + "description": "fs:allow-applog-meta -> This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applog-meta" + ] + }, + { + "description": "fs:allow-applog-meta-recursive -> This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-applog-meta-recursive" + ] + }, + { + "description": "fs:allow-applog-read -> This allows non-recursive read access to the `$APPLOG` folder.", + "type": "string", + "enum": [ + "fs:allow-applog-read" + ] + }, + { + "description": "fs:allow-applog-read-recursive -> This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applog-read-recursive" + ] + }, + { + "description": "fs:allow-applog-write -> This allows non-recursive write access to the `$APPLOG` folder.", + "type": "string", + "enum": [ + "fs:allow-applog-write" + ] + }, + { + "description": "fs:allow-applog-write-recursive -> This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-applog-write-recursive" + ] + }, + { + "description": "fs:allow-audio-meta -> This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-audio-meta" + ] + }, + { + "description": "fs:allow-audio-meta-recursive -> This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-audio-meta-recursive" + ] + }, + { + "description": "fs:allow-audio-read -> This allows non-recursive read access to the `$AUDIO` folder.", + "type": "string", + "enum": [ + "fs:allow-audio-read" + ] + }, + { + "description": "fs:allow-audio-read-recursive -> This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-audio-read-recursive" + ] + }, + { + "description": "fs:allow-audio-write -> This allows non-recursive write access to the `$AUDIO` folder.", + "type": "string", + "enum": [ + "fs:allow-audio-write" + ] + }, + { + "description": "fs:allow-audio-write-recursive -> This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-audio-write-recursive" + ] + }, + { + "description": "fs:allow-cache-meta -> This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-cache-meta" + ] + }, + { + "description": "fs:allow-cache-meta-recursive -> This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-cache-meta-recursive" + ] + }, + { + "description": "fs:allow-cache-read -> This allows non-recursive read access to the `$CACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-cache-read" + ] + }, + { + "description": "fs:allow-cache-read-recursive -> This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-cache-read-recursive" + ] + }, + { + "description": "fs:allow-cache-write -> This allows non-recursive write access to the `$CACHE` folder.", + "type": "string", + "enum": [ + "fs:allow-cache-write" + ] + }, + { + "description": "fs:allow-cache-write-recursive -> This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-cache-write-recursive" + ] + }, + { + "description": "fs:allow-config-meta -> This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-config-meta" + ] + }, + { + "description": "fs:allow-config-meta-recursive -> This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-config-meta-recursive" + ] + }, + { + "description": "fs:allow-config-read -> This allows non-recursive read access to the `$CONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-config-read" + ] + }, + { + "description": "fs:allow-config-read-recursive -> This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-config-read-recursive" + ] + }, + { + "description": "fs:allow-config-write -> This allows non-recursive write access to the `$CONFIG` folder.", + "type": "string", + "enum": [ + "fs:allow-config-write" + ] + }, + { + "description": "fs:allow-config-write-recursive -> This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-config-write-recursive" + ] + }, + { + "description": "fs:allow-data-meta -> This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-data-meta" + ] + }, + { + "description": "fs:allow-data-meta-recursive -> This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-data-meta-recursive" + ] + }, + { + "description": "fs:allow-data-read -> This allows non-recursive read access to the `$DATA` folder.", + "type": "string", + "enum": [ + "fs:allow-data-read" + ] + }, + { + "description": "fs:allow-data-read-recursive -> This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-data-read-recursive" + ] + }, + { + "description": "fs:allow-data-write -> This allows non-recursive write access to the `$DATA` folder.", + "type": "string", + "enum": [ + "fs:allow-data-write" + ] + }, + { + "description": "fs:allow-data-write-recursive -> This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-data-write-recursive" + ] + }, + { + "description": "fs:allow-desktop-meta -> This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-desktop-meta" + ] + }, + { + "description": "fs:allow-desktop-meta-recursive -> This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-desktop-meta-recursive" + ] + }, + { + "description": "fs:allow-desktop-read -> This allows non-recursive read access to the `$DESKTOP` folder.", + "type": "string", + "enum": [ + "fs:allow-desktop-read" + ] + }, + { + "description": "fs:allow-desktop-read-recursive -> This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-desktop-read-recursive" + ] + }, + { + "description": "fs:allow-desktop-write -> This allows non-recursive write access to the `$DESKTOP` folder.", + "type": "string", + "enum": [ + "fs:allow-desktop-write" + ] + }, + { + "description": "fs:allow-desktop-write-recursive -> This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-desktop-write-recursive" + ] + }, + { + "description": "fs:allow-document-meta -> This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-document-meta" + ] + }, + { + "description": "fs:allow-document-meta-recursive -> This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-document-meta-recursive" + ] + }, + { + "description": "fs:allow-document-read -> This allows non-recursive read access to the `$DOCUMENT` folder.", + "type": "string", + "enum": [ + "fs:allow-document-read" + ] + }, + { + "description": "fs:allow-document-read-recursive -> This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-document-read-recursive" + ] + }, + { + "description": "fs:allow-document-write -> This allows non-recursive write access to the `$DOCUMENT` folder.", + "type": "string", + "enum": [ + "fs:allow-document-write" + ] + }, + { + "description": "fs:allow-document-write-recursive -> This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-document-write-recursive" + ] + }, + { + "description": "fs:allow-download-meta -> This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-download-meta" + ] + }, + { + "description": "fs:allow-download-meta-recursive -> This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-download-meta-recursive" + ] + }, + { + "description": "fs:allow-download-read -> This allows non-recursive read access to the `$DOWNLOAD` folder.", + "type": "string", + "enum": [ + "fs:allow-download-read" + ] + }, + { + "description": "fs:allow-download-read-recursive -> This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-download-read-recursive" + ] + }, + { + "description": "fs:allow-download-write -> This allows non-recursive write access to the `$DOWNLOAD` folder.", + "type": "string", + "enum": [ + "fs:allow-download-write" + ] + }, + { + "description": "fs:allow-download-write-recursive -> This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-download-write-recursive" + ] + }, + { + "description": "fs:allow-exe-meta -> This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-exe-meta" + ] + }, + { + "description": "fs:allow-exe-meta-recursive -> This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-exe-meta-recursive" + ] + }, + { + "description": "fs:allow-exe-read -> This allows non-recursive read access to the `$EXE` folder.", + "type": "string", + "enum": [ + "fs:allow-exe-read" + ] + }, + { + "description": "fs:allow-exe-read-recursive -> This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-exe-read-recursive" + ] + }, + { + "description": "fs:allow-exe-write -> This allows non-recursive write access to the `$EXE` folder.", + "type": "string", + "enum": [ + "fs:allow-exe-write" + ] + }, + { + "description": "fs:allow-exe-write-recursive -> This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-exe-write-recursive" + ] + }, + { + "description": "fs:allow-font-meta -> This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-font-meta" + ] + }, + { + "description": "fs:allow-font-meta-recursive -> This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-font-meta-recursive" + ] + }, + { + "description": "fs:allow-font-read -> This allows non-recursive read access to the `$FONT` folder.", + "type": "string", + "enum": [ + "fs:allow-font-read" + ] + }, + { + "description": "fs:allow-font-read-recursive -> This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-font-read-recursive" + ] + }, + { + "description": "fs:allow-font-write -> This allows non-recursive write access to the `$FONT` folder.", + "type": "string", + "enum": [ + "fs:allow-font-write" + ] + }, + { + "description": "fs:allow-font-write-recursive -> This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-font-write-recursive" + ] + }, + { + "description": "fs:allow-home-meta -> This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-home-meta" + ] + }, + { + "description": "fs:allow-home-meta-recursive -> This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-home-meta-recursive" + ] + }, + { + "description": "fs:allow-home-read -> This allows non-recursive read access to the `$HOME` folder.", + "type": "string", + "enum": [ + "fs:allow-home-read" + ] + }, + { + "description": "fs:allow-home-read-recursive -> This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-home-read-recursive" + ] + }, + { + "description": "fs:allow-home-write -> This allows non-recursive write access to the `$HOME` folder.", + "type": "string", + "enum": [ + "fs:allow-home-write" + ] + }, + { + "description": "fs:allow-home-write-recursive -> This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-home-write-recursive" + ] + }, + { + "description": "fs:allow-localdata-meta -> This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-localdata-meta" + ] + }, + { + "description": "fs:allow-localdata-meta-recursive -> This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-localdata-meta-recursive" + ] + }, + { + "description": "fs:allow-localdata-read -> This allows non-recursive read access to the `$LOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-localdata-read" + ] + }, + { + "description": "fs:allow-localdata-read-recursive -> This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-localdata-read-recursive" + ] + }, + { + "description": "fs:allow-localdata-write -> This allows non-recursive write access to the `$LOCALDATA` folder.", + "type": "string", + "enum": [ + "fs:allow-localdata-write" + ] + }, + { + "description": "fs:allow-localdata-write-recursive -> This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-localdata-write-recursive" + ] + }, + { + "description": "fs:allow-log-meta -> This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-log-meta" + ] + }, + { + "description": "fs:allow-log-meta-recursive -> This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-log-meta-recursive" + ] + }, + { + "description": "fs:allow-log-read -> This allows non-recursive read access to the `$LOG` folder.", + "type": "string", + "enum": [ + "fs:allow-log-read" + ] + }, + { + "description": "fs:allow-log-read-recursive -> This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-log-read-recursive" + ] + }, + { + "description": "fs:allow-log-write -> This allows non-recursive write access to the `$LOG` folder.", + "type": "string", + "enum": [ + "fs:allow-log-write" + ] + }, + { + "description": "fs:allow-log-write-recursive -> This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-log-write-recursive" + ] + }, + { + "description": "fs:allow-picture-meta -> This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-picture-meta" + ] + }, + { + "description": "fs:allow-picture-meta-recursive -> This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-picture-meta-recursive" + ] + }, + { + "description": "fs:allow-picture-read -> This allows non-recursive read access to the `$PICTURE` folder.", + "type": "string", + "enum": [ + "fs:allow-picture-read" + ] + }, + { + "description": "fs:allow-picture-read-recursive -> This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-picture-read-recursive" + ] + }, + { + "description": "fs:allow-picture-write -> This allows non-recursive write access to the `$PICTURE` folder.", + "type": "string", + "enum": [ + "fs:allow-picture-write" + ] + }, + { + "description": "fs:allow-picture-write-recursive -> This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-picture-write-recursive" + ] + }, + { + "description": "fs:allow-public-meta -> This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-public-meta" + ] + }, + { + "description": "fs:allow-public-meta-recursive -> This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-public-meta-recursive" + ] + }, + { + "description": "fs:allow-public-read -> This allows non-recursive read access to the `$PUBLIC` folder.", + "type": "string", + "enum": [ + "fs:allow-public-read" + ] + }, + { + "description": "fs:allow-public-read-recursive -> This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-public-read-recursive" + ] + }, + { + "description": "fs:allow-public-write -> This allows non-recursive write access to the `$PUBLIC` folder.", + "type": "string", + "enum": [ + "fs:allow-public-write" + ] + }, + { + "description": "fs:allow-public-write-recursive -> This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-public-write-recursive" + ] + }, + { + "description": "fs:allow-resource-meta -> This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-resource-meta" + ] + }, + { + "description": "fs:allow-resource-meta-recursive -> This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-resource-meta-recursive" + ] + }, + { + "description": "fs:allow-resource-read -> This allows non-recursive read access to the `$RESOURCE` folder.", + "type": "string", + "enum": [ + "fs:allow-resource-read" + ] + }, + { + "description": "fs:allow-resource-read-recursive -> This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-resource-read-recursive" + ] + }, + { + "description": "fs:allow-resource-write -> This allows non-recursive write access to the `$RESOURCE` folder.", + "type": "string", + "enum": [ + "fs:allow-resource-write" + ] + }, + { + "description": "fs:allow-resource-write-recursive -> This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-resource-write-recursive" + ] + }, + { + "description": "fs:allow-runtime-meta -> This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-runtime-meta" + ] + }, + { + "description": "fs:allow-runtime-meta-recursive -> This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-runtime-meta-recursive" + ] + }, + { + "description": "fs:allow-runtime-read -> This allows non-recursive read access to the `$RUNTIME` folder.", + "type": "string", + "enum": [ + "fs:allow-runtime-read" + ] + }, + { + "description": "fs:allow-runtime-read-recursive -> This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-runtime-read-recursive" + ] + }, + { + "description": "fs:allow-runtime-write -> This allows non-recursive write access to the `$RUNTIME` folder.", + "type": "string", + "enum": [ + "fs:allow-runtime-write" + ] + }, + { + "description": "fs:allow-runtime-write-recursive -> This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-runtime-write-recursive" + ] + }, + { + "description": "fs:allow-temp-meta -> This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-temp-meta" + ] + }, + { + "description": "fs:allow-temp-meta-recursive -> This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-temp-meta-recursive" + ] + }, + { + "description": "fs:allow-temp-read -> This allows non-recursive read access to the `$TEMP` folder.", + "type": "string", + "enum": [ + "fs:allow-temp-read" + ] + }, + { + "description": "fs:allow-temp-read-recursive -> This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-temp-read-recursive" + ] + }, + { + "description": "fs:allow-temp-write -> This allows non-recursive write access to the `$TEMP` folder.", + "type": "string", + "enum": [ + "fs:allow-temp-write" + ] + }, + { + "description": "fs:allow-temp-write-recursive -> This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-temp-write-recursive" + ] + }, + { + "description": "fs:allow-template-meta -> This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-template-meta" + ] + }, + { + "description": "fs:allow-template-meta-recursive -> This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-template-meta-recursive" + ] + }, + { + "description": "fs:allow-template-read -> This allows non-recursive read access to the `$TEMPLATE` folder.", + "type": "string", + "enum": [ + "fs:allow-template-read" + ] + }, + { + "description": "fs:allow-template-read-recursive -> This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-template-read-recursive" + ] + }, + { + "description": "fs:allow-template-write -> This allows non-recursive write access to the `$TEMPLATE` folder.", + "type": "string", + "enum": [ + "fs:allow-template-write" + ] + }, + { + "description": "fs:allow-template-write-recursive -> This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-template-write-recursive" + ] + }, + { + "description": "fs:allow-video-meta -> This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-video-meta" + ] + }, + { + "description": "fs:allow-video-meta-recursive -> This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.", + "type": "string", + "enum": [ + "fs:allow-video-meta-recursive" + ] + }, + { + "description": "fs:allow-video-read -> This allows non-recursive read access to the `$VIDEO` folder.", + "type": "string", + "enum": [ + "fs:allow-video-read" + ] + }, + { + "description": "fs:allow-video-read-recursive -> This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-video-read-recursive" + ] + }, + { + "description": "fs:allow-video-write -> This allows non-recursive write access to the `$VIDEO` folder.", + "type": "string", + "enum": [ + "fs:allow-video-write" + ] + }, + { + "description": "fs:allow-video-write-recursive -> This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.", + "type": "string", + "enum": [ + "fs:allow-video-write-recursive" + ] + }, + { + "description": "fs:deny-default -> This denies access to dangerous Tauri relevant files and folders by default.", + "type": "string", + "enum": [ + "fs:deny-default" + ] + }, + { + "description": "fs:default -> # Tauri `fs` default permissions\n\nThis configuration file defines the default permissions granted\nto the filesystem.\n\n### Granted Permissions\n\nThis default permission set enables all read-related commands and\nallows access to the `$APP` folder and sub directories created in it.\nThe location of the `$APP` folder depends on the operating system,\nwhere the application is run.\n\nIn general the `$APP` folder needs to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\n### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n", + "type": "string", + "enum": [ + "fs:default" + ] + }, + { + "description": "fs:allow-copy-file -> Enables the copy_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-copy-file" + ] + }, + { + "description": "fs:allow-create -> Enables the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-create" + ] + }, + { + "description": "fs:allow-exists -> Enables the exists command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-exists" + ] + }, + { + "description": "fs:allow-fstat -> Enables the fstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-fstat" + ] + }, + { + "description": "fs:allow-ftruncate -> Enables the ftruncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-ftruncate" + ] + }, + { + "description": "fs:allow-lstat -> Enables the lstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-lstat" + ] + }, + { + "description": "fs:allow-mkdir -> Enables the mkdir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-mkdir" + ] + }, + { + "description": "fs:allow-open -> Enables the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-open" + ] + }, + { + "description": "fs:allow-read -> Enables the read command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read" + ] + }, + { + "description": "fs:allow-read-dir -> Enables the read_dir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-dir" + ] + }, + { + "description": "fs:allow-read-file -> Enables the read_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-file" + ] + }, + { + "description": "fs:allow-read-text-file -> Enables the read_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file" + ] + }, + { + "description": "fs:allow-read-text-file-lines -> Enables the read_text_file_lines command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file-lines" + ] + }, + { + "description": "fs:allow-read-text-file-lines-next -> Enables the read_text_file_lines_next command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-read-text-file-lines-next" + ] + }, + { + "description": "fs:allow-remove -> Enables the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-remove" + ] + }, + { + "description": "fs:allow-rename -> Enables the rename command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-rename" + ] + }, + { + "description": "fs:allow-seek -> Enables the seek command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-seek" + ] + }, + { + "description": "fs:allow-stat -> Enables the stat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-stat" + ] + }, + { + "description": "fs:allow-truncate -> Enables the truncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-truncate" + ] + }, + { + "description": "fs:allow-unwatch -> Enables the unwatch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-unwatch" + ] + }, + { + "description": "fs:allow-watch -> Enables the watch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-watch" + ] + }, + { + "description": "fs:allow-write -> Enables the write command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write" + ] + }, + { + "description": "fs:allow-write-file -> Enables the write_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write-file" + ] + }, + { + "description": "fs:allow-write-text-file -> Enables the write_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:allow-write-text-file" + ] + }, + { + "description": "fs:deny-copy-file -> Denies the copy_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-copy-file" + ] + }, + { + "description": "fs:deny-create -> Denies the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-create" + ] + }, + { + "description": "fs:deny-exists -> Denies the exists command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-exists" + ] + }, + { + "description": "fs:deny-fstat -> Denies the fstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-fstat" + ] + }, + { + "description": "fs:deny-ftruncate -> Denies the ftruncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-ftruncate" + ] + }, + { + "description": "fs:deny-lstat -> Denies the lstat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-lstat" + ] + }, + { + "description": "fs:deny-mkdir -> Denies the mkdir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-mkdir" + ] + }, + { + "description": "fs:deny-open -> Denies the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-open" + ] + }, + { + "description": "fs:deny-read -> Denies the read command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read" + ] + }, + { + "description": "fs:deny-read-dir -> Denies the read_dir command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-dir" + ] + }, + { + "description": "fs:deny-read-file -> Denies the read_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-file" + ] + }, + { + "description": "fs:deny-read-text-file -> Denies the read_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file" + ] + }, + { + "description": "fs:deny-read-text-file-lines -> Denies the read_text_file_lines command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file-lines" + ] + }, + { + "description": "fs:deny-read-text-file-lines-next -> Denies the read_text_file_lines_next command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-read-text-file-lines-next" + ] + }, + { + "description": "fs:deny-remove -> Denies the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-remove" + ] + }, + { + "description": "fs:deny-rename -> Denies the rename command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-rename" + ] + }, + { + "description": "fs:deny-seek -> Denies the seek command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-seek" + ] + }, + { + "description": "fs:deny-stat -> Denies the stat command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-stat" + ] + }, + { + "description": "fs:deny-truncate -> Denies the truncate command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-truncate" + ] + }, + { + "description": "fs:deny-unwatch -> Denies the unwatch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-unwatch" + ] + }, + { + "description": "fs:deny-watch -> Denies the watch command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-watch" + ] + }, + { + "description": "fs:deny-webview-data-linux -> This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.", + "type": "string", + "enum": [ + "fs:deny-webview-data-linux" + ] + }, + { + "description": "fs:deny-webview-data-windows -> This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.", + "type": "string", + "enum": [ + "fs:deny-webview-data-windows" + ] + }, + { + "description": "fs:deny-write -> Denies the write command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write" + ] + }, + { + "description": "fs:deny-write-file -> Denies the write_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write-file" + ] + }, + { + "description": "fs:deny-write-text-file -> Denies the write_text_file command without any pre-configured scope.", + "type": "string", + "enum": [ + "fs:deny-write-text-file" + ] + }, + { + "description": "fs:read-all -> This enables all read related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-all" + ] + }, + { + "description": "fs:read-dirs -> This enables directory read and file metadata related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-dirs" + ] + }, + { + "description": "fs:read-files -> This enables file read related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-files" + ] + }, + { + "description": "fs:read-meta -> This enables all index or metadata related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:read-meta" + ] + }, + { + "description": "fs:scope -> An empty permission you can use to modify the global scope.", + "type": "string", + "enum": [ + "fs:scope" + ] + }, + { + "description": "fs:scope-app -> This scope permits access to all files and list content of top level directories in the `$APP`folder.", + "type": "string", + "enum": [ + "fs:scope-app" + ] + }, + { + "description": "fs:scope-app-index -> This scope permits to list all files and folders in the `$APP`folder.", + "type": "string", + "enum": [ + "fs:scope-app-index" + ] + }, + { + "description": "fs:scope-app-recursive -> This scope recursive access to the complete `$APP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-app-recursive" + ] + }, + { + "description": "fs:scope-appcache -> This scope permits access to all files and list content of top level directories in the `$APPCACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-appcache" + ] + }, + { + "description": "fs:scope-appcache-index -> This scope permits to list all files and folders in the `$APPCACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-appcache-index" + ] + }, + { + "description": "fs:scope-appcache-recursive -> This scope recursive access to the complete `$APPCACHE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appcache-recursive" + ] + }, + { + "description": "fs:scope-appconfig -> This scope permits access to all files and list content of top level directories in the `$APPCONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-appconfig" + ] + }, + { + "description": "fs:scope-appconfig-index -> This scope permits to list all files and folders in the `$APPCONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-appconfig-index" + ] + }, + { + "description": "fs:scope-appconfig-recursive -> This scope recursive access to the complete `$APPCONFIG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appconfig-recursive" + ] + }, + { + "description": "fs:scope-appdata -> This scope permits access to all files and list content of top level directories in the `$APPDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-appdata" + ] + }, + { + "description": "fs:scope-appdata-index -> This scope permits to list all files and folders in the `$APPDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-appdata-index" + ] + }, + { + "description": "fs:scope-appdata-recursive -> This scope recursive access to the complete `$APPDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-appdata-recursive" + ] + }, + { + "description": "fs:scope-applocaldata -> This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-applocaldata" + ] + }, + { + "description": "fs:scope-applocaldata-index -> This scope permits to list all files and folders in the `$APPLOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-applocaldata-index" + ] + }, + { + "description": "fs:scope-applocaldata-recursive -> This scope recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-applocaldata-recursive" + ] + }, + { + "description": "fs:scope-applog -> This scope permits access to all files and list content of top level directories in the `$APPLOG`folder.", + "type": "string", + "enum": [ + "fs:scope-applog" + ] + }, + { + "description": "fs:scope-applog-index -> This scope permits to list all files and folders in the `$APPLOG`folder.", + "type": "string", + "enum": [ + "fs:scope-applog-index" + ] + }, + { + "description": "fs:scope-applog-recursive -> This scope recursive access to the complete `$APPLOG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-applog-recursive" + ] + }, + { + "description": "fs:scope-audio -> This scope permits access to all files and list content of top level directories in the `$AUDIO`folder.", + "type": "string", + "enum": [ + "fs:scope-audio" + ] + }, + { + "description": "fs:scope-audio-index -> This scope permits to list all files and folders in the `$AUDIO`folder.", + "type": "string", + "enum": [ + "fs:scope-audio-index" + ] + }, + { + "description": "fs:scope-audio-recursive -> This scope recursive access to the complete `$AUDIO` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-audio-recursive" + ] + }, + { + "description": "fs:scope-cache -> This scope permits access to all files and list content of top level directories in the `$CACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-cache" + ] + }, + { + "description": "fs:scope-cache-index -> This scope permits to list all files and folders in the `$CACHE`folder.", + "type": "string", + "enum": [ + "fs:scope-cache-index" + ] + }, + { + "description": "fs:scope-cache-recursive -> This scope recursive access to the complete `$CACHE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-cache-recursive" + ] + }, + { + "description": "fs:scope-config -> This scope permits access to all files and list content of top level directories in the `$CONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-config" + ] + }, + { + "description": "fs:scope-config-index -> This scope permits to list all files and folders in the `$CONFIG`folder.", + "type": "string", + "enum": [ + "fs:scope-config-index" + ] + }, + { + "description": "fs:scope-config-recursive -> This scope recursive access to the complete `$CONFIG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-config-recursive" + ] + }, + { + "description": "fs:scope-data -> This scope permits access to all files and list content of top level directories in the `$DATA`folder.", + "type": "string", + "enum": [ + "fs:scope-data" + ] + }, + { + "description": "fs:scope-data-index -> This scope permits to list all files and folders in the `$DATA`folder.", + "type": "string", + "enum": [ + "fs:scope-data-index" + ] + }, + { + "description": "fs:scope-data-recursive -> This scope recursive access to the complete `$DATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-data-recursive" + ] + }, + { + "description": "fs:scope-desktop -> This scope permits access to all files and list content of top level directories in the `$DESKTOP`folder.", + "type": "string", + "enum": [ + "fs:scope-desktop" + ] + }, + { + "description": "fs:scope-desktop-index -> This scope permits to list all files and folders in the `$DESKTOP`folder.", + "type": "string", + "enum": [ + "fs:scope-desktop-index" + ] + }, + { + "description": "fs:scope-desktop-recursive -> This scope recursive access to the complete `$DESKTOP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-desktop-recursive" + ] + }, + { + "description": "fs:scope-document -> This scope permits access to all files and list content of top level directories in the `$DOCUMENT`folder.", + "type": "string", + "enum": [ + "fs:scope-document" + ] + }, + { + "description": "fs:scope-document-index -> This scope permits to list all files and folders in the `$DOCUMENT`folder.", + "type": "string", + "enum": [ + "fs:scope-document-index" + ] + }, + { + "description": "fs:scope-document-recursive -> This scope recursive access to the complete `$DOCUMENT` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-document-recursive" + ] + }, + { + "description": "fs:scope-download -> This scope permits access to all files and list content of top level directories in the `$DOWNLOAD`folder.", + "type": "string", + "enum": [ + "fs:scope-download" + ] + }, + { + "description": "fs:scope-download-index -> This scope permits to list all files and folders in the `$DOWNLOAD`folder.", + "type": "string", + "enum": [ + "fs:scope-download-index" + ] + }, + { + "description": "fs:scope-download-recursive -> This scope recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-download-recursive" + ] + }, + { + "description": "fs:scope-exe -> This scope permits access to all files and list content of top level directories in the `$EXE`folder.", + "type": "string", + "enum": [ + "fs:scope-exe" + ] + }, + { + "description": "fs:scope-exe-index -> This scope permits to list all files and folders in the `$EXE`folder.", + "type": "string", + "enum": [ + "fs:scope-exe-index" + ] + }, + { + "description": "fs:scope-exe-recursive -> This scope recursive access to the complete `$EXE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-exe-recursive" + ] + }, + { + "description": "fs:scope-font -> This scope permits access to all files and list content of top level directories in the `$FONT`folder.", + "type": "string", + "enum": [ + "fs:scope-font" + ] + }, + { + "description": "fs:scope-font-index -> This scope permits to list all files and folders in the `$FONT`folder.", + "type": "string", + "enum": [ + "fs:scope-font-index" + ] + }, + { + "description": "fs:scope-font-recursive -> This scope recursive access to the complete `$FONT` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-font-recursive" + ] + }, + { + "description": "fs:scope-home -> This scope permits access to all files and list content of top level directories in the `$HOME`folder.", + "type": "string", + "enum": [ + "fs:scope-home" + ] + }, + { + "description": "fs:scope-home-index -> This scope permits to list all files and folders in the `$HOME`folder.", + "type": "string", + "enum": [ + "fs:scope-home-index" + ] + }, + { + "description": "fs:scope-home-recursive -> This scope recursive access to the complete `$HOME` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-home-recursive" + ] + }, + { + "description": "fs:scope-localdata -> This scope permits access to all files and list content of top level directories in the `$LOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-localdata" + ] + }, + { + "description": "fs:scope-localdata-index -> This scope permits to list all files and folders in the `$LOCALDATA`folder.", + "type": "string", + "enum": [ + "fs:scope-localdata-index" + ] + }, + { + "description": "fs:scope-localdata-recursive -> This scope recursive access to the complete `$LOCALDATA` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-localdata-recursive" + ] + }, + { + "description": "fs:scope-log -> This scope permits access to all files and list content of top level directories in the `$LOG`folder.", + "type": "string", + "enum": [ + "fs:scope-log" + ] + }, + { + "description": "fs:scope-log-index -> This scope permits to list all files and folders in the `$LOG`folder.", + "type": "string", + "enum": [ + "fs:scope-log-index" + ] + }, + { + "description": "fs:scope-log-recursive -> This scope recursive access to the complete `$LOG` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-log-recursive" + ] + }, + { + "description": "fs:scope-picture -> This scope permits access to all files and list content of top level directories in the `$PICTURE`folder.", + "type": "string", + "enum": [ + "fs:scope-picture" + ] + }, + { + "description": "fs:scope-picture-index -> This scope permits to list all files and folders in the `$PICTURE`folder.", + "type": "string", + "enum": [ + "fs:scope-picture-index" + ] + }, + { + "description": "fs:scope-picture-recursive -> This scope recursive access to the complete `$PICTURE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-picture-recursive" + ] + }, + { + "description": "fs:scope-public -> This scope permits access to all files and list content of top level directories in the `$PUBLIC`folder.", + "type": "string", + "enum": [ + "fs:scope-public" + ] + }, + { + "description": "fs:scope-public-index -> This scope permits to list all files and folders in the `$PUBLIC`folder.", + "type": "string", + "enum": [ + "fs:scope-public-index" + ] + }, + { + "description": "fs:scope-public-recursive -> This scope recursive access to the complete `$PUBLIC` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-public-recursive" + ] + }, + { + "description": "fs:scope-resource -> This scope permits access to all files and list content of top level directories in the `$RESOURCE`folder.", + "type": "string", + "enum": [ + "fs:scope-resource" + ] + }, + { + "description": "fs:scope-resource-index -> This scope permits to list all files and folders in the `$RESOURCE`folder.", + "type": "string", + "enum": [ + "fs:scope-resource-index" + ] + }, + { + "description": "fs:scope-resource-recursive -> This scope recursive access to the complete `$RESOURCE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-resource-recursive" + ] + }, + { + "description": "fs:scope-runtime -> This scope permits access to all files and list content of top level directories in the `$RUNTIME`folder.", + "type": "string", + "enum": [ + "fs:scope-runtime" + ] + }, + { + "description": "fs:scope-runtime-index -> This scope permits to list all files and folders in the `$RUNTIME`folder.", + "type": "string", + "enum": [ + "fs:scope-runtime-index" + ] + }, + { + "description": "fs:scope-runtime-recursive -> This scope recursive access to the complete `$RUNTIME` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-runtime-recursive" + ] + }, + { + "description": "fs:scope-temp -> This scope permits access to all files and list content of top level directories in the `$TEMP`folder.", + "type": "string", + "enum": [ + "fs:scope-temp" + ] + }, + { + "description": "fs:scope-temp-index -> This scope permits to list all files and folders in the `$TEMP`folder.", + "type": "string", + "enum": [ + "fs:scope-temp-index" + ] + }, + { + "description": "fs:scope-temp-recursive -> This scope recursive access to the complete `$TEMP` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-temp-recursive" + ] + }, + { + "description": "fs:scope-template -> This scope permits access to all files and list content of top level directories in the `$TEMPLATE`folder.", + "type": "string", + "enum": [ + "fs:scope-template" + ] + }, + { + "description": "fs:scope-template-index -> This scope permits to list all files and folders in the `$TEMPLATE`folder.", + "type": "string", + "enum": [ + "fs:scope-template-index" + ] + }, + { + "description": "fs:scope-template-recursive -> This scope recursive access to the complete `$TEMPLATE` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-template-recursive" + ] + }, + { + "description": "fs:scope-video -> This scope permits access to all files and list content of top level directories in the `$VIDEO`folder.", + "type": "string", + "enum": [ + "fs:scope-video" + ] + }, + { + "description": "fs:scope-video-index -> This scope permits to list all files and folders in the `$VIDEO`folder.", + "type": "string", + "enum": [ + "fs:scope-video-index" + ] + }, + { + "description": "fs:scope-video-recursive -> This scope recursive access to the complete `$VIDEO` folder, including sub directories and files.", + "type": "string", + "enum": [ + "fs:scope-video-recursive" + ] + }, + { + "description": "fs:write-all -> This enables all write related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:write-all" + ] + }, + { + "description": "fs:write-files -> This enables all file write related commands without any pre-configured accessible paths.", + "type": "string", + "enum": [ + "fs:write-files" + ] + }, + { + "description": "image:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "image:default" + ] + }, + { + "description": "image:allow-from-bytes -> Enables the from_bytes command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:allow-from-bytes" + ] + }, + { + "description": "image:allow-from-path -> Enables the from_path command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:allow-from-path" + ] + }, + { + "description": "image:allow-new -> Enables the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:allow-new" + ] + }, + { + "description": "image:allow-rgba -> Enables the rgba command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:allow-rgba" + ] + }, + { + "description": "image:allow-size -> Enables the size command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:allow-size" + ] + }, + { + "description": "image:deny-from-bytes -> Denies the from_bytes command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:deny-from-bytes" + ] + }, + { + "description": "image:deny-from-path -> Denies the from_path command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:deny-from-path" + ] + }, + { + "description": "image:deny-new -> Denies the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:deny-new" + ] + }, + { + "description": "image:deny-rgba -> Denies the rgba command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:deny-rgba" + ] + }, + { + "description": "image:deny-size -> Denies the size command without any pre-configured scope.", + "type": "string", + "enum": [ + "image:deny-size" + ] + }, + { + "description": "log:default -> Allows the log command", + "type": "string", + "enum": [ + "log:default" + ] + }, + { + "description": "log:allow-log -> Enables the log command without any pre-configured scope.", + "type": "string", + "enum": [ + "log:allow-log" + ] + }, + { + "description": "log:deny-log -> Denies the log command without any pre-configured scope.", + "type": "string", + "enum": [ + "log:deny-log" + ] + }, + { + "description": "menu:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "menu:default" + ] + }, + { + "description": "menu:allow-append -> Enables the append command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-append" + ] + }, + { + "description": "menu:allow-create-default -> Enables the create_default command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-create-default" + ] + }, + { + "description": "menu:allow-get -> Enables the get command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-get" + ] + }, + { + "description": "menu:allow-insert -> Enables the insert command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-insert" + ] + }, + { + "description": "menu:allow-is-checked -> Enables the is_checked command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-is-checked" + ] + }, + { + "description": "menu:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-is-enabled" + ] + }, + { + "description": "menu:allow-items -> Enables the items command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-items" + ] + }, + { + "description": "menu:allow-new -> Enables the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-new" + ] + }, + { + "description": "menu:allow-popup -> Enables the popup command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-popup" + ] + }, + { + "description": "menu:allow-prepend -> Enables the prepend command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-prepend" + ] + }, + { + "description": "menu:allow-remove -> Enables the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-remove" + ] + }, + { + "description": "menu:allow-remove-at -> Enables the remove_at command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-remove-at" + ] + }, + { + "description": "menu:allow-set-accelerator -> Enables the set_accelerator command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-accelerator" + ] + }, + { + "description": "menu:allow-set-as-app-menu -> Enables the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-as-app-menu" + ] + }, + { + "description": "menu:allow-set-as-help-menu-for-nsapp -> Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-as-help-menu-for-nsapp" + ] + }, + { + "description": "menu:allow-set-as-window-menu -> Enables the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-as-window-menu" + ] + }, + { + "description": "menu:allow-set-as-windows-menu-for-nsapp -> Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-as-windows-menu-for-nsapp" + ] + }, + { + "description": "menu:allow-set-checked -> Enables the set_checked command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-checked" + ] + }, + { + "description": "menu:allow-set-enabled -> Enables the set_enabled command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-enabled" + ] + }, + { + "description": "menu:allow-set-icon -> Enables the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-icon" + ] + }, + { + "description": "menu:allow-set-text -> Enables the set_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-set-text" + ] + }, + { + "description": "menu:allow-text -> Enables the text command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:allow-text" + ] + }, + { + "description": "menu:deny-append -> Denies the append command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-append" + ] + }, + { + "description": "menu:deny-create-default -> Denies the create_default command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-create-default" + ] + }, + { + "description": "menu:deny-get -> Denies the get command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-get" + ] + }, + { + "description": "menu:deny-insert -> Denies the insert command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-insert" + ] + }, + { + "description": "menu:deny-is-checked -> Denies the is_checked command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-is-checked" + ] + }, + { + "description": "menu:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-is-enabled" + ] + }, + { + "description": "menu:deny-items -> Denies the items command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-items" + ] + }, + { + "description": "menu:deny-new -> Denies the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-new" + ] + }, + { + "description": "menu:deny-popup -> Denies the popup command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-popup" + ] + }, + { + "description": "menu:deny-prepend -> Denies the prepend command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-prepend" + ] + }, + { + "description": "menu:deny-remove -> Denies the remove command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-remove" + ] + }, + { + "description": "menu:deny-remove-at -> Denies the remove_at command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-remove-at" + ] + }, + { + "description": "menu:deny-set-accelerator -> Denies the set_accelerator command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-accelerator" + ] + }, + { + "description": "menu:deny-set-as-app-menu -> Denies the set_as_app_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-as-app-menu" + ] + }, + { + "description": "menu:deny-set-as-help-menu-for-nsapp -> Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-as-help-menu-for-nsapp" + ] + }, + { + "description": "menu:deny-set-as-window-menu -> Denies the set_as_window_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-as-window-menu" + ] + }, + { + "description": "menu:deny-set-as-windows-menu-for-nsapp -> Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-as-windows-menu-for-nsapp" + ] + }, + { + "description": "menu:deny-set-checked -> Denies the set_checked command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-checked" + ] + }, + { + "description": "menu:deny-set-enabled -> Denies the set_enabled command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-enabled" + ] + }, + { + "description": "menu:deny-set-icon -> Denies the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-icon" + ] + }, + { + "description": "menu:deny-set-text -> Denies the set_text command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-set-text" + ] + }, + { + "description": "menu:deny-text -> Denies the text command without any pre-configured scope.", + "type": "string", + "enum": [ + "menu:deny-text" + ] + }, + { + "type": "string", + "enum": [ + "os:default" + ] + }, + { + "description": "os:allow-arch -> Enables the arch command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-arch" + ] + }, + { + "description": "os:allow-exe-extension -> Enables the exe_extension command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-exe-extension" + ] + }, + { + "description": "os:allow-family -> Enables the family command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-family" + ] + }, + { + "description": "os:allow-hostname -> Enables the hostname command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-hostname" + ] + }, + { + "description": "os:allow-locale -> Enables the locale command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-locale" + ] + }, + { + "description": "os:allow-os-type -> Enables the os_type command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-os-type" + ] + }, + { + "description": "os:allow-platform -> Enables the platform command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-platform" + ] + }, + { + "description": "os:allow-version -> Enables the version command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:allow-version" + ] + }, + { + "description": "os:deny-arch -> Denies the arch command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-arch" + ] + }, + { + "description": "os:deny-exe-extension -> Denies the exe_extension command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-exe-extension" + ] + }, + { + "description": "os:deny-family -> Denies the family command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-family" + ] + }, + { + "description": "os:deny-hostname -> Denies the hostname command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-hostname" + ] + }, + { + "description": "os:deny-locale -> Denies the locale command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-locale" + ] + }, + { + "description": "os:deny-os-type -> Denies the os_type command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-os-type" + ] + }, + { + "description": "os:deny-platform -> Denies the platform command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-platform" + ] + }, + { + "description": "os:deny-version -> Denies the version command without any pre-configured scope.", + "type": "string", + "enum": [ + "os:deny-version" + ] + }, + { + "description": "path:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "path:default" + ] + }, + { + "description": "path:allow-basename -> Enables the basename command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-basename" + ] + }, + { + "description": "path:allow-dirname -> Enables the dirname command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-dirname" + ] + }, + { + "description": "path:allow-extname -> Enables the extname command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-extname" + ] + }, + { + "description": "path:allow-is-absolute -> Enables the is_absolute command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-is-absolute" + ] + }, + { + "description": "path:allow-join -> Enables the join command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-join" + ] + }, + { + "description": "path:allow-normalize -> Enables the normalize command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-normalize" + ] + }, + { + "description": "path:allow-resolve -> Enables the resolve command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-resolve" + ] + }, + { + "description": "path:allow-resolve-directory -> Enables the resolve_directory command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:allow-resolve-directory" + ] + }, + { + "description": "path:deny-basename -> Denies the basename command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-basename" + ] + }, + { + "description": "path:deny-dirname -> Denies the dirname command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-dirname" + ] + }, + { + "description": "path:deny-extname -> Denies the extname command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-extname" + ] + }, + { + "description": "path:deny-is-absolute -> Denies the is_absolute command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-is-absolute" + ] + }, + { + "description": "path:deny-join -> Denies the join command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-join" + ] + }, + { + "description": "path:deny-normalize -> Denies the normalize command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-normalize" + ] + }, + { + "description": "path:deny-resolve -> Denies the resolve command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-resolve" + ] + }, + { + "description": "path:deny-resolve-directory -> Denies the resolve_directory command without any pre-configured scope.", + "type": "string", + "enum": [ + "path:deny-resolve-directory" + ] + }, + { + "description": "resources:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "resources:default" + ] + }, + { + "description": "resources:allow-close -> Enables the close command without any pre-configured scope.", + "type": "string", + "enum": [ + "resources:allow-close" + ] + }, + { + "description": "resources:deny-close -> Denies the close command without any pre-configured scope.", + "type": "string", + "enum": [ + "resources:deny-close" + ] + }, + { + "type": "string", + "enum": [ + "shell:default" + ] + }, + { + "description": "shell:allow-execute -> Enables the execute command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-execute" + ] + }, + { + "description": "shell:allow-kill -> Enables the kill command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-kill" + ] + }, + { + "description": "shell:allow-open -> Enables the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-open" + ] + }, + { + "description": "shell:allow-stdin-write -> Enables the stdin_write command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:allow-stdin-write" + ] + }, + { + "description": "shell:deny-execute -> Denies the execute command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-execute" + ] + }, + { + "description": "shell:deny-kill -> Denies the kill command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-kill" + ] + }, + { + "description": "shell:deny-open -> Denies the open command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-open" + ] + }, + { + "description": "shell:deny-stdin-write -> Denies the stdin_write command without any pre-configured scope.", + "type": "string", + "enum": [ + "shell:deny-stdin-write" + ] + }, + { + "description": "tray:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "tray:default" + ] + }, + { + "description": "tray:allow-get-by-id -> Enables the get_by_id command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-get-by-id" + ] + }, + { + "description": "tray:allow-new -> Enables the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-new" + ] + }, + { + "description": "tray:allow-remove-by-id -> Enables the remove_by_id command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-remove-by-id" + ] + }, + { + "description": "tray:allow-set-icon -> Enables the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-icon" + ] + }, + { + "description": "tray:allow-set-icon-as-template -> Enables the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-icon-as-template" + ] + }, + { + "description": "tray:allow-set-menu -> Enables the set_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-menu" + ] + }, + { + "description": "tray:allow-set-show-menu-on-left-click -> Enables the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-show-menu-on-left-click" + ] + }, + { + "description": "tray:allow-set-temp-dir-path -> Enables the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-temp-dir-path" + ] + }, + { + "description": "tray:allow-set-title -> Enables the set_title command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-title" + ] + }, + { + "description": "tray:allow-set-tooltip -> Enables the set_tooltip command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-tooltip" + ] + }, + { + "description": "tray:allow-set-visible -> Enables the set_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:allow-set-visible" + ] + }, + { + "description": "tray:deny-get-by-id -> Denies the get_by_id command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-get-by-id" + ] + }, + { + "description": "tray:deny-new -> Denies the new command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-new" + ] + }, + { + "description": "tray:deny-remove-by-id -> Denies the remove_by_id command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-remove-by-id" + ] + }, + { + "description": "tray:deny-set-icon -> Denies the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-icon" + ] + }, + { + "description": "tray:deny-set-icon-as-template -> Denies the set_icon_as_template command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-icon-as-template" + ] + }, + { + "description": "tray:deny-set-menu -> Denies the set_menu command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-menu" + ] + }, + { + "description": "tray:deny-set-show-menu-on-left-click -> Denies the set_show_menu_on_left_click command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-show-menu-on-left-click" + ] + }, + { + "description": "tray:deny-set-temp-dir-path -> Denies the set_temp_dir_path command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-temp-dir-path" + ] + }, + { + "description": "tray:deny-set-title -> Denies the set_title command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-title" + ] + }, + { + "description": "tray:deny-set-tooltip -> Denies the set_tooltip command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-tooltip" + ] + }, + { + "description": "tray:deny-set-visible -> Denies the set_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "tray:deny-set-visible" + ] + }, + { + "description": "updater:default -> Allows checking for new updates and installing them", + "type": "string", + "enum": [ + "updater:default" + ] + }, + { + "description": "updater:allow-check -> Enables the check command without any pre-configured scope.", + "type": "string", + "enum": [ + "updater:allow-check" + ] + }, + { + "description": "updater:allow-download-and-install -> Enables the download_and_install command without any pre-configured scope.", + "type": "string", + "enum": [ + "updater:allow-download-and-install" + ] + }, + { + "description": "updater:deny-check -> Denies the check command without any pre-configured scope.", + "type": "string", + "enum": [ + "updater:deny-check" + ] + }, + { + "description": "updater:deny-download-and-install -> Denies the download_and_install command without any pre-configured scope.", + "type": "string", + "enum": [ + "updater:deny-download-and-install" + ] + }, + { + "description": "webview:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "webview:default" + ] + }, + { + "description": "webview:allow-create-webview -> Enables the create_webview command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-create-webview" + ] + }, + { + "description": "webview:allow-create-webview-window -> Enables the create_webview_window command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-create-webview-window" + ] + }, + { + "description": "webview:allow-internal-toggle-devtools -> Enables the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-internal-toggle-devtools" + ] + }, + { + "description": "webview:allow-print -> Enables the print command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-print" + ] + }, + { + "description": "webview:allow-reparent -> Enables the reparent command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-reparent" + ] + }, + { + "description": "webview:allow-set-webview-focus -> Enables the set_webview_focus command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-set-webview-focus" + ] + }, + { + "description": "webview:allow-set-webview-position -> Enables the set_webview_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-set-webview-position" + ] + }, + { + "description": "webview:allow-set-webview-size -> Enables the set_webview_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-set-webview-size" + ] + }, + { + "description": "webview:allow-set-webview-zoom -> Enables the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-set-webview-zoom" + ] + }, + { + "description": "webview:allow-webview-close -> Enables the webview_close command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-webview-close" + ] + }, + { + "description": "webview:allow-webview-position -> Enables the webview_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-webview-position" + ] + }, + { + "description": "webview:allow-webview-size -> Enables the webview_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:allow-webview-size" + ] + }, + { + "description": "webview:deny-create-webview -> Denies the create_webview command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-create-webview" + ] + }, + { + "description": "webview:deny-create-webview-window -> Denies the create_webview_window command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-create-webview-window" + ] + }, + { + "description": "webview:deny-internal-toggle-devtools -> Denies the internal_toggle_devtools command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-internal-toggle-devtools" + ] + }, + { + "description": "webview:deny-print -> Denies the print command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-print" + ] + }, + { + "description": "webview:deny-reparent -> Denies the reparent command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-reparent" + ] + }, + { + "description": "webview:deny-set-webview-focus -> Denies the set_webview_focus command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-set-webview-focus" + ] + }, + { + "description": "webview:deny-set-webview-position -> Denies the set_webview_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-set-webview-position" + ] + }, + { + "description": "webview:deny-set-webview-size -> Denies the set_webview_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-set-webview-size" + ] + }, + { + "description": "webview:deny-set-webview-zoom -> Denies the set_webview_zoom command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-set-webview-zoom" + ] + }, + { + "description": "webview:deny-webview-close -> Denies the webview_close command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-webview-close" + ] + }, + { + "description": "webview:deny-webview-position -> Denies the webview_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-webview-position" + ] + }, + { + "description": "webview:deny-webview-size -> Denies the webview_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "webview:deny-webview-size" + ] + }, + { + "description": "window:default -> Default permissions for the plugin.", + "type": "string", + "enum": [ + "window:default" + ] + }, + { + "description": "window:allow-available-monitors -> Enables the available_monitors command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-available-monitors" + ] + }, + { + "description": "window:allow-center -> Enables the center command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-center" + ] + }, + { + "description": "window:allow-close -> Enables the close command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-close" + ] + }, + { + "description": "window:allow-create -> Enables the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-create" + ] + }, + { + "description": "window:allow-current-monitor -> Enables the current_monitor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-current-monitor" + ] + }, + { + "description": "window:allow-cursor-position -> Enables the cursor_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-cursor-position" + ] + }, + { + "description": "window:allow-destroy -> Enables the destroy command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-destroy" + ] + }, + { + "description": "window:allow-hide -> Enables the hide command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-hide" + ] + }, + { + "description": "window:allow-inner-position -> Enables the inner_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-inner-position" + ] + }, + { + "description": "window:allow-inner-size -> Enables the inner_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-inner-size" + ] + }, + { + "description": "window:allow-internal-toggle-maximize -> Enables the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-internal-toggle-maximize" + ] + }, + { + "description": "window:allow-is-closable -> Enables the is_closable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-closable" + ] + }, + { + "description": "window:allow-is-decorated -> Enables the is_decorated command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-decorated" + ] + }, + { + "description": "window:allow-is-focused -> Enables the is_focused command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-focused" + ] + }, + { + "description": "window:allow-is-fullscreen -> Enables the is_fullscreen command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-fullscreen" + ] + }, + { + "description": "window:allow-is-maximizable -> Enables the is_maximizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-maximizable" + ] + }, + { + "description": "window:allow-is-maximized -> Enables the is_maximized command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-maximized" + ] + }, + { + "description": "window:allow-is-minimizable -> Enables the is_minimizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-minimizable" + ] + }, + { + "description": "window:allow-is-minimized -> Enables the is_minimized command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-minimized" + ] + }, + { + "description": "window:allow-is-resizable -> Enables the is_resizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-resizable" + ] + }, + { + "description": "window:allow-is-visible -> Enables the is_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-is-visible" + ] + }, + { + "description": "window:allow-maximize -> Enables the maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-maximize" + ] + }, + { + "description": "window:allow-minimize -> Enables the minimize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-minimize" + ] + }, + { + "description": "window:allow-outer-position -> Enables the outer_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-outer-position" + ] + }, + { + "description": "window:allow-outer-size -> Enables the outer_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-outer-size" + ] + }, + { + "description": "window:allow-primary-monitor -> Enables the primary_monitor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-primary-monitor" + ] + }, + { + "description": "window:allow-request-user-attention -> Enables the request_user_attention command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-request-user-attention" + ] + }, + { + "description": "window:allow-scale-factor -> Enables the scale_factor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-scale-factor" + ] + }, + { + "description": "window:allow-set-always-on-bottom -> Enables the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-always-on-bottom" + ] + }, + { + "description": "window:allow-set-always-on-top -> Enables the set_always_on_top command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-always-on-top" + ] + }, + { + "description": "window:allow-set-closable -> Enables the set_closable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-closable" + ] + }, + { + "description": "window:allow-set-content-protected -> Enables the set_content_protected command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-content-protected" + ] + }, + { + "description": "window:allow-set-cursor-grab -> Enables the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-cursor-grab" + ] + }, + { + "description": "window:allow-set-cursor-icon -> Enables the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-cursor-icon" + ] + }, + { + "description": "window:allow-set-cursor-position -> Enables the set_cursor_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-cursor-position" + ] + }, + { + "description": "window:allow-set-cursor-visible -> Enables the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-cursor-visible" + ] + }, + { + "description": "window:allow-set-decorations -> Enables the set_decorations command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-decorations" + ] + }, + { + "description": "window:allow-set-effects -> Enables the set_effects command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-effects" + ] + }, + { + "description": "window:allow-set-focus -> Enables the set_focus command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-focus" + ] + }, + { + "description": "window:allow-set-fullscreen -> Enables the set_fullscreen command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-fullscreen" + ] + }, + { + "description": "window:allow-set-icon -> Enables the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-icon" + ] + }, + { + "description": "window:allow-set-ignore-cursor-events -> Enables the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-ignore-cursor-events" + ] + }, + { + "description": "window:allow-set-max-size -> Enables the set_max_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-max-size" + ] + }, + { + "description": "window:allow-set-maximizable -> Enables the set_maximizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-maximizable" + ] + }, + { + "description": "window:allow-set-min-size -> Enables the set_min_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-min-size" + ] + }, + { + "description": "window:allow-set-minimizable -> Enables the set_minimizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-minimizable" + ] + }, + { + "description": "window:allow-set-position -> Enables the set_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-position" + ] + }, + { + "description": "window:allow-set-progress-bar -> Enables the set_progress_bar command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-progress-bar" + ] + }, + { + "description": "window:allow-set-resizable -> Enables the set_resizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-resizable" + ] + }, + { + "description": "window:allow-set-shadow -> Enables the set_shadow command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-shadow" + ] + }, + { + "description": "window:allow-set-size -> Enables the set_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-size" + ] + }, + { + "description": "window:allow-set-skip-taskbar -> Enables the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-skip-taskbar" + ] + }, + { + "description": "window:allow-set-title -> Enables the set_title command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-title" + ] + }, + { + "description": "window:allow-set-visible-on-all-workspaces -> Enables the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-set-visible-on-all-workspaces" + ] + }, + { + "description": "window:allow-show -> Enables the show command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-show" + ] + }, + { + "description": "window:allow-start-dragging -> Enables the start_dragging command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-start-dragging" + ] + }, + { + "description": "window:allow-start-resize-dragging -> Enables the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-start-resize-dragging" + ] + }, + { + "description": "window:allow-theme -> Enables the theme command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-theme" + ] + }, + { + "description": "window:allow-title -> Enables the title command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-title" + ] + }, + { + "description": "window:allow-toggle-maximize -> Enables the toggle_maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-toggle-maximize" + ] + }, + { + "description": "window:allow-unmaximize -> Enables the unmaximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-unmaximize" + ] + }, + { + "description": "window:allow-unminimize -> Enables the unminimize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:allow-unminimize" + ] + }, + { + "description": "window:deny-available-monitors -> Denies the available_monitors command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-available-monitors" + ] + }, + { + "description": "window:deny-center -> Denies the center command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-center" + ] + }, + { + "description": "window:deny-close -> Denies the close command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-close" + ] + }, + { + "description": "window:deny-create -> Denies the create command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-create" + ] + }, + { + "description": "window:deny-current-monitor -> Denies the current_monitor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-current-monitor" + ] + }, + { + "description": "window:deny-cursor-position -> Denies the cursor_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-cursor-position" + ] + }, + { + "description": "window:deny-destroy -> Denies the destroy command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-destroy" + ] + }, + { + "description": "window:deny-hide -> Denies the hide command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-hide" + ] + }, + { + "description": "window:deny-inner-position -> Denies the inner_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-inner-position" + ] + }, + { + "description": "window:deny-inner-size -> Denies the inner_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-inner-size" + ] + }, + { + "description": "window:deny-internal-toggle-maximize -> Denies the internal_toggle_maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-internal-toggle-maximize" + ] + }, + { + "description": "window:deny-is-closable -> Denies the is_closable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-closable" + ] + }, + { + "description": "window:deny-is-decorated -> Denies the is_decorated command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-decorated" + ] + }, + { + "description": "window:deny-is-focused -> Denies the is_focused command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-focused" + ] + }, + { + "description": "window:deny-is-fullscreen -> Denies the is_fullscreen command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-fullscreen" + ] + }, + { + "description": "window:deny-is-maximizable -> Denies the is_maximizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-maximizable" + ] + }, + { + "description": "window:deny-is-maximized -> Denies the is_maximized command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-maximized" + ] + }, + { + "description": "window:deny-is-minimizable -> Denies the is_minimizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-minimizable" + ] + }, + { + "description": "window:deny-is-minimized -> Denies the is_minimized command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-minimized" + ] + }, + { + "description": "window:deny-is-resizable -> Denies the is_resizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-resizable" + ] + }, + { + "description": "window:deny-is-visible -> Denies the is_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-is-visible" + ] + }, + { + "description": "window:deny-maximize -> Denies the maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-maximize" + ] + }, + { + "description": "window:deny-minimize -> Denies the minimize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-minimize" + ] + }, + { + "description": "window:deny-outer-position -> Denies the outer_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-outer-position" + ] + }, + { + "description": "window:deny-outer-size -> Denies the outer_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-outer-size" + ] + }, + { + "description": "window:deny-primary-monitor -> Denies the primary_monitor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-primary-monitor" + ] + }, + { + "description": "window:deny-request-user-attention -> Denies the request_user_attention command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-request-user-attention" + ] + }, + { + "description": "window:deny-scale-factor -> Denies the scale_factor command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-scale-factor" + ] + }, + { + "description": "window:deny-set-always-on-bottom -> Denies the set_always_on_bottom command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-always-on-bottom" + ] + }, + { + "description": "window:deny-set-always-on-top -> Denies the set_always_on_top command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-always-on-top" + ] + }, + { + "description": "window:deny-set-closable -> Denies the set_closable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-closable" + ] + }, + { + "description": "window:deny-set-content-protected -> Denies the set_content_protected command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-content-protected" + ] + }, + { + "description": "window:deny-set-cursor-grab -> Denies the set_cursor_grab command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-cursor-grab" + ] + }, + { + "description": "window:deny-set-cursor-icon -> Denies the set_cursor_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-cursor-icon" + ] + }, + { + "description": "window:deny-set-cursor-position -> Denies the set_cursor_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-cursor-position" + ] + }, + { + "description": "window:deny-set-cursor-visible -> Denies the set_cursor_visible command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-cursor-visible" + ] + }, + { + "description": "window:deny-set-decorations -> Denies the set_decorations command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-decorations" + ] + }, + { + "description": "window:deny-set-effects -> Denies the set_effects command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-effects" + ] + }, + { + "description": "window:deny-set-focus -> Denies the set_focus command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-focus" + ] + }, + { + "description": "window:deny-set-fullscreen -> Denies the set_fullscreen command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-fullscreen" + ] + }, + { + "description": "window:deny-set-icon -> Denies the set_icon command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-icon" + ] + }, + { + "description": "window:deny-set-ignore-cursor-events -> Denies the set_ignore_cursor_events command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-ignore-cursor-events" + ] + }, + { + "description": "window:deny-set-max-size -> Denies the set_max_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-max-size" + ] + }, + { + "description": "window:deny-set-maximizable -> Denies the set_maximizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-maximizable" + ] + }, + { + "description": "window:deny-set-min-size -> Denies the set_min_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-min-size" + ] + }, + { + "description": "window:deny-set-minimizable -> Denies the set_minimizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-minimizable" + ] + }, + { + "description": "window:deny-set-position -> Denies the set_position command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-position" + ] + }, + { + "description": "window:deny-set-progress-bar -> Denies the set_progress_bar command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-progress-bar" + ] + }, + { + "description": "window:deny-set-resizable -> Denies the set_resizable command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-resizable" + ] + }, + { + "description": "window:deny-set-shadow -> Denies the set_shadow command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-shadow" + ] + }, + { + "description": "window:deny-set-size -> Denies the set_size command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-size" + ] + }, + { + "description": "window:deny-set-skip-taskbar -> Denies the set_skip_taskbar command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-skip-taskbar" + ] + }, + { + "description": "window:deny-set-title -> Denies the set_title command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-title" + ] + }, + { + "description": "window:deny-set-visible-on-all-workspaces -> Denies the set_visible_on_all_workspaces command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-set-visible-on-all-workspaces" + ] + }, + { + "description": "window:deny-show -> Denies the show command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-show" + ] + }, + { + "description": "window:deny-start-dragging -> Denies the start_dragging command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-start-dragging" + ] + }, + { + "description": "window:deny-start-resize-dragging -> Denies the start_resize_dragging command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-start-resize-dragging" + ] + }, + { + "description": "window:deny-theme -> Denies the theme command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-theme" + ] + }, + { + "description": "window:deny-title -> Denies the title command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-title" + ] + }, + { + "description": "window:deny-toggle-maximize -> Denies the toggle_maximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-toggle-maximize" + ] + }, + { + "description": "window:deny-unmaximize -> Denies the unmaximize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-unmaximize" + ] + }, + { + "description": "window:deny-unminimize -> Denies the unminimize command without any pre-configured scope.", + "type": "string", + "enum": [ + "window:deny-unminimize" + ] + }, + { + "type": "string", + "enum": [ + "window-state:default" + ] + }, + { + "description": "window-state:allow-filename -> Enables the filename command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:allow-filename" + ] + }, + { + "description": "window-state:allow-restore-state -> Enables the restore_state command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:allow-restore-state" + ] + }, + { + "description": "window-state:allow-save-window-state -> Enables the save_window_state command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:allow-save-window-state" + ] + }, + { + "description": "window-state:deny-filename -> Denies the filename command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:deny-filename" + ] + }, + { + "description": "window-state:deny-restore-state -> Denies the restore_state command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:deny-restore-state" + ] + }, + { + "description": "window-state:deny-save-window-state -> Denies the save_window_state command without any pre-configured scope.", + "type": "string", + "enum": [ + "window-state:deny-save-window-state" + ] + } + ] + }, + "Value": { + "description": "All supported ACL values.", + "anyOf": [ + { + "description": "Represents a null JSON value.", + "type": "null" + }, + { + "description": "Represents a [`bool`].", + "type": "boolean" + }, + { + "description": "Represents a valid ACL [`Number`].", + "allOf": [ + { + "$ref": "#/definitions/Number" + } + ] + }, + { + "description": "Represents a [`String`].", + "type": "string" + }, + { + "description": "Represents a list of other [`Value`]s.", + "type": "array", + "items": { + "$ref": "#/definitions/Value" + } + }, + { + "description": "Represents a map of [`String`] keys to [`Value`]s.", + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/Value" + } + } + ] + }, + "Number": { + "description": "A valid ACL number.", + "anyOf": [ + { + "description": "Represents an [`i64`].", + "type": "integer", + "format": "int64" + }, + { + "description": "Represents a [`f64`].", + "type": "number", + "format": "double" + } + ] + }, + "Target": { + "description": "Platform target.", + "oneOf": [ + { + "description": "MacOS.", + "type": "string", + "enum": [ + "macOS" + ] + }, + { + "description": "Windows.", + "type": "string", + "enum": [ + "windows" + ] + }, + { + "description": "Linux.", + "type": "string", + "enum": [ + "linux" + ] + }, + { + "description": "Android.", + "type": "string", + "enum": [ + "android" + ] + }, + { + "description": "iOS.", + "type": "string", + "enum": [ + "iOS" + ] + } + ] + }, + "ShellAllowedArg": { + "description": "A command argument allowed to be executed by the webview API.", + "anyOf": [ + { + "description": "A non-configurable argument that is passed to the command in the order it was specified.", + "type": "string" + }, + { + "description": "A variable that is set while calling the command from the webview API.", + "type": "object", + "required": [ + "validator" + ], + "properties": { + "validator": { + "description": "[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\n[regex]: https://docs.rs/regex/latest/regex/#syntax", + "type": "string" + } + }, + "additionalProperties": false + } + ] + }, + "ShellAllowedArgs": { + "description": "A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration.", + "anyOf": [ + { + "description": "Use a simple boolean to allow all or disable all arguments to this command configuration.", + "type": "boolean" + }, + { + "description": "A specific set of [`ShellAllowedArg`] that are valid to call for the command configuration.", + "type": "array", + "items": { + "$ref": "#/definitions/ShellAllowedArg" + } + } + ] + } + } +} \ No newline at end of file diff --git a/src-tauri/migrations/20240522031045_theme-settings.sql b/src-tauri/migrations/20240522031045_theme-settings.sql new file mode 100644 index 00000000..57c51e23 --- /dev/null +++ b/src-tauri/migrations/20240522031045_theme-settings.sql @@ -0,0 +1,4 @@ +ALTER TABLE settings + ADD COLUMN theme_dark TEXT DEFAULT 'yaak-dark' NOT NULL; +ALTER TABLE settings + ADD COLUMN theme_light TEXT DEFAULT 'yaak-light' NOT NULL; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index bec94c40..b7bb2a8d 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -34,7 +34,6 @@ use tokio::sync::Mutex; use ::grpc::{Code, deserialize_message, serialize_message, ServiceDefinition}; use ::grpc::manager::{DynamicMessage, GrpcHandle}; -use window_ext::TrafficLightWindowExt; use crate::analytics::{AnalyticsAction, AnalyticsResource}; use crate::grpc::metadata_to_map; @@ -69,8 +68,11 @@ mod notifications; mod plugin; mod render; mod updates; -mod window_ext; mod window_menu; +#[cfg(target_os = "macos")] +mod mac; +#[cfg(target_os = "windows")] +mod win; async fn migrate_db(app_handle: &AppHandle, db: &Mutex>) -> Result<(), String> { let pool = &*db.lock().await; @@ -230,8 +232,8 @@ async fn cmd_grpc_go( ..Default::default() }, ) - .await - .map_err(|e| e.to_string())? + .await + .map_err(|e| e.to_string())? }; let conn_id = conn.id.clone(); @@ -328,8 +330,8 @@ async fn cmd_grpc_go( ..base_msg.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); }); return; } @@ -344,8 +346,8 @@ async fn cmd_grpc_go( ..base_msg.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); }); } Ok(IncomingMsg::Commit) => { @@ -384,8 +386,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); async move { let (maybe_stream, maybe_msg) = match ( @@ -431,8 +433,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); } match maybe_msg { @@ -446,13 +448,13 @@ async fn cmd_grpc_go( } else { "Received response with metadata" } - .to_string(), + .to_string(), event_type: GrpcEventType::Info, ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); upsert_grpc_event( &w, &GrpcEvent { @@ -461,8 +463,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); upsert_grpc_event( &w, &GrpcEvent { @@ -472,8 +474,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); } Some(Err(e)) => { upsert_grpc_event( @@ -496,8 +498,8 @@ async fn cmd_grpc_go( }, }), ) - .await - .unwrap(); + .await + .unwrap(); } None => { // Server streaming doesn't return initial message @@ -515,13 +517,13 @@ async fn cmd_grpc_go( } else { "Received response with metadata" } - .to_string(), + .to_string(), event_type: GrpcEventType::Info, ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); stream.into_inner() } Some(Err(e)) => { @@ -545,8 +547,8 @@ async fn cmd_grpc_go( }, }), ) - .await - .unwrap(); + .await + .unwrap(); return; } None => return, @@ -564,8 +566,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); } Ok(None) => { let trailers = stream @@ -583,8 +585,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); break; } Err(status) => { @@ -598,8 +600,8 @@ async fn cmd_grpc_go( ..base_event.clone() }, ) - .await - .unwrap(); + .await + .unwrap(); } } } @@ -700,7 +702,7 @@ async fn cmd_send_ephemeral_request( None, &mut cancel_rx, ) - .await + .await } #[tauri::command] @@ -767,7 +769,7 @@ async fn cmd_import_data( AnalyticsAction::Import, Some(json!({ "plugin": plugin_name })), ) - .await; + .await; result = Some(r); break; } @@ -798,7 +800,7 @@ async fn cmd_import_data( let maybe_gen_id_opt = |id: Option, model: ModelType, ids: &mut HashMap| - -> Option { + -> Option { match id { Some(id) => Some(maybe_gen_id(id.as_str(), model, ids)), None => None, @@ -944,7 +946,7 @@ async fn cmd_export_data( AnalyticsAction::Export, None, ) - .await; + .await; Ok(()) } @@ -995,8 +997,8 @@ async fn cmd_send_http_request( None, None, ) - .await - .expect("Failed to create response"); + .await + .expect("Failed to create response"); let download_path = if let Some(p) = download_dir { Some(std::path::Path::new(p).to_path_buf()) @@ -1021,7 +1023,7 @@ async fn cmd_send_http_request( download_path, &mut cancel_rx, ) - .await + .await } async fn response_err( @@ -1129,8 +1131,8 @@ async fn cmd_create_cookie_jar( ..Default::default() }, ) - .await - .map_err(|e| e.to_string()) + .await + .map_err(|e| e.to_string()) } #[tauri::command] @@ -1149,8 +1151,8 @@ async fn cmd_create_environment( ..Default::default() }, ) - .await - .map_err(|e| e.to_string()) + .await + .map_err(|e| e.to_string()) } #[tauri::command] @@ -1171,8 +1173,8 @@ async fn cmd_create_grpc_request( ..Default::default() }, ) - .await - .map_err(|e| e.to_string()) + .await + .map_err(|e| e.to_string()) } #[tauri::command] @@ -1281,8 +1283,8 @@ async fn cmd_create_folder( ..Default::default() }, ) - .await - .map_err(|e| e.to_string()) + .await + .map_err(|e| e.to_string()) } #[tauri::command] @@ -1412,8 +1414,8 @@ async fn cmd_list_cookie_jars( ..Default::default() }, ) - .await - .expect("Failed to create CookieJar"); + .await + .expect("Failed to create CookieJar"); Ok(vec![cookie_jar]) } else { Ok(cookie_jars) @@ -1482,8 +1484,8 @@ async fn cmd_list_workspaces(w: WebviewWindow) -> Result, String> ..Default::default() }, ) - .await - .expect("Failed to create Workspace"); + .await + .expect("Failed to create Workspace"); Ok(vec![workspace]) } else { Ok(workspaces) @@ -1733,16 +1735,16 @@ fn create_window(handle: &AppHandle, url: Option<&str>) -> WebviewWindow { window_id, WebviewUrl::App(url.unwrap_or_default().into()), ) - .resizable(true) - .fullscreen(false) - .disable_drag_drop_handler() // Required for frontend Dnd on windows - .inner_size(1100.0, 600.0) - .position( - // Randomly offset so windows don't stack exactly - 100.0 + random::() * 30.0, - 100.0 + random::() * 30.0, - ) - .title(handle.package_info().name.to_string()); + .resizable(true) + .fullscreen(false) + .disable_drag_drop_handler() // Required for frontend Dnd on windows + .inner_size(1100.0, 600.0) + .position( + // Randomly offset so windows don't stack exactly + 100.0 + random::() * 30.0, + 100.0 + random::() * 30.0, + ) + .title(handle.package_info().name.to_string()); // Add macOS-only things #[cfg(target_os = "macos")] @@ -1798,25 +1800,19 @@ fn create_window(handle: &AppHandle, url: Option<&str>) -> WebviewWindow { } }); - let win3 = win.clone(); - win.on_window_event(move |e| { - let apply_offset = || { - win3.position_traffic_lights(); - }; + #[cfg(target_os = "macos")] + { + use mac::setup_mac_window; + let mut m_win = win.clone(); + setup_mac_window(&mut m_win); + }; + #[cfg(target_os = "windows")] + { + use win::setup_win_window; + let mut m_win = win.clone(); + setup_win_window(&mut m_win); + } - match e { - WindowEvent::Resized(..) => apply_offset(), - WindowEvent::ThemeChanged(..) => apply_offset(), - WindowEvent::Focused(..) => apply_offset(), - WindowEvent::ScaleFactorChanged { .. } => apply_offset(), - WindowEvent::CloseRequested { .. } => { - // api.prevent_close(); - } - _ => {} - } - }); - - win.position_traffic_lights(); win } diff --git a/src-tauri/src/mac.rs b/src-tauri/src/mac.rs new file mode 100644 index 00000000..43ce6c81 --- /dev/null +++ b/src-tauri/src/mac.rs @@ -0,0 +1,355 @@ +// Borrowed from our friends at Hoppscotch +// https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs + +use hex_color::HexColor; +use tauri::{Manager, WebviewWindow}; + +struct UnsafeWindowHandle(*mut std::ffi::c_void); + +unsafe impl Send for UnsafeWindowHandle {} + +unsafe impl Sync for UnsafeWindowHandle {} + +const WINDOW_CONTROL_PAD_X: f64 = 13.0; +const WINDOW_CONTROL_PAD_Y: f64 = 18.0; + +#[cfg(target_os = "macos")] +fn update_window_theme(window: &WebviewWindow, color: HexColor) { + use cocoa::appkit::{ + NSAppearance, NSAppearanceNameVibrantDark, NSAppearanceNameVibrantLight, NSWindow, + }; + + let brightness = (color.r as u64 + color.g as u64 + color.b as u64) / 3; + + unsafe { + let window_handle = UnsafeWindowHandle(window.ns_window().unwrap()); + + let _ = window.run_on_main_thread(move || { + let handle = window_handle; + + let selected_appearance = if brightness >= 128 { + NSAppearance(NSAppearanceNameVibrantLight) + } else { + NSAppearance(NSAppearanceNameVibrantDark) + }; + + NSWindow::setAppearance(handle.0 as cocoa::base::id, selected_appearance); + set_window_controls_pos( + handle.0 as cocoa::base::id, + WINDOW_CONTROL_PAD_X, + WINDOW_CONTROL_PAD_Y, + ); + }); + } +} + +#[cfg(target_os = "macos")] +fn set_window_controls_pos(window: cocoa::base::id, x: f64, y: f64) { + use cocoa::{ + appkit::{NSView, NSWindow, NSWindowButton}, + foundation::NSRect, + }; + + unsafe { + let close = window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); + let miniaturize = window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); + let zoom = window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); + + let title_bar_container_view = close.superview().superview(); + + let close_rect: NSRect = msg_send![close, frame]; + let button_height = close_rect.size.height; + + let title_bar_frame_height = button_height + y; + let mut title_bar_rect = NSView::frame(title_bar_container_view); + title_bar_rect.size.height = title_bar_frame_height; + title_bar_rect.origin.y = NSView::frame(window).size.height - title_bar_frame_height; + let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; + + let window_buttons = vec![close, miniaturize, zoom]; + let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x; + + for (i, button) in window_buttons.into_iter().enumerate() { + let mut rect: NSRect = NSView::frame(button); + rect.origin.x = x + (i as f64 * space_between); + button.setFrameOrigin(rect.origin); + } + } +} + +#[cfg(target_os = "macos")] +#[derive(Debug)] +struct AppState { + window: WebviewWindow, +} + +#[cfg(target_os = "macos")] +pub fn setup_mac_window(window: &mut WebviewWindow) { + use cocoa::delegate; + use cocoa::appkit::NSWindow; + use cocoa::base::{BOOL, id}; + use cocoa::foundation::NSUInteger; + use objc::runtime::{Object, Sel}; + use std::ffi::c_void; + + fn with_app_state T, T>(this: &Object, func: F) { + let ptr = unsafe { + let x: *mut c_void = *this.get_ivar("yaakApp"); + &mut *(x as *mut AppState) + }; + func(ptr); + } + + unsafe { + let ns_win = window.ns_window().unwrap() as id; + + let current_delegate: id = ns_win.delegate(); + + extern "C" fn on_window_should_close(this: &Object, _cmd: Sel, sender: id) -> BOOL { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + msg_send![super_del, windowShouldClose: sender] + } + } + extern "C" fn on_window_will_close(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowWillClose: notification]; + } + } + extern "C" fn on_window_did_resize(this: &Object, _cmd: Sel, notification: id) { + unsafe { + with_app_state(&*this, |state| { + let id = state.window.ns_window().unwrap() as id; + + set_window_controls_pos(id, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); + }); + + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidResize: notification]; + } + } + extern "C" fn on_window_did_move(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidMove: notification]; + } + } + extern "C" fn on_window_did_change_backing_properties( + this: &Object, + _cmd: Sel, + notification: id, + ) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidChangeBackingProperties: notification]; + } + } + extern "C" fn on_window_did_become_key(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidBecomeKey: notification]; + } + } + extern "C" fn on_window_did_resign_key(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidResignKey: notification]; + } + } + extern "C" fn on_dragging_entered(this: &Object, _cmd: Sel, notification: id) -> BOOL { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + msg_send![super_del, draggingEntered: notification] + } + } + extern "C" fn on_prepare_for_drag_operation( + this: &Object, + _cmd: Sel, + notification: id, + ) -> BOOL { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + msg_send![super_del, prepareForDragOperation: notification] + } + } + extern "C" fn on_perform_drag_operation(this: &Object, _cmd: Sel, sender: id) -> BOOL { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + msg_send![super_del, performDragOperation: sender] + } + } + extern "C" fn on_conclude_drag_operation(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, concludeDragOperation: notification]; + } + } + extern "C" fn on_dragging_exited(this: &Object, _cmd: Sel, notification: id) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, draggingExited: notification]; + } + } + extern "C" fn on_window_will_use_full_screen_presentation_options( + this: &Object, + _cmd: Sel, + window: id, + proposed_options: NSUInteger, + ) -> NSUInteger { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + msg_send![super_del, window: window willUseFullScreenPresentationOptions: proposed_options] + } + } + extern "C" fn on_window_did_enter_full_screen(this: &Object, _cmd: Sel, notification: id) { + unsafe { + with_app_state(&*this, |state| { + state.window.emit("did-enter-fullscreen", ()).unwrap(); + }); + + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidEnterFullScreen: notification]; + } + } + extern "C" fn on_window_will_enter_full_screen(this: &Object, _cmd: Sel, notification: id) { + unsafe { + with_app_state(&*this, |state| { + state.window.emit("will-enter-fullscreen", ()).unwrap(); + }); + + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowWillEnterFullScreen: notification]; + } + } + extern "C" fn on_window_did_exit_full_screen(this: &Object, _cmd: Sel, notification: id) { + unsafe { + with_app_state(&*this, |state| { + state.window.emit("did-exit-fullscreen", ()).unwrap(); + + let id = state.window.ns_window().unwrap() as id; + set_window_controls_pos(id, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); + }); + + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidExitFullScreen: notification]; + } + } + extern "C" fn on_window_will_exit_full_screen(this: &Object, _cmd: Sel, notification: id) { + unsafe { + with_app_state(&*this, |state| { + state.window.emit("will-exit-fullscreen", ()).unwrap(); + }); + + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowWillExitFullScreen: notification]; + } + } + extern "C" fn on_window_did_fail_to_enter_full_screen( + this: &Object, + _cmd: Sel, + window: id, + ) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, windowDidFailToEnterFullScreen: window]; + } + } + extern "C" fn on_effective_appearance_did_change( + this: &Object, + _cmd: Sel, + notification: id, + ) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![super_del, effectiveAppearanceDidChange: notification]; + } + } + extern "C" fn on_effective_appearance_did_changed_on_main_thread( + this: &Object, + _cmd: Sel, + notification: id, + ) { + unsafe { + let super_del: id = *this.get_ivar("super_delegate"); + let _: () = msg_send![ + super_del, + effectiveAppearanceDidChangedOnMainThread: notification + ]; + } + } + + // extern fn on_dealloc(this: &Object, cmd: Sel) { + // unsafe { + // let super_del: id = *this.get_ivar("super_delegate"); + // let _: () = msg_send![super_del, dealloc]; + // } + // } + + // extern fn on_mark_is_checking_zoomed_in(this: &Object, cmd: Sel) { + // unsafe { + // let super_del: id = *this.get_ivar("super_delegate"); + // let _: () = msg_send![super_del, markIsCheckingZoomedIn]; + // } + // } + + // extern fn on_clear_is_checking_zoomed_in(this: &Object, cmd: Sel) { + // unsafe { + // let super_del: id = *this.get_ivar("super_delegate"); + // let _: () = msg_send![super_del, clearIsCheckingZoomedIn]; + // } + // } + + // Are we deallocing this properly ? (I miss safe Rust :( ) + let w = window.clone(); + let app_state = AppState { window: w }; + let app_box = Box::into_raw(Box::new(app_state)) as *mut c_void; + set_window_controls_pos(ns_win, WINDOW_CONTROL_PAD_X, WINDOW_CONTROL_PAD_Y); + + ns_win.setDelegate_(delegate!("MainWindowDelegate", { + window: id = ns_win, + yaakApp: *mut c_void = app_box, + toolbar: id = cocoa::base::nil, + super_delegate: id = current_delegate, + // (dealloc) => on_dealloc as extern fn(&Object, Sel), + // (markIsCheckingZoomedIn) => on_mark_is_checking_zoomed_in as extern fn(&Object, Sel), + // (clearIsCheckingZoomedIn) => on_clear_is_checking_zoomed_in as extern fn(&Object, Sel), + (windowShouldClose:) => on_window_should_close as extern fn(&Object, Sel, id) -> BOOL, + (windowWillClose:) => on_window_will_close as extern fn(&Object, Sel, id), + (windowDidResize:) => on_window_did_resize as extern fn(&Object, Sel, id), + (windowDidMove:) => on_window_did_move as extern fn(&Object, Sel, id), + (windowDidChangeBackingProperties:) => on_window_did_change_backing_properties as extern fn(&Object, Sel, id), + (windowDidBecomeKey:) => on_window_did_become_key as extern fn(&Object, Sel, id), + (windowDidResignKey:) => on_window_did_resign_key as extern fn(&Object, Sel, id), + (draggingEntered:) => on_dragging_entered as extern fn(&Object, Sel, id) -> BOOL, + (prepareForDragOperation:) => on_prepare_for_drag_operation as extern fn(&Object, Sel, id) -> BOOL, + (performDragOperation:) => on_perform_drag_operation as extern fn(&Object, Sel, id) -> BOOL, + (concludeDragOperation:) => on_conclude_drag_operation as extern fn(&Object, Sel, id), + (draggingExited:) => on_dragging_exited as extern fn(&Object, Sel, id), + (window:willUseFullScreenPresentationOptions:) => on_window_will_use_full_screen_presentation_options as extern fn(&Object, Sel, id, NSUInteger) -> NSUInteger, + (windowDidEnterFullScreen:) => on_window_did_enter_full_screen as extern fn(&Object, Sel, id), + (windowWillEnterFullScreen:) => on_window_will_enter_full_screen as extern fn(&Object, Sel, id), + (windowDidExitFullScreen:) => on_window_did_exit_full_screen as extern fn(&Object, Sel, id), + (windowWillExitFullScreen:) => on_window_will_exit_full_screen as extern fn(&Object, Sel, id), + (windowDidFailToEnterFullScreen:) => on_window_did_fail_to_enter_full_screen as extern fn(&Object, Sel, id), + (effectiveAppearanceDidChange:) => on_effective_appearance_did_change as extern fn(&Object, Sel, id), + (effectiveAppearanceDidChangedOnMainThread:) => on_effective_appearance_did_changed_on_main_thread as extern fn(&Object, Sel, id) + })) + } + + let app = window.app_handle(); + let window = window.clone(); + update_window_theme(&window, HexColor::WHITE); + + // Control window theme based on app update_window + let window = window.clone(); + app.listen_any("yaak_bg_changed", move |ev| { + let payload = serde_json::from_str::<&str>(ev.payload()) + .unwrap() + .trim(); + + let color = HexColor::parse_rgb(payload).unwrap(); + + update_window_theme(&window, color); + }); +} diff --git a/src-tauri/src/models.rs b/src-tauri/src/models.rs index fcaf4409..10e260bd 100644 --- a/src-tauri/src/models.rs +++ b/src-tauri/src/models.rs @@ -4,9 +4,9 @@ use std::fs; use log::error; use rand::distributions::{Alphanumeric, DistString}; use serde::{Deserialize, Serialize}; -use sqlx::types::chrono::NaiveDateTime; -use sqlx::types::{Json, JsonValue}; use sqlx::{Pool, Sqlite}; +use sqlx::types::{Json, JsonValue}; +use sqlx::types::chrono::NaiveDateTime; use tauri::{AppHandle, Manager, WebviewWindow, Wry}; use tokio::sync::Mutex; @@ -52,6 +52,8 @@ pub struct Settings { pub updated_at: NaiveDateTime, pub theme: String, pub appearance: String, + pub theme_dark: String, + pub theme_light: String, pub update_channel: String, } @@ -883,7 +885,8 @@ async fn get_settings(mgr: &impl Manager) -> Result Settings, r#" SELECT - id, model, created_at, updated_at, theme, appearance, update_channel + id, model, created_at, updated_at, theme, appearance, + theme_dark, theme_light, update_channel FROM settings WHERE id = 'default' "#, @@ -919,11 +922,13 @@ pub async fn update_settings( sqlx::query!( r#" UPDATE settings SET ( - theme, appearance, update_channel - ) = (?, ?, ?) WHERE id = 'default'; + theme, appearance, theme_dark, theme_light, update_channel + ) = (?, ?, ?, ?, ?) WHERE id = 'default'; "#, settings.theme, settings.appearance, + settings.theme_dark, + settings.theme_light, settings.update_channel ) .execute(&db) diff --git a/src-tauri/src/updates.rs b/src-tauri/src/updates.rs index 2b75e58f..58611ab3 100644 --- a/src-tauri/src/updates.rs +++ b/src-tauri/src/updates.rs @@ -1,7 +1,7 @@ use std::fmt::{Display, Formatter}; use std::time::SystemTime; -use log::{debug, info}; +use log::info; use tauri::AppHandle; use tauri_plugin_dialog::DialogExt; use tauri_plugin_updater::UpdaterExt; @@ -118,7 +118,6 @@ impl YaakUpdater { // Don't check if dev if is_dev() { - debug!("Not checking for updates in dev"); return Ok(false); } diff --git a/src-tauri/src/win.rs b/src-tauri/src/win.rs new file mode 100644 index 00000000..70f763ec --- /dev/null +++ b/src-tauri/src/win.rs @@ -0,0 +1,79 @@ +// Borrowed from our friends at Hoppscotch +// https://github.com/hoppscotch/hoppscotch/blob/286fcd2bb08a84f027b10308d1e18da368f95ebf/packages/hoppscotch-selfhost-desktop/src-tauri/src/mac/window.rs +use std::mem::transmute; + +use hex_color::HexColor; + +use windows::Win32::Foundation::BOOL; +use windows::Win32::Foundation::COLORREF; +use windows::Win32::Foundation::HWND; +use windows::Win32::Graphics::Dwm::DwmSetWindowAttribute; +use windows::Win32::Graphics::Dwm::DWMWA_CAPTION_COLOR; +use windows::Win32::Graphics::Dwm::DWMWA_USE_IMMERSIVE_DARK_MODE; +use windows::Win32::UI::Controls::{WTA_NONCLIENT, WTNCA_NODRAWICON, WTNCA_NOMIRRORHELP, WTNCA_NOSYSMENU}; +use windows::Win32::UI::Controls::SetWindowThemeAttribute; +use windows::Win32::UI::Controls::WTNCA_NODRAWCAPTION; + +fn hex_color_to_colorref(color: HexColor) -> COLORREF { + // TODO: Remove this unsafe, This operation doesn't need to be unsafe! + unsafe { + COLORREF(transmute::<[u8; 4], u32>([color.r, color.g, color.b, 0])) + } +} + +struct WinThemeAttribute { + flag: u32, + mask: u32 +} + +#[cfg(target_os = "windows")] +fn update_bg_color(hwnd: &HWND, bg_color: HexColor) { + + let use_dark_mode = BOOL::from(true); + + let final_color = hex_color_to_colorref(bg_color); + + unsafe { + DwmSetWindowAttribute( + HWND(hwnd.0), + DWMWA_USE_IMMERSIVE_DARK_MODE, + ptr::addr_of!(use_dark_mode) as *const c_void, + size_of::().try_into().unwrap() + ).unwrap(); + + DwmSetWindowAttribute( + HWND(hwnd.0), + DWMWA_CAPTION_COLOR, + ptr::addr_of!(final_color) as *const c_void, + size_of::().try_into().unwrap() + ).unwrap(); + + let flags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON; + let mask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU | WTNCA_NOMIRRORHELP; + let options = WinThemeAttribute { flag: flags, mask }; + + SetWindowThemeAttribute( + HWND(hwnd.0), + WTA_NONCLIENT, + ptr::addr_of!(options) as *const c_void, + size_of::().try_into().unwrap() + ).unwrap(); + } +} + +#[cfg(target_os = "windows")] +pub fn setup_win_window(window: &mut WebviewWindow) { + let win_handle = window.hwnd().unwrap(); + let win_clone = win_handle.clone(); + + window.listen_global("yaak_bg_changed", move |ev| { + let payload = serde_json::from_str::<&str>(ev.payload().unwrap()) + .unwrap() + .trim(); + + let color = HexColor::parse_rgb(payload).unwrap(); + update_bg_color(&HWND(win_clone.0), color); + }); + + update_bg_color(&HWND(win_handle.0), HexColor::rgb(23, 23, 23)); +} diff --git a/src-tauri/src/window_ext.rs b/src-tauri/src/window_ext.rs deleted file mode 100644 index 6126277c..00000000 --- a/src-tauri/src/window_ext.rs +++ /dev/null @@ -1,53 +0,0 @@ -use tauri::WebviewWindow; - -const TRAFFIC_LIGHT_OFFSET_X: f64 = 13.0; -const TRAFFIC_LIGHT_OFFSET_Y: f64 = 18.0; - -pub trait TrafficLightWindowExt { - fn position_traffic_lights(&self); -} - -impl TrafficLightWindowExt for WebviewWindow { - #[cfg(not(target_os = "macos"))] - fn position_traffic_lights(&self) { - // No-op on other platforms - } - - #[cfg(target_os = "macos")] - fn position_traffic_lights(&self) { - use cocoa::appkit::{NSView, NSWindow, NSWindowButton}; - use cocoa::foundation::NSRect; - - let window = self.ns_window().unwrap() as cocoa::base::id; - - let x = TRAFFIC_LIGHT_OFFSET_X; - let y = TRAFFIC_LIGHT_OFFSET_Y; - - unsafe { - let close = window.standardWindowButton_(NSWindowButton::NSWindowCloseButton); - let miniaturize = - window.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); - let zoom = window.standardWindowButton_(NSWindowButton::NSWindowZoomButton); - - let title_bar_container_view = close.superview().superview(); - - let close_rect: NSRect = msg_send![close, frame]; - let button_height = close_rect.size.height; - - let title_bar_frame_height = button_height + y; - let mut title_bar_rect = NSView::frame(title_bar_container_view); - title_bar_rect.size.height = title_bar_frame_height; - title_bar_rect.origin.y = NSView::frame(window).size.height - title_bar_frame_height; - let _: () = msg_send![title_bar_container_view, setFrame: title_bar_rect]; - - let window_buttons = vec![close, miniaturize, zoom]; - let space_between = NSView::frame(miniaturize).origin.x - NSView::frame(close).origin.x; - - for (i, button) in window_buttons.into_iter().enumerate() { - let mut rect: NSRect = NSView::frame(button); - rect.origin.x = x + (i as f64 * space_between); - button.setFrameOrigin(rect.origin); - } - } - } -} diff --git a/src-web/components/GlobalHooks.tsx b/src-web/components/GlobalHooks.tsx index 35c3caa0..f6d4bc80 100644 --- a/src-web/components/GlobalHooks.tsx +++ b/src-web/components/GlobalHooks.tsx @@ -1,7 +1,5 @@ import { useQueryClient } from '@tanstack/react-query'; import { getCurrent } from '@tauri-apps/api/webviewWindow'; -import { useEffect } from 'react'; -import { useLocation } from 'react-router-dom'; import { useCommandPalette } from '../hooks/useCommandPalette'; import { cookieJarsQueryKey } from '../hooks/useCookieJars'; import { foldersQueryKey } from '../hooks/useFolders'; @@ -19,12 +17,11 @@ import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; import { useRequestUpdateKey } from '../hooks/useRequestUpdateKey'; import { settingsQueryKey } from '../hooks/useSettings'; -import { useSyncAppearance } from '../hooks/useSyncAppearance'; +import { useSyncThemeToDocument } from '../hooks/useSyncThemeToDocument'; import { useSyncWindowTitle } from '../hooks/useSyncWindowTitle'; import { workspacesQueryKey } from '../hooks/useWorkspaces'; import type { Model } from '../lib/models'; import { modelsEq } from '../lib/models'; -import { setPathname } from '../lib/persistPathname'; const DEFAULT_FONT_SIZE = 16; @@ -35,7 +32,7 @@ export function GlobalHooks() { useRecentRequests(); // Other useful things - useSyncAppearance(); + useSyncThemeToDocument(); useSyncWindowTitle(); useGlobalCommands(); useCommandPalette(); @@ -44,12 +41,6 @@ export function GlobalHooks() { const queryClient = useQueryClient(); const { wasUpdatedExternally } = useRequestUpdateKey(null); - // Listen for location changes and update the pathname - const location = useLocation(); - useEffect(() => { - setPathname(location.pathname).catch(console.error); - }, [location.pathname]); - interface ModelPayload { model: Model; windowLabel: string; diff --git a/src-web/components/IsDev.tsx b/src-web/components/IsDev.tsx new file mode 100644 index 00000000..f50bb5f0 --- /dev/null +++ b/src-web/components/IsDev.tsx @@ -0,0 +1,15 @@ +import type { ReactNode } from 'react'; +import { useAppInfo } from '../hooks/useAppInfo'; + +interface Props { + children: ReactNode; +} + +export function IsDev({ children }: Props) { + const appInfo = useAppInfo(); + if (!appInfo?.isDev) { + return null; + } + + return <>{children}; +} diff --git a/src-web/components/ResponsePane.tsx b/src-web/components/ResponsePane.tsx index 660ecf3d..9d463c09 100644 --- a/src-web/components/ResponsePane.tsx +++ b/src-web/components/ResponsePane.tsx @@ -20,9 +20,11 @@ import { TabContent, Tabs } from './core/Tabs/Tabs'; import { EmptyStateText } from './EmptyStateText'; import { RecentResponsesDropdown } from './RecentResponsesDropdown'; import { ResponseHeaders } from './ResponseHeaders'; +import { AudioViewer } from './responseViewers/AudioViewer'; import { CsvViewer } from './responseViewers/CsvViewer'; import { ImageViewer } from './responseViewers/ImageViewer'; import { TextViewer } from './responseViewers/TextViewer'; +import { VideoViewer } from './responseViewers/VideoViewer'; import { WebPageViewer } from './responseViewers/WebPageViewer'; interface Props { @@ -76,7 +78,7 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ 'x-theme-responsePane', 'max-h-full h-full', 'bg-background rounded-md border border-background-highlight', - 'shadow relative', + 'relative', )} > {activeResponse == null ? ( @@ -154,6 +156,10 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ ) : contentType?.startsWith('image') ? ( + ) : contentType?.startsWith('audio') ? ( + + ) : contentType?.startsWith('video') ? ( + ) : activeResponse.contentLength > 2 * 1000 * 1000 ? ( Cannot preview text responses larger than 2MB ) : viewMode === 'pretty' && contentType?.includes('html') ? ( @@ -161,7 +167,11 @@ export const ResponsePane = memo(function ResponsePane({ style, className, activ ) : contentType?.match(/csv|tab-separated/) ? ( ) : ( - + )} diff --git a/src-web/components/Settings/SettingsAppearance.tsx b/src-web/components/Settings/SettingsAppearance.tsx new file mode 100644 index 00000000..e40cae81 --- /dev/null +++ b/src-web/components/Settings/SettingsAppearance.tsx @@ -0,0 +1,162 @@ +import React from 'react'; +import { useActiveWorkspace } from '../../hooks/useActiveWorkspace'; +import { useResolvedAppearance } from '../../hooks/useResolvedAppearance'; +import { useResolvedTheme } from '../../hooks/useResolvedTheme'; +import { useSettings } from '../../hooks/useSettings'; +import { useThemes } from '../../hooks/useThemes'; +import { useUpdateSettings } from '../../hooks/useUpdateSettings'; +import { trackEvent } from '../../lib/analytics'; +import { isThemeDark } from '../../lib/theme/window'; +import type { ButtonProps } from '../core/Button'; +import { Editor } from '../core/Editor'; +import type { IconProps } from '../core/Icon'; +import { IconButton } from '../core/IconButton'; +import type { SelectOption } from '../core/Select'; +import { Select } from '../core/Select'; +import { HStack, VStack } from '../core/Stacks'; + +const buttonColors: ButtonProps['color'][] = [ + 'primary', + 'info', + 'success', + 'notice', + 'warning', + 'danger', + 'secondary', + 'default', +]; + +const icons: IconProps['icon'][] = [ + 'info', + 'box', + 'update', + 'alert', + 'arrowBigRightDash', + 'download', + 'copy', + 'magicWand', + 'settings', + 'trash', + 'sparkles', + 'pencil', + 'paste', + 'search', + 'sendHorizontal', +]; + +export function SettingsAppearance() { + const workspace = useActiveWorkspace(); + const settings = useSettings(); + const updateSettings = useUpdateSettings(); + const appearance = useResolvedAppearance(); + const { themes } = useThemes(); + const activeTheme = useResolvedTheme(); + + if (settings == null || workspace == null) { + return null; + } + + const lightThemes: SelectOption[] = themes + .filter((theme) => !isThemeDark(theme)) + .map((theme) => ({ + label: theme.name, + value: theme.id, + })); + + const darkThemes: SelectOption[] = themes + .filter((theme) => isThemeDark(theme)) + .map((theme) => ({ + label: theme.name, + value: theme.id, + })); + + return ( + + { + await updateSettings.mutateAsync({ ...settings, themeLight }); + trackEvent('setting', 'update', { themeLight }); + }} + /> + } + /> + +
+
+ {buttonColors.map((c, i) => ( + + ))} +
+
+ {buttonColors.map((c, i) => ( + + ))} +
+
+ {icons.map((v, i) => ( + + ))} +
+
+
+ Primary banner + Secondary banner + Danger banner + Warning banner + Success banner +
+ + ); +} diff --git a/src-web/components/Settings/SettingsDialog.tsx b/src-web/components/Settings/SettingsDialog.tsx new file mode 100644 index 00000000..714e6466 --- /dev/null +++ b/src-web/components/Settings/SettingsDialog.tsx @@ -0,0 +1,51 @@ +import classNames from 'classnames'; +import { createGlobalState } from 'react-use'; +import { useAppInfo } from '../../hooks/useAppInfo'; +import { capitalize } from '../../lib/capitalize'; +import { TabContent, Tabs } from '../core/Tabs/Tabs'; +import { SettingsAppearance } from './SettingsAppearance'; +import { SettingsDesign } from './SettingsDesign'; +import { SettingsGeneral } from './SettingsGeneral'; + +enum Tab { + General = 'general', + Appearance = 'appearance', + + // Dev-only + Design = 'design', +} + +const tabs = [Tab.General, Tab.Appearance, Tab.Design]; + +const useTabState = createGlobalState(Tab.Appearance); + +export const SettingsDialog = () => { + const [tab, setTab] = useTabState(); + const appInfo = useAppInfo(); + const isDev = appInfo?.isDev ?? false; + + return ( +
+ t !== Tab.Design || isDev) + .map((value) => ({ value, label: capitalize(value) }))} + > + + + + + + + + + + +
+ ); +}; diff --git a/src-web/components/SettingsDialog.tsx b/src-web/components/Settings/SettingsGeneral.tsx similarity index 64% rename from src-web/components/SettingsDialog.tsx rename to src-web/components/Settings/SettingsGeneral.tsx index e19d6e2a..81fa91c3 100644 --- a/src-web/components/SettingsDialog.tsx +++ b/src-web/components/Settings/SettingsGeneral.tsx @@ -1,20 +1,20 @@ -import { useActiveWorkspace } from '../hooks/useActiveWorkspace'; -import { useAppInfo } from '../hooks/useAppInfo'; -import { useCheckForUpdates } from '../hooks/useCheckForUpdates'; -import { useSettings } from '../hooks/useSettings'; -import { useUpdateSettings } from '../hooks/useUpdateSettings'; -import { useUpdateWorkspace } from '../hooks/useUpdateWorkspace'; -import { trackEvent } from '../lib/analytics'; -import { Checkbox } from './core/Checkbox'; -import { Heading } from './core/Heading'; -import { IconButton } from './core/IconButton'; -import { Input } from './core/Input'; -import { KeyValueRow, KeyValueRows } from './core/KeyValueRow'; -import { Select } from './core/Select'; -import { Separator } from './core/Separator'; -import { VStack } from './core/Stacks'; +import { useActiveWorkspace } from '../../hooks/useActiveWorkspace'; +import { useAppInfo } from '../../hooks/useAppInfo'; +import { useCheckForUpdates } from '../../hooks/useCheckForUpdates'; +import { useSettings } from '../../hooks/useSettings'; +import { useUpdateSettings } from '../../hooks/useUpdateSettings'; +import { useUpdateWorkspace } from '../../hooks/useUpdateWorkspace'; +import { trackEvent } from '../../lib/analytics'; +import { Checkbox } from '../core/Checkbox'; +import { Heading } from '../core/Heading'; +import { IconButton } from '../core/IconButton'; +import { Input } from '../core/Input'; +import { KeyValueRow, KeyValueRows } from '../core/KeyValueRow'; +import { Select } from '../core/Select'; +import { Separator } from '../core/Separator'; +import { VStack } from '../core/Stacks'; -export const SettingsDialog = () => { +export function SettingsGeneral() { const workspace = useActiveWorkspace(); const updateWorkspace = useUpdateWorkspace(workspace?.id ?? null); const settings = useSettings(); @@ -28,32 +28,6 @@ export const SettingsDialog = () => { return ( - { App Info - - - + + + ); -}; +} diff --git a/src-web/components/SettingsDropdown.tsx b/src-web/components/SettingsDropdown.tsx index 30e8904a..310994e7 100644 --- a/src-web/components/SettingsDropdown.tsx +++ b/src-web/components/SettingsDropdown.tsx @@ -11,7 +11,7 @@ import { Icon } from './core/Icon'; import { IconButton } from './core/IconButton'; import { useDialog } from './DialogContext'; import { KeyboardShortcutsDialog } from './KeyboardShortcutsDialog'; -import { SettingsDialog } from './SettingsDialog'; +import { SettingsDialog } from './Settings/SettingsDialog'; export function SettingsDropdown() { const importData = useImportData(); @@ -24,8 +24,9 @@ export function SettingsDropdown() { const showSettings = () => { dialog.show({ id: 'settings', - size: 'md', - title: 'Settings', + size: 'dynamic', + noScroll: true, + noPadding: true, render: () => , }); }; @@ -69,7 +70,7 @@ export function SettingsDropdown() { leftSlot: , onSelect: () => exportData.mutate(), }, - { type: 'separator', label: `Yaak v${appInfo.data?.version}` }, + { type: 'separator', label: `Yaak v${appInfo?.version}` }, { key: 'update-check', label: 'Check for Updates', @@ -88,7 +89,7 @@ export function SettingsDropdown() { label: 'Changelog', leftSlot: , rightSlot: , - onSelect: () => open(`https://yaak.app/changelog/${appInfo.data?.version}`), + onSelect: () => open(`https://yaak.app/changelog/${appInfo?.version}`), }, ]} > diff --git a/src-web/components/Sidebar.tsx b/src-web/components/Sidebar.tsx index 8b0a4816..c7c2395a 100644 --- a/src-web/components/Sidebar.tsx +++ b/src-web/components/Sidebar.tsx @@ -468,47 +468,6 @@ export function Sidebar({ className }: Props) { handleEnd={handleEnd} handleDragStart={handleDragStart} /> - {/*
*/} - {/*
*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/*
*/} - {/*
*/} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/* */} - {/*
*/} - {/*
*/} - {/* Primary banner*/} - {/* Secondary banner*/} - {/* Danger banner*/} - {/* Warning banner*/} - {/* Success banner*/} - {/*
*/} - {/*
*/} ); } @@ -800,11 +759,14 @@ const SidebarItem = forwardRef(function SidebarItem( const name = await prompt({ id: 'rename-request', title: 'Rename Request', - description: ( - <> - Enter a new name for {itemName} - - ), + description: + itemName === '' ? ( + 'Enter a new name' + ) : ( + <> + Enter a new name for {itemName} + + ), name: 'name', label: 'Name', placeholder: 'New Name', @@ -893,7 +855,7 @@ const SidebarItem = forwardRef(function SidebarItem( {isResponseLoading(latestHttpResponse) ? ( ) : ( - + )} ) : null} diff --git a/src-web/components/UrlBar.tsx b/src-web/components/UrlBar.tsx index 40738977..655944e0 100644 --- a/src-web/components/UrlBar.tsx +++ b/src-web/components/UrlBar.tsx @@ -59,7 +59,7 @@ export const UrlBar = memo(function UrlBar({ }; return ( -
+ setIsFocused(true)} onBlur={() => setIsFocused(false)} onPaste={onPaste} - containerClassName="shadow bg-background border" + containerClassName="bg-background border border-background-highlight" onChange={onUrlChange} defaultValue={url} placeholder={placeholder} diff --git a/src-web/components/core/Banner.tsx b/src-web/components/core/Banner.tsx index c94991eb..2b171d84 100644 --- a/src-web/components/core/Banner.tsx +++ b/src-web/components/core/Banner.tsx @@ -4,7 +4,7 @@ import type { ReactNode } from 'react'; interface Props { children: ReactNode; className?: string; - color?: 'primary' | 'secondary' | 'success' | 'warning' | 'danger'; + color?: 'primary' | 'secondary' | 'success' | 'notice' | 'warning' | 'danger'; } export function Banner({ children, className, color = 'secondary' }: Props) { diff --git a/src-web/components/core/Button.tsx b/src-web/components/core/Button.tsx index cbe79153..2e583d58 100644 --- a/src-web/components/core/Button.tsx +++ b/src-web/components/core/Button.tsx @@ -14,11 +14,12 @@ export type ButtonProps = Omit, 'color'> & { | 'primary' | 'info' | 'success' + | 'notice' | 'warning' | 'danger'; variant?: 'border' | 'solid'; isLoading?: boolean; - size?: 'xs' | 'sm' | 'md'; + size?: '2xs' | 'xs' | 'sm' | 'md'; justify?: 'start' | 'center'; type?: 'button' | 'submit'; forDropdown?: boolean; @@ -60,24 +61,27 @@ export const Button = forwardRef(function Button `x-theme-button--${variant}`, `x-theme-button--${variant}--${color}`, 'text-fg', + 'border', // They all have borders to ensure the same width 'max-w-full min-w-0', // Help with truncation 'hocus:opacity-100', // Force opacity for certain hover effects 'whitespace-nowrap outline-none', 'flex-shrink-0 flex items-center', - 'focus-visible-or-class:ring rounded-md', + 'focus-visible-or-class:ring', disabled ? 'pointer-events-none opacity-disabled' : 'pointer-events-auto', justify === 'start' && 'justify-start', justify === 'center' && 'justify-center', - size === 'md' && 'h-md px-3', - size === 'sm' && 'h-sm px-2.5 text-sm', - size === 'xs' && 'h-xs px-2 text-sm', + size === 'md' && 'h-md px-3 rounded-md', + size === 'sm' && 'h-sm px-2.5 text-sm rounded-md', + size === 'xs' && 'h-xs px-2 text-sm rounded-md', + size === '2xs' && 'h-5 px-1 text-xs rounded', // Solids + variant === 'solid' && 'border-transparent', + variant === 'solid' && color === 'custom' && 'ring-blue-400', variant === 'solid' && color !== 'custom' && color !== 'default' && 'bg-background enabled:hocus:bg-background-highlight ring-background-highlight-secondary', - variant === 'solid' && color === 'custom' && 'ring-blue-400', variant === 'solid' && color === 'default' && 'enabled:hocus:bg-background-highlight ring-fg-info', diff --git a/src-web/components/core/Checkbox.tsx b/src-web/components/core/Checkbox.tsx index d16d3365..684037bc 100644 --- a/src-web/components/core/Checkbox.tsx +++ b/src-web/components/core/Checkbox.tsx @@ -30,7 +30,7 @@ export function Checkbox({ alignItems="center" className={classNames(className, 'text-fg text-sm', disabled && 'opacity-disabled')} > -
+
{children} diff --git a/src-web/components/core/Dropdown.tsx b/src-web/components/core/Dropdown.tsx index 7239d185..adf650ef 100644 --- a/src-web/components/core/Dropdown.tsx +++ b/src-web/components/core/Dropdown.tsx @@ -413,7 +413,7 @@ const Menu = forwardRef, MenuPro )} {isOpen && ( -
+
(function E } return ( -
+
{cmContainer} {decoratedActions && ( = { 'application/graphql': graphqlLanguageSupport(), 'application/json': json(), diff --git a/src-web/components/core/Icon.tsx b/src-web/components/core/Icon.tsx index 2bdaa2df..d82f79e4 100644 --- a/src-web/components/core/Icon.tsx +++ b/src-web/components/core/Icon.tsx @@ -66,7 +66,7 @@ const icons = { export interface IconProps { icon: keyof typeof icons; className?: string; - size?: 'xs' | 'sm' | 'md' | 'lg'; + size?: '2xs' | 'xs' | 'sm' | 'md' | 'lg'; spin?: boolean; title?: string; } @@ -83,6 +83,7 @@ export const Icon = memo(function Icon({ icon, spin, size = 'md', className, tit size === 'md' && 'h-4 w-4', size === 'sm' && 'h-3.5 w-3.5', size === 'xs' && 'h-3 w-3', + size === '2xs' && 'h-2.5 w-2.5', spin && 'animate-spin', )} /> diff --git a/src-web/components/core/IconButton.tsx b/src-web/components/core/IconButton.tsx index e8904620..5ae12c5f 100644 --- a/src-web/components/core/IconButton.tsx +++ b/src-web/components/core/IconButton.tsx @@ -57,6 +57,7 @@ export const IconButton = forwardRef(function IconButt size === 'md' && 'w-9', size === 'sm' && 'w-8', size === 'xs' && 'w-6', + size === '2xs' && 'w-5', )} {...props} > diff --git a/src-web/components/core/InlineCode.tsx b/src-web/components/core/InlineCode.tsx index 788681a3..f43e7502 100644 --- a/src-web/components/core/InlineCode.tsx +++ b/src-web/components/core/InlineCode.tsx @@ -6,8 +6,8 @@ export function InlineCode({ className, ...props }: HTMLAttributes diff --git a/src-web/components/core/Input.tsx b/src-web/components/core/Input.tsx index 83efec5b..fba19719 100644 --- a/src-web/components/core/Input.tsx +++ b/src-web/components/core/Input.tsx @@ -145,6 +145,7 @@ export const Input = forwardRef(function Inp alignItems="stretch" className={classNames( containerClassName, + 'x-theme-input', 'relative w-full rounded-md text-fg', 'border', focused ? 'border-border-focus' : 'border-background-highlight', diff --git a/src-web/components/core/RadioDropdown.tsx b/src-web/components/core/RadioDropdown.tsx index 155ade41..2ed68567 100644 --- a/src-web/components/core/RadioDropdown.tsx +++ b/src-web/components/core/RadioDropdown.tsx @@ -1,3 +1,4 @@ +import type { ReactNode } from 'react'; import { useMemo } from 'react'; import type { DropdownItem, DropdownItemSeparator, DropdownProps } from './Dropdown'; import { Dropdown } from './Dropdown'; @@ -9,6 +10,7 @@ export type RadioDropdownItem = label: string; shortLabel?: string; value: T; + rightSlot?: ReactNode; } | DropdownItemSeparator; @@ -37,9 +39,10 @@ export function RadioDropdown({ key: item.label, label: item.label, shortLabel: item.shortLabel, + rightSlot: item.rightSlot, onSelect: () => onChange(item.value), leftSlot: , - }; + } as DropdownProps['items'][0]; } }), ...((extraItems ? [{ type: 'separator' }, ...extraItems] : []) as DropdownItem[]), diff --git a/src-web/components/core/Select.tsx b/src-web/components/core/Select.tsx index 299cdcdb..4feedc47 100644 --- a/src-web/components/core/Select.tsx +++ b/src-web/components/core/Select.tsx @@ -7,12 +7,17 @@ interface Props { labelClassName?: string; hideLabel?: boolean; value: T; - options: { label: string; value: T }[]; + options: SelectOption[]; onChange: (value: T) => void; size?: 'xs' | 'sm' | 'md' | 'lg'; className?: string; } +export interface SelectOption { + label: string; + value: T; +} + export function Select({ labelPosition = 'top', name, @@ -30,6 +35,7 @@ export function Select({
(null); @@ -78,12 +79,15 @@ export function Tabs({ '-ml-5 pl-3 pr-1 py-1', )} > - + {tabs.map((t) => { const isActive = t.value === value; const btnClassName = classNames( - isActive ? 'text-fg' : 'text-fg-subtler hover:text-fg-subtle', + 'h-full flex items-center text-sm rounded', '!px-2 ml-[1px]', + addBorders && 'border', + isActive ? 'text-fg' : 'text-fg-subtler hover:text-fg-subtle', + isActive && addBorders ? 'border-background-highlight' : 'border-transparent', ); if ('options' in t) { @@ -97,39 +101,34 @@ export function Tabs({ value={t.options.value} onChange={t.options.onChange} > - + + + ); } else { return ( - + + ); } })} @@ -161,3 +160,14 @@ export const TabContent = memo(function TabContent({
); }); + +function TabAccent({ isActive, enabled }: { isActive: boolean; enabled: boolean }) { + return ( +
+ ); +} diff --git a/src-web/components/core/Toast.tsx b/src-web/components/core/Toast.tsx index fe0bbc94..22a0239e 100644 --- a/src-web/components/core/Toast.tsx +++ b/src-web/components/core/Toast.tsx @@ -52,11 +52,11 @@ export function Toast({ transition={{ duration: 0.2 }} className={classNames( className, - 'x-theme-dialog', + 'x-theme-toast', 'pointer-events-auto', 'relative bg-background pointer-events-auto', 'rounded-lg', - 'border border-background-highlight dark:border-background-highlight-secondary shadow-xl', + 'border border-background-highlight shadow-lg', 'max-w-[calc(100vw-5rem)] max-h-[calc(100vh-6rem)]', 'w-[22rem] max-h-[80vh]', 'm-2 grid grid-cols-[1fr_auto]', diff --git a/src-web/components/responseViewers/AudioViewer.tsx b/src-web/components/responseViewers/AudioViewer.tsx new file mode 100644 index 00000000..9389dc9d --- /dev/null +++ b/src-web/components/responseViewers/AudioViewer.tsx @@ -0,0 +1,18 @@ +import { convertFileSrc } from '@tauri-apps/api/core'; +import React from 'react'; +import type { HttpResponse } from '../../lib/models'; + +interface Props { + response: HttpResponse; +} + +export function AudioViewer({ response }: Props) { + if (response.bodyPath === null) { + return
Empty response body
; + } + + const src = convertFileSrc(response.bodyPath); + + // eslint-disable-next-line jsx-a11y/media-has-caption + return ; +} diff --git a/src-web/components/responseViewers/ImageViewer.tsx b/src-web/components/responseViewers/ImageViewer.tsx index a1983d52..6c1a941c 100644 --- a/src-web/components/responseViewers/ImageViewer.tsx +++ b/src-web/components/responseViewers/ImageViewer.tsx @@ -2,7 +2,6 @@ import { convertFileSrc } from '@tauri-apps/api/core'; import classNames from 'classnames'; import { useState } from 'react'; import type { HttpResponse } from '../../lib/models'; -import { Button } from '../core/Button'; interface Props { response: HttpResponse; @@ -23,13 +22,9 @@ export function ImageViewer({ response, className }: Props) { <>
Response body is too large to preview.{' '} - +
); diff --git a/src-web/components/responseViewers/TextViewer.tsx b/src-web/components/responseViewers/TextViewer.tsx index 6becee36..241faa1d 100644 --- a/src-web/components/responseViewers/TextViewer.tsx +++ b/src-web/components/responseViewers/TextViewer.tsx @@ -18,9 +18,10 @@ const extraExtensions = [hyperlink]; interface Props { response: HttpResponse; pretty: boolean; + className?: string; } -export function TextViewer({ response, pretty }: Props) { +export function TextViewer({ response, pretty, className }: Props) { const [isSearching, toggleIsSearching] = useToggle(); const [filterText, setDebouncedFilterText, setFilterText] = useDebouncedState('', 400); @@ -85,6 +86,7 @@ export function TextViewer({ response, pretty }: Props) { return ( Empty response body
; + } + + const src = convertFileSrc(response.bodyPath); + + // eslint-disable-next-line jsx-a11y/media-has-caption + return ; +} diff --git a/src-web/hooks/useAppInfo.ts b/src-web/hooks/useAppInfo.ts index b22b7c1b..19b0a648 100644 --- a/src-web/hooks/useAppInfo.ts +++ b/src-web/hooks/useAppInfo.ts @@ -16,5 +16,5 @@ export function useAppInfo() { const metadata = await invoke('cmd_metadata'); return metadata as AppInfo; }, - }); + }).data; } diff --git a/src-web/hooks/useCommandPalette.tsx b/src-web/hooks/useCommandPalette.tsx index 432e322a..279cec94 100644 --- a/src-web/hooks/useCommandPalette.tsx +++ b/src-web/hooks/useCommandPalette.tsx @@ -8,7 +8,7 @@ export function useCommandPalette() { const appInfo = useAppInfo(); useHotKey('command_palette.toggle', () => { // Disabled in production for now - if (!appInfo.data?.isDev) { + if (!appInfo?.isDev) { return; } diff --git a/src-web/hooks/useSyncAppearance.ts b/src-web/hooks/useResolvedAppearance.ts similarity index 62% rename from src-web/hooks/useSyncAppearance.ts rename to src-web/hooks/useResolvedAppearance.ts index 010e82d8..8839c29b 100644 --- a/src-web/hooks/useSyncAppearance.ts +++ b/src-web/hooks/useResolvedAppearance.ts @@ -1,35 +1,23 @@ import { useEffect, useState } from 'react'; import type { Appearance } from '../lib/theme/window'; -import { - setAppearanceOnDocument, - getPreferredAppearance, - subscribeToPreferredAppearanceChange, -} from '../lib/theme/window'; +import { getPreferredAppearance, subscribeToPreferredAppearanceChange } from '../lib/theme/window'; import { useSettings } from './useSettings'; -export function useSyncAppearance() { +export function useResolvedAppearance() { const [preferredAppearance, setPreferredAppearance] = useState( getPreferredAppearance(), ); - const settings = useSettings(); - // Set appearance when preferred theme changes useEffect(() => { return subscribeToPreferredAppearanceChange(setPreferredAppearance); }, []); + const settings = useSettings(); const appearance = settings == null || settings?.appearance === 'system' ? preferredAppearance : settings.appearance; - useEffect(() => { - if (settings == null) { - return; - } - setAppearanceOnDocument(settings.appearance as Appearance); - }, [appearance, settings]); - - return { appearance }; + return appearance; } diff --git a/src-web/hooks/useResolvedTheme.ts b/src-web/hooks/useResolvedTheme.ts new file mode 100644 index 00000000..47e79144 --- /dev/null +++ b/src-web/hooks/useResolvedTheme.ts @@ -0,0 +1,20 @@ +import { isThemeDark } from '../lib/theme/window'; +import { useResolvedAppearance } from './useResolvedAppearance'; +import { useSettings } from './useSettings'; +import { useThemes } from './useThemes'; + +export function useResolvedTheme() { + const appearance = useResolvedAppearance(); + const settings = useSettings(); + const { themes, fallback } = useThemes(); + + const darkThemes = themes.filter((t) => isThemeDark(t)); + const lightThemes = themes.filter((t) => !isThemeDark(t)); + + const dark = darkThemes.find((t) => t.id === settings?.themeDark) ?? fallback.dark; + const light = lightThemes.find((t) => t.id === settings?.themeLight) ?? fallback.light; + + const active = appearance === 'dark' ? dark : light; + + return { dark, light, active }; +} diff --git a/src-web/hooks/useSyncThemeToDocument.ts b/src-web/hooks/useSyncThemeToDocument.ts new file mode 100644 index 00000000..219582ac --- /dev/null +++ b/src-web/hooks/useSyncThemeToDocument.ts @@ -0,0 +1,23 @@ +import { emit } from '@tauri-apps/api/event'; +import { useEffect } from 'react'; +import type { YaakTheme } from '../lib/theme/window'; +import { addThemeStylesToDocument, setThemeOnDocument } from '../lib/theme/window'; +import { useResolvedTheme } from './useResolvedTheme'; + +export function useSyncThemeToDocument() { + const theme = useResolvedTheme(); + + useEffect(() => { + setThemeOnDocument(theme.active); + emitBgChange(theme.active); + }, [theme.active]); + + useEffect(() => { + addThemeStylesToDocument(theme.active); + }, [theme.active]); +} + +function emitBgChange(t: YaakTheme) { + if (t.background == null) return; + emit('yaak_bg_changed', t.background.hex()).catch(console.error); +} diff --git a/src-web/hooks/useSyncWindowTitle.ts b/src-web/hooks/useSyncWindowTitle.ts index 657fcba8..41b69563 100644 --- a/src-web/hooks/useSyncWindowTitle.ts +++ b/src-web/hooks/useSyncWindowTitle.ts @@ -1,23 +1,24 @@ -// import { useEffect } from 'react'; -// import { fallbackRequestName } from '../lib/fallbackRequestName'; -// import { useActiveEnvironment } from './useActiveEnvironment'; -// import { useActiveRequest } from './useActiveRequest'; -// import { useActiveWorkspace } from './useActiveWorkspace'; +import { useEffect } from 'react'; +import { fallbackRequestName } from '../lib/fallbackRequestName'; +import { useActiveEnvironment } from './useActiveEnvironment'; +import { useActiveRequest } from './useActiveRequest'; +import { useActiveWorkspace } from './useActiveWorkspace'; export function useSyncWindowTitle() { - // const activeRequest = useActiveRequest(); - // const activeWorkspace = useActiveWorkspace(); - // const activeEnvironment = useActiveEnvironment(); - // useEffect(() => { - // let newTitle = activeWorkspace ? activeWorkspace.name : 'Yaak'; - // if (activeEnvironment) { - // newTitle += ` [${activeEnvironment.name}]`; - // } - // if (activeRequest) { - // newTitle += ` – ${fallbackRequestName(activeRequest)}`; - // } - // - // // TODO: This resets the stoplight position so we can't use it yet - // // getCurrent().setTitle(newTitle).catch(console.error); - // }, [activeEnvironment, activeRequest, activeWorkspace]); + const activeRequest = useActiveRequest(); + const activeWorkspace = useActiveWorkspace(); + const activeEnvironment = useActiveEnvironment(); + useEffect(() => { + let newTitle = activeWorkspace ? activeWorkspace.name : 'Yaak'; + if (activeEnvironment) { + newTitle += ` [${activeEnvironment.name}]`; + } + if (activeRequest) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + newTitle += ` – ${fallbackRequestName(activeRequest)}`; + } + + // TODO: This resets the stoplight position so we can't use it yet + // invoke('cmd_set_title', { title: newTitle }).catch(console.error); + }, [activeEnvironment, activeRequest, activeWorkspace]); } diff --git a/src-web/hooks/useThemes.ts b/src-web/hooks/useThemes.ts new file mode 100644 index 00000000..91c609f0 --- /dev/null +++ b/src-web/hooks/useThemes.ts @@ -0,0 +1,13 @@ +import { yaakDark, yaakLight, yaakThemes } from '../lib/theme/themes'; + +export function useThemes() { + const dark = yaakDark; + const light = yaakLight; + + const otherThemes = yaakThemes + .filter((t) => t.id !== dark.id && t.id !== light.id) + .sort((a, b) => a.name.localeCompare(b.name)); + + const themes = [dark, light, ...otherThemes]; + return { themes, fallback: { dark, light } }; +} diff --git a/src-web/lib/fallbackRequestName.ts b/src-web/lib/fallbackRequestName.ts index 4a10c854..27ad3c70 100644 --- a/src-web/lib/fallbackRequestName.ts +++ b/src-web/lib/fallbackRequestName.ts @@ -23,7 +23,6 @@ export function fallbackRequestName(r: HttpRequest | GrpcRequest | null): string try { const url = new URL(fixedUrl); const pathname = url.pathname === '/' ? '' : url.pathname; - console.log('hello', fixedUrl); return `${url.host}${pathname}`; } catch (_) { // Nothing diff --git a/src-web/lib/models.ts b/src-web/lib/models.ts index 4ef5e59f..6c137633 100644 --- a/src-web/lib/models.ts +++ b/src-web/lib/models.ts @@ -34,6 +34,8 @@ export interface Settings extends BaseModel { readonly model: 'settings'; theme: string; appearance: string; + themeLight: string; + themeDark: string; updateChannel: string; } diff --git a/src-web/lib/persistPathname.ts b/src-web/lib/persistPathname.ts deleted file mode 100644 index 99df02d7..00000000 --- a/src-web/lib/persistPathname.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { getCurrent } from '@tauri-apps/api/webviewWindow'; -import { getKeyValue, setKeyValue } from './keyValueStore'; - -const key = ['window_pathname', getCurrent().label]; -const namespace = 'no_sync'; -const fallback = undefined; - -export async function setPathname(value: string) { - await setKeyValue({ key, namespace, value }); -} - -export async function maybeRestorePathname() { - if (window.location.pathname !== '/') { - return; - } - - const pathname = await getKeyValue({ key, namespace, fallback }); - if (pathname != null) { - window.location.replace(pathname); - } -} diff --git a/src-web/lib/theme/color.ts b/src-web/lib/theme/color.ts index 9d375011..ad7c8b36 100644 --- a/src-web/lib/theme/color.ts +++ b/src-web/lib/theme/color.ts @@ -22,7 +22,15 @@ export class Color { } static transparent(): Color { - return new Color('rgba(0, 0, 0, 0.1)', 'light'); + return new Color('rgb(0,0,0)', 'light').translucify(1); + } + + static white(): Color { + return new Color('rgb(0,0,0)', 'light').lower(1); + } + + static black(): Color { + return new Color('rgb(0,0,0)', 'light').lift(1); } private clone(): Color { @@ -80,6 +88,10 @@ export class Color { return `hsla(${h}, ${s}%, ${l}%, ${a})`; } + hex(): string { + return parseColor(this.css()).hex; + } + private _lighten(mod: number): Color { const c = this.clone(); c.lightness = this.lightness + (100 - this.lightness) * mod; diff --git a/src-web/lib/theme/themes.ts b/src-web/lib/theme/themes.ts new file mode 100644 index 00000000..611c034b --- /dev/null +++ b/src-web/lib/theme/themes.ts @@ -0,0 +1,376 @@ +import { Color } from './color'; +import type { YaakTheme } from './window'; + +export const yaakLight: YaakTheme = { + id: 'yaak-light', + name: 'Yaak', + background: new Color('#f2f4f7', 'light').lower(1), + foreground: new Color('hsl(219,23%,15%)', 'light'), + colors: { + primary: new Color('hsl(266,100%,70%)', 'light'), + secondary: new Color('hsl(220,24%,59%)', 'light'), + info: new Color('hsl(206,100%,48%)', 'light'), + success: new Color('hsl(155,95%,33%)', 'light'), + notice: new Color('hsl(45,100%,41%)', 'light'), + warning: new Color('hsl(30,100%,43%)', 'light'), + danger: new Color('hsl(335,75%,57%)', 'light'), + }, + components: { + sidebar: { + background: new Color('#f2f4f7', 'light').lower(1), + }, + }, +}; + +export const yaakDark: YaakTheme = { + id: 'yaak-dark', + name: 'Yaak', + background: new Color('hsl(244,23%,12%)', 'dark'), + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.17), + backgroundHighlightSecondary: new Color('hsl(244,23%,12%)', 'dark').lift(0.1), + foreground: new Color('#bcbad4', 'dark'), + + colors: { + primary: new Color('hsl(266,100%,79%)', 'dark'), + secondary: new Color('hsl(245,23%,60%)', 'dark'), + info: new Color('hsl(206,100%,63%)', 'dark'), + success: new Color('hsl(150,99%,44%)', 'dark'), + notice: new Color('hsl(48,80%,63%)', 'dark'), + warning: new Color('hsl(28,100%,61%)', 'dark'), + danger: new Color('hsl(342,90%,68%)', 'dark'), + }, + + components: { + button: { + colors: { + primary: new Color('hsl(266,100%,79%)', 'dark').lower(0.1), + secondary: new Color('hsl(245,23%,60%)', 'dark').lower(0.1), + info: new Color('hsl(206,100%,63%)', 'dark').lower(0.1), + success: new Color('hsl(150,99%,44%)', 'dark').lower(0.1), + notice: new Color('hsl(48,80%,63%)', 'dark').lower(0.1), + warning: new Color('hsl(28,100%,61%)', 'dark').lower(0.1), + danger: new Color('hsl(342,90%,68%)', 'dark').lower(0.1), + }, + }, + input: { + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.18), + }, + dialog: { + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.11), + }, + sidebar: { + background: new Color('hsl(243,23%,15%)', 'dark'), + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.09), + }, + responsePane: { + background: new Color('hsl(243,23%,15%)', 'dark'), + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.09), + }, + appHeader: { + background: new Color('hsl(244,23%,12%)', 'dark'), + backgroundHighlight: new Color('hsl(244,23%,12%)', 'dark').lift(0.1), + }, + }, +}; + +const monokaiProOctagon: YaakTheme = { + id: 'monokai-pro-octagon', + name: 'Monokai Pro Octagon', + background: new Color('#282a3a', 'dark'), + foreground: new Color('#eaf2f1', 'dark'), + foregroundSubtle: new Color('#b2b9bd', 'dark'), + foregroundSubtler: new Color('#767b81', 'dark'), + + colors: { + primary: new Color('#c39ac9', 'dark'), + secondary: new Color('#b2b9bd', 'dark'), + info: new Color('#9cd1bb', 'dark'), + success: new Color('#bad761', 'dark'), + notice: new Color('#ffd76d', 'dark'), + warning: new Color('#ff9b5e', 'dark'), + danger: new Color('#ff657a', 'dark'), + }, + + components: { + appHeader: { + background: new Color('#1e1f2b', 'dark'), + foreground: new Color('#b2b9bd', 'dark'), + foregroundSubtle: new Color('#767b81', 'dark'), + foregroundSubtler: new Color('#696d77', 'dark'), + }, + button: { + colors: { + primary: new Color('#c39ac9', 'dark').lower(0.1).desaturate(0.1), + secondary: new Color('#b2b9bd', 'dark').lower(0.1).desaturate(0.1), + info: new Color('#9cd1bb', 'dark').lower(0.1).desaturate(0.1), + success: new Color('#bad761', 'dark').lower(0.1).desaturate(0.1), + notice: new Color('#ffd76d', 'dark').lower(0.1).desaturate(0.1), + warning: new Color('#ff9b5e', 'dark').lower(0.1).desaturate(0.1), + danger: new Color('#ff657a', 'dark').lower(0.1).desaturate(0.1), + }, + }, + }, +}; + +const catppuccinLatte: YaakTheme = { + name: 'Catppuccin Latte', + id: 'catppuccin-light', + background: new Color('#eff1f5', 'light'), + foreground: new Color('#4c4f69', 'dark'), + foregroundSubtle: new Color('#6c6f85', 'light'), + foregroundSubtler: new Color('#8c8fa1', 'light'), + colors: { + primary: new Color('#8839ef', 'light'), + secondary: new Color('#6c6f85', 'light'), + info: new Color('#7287fd', 'light'), + success: new Color('#179299', 'light'), + notice: new Color('#df8e1d', 'light'), + warning: new Color('#fe640b', 'light'), + danger: new Color('#e64553', 'light'), + }, + components: { + sidebar: { + background: new Color('#e6e9ef', 'light'), + backgroundHighlight: new Color('#e6e9ef', 'light').lift(0.05), + foregroundSubtler: new Color('#7287fd', 'light'), + }, + appHeader: { + background: new Color('#dce0e8', 'light'), + backgroundHighlight: new Color('#e6e9ef', 'light').lift(0.05), + foregroundSubtler: new Color('#7287fd', 'light'), + }, + }, +}; + +const catppuccinMocha: YaakTheme = { + name: 'Catppuccin Mocha', + id: 'catppuccin-mocha', + background: new Color('#181825', 'dark'), + foreground: new Color('#cdd6f4', 'dark'), + foregroundSubtle: new Color('#a6adc8', 'dark'), + foregroundSubtler: new Color('#7f849c', 'dark'), + colors: { + primary: new Color('#c6a0f6', 'dark'), + secondary: new Color('#bac2de', 'dark'), + info: new Color('#89b4fa', 'dark'), + success: new Color('#a6e3a1', 'dark'), + notice: new Color('#f9e2af', 'dark'), + warning: new Color('#fab387', 'dark'), + danger: new Color('#f38ba8', 'dark'), + }, + components: { + dialog: { + background: new Color('#181825', 'dark'), + }, + sidebar: { + background: new Color('#1e1e2e', 'dark'), + backgroundHighlight: new Color('#1e1e2e', 'dark').lift(0.05), + }, + appHeader: { + background: new Color('#11111b', 'dark'), + backgroundHighlight: new Color('#11111b', 'dark').lift(0.1), + }, + responsePane: { + background: new Color('#1e1e2e', 'dark'), + backgroundHighlight: new Color('#1e1e2e', 'dark').lift(0.05), + }, + button: { + colors: { + primary: new Color('#cba6f7', 'dark').lower(0.2).desaturate(0.2), + secondary: new Color('#bac2de', 'dark').lower(0.2).desaturate(0.2), + info: new Color('#89b4fa', 'dark').lower(0.2).desaturate(0.2), + success: new Color('#a6e3a1', 'dark').lower(0.2).desaturate(0.2), + notice: new Color('#f9e2af', 'dark').lower(0.2).desaturate(0.2), + warning: new Color('#fab387', 'dark').lower(0.2).desaturate(0.2), + danger: new Color('#f38ba8', 'dark').lower(0.2).desaturate(0.2), + }, + }, + }, +}; + +const relaxing: YaakTheme = { + name: 'Relaxing', + id: 'relaxing', + background: new Color('#2b1e3b', 'dark'), + foreground: new Color('#ede2f5', 'dark'), + colors: { + primary: new Color('#cba6f7', 'dark'), + secondary: new Color('#bac2de', 'dark'), + info: new Color('#89b4fa', 'dark'), + success: new Color('#a6e3a1', 'dark'), + notice: new Color('#f9e2af', 'dark'), + warning: new Color('#fab387', 'dark'), + danger: new Color('#f38ba8', 'dark'), + }, +}; + +export const rosePineMoon: YaakTheme = { + id: 'rose-pine-moon', + name: 'Rosé Pine Moon', + background: new Color('#232136', 'dark'), + foreground: new Color('#e0def4', 'dark'), + foregroundSubtle: new Color('#908caa', 'dark'), + foregroundSubtler: new Color('#6e6a86', 'dark'), + colors: { + primary: new Color('#c4a7e7', 'dark'), + secondary: new Color('#908caa', 'dark'), + info: new Color('#68aeca', 'dark'), + success: new Color('#9ccfd8', 'dark'), + notice: new Color('#f6c177', 'dark'), + warning: new Color('#ea9a97', 'dark'), + danger: new Color('#eb6f92', 'dark'), + }, + components: { + responsePane: { + background: new Color('#2a273f', 'dark'), + }, + sidebar: { + background: new Color('#2a273f', 'dark'), + }, + menu: { + background: new Color('#393552', 'dark'), + foregroundSubtle: new Color('#908caa', 'dark').lift(0.15), + foregroundSubtler: new Color('#6e6a86', 'dark').lift(0.15), + }, + }, +}; + +export const rosePineDawn: YaakTheme = { + id: 'rose-pine-dawn', + name: 'Rosé Pine Dawn', + background: new Color('#faf4ed', 'light'), + backgroundHighlight: new Color('#dfdad9', 'light'), + backgroundHighlightSecondary: new Color('#f4ede8', 'light'), + foreground: new Color('#575279', 'light'), + foregroundSubtle: new Color('#797593', 'light'), + foregroundSubtler: new Color('#9893a5', 'light'), + colors: { + primary: new Color('#9070ad', 'light'), + secondary: new Color('#6e6a86', 'light'), + info: new Color('#2d728d', 'light'), + success: new Color('#4f8c96', 'light'), + notice: new Color('#cb862d', 'light'), + warning: new Color('#ce7b78', 'light'), + danger: new Color('#b4637a', 'light'), + }, + components: { + responsePane: { + backgroundHighlight: new Color('#e8e4e2', 'light'), + }, + sidebar: { + backgroundHighlight: new Color('#e8e4e2', 'light'), + }, + appHeader: { + backgroundHighlight: new Color('#e8e4e2', 'light'), + }, + input: { + backgroundHighlight: new Color('#dfdad9', 'light'), + }, + dialog: { + backgroundHighlight: new Color('#e8e4e2', 'light'), + }, + menu: { + background: new Color('#f2e9e1', 'light'), + backgroundHighlight: new Color('#dfdad9', 'light'), + backgroundHighlightSecondary: new Color('#6e6a86', 'light'), + }, + }, +}; + +export const rosePine: YaakTheme = { + id: 'rose-pine', + name: 'Rosé Pine', + background: new Color('#191724', 'dark'), + foreground: new Color('#e0def4', 'dark'), + foregroundSubtle: new Color('#908caa', 'dark'), + foregroundSubtler: new Color('#6e6a86', 'dark'), + colors: { + primary: new Color('#c4a7e7', 'dark'), + secondary: new Color('#6e6a86', 'dark'), + info: new Color('#67abcb', 'dark'), + success: new Color('#9cd8d8', 'dark'), + notice: new Color('#f6c177', 'dark'), + warning: new Color('#f1a3a1', 'dark'), + danger: new Color('#eb6f92', 'dark'), + }, + components: { + responsePane: { + background: new Color('#1f1d2e', 'dark'), + }, + sidebar: { + background: new Color('#1f1d2e', 'dark'), + }, + menu: { + background: new Color('#393552', 'dark'), + foregroundSubtle: new Color('#908caa', 'dark').lift(0.15), + foregroundSubtler: new Color('#6e6a86', 'dark').lift(0.15), + }, + }, +}; + +export const githubDark: YaakTheme = { + id: 'github-dark', + name: 'GitHub', + background: new Color('#0d1218', 'dark'), + backgroundHighlight: new Color('#171c23', 'dark'), + backgroundHighlightSecondary: new Color('#1c2127', 'dark'), + foreground: new Color('#dce3eb', 'dark'), + foregroundSubtle: new Color('#88919b', 'dark'), + foregroundSubtler: new Color('#6b727d', 'dark'), + colors: { + primary: new Color('#a579ef', 'dark').lift(0.1), + secondary: new Color('#6b727d', 'dark').lift(0.1), + info: new Color('#458def', 'dark').lift(0.1), + success: new Color('#3eb24f', 'dark').lift(0.1), + notice: new Color('#dca132', 'dark').lift(0.1), + warning: new Color('#ec7934', 'dark').lift(0.1), + danger: new Color('#ee5049', 'dark').lift(0.1), + }, + components: { + button: { + colors: { + primary: new Color('#a579ef', 'dark'), + secondary: new Color('#6b727d', 'dark'), + info: new Color('#458def', 'dark'), + success: new Color('#3eb24f', 'dark'), + notice: new Color('#dca132', 'dark'), + warning: new Color('#ec7934', 'dark'), + danger: new Color('#ee5049', 'dark'), + }, + }, + }, +}; + +export const githubLight: YaakTheme = { + id: 'github-light', + name: 'GitHub', + background: new Color('#ffffff', 'light'), + backgroundHighlight: new Color('#e8ebee', 'light'), + backgroundHighlightSecondary: new Color('#f6f8fa', 'light'), + foreground: new Color('#1f2328', 'light'), + foregroundSubtle: new Color('#636c76', 'light'), + foregroundSubtler: new Color('#828d94', 'light'), + colors: { + primary: new Color('#8250df', 'light'), + secondary: new Color('#6e7781', 'light'), + info: new Color('#0969da', 'light'), + success: new Color('#1a7f37', 'light'), + notice: new Color('#9a6700', 'light'), + warning: new Color('#bc4c00', 'light'), + danger: new Color('#d1242f', 'light'), + }, +}; + +export const yaakThemes = [ + yaakLight, + yaakDark, + catppuccinMocha, + catppuccinLatte, + relaxing, + monokaiProOctagon, + rosePine, + rosePineMoon, + rosePineDawn, + githubLight, + githubDark, +]; diff --git a/src-web/lib/theme/window.ts b/src-web/lib/theme/window.ts index d06c6440..3dedf6a2 100644 --- a/src-web/lib/theme/window.ts +++ b/src-web/lib/theme/window.ts @@ -1,10 +1,9 @@ +import { getCurrent } from '@tauri-apps/api/webviewWindow'; import { indent } from '../indent'; import { Color } from './color'; export type Appearance = 'dark' | 'light' | 'system'; -const DEFAULT_APPEARANCE: Appearance = 'system'; - interface ThemeComponent { background?: Color; backgroundHighlight?: Color; @@ -13,19 +12,26 @@ interface ThemeComponent { foreground?: Color; foregroundSubtle?: Color; foregroundSubtler?: Color; + shadow?: Color; colors?: Partial; } -interface YaakTheme extends ThemeComponent { +export interface YaakTheme extends ThemeComponent { + id: string; name: string; components?: { dialog?: ThemeComponent; + menu?: ThemeComponent; + toast?: ThemeComponent; sidebar?: ThemeComponent; responsePane?: ThemeComponent; appHeader?: ThemeComponent; button?: ThemeComponent; banner?: ThemeComponent; placeholder?: ThemeComponent; + urlBar?: ThemeComponent; + editor?: ThemeComponent; + input?: ThemeComponent; }; } @@ -42,94 +48,6 @@ interface RootColors { type ColorName = keyof RootColors; type ComponentName = keyof NonNullable; -const yaakThemes: Record = { - yaakLight: { - name: 'Yaak (Light)', - background: new Color('#f2f4f7', 'light').lower(1), - foreground: new Color('hsl(219,23%,15%)', 'light'), - colors: { - primary: new Color('hsl(266,100%,70%)', 'light'), - secondary: new Color('hsl(220,24%,59%)', 'light'), - info: new Color('hsl(206,100%,48%)', 'light'), - success: new Color('hsl(155,95%,33%)', 'light'), - notice: new Color('hsl(45,100%,41%)', 'light'), - warning: new Color('hsl(30,100%,43%)', 'light'), - danger: new Color('hsl(335,75%,57%)', 'light'), - }, - components: { - sidebar: { - background: new Color('#f2f4f7', 'light'), - }, - }, - } as YaakTheme, - - yaakDark: { - name: 'Yaak Dark', - background: new Color('hsl(244,23%,12%)', 'dark'), - foreground: new Color('#bcbad4', 'dark'), - - colors: { - primary: new Color('hsl(266,100%,79%)', 'dark'), - secondary: new Color('hsl(245,23%,60%)', 'dark'), - info: new Color('hsl(206,100%,63%)', 'dark'), - success: new Color('hsl(150,100%,37%)', 'dark'), - notice: new Color('hsl(48,80%,63%)', 'dark'), - warning: new Color('hsl(28,100%,61%)', 'dark'), - danger: new Color('hsl(342,90%,68%)', 'dark'), - }, - - components: { - sidebar: { - background: new Color('hsl(243,23%,15%)', 'dark'), - }, - responsePane: { - background: new Color('hsl(243,23%,15%)', 'dark'), - }, - }, - }, - catppuccin: { - name: 'Catppuccin', - background: new Color('#181825', 'dark'), - foreground: new Color('#cdd6f4', 'dark'), - foregroundSubtle: new Color('#cdd6f4', 'dark').lower(0.1).translucify(0.3), - foregroundSubtler: new Color('#cdd6f4', 'dark').lower(0.1).translucify(0.55), - colors: { - primary: new Color('#cba6f7', 'dark'), - secondary: new Color('#bac2de', 'dark'), - info: new Color('#89b4fa', 'dark'), - success: new Color('#a6e3a1', 'dark'), - notice: new Color('#f9e2af', 'dark'), - warning: new Color('#fab387', 'dark'), - danger: new Color('#f38ba8', 'dark'), - }, - components: { - dialog: { - background: new Color('#181825', 'dark'), - }, - sidebar: { - background: new Color('#1e1e2e', 'dark'), - }, - appHeader: { - background: new Color('#11111b', 'dark'), - }, - responsePane: { - background: new Color('#1e1e2e', 'dark'), - }, - button: { - colors: { - primary: new Color('#cba6f7', 'dark').lower(0.2), - secondary: new Color('#bac2de', 'dark').lower(0.2), - info: new Color('#89b4fa', 'dark').lower(0.2), - success: new Color('#a6e3a1', 'dark').lower(0.2), - notice: new Color('#f9e2af', 'dark').lower(0.2), - warning: new Color('#fab387', 'dark').lower(0.2), - danger: new Color('#f38ba8', 'dark').lower(0.2), - }, - }, - }, - }, -}; - type CSSVariables = Record; function themeVariables(theme?: ThemeComponent, base?: CSSVariables): CSSVariables | null { @@ -147,6 +65,7 @@ function themeVariables(theme?: ThemeComponent, base?: CSSVariables): CSSVariabl '--fg-subtle': theme?.foregroundSubtle?.css() ?? theme?.foreground?.lower(0.2).css(), '--fg-subtler': theme?.foregroundSubtler?.css() ?? theme?.foreground?.lower(0.3).css(), '--border-focus': theme?.colors?.info?.css(), + '--shadow': theme?.shadow?.css() ?? Color.black().translucify(0.7).css(), }; for (const [color, value] of Object.entries(theme?.colors ?? {})) { @@ -261,7 +180,7 @@ function placeholderCSS(color: ColorName, colors?: Partial): string ].join('\n\n'); } -function isThemeDark(theme: YaakTheme): boolean { +export function isThemeDark(theme: YaakTheme): boolean { if (theme.background && theme.foreground) { return theme.foreground.lighterThan(theme.background); } @@ -269,10 +188,11 @@ function isThemeDark(theme: YaakTheme): boolean { return false; } -setThemeOnDocument(yaakThemes.yaakLight!); -setThemeOnDocument(yaakThemes.yaakDark!); - export function getThemeCSS(theme: YaakTheme): string { + theme.components = theme.components ?? {}; + // Toast defaults to menu styles + theme.components.toast = theme.components.toast ?? theme.components.menu; + let themeCSS = ''; try { const baseCss = variablesToCSS(null, themeVariables(theme)); @@ -298,29 +218,24 @@ export function getThemeCSS(theme: YaakTheme): string { return themeCSS; } -export function setAppearanceOnDocument(appearance: Appearance = DEFAULT_APPEARANCE) { - const resolvedAppearance = appearance === 'system' ? getPreferredAppearance() : appearance; - document.documentElement.setAttribute('data-resolved-appearance', resolvedAppearance); -} - -export function setThemeOnDocument(theme: YaakTheme) { - document.documentElement.setAttribute('data-theme', theme.name); - - const darkOrLight = isThemeDark(theme) ? 'dark' : 'light'; - let existingStyleEl = document.head.querySelector(`style[data-theme-definition=${darkOrLight}]`); - if (!existingStyleEl) { - const styleEl = document.createElement('style'); +export function addThemeStylesToDocument(theme: YaakTheme) { + let styleEl = document.head.querySelector(`style[data-theme]`); + if (!styleEl) { + styleEl = document.createElement('style'); document.head.appendChild(styleEl); - existingStyleEl = styleEl; } - existingStyleEl.textContent = [ + styleEl.setAttribute('data-theme', theme.id); + styleEl.textContent = [ `/* ${theme.name} */`, - `[data-resolved-appearance="${isThemeDark(theme) ? 'dark' : 'light'}"] {`, + `[data-theme="${theme.id}"] {`, getThemeCSS(theme), '}', ].join('\n'); - existingStyleEl.setAttribute('data-theme-definition', darkOrLight); +} + +export function setThemeOnDocument(theme: YaakTheme) { + document.documentElement.setAttribute('data-theme', theme.id); } export function getPreferredAppearance(): Appearance { @@ -330,8 +245,13 @@ export function getPreferredAppearance(): Appearance { export function subscribeToPreferredAppearanceChange( cb: (appearance: Appearance) => void, ): () => void { - const listener = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light'); - const m = window.matchMedia('(prefers-color-scheme: dark)'); - m.addEventListener('change', listener); - return () => m.removeEventListener('change', listener); + const container = { unsubscribe: () => {} }; + + getCurrent() + .onThemeChanged((t) => cb(t.payload)) + .then((l) => { + container.unsubscribe = l; + }); + + return () => container.unsubscribe(); } diff --git a/src-web/main.tsx b/src-web/main.tsx index 40d5058c..9bb8038a 100644 --- a/src-web/main.tsx +++ b/src-web/main.tsx @@ -2,11 +2,9 @@ import { getCurrent } from '@tauri-apps/api/webviewWindow'; import { type } from '@tauri-apps/plugin-os'; import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; +import { attachConsole } from 'tauri-plugin-log-api'; import { App } from './components/App'; import './main.css'; -import { getSettings } from './lib/store'; -import type { Appearance } from './lib/theme/window'; -import { setAppearanceOnDocument } from './lib/theme/window'; // Hide decorations here because it doesn't work in Rust for some reason (bug?) const osType = await type(); @@ -14,11 +12,7 @@ if (osType !== 'macos') { await getCurrent().setDecorations(false); } -// await attachConsole(); -// await maybeRestorePathname(); - -const settings = await getSettings(); -setAppearanceOnDocument(settings.appearance as Appearance); +await attachConsole(); window.addEventListener('keydown', (e) => { // Hack to not go back in history on backspace. Check for document body diff --git a/tailwind.config.cjs b/tailwind.config.cjs index f2e05f32..60f7799f 100644 --- a/tailwind.config.cjs +++ b/tailwind.config.cjs @@ -59,6 +59,10 @@ module.exports = { '4xl': '2.5rem', '5xl': '3rem', }, + boxShadow: { + DEFAULT: '0 1px 3px 0 var(--shadow);', + lg: '0 10px 15px -3px var(--shadow)', + }, colors: { 'transparent': 'transparent', 'placeholder': 'var(--fg-subtler)', @@ -88,7 +92,7 @@ module.exports = { require('@tailwindcss/container-queries'), plugin(function ({addVariant}) { addVariant('hocus', ['&:hover', '&:focus-visible', '&.focus:focus']); - addVariant('focus-visible-or-class', ['&:focus-visible']); + addVariant('focus-visible-or-class', ['&:focus-visible', '&.focus:focus']); }), ], };