Fix a hotkey scope race condition in command menu (#13025)
Fixes https://github.com/twentyhq/twenty/issues/12885 This PR fixes a hotkey scope race condition happening on note/task creation. The problem is that `ActivityRichTextEditor` catches the click event before the title cell. So here we prevent this from happening by checking if the record title cell is. This is only temporary and should be improved after the persist logic refactor : https://github.com/twentyhq/core-team-issues/issues/192
This commit is contained in:
@ -8,8 +8,6 @@ import {
|
||||
FieldInputEvent,
|
||||
} from '@/object-record/record-field/types/FieldInputEvent';
|
||||
|
||||
import { useInlineCell } from '../../record-inline-cell/hooks/useInlineCell';
|
||||
|
||||
import { RecordFieldComponentInstanceContext } from '@/object-record/record-field/states/contexts/RecordFieldComponentInstanceContext';
|
||||
import { RecordTitleCellContainer } from '@/object-record/record-title-cell/components/RecordTitleCellContainer';
|
||||
import {
|
||||
@ -18,6 +16,7 @@ import {
|
||||
} from '@/object-record/record-title-cell/components/RecordTitleCellContext';
|
||||
import { RecordTitleCellFieldDisplay } from '@/object-record/record-title-cell/components/RecordTitleCellFieldDisplay';
|
||||
import { RecordTitleCellFieldInput } from '@/object-record/record-title-cell/components/RecordTitleCellFieldInput';
|
||||
import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell';
|
||||
import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/types/RecordTitleCellContainerType';
|
||||
import { getRecordTitleCellId } from '@/object-record/record-title-cell/utils/getRecordTitleCellId';
|
||||
|
||||
@ -36,35 +35,50 @@ export const RecordTitleCell = ({
|
||||
|
||||
const isFieldInputOnly = useIsFieldInputOnly();
|
||||
|
||||
const { closeInlineCell } = useInlineCell(
|
||||
getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
);
|
||||
const { closeRecordTitleCell } = useRecordTitleCell();
|
||||
|
||||
const handleEnter: FieldInputEvent = (persistField) => {
|
||||
closeInlineCell();
|
||||
closeRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
});
|
||||
persistField();
|
||||
};
|
||||
|
||||
const handleEscape = () => {
|
||||
closeInlineCell();
|
||||
const handleEscape: FieldInputEvent = (persistField) => {
|
||||
closeRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
});
|
||||
persistField();
|
||||
};
|
||||
|
||||
const handleTab: FieldInputEvent = (persistField) => {
|
||||
closeInlineCell();
|
||||
closeRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
});
|
||||
persistField();
|
||||
};
|
||||
|
||||
const handleShiftTab: FieldInputEvent = (persistField) => {
|
||||
closeInlineCell();
|
||||
closeRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
});
|
||||
persistField();
|
||||
};
|
||||
|
||||
const handleClickOutside: FieldInputClickOutsideEvent = (persistField) => {
|
||||
closeInlineCell();
|
||||
closeRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition?.fieldMetadataId,
|
||||
containerType,
|
||||
});
|
||||
persistField();
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,7 @@
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY } from '@/object-record/record-inline-cell/constants/InlineCellHotkeyScopeMemoizeKey';
|
||||
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
|
||||
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
|
||||
import { TitleInputHotkeyScope } from '@/ui/input/types/TitleInputHotkeyScope';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { useRecordTitleCell } from '@/object-record/record-title-cell/hooks/useRecordTitleCell';
|
||||
import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/types/RecordTitleCellContainerType';
|
||||
import { Theme, withTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useContext } from 'react';
|
||||
@ -40,18 +38,16 @@ export const RecordTitleCellSingleTextDisplayMode = () => {
|
||||
const isEmpty =
|
||||
recordValue?.[fieldDefinition.metadata.fieldName]?.trim() === '';
|
||||
|
||||
const { openInlineCell } = useInlineCell();
|
||||
|
||||
const { setHotkeyScopeAndMemorizePreviousScope } = usePreviousHotkeyScope();
|
||||
const { openRecordTitleCell } = useRecordTitleCell();
|
||||
|
||||
return (
|
||||
<StyledDiv
|
||||
onClick={() => {
|
||||
setHotkeyScopeAndMemorizePreviousScope({
|
||||
scope: TitleInputHotkeyScope.TitleInput,
|
||||
memoizeKey: INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY,
|
||||
openRecordTitleCell({
|
||||
recordId,
|
||||
fieldMetadataId: fieldDefinition.fieldMetadataId,
|
||||
containerType: RecordTitleCellContainerType.ShowPage,
|
||||
});
|
||||
openInlineCell();
|
||||
}}
|
||||
>
|
||||
{isEmpty ? (
|
||||
|
||||
@ -6,7 +6,9 @@ import { RecordTitleCellContainerType } from '@/object-record/record-title-cell/
|
||||
import { getRecordTitleCellId } from '@/object-record/record-title-cell/utils/getRecordTitleCellId';
|
||||
import { TitleInputHotkeyScope } from '@/ui/input/types/TitleInputHotkeyScope';
|
||||
import { useGoBackToPreviousDropdownFocusId } from '@/ui/layout/dropdown/hooks/useGoBackToPreviousDropdownFocusId';
|
||||
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
|
||||
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
|
||||
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
@ -15,10 +17,9 @@ export const useRecordTitleCell = () => {
|
||||
const { goBackToPreviousDropdownFocusId } =
|
||||
useGoBackToPreviousDropdownFocusId();
|
||||
|
||||
const {
|
||||
setHotkeyScopeAndMemorizePreviousScope,
|
||||
goBackToPreviousHotkeyScope,
|
||||
} = usePreviousHotkeyScope();
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const closeRecordTitleCell = useRecoilCallback(
|
||||
({ set }) =>
|
||||
@ -38,11 +39,17 @@ export const useRecordTitleCell = () => {
|
||||
false,
|
||||
);
|
||||
|
||||
goBackToPreviousHotkeyScope(INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY);
|
||||
removeFocusItemFromFocusStackById({
|
||||
focusId: getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
});
|
||||
|
||||
goBackToPreviousDropdownFocusId();
|
||||
},
|
||||
[goBackToPreviousDropdownFocusId, goBackToPreviousHotkeyScope],
|
||||
[goBackToPreviousDropdownFocusId, removeFocusItemFromFocusStackById],
|
||||
);
|
||||
|
||||
const initFieldInputDraftValue = useInitDraftValueV2();
|
||||
@ -61,14 +68,41 @@ export const useRecordTitleCell = () => {
|
||||
customEditHotkeyScopeForField?: HotkeyScope;
|
||||
}) => {
|
||||
if (isDefined(customEditHotkeyScopeForField)) {
|
||||
setHotkeyScopeAndMemorizePreviousScope({
|
||||
scope: customEditHotkeyScopeForField.scope,
|
||||
customScopes: customEditHotkeyScopeForField.customScopes,
|
||||
pushFocusItemToFocusStack({
|
||||
focusId: getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
component: {
|
||||
type: FocusComponentType.OPENED_FIELD_INPUT,
|
||||
instanceId: getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
},
|
||||
hotkeyScope: customEditHotkeyScopeForField,
|
||||
memoizeKey: INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY,
|
||||
});
|
||||
} else {
|
||||
setHotkeyScopeAndMemorizePreviousScope({
|
||||
scope: TitleInputHotkeyScope.TitleInput,
|
||||
pushFocusItemToFocusStack({
|
||||
focusId: getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
component: {
|
||||
type: FocusComponentType.OPENED_FIELD_INPUT,
|
||||
instanceId: getRecordTitleCellId(
|
||||
recordId,
|
||||
fieldMetadataId,
|
||||
containerType,
|
||||
),
|
||||
},
|
||||
hotkeyScope: {
|
||||
scope: TitleInputHotkeyScope.TitleInput,
|
||||
},
|
||||
memoizeKey: INLINE_CELL_HOTKEY_SCOPE_MEMOIZE_KEY,
|
||||
});
|
||||
}
|
||||
@ -98,7 +132,7 @@ export const useRecordTitleCell = () => {
|
||||
fieldComponentInstanceId: recordTitleCellId,
|
||||
});
|
||||
},
|
||||
[initFieldInputDraftValue, setHotkeyScopeAndMemorizePreviousScope],
|
||||
[initFieldInputDraftValue, pushFocusItemToFocusStack],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user