diff --git a/desktop/src/features/home/ui/InboxDetailPane.tsx b/desktop/src/features/home/ui/InboxDetailPane.tsx index b45c9a0d7d..f43fa438e0 100644 --- a/desktop/src/features/home/ui/InboxDetailPane.tsx +++ b/desktop/src/features/home/ui/InboxDetailPane.tsx @@ -12,12 +12,13 @@ import type { InboxItem, InboxReply, } from "@/features/home/lib/inbox"; +import { + type InboxDisplayMessage, + InboxMessageRow, +} from "@/features/home/ui/InboxMessageRow"; import type { TimelineMessage } from "@/features/messages/types"; -import { MessageActionBar } from "@/features/messages/ui/MessageActionBar"; import { MessageComposer } from "@/features/messages/ui/MessageComposer"; -import { cn } from "@/shared/lib/cn"; import { Button } from "@/shared/ui/button"; -import { Markdown } from "@/shared/ui/markdown"; import { DropdownMenu, DropdownMenuContent, @@ -30,7 +31,6 @@ import { TooltipProvider, TooltipTrigger, } from "@/shared/ui/tooltip"; -import { UserAvatar } from "@/shared/ui/UserAvatar"; type InboxDetailPaneProps = { canDelete: boolean; @@ -61,23 +61,6 @@ type InboxDetailPaneProps = { ) => Promise; }; -type InboxDisplayMessage = InboxContextMessage & { - depth: number; -}; - -function toActionBarMessage(message: InboxDisplayMessage): TimelineMessage { - return { - id: message.id, - author: message.authorLabel, - avatarUrl: message.avatarUrl, - body: message.content, - createdAt: 0, - depth: message.depth, - reactions: message.reactions ?? [], - time: message.fullTimestampLabel, - }; -} - export function InboxDetailPane({ canDelete, canOpenChannel, @@ -267,88 +250,14 @@ export function InboxDetailPane({ {index === 1 ? (
) : null} -
-
- {canReply || onToggleReaction ? ( -
- { - const actionBarMessage = - toActionBarMessage(message); - const remove = - actionBarMessage.reactions?.some( - (reaction) => - reaction.emoji === emoji && - reaction.reactedByCurrentUser, - ) ?? false; - return onToggleReaction( - actionBarMessage, - emoji, - remove, - ); - } - : undefined - } - onReply={ - canReply - ? () => handleSelectReplyTarget(message) - : undefined - } - reactions={message.reactions ?? []} - /> -
- ) : null} - -
-
-

- {message.authorLabel} -

-

- {message.fullTimestampLabel} -

- {message.isSelected ? ( - - Inbox item - - ) : null} -
-
- -
-
-
-
+ ))}
diff --git a/desktop/src/features/home/ui/InboxMessageRow.tsx b/desktop/src/features/home/ui/InboxMessageRow.tsx new file mode 100644 index 0000000000..f463d22494 --- /dev/null +++ b/desktop/src/features/home/ui/InboxMessageRow.tsx @@ -0,0 +1,147 @@ +import * as React from "react"; + +import type { InboxContextMessage } from "@/features/home/lib/inbox"; +import type { TimelineMessage } from "@/features/messages/types"; +import { MessageActionBar } from "@/features/messages/ui/MessageActionBar"; +import { MessageReactions } from "@/features/messages/ui/MessageReactions"; +import { useReactionHandler } from "@/features/messages/ui/useReactionHandler"; +import { cn } from "@/shared/lib/cn"; +import { Markdown } from "@/shared/ui/markdown"; +import { UserAvatar } from "@/shared/ui/UserAvatar"; + +export type InboxDisplayMessage = InboxContextMessage & { + depth: number; +}; + +function toTimelineMessage(message: InboxDisplayMessage): TimelineMessage { + return { + id: message.id, + author: message.authorLabel, + avatarUrl: message.avatarUrl, + body: message.content, + createdAt: 0, + depth: message.depth, + reactions: message.reactions ?? [], + time: message.fullTimestampLabel, + }; +} + +type InboxMessageRowProps = { + activeReplyTargetId: string | null; + canReply: boolean; + isFocusHighlightVisible: boolean; + message: InboxDisplayMessage; + onSelectReplyTarget: (message: InboxDisplayMessage) => void; + onToggleReaction?: ( + message: TimelineMessage, + emoji: string, + remove: boolean, + ) => Promise; +}; + +export function InboxMessageRow({ + activeReplyTargetId, + canReply, + isFocusHighlightVisible, + message, + onSelectReplyTarget, + onToggleReaction, +}: InboxMessageRowProps) { + const timelineMessage = React.useMemo( + () => toTimelineMessage(message), + [message], + ); + const { + reactions, + canToggle: canToggleReactions, + pending: reactionPending, + errorMessage: reactionErrorMessage, + select: handleReactionSelect, + } = useReactionHandler(timelineMessage, onToggleReaction); + + return ( +
+
+ {canReply || canToggleReactions ? ( +
+ onSelectReplyTarget(message) : undefined + } + reactionErrorMessage={reactionErrorMessage} + reactionPending={reactionPending} + reactions={reactions} + /> +
+ ) : null} + + + +
+
+

+ {message.authorLabel} +

+

+ {message.fullTimestampLabel} +

+ {message.isSelected ? ( + + Inbox item + + ) : null} +
+ +
+ + { + void handleReactionSelect(emoji); + }} + pending={reactionPending} + reactions={reactions} + /> + {reactionErrorMessage ? ( +

+ {reactionErrorMessage} +

+ ) : null} +
+
+
+
+ ); +}