diff --git a/src/lib/components/MessageEditor.svelte b/src/lib/components/MessageEditor.svelte new file mode 100644 index 0000000..bba62cb --- /dev/null +++ b/src/lib/components/MessageEditor.svelte @@ -0,0 +1,116 @@ + + +
+ +
+ + {#if uploadError} + {uploadError} + {/if} +
+ +
diff --git a/src/lib/components/NewDiscussionModal.svelte b/src/lib/components/NewDiscussionModal.svelte index 73b3993..3537660 100644 --- a/src/lib/components/NewDiscussionModal.svelte +++ b/src/lib/components/NewDiscussionModal.svelte @@ -9,18 +9,14 @@ removeLabel, publishDraft, } from "$lib/draft.svelte"; - import { LABELS, BLOSSOM_URL } from "$lib/config"; + import { LABELS } from "$lib/config"; import { groupStore } from "$lib/group.svelte"; - import { uploadImage } from "$lib/blossom"; + import MessageEditor from "$lib/components/MessageEditor.svelte"; let labelInput = $state(""); let labelInputEl = $state(null); let suggestOpen = $state(false); let titleEl = $state(null); - let contentEl = $state(null); - let fileInputEl = $state(null); - let uploading = $state(false); - let uploadError = $state(null); const available = $derived( LABELS.filter((l) => !draftState.labels.includes(l)), @@ -48,9 +44,7 @@ tick().then(() => titleEl?.focus()); } else { // Modal stays mounted in the layout — reset transient local state so a - // hung "Uploading…" or stale error doesn't carry over to the next open. - uploading = false; - uploadError = null; + // stale label input doesn't carry over to the next open. labelInput = ""; suggestOpen = false; } @@ -106,46 +100,6 @@ }, 150); } - async function onUploadClick() { - fileInputEl?.click(); - } - - async function onFileChange(e: Event) { - const input = e.target as HTMLInputElement; - const file = input.files?.[0]; - if (!file) return; - console.log("[upload] picked file:", file.name, file.size, file.type); - uploadError = null; - uploading = true; - try { - const blob = await uploadImage(file); - const ta = contentEl; - if (ta) { - const start = ta.selectionStart; - const end = ta.selectionEnd; - const before = draftState.content.slice(0, start); - const after = draftState.content.slice(end); - const sep = before.length > 0 && !before.endsWith("\n") ? "\n" : ""; - const insertion = sep + blob.url + "\n"; - draftState.content = before + insertion + after; - await tick(); - ta.focus(); - const pos = (before + insertion).length; - ta.setSelectionRange(pos, pos); - } else { - draftState.content = - (draftState.content ? draftState.content + "\n" : "") + - blob.url + - "\n"; - } - } catch (err) { - uploadError = err instanceof Error ? err.message : "Upload failed"; - } finally { - uploading = false; - input.value = ""; - } - } - async function onPublish() { const res = await publishDraft(); if (res.ok && res.threadId) { @@ -309,53 +263,12 @@ {/if} -
- -
- - {#if uploadError} - {uploadError} - {/if} -
- -
+ {#if draftState.publishError}
{/if} - + rows={4} + placeholder="Write a reply..." + />