diff --git a/apps/web/src/components/navbar.tsx b/apps/web/src/components/navbar.tsx index 5bb9830..53fb740 100644 --- a/apps/web/src/components/navbar.tsx +++ b/apps/web/src/components/navbar.tsx @@ -96,7 +96,7 @@ export default function Navbar({ forMobile }: { forMobile: boolean }) { ) } - loading={} + loading={} /> )} diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx index d088a57..3ea2f1e 100644 --- a/packages/chat/src/components/message.tsx +++ b/packages/chat/src/components/message.tsx @@ -21,9 +21,7 @@ import { Card, cn, Separator, - Tooltip, - TooltipContent, - TooltipTrigger, + Skeleton, } from "@tensamin/ui"; import MessageContextMenu from "./messageContextMenu"; import Media from "./media"; @@ -44,13 +42,15 @@ function MessageComponent({ }; user: User | null; }) { - const actuallyFailed = message.failed && message.MessageState === "awaiting"; + const [decryptionFailed, setDecryptionFailed] = useState(false); + const actuallyFailed = + (message.failed && message.MessageState === "awaiting") || decryptionFailed; // Fade-in const [hasFadedIn, setHasFadedIn] = useState(false); const opacityClass = !hasFadedIn ? "opacity-0" - : actuallyFailed || message.MessageState === "awaiting" + : message.MessageState === "awaiting" ? "opacity-50" : "opacity-100"; useEffect(() => { @@ -63,19 +63,6 @@ function MessageComponent({ }; }, []); - // Check if message is a url - const [isValidURL, setIsValidURL] = useState(false); - useEffect(() => { - try { - if (message.Content.split(" ").length > 1) throw new Error(); - - new URL(message.Content); - setIsValidURL(true); - } catch { - setIsValidURL(false); - } - }, [message.Content]); - // Message states const { load } = useStorage(); const { send } = useMTP(); @@ -141,109 +128,126 @@ function MessageComponent({ (err) => { toast("error", "Failed to decrypt message", String(err)); log(1, "chat", "red", err); + setDecryptionFailed(true); }, ); }, [chatSecret, message.Content]); + // Check if message is a url + const [isValidURL, setIsValidURL] = useState(false); + useEffect(() => { + if (!decryptedContent) return; + + try { + if (decryptedContent.split(" ").length > 1) throw new Error(); + + new URL(decryptedContent); + setIsValidURL(true); + } catch { + setIsValidURL(false); + } + }, [decryptedContent]); + return (
- {user && decryptedContent ? ( - -
+ {grouped ? ( +

+ {new Date(message.SendTime).toLocaleString([], { + hour: "2-digit", + minute: "2-digit", + })} +

+ ) : ( + + + + {user.Display.slice(0, 2).toUpperCase()} + + )} - > - <> - {grouped ? ( -

- {new Date(message.SendTime).toLocaleString([], { - hour: "2-digit", - minute: "2-digit", - })} -

- ) : ( - - - - {user.Display.slice(0, 2).toUpperCase()} - - - )} - {message.failed && message.MessageState === "awaiting" && ( - - -

Failed to send message

-
- } /> -
- )} -
- - {[0, 1, 2].map((item) => ( - - ))} - - - - - - {!grouped && ( -
-

{user.Display}

-

- {new Date(message.SendTime).toLocaleString([], { - hour: "2-digit", - minute: "2-digit", - })} -

-
- {message.MessageState === "read" ? ( - - ) : message.MessageState === "received" ? ( - - ) : message.MessageState === "sent" ? ( - - ) : message.MessageState === "sending" ? ( - - ) : null} -
+ ))} + + + + + + {!grouped && ( +
+

{user.Display}

+

+ {new Date(message.SendTime).toLocaleString([], { + hour: "2-digit", + minute: "2-digit", + })} +

+
+ {message.MessageState === "read" ? ( + + ) : message.MessageState === "received" ? ( + + ) : message.MessageState === "sent" ? ( + + ) : message.MessageState === "sending" ? ( + + ) : null} + {actuallyFailed && ( + + )}
- )} - {isValidURL ? ( - - ) : ( - - )} -
- -
- +
+ )} + + {decryptedContent ? ( + + {isValidURL ? ( + + ) : ( + + )} + + ) : decryptionFailed ? ( + + ) : ( + + )} +
+ +
) : ( - "Loading" + )} );