From a49b842a4ca200f8271f1b8b41cc96183583ab88 Mon Sep 17 00:00:00 2001 From: E44 <129310925+programmer-44@users.noreply.github.com> Date: Sat, 13 Jun 2026 22:00:09 +0200 Subject: [PATCH] feat(control): bind arrow keys to arrow buttons --- .../frontend/src/lib/components/PopUp.svelte | 2 +- .../frontend/src/routes/ControlView.svelte | 107 ++++++++++++++---- 2 files changed, 87 insertions(+), 22 deletions(-) diff --git a/control/frontend/src/lib/components/PopUp.svelte b/control/frontend/src/lib/components/PopUp.svelte index 940e291..852f9e6 100644 --- a/control/frontend/src/lib/components/PopUp.svelte +++ b/control/frontend/src/lib/components/PopUp.svelte @@ -36,7 +36,7 @@ {#if content.open}
| undefined = $state(); $effect(() => { @@ -44,11 +45,16 @@ let popup_content: PopupContent = $state({ open: false, snippet: null, - title: '', + title: '' }); let current_text = $state(''); + const key_pressed = $state({ + ArrowRight: false, + ArrowLeft: false + }); + function popup_close_function() { popup_content.open = false; } @@ -79,7 +85,7 @@ snippet: website_popup, title: 'Webseite Anzeigen', window_class: 'w-xl', - title_icon: Globe, + title_icon: Globe }; }; @@ -102,7 +108,7 @@ open: true, snippet: ask_shutdown_popup, title: 'Bildschirm Herunterfahren', - title_icon: PowerOff, + title_icon: PowerOff }; } @@ -110,7 +116,10 @@ popup_content.open = false; await run_on_all_selected_displays((d) => { shutdown(d.ip); // no await here because we want to be fast - db.displays.update(d.id, { status: 'app_offline', preview: { currently_updating: false, url: null} }); + db.displays.update(d.id, { + status: 'app_offline', + preview: { currently_updating: false, url: null } + }); }, false); } @@ -143,10 +152,58 @@ async function send_website() { popup_content.open = false; - await run_on_all_selected_displays((d) => - open_website(d.ip, website_url) - ); + await run_on_all_selected_displays((d) => open_website(d.ip, website_url)); } + + function has_open_popup(): boolean { + return document.querySelector('.popup') !== null; + } + + function handle_key( + event: KeyboardEvent, + key: 'ArrowRight' | 'ArrowLeft', + action: 'press' | 'release' + ) { + if (event.key === key) { + const current_press_state: boolean = key_pressed[key]; + if ( + (action === 'press' && (current_press_state === true || has_open_popup())) || + (action === 'release' && current_press_state === false) + ) + return; + + key_pressed[key] = !current_press_state; + add_to_keyboard_queue(async () => { + await run_on_all_selected_displays( + (d) => send_keyboard_input(d.ip, [{ key, action }]), + true + ); + }); + } + } + + function add_remove_event_listeners( + add_remove_function: (type: string, listener: (e: KeyboardEvent) => void) => void + ) { + const actions = { + keydown: 'press', + keyup: 'release' + } as const; + const keys = ['ArrowRight', 'ArrowLeft'] as const; + + for (const [action_type, action_value] of Object.entries(actions)) { + for (const key of keys) { + add_remove_function(action_type, (e: KeyboardEvent) => handle_key(e, key, action_value)); + } + } + } + + onMount(() => { + add_remove_event_listeners(window.addEventListener); + return () => { + add_remove_event_listeners(window.removeEventListener); + }; + }); {#snippet website_popup()} @@ -185,11 +242,11 @@ {/snippet} {#snippet send_keys_popup()} - + {/snippet} {#snippet text_popup()} - + {/snippet}
@@ -202,15 +259,19 @@