mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
feat(control): bind arrow keys to arrow buttons
This commit is contained in:
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
{#if content.open}
|
{#if content.open}
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 backdrop-blur flex justify-center items-center z-50 {className}"
|
class="popup absolute inset-0 backdrop-blur flex justify-center items-center z-50 {className}"
|
||||||
transition:fade={{ duration: 100 }}
|
transition:fade={{ duration: 100 }}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
import { liveQuery, type Observable } from 'dexie';
|
import { liveQuery, type Observable } from 'dexie';
|
||||||
import TextInput from '$lib/components/TextInput.svelte';
|
import TextInput from '$lib/components/TextInput.svelte';
|
||||||
import { add_to_keyboard_queue } from '$lib/ts/utils';
|
import { add_to_keyboard_queue } from '$lib/ts/utils';
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
let all_display_states: Observable<'on' | 'off' | 'mixed'> | undefined = $state();
|
let all_display_states: Observable<'on' | 'off' | 'mixed'> | undefined = $state();
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
@@ -44,11 +45,16 @@
|
|||||||
let popup_content: PopupContent = $state({
|
let popup_content: PopupContent = $state({
|
||||||
open: false,
|
open: false,
|
||||||
snippet: null,
|
snippet: null,
|
||||||
title: '',
|
title: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
let current_text = $state('');
|
let current_text = $state('');
|
||||||
|
|
||||||
|
const key_pressed = $state({
|
||||||
|
ArrowRight: false,
|
||||||
|
ArrowLeft: false
|
||||||
|
});
|
||||||
|
|
||||||
function popup_close_function() {
|
function popup_close_function() {
|
||||||
popup_content.open = false;
|
popup_content.open = false;
|
||||||
}
|
}
|
||||||
@@ -79,7 +85,7 @@
|
|||||||
snippet: website_popup,
|
snippet: website_popup,
|
||||||
title: 'Webseite Anzeigen',
|
title: 'Webseite Anzeigen',
|
||||||
window_class: 'w-xl',
|
window_class: 'w-xl',
|
||||||
title_icon: Globe,
|
title_icon: Globe
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,7 +108,7 @@
|
|||||||
open: true,
|
open: true,
|
||||||
snippet: ask_shutdown_popup,
|
snippet: ask_shutdown_popup,
|
||||||
title: 'Bildschirm Herunterfahren',
|
title: 'Bildschirm Herunterfahren',
|
||||||
title_icon: PowerOff,
|
title_icon: PowerOff
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +116,10 @@
|
|||||||
popup_content.open = false;
|
popup_content.open = false;
|
||||||
await run_on_all_selected_displays((d) => {
|
await run_on_all_selected_displays((d) => {
|
||||||
shutdown(d.ip); // no await here because we want to be fast
|
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);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,10 +152,58 @@
|
|||||||
|
|
||||||
async function send_website() {
|
async function send_website() {
|
||||||
popup_content.open = false;
|
popup_content.open = false;
|
||||||
await run_on_all_selected_displays((d) =>
|
await run_on_all_selected_displays((d) => open_website(d.ip, website_url));
|
||||||
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);
|
||||||
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#snippet website_popup()}
|
{#snippet website_popup()}
|
||||||
@@ -185,11 +242,11 @@
|
|||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
{#snippet send_keys_popup()}
|
{#snippet send_keys_popup()}
|
||||||
<KeyInput {popup_close_function}/>
|
<KeyInput {popup_close_function} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
{#snippet text_popup()}
|
{#snippet text_popup()}
|
||||||
<TipTapInput bind:text={current_text}/>
|
<TipTapInput bind:text={current_text} />
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
<div class="grid grid-rows-[2.5rem_auto] bg-stone-800 rounded-2xl min-w-0">
|
<div class="grid grid-rows-[2.5rem_auto] bg-stone-800 rounded-2xl min-w-0">
|
||||||
@@ -202,15 +259,19 @@
|
|||||||
<div class="flex flex-row gap-2 w-75 justify-normal">
|
<div class="flex flex-row gap-2 w-75 justify-normal">
|
||||||
<button
|
<button
|
||||||
title="Vorherige Folie (Pfeil nach Links) [gedrückt halten möglich]"
|
title="Vorherige Folie (Pfeil nach Links) [gedrückt halten möglich]"
|
||||||
class="px-9 bg-stone-700 {$selected_online_display_ids.length === 0
|
class="px-9 {key_pressed.ArrowLeft
|
||||||
|
? 'bg-stone-500'
|
||||||
|
: 'bg-stone-700'} {$selected_online_display_ids.length === 0
|
||||||
? 'text-stone-500 cursor-not-allowed'
|
? 'text-stone-500 cursor-not-allowed'
|
||||||
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
||||||
disabled={$selected_online_display_ids.length === 0}
|
disabled={$selected_online_display_ids.length === 0 || key_pressed.ArrowLeft}
|
||||||
onmousedown={() => {
|
onmousedown={() => {
|
||||||
add_to_keyboard_queue(async () => await send_single_key_press('ArrowLeft', 'press'));
|
add_to_keyboard_queue(async () => await send_single_key_press('ArrowLeft', 'press'));
|
||||||
}}
|
}}
|
||||||
onmouseup={() => {
|
onmouseup={() => {
|
||||||
add_to_keyboard_queue(async () => await send_single_key_press('ArrowLeft', 'release'));
|
add_to_keyboard_queue(
|
||||||
|
async () => await send_single_key_press('ArrowLeft', 'release')
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowBigLeft />
|
<ArrowBigLeft />
|
||||||
@@ -218,15 +279,21 @@
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
title="Nächste Folie (Pfeil nach Rechts) [gedrückt halten möglich]"
|
title="Nächste Folie (Pfeil nach Rechts) [gedrückt halten möglich]"
|
||||||
class="px-9 bg-stone-700 {$selected_online_display_ids.length === 0
|
class="px-9 {key_pressed.ArrowRight
|
||||||
? 'text-stone-500 cursor-not-allowed'
|
? 'bg-stone-500 cursor-not-allowed'
|
||||||
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
: `bg-stone-700 ${
|
||||||
disabled={$selected_online_display_ids.length === 0}
|
$selected_online_display_ids.length === 0
|
||||||
|
? 'text-stone-500 cursor-not-allowed'
|
||||||
|
: 'hover:bg-stone-600 active:bg-stone-500 cursor-pointer'
|
||||||
|
}`} py-2 rounded-xl flex justify-center items-center transition-colors duration-200"
|
||||||
|
disabled={$selected_online_display_ids.length === 0 || key_pressed.ArrowRight}
|
||||||
onmousedown={() => {
|
onmousedown={() => {
|
||||||
add_to_keyboard_queue(async () => await send_single_key_press('ArrowRight', 'press'));
|
add_to_keyboard_queue(async () => await send_single_key_press('ArrowRight', 'press'));
|
||||||
}}
|
}}
|
||||||
onmouseup={() => {
|
onmouseup={() => {
|
||||||
add_to_keyboard_queue(async () => await send_single_key_press('ArrowRight', 'release'));
|
add_to_keyboard_queue(
|
||||||
|
async () => await send_single_key_press('ArrowRight', 'release')
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowBigRight />
|
<ArrowBigRight />
|
||||||
@@ -271,8 +338,7 @@
|
|||||||
<div class="flex flex-col gap-2">
|
<div class="flex flex-col gap-2">
|
||||||
<Button
|
<Button
|
||||||
className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||||
disabled={$all_display_states === 'on' ||
|
disabled={$all_display_states === 'on' || $selected_display_ids.length === 0}
|
||||||
$selected_display_ids.length === 0}
|
|
||||||
click_function={startup_action}
|
click_function={startup_action}
|
||||||
>
|
>
|
||||||
<Power /> Bildschirm Hochfahren
|
<Power /> Bildschirm Hochfahren
|
||||||
@@ -280,8 +346,7 @@
|
|||||||
|
|
||||||
<Button
|
<Button
|
||||||
className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||||
disabled={$all_display_states === 'off' ||
|
disabled={$all_display_states === 'off' || $selected_online_display_ids.length === 0}
|
||||||
$selected_online_display_ids.length === 0}
|
|
||||||
click_function={ask_shutdown}
|
click_function={ask_shutdown}
|
||||||
>
|
>
|
||||||
<PowerOff /> Bildschirm Herunterfahren</Button
|
<PowerOff /> Bildschirm Herunterfahren</Button
|
||||||
|
|||||||
Reference in New Issue
Block a user