fix(tamagotchi): missing shortcuts editor (#190)
This commit is contained in:
Generated
+146
-3
@@ -101,6 +101,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-build",
|
||||
"tauri-plugin-global-shortcut",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-mcp",
|
||||
"tauri-plugin-os",
|
||||
@@ -1151,13 +1152,23 @@ dependencies = [
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"rustix 1.0.7",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
@@ -1286,6 +1297,24 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
||||
|
||||
[[package]]
|
||||
name = "global-hotkey"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"keyboard-types",
|
||||
"objc2 0.6.1",
|
||||
"objc2-app-kit",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"thiserror 2.0.12",
|
||||
"windows-sys 0.59.0",
|
||||
"x11rb",
|
||||
"xkeysym",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.18.0"
|
||||
@@ -1863,6 +1892,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
@@ -2976,6 +3011,19 @@ dependencies = [
|
||||
"semver",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.4.15",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.7"
|
||||
@@ -2985,7 +3033,7 @@ dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
@@ -3677,6 +3725,21 @@ dependencies = [
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-global-shortcut"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "31919f3c07bcb585afef217c0c33cde80da9ebccf5b8e2c90e0e0a535b14ab47"
|
||||
dependencies = [
|
||||
"global-hotkey",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"tauri-plugin",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-log"
|
||||
version = "2.4.0"
|
||||
@@ -3719,7 +3782,7 @@ version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "424f19432397850c2ddd42aa58078630c15287bbce3866eb1d90e7dbee680637"
|
||||
dependencies = [
|
||||
"gethostname",
|
||||
"gethostname 1.0.2",
|
||||
"log",
|
||||
"os_info",
|
||||
"serde",
|
||||
@@ -4729,6 +4792,21 @@ dependencies = [
|
||||
"windows_x86_64_msvc 0.42.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
@@ -4769,6 +4847,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
@@ -4781,6 +4865,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -4793,6 +4883,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@@ -4811,6 +4907,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -4823,6 +4925,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
@@ -4835,6 +4943,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
@@ -4847,6 +4961,12 @@ version = "0.42.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
@@ -4970,6 +5090,29 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
|
||||
dependencies = [
|
||||
"gethostname 0.4.3",
|
||||
"rustix 0.38.44",
|
||||
"x11rb-protocol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb-protocol"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
|
||||
|
||||
[[package]]
|
||||
name = "xkeysym"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.0"
|
||||
|
||||
@@ -42,7 +42,7 @@ Have you dreamed about having a cyber living being (cyber waifu / husbando, digi
|
||||
|
||||
With the power of modern large langauge models like [ChatGPT](https://chatgpt.com), and famous [Claude](https://claude.ai), asking a virtual being to have role playing and chat with us is already easy enough for everyone. Platforms like [Character.ai (a.k.a. c.ai)](https://character.ai) and [JanitorAI](https://janitorai.com/), and local playgrounds like [SillyTavern](https://github.com/SillyTavern/SillyTavern) is already a well-enough solution for chat based, or visuali adventure game like experience.
|
||||
|
||||
But, what about the abilities to play games? And see what you are coding at? Chatting while playing games, watching videos, and capable of doing many other things Perhaps you know [Neuro-sama](https://www.youtube.com/@Neurosama) already, she is currenly the best companion capable of playing games, chatting, and interacting with you and the participants (in VTuber community), some call this kind of being, "digital human" too. **Sadly, it's not open sourced, you cannot interact with her after she went offline from live stream**.
|
||||
But, what about the abilities to play games? And see what you are coding at? Chatting while playing games, watching videos, and capable of doing many other things Perhaps you know [Neuro-sama](https://www.youtube.com/@Neurosama) already, she is currenly the best companion capable of playing games, chatting, and interacting with you and the participants (in VTuber community), some call this kind of being, "digital human" too. **Sadly, it's not open sourced, you cannot interact with her after she went offline from live stream**.
|
||||
|
||||
Therefore, this project, AIRI, offers another possibilty here: **let you own yours, easily, anywhere, anytime**.
|
||||
|
||||
|
||||
@@ -354,7 +354,16 @@ settings:
|
||||
description: Configure the environment where the character lives
|
||||
title: Scene
|
||||
themes:
|
||||
color-scheme:
|
||||
description: Change the color scheme of the stage.
|
||||
title: Color Scheme
|
||||
description: Customize your stage!
|
||||
developer:
|
||||
description: Some developer options.
|
||||
title: Developers
|
||||
general:
|
||||
description: Dark theme, languages, etc.
|
||||
title: General
|
||||
sections:
|
||||
section:
|
||||
custom-color:
|
||||
@@ -431,7 +440,19 @@ settings:
|
||||
porcelain and paintings
|
||||
title: Chinese Traditional Colors
|
||||
title: Color Scheme Presets
|
||||
window-shortcuts:
|
||||
title: Keyboard Shortcuts
|
||||
title: Appearance
|
||||
window-shortcuts:
|
||||
description: Modify the window shortcuts.
|
||||
title: Window Shortcuts
|
||||
toggle-move:
|
||||
label: Toggle Move
|
||||
toggle-resize:
|
||||
label: Toggle Resize
|
||||
toggle-ignore-mouse-event:
|
||||
label: Toggle Ignore Mouse Event
|
||||
press-keys: Press Keys...
|
||||
sections:
|
||||
section:
|
||||
general:
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
"@proj-airi/ui": "workspace:^",
|
||||
"@ricky0123/vad-web": "^0.0.24",
|
||||
"@tauri-apps/api": "^2.5.0",
|
||||
"@tauri-apps/plugin-global-shortcut": "^2.2.1",
|
||||
"@tauri-apps/plugin-os": ">=2.2.1",
|
||||
"@tresjs/cientos": "^4.3.1",
|
||||
"@tresjs/core": "^4.3.5",
|
||||
|
||||
@@ -50,3 +50,6 @@ objc2-foundation = "0.3.1"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
windows = { version = "0.61.1", features = ["Win32_UI_WindowsAndMessaging", "Win32_Foundation"] }
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||
tauri-plugin-global-shortcut = "2.0.0"
|
||||
|
||||
@@ -10,6 +10,12 @@
|
||||
"os:default",
|
||||
"core:window:default",
|
||||
"core:window:allow-start-dragging",
|
||||
"mcp:default"
|
||||
"core:window:allow-set-focus",
|
||||
"core:window:allow-set-minimizable",
|
||||
"mcp:default",
|
||||
"global-shortcut:allow-is-registered",
|
||||
"global-shortcut:allow-register",
|
||||
"global-shortcut:allow-unregister",
|
||||
"global-shortcut:allow-unregister-all"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -56,17 +56,3 @@ pub async fn is_cursor_in_window(window: &tauri::Window) -> bool {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Check if modifier key is pressed (Option/Alt or Control)
|
||||
#[cfg(target_os = "macos")]
|
||||
pub fn is_modifier_pressed() -> bool {
|
||||
unsafe {
|
||||
let event_class: &'static objc2::runtime::AnyClass = class!(NSEvent);
|
||||
let flags: u64 = msg_send![event_class, modifierFlags];
|
||||
|
||||
// Check for Alt/Option (1 << 19) or Control (1 << 18)
|
||||
// let ctrl_pressed = (flags & (1 << 18)) != 0;
|
||||
// alt_pressed || ctrl_pressed
|
||||
(flags & (1 << 19)) != 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,9 +17,9 @@ mod app_windows;
|
||||
mod commands;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use app_click_through::native_macos::{is_cursor_in_window, is_modifier_pressed};
|
||||
use app_click_through::native_macos::is_cursor_in_window;
|
||||
#[cfg(target_os = "windows")]
|
||||
use app_click_through::native_windows::{is_cursor_in_window, is_modifier_pressed};
|
||||
use app_click_through::native_windows::is_cursor_in_window;
|
||||
use app_click_through::state::{set_click_through_enabled, set_cursor_inside, WindowClickThroughState};
|
||||
|
||||
#[tauri::command]
|
||||
@@ -55,23 +55,21 @@ async fn start_monitor_for_clicking_through(window: tauri::Window) -> Result<(),
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let cursor_inside = is_cursor_in_window(&window).await;
|
||||
let modifier_pressed = is_modifier_pressed();
|
||||
|
||||
// Only allow disabling click-through when:
|
||||
// 1. Cursor is OUTSIDE the window AND
|
||||
// 2. Modifier key is pressed
|
||||
let _ = set_cursor_inside(&window, cursor_inside && !modifier_pressed);
|
||||
let _ = set_cursor_inside(&window, cursor_inside);
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
let cursor_inside = is_cursor_in_window(&window).await;
|
||||
let modifier_pressed = is_modifier_pressed();
|
||||
|
||||
// Only allow disabling click-through when:
|
||||
// 1. Cursor is OUTSIDE the window AND
|
||||
// 2. Modifier key is pressed
|
||||
let _ = set_cursor_inside(&window, cursor_inside && !modifier_pressed);
|
||||
let _ = set_cursor_inside(&window, cursor_inside);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -113,6 +111,7 @@ pub fn run() {
|
||||
.plugin(prevent_default_plugin)
|
||||
.plugin(tauri_plugin_mcp::Builder.build())
|
||||
.plugin(tauri_plugin_os::init())
|
||||
.plugin(tauri_plugin_global_shortcut::Builder::new().build())
|
||||
.manage(WindowClickThroughState::default())
|
||||
.setup(|app| {
|
||||
let mut builder = WebviewWindowBuilder::new(app, "main", WebviewUrl::default());
|
||||
@@ -140,7 +139,8 @@ pub fn run() {
|
||||
let settings_item = MenuItem::with_id(app, "settings", "Settings", true, None::<&str>)?;
|
||||
let hide_item = MenuItem::with_id(app, "hide", "Hide", true, None::<&str>)?;
|
||||
let show_item = MenuItem::with_id(app, "show", "Show", true, None::<&str>)?;
|
||||
let menu = Menu::with_items(app, &[&settings_item, &hide_item, &show_item, &quit_item])?;
|
||||
let show_devtools_item = MenuItem::with_id(app, "show-devtools", "Show Devtools", true, None::<&str>)?;
|
||||
let menu = Menu::with_items(app, &[&settings_item, &hide_item, &show_item, &show_devtools_item, &quit_item])?;
|
||||
|
||||
let _ = TrayIconBuilder::new()
|
||||
.icon(app.default_window_icon().unwrap().clone()) // TODO: use custom icon
|
||||
@@ -173,6 +173,12 @@ pub fn run() {
|
||||
let _ = window.show();
|
||||
}
|
||||
}
|
||||
"show-devtools" => {
|
||||
let window = app.get_webview_window("main");
|
||||
if let Some(window) = window {
|
||||
window.open_devtools();
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
})
|
||||
.show_menu_on_left_click(true)
|
||||
|
||||
@@ -1,56 +1,88 @@
|
||||
import type { EffectScope } from 'vue'
|
||||
import type { ShortcutEvent } from '@tauri-apps/plugin-global-shortcut'
|
||||
|
||||
import { useMagicKeys, whenever } from '@vueuse/core'
|
||||
import { register, unregisterAll } from '@tauri-apps/plugin-global-shortcut'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, effectScope, watch } from 'vue'
|
||||
import { computed, watch } from 'vue'
|
||||
|
||||
import { useShortcutsStore } from '../stores/shortcuts'
|
||||
import { useWindowControlStore } from '../stores/window-controls'
|
||||
import { WindowControlMode } from '../types/window-controls'
|
||||
import { startClickThrough, stopClickThrough } from '../utils/windows'
|
||||
|
||||
export function useWindowShortcuts() {
|
||||
const windowStore = useWindowControlStore()
|
||||
const magicKeys = useMagicKeys()
|
||||
|
||||
const { shortcuts } = storeToRefs(useShortcutsStore())
|
||||
const handlers = computed(() => [
|
||||
{
|
||||
handle: () => {
|
||||
handle: async (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
windowStore.setMode(WindowControlMode.MOVE)
|
||||
windowStore.toggleControl()
|
||||
},
|
||||
shortcut: shortcuts.value.find(shortcut => shortcut.type === 'move')?.shortcut,
|
||||
},
|
||||
{
|
||||
handle: () => {
|
||||
handle: async (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
windowStore.setMode(WindowControlMode.RESIZE)
|
||||
windowStore.toggleControl()
|
||||
},
|
||||
shortcut: shortcuts.value.find(shortcut => shortcut.type === 'resize')?.shortcut,
|
||||
},
|
||||
{
|
||||
handle: () => {
|
||||
handle: async (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
windowStore.setMode(WindowControlMode.DEBUG)
|
||||
windowStore.toggleControl()
|
||||
},
|
||||
shortcut: shortcuts.value.find(shortcut => shortcut.type === 'debug')?.shortcut,
|
||||
},
|
||||
])
|
||||
|
||||
let currentScope: EffectScope | null = null
|
||||
watch(handlers, () => {
|
||||
if (currentScope) {
|
||||
currentScope.stop()
|
||||
}
|
||||
|
||||
currentScope = effectScope()
|
||||
currentScope.run(() => {
|
||||
handlers.value.forEach((handler) => {
|
||||
if (!handler.shortcut) {
|
||||
{
|
||||
handle: async (event: ShortcutEvent) => {
|
||||
if (event.state === 'Pressed') {
|
||||
stopClickThrough()
|
||||
return
|
||||
}
|
||||
whenever(magicKeys[handler.shortcut], handler.handle)
|
||||
|
||||
startClickThrough()
|
||||
},
|
||||
shortcut: shortcuts.value.find(shortcut => shortcut.type === 'ignore-mouse-event')?.shortcut,
|
||||
},
|
||||
])
|
||||
|
||||
watch(handlers, async () => {
|
||||
await unregisterAll()
|
||||
|
||||
for (const handler of handlers.value) {
|
||||
if (!handler.shortcut) {
|
||||
return
|
||||
}
|
||||
|
||||
await register(handler.shortcut
|
||||
.replaceAll('Meta', 'CommandOrControl')
|
||||
.replaceAll('meta', 'CommandOrControl')
|
||||
.replaceAll('Ctrl', 'CommandOrControl')
|
||||
.replaceAll('ctrl', 'CommandOrControl')
|
||||
.replaceAll('Option', 'OptionOrAlt')
|
||||
.replaceAll('option', 'OptionOrAlt'), (event: ShortcutEvent) => {
|
||||
if (event.state !== 'Pressed') {
|
||||
return
|
||||
}
|
||||
|
||||
handler.handle(event).catch((error) => {
|
||||
console.error('Error handling shortcut', error)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
}, { immediate: true })
|
||||
}
|
||||
|
||||
@@ -23,6 +23,22 @@ const routeHeaderMetadataMap = computed(() => {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.themes.title'),
|
||||
},
|
||||
'/settings/appearance/general': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.themes.general.title'),
|
||||
},
|
||||
'/settings/appearance/color-scheme': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.themes.color-scheme.title'),
|
||||
},
|
||||
'/settings/appearance/window-shortcuts': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.themes.window-shortcuts.title'),
|
||||
},
|
||||
'/settings/appearance/developer': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.themes.developer.title'),
|
||||
},
|
||||
'/settings/memory': {
|
||||
subtitle: t('settings.title'),
|
||||
title: t('settings.pages.memory.title'),
|
||||
|
||||
@@ -10,11 +10,12 @@ import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useWindowShortcuts } from '../composables/window-shortcuts'
|
||||
import { useWindowControlStore } from '../stores/window-controls'
|
||||
import { WindowControlMode } from '../types/window-controls'
|
||||
import { startClickThrough, stopClickThrough } from '../utils/windows'
|
||||
|
||||
const windowStore = useWindowControlStore()
|
||||
useWindowShortcuts()
|
||||
const isCursorInside = ref(false)
|
||||
|
||||
const viewRef = ref<HTMLDivElement>()
|
||||
const mcpStore = useMcpStore()
|
||||
const { connected, serverCmd, serverArgs } = storeToRefs(mcpStore)
|
||||
|
||||
@@ -33,11 +34,11 @@ const modeIndicatorClass = computed(() => {
|
||||
|
||||
onMounted(async () => {
|
||||
await invoke('start_monitor_for_clicking_through')
|
||||
await invoke('start_click_through')
|
||||
await startClickThrough()
|
||||
})
|
||||
|
||||
onUnmounted(async () => {
|
||||
await invoke('stop_click_through')
|
||||
await stopClickThrough()
|
||||
await invoke('stop_monitor_for_clicking_through')
|
||||
})
|
||||
|
||||
@@ -54,15 +55,7 @@ function openChat() {
|
||||
onMounted(async () => {
|
||||
// Listen for click-through state changes
|
||||
unlisten.push(await listen('tauri-app:window-click-through:is-inside', (event: { payload: boolean }) => {
|
||||
if (!viewRef.value)
|
||||
return
|
||||
|
||||
if (event.payload) {
|
||||
viewRef.value.style.opacity = '0'
|
||||
}
|
||||
else {
|
||||
viewRef.value.style.opacity = '1'
|
||||
}
|
||||
isCursorInside.value = event.payload
|
||||
}))
|
||||
|
||||
if (connected.value)
|
||||
@@ -85,8 +78,9 @@ onUnmounted(() => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="viewRef"
|
||||
:class="[modeIndicatorClass]"
|
||||
:class="[modeIndicatorClass, {
|
||||
'op-0': isCursorInside && !windowStore.isControlActive,
|
||||
}]"
|
||||
relative
|
||||
max-h="[100vh]"
|
||||
max-w="[100vw]"
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
<script setup lang="ts">
|
||||
import { Section } from '@proj-airi/stage-ui/components'
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import ColorPalette from '../../../components/Settings/ColorPalette.vue'
|
||||
import COLOR_PRESETS from './color-presets.json'
|
||||
|
||||
const settings = useSettings()
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Section
|
||||
v-motion
|
||||
mb-2
|
||||
:title="t('settings.pages.themes.sections.section.custom-color.title')"
|
||||
icon="i-solar:pallete-2-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (4 * 10)"
|
||||
:delay="4 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div
|
||||
v-motion flex items-center
|
||||
justify-between
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (5 * 10)"
|
||||
:delay="5 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span text-lg font-semibold>{{ $t('settings.pages.themes.sections.section.custom-color.fields.field.primary-color.label') }}</span>
|
||||
<label relative flex cursor-pointer items-center gap-2>
|
||||
<input
|
||||
v-model="settings.themeColorsHueDynamic"
|
||||
type="checkbox"
|
||||
class="peer sr-only"
|
||||
>
|
||||
<div
|
||||
class="h-6 w-11 rounded-full bg-neutral-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:bg-white dark:bg-neutral-600 peer-checked:bg-primary-500 after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"
|
||||
/>
|
||||
{{ $t('settings.pages.themes.sections.section.custom-color.fields.field.primary-color.rgb-on.title') }}
|
||||
</label>
|
||||
</div>
|
||||
<input
|
||||
v-model="settings.themeColorsHue"
|
||||
v-motion
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (6 * 10)"
|
||||
:delay="6 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
type="range" min="0" max="360" step="0.01" class="theme-hue-slider"
|
||||
:disabled="settings.themeColorsHueDynamic"
|
||||
:class="settings.themeColorsHueDynamic ? 'opacity-25 cursor-not-allowed' : 'cursor-pointer'"
|
||||
>
|
||||
<div
|
||||
v-motion
|
||||
class="color-bar"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (7 * 10)"
|
||||
:delay="7 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span bg-primary-50>50</span>
|
||||
<span bg-primary-100>100</span>
|
||||
<span bg-primary-200>200</span>
|
||||
<span bg-primary-300>300</span>
|
||||
<span bg-primary-400>400</span>
|
||||
<span bg-primary-500>500</span>
|
||||
<div
|
||||
v-motion
|
||||
text-white
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (8 * 10)"
|
||||
:delay="8 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span bg-primary-600>600</span>
|
||||
<span bg-primary-700>700</span>
|
||||
<span bg-primary-800>800</span>
|
||||
<span bg-primary-900>900</span>
|
||||
<span bg-primary-950>950</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-motion
|
||||
class="color-bar transparency-grid"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (9 * 10)"
|
||||
:delay="9 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span bg="primary-500/5">500/5</span>
|
||||
<span bg="primary-500/10">500/10</span>
|
||||
<span bg="primary-500/20">500/20</span>
|
||||
<span bg="primary-500/30">500/30</span>
|
||||
<span bg="primary-500/40">500/40</span>
|
||||
<span bg="primary-500/50">500/50</span>
|
||||
<span bg="primary-500/60">500/60</span>
|
||||
<span bg="primary-500/70">500/70</span>
|
||||
<span bg="primary-500/80">500/80</span>
|
||||
<span bg="primary-500/90">500/90</span>
|
||||
<span bg="primary-500">500</span>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
v-motion
|
||||
mb-2 :title="t('settings.pages.themes.sections.section.theme-presets.title')"
|
||||
icon="i-solar:magic-stick-2-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (10 * 10)"
|
||||
:delay="10 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div
|
||||
v-for="({ title, description, colors }, i) in $tm('settings.pages.themes.sections.section.theme-presets.presets')" :key="i"
|
||||
v-motion
|
||||
class="w-full flex items-center justify-between rounded-lg px-4 py-3 outline-none transition-all duration-250 ease-in-out"
|
||||
bg="neutral-100 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (11 * 10) + (i * 10)"
|
||||
:delay="11 * 50 + (i * 50)"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div>
|
||||
<span font-medium>{{ $rt(title) }}</span>
|
||||
<div text="sm neutral-500">
|
||||
{{ $rt(description) }}
|
||||
</div>
|
||||
</div>
|
||||
<ColorPalette :colors="(colors as any[]).map((name, j) => ({ hex: COLOR_PRESETS[i][j], name: $rt(name) }))" />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<div
|
||||
v-motion
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[65dvh]" right--15 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="250"
|
||||
flex items-center justify-center
|
||||
>
|
||||
<div text="60" i-solar:pallete-2-bold-duotone />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.theme-hue-slider {
|
||||
--at-apply: appearance-none h-10 rounded-lg;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
oklch(85% 0.2 0),
|
||||
oklch(85% 0.2 60),
|
||||
oklch(85% 0.2 120),
|
||||
oklch(85% 0.2 180),
|
||||
oklch(85% 0.2 240),
|
||||
oklch(85% 0.2 300),
|
||||
oklch(85% 0.2 360)
|
||||
);
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-600 cursor-pointer shadow-lg border-2 border-neutral-500
|
||||
hover: bg-neutral-800 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.dark &::-webkit-slider-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-100 cursor-pointer shadow-md border-2 border-white
|
||||
hover: bg-neutral-300 transition-colors duration-200;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-600 cursor-pointer shadow-lg border-2 border-neutral-500
|
||||
hover: bg-neutral-800 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.dark &::-moz-range-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-100 cursor-pointer shadow-md border-2 border-white
|
||||
hover: bg-neutral-300 transition-colors duration-200;
|
||||
}
|
||||
}
|
||||
|
||||
.color-bar {
|
||||
--at-apply: flex of-hidden rounded-lg lh-10 text-center text-black;
|
||||
|
||||
* {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
display: contents;
|
||||
}
|
||||
}
|
||||
|
||||
.transparency-grid {
|
||||
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
|
||||
linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%),
|
||||
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
||||
background-size: 20px 20px;
|
||||
background-position:
|
||||
0 0,
|
||||
0 10px,
|
||||
10px -10px,
|
||||
-10px 0px;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
@@ -0,0 +1,56 @@
|
||||
<script setup lang="ts">
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
|
||||
import CheckBar from '../../../components/Settings/CheckBar.vue'
|
||||
|
||||
const settings = useSettings()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CheckBar
|
||||
v-model="settings.disableTransitions"
|
||||
v-motion
|
||||
mb-2
|
||||
icon-on="i-solar:people-nearby-bold-duotone"
|
||||
icon-off="i-solar:running-2-line-duotone"
|
||||
text="settings.animations.stage-transitions.title"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (19 * 10)"
|
||||
:delay="19 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
<CheckBar
|
||||
v-model="settings.usePageSpecificTransitions"
|
||||
v-motion
|
||||
:disabled="settings.disableTransitions"
|
||||
icon-on="i-solar:running-2-line-duotone"
|
||||
icon-off="i-solar:people-nearby-bold-duotone"
|
||||
text="settings.animations.use-page-specific-transitions.title"
|
||||
description="settings.animations.use-page-specific-transitions.description"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (20 * 10)"
|
||||
:delay="20 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
|
||||
<div
|
||||
v-motion
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[65dvh]" right--15 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="250"
|
||||
flex items-center justify-center
|
||||
>
|
||||
<div text="60" i-solar:code-bold-duotone />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
@@ -0,0 +1,71 @@
|
||||
<script setup lang="ts">
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
import { useDark } from '@vueuse/core'
|
||||
|
||||
import CheckBar from '../../../components/Settings/CheckBar.vue'
|
||||
|
||||
const settings = useSettings()
|
||||
|
||||
const dark = useDark()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CheckBar
|
||||
v-model="dark"
|
||||
v-motion
|
||||
mb-2
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (2 * 10)"
|
||||
:delay="2 * 50"
|
||||
icon-on="i-solar:moon-stars-bold-duotone"
|
||||
icon-off="i-solar:sun-fog-bold-duotone"
|
||||
text="settings.theme"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
<!-- Language Setting -->
|
||||
<div
|
||||
v-motion
|
||||
class="w-full flex items-center justify-between rounded-lg px-4 py-3 text-sm outline-none transition-all duration-250 ease-in-out"
|
||||
bg="neutral-50 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (3 * 10)"
|
||||
:delay="3 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
{{ $t('settings.language.title') }}
|
||||
<select
|
||||
v-model="settings.language"
|
||||
transition="all ease-in-out duration-250"
|
||||
cursor-pointer bg-transparent text-right outline-none
|
||||
>
|
||||
<option value="en-US">
|
||||
{{ $t('settings.language.english') }}
|
||||
</option>
|
||||
<option value="zh-CN">
|
||||
{{ $t('settings.language.chinese') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-motion
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[65dvh]" right--15 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="250"
|
||||
flex items-center justify-center
|
||||
>
|
||||
<div text="60" i-solar:emoji-funny-square-bold-duotone />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
@@ -1,318 +1,73 @@
|
||||
<script setup lang="ts">
|
||||
import { Section } from '@proj-airi/stage-ui/components'
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
import { useDark } from '@vueuse/core'
|
||||
import { ref, watch } from 'vue'
|
||||
import { IconItem } from '@proj-airi/stage-ui/components'
|
||||
import { computed } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import CheckBar from '../../../components/Settings/CheckBar.vue'
|
||||
import ColorPalette from '../../../components/Settings/ColorPalette.vue'
|
||||
import COLOR_PRESETS from './color-presets.json'
|
||||
|
||||
const settings = useSettings()
|
||||
const dark = useDark()
|
||||
const { t } = useI18n()
|
||||
|
||||
const usePageSpecificTransitionsSettingChanged = ref(false)
|
||||
|
||||
// avoid showing the animation component when the page specific transitions are enabled
|
||||
watch(() => [settings.usePageSpecificTransitions, settings.disableTransitions], () => {
|
||||
usePageSpecificTransitionsSettingChanged.value = true
|
||||
})
|
||||
const settings = computed(() => [
|
||||
{
|
||||
title: t('settings.pages.themes.general.title'),
|
||||
description: t('settings.pages.themes.general.description'),
|
||||
icon: 'i-solar:emoji-funny-square-bold-duotone',
|
||||
to: '/settings/appearance/general',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.themes.color-scheme.title'),
|
||||
description: t('settings.pages.themes.color-scheme.description'),
|
||||
icon: 'i-solar:pallete-2-bold-duotone',
|
||||
to: '/settings/appearance/color-scheme',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.themes.window-shortcuts.title'),
|
||||
description: t('settings.pages.themes.window-shortcuts.description'),
|
||||
icon: 'i-solar:keyboard-bold-duotone',
|
||||
to: '/settings/appearance/window-shortcuts',
|
||||
},
|
||||
{
|
||||
title: t('settings.pages.themes.developer.title'),
|
||||
description: t('settings.pages.themes.developer.description'),
|
||||
icon: 'i-solar:code-bold-duotone',
|
||||
to: '/settings/appearance/developer',
|
||||
},
|
||||
])
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Section
|
||||
v-motion
|
||||
:title="t('settings.sections.section.general.title')"
|
||||
icon="i-solar:filters-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (1 * 10)"
|
||||
:delay="1 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<!-- Theme Setting -->
|
||||
<CheckBar
|
||||
v-model="dark"
|
||||
v-motion
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (2 * 10)"
|
||||
:delay="2 * 50"
|
||||
icon-on="i-solar:moon-stars-bold-duotone"
|
||||
icon-off="i-solar:sun-fog-bold-duotone"
|
||||
text="settings.theme"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
<!-- Language Setting -->
|
||||
<div
|
||||
v-motion
|
||||
class="w-full flex items-center justify-between rounded-lg px-4 py-3 text-sm outline-none transition-all duration-250 ease-in-out"
|
||||
bg="neutral-50 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (3 * 10)"
|
||||
:delay="3 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
{{ $t('settings.language.title') }}
|
||||
<select
|
||||
v-model="settings.language"
|
||||
transition="all ease-in-out duration-250"
|
||||
cursor-pointer bg-transparent text-right outline-none
|
||||
>
|
||||
<option value="en-US">
|
||||
{{ $t('settings.language.english') }}
|
||||
</option>
|
||||
<option value="zh-CN">
|
||||
{{ $t('settings.language.chinese') }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
v-motion
|
||||
:title="t('settings.pages.themes.sections.section.custom-color.title')"
|
||||
icon="i-solar:pallete-2-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (4 * 10)"
|
||||
:delay="4 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div
|
||||
v-motion flex items-center
|
||||
justify-between
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (5 * 10)"
|
||||
:delay="5 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span text-lg font-semibold>{{ $t('settings.pages.themes.sections.section.custom-color.fields.field.primary-color.label') }}</span>
|
||||
<label relative flex cursor-pointer items-center gap-2>
|
||||
<input
|
||||
v-model="settings.themeColorsHueDynamic"
|
||||
type="checkbox"
|
||||
class="peer sr-only"
|
||||
>
|
||||
<div
|
||||
class="h-6 w-11 rounded-full bg-neutral-200 after:absolute after:left-[2px] after:top-[2px] after:h-5 after:w-5 after:rounded-full after:bg-white dark:bg-neutral-600 peer-checked:bg-primary-500 after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"
|
||||
/>
|
||||
{{ $t('settings.pages.themes.sections.section.custom-color.fields.field.primary-color.rgb-on.title') }}
|
||||
</label>
|
||||
</div>
|
||||
<input
|
||||
v-model="settings.themeColorsHue"
|
||||
v-motion
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (6 * 10)"
|
||||
:delay="6 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
type="range" min="0" max="360" step="0.01" class="theme-hue-slider"
|
||||
:disabled="settings.themeColorsHueDynamic"
|
||||
:class="settings.themeColorsHueDynamic ? 'opacity-25 cursor-not-allowed' : 'cursor-pointer'"
|
||||
>
|
||||
<div
|
||||
v-motion
|
||||
class="color-bar"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (7 * 10)"
|
||||
:delay="7 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span bg-primary-50>50</span>
|
||||
<span bg-primary-100>100</span>
|
||||
<span bg-primary-200>200</span>
|
||||
<span bg-primary-300>300</span>
|
||||
<span bg-primary-400>400</span>
|
||||
<span bg-primary-500>500</span>
|
||||
<div
|
||||
<div flex="~ col gap-4" font-thin>
|
||||
<div />
|
||||
<div flex="~ col gap-4">
|
||||
<IconItem
|
||||
v-for="(setting, index) in settings"
|
||||
:key="setting.to"
|
||||
v-motion
|
||||
text-white
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (8 * 10)"
|
||||
:delay="8 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<span bg-primary-600>600</span>
|
||||
<span bg-primary-700>700</span>
|
||||
<span bg-primary-800>800</span>
|
||||
<span bg-primary-900>900</span>
|
||||
<span bg-primary-950>950</span>
|
||||
</div>
|
||||
:duration="250"
|
||||
:style="{
|
||||
transitionDelay: `${index * 50}ms`, // delay between each item, unocss doesn't support dynamic generation of classes now
|
||||
}"
|
||||
:title="setting.title"
|
||||
:description="setting.description"
|
||||
:icon="setting.icon"
|
||||
:to="setting.to"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-motion
|
||||
class="color-bar transparency-grid"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (9 * 10)"
|
||||
:delay="9 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[calc(100dvh-12rem)]" bottom-0 right--10 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 180 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="500"
|
||||
size-60
|
||||
flex items-center justify-center
|
||||
>
|
||||
<span bg="primary-500/5">500/5</span>
|
||||
<span bg="primary-500/10">500/10</span>
|
||||
<span bg="primary-500/20">500/20</span>
|
||||
<span bg="primary-500/30">500/30</span>
|
||||
<span bg="primary-500/40">500/40</span>
|
||||
<span bg="primary-500/50">500/50</span>
|
||||
<span bg="primary-500/60">500/60</span>
|
||||
<span bg="primary-500/70">500/70</span>
|
||||
<span bg="primary-500/80">500/80</span>
|
||||
<span bg="primary-500/90">500/90</span>
|
||||
<span bg="primary-500">500</span>
|
||||
<div v-motion text="60" i-solar:settings-bold-duotone />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
v-motion title="settings.pages.themes.sections.section.theme-presets.title"
|
||||
icon="i-solar:magic-stick-2-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (10 * 10)"
|
||||
:delay="10 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div
|
||||
v-for="({ title, description, colors }, i) in $tm('settings.pages.themes.sections.section.theme-presets.presets')" :key="i"
|
||||
v-motion
|
||||
class="w-full flex items-center justify-between rounded-lg px-4 py-3 outline-none transition-all duration-250 ease-in-out"
|
||||
bg="neutral-100 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (11 * 10) + (i * 10)"
|
||||
:delay="11 * 50 + (i * 50)"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<div>
|
||||
<span font-medium>{{ $rt(title) }}</span>
|
||||
<div text="sm neutral-500">
|
||||
{{ $rt(description) }}
|
||||
</div>
|
||||
</div>
|
||||
<ColorPalette :colors="(colors as any[]).map((name, j) => ({ hex: COLOR_PRESETS[i][j], name: $rt(name) }))" />
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
v-motion title="settings.pages.themes.sections.section.developer.title"
|
||||
icon="i-solar:code-bold-duotone"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (18 * 10)"
|
||||
:delay="18 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
>
|
||||
<CheckBar
|
||||
v-model="settings.disableTransitions"
|
||||
v-motion
|
||||
icon-on="i-solar:people-nearby-bold-duotone"
|
||||
icon-off="i-solar:running-2-line-duotone"
|
||||
text="settings.animations.stage-transitions.title"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (19 * 10)"
|
||||
:delay="19 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
<CheckBar
|
||||
v-model="settings.usePageSpecificTransitions"
|
||||
v-motion
|
||||
:disabled="settings.disableTransitions"
|
||||
icon-on="i-solar:running-2-line-duotone"
|
||||
icon-off="i-solar:people-nearby-bold-duotone"
|
||||
text="settings.animations.use-page-specific-transitions.title"
|
||||
description="settings.animations.use-page-specific-transitions.description"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (20 * 10)"
|
||||
:delay="20 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
/>
|
||||
</Section>
|
||||
|
||||
<div
|
||||
v-motion
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[65dvh]" right--15 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="250"
|
||||
flex items-center justify-center
|
||||
>
|
||||
<div text="60" i-solar:filters-bold-duotone />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.theme-hue-slider {
|
||||
--at-apply: appearance-none h-10 rounded-lg;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
oklch(85% 0.2 0),
|
||||
oklch(85% 0.2 60),
|
||||
oklch(85% 0.2 120),
|
||||
oklch(85% 0.2 180),
|
||||
oklch(85% 0.2 240),
|
||||
oklch(85% 0.2 300),
|
||||
oklch(85% 0.2 360)
|
||||
);
|
||||
|
||||
&::-webkit-slider-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-600 cursor-pointer shadow-lg border-2 border-neutral-500
|
||||
hover: bg-neutral-800 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.dark &::-webkit-slider-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-100 cursor-pointer shadow-md border-2 border-white
|
||||
hover: bg-neutral-300 transition-colors duration-200;
|
||||
}
|
||||
|
||||
&::-moz-range-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-600 cursor-pointer shadow-lg border-2 border-neutral-500
|
||||
hover: bg-neutral-800 transition-colors duration-200;
|
||||
}
|
||||
|
||||
.dark &::-moz-range-thumb {
|
||||
--at-apply: w-1 h-12 appearance-none rounded-md bg-neutral-100 cursor-pointer shadow-md border-2 border-white
|
||||
hover: bg-neutral-300 transition-colors duration-200;
|
||||
}
|
||||
}
|
||||
|
||||
.color-bar {
|
||||
--at-apply: flex of-hidden rounded-lg lh-10 text-center text-black;
|
||||
|
||||
* {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
div {
|
||||
display: contents;
|
||||
}
|
||||
}
|
||||
|
||||
.transparency-grid {
|
||||
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
|
||||
linear-gradient(-45deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%),
|
||||
linear-gradient(-45deg, transparent 75%, #ccc 75%);
|
||||
background-size: 20px 20px;
|
||||
background-position:
|
||||
0 0,
|
||||
0 10px,
|
||||
10px -10px,
|
||||
-10px 0px;
|
||||
background-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
<script setup lang="ts">
|
||||
import { useSettings } from '@proj-airi/stage-ui/stores'
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { useEventListener } from '@vueuse/core'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
import { useShortcutsStore } from '../../../stores/shortcuts'
|
||||
|
||||
const settings = useSettings()
|
||||
|
||||
const { t } = useI18n()
|
||||
const { shortcuts } = storeToRefs(useShortcutsStore())
|
||||
|
||||
const usePageSpecificTransitionsSettingChanged = ref(false)
|
||||
|
||||
// avoid showing the animation component when the page specific transitions are enabled
|
||||
watch(() => [settings.usePageSpecificTransitions, settings.disableTransitions], () => {
|
||||
usePageSpecificTransitionsSettingChanged.value = true
|
||||
})
|
||||
|
||||
const recordingFor = ref<string | null>(null)
|
||||
const recordingKeys = ref<{
|
||||
modifier: string[]
|
||||
key: string
|
||||
}>({
|
||||
modifier: [],
|
||||
key: '',
|
||||
})
|
||||
|
||||
// Add function to handle shortcut recording
|
||||
function startRecording(shortcut: typeof shortcuts.value[0]) {
|
||||
recordingFor.value = shortcut.type
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getCurrentWindow().setMinimizable(false) // to avoid the window from being minimized when the shortcut is being recorded
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
getCurrentWindow().setMinimizable(true)
|
||||
})
|
||||
|
||||
// Handle key combinations
|
||||
useEventListener('keydown', (e) => {
|
||||
if (!recordingFor.value)
|
||||
return
|
||||
if (!e.code.startsWith('Key')) // ignore non-key events
|
||||
return
|
||||
if (e.metaKey)
|
||||
recordingKeys.value.modifier.push('Meta')
|
||||
if (e.ctrlKey)
|
||||
recordingKeys.value.modifier.push('Control')
|
||||
if (e.altKey)
|
||||
recordingKeys.value.modifier.push('Alt')
|
||||
if (e.shiftKey)
|
||||
recordingKeys.value.modifier.push('Shift')
|
||||
|
||||
if (recordingKeys.value.modifier.length === 0)
|
||||
return
|
||||
|
||||
recordingKeys.value.key = e.code.slice(3)
|
||||
const shortcut = shortcuts.value.find(s => s.type === recordingFor.value)
|
||||
if (shortcut)
|
||||
shortcut.shortcut = `${recordingKeys.value.modifier.join('+')}+${recordingKeys.value.key}`
|
||||
recordingKeys.value = {
|
||||
modifier: [],
|
||||
key: '',
|
||||
}
|
||||
recordingFor.value = null
|
||||
}, { passive: false })
|
||||
// Add click outside handler to cancel recording
|
||||
useEventListener('click', (e) => {
|
||||
if (recordingFor.value) {
|
||||
const target = e.target as HTMLElement
|
||||
if (!target.closest('.shortcut-item')) {
|
||||
recordingFor.value = null
|
||||
recordingKeys.value = {
|
||||
modifier: [],
|
||||
key: '',
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const pressKeysMessage = computed(() => {
|
||||
if (recordingKeys.value.modifier.length === 0)
|
||||
return t('settings.pages.themes.window-shortcuts.press-keys')
|
||||
return `${t('settings.pages.themes.window-shortcuts.press-keys')}: ${recordingKeys.value.modifier.join('+')}+${recordingKeys.value.key}`
|
||||
})
|
||||
function isConflict(shortcut: typeof shortcuts.value[0]) {
|
||||
return shortcuts.value.some(s => s.type !== shortcut.type && s.shortcut === shortcut.shortcut)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div pb-2>
|
||||
<div
|
||||
v-for="shortcut in shortcuts" :key="shortcut.type"
|
||||
v-motion
|
||||
mb-2
|
||||
class="w-full flex items-center justify-between rounded-lg px-4 py-3 text-sm outline-none transition-all duration-250 ease-in-out"
|
||||
bg="neutral-50 dark:neutral-800"
|
||||
hover="bg-neutral-200 dark:bg-neutral-700"
|
||||
:initial="{ opacity: 0, y: 10 }"
|
||||
:enter="{ opacity: 1, y: 0 }"
|
||||
:duration="250 + (3 * 10)"
|
||||
:delay="3 * 50"
|
||||
transition="all ease-in-out duration-250"
|
||||
cursor-pointer
|
||||
@click="startRecording(shortcut)"
|
||||
>
|
||||
<span text="xs">
|
||||
{{ t(shortcut.name) }}
|
||||
</span>
|
||||
<div
|
||||
class="shortcut-item flex items-center justify-end gap-x-2 px-2 py-0.5"
|
||||
:class="{ recording: recordingFor === shortcut.type }"
|
||||
text="xs"
|
||||
>
|
||||
<div v-if="recordingFor === shortcut.type" class="pointer-events-none animate-flash animate-count-infinite">
|
||||
{{ pressKeysMessage }}
|
||||
</div>
|
||||
<div v-else class="pointer-events-none">
|
||||
{{ shortcut.shortcut }}
|
||||
</div>
|
||||
<div v-if="isConflict(shortcut)" text="xs" i-solar:danger-square-bold w-4 />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-motion
|
||||
text="neutral-200/50 dark:neutral-600/20" pointer-events-none
|
||||
fixed top="[65dvh]" right--15 z--1
|
||||
:initial="{ scale: 0.9, opacity: 0, rotate: 30 }"
|
||||
:enter="{ scale: 1, opacity: 1, rotate: 0 }"
|
||||
:duration="250"
|
||||
flex items-center justify-center
|
||||
>
|
||||
<div text="60" i-solar:keyboard-bold-duotone />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route lang="yaml">
|
||||
meta:
|
||||
layout: settings
|
||||
stageTransition:
|
||||
name: slide
|
||||
</route>
|
||||
@@ -66,22 +66,22 @@ function useVersionedLocalStorage<T>(
|
||||
export const useShortcutsStore = defineStore('shortcuts', () => {
|
||||
const shortcuts = ref([
|
||||
{
|
||||
name: 'settings.pages.shortcuts.sections.section.window-controls.fields.field.toggle-move.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/move', 'Shift+Alt+˜'), // Shift + Alt + N
|
||||
name: 'settings.pages.themes.window-shortcuts.toggle-move.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/move', 'Shift+Alt+N'), // Shift + Alt + N
|
||||
group: 'window',
|
||||
type: 'move',
|
||||
},
|
||||
{
|
||||
name: 'settings.pages.shortcuts.sections.section.window-controls.fields.field.toggle-resize.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/resize', 'Shift+Alt+®'), // Shift + Alt + R
|
||||
name: 'settings.pages.themes.window-shortcuts.toggle-resize.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/resize', 'Shift+Alt+R'), // Shift + Alt + R
|
||||
group: 'window',
|
||||
type: 'resize',
|
||||
},
|
||||
{
|
||||
name: 'settings.pages.shortcuts.sections.section.window-controls.fields.field.toggle-ignore-mouse-event.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/debug', 'Shift+Alt+ˆ'), // Shift + Alt + I
|
||||
name: 'settings.pages.themes.window-shortcuts.toggle-ignore-mouse-event.label',
|
||||
shortcut: useVersionedLocalStorage('shortcuts/window/debug', 'Shift+Alt+I'), // Shift + Alt + I
|
||||
group: 'window',
|
||||
type: 'debug',
|
||||
type: 'ignore-mouse-event',
|
||||
},
|
||||
])
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { getCurrentWindow } from '@tauri-apps/api/window'
|
||||
import { useLocalStorage } from '@vueuse/core'
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { WindowControlMode } from '../types/window-controls'
|
||||
import { startClickThrough, stopClickThrough } from '../utils/windows'
|
||||
|
||||
export const useWindowControlStore = defineStore('windowControl', () => {
|
||||
const controlMode = ref<WindowControlMode>(WindowControlMode.NONE)
|
||||
@@ -12,17 +14,20 @@ export const useWindowControlStore = defineStore('windowControl', () => {
|
||||
|
||||
function setMode(mode: WindowControlMode) {
|
||||
controlMode.value = mode
|
||||
|
||||
if (mode === WindowControlMode.RESIZE) {
|
||||
// return
|
||||
}
|
||||
}
|
||||
|
||||
function toggleControl() {
|
||||
isControlActive.value = !isControlActive.value
|
||||
if (!isControlActive.value) {
|
||||
controlMode.value = WindowControlMode.NONE
|
||||
startClickThrough()
|
||||
return
|
||||
}
|
||||
|
||||
stopClickThrough()
|
||||
|
||||
const window = getCurrentWindow()
|
||||
window.setFocus()
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
|
||||
export async function startClickThrough() {
|
||||
await invoke('start_click_through')
|
||||
}
|
||||
|
||||
export async function stopClickThrough() {
|
||||
await invoke('stop_click_through')
|
||||
}
|
||||
Generated
+52
-41
@@ -251,6 +251,9 @@ importers:
|
||||
'@tauri-apps/api':
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
'@tauri-apps/plugin-global-shortcut':
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
'@tauri-apps/plugin-os':
|
||||
specifier: '>=2.2.1'
|
||||
version: 2.2.1
|
||||
@@ -4400,6 +4403,9 @@ packages:
|
||||
engines: {node: '>= 10'}
|
||||
hasBin: true
|
||||
|
||||
'@tauri-apps/plugin-global-shortcut@2.2.1':
|
||||
resolution: {integrity: sha512-b64/TI1t5LIi2JY4OWlYjZpPRq60T5GVVL/no27sUuxaNUZY8dVtwsMtDUgxUpln2yR+P2PJsYlqY5V8sLSxEw==}
|
||||
|
||||
'@tauri-apps/plugin-os@2.2.1':
|
||||
resolution: {integrity: sha512-cNYpNri2CCc6BaNeB6G/mOtLvg8dFyFQyCUdf2y0K8PIAKGEWdEcu8DECkydU2B+oj4OJihDPD2de5K6cbVl9A==}
|
||||
|
||||
@@ -5351,8 +5357,8 @@ packages:
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.1':
|
||||
resolution: {integrity: sha512-5+AIOYe5moH0svsfjPwA2IhHJflLIEiOI8MIjoVgGL+VSgLEJoxr/KzAumQc4wR1KMdLK9PkBcCew6WRpmjzTw==}
|
||||
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.2':
|
||||
resolution: {integrity: sha512-AwQBwj2e3mxozjN+tF/bUbx9+K6jPM4gOsVnQP2GnYaQwvV1SHR6W8swDWb4ZiexIOoAD7TVzLVe9QaIh/D9PQ==}
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.3':
|
||||
resolution: {integrity: sha512-aSR524BAjy651No425KYgVcLVHE7lDYWvhCE038P1Bk00G05sxxI4hwmZStrJjIOk5nksx/zPb2ZABcdeOaAhg==}
|
||||
|
||||
'@xsai-transformers/embed@0.0.6':
|
||||
resolution: {integrity: sha512-Ktxl2V1jkInqN8AXB7XetFNluTLlztWu+mOyfvB3BHWBb/+mUDLDO0fDXliMrJsSk5+fNDNYRESZFpG85Joy2w==}
|
||||
@@ -5392,8 +5398,8 @@ packages:
|
||||
'@xsai/shared-chat@0.3.0-beta.1':
|
||||
resolution: {integrity: sha512-1lx5+TLxdukM4hHlH8xma7x6WR1rGVDBghVaNDiY1WS7yrTsDyEiphkRrfFR7sOw1/3hRNOX7cZ55W+LBueI2Q==}
|
||||
|
||||
'@xsai/shared-chat@0.3.0-beta.2':
|
||||
resolution: {integrity: sha512-RsUXOewyEiyMkjt68DHC5M+P41M0zq0wjQyA48ydpxrM/fqNQrG2aeTcsV6ylbNyAQaolauhwPG1CPC5A/9xhQ==}
|
||||
'@xsai/shared-chat@0.3.0-beta.3':
|
||||
resolution: {integrity: sha512-LtHGPVog0YjZ+lp7FM7MX0BfuEczSGsWC8EIeucdQ3IrZf9MYn23AUnhKZZNSz4cIkywmNGAF1oQzRrRiT/CoA==}
|
||||
|
||||
'@xsai/shared@0.2.0':
|
||||
resolution: {integrity: sha512-fFMJ1T/9P4o7iOmLvc4/UIFMy2tYkXUmL8aJWULmV36Ddq/gYYOndBZJZfoy3mNiDtxgDBkmIBMdIOFQu9iamg==}
|
||||
@@ -5401,8 +5407,8 @@ packages:
|
||||
'@xsai/shared@0.2.2':
|
||||
resolution: {integrity: sha512-bgalLd3samx36hDRRmu3M75LY5NfWwh3YRaMwY4Woy7X09JQx+vEqVpJcaIeqcmVqztm8NGYzj8hUru7lwPh0w==}
|
||||
|
||||
'@xsai/shared@0.3.0-beta.2':
|
||||
resolution: {integrity: sha512-H9a6K0n8p05qGz9EutqhEXzP86YYMYAiwWv/d4eEVdnjHa51pdxiB93PTNFn3snkCcCG5oahli6am5RDIf23Zg==}
|
||||
'@xsai/shared@0.3.0-beta.3':
|
||||
resolution: {integrity: sha512-oEwhwLeh2xXb5J0Wt/K/4zQrdBxBvFV9v3aG5UOr4AoZpXsUm3F6Hf+XB2aMX0KegFVhV2dhXe00f7XBa2vFeg==}
|
||||
|
||||
'@xsai/stream-text@0.2.2':
|
||||
resolution: {integrity: sha512-GTVGuKEpYBOglPQ7cjO18/v8jiZxY/lejXMt+KsZqyMQo/WmH6gUkYkRME/cTyxlQEUiF0L/0CqRjQvtaDlB+Q==}
|
||||
@@ -8761,6 +8767,7 @@ packages:
|
||||
node-domexception@1.0.0:
|
||||
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||
engines: {node: '>=10.5.0'}
|
||||
deprecated: Use your platform's native DOMException instead
|
||||
|
||||
node-fetch-native@1.6.6:
|
||||
resolution: {integrity: sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ==}
|
||||
@@ -11619,8 +11626,8 @@ packages:
|
||||
zod-to-json-schema:
|
||||
optional: true
|
||||
|
||||
xsschema@0.3.0-beta.2:
|
||||
resolution: {integrity: sha512-J3DZQuitaGtYqikylm+cJvlI/aatbWvPj2GIzjeUO03opEG/+nIQMLVdZhUjFFE6eEWYDjgtrBLevkqewVcjqQ==}
|
||||
xsschema@0.3.0-beta.3:
|
||||
resolution: {integrity: sha512-8fKI0Kqxs7npz3ElebNCeGdS0HDuS2qL3IqHK5O53yCdh419hcr3GQillwN39TNFasHjbMLQ+DjSwpY0NONdnQ==}
|
||||
peerDependencies:
|
||||
'@valibot/to-json-schema': ^1.0.0
|
||||
arktype: ^2.1.16
|
||||
@@ -15120,6 +15127,10 @@ snapshots:
|
||||
'@tauri-apps/cli-win32-ia32-msvc': 2.5.0
|
||||
'@tauri-apps/cli-win32-x64-msvc': 2.5.0
|
||||
|
||||
'@tauri-apps/plugin-global-shortcut@2.2.1':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.5.0
|
||||
|
||||
'@tauri-apps/plugin-os@2.2.1':
|
||||
dependencies:
|
||||
'@tauri-apps/api': 2.5.0
|
||||
@@ -16478,25 +16489,25 @@ snapshots:
|
||||
|
||||
'@xsai-ext/providers-cloud@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai-ext/shared-providers': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai-ext/shared-providers': 0.3.0-beta.3
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai-ext/providers-local@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai-ext/shared-providers': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai-ext/shared-providers': 0.3.0-beta.3
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai-ext/shared-providers@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.2':
|
||||
'@xsai-ext/shared-providers@0.3.0-beta.3':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai-transformers/embed@0.0.6(web-worker@1.5.0)':
|
||||
dependencies:
|
||||
@@ -16520,65 +16531,65 @@ snapshots:
|
||||
|
||||
'@xsai/embed@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/embed@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/generate-speech@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/generate-text@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
'@xsai/generate-text@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
'@xsai/generate-transcription@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/model@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/shared-chat@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/shared-chat@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/shared-chat@0.3.0-beta.2':
|
||||
'@xsai/shared-chat@0.3.0-beta.3':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
|
||||
'@xsai/shared@0.2.0': {}
|
||||
|
||||
'@xsai/shared@0.2.2': {}
|
||||
|
||||
'@xsai/shared@0.3.0-beta.2': {}
|
||||
'@xsai/shared@0.3.0-beta.3': {}
|
||||
|
||||
'@xsai/stream-text@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
'@xsai/stream-text@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
'@xsai/tool@0.2.2(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
xsschema: 0.3.0-beta.2(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
xsschema: 0.3.0-beta.3(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)
|
||||
transitivePeerDependencies:
|
||||
- '@valibot/to-json-schema'
|
||||
- arktype
|
||||
@@ -16589,9 +16600,9 @@ snapshots:
|
||||
|
||||
'@xsai/tool@0.3.0-beta.1(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)':
|
||||
dependencies:
|
||||
'@xsai/shared': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
xsschema: 0.3.0-beta.2(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)
|
||||
'@xsai/shared': 0.3.0-beta.3
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
xsschema: 0.3.0-beta.3(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28)
|
||||
transitivePeerDependencies:
|
||||
- '@valibot/to-json-schema'
|
||||
- arktype
|
||||
@@ -16602,11 +16613,11 @@ snapshots:
|
||||
|
||||
'@xsai/utils-chat@0.2.2':
|
||||
dependencies:
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
'@xsai/utils-chat@0.3.0-beta.1':
|
||||
dependencies:
|
||||
'@xsai/shared-chat': 0.3.0-beta.2
|
||||
'@xsai/shared-chat': 0.3.0-beta.3
|
||||
|
||||
abbrev@1.1.1:
|
||||
optional: true
|
||||
@@ -24434,7 +24445,7 @@ snapshots:
|
||||
zod: 3.25.28
|
||||
zod-to-json-schema: 3.24.5(zod@3.25.28)
|
||||
|
||||
xsschema@0.3.0-beta.2(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28):
|
||||
xsschema@0.3.0-beta.3(zod-to-json-schema@3.24.5(zod@3.25.28))(zod@3.25.28):
|
||||
optionalDependencies:
|
||||
zod: 3.25.28
|
||||
zod-to-json-schema: 3.24.5(zod@3.25.28)
|
||||
|
||||
Reference in New Issue
Block a user