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 @@