perf: memo MemberHoverCard, ActiveTasksBlock, PendingRepliesBlock

This commit is contained in:
Mike 2026-05-02 22:29:00 +05:00
parent 5cd890dcdd
commit 4c8a093200
3 changed files with 14 additions and 10 deletions

View file

@ -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 { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables';
import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'; import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors';
@ -32,14 +32,14 @@ interface ActivityEntry {
kind: 'working' | 'reviewing'; kind: 'working' | 'reviewing';
} }
export const ActiveTasksBlock = ({ export const ActiveTasksBlock = memo(function ActiveTasksBlock({
members, members,
tasks, tasks,
defaultCollapsed = false, defaultCollapsed = false,
headerRight, headerRight,
onMemberClick, onMemberClick,
onTaskClick, onTaskClick,
}: ActiveTasksBlockProps): React.JSX.Element | null => { }: ActiveTasksBlockProps): React.JSX.Element | null {
const { isLight } = useTheme(); const { isLight } = useTheme();
const [collapsed, setCollapsed] = useState(defaultCollapsed); const [collapsed, setCollapsed] = useState(defaultCollapsed);
const colorMap = buildMemberColorMap(members); const colorMap = buildMemberColorMap(members);
@ -188,4 +188,4 @@ export const ActiveTasksBlock = ({
})} })}
</div> </div>
); );
}; });

View file

@ -1,3 +1,5 @@
import { memo } from 'react';
import { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables'; import { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables';
import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors'; import { getTeamColorSet, getThemedBadge } from '@renderer/constants/teamColors';
import { useTheme } from '@renderer/hooks/useTheme'; import { useTheme } from '@renderer/hooks/useTheme';
@ -32,13 +34,13 @@ interface PendingRepliesBlockProps {
onMemberClick?: (member: ResolvedTeamMember) => void; onMemberClick?: (member: ResolvedTeamMember) => void;
} }
export const PendingRepliesBlock = ({ export const PendingRepliesBlock = memo(function PendingRepliesBlock({
members, members,
pendingRepliesByMember, pendingRepliesByMember,
pendingCrossTeamReplies = [], pendingCrossTeamReplies = [],
headerRight, headerRight,
onMemberClick, onMemberClick,
}: PendingRepliesBlockProps): React.JSX.Element | null => { }: PendingRepliesBlockProps): React.JSX.Element | null {
const { isLight } = useTheme(); const { isLight } = useTheme();
const pendingApprovals = useStore(useShallow((s) => s.pendingApprovals)); const pendingApprovals = useStore(useShallow((s) => s.pendingApprovals));
const colorMap = buildMemberColorMap(members); const colorMap = buildMemberColorMap(members);
@ -270,4 +272,4 @@ export const PendingRepliesBlock = ({
})} })}
</div> </div>
); );
}; });

View file

@ -1,3 +1,5 @@
import { memo } from 'react';
import { Badge } from '@renderer/components/ui/badge'; import { Badge } from '@renderer/components/ui/badge';
import { HoverCard, HoverCardContent, HoverCardTrigger } from '@renderer/components/ui/hover-card'; import { HoverCard, HoverCardContent, HoverCardTrigger } from '@renderer/components/ui/hover-card';
import { import {
@ -57,13 +59,13 @@ interface MemberHoverCardProps {
* Reads member data from the team snapshot + resolved member selectors. * Reads member data from the team snapshot + resolved member selectors.
* Falls back to a simple wrapper when member data is unavailable. * Falls back to a simple wrapper when member data is unavailable.
*/ */
export const MemberHoverCard = ({ export const MemberHoverCard = memo(function MemberHoverCard({
name, name,
color, color,
teamName, teamName,
onOpenTask, onOpenTask,
children, children,
}: MemberHoverCardProps): React.JSX.Element => { }: MemberHoverCardProps): React.JSX.Element {
const { isLight } = useTheme(); const { isLight } = useTheme();
const selectedTeamName = useStore((s) => s.selectedTeamName); const selectedTeamName = useStore((s) => s.selectedTeamName);
const effectiveTeamName = teamName ?? selectedTeamName; const effectiveTeamName = teamName ?? selectedTeamName;
@ -287,4 +289,4 @@ export const MemberHoverCard = ({
</HoverCardContent> </HoverCardContent>
</HoverCard> </HoverCard>
); );
}; });