Replace hotkey scopes by focus stack (Part 6 - Remove Hotkey scopes 🫳🎤) (#13127)
# Replace hotkey scopes by focus stack (Part 6 - Remove Hotkey scopes) This PR is the last part of a refactoring aiming to deprecate the hotkey scopes api in favor of the new focus stack api which is more robust. Part 1: https://github.com/twentyhq/twenty/pull/12673 Part 2: https://github.com/twentyhq/twenty/pull/12798 Part 3: https://github.com/twentyhq/twenty/pull/12910 Part 4: https://github.com/twentyhq/twenty/pull/12933 Part 5: https://github.com/twentyhq/twenty/pull/13106 In this part, we completely remove the hotkey scopes.
This commit is contained in:
@ -8,18 +8,6 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe
|
||||
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
|
||||
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
||||
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
|
||||
const mockGoBackToPreviousHotkeyScope = jest.fn();
|
||||
const mockSetHotkeyScopeAndMemorizePreviousScope = jest.fn();
|
||||
|
||||
jest.mock('@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope', () => ({
|
||||
usePreviousHotkeyScope: () => ({
|
||||
goBackToPreviousHotkeyScope: mockGoBackToPreviousHotkeyScope,
|
||||
setHotkeyScopeAndMemorizePreviousScope:
|
||||
mockSetHotkeyScopeAndMemorizePreviousScope,
|
||||
}),
|
||||
}));
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
@ -71,13 +59,6 @@ describe('useCommandMenu', () => {
|
||||
});
|
||||
|
||||
expect(result.current.isCommandMenuOpened).toBe(true);
|
||||
expect(mockSetHotkeyScopeAndMemorizePreviousScope).toHaveBeenCalledWith({
|
||||
scope: CommandMenuHotkeyScope.CommandMenuFocused,
|
||||
memoizeKey: 'command-menu',
|
||||
customScopes: {
|
||||
commandMenuOpen: true,
|
||||
},
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.commandMenu.closeCommandMenu();
|
||||
@ -96,13 +77,6 @@ describe('useCommandMenu', () => {
|
||||
});
|
||||
|
||||
expect(result.current.isCommandMenuOpened).toBe(true);
|
||||
expect(mockSetHotkeyScopeAndMemorizePreviousScope).toHaveBeenCalledWith({
|
||||
scope: CommandMenuHotkeyScope.CommandMenuFocused,
|
||||
memoizeKey: 'command-menu',
|
||||
customScopes: {
|
||||
commandMenuOpen: true,
|
||||
},
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.commandMenu.toggleCommandMenu();
|
||||
@ -110,21 +84,4 @@ describe('useCommandMenu', () => {
|
||||
|
||||
expect(result.current.isCommandMenuOpened).toBe(false);
|
||||
});
|
||||
|
||||
it('should call goBackToPreviousHotkeyScope when closing the command menu', () => {
|
||||
const { result } = renderHooks();
|
||||
|
||||
act(() => {
|
||||
result.current.commandMenu.openCommandMenu();
|
||||
});
|
||||
|
||||
expect(result.current.isCommandMenuOpened).toBe(true);
|
||||
expect(mockGoBackToPreviousHotkeyScope).not.toHaveBeenCalled();
|
||||
|
||||
act(() => {
|
||||
result.current.commandMenu.closeCommandMenu();
|
||||
});
|
||||
|
||||
expect(mockGoBackToPreviousHotkeyScope).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
@ -6,15 +6,12 @@ import { commandMenuNavigationStackState } from '@/command-menu/states/commandMe
|
||||
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
|
||||
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
||||
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { getShowPageTabListComponentId } from '@/ui/layout/show-page/utils/getShowPageTabListComponentId';
|
||||
import { activeTabIdComponentState } from '@/ui/layout/tab-list/states/activeTabIdComponentState';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCommandMenuHistory = () => {
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const goBackFromCommandMenu = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
@ -69,78 +66,64 @@ export const useCommandMenuHistory = () => {
|
||||
}
|
||||
|
||||
set(hasUserSelectedCommandState, false);
|
||||
|
||||
setHotkeyScope(CommandMenuHotkeyScope.CommandMenuFocused, {
|
||||
commandMenuOpen: true,
|
||||
});
|
||||
};
|
||||
},
|
||||
[closeCommandMenu, setHotkeyScope],
|
||||
[closeCommandMenu],
|
||||
);
|
||||
|
||||
const navigateCommandMenuHistory = useRecoilCallback(
|
||||
({ snapshot, set }) => {
|
||||
return (pageIndex: number) => {
|
||||
const currentNavigationStack = snapshot
|
||||
.getLoadable(commandMenuNavigationStackState)
|
||||
.getValue();
|
||||
const navigateCommandMenuHistory = useRecoilCallback(({ snapshot, set }) => {
|
||||
return (pageIndex: number) => {
|
||||
const currentNavigationStack = snapshot
|
||||
.getLoadable(commandMenuNavigationStackState)
|
||||
.getValue();
|
||||
|
||||
const newNavigationStack = currentNavigationStack.slice(
|
||||
0,
|
||||
pageIndex + 1,
|
||||
const newNavigationStack = currentNavigationStack.slice(0, pageIndex + 1);
|
||||
|
||||
set(commandMenuNavigationStackState, newNavigationStack);
|
||||
|
||||
const newNavigationStackItem = newNavigationStack.at(-1);
|
||||
|
||||
if (!isDefined(newNavigationStackItem)) {
|
||||
throw new Error(
|
||||
`No command menu navigation stack item found for index ${pageIndex}`,
|
||||
);
|
||||
}
|
||||
|
||||
set(commandMenuNavigationStackState, newNavigationStack);
|
||||
set(commandMenuPageState, newNavigationStackItem.page);
|
||||
set(commandMenuPageInfoState, {
|
||||
title: newNavigationStackItem.pageTitle,
|
||||
Icon: newNavigationStackItem.pageIcon,
|
||||
instanceId: newNavigationStackItem.pageId,
|
||||
});
|
||||
const currentMorphItems = snapshot
|
||||
.getLoadable(commandMenuNavigationMorphItemByPageState)
|
||||
.getValue();
|
||||
|
||||
const newNavigationStackItem = newNavigationStack.at(-1);
|
||||
|
||||
if (!isDefined(newNavigationStackItem)) {
|
||||
throw new Error(
|
||||
`No command menu navigation stack item found for index ${pageIndex}`,
|
||||
for (const [pageId, morphItem] of currentMorphItems.entries()) {
|
||||
if (!newNavigationStack.some((item) => item.pageId === pageId)) {
|
||||
set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId,
|
||||
targetObjectId: morphItem.recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
set(commandMenuPageState, newNavigationStackItem.page);
|
||||
set(commandMenuPageInfoState, {
|
||||
title: newNavigationStackItem.pageTitle,
|
||||
Icon: newNavigationStackItem.pageIcon,
|
||||
instanceId: newNavigationStackItem.pageId,
|
||||
});
|
||||
const currentMorphItems = snapshot
|
||||
.getLoadable(commandMenuNavigationMorphItemByPageState)
|
||||
.getValue();
|
||||
const newMorphItems = new Map(
|
||||
Array.from(currentMorphItems.entries()).filter(([pageId]) =>
|
||||
newNavigationStack.some((item) => item.pageId === pageId),
|
||||
),
|
||||
);
|
||||
|
||||
for (const [pageId, morphItem] of currentMorphItems.entries()) {
|
||||
if (!newNavigationStack.some((item) => item.pageId === pageId)) {
|
||||
set(
|
||||
activeTabIdComponentState.atomFamily({
|
||||
instanceId: getShowPageTabListComponentId({
|
||||
pageId,
|
||||
targetObjectId: morphItem.recordId,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
);
|
||||
}
|
||||
}
|
||||
set(commandMenuNavigationMorphItemByPageState, newMorphItems);
|
||||
|
||||
const newMorphItems = new Map(
|
||||
Array.from(currentMorphItems.entries()).filter(([pageId]) =>
|
||||
newNavigationStack.some((item) => item.pageId === pageId),
|
||||
),
|
||||
);
|
||||
|
||||
set(commandMenuNavigationMorphItemByPageState, newMorphItems);
|
||||
|
||||
set(hasUserSelectedCommandState, false);
|
||||
|
||||
setHotkeyScope(CommandMenuHotkeyScope.CommandMenuFocused, {
|
||||
commandMenuOpen: true,
|
||||
});
|
||||
};
|
||||
},
|
||||
[setHotkeyScope],
|
||||
);
|
||||
set(hasUserSelectedCommandState, false);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return {
|
||||
goBackFromCommandMenu,
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
|
||||
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
|
||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||
import { useCommandMenuHistory } from '@/command-menu/hooks/useCommandMenuHistory';
|
||||
import { useOpenRecordsSearchPageInCommandMenu } from '@/command-menu/hooks/useOpenRecordsSearchPageInCommandMenu';
|
||||
import { useSetGlobalCommandMenuContext } from '@/command-menu/hooks/useSetGlobalCommandMenuContext';
|
||||
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
|
||||
import { commandMenuSearchState } from '@/command-menu/states/commandMenuSearchState';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
|
||||
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
||||
import { useGlobalHotkeys } from '@/ui/utilities/hotkey/hooks/useGlobalHotkeys';
|
||||
import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope';
|
||||
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@ -43,7 +43,6 @@ export const useCommandMenuHotKeys = () => {
|
||||
toggleCommandMenu();
|
||||
},
|
||||
true,
|
||||
AppHotkeyScope.CommandMenu,
|
||||
[closeKeyboardShortcutMenu, toggleCommandMenu],
|
||||
);
|
||||
|
||||
@ -53,26 +52,24 @@ export const useCommandMenuHotKeys = () => {
|
||||
openRecordsSearchPage();
|
||||
},
|
||||
false,
|
||||
AppHotkeyScope.SearchRecords,
|
||||
[openRecordsSearchPage],
|
||||
{
|
||||
ignoreModifiers: true,
|
||||
},
|
||||
);
|
||||
|
||||
useGlobalHotkeys(
|
||||
[Key.Escape],
|
||||
() => {
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: [Key.Escape],
|
||||
callback: () => {
|
||||
goBackFromCommandMenu();
|
||||
},
|
||||
true,
|
||||
CommandMenuHotkeyScope.CommandMenuFocused,
|
||||
[goBackFromCommandMenu],
|
||||
);
|
||||
focusId: SIDE_PANEL_FOCUS_ID,
|
||||
dependencies: [goBackFromCommandMenu],
|
||||
});
|
||||
|
||||
useGlobalHotkeys(
|
||||
[Key.Backspace, Key.Delete],
|
||||
() => {
|
||||
useHotkeysOnFocusedElement({
|
||||
keys: [Key.Backspace, Key.Delete],
|
||||
callback: () => {
|
||||
if (isNonEmptyString(commandMenuSearch)) {
|
||||
return;
|
||||
}
|
||||
@ -91,17 +88,13 @@ export const useCommandMenuHotKeys = () => {
|
||||
goBackFromCommandMenu();
|
||||
}
|
||||
},
|
||||
true,
|
||||
CommandMenuHotkeyScope.CommandMenuFocused,
|
||||
[
|
||||
focusId: SIDE_PANEL_FOCUS_ID,
|
||||
dependencies: [
|
||||
commandMenuPage,
|
||||
commandMenuSearch,
|
||||
contextStoreTargetedRecordsRuleComponent,
|
||||
goBackFromCommandMenu,
|
||||
setGlobalCommandMenuContext,
|
||||
],
|
||||
{
|
||||
preventDefault: false,
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@ -10,7 +10,6 @@ import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState
|
||||
import { hasUserSelectedCommandState } from '@/command-menu/states/hasUserSelectedCommandState';
|
||||
import { isCommandMenuClosingState } from '@/command-menu/states/isCommandMenuClosingState';
|
||||
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
|
||||
import { CommandMenuHotkeyScope } from '@/command-menu/types/CommandMenuHotkeyScope';
|
||||
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { isDragSelectionStartEnabledState } from '@/ui/utilities/drag-select/states/internal/isDragSelectionStartEnabledState';
|
||||
@ -61,13 +60,9 @@ export const useNavigateCommandMenu = () => {
|
||||
type: FocusComponentType.SIDE_PANEL,
|
||||
instanceId: COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
},
|
||||
hotkeyScope: {
|
||||
scope: CommandMenuHotkeyScope.CommandMenuFocused,
|
||||
customScopes: {
|
||||
commandMenuOpen: true,
|
||||
},
|
||||
globalHotkeysConfig: {
|
||||
enableGlobalHotkeysConflictingWithKeyboard: false,
|
||||
},
|
||||
memoizeKey: COMMAND_MENU_COMPONENT_INSTANCE_ID,
|
||||
});
|
||||
|
||||
copyContextStoreStates({
|
||||
|
||||
Reference in New Issue
Block a user