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..."
+ />