Просмотр исходного кода

Merge pull request #10614 from growilabs/fix/176020-prevent-submission-during-text-composition-in-page-tree

fix: Prevent submission during text composition in PageTree
Yuki Takei 3 месяцев назад
Родитель
Сommit
aa13c4ccb8

+ 10 - 2
apps/app/src/features/page-tree/components/ItemsTree.tsx

@@ -78,8 +78,13 @@ export const ItemsTree: FC<Props> = (props: Props) => {
   const dataLoader = useDataLoader(rootPageId, allPagesCount);
 
   // Tree item handlers (rename, create, etc.) with stable callbacks for headless-tree
-  const { getItemName, isItemFolder, handleRename, creatingParentId } =
-    useTreeItemHandlers(triggerTreeRebuild);
+  const {
+    getItemName,
+    isItemFolder,
+    handleRename,
+    creatingParentId,
+    completeRenamingHotkey,
+  } = useTreeItemHandlers(triggerTreeRebuild);
 
   // Configure tree features and get checkbox state and D&D handlers
   const { features, checkboxProperties, dndProperties } = useTreeFeatures({
@@ -137,6 +142,9 @@ export const ItemsTree: FC<Props> = (props: Props) => {
       onDrop: handleDrop,
       canDropInbetween: false,
     }),
+    hotkeys: {
+      completeRenaming: completeRenamingHotkey,
+    },
   });
 
   // Notify parent when checked items change

+ 35 - 2
apps/app/src/features/page-tree/hooks/_inner/use-tree-item-handlers.tsx

@@ -1,5 +1,9 @@
-import { useCallback, useRef } from 'react';
-import type { ItemInstance, TreeConfig } from '@headless-tree/core';
+import { useCallback, useMemo, useRef } from 'react';
+import type {
+  CustomHotkeysConfig,
+  ItemInstance,
+  TreeConfig,
+} from '@headless-tree/core';
 
 import type { IPageForTreeItem } from '~/interfaces/page';
 
@@ -7,6 +11,9 @@ import { useCreatingParentId } from '../../states/_inner';
 import { usePageCreate } from '../use-page-create';
 import { usePageRename } from '../use-page-rename';
 
+type completeRenamingHotkey =
+  CustomHotkeysConfig<IPageForTreeItem>['completeRenaming'];
+
 type UseTreeItemHandlersReturn = {
   /**
    * Stable callback for headless-tree getItemName config
@@ -28,6 +35,11 @@ type UseTreeItemHandlersReturn = {
    * Current creating parent ID (for tree expansion logic)
    */
   creatingParentId: string | null;
+
+  /**
+   * Hotkeys config to complete renaming
+   */
+  completeRenamingHotkey: completeRenamingHotkey;
 };
 
 /**
@@ -116,10 +128,31 @@ export const useTreeItemHandlers = (
     [],
   );
 
+  // When using IME (e.g., Japanese input), pressing Enter to confirm
+  // the conversion would also trigger this hotkey, completing the rename
+  // prematurely. We check `isComposing` to ignore Enter presses during
+  // IME composition.
+  const completeRenamingHotkey: completeRenamingHotkey = useMemo(
+    () => ({
+      hotkey: 'Enter',
+      allowWhenInputFocused: true,
+      isEnabled: (tree) => tree.isRenamingItem(),
+      handler: (e, tree) => {
+        // Disable rename during IME composition
+        if (e.isComposing) {
+          return;
+        }
+        tree.completeRenaming();
+      },
+    }),
+    [],
+  );
+
   return {
     getItemName,
     isItemFolder,
     handleRename,
     creatingParentId,
+    completeRenamingHotkey,
   };
 };