diff --git a/src/components/PageComponents/Messages/ChannelChat.tsx b/src/components/PageComponents/Messages/ChannelChat.tsx index 56ee39e9..cdbca329 100644 --- a/src/components/PageComponents/Messages/ChannelChat.tsx +++ b/src/components/PageComponents/Messages/ChannelChat.tsx @@ -51,7 +51,7 @@ export const ChannelChat = ({ if (!messages?.length) { return ( -
+
@@ -63,23 +63,25 @@ export const ChannelChat = ({ } return ( -
-
-
- {messages.map((message, index) => ( - 0 && messages[index - 1].from === message.from - } - sender={nodes.get(message.from)} - /> - ))} +
+
+
+ {messages.map((message, index) => { + return ( + 0 && messages[index - 1].from === message.from + } + /> + ); + })}
-
+
diff --git a/src/components/PageComponents/Messages/Message.tsx b/src/components/PageComponents/Messages/Message.tsx index 66268219..a6eb8f9a 100644 --- a/src/components/PageComponents/Messages/Message.tsx +++ b/src/components/PageComponents/Messages/Message.tsx @@ -1,10 +1,21 @@ -import type { MessageWithState } from "@app/core/stores/deviceStore.ts"; +import { + Tooltip, + TooltipArrow, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@app/components/UI/Tooltip"; +import { useAppStore } from "@app/core/stores/appStore"; +import { + type MessageWithState, + useDeviceStore, +} 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"; import { AlertCircle, CheckCircle2, CircleEllipsis } from "lucide-react"; import type { LucideIcon } from "lucide-react"; +import { useMemo } from "react"; const MESSAGE_STATES = { ACK: "ack", @@ -17,7 +28,7 @@ type MessageState = MessageWithState["state"]; interface MessageProps { lastMsgSameUser: boolean; message: MessageWithState; - sender?: Protobuf.Mesh.NodeInfo; + sender: Protobuf.Mesh.NodeInfo; } interface StatusTooltipProps { @@ -45,22 +56,20 @@ const STATUS_ICON_MAP: Record = { const getStatusText = (state: MessageState): string => STATUS_TEXT_MAP[state]; const StatusTooltip = ({ state, children }: StatusTooltipProps) => ( - - - {children} - - - {getStatusText(state)} - - - - - + + + {children} + + {getStatusText(state)} + + + + ); const StatusIcon = ({ state, className, ...otherProps }: StatusIconProps) => { @@ -88,7 +97,7 @@ const getMessageTextStyles = (state: MessageState) => { const isWaiting = state === MESSAGE_STATES.WAITING; return cn( - "pl-2 break-words overflow-hidden", + "break-words overflow-hidden", isAcknowledged ? "text-black dark:text-white" : "text-black dark:text-gray-400", @@ -96,8 +105,11 @@ const getMessageTextStyles = (state: MessageState) => { ); }; -const TimeDisplay = ({ date }: { date: Date }) => ( -
+const TimeDisplay = ({ + date, + className, +}: { date: Date; className?: string }) => ( +
{date.toLocaleDateString()} @@ -111,44 +123,46 @@ const TimeDisplay = ({ date }: { date: Date }) => ( ); export const Message = ({ lastMsgSameUser, message, sender }: MessageProps) => { + const { getDevices } = useDeviceStore(); + + const isDeviceUser = useMemo( + () => + getDevices() + .map((device) => device.nodes.get(device.hardware.myNodeNum)?.num) + .includes(message.from), + [getDevices, message.from], + ); + const messageUser = sender?.user; + const messageTextClass = getMessageTextStyles(message.state); - const isFailed = message.state === MESSAGE_STATES.ACK; - - const baseMessageWrapper = cn( - "flex items-center gap-2 w-full max-w-full pl-11", - !lastMsgSameUser && "flex-wrap flex-grow", - ); - - const containerClass = cn( - "w-full px-4 relative", - lastMsgSameUser ? "mt-1" : "mt-2", - !lastMsgSameUser && "pt-2", - ); return ( -
- {!lastMsgSameUser && ( -
-
- - - {sender?.user?.longName ?? "UNK"} - +
+
+
+ {!lastMsgSameUser ? ( +
+ +
+ + {messageUser?.longName} + +
+
+ ) : null} +
+ +
+
+ {message.data}
- +
- )} -
-
-
{message.data}
-
-
); diff --git a/src/components/PageComponents/Messages/MessageInput.tsx b/src/components/PageComponents/Messages/MessageInput.tsx index d1cbc5ee..e8b85357 100644 --- a/src/components/PageComponents/Messages/MessageInput.tsx +++ b/src/components/PageComponents/Messages/MessageInput.tsx @@ -32,7 +32,7 @@ export const MessageInput = ({ } = useDevice(); const myNodeNum = hardware.myNodeNum; const [localDraft, setLocalDraft] = useState(messageDraft); - const [messageBytes, setMessageBytes] = useState(maxBytes); + const [messageBytes, setMessageBytes] = useState(0); const debouncedSetMessageDraft = useMemo( () => debounce(setMessageDraft, 300), @@ -69,11 +69,12 @@ export const MessageInput = ({ const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; - const messageLength = newValue.length; - if (messageLength <= maxBytes) { + const byteLength = new Blob([newValue]).size; + + if (byteLength <= maxBytes) { setLocalDraft(newValue); debouncedSetMessageDraft(newValue); - setMessageBytes(maxBytes - messageLength); + setMessageBytes(byteLength); } }; @@ -89,6 +90,7 @@ export const MessageInput = ({ sendText(message); setLocalDraft(""); setMessageDraft(""); + setMessageBytes(0); }); }} > @@ -103,9 +105,10 @@ export const MessageInput = ({ onChange={handleInputChange} /> -
+
{messageBytes}/{maxBytes}
+ diff --git a/src/components/UI/Tooltip.tsx b/src/components/UI/Tooltip.tsx index bde4b344..2353418a 100644 --- a/src/components/UI/Tooltip.tsx +++ b/src/components/UI/Tooltip.tsx @@ -9,6 +9,7 @@ const Tooltip = ({ ...props }) => ; Tooltip.displayName = TooltipPrimitive.Tooltip.displayName; const TooltipTrigger = TooltipPrimitive.Trigger; +const TooltipArrow = TooltipPrimitive.Arrow; const TooltipContent = React.forwardRef< React.ElementRef, @@ -26,4 +27,10 @@ const TooltipContent = React.forwardRef< )); TooltipContent.displayName = TooltipPrimitive.Content.displayName; -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; +export { + Tooltip, + TooltipTrigger, + TooltipContent, + TooltipProvider, + TooltipArrow, +};