mirror of
https://codeberg.org/PLG-Development/PLG-MuDiCS
synced 2026-07-06 00:47:09 +00:00
chore: add display text
This commit is contained in:
Generated
+20
@@ -10,6 +10,7 @@
|
|||||||
"npm:@tailwindcss/typography@~0.5.15": "0.5.16_tailwindcss@4.1.11",
|
"npm:@tailwindcss/typography@~0.5.15": "0.5.16_tailwindcss@4.1.11",
|
||||||
"npm:@tailwindcss/vite@4": "4.1.11_vite@7.0.6__picomatch@4.0.3",
|
"npm:@tailwindcss/vite@4": "4.1.11_vite@7.0.6__picomatch@4.0.3",
|
||||||
"npm:@thisux/sveltednd@^0.0.20": "0.0.20_svelte@5.37.1__acorn@8.15.0",
|
"npm:@thisux/sveltednd@^0.0.20": "0.0.20_svelte@5.37.1__acorn@8.15.0",
|
||||||
|
"npm:dexie@^4.2.1": "4.2.1",
|
||||||
"npm:eslint-config-prettier@^10.0.1": "10.1.8_eslint@9.33.0",
|
"npm:eslint-config-prettier@^10.0.1": "10.1.8_eslint@9.33.0",
|
||||||
"npm:eslint-plugin-svelte@3": "3.11.0_eslint@9.33.0_svelte@5.37.1__acorn@8.15.0_postcss@8.5.6",
|
"npm:eslint-plugin-svelte@3": "3.11.0_eslint@9.33.0_svelte@5.37.1__acorn@8.15.0_postcss@8.5.6",
|
||||||
"npm:eslint@^9.18.0": "9.33.0",
|
"npm:eslint@^9.18.0": "9.33.0",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"npm:prettier@^3.4.2": "3.6.2",
|
"npm:prettier@^3.4.2": "3.6.2",
|
||||||
"npm:svelte-check@4": "4.3.0_svelte@5.37.1__acorn@8.15.0_typescript@5.8.3",
|
"npm:svelte-check@4": "4.3.0_svelte@5.37.1__acorn@8.15.0_typescript@5.8.3",
|
||||||
"npm:svelte-dnd-action@~0.9.65": "0.9.65_svelte@5.37.1__acorn@8.15.0",
|
"npm:svelte-dnd-action@~0.9.65": "0.9.65_svelte@5.37.1__acorn@8.15.0",
|
||||||
|
"npm:svelte-splitpanes@^8.0.9": "8.0.9_svelte@5.37.1__acorn@8.15.0",
|
||||||
"npm:svelte@5": "5.37.1_acorn@8.15.0",
|
"npm:svelte@5": "5.37.1_acorn@8.15.0",
|
||||||
"npm:tailwindcss@4": "4.1.11",
|
"npm:tailwindcss@4": "4.1.11",
|
||||||
"npm:typescript-eslint@^8.20.0": "8.40.0_eslint@9.33.0_typescript@5.8.3_@typescript-eslint+parser@8.40.0__eslint@9.33.0__typescript@5.8.3",
|
"npm:typescript-eslint@^8.20.0": "8.40.0_eslint@9.33.0_typescript@5.8.3_@typescript-eslint+parser@8.40.0__eslint@9.33.0__typescript@5.8.3",
|
||||||
@@ -867,6 +869,9 @@
|
|||||||
"devalue@5.1.1": {
|
"devalue@5.1.1": {
|
||||||
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
|
"integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw=="
|
||||||
},
|
},
|
||||||
|
"dexie@4.2.1": {
|
||||||
|
"integrity": "sha512-Ckej0NS6jxQ4Po3OrSQBFddayRhTCic2DoCAG5zacOfOVB9P2Q5Xc5uL/nVa7ZVs+HdMnvUPzLFCB/JwpB6Csg=="
|
||||||
|
},
|
||||||
"enhanced-resolve@5.18.2": {
|
"enhanced-resolve@5.18.2": {
|
||||||
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
|
"integrity": "sha512-6Jw4sE1maoRJo3q8MsSIn2onJFbLTOjY9hlx4DZXmOKvLRd1Ok2kXmAGXaafL2+ijsJZ1ClYbl/pmqr9+k4iUQ==",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
@@ -991,6 +996,12 @@
|
|||||||
],
|
],
|
||||||
"bin": true
|
"bin": true
|
||||||
},
|
},
|
||||||
|
"esm-env-robust@0.0.3": {
|
||||||
|
"integrity": "sha512-90Gnuw2DALOqlL1581VxP3GHPUNHX9U+fQ+8FNcTTFClhY5gEggAAnJ3q1b2Oq23knRsjv8YpNeMRPaMLUymOA==",
|
||||||
|
"dependencies": [
|
||||||
|
"esm-env"
|
||||||
|
]
|
||||||
|
},
|
||||||
"esm-env@1.2.2": {
|
"esm-env@1.2.2": {
|
||||||
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="
|
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="
|
||||||
},
|
},
|
||||||
@@ -1579,6 +1590,13 @@
|
|||||||
"svelte"
|
"svelte"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"svelte-splitpanes@8.0.9_svelte@5.37.1__acorn@8.15.0": {
|
||||||
|
"integrity": "sha512-L3oLXTC99M191FInTXJ/f/2i0welRql1QuVbPaU8iy6nvCR6X9VyjHCsCpLqKGWHwqkWo/AM9CQ1c0nzlb+MkA==",
|
||||||
|
"dependencies": [
|
||||||
|
"esm-env-robust",
|
||||||
|
"svelte"
|
||||||
|
]
|
||||||
|
},
|
||||||
"svelte@5.37.1_acorn@8.15.0": {
|
"svelte@5.37.1_acorn@8.15.0": {
|
||||||
"integrity": "sha512-h8arWpQZ+3z8eahyBT5KkiBOUsG6xvI5Ykg0ozRr9xEdImgSMUPUlOFWRNkUsT7Ti0DSUCTEbPoped0aoxFyWA==",
|
"integrity": "sha512-h8arWpQZ+3z8eahyBT5KkiBOUsG6xvI5Ykg0ozRr9xEdImgSMUPUlOFWRNkUsT7Ti0DSUCTEbPoped0aoxFyWA==",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
@@ -1729,6 +1747,7 @@
|
|||||||
"npm:@tailwindcss/typography@~0.5.15",
|
"npm:@tailwindcss/typography@~0.5.15",
|
||||||
"npm:@tailwindcss/vite@4",
|
"npm:@tailwindcss/vite@4",
|
||||||
"npm:@thisux/sveltednd@^0.0.20",
|
"npm:@thisux/sveltednd@^0.0.20",
|
||||||
|
"npm:dexie@^4.2.1",
|
||||||
"npm:eslint-config-prettier@^10.0.1",
|
"npm:eslint-config-prettier@^10.0.1",
|
||||||
"npm:eslint-plugin-svelte@3",
|
"npm:eslint-plugin-svelte@3",
|
||||||
"npm:eslint@^9.18.0",
|
"npm:eslint@^9.18.0",
|
||||||
@@ -1738,6 +1757,7 @@
|
|||||||
"npm:prettier@^3.4.2",
|
"npm:prettier@^3.4.2",
|
||||||
"npm:svelte-check@4",
|
"npm:svelte-check@4",
|
||||||
"npm:svelte-dnd-action@~0.9.65",
|
"npm:svelte-dnd-action@~0.9.65",
|
||||||
|
"npm:svelte-splitpanes@^8.0.9",
|
||||||
"npm:svelte@5",
|
"npm:svelte@5",
|
||||||
"npm:tailwindcss@4",
|
"npm:tailwindcss@4",
|
||||||
"npm:typescript-eslint@^8.20.0",
|
"npm:typescript-eslint@^8.20.0",
|
||||||
|
|||||||
Generated
+1528
-32
File diff suppressed because it is too large
Load Diff
@@ -20,14 +20,15 @@
|
|||||||
"@sveltejs/adapter-static": "^3.0.9",
|
"@sveltejs/adapter-static": "^3.0.9",
|
||||||
"@sveltejs/kit": "^2.22.0",
|
"@sveltejs/kit": "^2.22.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
|
||||||
"@tailwindcss/vite": "^4.0.0",
|
"@tailwindcss/vite": "^4.0.0",
|
||||||
|
"@tiptap/extension-placeholder": "^3.11.0",
|
||||||
"eslint": "^9.18.0",
|
"eslint": "^9.18.0",
|
||||||
"eslint-config-prettier": "^10.0.1",
|
"eslint-config-prettier": "^10.0.1",
|
||||||
"eslint-plugin-svelte": "^3.0.0",
|
"eslint-plugin-svelte": "^3.0.0",
|
||||||
"globals": "^16.0.0",
|
"globals": "^16.0.0",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.3.3",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
|
"sass-embedded": "^1.93.3",
|
||||||
"svelte": "^5.0.0",
|
"svelte": "^5.0.0",
|
||||||
"svelte-check": "^4.0.0",
|
"svelte-check": "^4.0.0",
|
||||||
"svelte-dnd-action": "^0.9.65",
|
"svelte-dnd-action": "^0.9.65",
|
||||||
@@ -38,6 +39,12 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@thisux/sveltednd": "^0.0.20",
|
"@thisux/sveltednd": "^0.0.20",
|
||||||
|
"@tiptap/core": "^3.11.0",
|
||||||
|
"@tiptap/extension-highlight": "^3.11.0",
|
||||||
|
"@tiptap/extension-text-style": "^3.11.0",
|
||||||
|
"@tiptap/extensions": "^3.11.0",
|
||||||
|
"@tiptap/pm": "^3.11.0",
|
||||||
|
"@tiptap/starter-kit": "^3.11.0",
|
||||||
"dexie": "^4.2.1",
|
"dexie": "^4.2.1",
|
||||||
"lucide-svelte": "^0.545.0",
|
"lucide-svelte": "^0.545.0",
|
||||||
"svelte-splitpanes": "^8.0.9"
|
"svelte-splitpanes": "^8.0.9"
|
||||||
|
|||||||
@@ -15,13 +15,11 @@
|
|||||||
import PopUp from './PopUp.svelte';
|
import PopUp from './PopUp.svelte';
|
||||||
import type { PopupContent } from '../ts/types';
|
import type { PopupContent } from '../ts/types';
|
||||||
import KeyInput from './KeyInput.svelte';
|
import KeyInput from './KeyInput.svelte';
|
||||||
import { send_keyboard_input, show_blackscreen } from '../ts/api_handler';
|
import { send_keyboard_input, show_blackscreen, show_html } from '../ts/api_handler';
|
||||||
import { run_on_all_selected_displays } from '../ts/stores/displays';
|
import { run_on_all_selected_displays } from '../ts/stores/displays';
|
||||||
import { selected_display_ids } from '../ts/stores/select';
|
import { selected_display_ids } from '../ts/stores/select';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import TipTapInput from './TipTapInput.svelte';
|
||||||
let show_text_body: string = `<p>I've been working on this <strong>new feature</strong> for the past few days.
|
|
||||||
It's been quite <em>challenging</em> but I think I'm making good progress.</p>`;
|
|
||||||
|
|
||||||
let popup_content: PopupContent = $state({
|
let popup_content: PopupContent = $state({
|
||||||
open: false,
|
open: false,
|
||||||
@@ -50,28 +48,25 @@
|
|||||||
snippet: text_popup,
|
snippet: text_popup,
|
||||||
title: 'Text anzeigen',
|
title: 'Text anzeigen',
|
||||||
title_icon: TextAlignStart,
|
title_icon: TextAlignStart,
|
||||||
closable: true
|
closable: true,
|
||||||
|
window_class: 'size-full'
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
show_text_popup();
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#snippet send_keys_popup()}
|
{#snippet send_keys_popup()}
|
||||||
|
<div class="overflow-hidden flex flex-col gap-2">
|
||||||
<div>
|
<div>
|
||||||
<KeyInput />
|
<KeyInput />
|
||||||
</div>
|
</div>
|
||||||
<div class="flex flex-row justify-end gap-2">
|
<div class="flex flex-row justify-end gap-2">
|
||||||
<Button className="px-4 font-bold" click_function={popup_close_function}>Fertig</Button>
|
<Button className="px-4 font-bold" click_function={popup_close_function}>Fertig</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
|
|
||||||
{#snippet text_popup()}
|
{#snippet text_popup()}
|
||||||
<!-- <div class="flex flex-row justify-end gap-2">
|
<TipTapInput />
|
||||||
<Button className="px-4 font-bold" click_function={popup_close_function}>Fertig</Button>
|
|
||||||
</div> -->
|
|
||||||
{/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">
|
||||||
@@ -159,7 +154,7 @@
|
|||||||
content={popup_content}
|
content={popup_content}
|
||||||
close_function={popup_close_function}
|
close_function={popup_close_function}
|
||||||
className="rounded-b-2xl"
|
className="rounded-b-2xl"
|
||||||
snippet_container_class="overflow-hidden"
|
snippet_container_class="size-full"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -181,7 +181,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<div class="flex flex-row gap-1">
|
<div class="flex flex-row gap-1">
|
||||||
<button
|
<button
|
||||||
class="gap-2 min-w-40 px-4 rounded-xl cursor-pointer duration-200 transition-colors {get_selectable_color_classes(
|
class="min-w-40 px-4 rounded-xl cursor-pointer duration-200 transition-colors {get_selectable_color_classes(
|
||||||
all_selected($displays, $selected_display_ids),
|
all_selected($displays, $selected_display_ids),
|
||||||
{
|
{
|
||||||
bg: true,
|
bg: true,
|
||||||
|
|||||||
@@ -5,7 +5,12 @@
|
|||||||
import type { PopupContent } from '../ts/types';
|
import type { PopupContent } from '../ts/types';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
|
|
||||||
let { content, close_function, className = '', snippet_container_class = '' } = $props<{
|
let {
|
||||||
|
content,
|
||||||
|
close_function,
|
||||||
|
className = '',
|
||||||
|
snippet_container_class = ''
|
||||||
|
} = $props<{
|
||||||
content: PopupContent;
|
content: PopupContent;
|
||||||
close_function: () => void;
|
close_function: () => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
@@ -40,13 +45,16 @@
|
|||||||
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
||||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||||
<div
|
<div
|
||||||
class="bg-stone-800 rounded-2xl min-w-[30%] max-w-[95%] max-h-[90%] flex flex-col shadow-2xl/60 overflow-hidden"
|
class="bg-stone-800 rounded-2xl min-w-[30%] max-w-[90%] max-h-[85%] flex flex-col shadow-2xl/60 overflow-hidden {content.window_class ??
|
||||||
|
''}"
|
||||||
onclick={(e) => e.stopPropagation()}
|
onclick={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
|
{#if content.title}
|
||||||
|
<div class="font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-8 w-full">
|
||||||
<div
|
<div
|
||||||
class="font-bold bg-stone-700 p-1.5 flex flex-row justify-between gap-8 w-full"
|
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 ??
|
||||||
|
''}"
|
||||||
>
|
>
|
||||||
<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}
|
{#if content.title_icon}
|
||||||
{@const Icon = content.title_icon}
|
{@const Icon = content.title_icon}
|
||||||
<Icon strokeWidth="2" class="flex-shrink-0" />
|
<Icon strokeWidth="2" class="flex-shrink-0" />
|
||||||
@@ -63,6 +71,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2 {snippet_container_class}">
|
<div class="p-2 min-h-0 overflow-auto flex flex-col gap-2 {snippet_container_class}">
|
||||||
{@render content.snippet(content.snippet_arg)}
|
{@render content.snippet(content.snippet_arg)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,255 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { onMount, onDestroy } from 'svelte';
|
||||||
|
import { Editor } from '@tiptap/core';
|
||||||
|
import { StarterKit } from '@tiptap/starter-kit';
|
||||||
|
import Placeholder from '@tiptap/extension-placeholder';
|
||||||
|
import {
|
||||||
|
Baseline,
|
||||||
|
Bold,
|
||||||
|
Code,
|
||||||
|
Highlighter,
|
||||||
|
Italic,
|
||||||
|
PaintBucket,
|
||||||
|
QrCode,
|
||||||
|
Strikethrough
|
||||||
|
} from 'lucide-svelte';
|
||||||
|
import Button from './Button.svelte';
|
||||||
|
import { run_on_all_selected_displays } from '../ts/stores/displays';
|
||||||
|
import { show_html } from '../ts/api_handler';
|
||||||
|
import { get_selectable_color_classes } from '../ts/stores/ui_behavior';
|
||||||
|
import { TextStyle } from '@tiptap/extension-text-style';
|
||||||
|
import { Color } from '@tiptap/extension-text-style';
|
||||||
|
import Highlight from '@tiptap/extension-highlight';
|
||||||
|
|
||||||
|
type TextEditOption = {
|
||||||
|
onclick: () => void;
|
||||||
|
is_selected: () => boolean;
|
||||||
|
icon: typeof Bold;
|
||||||
|
title: string;
|
||||||
|
color?: ColorElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ColorElement = {
|
||||||
|
color_string: () => string;
|
||||||
|
color_picker: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ColorState = {
|
||||||
|
el: HTMLInputElement | null;
|
||||||
|
value: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
let element = $state<HTMLElement>();
|
||||||
|
let editor_state = $state<{ editor: Editor | null }>({ editor: null });
|
||||||
|
|
||||||
|
let color_states: { text: ColorState; highlight: ColorState; bg: ColorState } = $state({
|
||||||
|
text: { el: null, value: '#b91c1c' },
|
||||||
|
highlight: { el: null, value: '#0c4a6e' },
|
||||||
|
bg: { el: null, value: '#1c1917' }
|
||||||
|
});
|
||||||
|
|
||||||
|
const text_edit_options: TextEditOption[][] = [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
onclick: () => editor_state.editor?.chain().focus().toggleBold().run(),
|
||||||
|
is_selected: () => editor_state.editor?.isActive('bold') ?? false,
|
||||||
|
title: 'Fett (STRG+B)',
|
||||||
|
icon: Bold
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onclick: () => editor_state.editor?.chain().focus().toggleItalic().run(),
|
||||||
|
is_selected: () => editor_state.editor?.isActive('italic') ?? false,
|
||||||
|
title: 'Kursiv (STRG+I)',
|
||||||
|
icon: Italic
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onclick: () => editor_state.editor?.chain().focus().toggleStrike().run(),
|
||||||
|
is_selected: () => editor_state.editor?.isActive('strike') ?? false,
|
||||||
|
title: 'Durchgestrichen',
|
||||||
|
icon: Strikethrough
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onclick: () => {},
|
||||||
|
is_selected: () => false,
|
||||||
|
title: 'QR-Code anfügen',
|
||||||
|
icon: QrCode
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
onclick: () => editor_state.editor?.chain().focus().setColor(color_states.text.value).run(),
|
||||||
|
is_selected: () =>
|
||||||
|
editor_state.editor?.isActive('textStyle', { color: color_states.text.value }) ?? false,
|
||||||
|
icon: Baseline,
|
||||||
|
title: 'Textfarbe',
|
||||||
|
color: get_color_element(color_states.text)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onclick: () =>
|
||||||
|
editor_state.editor
|
||||||
|
?.chain()
|
||||||
|
.focus()
|
||||||
|
.toggleHighlight({ color: color_states.highlight.value })
|
||||||
|
.run(),
|
||||||
|
is_selected: () =>
|
||||||
|
editor_state.editor?.isActive('highlight', { color: color_states.highlight.value }) ??
|
||||||
|
false,
|
||||||
|
icon: Highlighter,
|
||||||
|
title: 'Markierungsfarbe',
|
||||||
|
color: get_color_element(color_states.highlight)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
onclick: () => color_states.bg.el?.click(),
|
||||||
|
is_selected: () => false,
|
||||||
|
title: 'Hintergrundfarbe',
|
||||||
|
icon: PaintBucket
|
||||||
|
}
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
function get_color_element(color_state: ColorState) {
|
||||||
|
return {
|
||||||
|
color_string: () => color_state.value,
|
||||||
|
color_picker: () => color_state.el?.click()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_text() {
|
||||||
|
const html =
|
||||||
|
editor_state.editor?.getHTML() +
|
||||||
|
`<style>:root {--background-color: ${color_states.bg.value} !important;}
|
||||||
|
</style>`;
|
||||||
|
run_on_all_selected_displays(show_html, true, html);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
editor_state.editor = new Editor({
|
||||||
|
element: element,
|
||||||
|
extensions: [
|
||||||
|
StarterKit,
|
||||||
|
Placeholder.configure({
|
||||||
|
placeholder: 'Text hier eingeben ...'
|
||||||
|
}),
|
||||||
|
TextStyle,
|
||||||
|
Color,
|
||||||
|
Highlight.configure({
|
||||||
|
multicolor: true
|
||||||
|
})
|
||||||
|
],
|
||||||
|
content: '',
|
||||||
|
onTransaction: ({ editor }) => {
|
||||||
|
// Increment the state signal to force a re-render
|
||||||
|
editor_state = { editor };
|
||||||
|
},
|
||||||
|
autofocus: true
|
||||||
|
});
|
||||||
|
});
|
||||||
|
onDestroy(() => {
|
||||||
|
editor_state.editor?.destroy();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#each Object.values(color_states) as color_state}
|
||||||
|
<input type="color" bind:this={color_state.el} bind:value={color_state.value} class="hidden" />
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<div class="flex flex-row gap-2 size-full">
|
||||||
|
<div
|
||||||
|
class="rounded-xl size-full flex-shrink min-w-0 flex"
|
||||||
|
style="background-color: {color_states.bg.value};"
|
||||||
|
>
|
||||||
|
<div bind:this={element} class="size-full overflow-auto px-3 py-2"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-2 justify-between">
|
||||||
|
<div class="flex flex-col gap-2">
|
||||||
|
{#each text_edit_options as edit_row}
|
||||||
|
<div class="flex flex-row gap-1">
|
||||||
|
{#each edit_row as option}
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<button
|
||||||
|
title={option.title}
|
||||||
|
onclick={option.onclick}
|
||||||
|
class="p-1 {option.color
|
||||||
|
? 'rounded-l-xl'
|
||||||
|
: 'rounded-xl'} cursor-pointer duration-200 transition-colors {get_selectable_color_classes(
|
||||||
|
option.is_selected(),
|
||||||
|
{
|
||||||
|
bg: true,
|
||||||
|
hover: true,
|
||||||
|
active: true,
|
||||||
|
text: true
|
||||||
|
},
|
||||||
|
-100,
|
||||||
|
50
|
||||||
|
)}"
|
||||||
|
>
|
||||||
|
{#if option.icon}
|
||||||
|
{@const Icon = option.icon}
|
||||||
|
<Icon class="h-7 w-7" />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{#if option.color}
|
||||||
|
<button
|
||||||
|
onclick={option.color.color_picker}
|
||||||
|
title={option.title}
|
||||||
|
class="flex p-1 rounded-r-xl cursor-pointer duration-200 transition-colors justify-center items-center {get_selectable_color_classes(
|
||||||
|
option.is_selected(),
|
||||||
|
{
|
||||||
|
bg: true,
|
||||||
|
hover: true,
|
||||||
|
active: true,
|
||||||
|
text: true
|
||||||
|
},
|
||||||
|
-100,
|
||||||
|
50
|
||||||
|
)}"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="h-7 w-3 rounded-full"
|
||||||
|
style="background-color: {option.color.color_string()};"
|
||||||
|
></span>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button click_function={show_text} className="w-full font-bold">Text anzeigen</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:global(.tiptap) {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
--tw-outline-style: none;
|
||||||
|
outline-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.tiptap ul),
|
||||||
|
:global(.tiptap ol) {
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.tiptap ul) {
|
||||||
|
list-style: disc;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.tiptap ol) {
|
||||||
|
list-style: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.tiptap p) {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
:global(.tiptap p.is-editor-empty:first-child::before) {
|
||||||
|
content: attr(data-placeholder);
|
||||||
|
pointer-events: none;
|
||||||
|
color: oklch(44.4% 0.011 73.639);
|
||||||
|
float: left;
|
||||||
|
height: 0;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
@@ -25,6 +25,17 @@ export async function send_keyboard_input(ip: string, key: string): Promise<void
|
|||||||
await request_display(ip, '/keyboardInput', options);
|
await request_display(ip, '/keyboardInput', options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function show_html(ip: string, html: string) {
|
||||||
|
const options = {
|
||||||
|
method: 'PATCH',
|
||||||
|
headers: { 'content-type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
html: html
|
||||||
|
})
|
||||||
|
};
|
||||||
|
await request_display(ip, '/showHTML', options);
|
||||||
|
}
|
||||||
|
|
||||||
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
export async function get_file_data(ip: string, path: string): Promise<FolderElement[]> {
|
||||||
interface FileInfo {
|
interface FileInfo {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -136,7 +147,7 @@ async function request_control(api_route: string, options: { method: string, hea
|
|||||||
async function request(url: string, options: { method: string, headers?: Record<string, string>, body?: any }, supress_error_handling_http_codes: number[] = []): Promise<RequestResponse> {
|
async function request(url: string, options: { method: string, headers?: Record<string, string>, body?: any }, supress_error_handling_http_codes: number[] = []): Promise<RequestResponse> {
|
||||||
try {
|
try {
|
||||||
const cache_buster = `${url.includes('?') ? '&' : '?'}=${Date.now()}`;
|
const cache_buster = `${url.includes('?') ? '&' : '?'}=${Date.now()}`;
|
||||||
console.log(url + cache_buster)
|
console.log(url + cache_buster, options.body ?? null);
|
||||||
const response = await fetch(url + cache_buster, options);
|
const response = await fetch(url + cache_buster, options);
|
||||||
if (response.ok || supress_error_handling_http_codes.includes(response.status)) {
|
if (response.ok || supress_error_handling_http_codes.includes(response.status)) {
|
||||||
const contentType = response.headers.get("content-type") || "";
|
const contentType = response.headers.get("content-type") || "";
|
||||||
|
|||||||
@@ -73,9 +73,10 @@ export type PopupContent = {
|
|||||||
open: boolean;
|
open: boolean;
|
||||||
snippet: Snippet<[string]> | null;
|
snippet: Snippet<[string]> | null;
|
||||||
snippet_arg?: string;
|
snippet_arg?: string;
|
||||||
title: string;
|
title?: string;
|
||||||
title_class?: string;
|
title_class?: string;
|
||||||
title_icon?: typeof X | null;
|
title_icon?: typeof X | null;
|
||||||
|
window_class?: string;
|
||||||
closable?: boolean;
|
closable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-7
@@ -13,7 +13,8 @@ templ indexTemplate() {
|
|||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--background-color: black;
|
--background-color: black;
|
||||||
--foreground-color: oklch(92.3% 0.003 48.717)
|
--foreground-color: oklch(92.3% 0.003 48.717);
|
||||||
|
--font-size: 5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@@ -44,13 +45,19 @@ templ indexTemplate() {
|
|||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p,
|
||||||
font-size: 6rem;
|
li {
|
||||||
line-height: 1;
|
font-size: var(--font-size);
|
||||||
|
line-height: 1.2;
|
||||||
text-wrap: balance;
|
text-wrap: balance;
|
||||||
max-width: 90vw;
|
max-width: 90vw;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
display: block;
|
margin: 0 0 calc(var(--font-size) * 0.4) 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul,
|
||||||
|
ol {
|
||||||
|
padding-left: calc(var(--font-size)*1.5);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
@@ -89,14 +96,16 @@ templ imageTemplate(path string) {
|
|||||||
|
|
||||||
templ deviceInfoTemplate(ip string, mac string, showQR bool) {
|
templ deviceInfoTemplate(ip string, mac string, showQR bool) {
|
||||||
<div style="width: 100vw; height: 100vh; display: flex; flex-direction: row; justify-content: space-between;">
|
<div style="width: 100vw; height: 100vh; display: flex; flex-direction: row; justify-content: space-between;">
|
||||||
<div style="display: flex; flex-direction: column; gap: 1rem; justify-content: end; padding: 2rem; font-size: 4rem;">
|
<div
|
||||||
|
style="display: flex; flex-direction: column; gap: 1rem; justify-content: end; padding: 2rem; font-size: 4rem;">
|
||||||
{ ip }
|
{ ip }
|
||||||
<span style="text-transform: uppercase;">{ mac }</span>
|
<span style="text-transform: uppercase;">{ mac }</span>
|
||||||
</div>
|
</div>
|
||||||
if showQR {
|
if showQR {
|
||||||
<div style="display: flex; justify-content: end; align-items: end; padding: 2rem;">
|
<div style="display: flex; justify-content: end; align-items: end; padding: 2rem;">
|
||||||
<div style="padding: 1rem; background-color: var(--foreground-color); border-radius: 1rem;">
|
<div style="padding: 1rem; background-color: var(--foreground-color); border-radius: 1rem;">
|
||||||
<img style="height: 30vh; width: auto; image-rendering: pixelated; image-rendering: crisp-edges;" src={"/qr?data=http://" + ip + ":8080" } alt="QR-Code" />
|
<img style="height: 30vh; width: auto; image-rendering: pixelated; image-rendering: crisp-edges;"
|
||||||
|
src={ "/qr?data=http://" + ip + ":8080" } alt="QR-Code" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user