From 74d84cb2f22600b6246343e9ea606cf0db7517f0 Mon Sep 17 00:00:00 2001
From: polwex <polwex@sortug.com>
Date: Wed, 19 Nov 2025 05:47:30 +0700
Subject: Big GUI improvements on Nostr rendering and fetching

---
 gui/src/components/composer/Composer.tsx | 77 +++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 25 deletions(-)

(limited to 'gui/src/components/composer/Composer.tsx')

diff --git a/gui/src/components/composer/Composer.tsx b/gui/src/components/composer/Composer.tsx
index 8b7e343..1fb0c6c 100644
--- a/gui/src/components/composer/Composer.tsx
+++ b/gui/src/components/composer/Composer.tsx
@@ -1,10 +1,13 @@
+import "@/styles/Composer.css";
 import useLocalState from "@/state/state";
+import spinner from "@/assets/triangles.svg";
 import Sigil from "@/components/Sigil";
 import { useState, useEffect, useRef, type FormEvent } from "react";
 import Snippets, { ReplySnippet } from "./Snippets";
 import toast from "react-hot-toast";
 import Icon from "@/components/Icon";
 import { wait } from "@/logic/utils";
+import type { UserType } from "@/types/nostrill";
 
 function Composer({ isAnon }: { isAnon?: boolean }) {
   const { api, composerData, addNotification, setComposerData } = useLocalState(
@@ -15,12 +18,12 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
       setComposerData: s.setComposerData,
     }),
   );
-  const our = api!.airlock.our!;
   const [input, setInput] = useState("");
   const [isExpanded, setIsExpanded] = useState(false);
   const [isLoading, setLoading] = useState(false);
   const inputRef = useRef<HTMLInputElement>(null);
 
+  console.log({ composerData });
   useEffect(() => {
     if (composerData) {
       setIsExpanded(true);
@@ -29,8 +32,6 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
         composerData.post &&
         "trill" in composerData.post
       ) {
-        const author = composerData.post.trill.author;
-        setInput(`${author} `);
       }
       // Auto-focus input when composer opens
       setTimeout(() => {
@@ -38,27 +39,46 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
       }, 100); // Small delay to ensure the composer is rendered
     }
   }, [composerData]);
+  async function addSimple() {
+    if (!api) return; // TODOhandle error
+    return await api.addPost(input);
+  }
+  async function addComplex() {
+    if (!api) return; // TODOhandle error
+    if (!composerData) return;
+    const host: UserType =
+      "trill" in composerData.post
+        ? { urbit: composerData.post.trill.author }
+        : "nostr" in composerData.post
+          ? { nostr: composerData.post.nostr.pubkey }
+          : { urbit: api.airlock.our! };
+    const id =
+      "trill" in composerData.post
+        ? composerData.post.trill.id
+        : "nostr" in composerData.post
+          ? composerData.post.nostr.eventId
+          : "";
+    const thread =
+      "trill" in composerData.post
+        ? composerData.post.trill.thread || composerData.post.trill.id
+        : "nostr" in composerData.post
+          ? composerData.post.nostr.eventId
+          : "";
+
+    const res =
+      composerData.type === "reply"
+        ? api.addReply(input, host, id, thread)
+        : composerData?.type === "quote"
+          ? api.addQuote(input, host, id)
+          : wait(500);
+    return await res;
+  }
   async function poast(e: FormEvent<HTMLFormElement>) {
     e.preventDefault();
-    // TODO
+    if (!api) return; // TODOhandle error
+    const our = api.airlock.our!;
     setLoading(true);
-
-    const res =
-      composerData?.type === "reply" && "trill" in composerData.post
-        ? api!.addReply(
-            input,
-            composerData.post.trill.host,
-            composerData.post.trill.id,
-            composerData.post.trill.thread || composerData.post.trill.id,
-          )
-        : composerData?.type === "quote" && "trill" in composerData.post
-          ? api!.addQuote(input, {
-              ship: composerData.post.trill.host,
-              id: composerData.post.trill.id,
-            })
-          : !composerData
-            ? api!.addPost(input)
-            : wait(500);
+    const res = !composerData ? addSimple() : addComplex();
     const ares = await res;
     if (ares) {
       // // Check for mentions in the post (ship names starting with ~)
@@ -95,6 +115,7 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
       setInput("");
       setComposerData(null); // Clear composer data after successful post
       toast.success("post sent");
+      setLoading(false);
       setIsExpanded(false);
     }
   }
@@ -121,7 +142,7 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
       onSubmit={poast}
     >
       <div className="sigil avatar">
-        <Sigil patp={our} size={46} />
+        <Sigil patp={api?.airlock.our || ""} size={46} />
       </div>
 
       <div className="composer-content">
@@ -172,9 +193,15 @@ function Composer({ isAnon }: { isAnon?: boolean }) {
             onFocus={() => setIsExpanded(true)}
             placeholder={placeHolder}
           />
-          <button type="submit" disabled={!input.trim()} className="post-btn">
-            Post
-          </button>
+          {isLoading ? (
+            <div className="loading-container">
+              <img src={spinner} />
+            </div>
+          ) : (
+            <button type="submit" disabled={!input.trim()} className="post-btn">
+              Post
+            </button>
+          )}
         </div>
 
         {/* Quote snippets appear below input */}
-- 
cgit v1.2.3

