From ebf6e0311f58b36ee7c9f9d9c7f4077b3ccf72ba Mon Sep 17 00:00:00 2001 From: PandaDEV <70103896+0PandaDEV@users.noreply.github.com> Date: Tue, 27 Aug 2024 17:15:37 +1000 Subject: [PATCH] change keybind test --- app.vue | 514 ++++---------------------- assets/css/{style.scss => index.scss} | 50 --- assets/css/keybind.scss | 66 ++++ pages/index.vue | 459 +++++++++++++++++++++++ pages/keybind.vue | 53 +++ src-tauri/src/api/hotkeys.rs | 152 ++++++-- src-tauri/src/api/tray.rs | 9 +- src-tauri/src/main.rs | 8 +- 8 files changed, 780 insertions(+), 531 deletions(-) rename assets/css/{style.scss => index.scss} (88%) create mode 100644 assets/css/keybind.scss create mode 100644 pages/index.vue create mode 100644 pages/keybind.vue diff --git a/app.vue b/app.vue index fa71e44..72fdf7e 100644 --- a/app.vue +++ b/app.vue @@ -1,465 +1,75 @@ \ No newline at end of file diff --git a/assets/css/style.scss b/assets/css/index.scss similarity index 88% rename from assets/css/style.scss rename to assets/css/index.scss index 33e20cd..b175ff8 100644 --- a/assets/css/style.scss +++ b/assets/css/index.scss @@ -6,56 +6,6 @@ $text: #E5DFD5; $text2: #ADA9A1; $mutedtext: #78756F; -@font-face { - font-family: SFRoundedRegular; - font-display: swap; - src: url("~/assets/fonts/SFRoundedRegular.otf") format("opentype"); -} - -@font-face { - font-family: SFRoundedMedium; - font-display: swap; - src: url("~/assets/fonts/SFRoundedMedium.otf") format("opentype"); -} - -@font-face { - font-family: SFRoundedSemiBold; - font-display: swap; - src: url("~/assets/fonts/SFRoundedSemiBold.otf") format("opentype"); -} - -@font-face { - font-family: CommitMono; - font-display: swap; - src: url("~/assets/fonts/CommitMono.woff2") format("woff2"); -} - -* { - margin: 0; - padding: 0; - box-sizing: border-box; - color: $text; - text-decoration: none; - font-family: SFRoundedRegular; - scroll-behavior: smooth; - scrollbar-width: thin; - user-select: none; - - --os-handle-bg: #ADA9A1; - --os-handle-bg-hover: #78756F; - --os-handle-bg-active: #78756F; -} - -html, -body, -#__nuxt { - background-color: transparent; -} - -.os-scrollbar-horizontal { - display: none; -} - .bg { width: 750px; height: 474px; diff --git a/assets/css/keybind.scss b/assets/css/keybind.scss new file mode 100644 index 0000000..e1b871a --- /dev/null +++ b/assets/css/keybind.scss @@ -0,0 +1,66 @@ +$primary: #2E2D2B; +$accent: #FEB453; +$divider: #ffffff0d; + +$text: #E5DFD5; +$text2: #ADA9A1; +$mutedtext: #78756F; + +.bg { + width: 750px; + height: 474px; + background-color: $primary; + border: 1px solid $divider; + border-radius: 12px; + z-index: -1; + position: fixed; + outline: none; +} + +.keybind-container { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100%; + padding: 20px; +} + +h2 { + margin-bottom: 20px; +} + +.keybind-input { + width: 300px; + height: 50px; + border: 2px solid $accent; + border-radius: 5px; + display: flex; + align-items: center; + justify-content: center; + font-size: 18px; + cursor: pointer; + margin-bottom: 20px; + background-color: rgba($accent, 0.1); + user-select: none; +} + +.keybind-input:focus { + outline: none; + box-shadow: 0 0 0 2px rgba($accent, 0.5); +} + +button { + padding: 10px 20px; + background-color: $accent; + color: $primary; + border: none; + border-radius: 5px; + font-size: 16px; + cursor: pointer; +} + +button:disabled { + opacity: 0.5; + cursor: not-allowed; +} diff --git a/pages/index.vue b/pages/index.vue new file mode 100644 index 0000000..e045e51 --- /dev/null +++ b/pages/index.vue @@ -0,0 +1,459 @@ + + + + + \ No newline at end of file diff --git a/pages/keybind.vue b/pages/keybind.vue new file mode 100644 index 0000000..d9fef25 --- /dev/null +++ b/pages/keybind.vue @@ -0,0 +1,53 @@ + + + + + \ No newline at end of file diff --git a/src-tauri/src/api/hotkeys.rs b/src-tauri/src/api/hotkeys.rs index 9138326..ca93955 100644 --- a/src-tauri/src/api/hotkeys.rs +++ b/src-tauri/src/api/hotkeys.rs @@ -1,32 +1,136 @@ -use rdev::{listen, EventType, Key}; -use tauri::Manager; +use rdev::{listen, Event, EventType, Key}; +use tauri::{Manager, Emitter}; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::{Arc, Mutex}; +use std::collections::HashSet; +use serde::Serialize; use crate::utils::commands::center_window_on_current_monitor; -#[warn(dead_code)] +static IS_CAPTURING_KEYBIND: AtomicBool = AtomicBool::new(false); + +#[derive(Debug, Clone, Serialize)] +struct CapturedKeybind { + modifiers: Vec, + key: String, +} + +struct KeybindState { + pressed_keys: HashSet, +} + +impl KeybindState { + fn new() -> Self { + Self { + pressed_keys: HashSet::new(), + } + } +} + pub fn setup(app_handle: tauri::AppHandle) { + let app_handle_clone = app_handle.clone(); + let keybind_state = Arc::new(Mutex::new(KeybindState::new())); + std::thread::spawn(move || { - let mut meta_pressed = false; - listen(move |event| { - match event.event_type { - EventType::KeyPress(Key::MetaLeft) | EventType::KeyPress(Key::MetaRight) => { - meta_pressed = true; - } - EventType::KeyRelease(Key::MetaLeft) | EventType::KeyRelease(Key::MetaRight) => { - meta_pressed = false; - } - EventType::KeyPress(Key::KeyV) => { - if meta_pressed { - meta_pressed = false; - let window = app_handle.get_webview_window("main").unwrap(); - window.show().unwrap(); - window.set_focus().unwrap(); - center_window_on_current_monitor(&window); - } - } - _ => {} + if let Err(e) = listen(move |event| { + let mut state = keybind_state.lock().unwrap(); + if IS_CAPTURING_KEYBIND.load(Ordering::SeqCst) { + handle_keybind_capture(&app_handle_clone, event, &mut state); + } else { + handle_normal_hotkey(&app_handle_clone, event, &mut state); } - }) - .unwrap(); + }) { + eprintln!("Error setting up event listener: {:?}", e); + } }); +} + +fn handle_normal_hotkey(app_handle: &tauri::AppHandle, event: Event, state: &mut KeybindState) { + match event.event_type { + EventType::KeyPress(Key::MetaLeft) | EventType::KeyPress(Key::MetaRight) => { + state.pressed_keys.insert(Key::MetaLeft); + } + EventType::KeyRelease(Key::MetaLeft) | EventType::KeyRelease(Key::MetaRight) => { + state.pressed_keys.remove(&Key::MetaLeft); + } + EventType::KeyPress(Key::KeyV) => { + if state.pressed_keys.contains(&Key::MetaLeft) { + state.pressed_keys.clear(); + if let Some(window) = app_handle.get_webview_window("main") { + let _ = window.show(); + let _ = window.set_focus(); + center_window_on_current_monitor(&window); + } + } + } + _ => {} + } +} + +fn handle_keybind_capture(app_handle: &tauri::AppHandle, event: Event, state: &mut KeybindState) { + match event.event_type { + EventType::KeyPress(key) => { + state.pressed_keys.insert(key); + update_captured_keybind(app_handle, &state.pressed_keys); + } + EventType::KeyRelease(key) => { + state.pressed_keys.remove(&key); + } + _ => {} + } +} + +fn update_captured_keybind(app_handle: &tauri::AppHandle, pressed_keys: &HashSet) { + let modifiers: Vec = vec![Key::ControlLeft, Key::ShiftLeft, Key::Alt, Key::MetaLeft] + .into_iter() + .filter(|key| pressed_keys.contains(key)) + .map(|key| key_to_string(key)) + .collect(); + + let key = pressed_keys.iter() + .find(|&&key| !vec![Key::ControlLeft, Key::ShiftLeft, Key::Alt, Key::MetaLeft].contains(&key)) + .map(|&key| key_to_string(key)); + + if let Some(key) = key { + let captured_keybind = CapturedKeybind { + modifiers, + key, + }; + if let Err(e) = app_handle.emit("keybind_captured", captured_keybind) { + eprintln!("Error emitting keybind_captured event: {:?}", e); + } + } +} + +fn key_to_string(key: Key) -> String { + match key { + Key::ControlLeft | Key::ControlRight => "Ctrl".to_string(), + Key::ShiftLeft | Key::ShiftRight => "Shift".to_string(), + Key::Alt => "Alt".to_string(), + Key::MetaLeft | Key::MetaRight => "Meta".to_string(), + _ => format!("{:?}", key), + } +} + +#[tauri::command] +pub fn start_keybind_capture() { + IS_CAPTURING_KEYBIND.store(true, Ordering::SeqCst); +} + +#[tauri::command] +pub fn stop_keybind_capture() { + IS_CAPTURING_KEYBIND.store(false, Ordering::SeqCst); +} + +#[tauri::command] +pub fn get_current_keybind() -> String { + // Implement logic to retrieve the current keybind from your configuration + "Meta+V".to_string() // Placeholder +} + +#[tauri::command] +pub fn save_keybind(keybind: String) -> Result<(), String> { + // Implement logic to save the new keybind to your configuration + println!("Saving keybind: {}", keybind); + Ok(()) } \ No newline at end of file diff --git a/src-tauri/src/api/tray.rs b/src-tauri/src/api/tray.rs index bf2af58..6b78b8c 100644 --- a/src-tauri/src/api/tray.rs +++ b/src-tauri/src/api/tray.rs @@ -1,7 +1,5 @@ use tauri::{ - menu::{MenuBuilder, MenuItemBuilder}, - tray::TrayIconBuilder, - Manager, + menu::{MenuBuilder, MenuItemBuilder}, tray::TrayIconBuilder, Emitter, Manager }; pub fn setup(app: &mut tauri::App) -> Result<(), Box> { @@ -18,6 +16,7 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box> { .enabled(false) .build(app)?]) .items(&[&MenuItemBuilder::with_id("show", "Show/Hide").build(app)?]) + .items(&[&MenuItemBuilder::with_id("keybind", "Change keybind").build(app)?]) .items(&[&MenuItemBuilder::with_id("quit", "Quit").build(app)?]) .build()?, ) @@ -33,6 +32,10 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box> { window_clone_for_tray.show().unwrap(); window_clone_for_tray.set_focus().unwrap(); } + window_clone_for_tray.emit("main_route", ()).unwrap(); + } + "keybind" => { + window_clone_for_tray.emit("change_keybind", ()).unwrap(); } _ => (), }) diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a1f0b98..07b47a8 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -30,8 +30,8 @@ fn main() { ) .setup(|app| { let app_handle = app.handle().clone(); - - #[cfg(not(target_os = "macos"))] + + // #[cfg(not(target_os = "macos"))] api::hotkeys::setup(app_handle.clone()); api::tray::setup(app)?; api::database::setup(app)?; @@ -74,6 +74,10 @@ fn main() { api::clipboard::get_image_path, api::clipboard::write_and_paste, api::clipboard::read_image, + api::hotkeys::start_keybind_capture, + api::hotkeys::stop_keybind_capture, + api::hotkeys::get_current_keybind, + api::hotkeys::save_keybind, ]) .run(tauri::generate_context!()) .expect("error while running tauri application");