perf(renderer): isolate send dialog state from team page
This commit is contained in:
parent
c9e9e4ae09
commit
7019567537
1 changed files with 85 additions and 51 deletions
|
|
@ -897,6 +897,14 @@ type TeamMessagesPanelBridgeProps = Omit<
|
||||||
ComponentProps<typeof MessagesPanel>,
|
ComponentProps<typeof MessagesPanel>,
|
||||||
'leadActivity' | LeadUpdatedKey
|
'leadActivity' | LeadUpdatedKey
|
||||||
>;
|
>;
|
||||||
|
type SendMessageDialogBridgeProps = Omit<
|
||||||
|
ComponentProps<typeof SendMessageDialog>,
|
||||||
|
'sending' | 'sendError' | 'sendWarning' | 'sendDebugDetails' | 'lastResult' | 'onSend'
|
||||||
|
> & {
|
||||||
|
onPendingReplyStart: (member: string, sentAtMs: number) => void;
|
||||||
|
onPendingReplySettled: (member: string, sentAtMs: number) => void;
|
||||||
|
};
|
||||||
|
type SendMessageDialogOnSend = ComponentProps<typeof SendMessageDialog>['onSend'];
|
||||||
type SharedTeamMessagesPanelProps = Omit<TeamMessagesPanelBridgeProps, 'position'>;
|
type SharedTeamMessagesPanelProps = Omit<TeamMessagesPanelBridgeProps, 'position'>;
|
||||||
type TeamMemberListBridgeProps = Omit<
|
type TeamMemberListBridgeProps = Omit<
|
||||||
ComponentProps<typeof MemberList>,
|
ComponentProps<typeof MemberList>,
|
||||||
|
|
@ -1419,6 +1427,69 @@ const TeamSidebarRailBridge = memo(function TeamSidebarRailBridge({
|
||||||
return <TeamSidebarRail {...props} messagesPanelProps={bridgedMessagesPanelProps} />;
|
return <TeamSidebarRail {...props} messagesPanelProps={bridgedMessagesPanelProps} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const SendMessageDialogBridge = memo(function SendMessageDialogBridge({
|
||||||
|
teamName,
|
||||||
|
onPendingReplyStart,
|
||||||
|
onPendingReplySettled,
|
||||||
|
...props
|
||||||
|
}: SendMessageDialogBridgeProps): React.JSX.Element {
|
||||||
|
const {
|
||||||
|
sendTeamMessage,
|
||||||
|
sendingMessage,
|
||||||
|
sendMessageError,
|
||||||
|
sendMessageWarning,
|
||||||
|
sendMessageDebugDetails,
|
||||||
|
lastSendMessageResult,
|
||||||
|
} = useStore(
|
||||||
|
useShallow((s) => ({
|
||||||
|
sendTeamMessage: s.sendTeamMessage,
|
||||||
|
sendingMessage: s.sendingMessage,
|
||||||
|
sendMessageError: s.sendMessageError,
|
||||||
|
sendMessageWarning: s.sendMessageWarning,
|
||||||
|
sendMessageDebugDetails: s.sendMessageDebugDetails,
|
||||||
|
lastSendMessageResult: s.lastSendMessageResult,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSend = useCallback<SendMessageDialogOnSend>(
|
||||||
|
async (member, text, summary, attachments, actionMode, taskRefs) => {
|
||||||
|
const sentAtMs = Date.now();
|
||||||
|
onPendingReplyStart(member, sentAtMs);
|
||||||
|
try {
|
||||||
|
const result = await sendTeamMessage(teamName, {
|
||||||
|
member,
|
||||||
|
text,
|
||||||
|
summary,
|
||||||
|
attachments,
|
||||||
|
actionMode,
|
||||||
|
taskRefs,
|
||||||
|
});
|
||||||
|
if (shouldClearPendingReplyForOpenCodeRuntimeDelivery(result?.runtimeDelivery)) {
|
||||||
|
onPendingReplySettled(member, sentAtMs);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} catch (error) {
|
||||||
|
onPendingReplySettled(member, sentAtMs);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[onPendingReplySettled, onPendingReplyStart, sendTeamMessage, teamName]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<SendMessageDialog
|
||||||
|
{...props}
|
||||||
|
teamName={teamName}
|
||||||
|
sending={sendingMessage}
|
||||||
|
sendError={sendMessageError}
|
||||||
|
sendWarning={sendMessageWarning}
|
||||||
|
sendDebugDetails={sendMessageDebugDetails}
|
||||||
|
lastResult={lastSendMessageResult}
|
||||||
|
onSend={handleSend}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
const TeamMemberDetailDialogBridge = memo(function TeamMemberDetailDialogBridge({
|
const TeamMemberDetailDialogBridge = memo(function TeamMemberDetailDialogBridge({
|
||||||
teamName,
|
teamName,
|
||||||
member,
|
member,
|
||||||
|
|
@ -1634,18 +1705,12 @@ export const TeamDetailView = memo(function TeamDetailView({
|
||||||
updateKanbanColumnOrder,
|
updateKanbanColumnOrder,
|
||||||
updateTaskStatus,
|
updateTaskStatus,
|
||||||
updateTaskOwner,
|
updateTaskOwner,
|
||||||
sendTeamMessage,
|
|
||||||
requestReview,
|
requestReview,
|
||||||
createTeamTask,
|
createTeamTask,
|
||||||
startTaskByUser,
|
startTaskByUser,
|
||||||
deleteTeam,
|
deleteTeam,
|
||||||
openTeamsTab,
|
openTeamsTab,
|
||||||
closeTab,
|
closeTab,
|
||||||
sendingMessage,
|
|
||||||
sendMessageError,
|
|
||||||
sendMessageWarning,
|
|
||||||
sendMessageDebugDetails,
|
|
||||||
lastSendMessageResult,
|
|
||||||
reviewActionError,
|
reviewActionError,
|
||||||
addMember,
|
addMember,
|
||||||
restartMember,
|
restartMember,
|
||||||
|
|
@ -1691,18 +1756,12 @@ export const TeamDetailView = memo(function TeamDetailView({
|
||||||
updateKanbanColumnOrder: s.updateKanbanColumnOrder,
|
updateKanbanColumnOrder: s.updateKanbanColumnOrder,
|
||||||
updateTaskStatus: s.updateTaskStatus,
|
updateTaskStatus: s.updateTaskStatus,
|
||||||
updateTaskOwner: s.updateTaskOwner,
|
updateTaskOwner: s.updateTaskOwner,
|
||||||
sendTeamMessage: s.sendTeamMessage,
|
|
||||||
requestReview: s.requestReview,
|
requestReview: s.requestReview,
|
||||||
createTeamTask: s.createTeamTask,
|
createTeamTask: s.createTeamTask,
|
||||||
startTaskByUser: s.startTaskByUser,
|
startTaskByUser: s.startTaskByUser,
|
||||||
deleteTeam: s.deleteTeam,
|
deleteTeam: s.deleteTeam,
|
||||||
openTeamsTab: s.openTeamsTab,
|
openTeamsTab: s.openTeamsTab,
|
||||||
closeTab: s.closeTab,
|
closeTab: s.closeTab,
|
||||||
sendingMessage: s.sendingMessage,
|
|
||||||
sendMessageError: s.sendMessageError,
|
|
||||||
sendMessageWarning: s.sendMessageWarning,
|
|
||||||
sendMessageDebugDetails: s.sendMessageDebugDetails,
|
|
||||||
lastSendMessageResult: s.lastSendMessageResult,
|
|
||||||
reviewActionError: s.reviewActionError,
|
reviewActionError: s.reviewActionError,
|
||||||
addMember: s.addMember,
|
addMember: s.addMember,
|
||||||
restartMember: s.restartMember,
|
restartMember: s.restartMember,
|
||||||
|
|
@ -2773,6 +2832,17 @@ export const TeamDetailView = memo(function TeamDetailView({
|
||||||
};
|
};
|
||||||
|
|
||||||
const messagesPanelTasks = useStableMessagesPanelTasks(data?.tasks);
|
const messagesPanelTasks = useStableMessagesPanelTasks(data?.tasks);
|
||||||
|
const handlePendingReplyStart = useCallback((member: string, sentAtMs: number): void => {
|
||||||
|
setPendingRepliesByMember((prev) => ({ ...prev, [member]: sentAtMs }));
|
||||||
|
}, []);
|
||||||
|
const handlePendingReplySettled = useCallback((member: string, sentAtMs: number): void => {
|
||||||
|
setPendingRepliesByMember((prev) => {
|
||||||
|
if (prev[member] !== sentAtMs) return prev;
|
||||||
|
const next = { ...prev };
|
||||||
|
delete next[member];
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
const sharedMessagesPanelProps = useMemo<SharedTeamMessagesPanelProps>(
|
const sharedMessagesPanelProps = useMemo<SharedTeamMessagesPanelProps>(
|
||||||
() => ({
|
() => ({
|
||||||
|
|
@ -3656,7 +3726,7 @@ export const TeamDetailView = memo(function TeamDetailView({
|
||||||
|
|
||||||
{sendDialogOpen && (
|
{sendDialogOpen && (
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<SendMessageDialog
|
<SendMessageDialogBridge
|
||||||
open={sendDialogOpen}
|
open={sendDialogOpen}
|
||||||
teamName={teamName}
|
teamName={teamName}
|
||||||
members={activeMembers}
|
members={activeMembers}
|
||||||
|
|
@ -3665,44 +3735,8 @@ export const TeamDetailView = memo(function TeamDetailView({
|
||||||
defaultChip={sendDialogDefaultChip}
|
defaultChip={sendDialogDefaultChip}
|
||||||
quotedMessage={replyQuote}
|
quotedMessage={replyQuote}
|
||||||
isTeamAlive={data.isAlive}
|
isTeamAlive={data.isAlive}
|
||||||
sending={sendingMessage}
|
onPendingReplyStart={handlePendingReplyStart}
|
||||||
sendError={sendMessageError}
|
onPendingReplySettled={handlePendingReplySettled}
|
||||||
sendWarning={sendMessageWarning}
|
|
||||||
sendDebugDetails={sendMessageDebugDetails}
|
|
||||||
lastResult={lastSendMessageResult}
|
|
||||||
onSend={async (member, text, summary, attachments, actionMode, taskRefs) => {
|
|
||||||
const sentAtMs = Date.now();
|
|
||||||
setPendingRepliesByMember((prev) => ({ ...prev, [member]: sentAtMs }));
|
|
||||||
try {
|
|
||||||
const result = await sendTeamMessage(teamName, {
|
|
||||||
member,
|
|
||||||
text,
|
|
||||||
summary,
|
|
||||||
attachments,
|
|
||||||
actionMode,
|
|
||||||
taskRefs,
|
|
||||||
});
|
|
||||||
if (
|
|
||||||
shouldClearPendingReplyForOpenCodeRuntimeDelivery(result?.runtimeDelivery)
|
|
||||||
) {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
setSendDialogOpen(false);
|
setSendDialogOpen(false);
|
||||||
setReplyQuote(undefined);
|
setReplyQuote(undefined);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue