diff --git a/frontend/src/routes/admin/+page.svelte b/frontend/src/routes/admin/+page.svelte index 5b8453c..7bd1e14 100644 --- a/frontend/src/routes/admin/+page.svelte +++ b/frontend/src/routes/admin/+page.svelte @@ -136,13 +136,41 @@ } } - // In-site reply (plain text, sent via SMTP; only stored on successful send). + // In-site reply (Markdown-ish: textarea + toolbar; server renders sanitized HTML). let replyingId = $state(null); let replyText = $state(''); let replyBusy = $state(false); let replyErr = $state(''); + let replyTextarea = $state(null); function openReply(f) { replyingId = f.id; replyText = ''; replyErr = ''; } function cancelReply() { replyingId = null; replyText = ''; replyErr = ''; } + + // Wrap the current selection (e.g. **bold**), restoring focus + selection. + function mdWrap(token) { + const el = replyTextarea; + if (!el) return; + const s = el.selectionStart, e = el.selectionEnd; + const sel = replyText.slice(s, e) || 'text'; + replyText = replyText.slice(0, s) + token + sel + token + replyText.slice(e); + queueMicrotask(() => { + el.focus(); + el.selectionStart = s + token.length; + el.selectionEnd = s + token.length + sel.length; + }); + } + // Prefix each selected line (e.g. "- " or "## "). + function mdPrefix(prefix) { + const el = replyTextarea; + if (!el) return; + const s = el.selectionStart, e = el.selectionEnd; + const start = replyText.lastIndexOf('\n', s - 1) + 1; + let end = replyText.indexOf('\n', e); + if (end === -1) end = replyText.length; + const block = replyText.slice(start, end) || 'item'; + const prefixed = block.split('\n').map((ln) => prefix + ln).join('\n'); + replyText = replyText.slice(0, start) + prefixed + replyText.slice(end); + queueMicrotask(() => el.focus()); + } async function sendReply(f) { const msg = replyText.trim(); if (!msg || replyBusy) return; @@ -434,7 +462,12 @@ {#each f.replies as r (r.id)}
↪ Replied · {fwhen(r.sent_at)} -

{r.message}

+ {#if r.message_html} + +
{@html r.message_html}
+ {:else} +

{r.message}

+ {/if}
{/each} @@ -442,7 +475,12 @@ {#if replyingId === f.id}
- +
+ + + +
+ {#if replyErr}

{replyErr}

{/if}