added ability to save hotkey into settings

This commit is contained in:
PandaDEV 2024-09-01 11:36:08 +10:00
parent 1370408129
commit 79dd783bf7
No known key found for this signature in database
GPG key ID: 13EFF9BAF70EE75C
4 changed files with 171 additions and 48 deletions

View file

@ -2,13 +2,7 @@
<div class="bg"> <div class="bg">
<div class="keybind-container"> <div class="keybind-container">
<h2>Set New Keybind</h2> <h2>Set New Keybind</h2>
<div <div class="keybind-input" tabindex="0" @keydown="onKeyDown" @keyup="onKeyUp" @focus="onFocus" ref="keybindInput">
class="keybind-input"
tabindex="0"
@focus="startCapture"
@blur="stopCapture"
ref="keybindInput"
>
{{ currentKeybind || 'Click here, then press your desired key combination' }} {{ currentKeybind || 'Click here, then press your desired key combination' }}
</div> </div>
<button @click="saveKeybind" :disabled="!currentKeybind">Save Keybind</button> <button @click="saveKeybind" :disabled="!currentKeybind">Save Keybind</button>
@ -17,35 +11,93 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'; import { ref } from 'vue';
import { invoke } from '@tauri-apps/api/core'; import { invoke } from '@tauri-apps/api/core';
import { listen } from '@tauri-apps/api/event';
const currentKeybind = ref(''); const currentKeybind = ref('');
const keybindInput = ref<HTMLElement | null>(null); const keybindInput = ref<HTMLElement | null>(null);
const keys = ref<Set<string>>(new Set());
const recording = ref(false);
const startCapture = async () => { const keyToDisplayMap: Record<string, string> = {
await invoke('start_keybind_capture'); " ": "Space",
Alt: "Alt",
ArrowDown: "↓",
ArrowLeft: "←",
ArrowRight: "→",
ArrowUp: "↑",
Control: "Ctrl",
Enter: "↵",
Escape: "Esc",
Meta: "Meta",
Shift: "⇧",
}; };
const stopCapture = async () => { const modifierKeySet = new Set(["Alt", "Control", "Meta", "Shift"]);
await invoke('stop_keybind_capture');
function keyCodeToKey(keyCode: string): string {
if (keyCode.startsWith("Key")) return keyCode.slice(3);
if (keyCode.endsWith("Left")) return keyCode.slice(0, -4);
if (keyCode.startsWith("Digit")) return keyCode.slice(5);
if (keyCode.endsWith("Right")) return keyCode.slice(0, -5);
return keyCode;
}
function keyToDisplay(keyCode: string): string {
const key = keyCodeToKey(keyCode);
return keyToDisplayMap[key] || key;
}
function keyCombToDisplay(keyComb: Set<string>): string {
return Array.from(keyComb).map(keyToDisplay).join("+");
}
function mapKeyToTauriKey(key: string): string {
return key === "Meta" ? "Command" : key;
}
const onKeyDown = (event: KeyboardEvent) => {
event.preventDefault();
const key = keyCodeToKey(event.code);
if (modifierKeySet.has(key) && !keys.value.has(key)) {
keys.value = new Set(Array.from(keys.value).filter(k => modifierKeySet.has(k)));
}
keys.value.add(key);
updateCurrentKeybind();
}; };
const saveKeybind = () => { const onKeyUp = (event: KeyboardEvent) => {
console.log('Saving keybind:', currentKeybind.value); event.preventDefault();
// Implement saving logic here const key = keyCodeToKey(event.code);
if (!modifierKeySet.has(key)) {
recording.value = false;
updateCurrentKeybind();
}
}; };
onMounted(async () => { const onFocus = () => {
const unlisten = await listen('keybind_captured', (event: any) => { resetKeybind();
currentKeybind.value = event.payload as string; };
});
onUnmounted(() => { const updateCurrentKeybind = () => {
unlisten(); currentKeybind.value = keyCombToDisplay(keys.value);
}); };
});
const resetKeybind = () => {
keys.value.clear();
currentKeybind.value = '';
recording.value = true;
};
const saveKeybind = async () => {
console.log(await invoke("get_keybind"));
};
const startCapture = () => {
resetKeybind();
};
</script> </script>
<style lang="scss"> <style lang="scss">

View file

@ -1,9 +1,16 @@
use sqlx::sqlite::SqlitePoolOptions;
use std::fs;
use tokio::runtime::Runtime;
use tauri::Manager;
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric; use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use serde::{Deserialize, Serialize};
use sqlx::sqlite::{SqlitePool, SqlitePoolOptions};
use std::fs;
use tauri::Manager;
use tauri::State;
use tokio::runtime::Runtime;
#[derive(Deserialize, Serialize)]
struct KeybindSetting {
keybind: Vec<String>,
}
pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> { pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
let rt = Runtime::new().expect("Failed to create Tokio runtime"); let rt = Runtime::new().expect("Failed to create Tokio runtime");
@ -27,6 +34,46 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
}); });
rt.block_on(async { rt.block_on(async {
// Setup settings table
sqlx::query(
"CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT NOT NULL
)"
)
.execute(&pool)
.await
.expect("Failed to create settings table");
let existing_keybind = sqlx::query_scalar::<_, Option<String>>(
"SELECT value FROM settings WHERE key = 'keybind'"
)
.fetch_one(&pool)
.await;
match existing_keybind {
Ok(Some(_)) => {
},
Ok(None) => {
let default_keybind = KeybindSetting {
keybind: vec!["Meta".to_string(), "V".to_string()],
};
let json = serde_json::to_string(&default_keybind).unwrap();
sqlx::query(
"INSERT INTO settings (key, value) VALUES ('keybind', ?)"
)
.bind(json)
.execute(&pool)
.await
.expect("Failed to insert default keybind");
},
Err(e) => {
eprintln!("Failed to check existing keybind: {}", e);
}
}
// Setup history table
sqlx::query( sqlx::query(
"CREATE TABLE IF NOT EXISTS history ( "CREATE TABLE IF NOT EXISTS history (
id TEXT PRIMARY KEY, id TEXT PRIMARY KEY,
@ -38,7 +85,7 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
) )
.execute(&pool) .execute(&pool)
.await .await
.expect("Failed to create table"); .expect("Failed to create history table");
sqlx::query( sqlx::query(
"CREATE INDEX IF NOT EXISTS idx_timestamp ON history (timestamp)" "CREATE INDEX IF NOT EXISTS idx_timestamp ON history (timestamp)"
@ -68,3 +115,40 @@ pub fn setup(app: &mut tauri::App) -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
#[tauri::command]
pub async fn save_keybind(
keybind: Vec<String>,
pool: State<'_, SqlitePool>,
) -> Result<(), String> {
let setting = KeybindSetting { keybind };
let json = serde_json::to_string(&setting).map_err(|e| e.to_string())?;
sqlx::query(
"INSERT OR REPLACE INTO settings (key, value) VALUES ('keybind', ?)"
)
.bind(json)
.execute(&*pool)
.await
.map_err(|e| e.to_string())?;
Ok(())
}
#[tauri::command]
pub async fn get_keybind(pool: State<'_, SqlitePool>) -> Result<Vec<String>, String> {
let result = sqlx::query_scalar::<_, String>(
"SELECT value FROM settings WHERE key = 'keybind'"
)
.fetch_optional(&*pool)
.await
.map_err(|e| e.to_string())?;
match result {
Some(json) => {
let setting: KeybindSetting = serde_json::from_str(&json).map_err(|e| e.to_string())?;
Ok(setting.keybind)
},
None => Ok(vec!["Meta".to_string(), "V".to_string()]),
}
}

View file

@ -121,16 +121,3 @@ pub fn start_keybind_capture() {
pub fn stop_keybind_capture() { pub fn stop_keybind_capture() {
IS_CAPTURING_KEYBIND.store(false, Ordering::SeqCst); 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(())
}

View file

@ -31,10 +31,10 @@ fn main() {
.setup(|app| { .setup(|app| {
let app_handle = app.handle().clone(); let app_handle = app.handle().clone();
// #[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
api::hotkeys::setup(app_handle.clone()); api::hotkeys::setup(app_handle.clone());
api::tray::setup(app)?; api::tray::setup(app)?;
api::database::setup(app)?; let _ = api::database::setup(app);
api::clipboard::setup(app.handle()); api::clipboard::setup(app.handle());
let _ = api::clipboard::start_monitor(app_handle.clone()); let _ = api::clipboard::start_monitor(app_handle.clone());
@ -76,8 +76,8 @@ fn main() {
api::clipboard::read_image, api::clipboard::read_image,
api::hotkeys::start_keybind_capture, api::hotkeys::start_keybind_capture,
api::hotkeys::stop_keybind_capture, api::hotkeys::stop_keybind_capture,
api::hotkeys::get_current_keybind, api::database::save_keybind,
api::hotkeys::save_keybind, api::database::get_keybind
]) ])
.run(tauri::generate_context!()) .run(tauri::generate_context!())
.expect("error while running tauri application"); .expect("error while running tauri application");