diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c75e8e..8bf0c8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # CHANGELOG +## v6.2.0 + +> [!WARNING] +> Prior to 6.2.0 auto-updater was not working. Now it's fixed but you need to download and install this version manually. + +- Fixed Auto-Updater and added a new update controls. +- Replaced tray/buttons controls for Fullscreen and Zoom with Global Shortcuts (Ctrl + ...) and added Help button. +- Added icons to server status details. + ## v6.1.0 - Added detailed status of server, if available: version, system, users. diff --git a/package-lock.json b/package-lock.json index bcd3365..c2d45fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,11 +17,12 @@ "@sveltejs/vite-plugin-svelte": "^4.0.1", "@tauri-apps/api": "^2.1.1", "@tauri-apps/cli": "^2.1.0", - "@tauri-apps/plugin-dialog": "~2.0.1", - "@tauri-apps/plugin-http": "~2.0.1", - "@tauri-apps/plugin-os": "~2.0.0", - "@tauri-apps/plugin-shell": "~2.0.1", - "@tauri-apps/plugin-updater": "~2.0.0", + "@tauri-apps/plugin-dialog": "^2.0.1", + "@tauri-apps/plugin-global-shortcut": "^2.0.0", + "@tauri-apps/plugin-http": "^2.0.1", + "@tauri-apps/plugin-os": "^2.0.0", + "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-updater": "^2.0.0", "@types/eslint": "^9.6.1", "autoprefixer": "^10.4.20", "bits-ui": "^1.0.0-next.63", @@ -33,8 +34,8 @@ "lucide-svelte": "^0.460.1", "mode-watcher": "^0.5.0", "prettier": "^3.3.3", - "prettier-plugin-svelte": "^3.2.8", - "svelte": "^5.2.5", + "prettier-plugin-svelte": "^3.3.0", + "svelte": "^5.2.7", "svelte-check": "^4.0.9", "svelte-sonner": "^0.3.28", "tailwind-merge": "^2.5.4", @@ -1405,6 +1406,16 @@ "@tauri-apps/api": "^2.0.0" } }, + "node_modules/@tauri-apps/plugin-global-shortcut": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-global-shortcut/-/plugin-global-shortcut-2.0.0.tgz", + "integrity": "sha512-pnB4CUwFVjg4twtBSxoLJ4uLFTYxsvOdC1zIbG581pYzhYatOl6mjB+ijD5SSXgiS/jNoqMcfkOF9PWAisurew==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@tauri-apps/api": "^2.0.0" + } + }, "node_modules/@tauri-apps/plugin-http": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@tauri-apps/plugin-http/-/plugin-http-2.0.1.tgz", @@ -1801,19 +1812,6 @@ "node": ">= 8" } }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -2009,9 +2007,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001680", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001680.tgz", - "integrity": "sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==", + "version": "1.0.30001683", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001683.tgz", + "integrity": "sha512-iqmNnThZ0n70mNwvxpEC2nBJ037ZHZUoBI5Gorh1Mw6IlEAZujEoU1tXA628iZfzm7R9FvFzxbfdgml82a3k8Q==", "dev": true, "funding": [ { @@ -3178,19 +3176,6 @@ "node": ">=8.6" } }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", @@ -3458,15 +3443,13 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", - "optional": true, - "peer": true, "engines": { - "node": ">=12" + "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" @@ -3707,9 +3690,9 @@ } }, "node_modules/prettier-plugin-svelte": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.2.8.tgz", - "integrity": "sha512-PAHmmU5cGZdnhW4mWhmvxuG2PVbbHIxUuPOdUKvfE+d4Qt2d29iU5VWrPdsaW5YqVEE0nqhlvN4eoKmVMpIF3Q==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/prettier-plugin-svelte/-/prettier-plugin-svelte-3.3.0.tgz", + "integrity": "sha512-iNoYiQUx4zwqbQDW/bk0WR75w+QiY4fHJQpGQ5v8Yr7X5m7YoSvs2buUnhoYFXNAL32ULVmrjPSc0vVOHJsO0Q==", "dev": true, "license": "MIT", "peerDependencies": { @@ -4160,9 +4143,9 @@ } }, "node_modules/svelte": { - "version": "5.2.5", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.2.5.tgz", - "integrity": "sha512-D33RkKYF4AFIgM+HrItxFudmWrXOLaua8vW3Mq7bObn7UwRn6zJPZ58bEIlj8wEYfi08n8VVvTk8dCLVHNnikQ==", + "version": "5.2.7", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.2.7.tgz", + "integrity": "sha512-cEhPGuLHiH2+Z8B1FwQgiZJgA39uUmJR4516TKrM5zrp0/cuwJkfhUfcTxhAkznanAF5fXUKzvYR4o+Ksx3ZCQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4428,19 +4411,6 @@ "node": ">= 6" } }, - "node_modules/tailwindcss/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/tailwindcss/node_modules/postcss-load-config": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", diff --git a/package.json b/package.json index 7983994..ac34c08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "flc", - "version": "6.1.0", + "version": "6.2.0", "description": "Foundry Lightweight Client", "type": "module", "scripts": { @@ -22,11 +22,12 @@ "@sveltejs/vite-plugin-svelte": "^4.0.1", "@tauri-apps/api": "^2.1.1", "@tauri-apps/cli": "^2.1.0", - "@tauri-apps/plugin-dialog": "~2.0.1", - "@tauri-apps/plugin-http": "~2.0.1", - "@tauri-apps/plugin-os": "~2.0.0", - "@tauri-apps/plugin-shell": "~2.0.1", - "@tauri-apps/plugin-updater": "~2.0.0", + "@tauri-apps/plugin-dialog": "^2.0.1", + "@tauri-apps/plugin-global-shortcut": "^2.0.0", + "@tauri-apps/plugin-http": "^2.0.1", + "@tauri-apps/plugin-os": "^2.0.0", + "@tauri-apps/plugin-shell": "^2.0.1", + "@tauri-apps/plugin-updater": "^2.0.0", "@types/eslint": "^9.6.1", "autoprefixer": "^10.4.20", "bits-ui": "^1.0.0-next.63", @@ -38,8 +39,8 @@ "lucide-svelte": "^0.460.1", "mode-watcher": "^0.5.0", "prettier": "^3.3.3", - "prettier-plugin-svelte": "^3.2.8", - "svelte": "^5.2.5", + "prettier-plugin-svelte": "^3.3.0", + "svelte": "^5.2.7", "svelte-check": "^4.0.9", "svelte-sonner": "^0.3.28", "tailwind-merge": "^2.5.4", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 0228218..63689b4 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -975,13 +975,14 @@ dependencies = [ [[package]] name = "flc" -version = "6.1.0" +version = "6.0.0" dependencies = [ "serde", "serde_json", "tauri", "tauri-build", "tauri-plugin-dialog", + "tauri-plugin-global-shortcut", "tauri-plugin-http", "tauri-plugin-os", "tauri-plugin-shell", @@ -1355,6 +1356,23 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "global-hotkey" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00d88f1be7bf4cd2e61623ce08e84be2dfa4eab458e5d632d3dab95f16c1f64" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2", + "objc2-app-kit", + "once_cell", + "serde", + "thiserror 1.0.69", + "windows-sys 0.59.0", + "x11-dl", +] + [[package]] name = "gobject-sys" version = "0.18.0" @@ -3993,6 +4011,21 @@ dependencies = [ "uuid", ] +[[package]] +name = "tauri-plugin-global-shortcut" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c15fb7f5e4c80a73ce97217dcff27e423f496178cbcb87e13b4efe99eebb550" +dependencies = [ + "global-hotkey", + "log", + "serde", + "serde_json", + "tauri", + "tauri-plugin", + "thiserror 1.0.69", +] + [[package]] name = "tauri-plugin-http" version = "2.0.3" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index a985174..a60aa93 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flc" -version = "6.1.0" +version = "6.2.0" description = "Foundry Lightweight Client" authors = ["phenomen"] license = "MIT" @@ -29,7 +29,7 @@ crate-type = ["staticlib", "cdylib", "rlib"] tauri-build = { version = "2", features = [] } [dependencies] -tauri = { version = "2", features = ["tray-icon", "devtools"] } +tauri = { version = "2", features = ["devtools"] } tauri-plugin-shell = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" @@ -38,4 +38,5 @@ tauri-plugin-http = "2" tauri-plugin-os = "2" [target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies] +tauri-plugin-global-shortcut = "2" tauri-plugin-updater = "2" diff --git a/src-tauri/capabilities/default.json b/src-tauri/capabilities/default.json index cf77492..2633e89 100644 --- a/src-tauri/capabilities/default.json +++ b/src-tauri/capabilities/default.json @@ -21,7 +21,12 @@ "shell:allow-open", "shell:allow-spawn", "shell:allow-kill", - "updater:default", + "updater:default", + "updater:allow-check", + "updater:allow-download", + "updater:allow-install", + "updater:allow-download-and-install", + "global-shortcut:allow-register", "core:app:allow-default-window-icon", "core:app:allow-set-app-theme", "core:webview:allow-create-webview-window", @@ -32,6 +37,7 @@ "core:window:allow-close", "core:window:allow-create", "core:window:allow-is-fullscreen", + "core:window:allow-is-focused", "core:window:allow-set-focus", "core:window:allow-set-fullscreen", { @@ -55,6 +61,7 @@ } ], "sidecar": false - } + }, + "global-shortcut:default" ] } \ No newline at end of file diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json index 2bbd301..d388593 100644 --- a/src-tauri/gen/schemas/capabilities.json +++ b/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:default","core:window:default","core:webview:default","dialog:default","http:default","os:default","shell:default","shell:allow-open","shell:allow-spawn","shell:allow-kill","updater:default","core:app:allow-default-window-icon","core:app:allow-set-app-theme","core:webview:allow-create-webview-window","core:webview:allow-create-webview","core:webview:allow-set-webview-focus","core:webview:allow-set-webview-size","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-create","core:window:allow-is-fullscreen","core:window:allow-set-focus","core:window:allow-set-fullscreen",{"identifier":"http:default","allow":[{"url":"https://*:*"},{"url":"http://*:*"}]},{"identifier":"shell:allow-spawn","allow":[{"args":true,"cmd":"node","name":"node"}]}],"platforms":["macOS","windows","linux"]}} \ No newline at end of file +{"default":{"identifier":"default","description":"Capability for the main window","local":true,"windows":["main"],"permissions":["core:default","core:window:default","core:webview:default","dialog:default","http:default","os:default","shell:default","shell:allow-open","shell:allow-spawn","shell:allow-kill","updater:default","updater:allow-check","updater:allow-download","updater:allow-install","updater:allow-download-and-install","global-shortcut:allow-register","core:app:allow-default-window-icon","core:app:allow-set-app-theme","core:webview:allow-create-webview-window","core:webview:allow-create-webview","core:webview:allow-set-webview-focus","core:webview:allow-set-webview-size","core:webview:allow-set-webview-zoom","core:window:allow-close","core:window:allow-create","core:window:allow-is-fullscreen","core:window:allow-is-focused","core:window:allow-set-focus","core:window:allow-set-fullscreen",{"identifier":"http:default","allow":[{"url":"https://*:*"},{"url":"http://*:*"}]},{"identifier":"shell:allow-spawn","allow":[{"args":true,"cmd":"node","name":"node"}]},"global-shortcut:default"],"platforms":["macOS","windows","linux"]}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index 3dac512..46d8b98 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -2027,6 +2027,61 @@ "type": "string", "const": "dialog:deny-save" }, + { + "description": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n", + "type": "string", + "const": "global-shortcut:default" + }, + { + "description": "Enables the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-is-registered" + }, + { + "description": "Enables the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register" + }, + { + "description": "Enables the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register-all" + }, + { + "description": "Enables the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister" + }, + { + "description": "Enables the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister-all" + }, + { + "description": "Denies the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-is-registered" + }, + { + "description": "Denies the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register" + }, + { + "description": "Denies the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register-all" + }, + { + "description": "Denies the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister" + }, + { + "description": "Denies the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister-all" + }, { "description": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n", "type": "string", diff --git a/src-tauri/gen/schemas/windows-schema.json b/src-tauri/gen/schemas/windows-schema.json index 3dac512..46d8b98 100644 --- a/src-tauri/gen/schemas/windows-schema.json +++ b/src-tauri/gen/schemas/windows-schema.json @@ -2027,6 +2027,61 @@ "type": "string", "const": "dialog:deny-save" }, + { + "description": "No features are enabled by default, as we believe\nthe shortcuts can be inherently dangerous and it is\napplication specific if specific shortcuts should be\nregistered or unregistered.\n", + "type": "string", + "const": "global-shortcut:default" + }, + { + "description": "Enables the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-is-registered" + }, + { + "description": "Enables the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register" + }, + { + "description": "Enables the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-register-all" + }, + { + "description": "Enables the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister" + }, + { + "description": "Enables the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:allow-unregister-all" + }, + { + "description": "Denies the is_registered command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-is-registered" + }, + { + "description": "Denies the register command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register" + }, + { + "description": "Denies the register_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-register-all" + }, + { + "description": "Denies the unregister command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister" + }, + { + "description": "Denies the unregister_all command without any pre-configured scope.", + "type": "string", + "const": "global-shortcut:deny-unregister-all" + }, { "description": "This permission set configures what kind of\nfetch operations are available from the http plugin.\n\nThis enables all fetch operations but does not\nallow explicitly any origins to be fetched. This needs to\nbe manually configured before usage.\n\n#### Granted Permissions\n\nAll fetch operations are enabled.\n\n", "type": "string", diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index be37d2f..efbdf7a 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -7,6 +7,7 @@ fn greet(name: &str) -> String { #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() + .plugin(tauri_plugin_global_shortcut::Builder::new().build()) .plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_dialog::init()) diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6c264eb..3eb6eb7 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "FLC", - "version": "6.1.0", + "version": "6.2.0", "identifier": "com.phenomen.flc", "build": { "beforeDevCommand": "npm run dev", @@ -25,6 +25,10 @@ } ], "security": { + "headers": { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp" + }, "csp": null } }, @@ -32,9 +36,9 @@ "active": true, "longDescription": "Foundry Lightweight Client", "category": "RolePlayingGame", - "copyright": "phenomen", + "copyright": "ruleplaying.com", "targets": ["msi", "app", "dmg", "appimage"], - "createUpdaterArtifacts": "v1Compatible", + "createUpdaterArtifacts": true, "icon": [ "icons/32x32.png", "icons/128x128.png", diff --git a/src/app.html b/src/app.html index fcd24d9..d857ce6 100644 --- a/src/app.html +++ b/src/app.html @@ -20,6 +20,6 @@ data-sveltekit-preload-data="hover" class="h-full bg-muted" > -
%sveltekit.body%
+
%sveltekit.body%
diff --git a/src/lib/components/FoundryControls.svelte b/src/lib/components/FoundryControls.svelte index 4af43e0..3d45ca5 100644 --- a/src/lib/components/FoundryControls.svelte +++ b/src/lib/components/FoundryControls.svelte @@ -1,38 +1,45 @@ -
- - - + + +
+ +
+
+ +
+
+ Ctrl/⌘ F11Toggle Fullscreen +
+ +
+ Ctrl/⌘ +Zoom In +
+ +
+ Ctrl/⌘ -Zoom Out +
+ +
+ Ctrl/⌘ 0Reset Zoom +
+
+
+
- -
+ diff --git a/src/lib/components/NodeserverCard.svelte b/src/lib/components/NodeserverCard.svelte index 4702a05..f7925bb 100644 --- a/src/lib/components/NodeserverCard.svelte +++ b/src/lib/components/NodeserverCard.svelte @@ -90,13 +90,21 @@ -
+

{server.label}

@@ -191,6 +199,9 @@ class="w-full h-full bg-primary text-primary-foreground overflow-hidden max-w-16 hover:bg-primary/90 border-primary border" title="Load Server Settings" > - + diff --git a/src/lib/components/NodeserverGrid.svelte b/src/lib/components/NodeserverGrid.svelte index ce30081..282aa96 100644 --- a/src/lib/components/NodeserverGrid.svelte +++ b/src/lib/components/NodeserverGrid.svelte @@ -5,7 +5,7 @@ import { nodeservers } from "$scripts/nodeservers.svelte.js"; -
+
{#if nodeservers.current.length} {#each nodeservers.current as server (server.id)}
diff --git a/src/lib/components/ServerCard.svelte b/src/lib/components/ServerCard.svelte index 9fc3022..dc1fe35 100644 --- a/src/lib/components/ServerCard.svelte +++ b/src/lib/components/ServerCard.svelte @@ -14,7 +14,11 @@ import Settings from "lucide-svelte/icons/settings"; import X from "lucide-svelte/icons/x"; import LogIn from "lucide-svelte/icons/log-in"; - import Dot from "lucide-svelte/icons/dot"; + import Smile from "lucide-svelte/icons/smile"; + import Zap from "lucide-svelte/icons/zap"; + import Dices from "lucide-svelte/icons/dices"; + import Hexagon from "lucide-svelte/icons/hexagon"; + import Globe from "lucide-svelte/icons/globe"; import { deleteServer, updateServer } from "$scripts/servers.svelte.js"; import { openWebview } from "$scripts/webview.svelte.js"; @@ -67,19 +71,6 @@ } } - async function checkOnline() { - online = false; - - const response = await fetch(url, { - method: "GET" - }); - - if (response.statusText === "OK" || response.status === 200) { - online = true; - await checkStatus(); - } - } - async function checkStatus() { const response = await fetch(`${url}${url.endsWith("/") ? "" : "/"}api/status`, { method: "GET", @@ -94,7 +85,7 @@ } onMount(async () => { - await checkOnline(); + await checkStatus(); }); @@ -102,13 +93,21 @@ -
- - - -
+
+

{server.label}

-
- {#if status}Online - V{status.version} - {#if status.users}{status.users} users{/if} - {#if status.system}{status.system.toUpperCase()}{/if} +
+ {#if status} + Online + {status.version} + {#if status.system}{status.system.toUpperCase()}{/if} + {#if status.users !== undefined}{status.users}{/if} {:else} - Offline{/if} + + Offline{/if}
diff --git a/src/lib/components/ServerGrid.svelte b/src/lib/components/ServerGrid.svelte index 466435b..24c029c 100644 --- a/src/lib/components/ServerGrid.svelte +++ b/src/lib/components/ServerGrid.svelte @@ -5,7 +5,7 @@ import { servers } from "$scripts/servers.svelte.js"; -
+
{#if servers.current.length} {#each servers.current as server (server.id)}
diff --git a/src/lib/components/Updater.svelte b/src/lib/components/Updater.svelte new file mode 100644 index 0000000..fa0854c --- /dev/null +++ b/src/lib/components/Updater.svelte @@ -0,0 +1,61 @@ + + +{#if update} +
+
+
{message}
+ {#if install} + + {/if} +
+
+{/if} diff --git a/src/lib/scripts/servers.svelte.ts b/src/lib/scripts/servers.svelte.ts index ac0c322..1ff8300 100644 --- a/src/lib/scripts/servers.svelte.ts +++ b/src/lib/scripts/servers.svelte.ts @@ -2,18 +2,14 @@ import { LocalStorage } from "$scripts/storage.svelte.js"; import { nanoid } from "nanoid"; import * as v from "valibot"; -const URLSchema = v.union( - [ - v.pipe(v.string(), v.trim(), v.url(), v.startsWith("http://")), - v.pipe(v.string(), v.trim(), v.url(), v.startsWith("https://")) - ], - "Please enter a correct URL starting with either http:// or https://" -); - const ServerSchema = v.object({ id: v.string(), label: v.pipe(v.string(), v.trim(), v.minLength(1, "Please enter a server name")), - url: URLSchema, + url: v.pipe( + v.string(), + v.trim(), + v.regex(/^https?:\/\//, "Please enter a correct URL starting with either http:// or https://") + ), notes: v.optional(v.string()) }); diff --git a/src/lib/scripts/shortcuts.svelte.ts b/src/lib/scripts/shortcuts.svelte.ts new file mode 100644 index 0000000..9fbf093 --- /dev/null +++ b/src/lib/scripts/shortcuts.svelte.ts @@ -0,0 +1,23 @@ +import { getAllWindows } from "@tauri-apps/api/window"; +import { register } from "@tauri-apps/plugin-global-shortcut"; + +export async function toggleFullscreen() { + const windows = await getAllWindows(); + const foundryWindows = windows.filter((window) => window.label.includes("foundry")); + + for (const window of foundryWindows) { + const focused = await window.isFocused(); + if (focused) { + const fullscreen = await window.isFullscreen(); + await window.setFullscreen(!fullscreen); + } + } +} + +export async function registerShortcuts() { + await register("CommandOrControl+F11", async (event) => { + if (event.state === "Pressed") { + await toggleFullscreen(); + } + }); +} diff --git a/src/lib/scripts/tray.svelte.ts b/src/lib/scripts/tray.svelte.ts deleted file mode 100644 index eb752d5..0000000 --- a/src/lib/scripts/tray.svelte.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { defaultWindowIcon } from "@tauri-apps/api/app"; -import { getCurrentWindow, getAllWindows } from "@tauri-apps/api/window"; -import { Menu, Submenu } from "@tauri-apps/api/menu"; -import { TrayIcon } from "@tauri-apps/api/tray"; -import { getAllWebviews } from "@tauri-apps/api/webview"; -import { toast } from "svelte-sonner"; - -let zoom = $state(1.0); - -export async function toggleFullscreen() { - const windows = await getAllWindows(); - const foundryWindow = windows.find((window) => window.label === "foundry"); - if (foundryWindow) { - const fullscreen = await foundryWindow.isFullscreen(); - await foundryWindow.setFullscreen(!fullscreen); - } else { - return toast("Open a Foundry VTT window to toggle fullscreen."); - } -} - -export async function setZoomFactor(factor: number) { - const webviews = await getAllWebviews(); - const foundryWebview = webviews.find((webview) => webview.label === "foundry"); - if (foundryWebview) { - await foundryWebview.setZoom(factor); - return toast(`Zoom level is x${factor.toPrecision(2)}`); - } else { - return toast("Open a Foundry VTT window to set zoom level."); - } -} - -export async function zoomIn() { - const webviews = await getAllWebviews(); - const foundryWebview = webviews.find((webview) => webview.label === "foundry"); - - if (foundryWebview) { - if (zoom > 1.8) { - return toast("Zoom is already at maximum level."); - } else { - zoom = zoom + 0.1; - } - } - await setZoomFactor(zoom); -} - -export async function zoomOut() { - const webviews = await getAllWebviews(); - const foundryWebview = webviews.find((webview) => webview.label === "foundry"); - - if (foundryWebview) { - if (zoom < 0.8) { - return toast("Zoom is already at minimum level."); - } else { - zoom = zoom - 0.1; - } - } - await setZoomFactor(zoom); -} - -export async function registerTray() { - const currentMenu = await TrayIcon.getById("flc"); - - if (currentMenu) { - return; - } - - const submenu = await Submenu.new({ - id: "zoom", - text: "Zoom", - items: [ - { - id: "zoom120", - text: "120%", - action: async () => { - await setZoomFactor(1.2); - } - }, - { - id: "zoom110", - text: "110%", - action: async () => { - await setZoomFactor(1.1); - } - }, - { - id: "zoom100", - text: "100%", - action: async () => { - await setZoomFactor(1.0); - } - }, - { - id: "zoom90", - text: "90%", - action: async () => { - await setZoomFactor(0.9); - } - }, - { - id: "zoom80", - text: "80%", - action: async () => { - await setZoomFactor(0.8); - } - } - ] - }); - - const menu = await Menu.new({ - items: [ - { - id: "fullscreen", - text: "Toggle Fullscreen", - action: async () => { - await toggleFullscreen(); - } - }, - submenu, - { - id: "exit", - text: "Exit", - action: async () => { - await getCurrentWindow().close(); - } - } - ] - }); - - const options = { - id: "flc", - menu, - menuOnLeftClick: true, - icon: await defaultWindowIcon() - }; - - await TrayIcon.new(options); -} diff --git a/src/lib/scripts/webview.svelte.ts b/src/lib/scripts/webview.svelte.ts index 07d672e..5913295 100644 --- a/src/lib/scripts/webview.svelte.ts +++ b/src/lib/scripts/webview.svelte.ts @@ -1,8 +1,8 @@ import { WebviewWindow } from "@tauri-apps/api/webviewWindow"; import { toast } from "svelte-sonner"; -export async function openWebview(url: string, title?: string) { - const webview = new WebviewWindow("foundry", { +export async function openWebview(url: string, id: string, title: string) { + const webview = new WebviewWindow(`foundry-${id}`, { title: `Foundry VTT - ${title}`, url, x: 0, @@ -22,8 +22,5 @@ export async function openWebview(url: string, title?: string) { webview.once("tauri://error", function (e) { console.log(e); - if (e.payload === "a webview with label `foundry` already exists") { - toast("Foundry VTT window is already open."); - } }); } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index da63e2d..5a968c2 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -4,18 +4,16 @@ import { ModeWatcher } from "mode-watcher"; - import { Toaster } from "$ui/sonner/index.js"; - import Header from "$components/Header.svelte"; - import { registerTray } from "$scripts/tray.svelte.js"; + import Updater from "$components/Updater.svelte"; + import { registerShortcuts } from "$scripts/shortcuts.svelte.js"; let { children } = $props(); - registerTray(); + registerShortcuts(); -
- {@render children?.()} + diff --git a/vite.config.js b/vite.config.js index 5ae20b6..087ac83 100644 --- a/vite.config.js +++ b/vite.config.js @@ -14,6 +14,10 @@ export default defineConfig(async () => ({ clearScreen: false, // 2. tauri expects a fixed port, fail if that port is not available server: { + headers: { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp" + }, port: 1420, strictPort: true, host: host || false,