2024-10-06 23:22:33 +02:00
|
|
|
import { Avatar } from '@/renderer/components/avatars/avatar';
|
2024-08-03 19:14:38 +02:00
|
|
|
import {
|
|
|
|
|
Tooltip,
|
|
|
|
|
TooltipContent,
|
|
|
|
|
TooltipTrigger,
|
2024-10-03 17:42:17 +02:00
|
|
|
} from '@/renderer/components/ui/tooltip';
|
2024-11-13 23:44:21 +01:00
|
|
|
import { formatDate, timeAgo } from '@/shared/lib/utils';
|
2024-08-03 19:14:38 +02:00
|
|
|
import { InView } from 'react-intersection-observer';
|
2024-10-03 17:42:17 +02:00
|
|
|
import { MessageReactionCreatePopover } from '@/renderer/components/messages/message-reaction-create-popover';
|
|
|
|
|
import { MessageDeleteButton } from '@/renderer/components/messages/message-delete-button';
|
|
|
|
|
import { NodeRenderer } from '@/renderer/editor/renderers/node';
|
2024-11-13 23:44:21 +01:00
|
|
|
import { MessageNode } from '@/shared/types/messages';
|
2024-10-03 17:42:17 +02:00
|
|
|
import { MessageReactions } from '@/renderer/components/messages/message-reactions';
|
2024-10-03 17:34:11 +02:00
|
|
|
import { useMutation } from '@/renderer/hooks/use-mutation';
|
2024-10-03 17:35:28 +02:00
|
|
|
import { useWorkspace } from '@/renderer/contexts/workspace';
|
2024-10-27 09:14:09 +01:00
|
|
|
import { MessagesSquare, Reply } from 'lucide-react';
|
2024-11-12 23:00:22 +01:00
|
|
|
import { useConversation } from '@/renderer/contexts/conversation';
|
2024-11-14 17:11:53 +01:00
|
|
|
import { useRadar } from '@/renderer/contexts/radar';
|
2024-08-03 19:14:38 +02:00
|
|
|
|
|
|
|
|
interface MessageProps {
|
2024-08-22 20:17:36 +02:00
|
|
|
message: MessageNode;
|
2024-11-01 20:01:20 +01:00
|
|
|
previousMessage?: MessageNode | null;
|
2024-08-03 19:14:38 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-15 16:29:47 +02:00
|
|
|
const shouldDisplayUserInfo = (
|
|
|
|
|
message: MessageNode,
|
2024-11-07 09:15:00 +01:00
|
|
|
previousMessage?: MessageNode | null
|
2024-09-15 16:29:47 +02:00
|
|
|
) => {
|
|
|
|
|
if (!previousMessage) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2024-08-06 21:45:12 +02:00
|
|
|
|
2024-09-15 16:29:47 +02:00
|
|
|
const previousMessageDate = new Date(previousMessage.createdAt);
|
|
|
|
|
const currentMessageDate = new Date(message.createdAt);
|
2024-08-06 21:45:12 +02:00
|
|
|
|
2024-09-15 16:29:47 +02:00
|
|
|
if (previousMessageDate.getDate() !== currentMessageDate.getDate()) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2024-08-06 21:45:12 +02:00
|
|
|
|
2024-09-15 16:29:47 +02:00
|
|
|
return previousMessage.author.id !== message.author.id;
|
|
|
|
|
};
|
2024-08-03 19:14:38 +02:00
|
|
|
|
2024-11-12 23:00:22 +01:00
|
|
|
export const Message = ({ message, previousMessage }: MessageProps) => {
|
2024-10-03 17:11:39 +02:00
|
|
|
const workspace = useWorkspace();
|
2024-11-12 23:00:22 +01:00
|
|
|
const conversation = useConversation();
|
2024-11-14 17:11:53 +01:00
|
|
|
const radar = useRadar();
|
2024-11-12 23:00:22 +01:00
|
|
|
|
2024-10-03 17:11:39 +02:00
|
|
|
const { mutate, isPending } = useMutation();
|
2024-08-03 19:14:38 +02:00
|
|
|
|
2024-11-12 23:00:22 +01:00
|
|
|
const canDelete = conversation.canDeleteMessage(message);
|
2024-11-18 12:54:58 +01:00
|
|
|
const canReplyInThread = false;
|
2024-09-15 16:29:47 +02:00
|
|
|
const displayUserInfo = shouldDisplayUserInfo(message, previousMessage);
|
|
|
|
|
|
2024-08-27 15:20:16 +02:00
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
id={`message-${message.id}`}
|
|
|
|
|
key={`message-${message.id}`}
|
|
|
|
|
className={`group flex flex-row px-1 hover:bg-gray-50 ${
|
2024-09-15 16:29:47 +02:00
|
|
|
displayUserInfo ? 'mt-2 first:mt-0' : ''
|
2024-08-27 15:20:16 +02:00
|
|
|
}`}
|
|
|
|
|
>
|
|
|
|
|
<div className="mr-2 w-10 pt-1">
|
2024-09-15 16:29:47 +02:00
|
|
|
{displayUserInfo && (
|
2024-09-10 08:11:29 +02:00
|
|
|
<Avatar
|
|
|
|
|
id={message.author.id}
|
|
|
|
|
name={message.author.name}
|
2024-10-27 22:15:17 +01:00
|
|
|
avatar={message.author.avatar}
|
2024-09-10 08:11:29 +02:00
|
|
|
size="medium"
|
|
|
|
|
/>
|
2024-08-27 15:20:16 +02:00
|
|
|
)}
|
|
|
|
|
</div>
|
2024-08-03 19:14:38 +02:00
|
|
|
|
2024-08-27 15:20:16 +02:00
|
|
|
<div className="relative w-full">
|
2024-09-15 16:29:47 +02:00
|
|
|
{displayUserInfo && (
|
2024-11-12 23:00:22 +01:00
|
|
|
<div className="font-medium">
|
|
|
|
|
<span>{message.author.name}</span>
|
2024-08-27 15:20:16 +02:00
|
|
|
<Tooltip>
|
|
|
|
|
<TooltipTrigger asChild>
|
|
|
|
|
<span className="ml-2 text-xs text-muted-foreground">
|
|
|
|
|
{timeAgo(message.createdAt)}
|
|
|
|
|
</span>
|
|
|
|
|
</TooltipTrigger>
|
|
|
|
|
<TooltipContent>
|
2024-11-12 23:00:22 +01:00
|
|
|
<span className="text-sm shadow-md">
|
2024-08-27 15:20:16 +02:00
|
|
|
{formatDate(message.createdAt)}
|
|
|
|
|
</span>
|
|
|
|
|
</TooltipContent>
|
|
|
|
|
</Tooltip>
|
2024-11-12 23:00:22 +01:00
|
|
|
</div>
|
2024-08-27 15:20:16 +02:00
|
|
|
)}
|
2024-08-03 19:14:38 +02:00
|
|
|
|
2024-08-27 15:20:16 +02:00
|
|
|
<InView
|
|
|
|
|
rootMargin="50px"
|
|
|
|
|
onChange={(inView) => {
|
2024-10-28 20:35:30 +01:00
|
|
|
if (inView) {
|
2024-11-14 17:11:53 +01:00
|
|
|
radar.markAsSeen(workspace.userId, message.id, message.versionId);
|
2024-10-28 20:35:30 +01:00
|
|
|
}
|
2024-08-27 15:20:16 +02:00
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<ul className="invisible absolute -top-2 right-1 z-10 flex flex-row bg-gray-100 text-muted-foreground shadow group-hover:visible">
|
|
|
|
|
{canReplyInThread && (
|
2024-09-15 16:29:47 +02:00
|
|
|
<li className="flex h-8 w-7 cursor-pointer items-center justify-center hover:bg-gray-200">
|
2024-10-27 09:14:09 +01:00
|
|
|
<MessagesSquare className="size-4 cursor-pointer" />
|
2024-08-27 15:20:16 +02:00
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
<li className="flex h-8 w-7 cursor-pointer items-center justify-center hover:bg-gray-200">
|
2024-09-15 16:29:47 +02:00
|
|
|
<MessageReactionCreatePopover
|
|
|
|
|
onReactionClick={(reaction) => {
|
2024-10-03 17:11:39 +02:00
|
|
|
if (isPending) {
|
2024-09-15 16:29:47 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-03 17:11:39 +02:00
|
|
|
mutate({
|
|
|
|
|
input: {
|
|
|
|
|
type: 'node_reaction_create',
|
|
|
|
|
nodeId: message.id,
|
|
|
|
|
userId: workspace.userId,
|
|
|
|
|
reaction,
|
|
|
|
|
},
|
|
|
|
|
});
|
2024-08-27 15:20:16 +02:00
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</li>
|
2024-11-13 00:56:54 +01:00
|
|
|
{conversation.canCreateMessage && (
|
|
|
|
|
<li className="flex h-8 w-7 cursor-pointer items-center justify-center hover:bg-gray-200">
|
|
|
|
|
<Reply
|
|
|
|
|
className="size-4 cursor-pointer"
|
|
|
|
|
onClick={() => {
|
|
|
|
|
conversation.onReply(message);
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
2024-08-27 15:20:16 +02:00
|
|
|
{canDelete && (
|
|
|
|
|
<li className="flex h-8 w-7 cursor-pointer items-center justify-center hover:bg-gray-200">
|
|
|
|
|
<MessageDeleteButton id={message.id} />
|
2024-08-03 19:14:38 +02:00
|
|
|
</li>
|
2024-08-27 15:20:16 +02:00
|
|
|
)}
|
|
|
|
|
</ul>
|
|
|
|
|
<div className="text-foreground">
|
2024-09-10 08:11:29 +02:00
|
|
|
{message.content.map((node) => (
|
2024-10-09 11:29:08 +02:00
|
|
|
<NodeRenderer
|
|
|
|
|
key={node.attrs?.id}
|
|
|
|
|
node={node}
|
|
|
|
|
keyPrefix={node.attrs?.id}
|
|
|
|
|
/>
|
2024-09-10 08:11:29 +02:00
|
|
|
))}
|
2024-08-27 15:20:16 +02:00
|
|
|
</div>
|
2024-10-15 23:12:52 +02:00
|
|
|
{message.reactionCounts?.length > 0 && (
|
2024-09-15 16:29:47 +02:00
|
|
|
<MessageReactions
|
|
|
|
|
message={message}
|
|
|
|
|
onReactionClick={(reaction) => {
|
2024-10-03 17:11:39 +02:00
|
|
|
if (isPending) {
|
2024-09-15 16:29:47 +02:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-15 23:12:52 +02:00
|
|
|
if (
|
|
|
|
|
message.reactionCounts.some(
|
|
|
|
|
(reactionCount) =>
|
|
|
|
|
reactionCount.reaction === reaction &&
|
2024-11-07 09:15:00 +01:00
|
|
|
reactionCount.isReactedTo
|
2024-10-15 23:12:52 +02:00
|
|
|
)
|
|
|
|
|
) {
|
2024-10-03 17:11:39 +02:00
|
|
|
mutate({
|
|
|
|
|
input: {
|
|
|
|
|
type: 'node_reaction_delete',
|
|
|
|
|
nodeId: message.id,
|
|
|
|
|
userId: workspace.userId,
|
|
|
|
|
reaction,
|
|
|
|
|
},
|
|
|
|
|
});
|
2024-09-15 16:29:47 +02:00
|
|
|
} else {
|
2024-10-03 17:11:39 +02:00
|
|
|
mutate({
|
|
|
|
|
input: {
|
|
|
|
|
type: 'node_reaction_create',
|
|
|
|
|
nodeId: message.id,
|
|
|
|
|
userId: workspace.userId,
|
|
|
|
|
reaction,
|
|
|
|
|
},
|
|
|
|
|
});
|
2024-09-15 16:29:47 +02:00
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2024-08-27 15:20:16 +02:00
|
|
|
</InView>
|
2024-08-03 19:14:38 +02:00
|
|
|
</div>
|
2024-08-27 15:20:16 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|