From 4c8a093200966a06cb9edf6cd9c8f7f7f258c6fa Mon Sep 17 00:00:00 2001 From: Mike Date: Sat, 2 May 2026 22:29:00 +0500 Subject: [PATCH] perf: memo MemberHoverCard, ActiveTasksBlock, PendingRepliesBlock --- .../components/team/activity/ActiveTasksBlock.tsx | 8 ++++---- .../components/team/activity/PendingRepliesBlock.tsx | 8 +++++--- src/renderer/components/team/members/MemberHoverCard.tsx | 8 +++++--- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/renderer/components/team/activity/ActiveTasksBlock.tsx b/src/renderer/components/team/activity/ActiveTasksBlock.tsx index 64398b5d..ac55ed8c 100644 --- a/src/renderer/components/team/activity/ActiveTasksBlock.tsx +++ b/src/renderer/components/team/activity/ActiveTasksBlock.tsx @@ -1,4 +1,4 @@ -import { type ReactNode, useState } from 'react'; +import { memo, type ReactNode, useState } from 'react'; import { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables'; import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'; @@ -32,14 +32,14 @@ interface ActivityEntry { kind: 'working' | 'reviewing'; } -export const ActiveTasksBlock = ({ +export const ActiveTasksBlock = memo(function ActiveTasksBlock({ members, tasks, defaultCollapsed = false, headerRight, onMemberClick, onTaskClick, -}: ActiveTasksBlockProps): React.JSX.Element | null => { +}: ActiveTasksBlockProps): React.JSX.Element | null { const { isLight } = useTheme(); const [collapsed, setCollapsed] = useState(defaultCollapsed); const colorMap = buildMemberColorMap(members); @@ -188,4 +188,4 @@ export const ActiveTasksBlock = ({ })} ); -}; +}); diff --git a/src/renderer/components/team/activity/PendingRepliesBlock.tsx b/src/renderer/components/team/activity/PendingRepliesBlock.tsx index fd521447..8e266ddb 100644 --- a/src/renderer/components/team/activity/PendingRepliesBlock.tsx +++ b/src/renderer/components/team/activity/PendingRepliesBlock.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react'; + import { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables'; import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'; import { useTheme } from '@renderer/hooks/useTheme'; @@ -32,13 +34,13 @@ interface PendingRepliesBlockProps { onMemberClick?: (member: ResolvedTeamMember) => void; } -export const PendingRepliesBlock = ({ +export const PendingRepliesBlock = memo(function PendingRepliesBlock({ members, pendingRepliesByMember, pendingCrossTeamReplies = [], headerRight, onMemberClick, -}: PendingRepliesBlockProps): React.JSX.Element | null => { +}: PendingRepliesBlockProps): React.JSX.Element | null { const { isLight } = useTheme(); const pendingApprovals = useStore(useShallow((s) => s.pendingApprovals)); const colorMap = buildMemberColorMap(members); @@ -270,4 +272,4 @@ export const PendingRepliesBlock = ({ })} ); -}; +}); diff --git a/src/renderer/components/team/members/MemberHoverCard.tsx b/src/renderer/components/team/members/MemberHoverCard.tsx index 92a48c25..b1601c12 100644 --- a/src/renderer/components/team/members/MemberHoverCard.tsx +++ b/src/renderer/components/team/members/MemberHoverCard.tsx @@ -1,3 +1,5 @@ +import { memo } from 'react'; + import { Badge } from '@renderer/components/ui/badge'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@renderer/components/ui/hover-card'; import { @@ -57,13 +59,13 @@ interface MemberHoverCardProps { * Reads member data from the team snapshot + resolved member selectors. * Falls back to a simple wrapper when member data is unavailable. */ -export const MemberHoverCard = ({ +export const MemberHoverCard = memo(function MemberHoverCard({ name, color, teamName, onOpenTask, children, -}: MemberHoverCardProps): React.JSX.Element => { +}: MemberHoverCardProps): React.JSX.Element { const { isLight } = useTheme(); const selectedTeamName = useStore((s) => s.selectedTeamName); const effectiveTeamName = teamName ?? selectedTeamName; @@ -287,4 +289,4 @@ export const MemberHoverCard = ({ ); -}; +});