diff --git a/src-tauri/src/config.rs b/src-tauri/src/config.rs index dc20103..f75c1f7 100644 --- a/src-tauri/src/config.rs +++ b/src-tauri/src/config.rs @@ -6,7 +6,6 @@ use is_terminal::IsTerminal; use serde::{Serialize, Deserialize}; use sqlx::SqlitePool; use tauri::{ - AppHandle, Manager, GlobalShortcutManager, async_runtime as rt, @@ -27,10 +26,17 @@ pub struct TermConfig { #[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] -pub struct HotkeyConfig { +pub struct HotkeysConfig { // tauri uses strings to represent keybinds, so we will as well - pub show_window: String, - pub launch_terminal: String, + pub show_window: Hotkey, + pub launch_terminal: Hotkey, +} + + +#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)] +pub struct Hotkey { + pub keys: String, + pub enabled: bool, } @@ -49,7 +55,7 @@ pub struct AppConfig { #[serde(default = "default_term_config")] pub terminal: TermConfig, #[serde(default = "default_hotkey_config")] - pub hotkeys: HotkeyConfig, + pub hotkeys: HotkeysConfig, } @@ -187,42 +193,46 @@ fn default_term_config() -> TermConfig { } -fn default_hotkey_config() -> HotkeyConfig { - HotkeyConfig { - show_window: "alt+shift+C".into(), - launch_terminal: "alt+shift+T".into(), +fn default_hotkey_config() -> HotkeysConfig { + HotkeysConfig { + show_window: Hotkey {keys: "alt+shift+C".into(), enabled: true}, + launch_terminal: Hotkey {keys: "alt+shift+T".into(), enabled: true}, } } // note: will panic if called before APP is set -pub fn register_hotkeys(hotkeys: &HotkeyConfig) -> tauri::Result<()> { +pub fn register_hotkeys(hotkeys: &HotkeysConfig) -> tauri::Result<()> { let app = crate::app::APP.get().unwrap(); let mut manager = app.global_shortcut_manager(); manager.unregister_all()?; - let h = app.app_handle(); - manager.register( - &hotkeys.show_window, - move || { - h.get_window("main") - .map(|w| w.show().error_popup("Failed to show")) - .ok_or(HandlerError::NoMainWindow) - .error_popup("No main window"); - }, - )?; + if hotkeys.show_window.enabled { + let handle = app.app_handle(); + manager.register( + &hotkeys.show_window.keys, + move || { + handle.get_window("main") + .map(|w| w.show().error_popup("Failed to show")) + .ok_or(HandlerError::NoMainWindow) + .error_popup("No main window"); + }, + )?; + } - // register() doesn't take an async fn, so we have to use spawn - manager.register( - &hotkeys.launch_terminal, - || { - rt::spawn(async { - crate::terminal::launch(false) - .await - .error_popup("Failed to launch"); - }); - } - )?; + if hotkeys.launch_terminal.enabled { + // register() doesn't take an async fn, so we have to use spawn + manager.register( + &hotkeys.launch_terminal.keys, + || { + rt::spawn(async { + crate::terminal::launch(false) + .await + .error_popup("Failed to launch"); + }); + } + )?; + } Ok(()) } diff --git a/src-tauri/src/state.rs b/src-tauri/src/state.rs index ffb2c9f..633a1f6 100644 --- a/src-tauri/src/state.rs +++ b/src-tauri/src/state.rs @@ -71,7 +71,9 @@ impl AppState { sv.rebind(new_config.listen_addr, new_config.listen_port).await?; } // re-register hotkeys if necessary - if new_config.hotkeys != live_config.hotkeys { + if new_config.hotkeys.show_window != live_config.hotkeys.show_window + || new_config.hotkeys.launch_terminal != live_config.hotkeys.launch_terminal + { config::register_hotkeys(&new_config.hotkeys)?; } diff --git a/src/ui/KeyCombo.svelte b/src/ui/KeyCombo.svelte new file mode 100644 index 0000000..99b01e1 --- /dev/null +++ b/src/ui/KeyCombo.svelte @@ -0,0 +1,11 @@ + + + +
+ {#each keys as key, i} + {#if i > 0} + {/if} + {key} + {/each} +
diff --git a/src/ui/settings/FileSetting.svelte b/src/ui/settings/FileSetting.svelte index 0eef6e6..c3c0bde 100644 --- a/src/ui/settings/FileSetting.svelte +++ b/src/ui/settings/FileSetting.svelte @@ -4,14 +4,13 @@ import Setting from './Setting.svelte'; export let title; - export let divider = true; export let value; const dispatch = createEventDispatcher(); - +
+ import { createEventDispatcher } from 'svelte'; + import KeyCombo from '../KeyCombo.svelte'; + + export let description; + export let value; + + const id = Math.random().toString().slice(2); + const dispatch = createEventDispatcher(); + let listening = false; + + function listen() { + // don't re-listen if we already are + if (listening) return; + + listening = true; + window.addEventListener('keyup', setKeybind, {once: true}); + // setTimeout avoids reacting to the click event that we are currently processing + setTimeout(() => window.addEventListener('click', cancel, {once: true}), 0); + } + + function setKeybind(event) { + console.log(event); + let keys = []; + if (event.ctrlKey) keys.push('ctrl'); + if (event.altKey) keys.push('alt'); + if (event.metaKey) keys.push('meta'); + if (event.shiftKey) keys.push('shift'); + keys.push(event.key); + + value.keys = keys.join('+'); + dispatch('update', {value}); + listening = false; + window.removeEventListener('click', cancel, {once: true}); + event.preventDefault(); + event.stopPropagation(); + } + + function cancel() { + listening = false; + window.removeEventListener('keyup', setKeybind, {once: true}); + } + + + + dispatch('update', {value})} +> + + + diff --git a/src/ui/settings/NumericSetting.svelte b/src/ui/settings/NumericSetting.svelte index 161b923..4c8e4c2 100644 --- a/src/ui/settings/NumericSetting.svelte +++ b/src/ui/settings/NumericSetting.svelte @@ -4,8 +4,8 @@ import Setting from './Setting.svelte'; export let title; - export let divider = true; export let value; + export let unit = ''; export let min = null; export let max = null; @@ -60,7 +60,7 @@ - +
{#if unit} {unit}: diff --git a/src/ui/settings/Setting.svelte b/src/ui/settings/Setting.svelte index d7f0b9a..e506312 100644 --- a/src/ui/settings/Setting.svelte +++ b/src/ui/settings/Setting.svelte @@ -3,20 +3,20 @@ import ErrorAlert from '../ErrorAlert.svelte'; export let title; - export let divider = true; -{#if divider} -
-{/if} -
-

{title}

- -
+
+
+

{title}

+ {#if $$slots.input} + + {/if} +
-{#if $$slots.description} -

- -

-{/if} + {#if $$slots.description} +

+ +

+ {/if} +
diff --git a/src/ui/settings/SettingsGroup.svelte b/src/ui/settings/SettingsGroup.svelte new file mode 100644 index 0000000..97b4d3f --- /dev/null +++ b/src/ui/settings/SettingsGroup.svelte @@ -0,0 +1,14 @@ + + + +
+
+

{name}

+
+ +
+ +
+
diff --git a/src/ui/settings/TextSetting.svelte b/src/ui/settings/TextSetting.svelte index 1bdbfb4..bcb9917 100644 --- a/src/ui/settings/TextSetting.svelte +++ b/src/ui/settings/TextSetting.svelte @@ -3,14 +3,13 @@ import Setting from './Setting.svelte'; export let title; - export let divider = true; export let value; const dispatch = createEventDispatcher(); - +
- +
diff --git a/src/views/Settings.svelte b/src/views/Settings.svelte index eb3a248..602d8f4 100644 --- a/src/views/Settings.svelte +++ b/src/views/Settings.svelte @@ -1,11 +1,18 @@ + + + @@ -36,68 +38,71 @@ {#await invoke('get_config') then config} -
- +
+ + + + Start Creddy when you log in to your computer. + + -
-

General

-
- - - - Start Creddy when you log in to your computer. - - + + + Minimize to the system tray at startup. + + - - - Minimize to the system tray at startup. - - + + + How long to wait after a request is approved/denied before minimizing + the window to tray. Only applicable if the window was minimized + to tray before the request was received. + + - - - How long to wait after a request is approved/denied before minimizing - the window to tray. Only applicable if the window was minimized - to tray before the request was received. - - + + + Listen for credentials requests on this port. + (Should be used with $AWS_CONTAINER_CREDENTIALS_FULL_URI) + + - - - Listen for credentials requests on this port. - (Should be used with $AWS_CONTAINER_CREDENTIALS_FULL_URI) - - + + + + + + Update or re-enter your encrypted credentials. + + - - - - - - Update or re-enter your encrypted credentials. - - + + + Choose your preferred terminal emulator (e.g. gnome-terminal or wt.exe.) May be an absolute path or an executable discoverable on $PATH. + + +
-
-

Terminal

-
+ +
+

Click on a keybinding to modify it. Use the checkbox to enable or disable a keybinding entirely.

+ +
+ + +
+
+
- - - Choose your preferred terminal emulator (e.g. gnome-terminal, wt.exe.) May be an absolute path or an executable discoverable on $PATH. - -
{/await}