diff --git a/src/renderer/components/team/TeamDetailView.tsx b/src/renderer/components/team/TeamDetailView.tsx index d949b9b2..fdd68f1c 100644 --- a/src/renderer/components/team/TeamDetailView.tsx +++ b/src/renderer/components/team/TeamDetailView.tsx @@ -78,12 +78,9 @@ import { import { useShallow } from 'zustand/react/shallow'; import { AddMemberDialog } from './dialogs/AddMemberDialog'; -import { CreateTaskDialog } from './dialogs/CreateTaskDialog'; import { EditTeamDialog } from './dialogs/EditTeamDialog'; import type { TeamLaunchDialogMode } from './dialogs/LaunchTeamDialog'; import { ReviewDialog } from './dialogs/ReviewDialog'; -import { SendMessageDialog } from './dialogs/SendMessageDialog'; -import { TaskDetailDialog } from './dialogs/TaskDetailDialog'; import { executeTeamRelaunch } from './dialogs/teamRelaunchFlow'; import { KanbanBoard } from './kanban/KanbanBoard'; import { UNASSIGNED_OWNER } from './kanban/KanbanFilterPopover'; @@ -107,9 +104,20 @@ const TeamGraphOverlay = lazy(() => default: m.TeamGraphOverlay, })) ); +const TaskDetailDialog = lazy(() => + import('./dialogs/TaskDetailDialog').then((m) => ({ default: m.TaskDetailDialog })) +); +const SendMessageDialog = lazy(() => + import('./dialogs/SendMessageDialog').then((m) => ({ default: m.SendMessageDialog })) +); +const CreateTaskDialog = lazy(() => + import('./dialogs/CreateTaskDialog').then((m) => ({ default: m.CreateTaskDialog })) +); +const ChangeReviewDialog = lazy(() => + import('./review/ChangeReviewDialog').then((m) => ({ default: m.ChangeReviewDialog })) +); import { MemberList } from './members/MemberList'; import { MessagesPanel } from './messages/MessagesPanel'; -import { ChangeReviewDialog } from './review/ChangeReviewDialog'; import { ScheduleSection } from './schedule/ScheduleSection'; import { TeamSidebarHost } from './sidebar/TeamSidebarHost'; import { TeamSidebarPortalSource } from './sidebar/TeamSidebarPortalSource'; @@ -2857,21 +2865,23 @@ export const TeamDetailView = memo( }} /> - + + + - { - const sentAtMs = Date.now(); - setPendingRepliesByMember((prev) => ({ ...prev, [member]: sentAtMs })); - try { - const result = await sendTeamMessage(teamName, { - member, - text, - summary, - attachments, - actionMode, - taskRefs, - }); - if ( - result?.runtimeDelivery?.attempted === true && - result.runtimeDelivery.delivered === false - ) { + + { + const sentAtMs = Date.now(); + setPendingRepliesByMember((prev) => ({ ...prev, [member]: sentAtMs })); + try { + const result = await sendTeamMessage(teamName, { + member, + text, + summary, + attachments, + actionMode, + taskRefs, + }); + if ( + result?.runtimeDelivery?.attempted === true && + result.runtimeDelivery.delivered === false + ) { + setPendingRepliesByMember((prev) => { + if (prev[member] !== sentAtMs) return prev; + const next = { ...prev }; + delete next[member]; + return next; + }); + } + return result; + } catch (error) { setPendingRepliesByMember((prev) => { if (prev[member] !== sentAtMs) return prev; const next = { ...prev }; delete next[member]; return next; }); + throw error; } - return result; - } catch (error) { - setPendingRepliesByMember((prev) => { - if (prev[member] !== sentAtMs) return prev; - const next = { ...prev }; - delete next[member]; - return next; - }); - throw error; - } - }} - onClose={() => { - setSendDialogOpen(false); - setReplyQuote(undefined); - setSendDialogDefaultText(undefined); - setSendDialogDefaultChip(undefined); - }} - /> + }} + onClose={() => { + setSendDialogOpen(false); + setReplyQuote(undefined); + setSendDialogDefaultText(undefined); + setSendDialogDefaultChip(undefined); + }} + /> + - setSelectedTask(null)} - onScrollToTask={(taskId) => { - setSelectedTask(null); - const el = document.querySelector(`[data-task-id="${taskId}"]`); - if (el) { - el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); - el.classList.remove('kanban-card-focus-pulse'); - void (el as HTMLElement).offsetWidth; - el.classList.add('kanban-card-focus-pulse'); - el.addEventListener( - 'animationend', - () => el.classList.remove('kanban-card-focus-pulse'), - { once: true } - ); + + { - void (async () => { - try { - await updateTaskOwner(teamName, taskId, owner); - } catch { - // error via store + taskMap={taskMap} + members={activeMembers} + onClose={() => setSelectedTask(null)} + onScrollToTask={(taskId) => { + setSelectedTask(null); + const el = document.querySelector(`[data-task-id="${taskId}"]`); + if (el) { + el.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); + el.classList.remove('kanban-card-focus-pulse'); + void (el as HTMLElement).offsetWidth; + el.classList.add('kanban-card-focus-pulse'); + el.addEventListener( + 'animationend', + () => el.classList.remove('kanban-card-focus-pulse'), + { once: true } + ); } - })(); - }} - onViewChanges={handleViewChangesForFile} - onOpenInEditor={(filePath) => { - const { revealFileInEditor } = useStore.getState(); - revealFileInEditor(filePath); - }} - onDeleteTask={handleDeleteTask} - /> + }} + onOwnerChange={(taskId, owner) => { + void (async () => { + try { + await updateTaskOwner(teamName, taskId, owner); + } catch { + // error via store + } + })(); + }} + onViewChanges={handleViewChangesForFile} + onOpenInEditor={(filePath) => { + const { revealFileInEditor } = useStore.getState(); + revealFileInEditor(filePath); + }} + onDeleteTask={handleDeleteTask} + /> + - - setReviewDialogState((prev) => ({ - ...prev, - open, - ...(open - ? {} - : { initialFilePath: undefined, taskChangeRequestOptions: undefined }), - })) - } - teamName={teamName} - mode={reviewDialogState.mode} - memberName={reviewDialogState.memberName} - taskId={reviewDialogState.taskId} - initialFilePath={reviewDialogState.initialFilePath} - taskChangeRequestOptions={reviewDialogState.taskChangeRequestOptions} - projectPath={data.config.projectPath} - onEditorAction={handleEditorAction} - /> + + + setReviewDialogState((prev) => ({ + ...prev, + open, + ...(open + ? {} + : { initialFilePath: undefined, taskChangeRequestOptions: undefined }), + })) + } + teamName={teamName} + mode={reviewDialogState.mode} + memberName={reviewDialogState.memberName} + taskId={reviewDialogState.taskId} + initialFilePath={reviewDialogState.initialFilePath} + taskChangeRequestOptions={reviewDialogState.taskChangeRequestOptions} + projectPath={data.config.projectPath} + onEditorAction={handleEditorAction} + /> +