From 87ddaad966e613877ef52c3ebc1cffc4ce8014a5 Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Mon, 3 Feb 2025 20:28:01 -0500 Subject: [PATCH] fix: styling updates, chat conversation moved to bottom of chat window. --- .../PageComponents/Messages/ChannelChat.tsx | 45 +++++++--- .../PageComponents/Messages/Message.tsx | 90 ++++++++++--------- 2 files changed, 83 insertions(+), 52 deletions(-) diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index fc7a60a1..46423237 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -6,6 +6,7 @@ import { Message } from "@components/PageComponents/Messages/Message.tsx"; import { MessageInput } from "@components/PageComponents/Messages/MessageInput.tsx"; import type { Types } from "@meshtastic/js"; import { InboxIcon } from "lucide-react"; +import { useCallback, useEffect, useRef } from "react"; import type { JSX } from "react"; export interface ChannelChatProps { @@ -27,24 +28,45 @@ export const ChannelChat = ({ to, }: ChannelChatProps): JSX.Element => { const { nodes } = useDevice(); + const messagesEndRef = useRef(null); + const scrollContainerRef = useRef(null); + + const scrollToBottom = useCallback(() => { + const scrollContainer = scrollContainerRef.current; + if (scrollContainer) { + const isNearBottom = + scrollContainer.scrollHeight - + scrollContainer.scrollTop - + scrollContainer.clientHeight < + 100; + + if (isNearBottom) { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + } + } + }, []); + + useEffect(() => { + scrollToBottom(); + }, [scrollToBottom]); if (!messages?.length) { return ( - <> -
+
+
-
+
- +
); } return ( - <> -
-
+
+
+
{messages.map((message, index) => ( ))} +
-
- -
- +
+ +
+
); }; diff --git a/src/components/PageComponents/Messages/Message.tsx b/src/components/PageComponents/Messages/Message.tsx index 53244080..3a96fd3b 100644 --- a/src/components/PageComponents/Messages/Message.tsx +++ b/src/components/PageComponents/Messages/Message.tsx @@ -1,4 +1,5 @@ import type { MessageWithState } from "@app/core/stores/deviceStore.ts"; +import { cn } from "@app/core/utils/cn"; import { Avatar } from "@components/UI/Avatar"; import type { Protobuf } from "@meshtastic/js"; import * as Tooltip from "@radix-ui/react-tooltip"; @@ -45,8 +46,14 @@ const StatusTooltip = ({ state, children }: StatusTooltipProps) => ( ); -const StatusIcon = ({ state }: { state: MessageWithState["state"] }) => { - const iconClass = "text-gray-500 dark:text-gray-400 w-4 h-4"; +const StatusIcon = ({ + state, + className, +}: { state: MessageWithState["state"]; className?: string }) => { + const iconClass = cn( + className, + "text-gray-500 dark:text-gray-400 w-4 h-4 flex-shrink-0", + ); const Icon = (() => { switch (state) { case "ack": @@ -57,7 +64,6 @@ const StatusIcon = ({ state }: { state: MessageWithState["state"] }) => { return AlertCircle; } })(); - return ( @@ -66,50 +72,52 @@ const StatusIcon = ({ state }: { state: MessageWithState["state"] }) => { }; export const Message = ({ lastMsgSameUser, message, sender }: MessageProps) => { - const messageTextClass = + const messageTextClass = cn( + "border-l-2 pl-4 break-words min-w-0", message.state === "ack" ? "text-gray-900 dark:text-white" - : "text-gray-500 dark:text-gray-400"; + : "text-gray-500 dark:text-gray-400", + lastMsgSameUser + ? "border-gray-600 dark:border-gray-700" + : "border-gray-200 dark:border-gray-600", + ); - if (lastMsgSameUser) { - return ( -
-
-
- {message.data} -
- -
-
- ); - } + const baseMessageWrapper = cn( + "ml-12 flex items-start gap-2 w-full max-w-full", + lastMsgSameUser ? "mt-1" : "mt-4", + !lastMsgSameUser && "flex-wrap flex-grow", + ); + + const containerClass = cn( + "px-4 relative", + lastMsgSameUser ? "mt-0" : "mt-2", + !lastMsgSameUser && "pt-2", + ); return ( -
-
- - - {sender?.user?.longName ?? "UNK"} - - - {message.rxTime.toLocaleDateString()} - - - {message.rxTime.toLocaleTimeString(undefined, { - hour: "2-digit", - minute: "2-digit", - })} - -
-
-
- {message.data} +
+ {!lastMsgSameUser && ( +
+ + + {sender?.user?.longName ?? "UNK"} + + + {message.rxTime.toLocaleDateString()} + + + {message.rxTime.toLocaleTimeString(undefined, { + hour: "2-digit", + minute: "2-digit", + })} + +
+ )} +
+
+
{message.data}
- +
);