perf(renderer): memoize active task summary data

This commit is contained in:
777genius 2026-05-31 06:25:28 +03:00
parent 34c2215c31
commit 477d18d798

View file

@ -1,4 +1,4 @@
import { memo, type ReactNode, useState } from 'react';
import { memo, type ReactNode, useMemo, useState } from 'react';
import { useAppTranslation } from '@features/localization/renderer';
import { CARD_BG, CARD_BORDER_STYLE, CARD_ICON_MUTED } from '@renderer/constants/cssVariables';
@ -46,33 +46,45 @@ export const ActiveTasksBlock = memo(function ActiveTasksBlock({
const { t } = useAppTranslation('team');
const { isLight } = useTheme();
const [collapsed, setCollapsed] = useState(defaultCollapsed);
const colorMap = buildMemberColorMap(members);
const avatarMap = buildMemberAvatarMap(members);
const taskMap = new Map(tasks.map((t) => [t.id, t]));
const entries: ActivityEntry[] = [];
// Members working on tasks
const workingMemberNames = new Set<string>();
for (const m of members) {
if (!m.currentTaskId) continue;
const task = taskMap.get(m.currentTaskId);
// Defense-in-depth: hide stale currentTaskId until backend refresh clears it.
if (!isDisplayableCurrentTask(task)) continue;
workingMemberNames.add(m.name);
entries.push({ member: m, task, taskId: m.currentTaskId, kind: 'working' });
}
// Members reviewing tasks (only if not already shown as working)
for (const m of members) {
if (workingMemberNames.has(m.name)) continue;
const reviewTask = tasks.find(
(t) => t.reviewer === m.name && getTeamTaskWorkflowColumn(t) === 'review'
);
if (reviewTask) {
entries.push({ member: m, task: reviewTask, taskId: reviewTask.id, kind: 'reviewing' });
const colorMap = useMemo(() => buildMemberColorMap(members), [members]);
const avatarMap = useMemo(() => buildMemberAvatarMap(members), [members]);
const entries = useMemo<ActivityEntry[]>(() => {
const taskMap = new Map(tasks.map((task) => [task.id, task]));
const reviewTaskByReviewer = new Map<string, TeamTaskWithKanban>();
for (const task of tasks) {
if (!task.reviewer || getTeamTaskWorkflowColumn(task) !== 'review') continue;
if (!reviewTaskByReviewer.has(task.reviewer)) {
reviewTaskByReviewer.set(task.reviewer, task);
}
}
}
const nextEntries: ActivityEntry[] = [];
const workingMemberNames = new Set<string>();
for (const member of members) {
if (!member.currentTaskId) continue;
const task = taskMap.get(member.currentTaskId);
// Defense-in-depth: hide stale currentTaskId until backend refresh clears it.
if (!isDisplayableCurrentTask(task)) continue;
workingMemberNames.add(member.name);
nextEntries.push({ member, task, taskId: member.currentTaskId, kind: 'working' });
}
for (const member of members) {
if (workingMemberNames.has(member.name)) continue;
const reviewTask = reviewTaskByReviewer.get(member.name);
if (reviewTask) {
nextEntries.push({
member,
task: reviewTask,
taskId: reviewTask.id,
kind: 'reviewing',
});
}
}
return nextEntries;
}, [members, tasks]);
if (entries.length === 0) return null;