From 5694a9ec73be858bf87355625fc9322b52841c59 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 10:58:36 +0200 Subject: [PATCH 01/11] Nightly: Containerbreite auf mindestens 90% des Monitors erweitert (data-build=nightly) --- web/src/App.tsx | 5 +++++ web/src/styles.css | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/web/src/App.tsx b/web/src/App.tsx index 17bc640..a4b9c86 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -89,6 +89,11 @@ export default function App() { // Theme anwenden/persistieren useEffect(() => { document.body.setAttribute('data-theme', theme); + if (import.meta.env.VITE_BUILD_CHANNEL === 'nightly') { + document.body.setAttribute('data-build', 'nightly'); + } else { + document.body.removeAttribute('data-build'); + } localStorage.setItem('theme', theme); }, [theme]); diff --git a/web/src/styles.css b/web/src/styles.css index 928b377..dd346bd 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -303,6 +303,12 @@ body { .container { width: 90vw; max-width: 1800px; margin: 0 auto; padding: 28px; } +/* Nightly Build: volle Breite (mind. 90% der Anzeige), kein max-width-Limit */ +[data-build="nightly"] .container { + width: 90vw; + max-width: none; +} + /* Neuer Header-Style basierend auf Google Stitch Design */ header { display: flex; From 6bf692ade5ba09f39658a0262a128a49f02b186c Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 13:54:38 +0200 Subject: [PATCH 02/11] =?UTF-8?q?Nightly:=20CHAOS-Button=20hinzugef=C3=BCg?= =?UTF-8?q?t=20-=20spielt=20zuf=C3=A4llige=20Sounds=20alle=202-6=20Minuten?= =?UTF-8?q?=20ab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 75 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/web/src/App.tsx b/web/src/App.tsx index a4b9c86..69fb448 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -27,6 +27,8 @@ export default function App() { const [clock, setClock] = useState(() => new Intl.DateTimeFormat('de-DE', { hour: '2-digit', minute: '2-digit', hour12: false, timeZone: 'Europe/Berlin' }).format(new Date())); const [totalPlays, setTotalPlays] = useState(0); const [mediaUrl, setMediaUrl] = useState(''); + const [chaosMode, setChaosMode] = useState(false); + const chaosIntervalRef = useRef(null); useEffect(() => { (async () => { @@ -165,6 +167,69 @@ export default function App() { } } + // CHAOS Mode Funktionen + const startChaosMode = async () => { + if (!selected || !sounds.length) return; + + const playRandomSound = async () => { + const randomSound = sounds[Math.floor(Math.random() * sounds.length)]; + const [guildId, channelId] = selected.split(':'); + try { + await playSound(randomSound.name, guildId, channelId, volume, randomSound.relativePath); + } catch (e: any) { + console.error('Chaos sound play failed:', e); + } + }; + + // Sofort ersten Sound abspielen + await playRandomSound(); + + // Interval für weitere zufällige Sounds (2-6 Minuten) + const interval = setInterval(async () => { + if (chaosMode) { + await playRandomSound(); + } + }, Math.random() * (6 - 2) * 60 * 1000 + 2 * 60 * 1000); // 2-6 Minuten + + chaosIntervalRef.current = interval; + }; + + const stopChaosMode = async () => { + if (chaosIntervalRef.current) { + clearInterval(chaosIntervalRef.current); + chaosIntervalRef.current = null; + } + + // Alle Sounds stoppen (wie Panic Button) + if (selected) { + const [guildId] = selected.split(':'); + try { + await fetch(`/api/stop?guildId=${encodeURIComponent(guildId)}`, { method: 'POST' }); + } catch (e: any) { + console.error('Chaos stop failed:', e); + } + } + }; + + const toggleChaosMode = async () => { + if (chaosMode) { + setChaosMode(false); + await stopChaosMode(); + } else { + setChaosMode(true); + await startChaosMode(); + } + }; + + // Cleanup bei Komponenten-Unmount + useEffect(() => { + return () => { + if (chaosIntervalRef.current) { + clearInterval(chaosIntervalRef.current); + } + }; + }, []); + return (
@@ -204,6 +269,16 @@ export default function App() { +
From d56c4dc0ed7baee3adb3e29326283c8e6201eafd Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 14:52:27 +0200 Subject: [PATCH 03/11] =?UTF-8?q?Nightly:=20CHAOS-Button=20Text=20ge=C3=A4?= =?UTF-8?q?ndert=20und=20Regenbogen-Animation=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 20 ++++++++++---------- web/src/styles.css | 13 +++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 69fb448..4f92371 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -269,16 +269,16 @@ export default function App() { - + diff --git a/web/src/styles.css b/web/src/styles.css index dd346bd..72d18c6 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -309,6 +309,19 @@ body { max-width: none; } +/* CHAOS Button Regenbogen-Animation */ +.chaos-rainbow { + background: linear-gradient(45deg, #ff0000, #ff8000, #ffff00, #80ff00, #00ff00, #00ff80, #00ffff, #0080ff, #0000ff, #8000ff, #ff00ff, #ff0080); + background-size: 400% 400%; + animation: chaos-rainbow-animation 2s ease-in-out infinite; +} + +@keyframes chaos-rainbow-animation { + 0% { background-position: 0% 50%; } + 50% { background-position: 100% 50%; } + 100% { background-position: 0% 50%; } +} + /* Neuer Header-Style basierend auf Google Stitch Design */ header { display: flex; From ec71858345295074aec8845d00edf85a366b70eb Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 14:58:55 +0200 Subject: [PATCH 04/11] =?UTF-8?q?Nightly:=20CHAOS-Logik=20angepasst=20=20z?= =?UTF-8?q?uf=C3=A4llige=20Wiedergabe=20alle=2013=20Minuten=20via=20rekurs?= =?UTF-8?q?ivem=20setTimeout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 4f92371..f56774e 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -28,7 +28,7 @@ export default function App() { const [totalPlays, setTotalPlays] = useState(0); const [mediaUrl, setMediaUrl] = useState(''); const [chaosMode, setChaosMode] = useState(false); - const chaosIntervalRef = useRef(null); + const chaosTimeoutRef = useRef(null); useEffect(() => { (async () => { @@ -167,12 +167,14 @@ export default function App() { } } - // CHAOS Mode Funktionen + // CHAOS Mode Funktionen (zufällige Wiedergabe alle 1-3 Minuten) const startChaosMode = async () => { if (!selected || !sounds.length) return; - + const playRandomSound = async () => { - const randomSound = sounds[Math.floor(Math.random() * sounds.length)]; + const pool = sounds; + if (!pool.length || !selected) return; + const randomSound = pool[Math.floor(Math.random() * pool.length)]; const [guildId, channelId] = selected.split(':'); try { await playSound(randomSound.name, guildId, channelId, volume, randomSound.relativePath); @@ -181,23 +183,22 @@ export default function App() { } }; - // Sofort ersten Sound abspielen - await playRandomSound(); + const scheduleNextPlay = async () => { + if (!chaosMode) return; + await playRandomSound(); + const delay = 60_000 + Math.floor(Math.random() * 120_000); // 1-3 Minuten + chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, delay); + }; - // Interval für weitere zufällige Sounds (2-6 Minuten) - const interval = setInterval(async () => { - if (chaosMode) { - await playRandomSound(); - } - }, Math.random() * (6 - 2) * 60 * 1000 + 2 * 60 * 1000); // 2-6 Minuten - - chaosIntervalRef.current = interval; + // ersten Start zufällig zwischen 1-3 Minuten planen + const firstDelay = 60_000 + Math.floor(Math.random() * 120_000); + chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, firstDelay); }; const stopChaosMode = async () => { - if (chaosIntervalRef.current) { - clearInterval(chaosIntervalRef.current); - chaosIntervalRef.current = null; + if (chaosTimeoutRef.current) { + clearTimeout(chaosTimeoutRef.current); + chaosTimeoutRef.current = null; } // Alle Sounds stoppen (wie Panic Button) @@ -224,8 +225,8 @@ export default function App() { // Cleanup bei Komponenten-Unmount useEffect(() => { return () => { - if (chaosIntervalRef.current) { - clearInterval(chaosIntervalRef.current); + if (chaosTimeoutRef.current) { + clearTimeout(chaosTimeoutRef.current); } }; }, []); From 399ab0a14bc0bf364c69e4d6a7b20dcf260a2aa3 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:25:06 +0200 Subject: [PATCH 05/11] =?UTF-8?q?Nightly:=20Panic=20stoppt=20jetzt=20auch?= =?UTF-8?q?=20CHAOS=20und=20setzt=20Mode=20zur=C3=BCck;=20CHAOS-Button=20z?= =?UTF-8?q?eigt=20immer=20'CHAOS'=20(aktiv=20mit=20Rainbow)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index f56774e..42e339a 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -270,7 +270,7 @@ export default function App() { - - + From 460c53c1d441d1e1354bb9ab0ed0e4e18641230d Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:28:32 +0200 Subject: [PATCH 06/11] =?UTF-8?q?Nightly:=20CHAOS=20fixt=20=20sofort=20ers?= =?UTF-8?q?ter=20Sound,=20stabile=20Wiederholung=20=C3=BCber=20Ref=20(13?= =?UTF-8?q?=20Min),=20sauberes=20Stoppen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 42e339a..9625e24 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -29,6 +29,8 @@ export default function App() { const [mediaUrl, setMediaUrl] = useState(''); const [chaosMode, setChaosMode] = useState(false); const chaosTimeoutRef = useRef(null); + const chaosModeRef = useRef(false); + useEffect(() => { chaosModeRef.current = chaosMode; }, [chaosMode]); useEffect(() => { (async () => { @@ -184,13 +186,15 @@ export default function App() { }; const scheduleNextPlay = async () => { - if (!chaosMode) return; + if (!chaosModeRef.current) return; await playRandomSound(); const delay = 60_000 + Math.floor(Math.random() * 120_000); // 1-3 Minuten chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, delay); }; - // ersten Start zufällig zwischen 1-3 Minuten planen + // Sofort ersten Sound abspielen + await playRandomSound(); + // Nächsten zufällig in 1-3 Minuten planen const firstDelay = 60_000 + Math.floor(Math.random() * 120_000); chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, firstDelay); }; From 8488d9da0af07dad564cdf8d631d205aa640c881 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:37:47 +0200 Subject: [PATCH 07/11] Nightly: CHAOS-Intervall angepasst auf 60120 Sekunden --- web/src/App.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 9625e24..ffd11ef 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -188,14 +188,14 @@ export default function App() { const scheduleNextPlay = async () => { if (!chaosModeRef.current) return; await playRandomSound(); - const delay = 60_000 + Math.floor(Math.random() * 120_000); // 1-3 Minuten + const delay = 60_000 + Math.floor(Math.random() * 60_000); // 60-120 Sekunden chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, delay); }; // Sofort ersten Sound abspielen await playRandomSound(); // Nächsten zufällig in 1-3 Minuten planen - const firstDelay = 60_000 + Math.floor(Math.random() * 120_000); + const firstDelay = 60_000 + Math.floor(Math.random() * 60_000); chaosTimeoutRef.current = window.setTimeout(scheduleNextPlay, firstDelay); }; From fa915fb52206fdd6356688be68c1a8e655870626 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:40:25 +0200 Subject: [PATCH 08/11] =?UTF-8?q?Nightly:=20Schriftst=C3=A4rke=20der=20Sou?= =?UTF-8?q?ndbutton-Texte=20auf=20501=20angehoben=20(nur=20Label,=20keine?= =?UTF-8?q?=20Icons)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/styles.css | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/src/styles.css b/web/src/styles.css index 72d18c6..033a922 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -575,6 +575,8 @@ header p { padding: 12px 16px; /* gleichmäßiges Padding links/rechts */ justify-content: center; /* Text zentrieren */ } +/* Soundbutton-Text minimal kräftiger als 500 */ +.sounds-flow .sound-btn > span { font-weight: 501 !important; } .sound-wrap { position: relative; display: block; } .sound-wrap.row .sound { width: 100%; } .row-check { width: 18px; height: 18px; accent-color: #60a5fa; } From 2e1342a58e17a23a5875ce68a519980791e975f2 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:43:57 +0200 Subject: [PATCH 09/11] =?UTF-8?q?Nightly:=20URL-Input-Text=20l=C3=A4uft=20?= =?UTF-8?q?nicht=20mehr=20=C3=BCber=20Download-Button=20(padding-right=20+?= =?UTF-8?q?=20ellipsis)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/styles.css | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/web/src/styles.css b/web/src/styles.css index 033a922..940fe0a 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -577,6 +577,14 @@ header p { } /* Soundbutton-Text minimal kräftiger als 500 */ .sounds-flow .sound-btn > span { font-weight: 501 !important; } + +/* URL Input mit Download Button - Text soll nicht über Button laufen */ +.input-field.pl-10.with-left-icon { + padding-right: 100px !important; /* Platz für Download Button */ + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; +} .sound-wrap { position: relative; display: block; } .sound-wrap.row .sound { width: 100%; } .row-check { width: 18px; height: 18px; accent-color: #60a5fa; } From d88592433396d8c57df03b3a590aaa4844130a66 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:45:10 +0200 Subject: [PATCH 10/11] =?UTF-8?q?Nightly:=20Enter-Taste=20f=C3=BCr=20Admin?= =?UTF-8?q?-Login=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index ffd11ef..2a9d1e2 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -357,7 +357,24 @@ export default function App() { {!isAdmin ? ( <>
- setAdminPwd(e.target.value)} /> + setAdminPwd(e.target.value)} + onKeyDown={async (e)=>{ + if(e.key === 'Enter') { + const ok = await adminLogin(adminPwd); + if(ok) { + setIsAdmin(true); + setAdminPwd(''); + } else { + alert('Login fehlgeschlagen'); + } + } + }} + /> lock
From 778a19e28b7950d35c9f9d17745c4cbbf03de8f7 Mon Sep 17 00:00:00 2001 From: vibe-bot Date: Sat, 9 Aug 2025 15:46:12 +0200 Subject: [PATCH 11/11] =?UTF-8?q?Nightly:=20Fehler-=20und=20Erfolgsmeldung?= =?UTF-8?q?en=20=C3=BCber=20die=20Filter/Tabs=20verschoben?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/src/App.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 2a9d1e2..7daedf3 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -418,6 +418,9 @@ export default function App() { + {error &&
{error}
} + {info &&
{info}
} +
@@ -440,9 +443,6 @@ export default function App() {
- {error &&
{error}
} - {info &&
{info}
} -
{(activeFolder === '__favs__' ? filtered.filter((s) => !!favs[s.relativePath ?? s.fileName]) : filtered).map((s) => { const key = `${s.relativePath ?? s.fileName}`;