mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
add Keyboard Input, improve PopUp, improve general code
This commit is contained in:
@@ -12,50 +12,90 @@
|
||||
TrafficCone
|
||||
} from 'lucide-svelte';
|
||||
import Button from './Button.svelte';
|
||||
import PopUp from './PopUp.svelte';
|
||||
import type { PopupContent } from '../ts/types';
|
||||
import KeyInput from './KeyInput.svelte';
|
||||
|
||||
let popup_content: PopupContent = $state({
|
||||
open: false,
|
||||
snippet: null,
|
||||
title: '',
|
||||
closable: true
|
||||
});
|
||||
|
||||
function popup_close_function() {
|
||||
popup_content.open = false;
|
||||
}
|
||||
|
||||
const show_send_keys_popup = () => {
|
||||
popup_content = {
|
||||
open: true,
|
||||
snippet: send_keys_popup,
|
||||
title: 'Tastatur-Eingaben durchgeben',
|
||||
title_icon: Keyboard,
|
||||
closable: true
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
{#snippet send_keys_popup()}
|
||||
<div>
|
||||
<KeyInput />
|
||||
</div>
|
||||
<div class="flex flex-row justify-end gap-2">
|
||||
<Button className="px-4 font-bold" click_function={popup_close_function}>Fertig</Button>
|
||||
</div>
|
||||
{/snippet}
|
||||
|
||||
<div class="grid grid-rows-[2.5rem_auto] bg-stone-800 rounded-2xl min-w-0">
|
||||
<div class="text-xl font-bold pl-3 content-center bg-stone-700 rounded-t-2xl truncate min-w-0">
|
||||
Bildschirme steuern
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 p-2 overflow-auto">
|
||||
<div class="relative flex flex-col gap-2 p-2 overflow-auto">
|
||||
<div class="flex flex-row justify-between gap-2">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex flex-row gap-2 w-70 justify-normal">
|
||||
<Button title="Vorherige Folie (Pfeil nach Links)" className="px-7"
|
||||
<div class="flex flex-row gap-2 w-75 justify-normal">
|
||||
<Button title="Vorherige Folie (Pfeil nach Links)" className="px-9"
|
||||
><ArrowBigLeft /></Button
|
||||
>
|
||||
<Button title="Nächste Folie (Pfeil nach Rechts)" className="px-7"
|
||||
<Button title="Nächste Folie (Pfeil nach Rechts)" className="px-9"
|
||||
><ArrowBigRight /></Button
|
||||
>
|
||||
</div>
|
||||
<Button className="px-3 flex gap-3 w-70 justify-normal"
|
||||
<Button className="px-3 flex gap-3 w-75 justify-normal"
|
||||
><TextAlignStart /> Text anzeigen</Button
|
||||
>
|
||||
<Button className="px-3 flex gap-3 w-70 justify-normal"><Presentation />Blackout</Button>
|
||||
<Button className="px-3 flex gap-3 w-75 justify-normal"><Presentation />Blackout</Button>
|
||||
<div class="flex flex-row justify-normal">
|
||||
<Button className="rounded-r-none pl-3 flex gap-3 grow w-60 justify-normal"
|
||||
<Button className="rounded-r-none pl-3 flex gap-3 grow w-65 justify-normal"
|
||||
><TrafficCone /> Fallback-Bild anzeigen</Button
|
||||
>
|
||||
<Button className="rounded-l-none flex grow-0 w-10"><ChevronDown /></Button>
|
||||
</div>
|
||||
<Button className="px-3 flex gap-3 w-70 justify-normal"
|
||||
><Keyboard /> Tastatur-Inputs durchgeben</Button
|
||||
<Button
|
||||
className="px-3 flex gap-3 w-75 justify-normal"
|
||||
click_function={show_send_keys_popup}><Keyboard /> Tastatur-Eingaben durchgeben</Button
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2 justify-between">
|
||||
<div class="flex flex-col gap-2">
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||
><Power /> PC hochfahren</Button
|
||||
>
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||
><PowerOff /> PC herunterfahren</Button
|
||||
>
|
||||
</div>
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-70 justify-normal"
|
||||
<Button className="px-3 flex gap-3 w-full xl:w-75 justify-normal"
|
||||
><SquareTerminal /> Shell-Befehl ausführen</Button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<PopUp
|
||||
content={popup_content}
|
||||
close_function={popup_close_function}
|
||||
className="rounded-b-2xl"
|
||||
snippet_container_class="overflow-hidden"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
import OnlineState from './OnlineState.svelte';
|
||||
import type { Display, MenuOption } from '../ts/types';
|
||||
import { is_selected, select, selected_display_ids } from '../ts/stores/select';
|
||||
import { update_screenshot } from '../ts/stores/displays';
|
||||
|
||||
let { display, get_display_menu_options } = $props<{
|
||||
display: Display;
|
||||
@@ -29,6 +30,7 @@
|
||||
} else {
|
||||
$pinned_display_id = display.id;
|
||||
}
|
||||
update_screenshot(display.id);
|
||||
e.stopPropagation();
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
<div class="flex flex-row gap-1">
|
||||
<OnlineState
|
||||
selected={false}
|
||||
status={pinned_display?.status ?? ''}
|
||||
status={pinned_display?.status ?? null}
|
||||
className="flex items-center px-2"
|
||||
/>
|
||||
<Button
|
||||
|
||||
@@ -30,7 +30,12 @@
|
||||
import RefreshPlay from './RefreshPlay.svelte';
|
||||
import { get_file_size_display_string } from '../ts/utils';
|
||||
import { open_file } from '../ts/api_handler';
|
||||
import { displays, get_display_by_id, update_screenshot } from '../ts/stores/displays';
|
||||
import {
|
||||
displays,
|
||||
get_display_by_id,
|
||||
run_on_all_selected_displays,
|
||||
update_screenshot
|
||||
} from '../ts/stores/displays';
|
||||
|
||||
let { file } = $props<{ file: FolderElement }>();
|
||||
|
||||
@@ -97,13 +102,7 @@
|
||||
change_file_path($current_file_path + file.name + '/');
|
||||
} else {
|
||||
const path_to_file = $current_file_path + file.name;
|
||||
for (const display_id of $selected_display_ids) {
|
||||
const ip = get_display_by_id(display_id, $displays)?.ip ?? null;
|
||||
if (ip) {
|
||||
await open_file(ip, path_to_file);
|
||||
await update_screenshot(display_id);
|
||||
}
|
||||
}
|
||||
await run_on_all_selected_displays(open_file, true, path_to_file);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<script lang="ts">
|
||||
import { flip } from 'svelte/animate';
|
||||
import { get_selectable_color_classes } from '../ts/stores/ui_behavior';
|
||||
import key_map_json from './../../../../shared/keys.json';
|
||||
import { fade } from 'svelte/transition';
|
||||
import { selected_display_ids } from '../ts/stores/select';
|
||||
import { displays, get_display_by_id, run_on_all_selected_displays } from '../ts/stores/displays';
|
||||
import { send_keyboard_input } from '../ts/api_handler';
|
||||
|
||||
const bg = 'bg-stone-700';
|
||||
const key_map: Record<string, string> = key_map_json as Record<string, string>;
|
||||
|
||||
let active = $state(false);
|
||||
let last_keys: { id: number; key: string }[] = $state([]);
|
||||
|
||||
let el: HTMLDivElement;
|
||||
|
||||
function add_to_last_keys(name: string) {
|
||||
const id = Date.now();
|
||||
last_keys.push({ id, key: name });
|
||||
setTimeout(() => {
|
||||
last_keys = last_keys.filter((e) => e.id !== id);
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
async function on_key_down(e: KeyboardEvent) {
|
||||
if (!active) return;
|
||||
const id = key_map[e.code];
|
||||
if (!id) return;
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
add_to_last_keys(e.code);
|
||||
if (e.repeat) return;
|
||||
|
||||
await run_on_all_selected_displays(send_keyboard_input, true, id);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
role="textbox"
|
||||
tabindex="0"
|
||||
bind:this={el}
|
||||
onclick={() => {
|
||||
if (active) {
|
||||
el.blur();
|
||||
} else {
|
||||
el.focus();
|
||||
active = true;
|
||||
}
|
||||
}}
|
||||
onblur={() => (active = false)}
|
||||
onkeydown={on_key_down}
|
||||
class="relative flex justify-center items-center h-15 w-full cursor-pointer rounded-xl transition-colors duration-200 select-none {get_selectable_color_classes(
|
||||
active,
|
||||
{
|
||||
bg: true,
|
||||
hover: true,
|
||||
active: true,
|
||||
text: true
|
||||
}
|
||||
)}"
|
||||
>
|
||||
{active ? 'Erfassung aktiv' : 'Hier für Erfassung klicken'}
|
||||
<div class="absolute top-full left-0 ml-1 mt-0.5 flex flex-col-reverse text-sm text-stone-400">
|
||||
{#each last_keys as key (key.id)}
|
||||
<span animate:flip={{ duration: 200 }} in:fade={{ duration: 200 }} out:fade={{ duration: 500 }} >{key.key}</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
@@ -5,9 +5,11 @@
|
||||
import type { PopupContent } from '../ts/types';
|
||||
import { fade } from 'svelte/transition';
|
||||
|
||||
let { content, close_function } = $props<{
|
||||
let { content, close_function, className = '', snippet_container_class = '' } = $props<{
|
||||
content: PopupContent;
|
||||
close_function: () => void;
|
||||
className?: string;
|
||||
snippet_container_class?: string;
|
||||
}>();
|
||||
|
||||
function try_to_close() {
|
||||
@@ -31,7 +33,7 @@
|
||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div
|
||||
class="absolute inset-0 backdrop-blur bg-white/10 flex justify-center items-center"
|
||||
class="absolute inset-0 backdrop-blur flex justify-center items-center {className}"
|
||||
onclick={try_to_close}
|
||||
transition:fade={{ duration: 100 }}
|
||||
>
|
||||
@@ -42,12 +44,12 @@
|
||||
onclick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div
|
||||
class="text-2xl font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-6 w-full"
|
||||
class="font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-8 w-full"
|
||||
>
|
||||
<div class="flex flex-row flex-1 gap-4 pl-2 py-1 items-center grow whitespace-nowrap min-w-0 flex-shrink-0 {content.title_class ?? ''}">
|
||||
<div class="flex flex-row flex-1 gap-3 pl-2 py-1 items-center grow whitespace-nowrap min-w-0 flex-shrink-0 text-lg {content.title_class ?? ''}">
|
||||
{#if content.title_icon}
|
||||
{@const Icon = content.title_icon}
|
||||
<Icon strokeWidth="2.8" class="flex-shrink-0" />
|
||||
<Icon strokeWidth="2" class="flex-shrink-0" />
|
||||
{/if}
|
||||
<div class="flex-shrink-0">
|
||||
{content.title}
|
||||
@@ -61,7 +63,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2">
|
||||
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2 {snippet_container_class}">
|
||||
{@render content.snippet(content.snippet_arg)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user