From a5e60b54868253d9c6d5321e411235f139e062ee Mon Sep 17 00:00:00 2001 From: JCEEE <0xjceee@proton.me> Date: Tue, 8 Sep 2026 09:42:58 +0100 Subject: [PATCH] add new flag to disable some future features and make some updates to chat ux --- frontend/src/lib/components/Chat.svelte | 44 ++++++++-- frontend/src/lib/server/migrate.ts | 2 +- frontend/src/routes/+page.svelte | 3 +- .../[fam]/[username]/rewards/+page.svelte | 85 +++++++++++++++---- frontend/src/routes/admin/+page.svelte | 19 +++++ 5 files changed, 128 insertions(+), 25 deletions(-) diff --git a/frontend/src/lib/components/Chat.svelte b/frontend/src/lib/components/Chat.svelte index 53996da..f3d5ac8 100644 --- a/frontend/src/lib/components/Chat.svelte +++ b/frontend/src/lib/components/Chat.svelte @@ -39,6 +39,19 @@ } }); + // Close the panel with Escape while it's open. + $effect(() => { + if (!chatStore.open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + e.preventDefault(); + onClose(); + } + }; + window.addEventListener('keydown', onKey); + return () => window.removeEventListener('keydown', onKey); + }); + async function send() { const text = draft.trim(); if (!text || sending) return; @@ -82,18 +95,27 @@ draft = (draft ? draft + ' ' : '') + '@' + name + ' '; } - // Render content, wrapping @mentions in a styled token. + // Render content, wrapping @mentions in a styled token and https:// URLs in + // clickable links (opened in a new window). function renderContent(text: string) { - const segs: { text: string; mention: boolean }[] = []; - const re = /(@[A-Za-z0-9_.-]+)/g; + const segs: { text: string; mention: boolean; url: string | null }[] = []; + const re = /(@[A-Za-z0-9_.-]+|https?:\/\/[^\s]+)/g; let last = 0; let m: RegExpExecArray | null; while ((m = re.exec(text)) !== null) { - if (m.index > last) segs.push({ text: text.slice(last, m.index), mention: false }); - segs.push({ text: m[1], mention: true }); + if (m.index > last) segs.push({ text: text.slice(last, m.index), mention: false, url: null }); + const tok = m[1]; + if (tok.startsWith('@')) { + segs.push({ text: tok, mention: true, url: null }); + } else { + const url = tok.replace(/[.,;:!?]+$/, ''); + if (url) segs.push({ text: url, mention: false, url }); + const rest = tok.slice(url.length); + if (rest) segs.push({ text: rest, mention: false, url: null }); + } last = m.index + m[0].length; } - if (last < text.length) segs.push({ text: text.slice(last), mention: false }); + if (last < text.length) segs.push({ text: text.slice(last), mention: false, url: null }); return segs; } @@ -132,6 +154,8 @@ + {:else if seg.url} + {seg.url} {:else} {seg.text} {/if} @@ -206,7 +230,8 @@ display: flex; align-items: center; justify-content: space-between; - padding: 0.85rem 1.25rem; + height: 52px; + padding: 0 1.25rem; border-bottom: 1px solid #e5e7eb; background: #4338ca; color: #fff; @@ -309,6 +334,11 @@ font-size: 0.85rem; cursor: pointer; } + .msg-link { + color: #6366f1; + text-decoration: underline; + word-break: break-all; + } .chat-typing { min-height: 1.5rem; padding: 0 1.25rem; diff --git a/frontend/src/lib/server/migrate.ts b/frontend/src/lib/server/migrate.ts index f185920..bec69f1 100644 --- a/frontend/src/lib/server/migrate.ts +++ b/frontend/src/lib/server/migrate.ts @@ -356,7 +356,7 @@ async function seedPlatform(): Promise { const created = await fetch(`${PB_ENDPOINT}/api/collections/platform/records`, { method: 'POST', headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${t}` }, - body: JSON.stringify({ label: 'global', flags: { debug: false } }) + body: JSON.stringify({ label: 'global', flags: { debug: false, rewardsTargets: false } }) }); const c = await created.json(); if (!created.ok) throw new Error(`Seed platform failed: ${JSON.stringify(c)}`); diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index 76d6c75..e846220 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,5 +1,4 @@