fix(emails): stop reply composer infinite re-render (#21935)
<!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21935?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+53
-60
@@ -1,14 +1,13 @@
|
||||
import { styled } from '@linaria/react';
|
||||
import { useCallback, useEffect, useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { EmailComposerFields } from '@/activities/emails/components/EmailComposerFields';
|
||||
import { useEmailComposerState } from '@/activities/emails/hooks/useEmailComposerState';
|
||||
import { type ReplyContextReady } from '@/activities/emails/hooks/useReplyContext';
|
||||
import { EmailThreadComposerFooterEffect } from '@/page-layout/widgets/email-thread/components/EmailThreadComposerFooterEffect';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
|
||||
import { sidePanelWidgetFooterCommandMenuItemsState } from '@/ui/layout/side-panel/states/sidePanelWidgetFooterCommandMenuItemsState';
|
||||
import { type SidePanelFooterCommandMenuItem } from '@/ui/layout/side-panel/types/SidePanelFooterCommandMenuItem';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { IconArrowBackUp, IconSend, IconX } from 'twenty-ui/icon';
|
||||
import { themeCssVariables } from 'twenty-ui/theme-constants';
|
||||
@@ -55,58 +54,47 @@ export const EmailThreadComposer = ({
|
||||
onSent: handleReplySent,
|
||||
});
|
||||
|
||||
const setSidePanelWidgetFooterCommandMenuItems = useSetAtomState(
|
||||
sidePanelWidgetFooterCommandMenuItemsState,
|
||||
);
|
||||
const { handleSend, canSend } = composerState;
|
||||
|
||||
const footerCommandMenuItems =
|
||||
useMemo((): SidePanelFooterCommandMenuItem[] => {
|
||||
if (!isComposerOpen) {
|
||||
return [
|
||||
{
|
||||
id: 'reply',
|
||||
label: t`Reply`,
|
||||
Icon: IconArrowBackUp,
|
||||
isPrimaryCTA: true,
|
||||
onClick: () => setIsComposerOpen(true),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const footerActions = useMemo((): SidePanelFooterCommandMenuItem[] => {
|
||||
if (!isComposerOpen) {
|
||||
return [
|
||||
{
|
||||
id: 'reply',
|
||||
label: t`Reply`,
|
||||
Icon: IconArrowBackUp,
|
||||
id: 'cancel-reply',
|
||||
label: t`Cancel reply`,
|
||||
Icon: IconX,
|
||||
isPinned: false,
|
||||
onClick: () => setIsComposerOpen(false),
|
||||
},
|
||||
{
|
||||
id: 'send',
|
||||
label: t`Send`,
|
||||
Icon: IconSend,
|
||||
isPrimaryCTA: true,
|
||||
onClick: () => setIsComposerOpen(true),
|
||||
hotkeys: [getOsControlSymbol(), '⏎'],
|
||||
onClick: handleSend,
|
||||
disabled: !canSend,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: 'cancel-reply',
|
||||
label: t`Cancel reply`,
|
||||
Icon: IconX,
|
||||
isPinned: false,
|
||||
onClick: () => setIsComposerOpen(false),
|
||||
},
|
||||
{
|
||||
id: 'send',
|
||||
label: t`Send`,
|
||||
Icon: IconSend,
|
||||
isPrimaryCTA: true,
|
||||
hotkeys: [getOsControlSymbol(), '⏎'],
|
||||
onClick: composerState.handleSend,
|
||||
disabled: !composerState.canSend,
|
||||
},
|
||||
];
|
||||
}, [isComposerOpen, composerState, setIsComposerOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isInSidePanel) {
|
||||
return;
|
||||
}
|
||||
|
||||
setSidePanelWidgetFooterCommandMenuItems(footerActions);
|
||||
|
||||
return () => setSidePanelWidgetFooterCommandMenuItems([]);
|
||||
}, [isInSidePanel, footerActions, setSidePanelWidgetFooterCommandMenuItems]);
|
||||
}, [isComposerOpen, handleSend, canSend, setIsComposerOpen]);
|
||||
|
||||
const handleSendHotkey = useCallback(() => {
|
||||
if (isComposerOpen && composerState.canSend) {
|
||||
composerState.handleSend();
|
||||
if (isComposerOpen && canSend) {
|
||||
handleSend();
|
||||
}
|
||||
}, [isComposerOpen, composerState]);
|
||||
}, [isComposerOpen, canSend, handleSend]);
|
||||
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: ['ctrl+Enter,meta+Enter'],
|
||||
@@ -115,18 +103,23 @@ export const EmailThreadComposer = ({
|
||||
dependencies: [handleSendHotkey],
|
||||
});
|
||||
|
||||
if (!isComposerOpen) {
|
||||
if (isInSidePanel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledReplyBar onClick={() => setIsComposerOpen(true)}>
|
||||
<IconArrowBackUp size={16} />
|
||||
{t`Reply...`}
|
||||
</StyledReplyBar>
|
||||
);
|
||||
}
|
||||
|
||||
return <EmailComposerFields composerState={composerState} />;
|
||||
return (
|
||||
<>
|
||||
{isInSidePanel && (
|
||||
<EmailThreadComposerFooterEffect
|
||||
footerCommandMenuItems={footerCommandMenuItems}
|
||||
/>
|
||||
)}
|
||||
{isComposerOpen ? (
|
||||
<EmailComposerFields composerState={composerState} />
|
||||
) : (
|
||||
!isInSidePanel && (
|
||||
<StyledReplyBar onClick={() => setIsComposerOpen(true)}>
|
||||
<IconArrowBackUp size={16} />
|
||||
{t`Reply...`}
|
||||
</StyledReplyBar>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { sidePanelWidgetFooterCommandMenuItemsState } from '@/ui/layout/side-panel/states/sidePanelWidgetFooterCommandMenuItemsState';
|
||||
import { type SidePanelFooterCommandMenuItem } from '@/ui/layout/side-panel/types/SidePanelFooterCommandMenuItem';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
|
||||
type EmailThreadComposerFooterEffectProps = {
|
||||
footerCommandMenuItems: SidePanelFooterCommandMenuItem[];
|
||||
};
|
||||
|
||||
export const EmailThreadComposerFooterEffect = ({
|
||||
footerCommandMenuItems,
|
||||
}: EmailThreadComposerFooterEffectProps) => {
|
||||
const setSidePanelWidgetFooterCommandMenuItems = useSetAtomState(
|
||||
sidePanelWidgetFooterCommandMenuItemsState,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setSidePanelWidgetFooterCommandMenuItems(footerCommandMenuItems);
|
||||
|
||||
return () => setSidePanelWidgetFooterCommandMenuItems([]);
|
||||
}, [footerCommandMenuItems, setSidePanelWidgetFooterCommandMenuItems]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
Reference in New Issue
Block a user