Przeglądaj źródła

refactor usePageRename hook

Yuki Takei 4 miesięcy temu
rodzic
commit
9df0c5840e

+ 7 - 20
apps/app/src/client/components/Sidebar/PageTreeItem/SimplifiedPageTreeItem.tsx

@@ -1,5 +1,5 @@
 import type { FC } from 'react';
-import { useCallback, useMemo } from 'react';
+import { useCallback } from 'react';
 
 import path from 'path';
 
@@ -10,7 +10,7 @@ import { useTranslation } from 'next-i18next';
 import { useRouter } from 'next/router';
 
 import { toastSuccess } from '~/client/util/toastr';
-import { ROOT_PAGE_VIRTUAL_ID, usePageTreeInformationUpdate, RenameInput } from '~/features/page-tree';
+import { ROOT_PAGE_VIRTUAL_ID, usePageTreeInformationUpdate, usePageRename } from '~/features/page-tree';
 import type { IPageForItem } from '~/interfaces/page';
 import type { OnDeletedFunction, OnDuplicatedFunction } from '~/interfaces/ui';
 import { useCurrentPagePath, useFetchCurrentPage } from '~/states/page';
@@ -21,7 +21,7 @@ import { mutateAllPageInfo } from '~/stores/page';
 import { mutatePageTree, mutatePageList } from '~/stores/page-listing';
 import { mutateSearching } from '~/stores/search';
 
-import type { TreeItemProps, TreeItemToolProps } from '../../TreeItem';
+import type { TreeItemProps } from '../../TreeItem';
 import { TreeItemLayout } from '../../TreeItem';
 
 import { CountBadgeForPageTreeItem } from './CountBadgeForPageTreeItem';
@@ -42,7 +42,6 @@ export const SimplifiedPageTreeItem: FC<TreeItemProps> = ({
   isWipPageShown,
   isEnableActions = false,
   isReadOnlyUser = false,
-  validateName,
   onToggle,
 }) => {
   const { t } = useTranslation();
@@ -106,20 +105,8 @@ export const SimplifiedPageTreeItem: FC<TreeItemProps> = ({
 
   const { Control } = usePageItemControl();
 
-  // Check if item is in renaming mode
-  const isRenaming = item.isRenaming?.() ?? false;
-
-  // Create RenameInput as AlternativeComponent
-  // RenameAlternative component with explicit props validation for 'item'
-  const RenameAlternative: FC<TreeItemToolProps> = useMemo(() => {
-    const RenameAlternativeComponent: FC<{ item: TreeItemToolProps['item'] }> = ({ item: itemInstance }) => (
-      <RenameInput
-        inputProps={itemInstance.getRenameInputProps()}
-        validateName={validateName}
-      />
-    );
-    return RenameAlternativeComponent;
-  }, [validateName]);
+  // Rename feature from usePageRename hook
+  const { isRenaming, RenameAlternativeComponent } = usePageRename();
 
   const itemSelectedHandler = useCallback((page: IPageForItem) => {
     if (page.path == null || page._id == null) return;
@@ -151,8 +138,8 @@ export const SimplifiedPageTreeItem: FC<TreeItemProps> = ({
       onClickDeleteMenuItem={onClickDeleteMenuItem}
       customEndComponents={[CountBadgeForPageTreeItem]}
       customHoveredEndComponents={[Control]}
-      showAlternativeContent={isRenaming}
-      customAlternativeComponents={[RenameAlternative]}
+      showAlternativeContent={isRenaming(item)}
+      customAlternativeComponents={[RenameAlternativeComponent]}
     />
   );
 };

+ 1 - 2
apps/app/src/features/page-tree/client/components/SimplifiedItemsTree.tsx

@@ -55,7 +55,7 @@ export const SimplifiedItemsTree: FC<Props> = (props: Props) => {
   const dataLoader = useDataLoader(rootPageId, allPagesCount);
 
   // Page rename hook
-  const { rename, validateName, getPageName } = usePageRename();
+  const { rename, getPageName } = usePageRename();
 
   // onRename handler for headless-tree
   const handleRename = useCallback(
@@ -150,7 +150,6 @@ export const SimplifiedItemsTree: FC<Props> = (props: Props) => {
               isWipPageShown={isWipPageShown}
               isEnableActions={isEnableActions}
               isReadOnlyUser={isReadOnlyUser}
-              validateName={validateName}
               onToggle={() => {
                 // Trigger re-render to show/hide children
                 setRebuildTrigger((prev) => prev + 1);

+ 34 - 6
apps/app/src/features/page-tree/client/hooks/use-page-rename.ts → apps/app/src/features/page-tree/client/hooks/use-page-rename.tsx

@@ -1,4 +1,5 @@
-import { useCallback } from 'react';
+import type { FC } from 'react';
+import { useCallback, useMemo } from 'react';
 import { pathUtils } from '@growi/core/dist/utils';
 import type { ItemInstance } from '@headless-tree/core';
 import { useTranslation } from 'next-i18next';
@@ -14,6 +15,8 @@ import {
 import type { IPageForItem } from '~/interfaces/page';
 import { mutatePageTree } from '~/stores/page-listing';
 
+import { RenameInput } from '../components/RenameInput';
+import type { TreeItemToolProps } from '../interfaces';
 import { usePageTreeInformationUpdate } from '../states/page-tree-update';
 
 type RenameResult = {
@@ -26,9 +29,6 @@ type RenameResult = {
 type UsePageRenameReturn = {
   /**
    * Rename a page
-   * @param item The item instance from headless-tree
-   * @param newName The new page name (basename only, not full path)
-   * @returns Promise with rename result
    */
   rename: (
     item: ItemInstance<IPageForItem>,
@@ -37,8 +37,6 @@ type UsePageRenameReturn = {
 
   /**
    * Validate page name
-   * @param name The page name to validate
-   * @returns Validation result or null if valid
    */
   validateName: (name: string) => InputValidationResult | null;
 
@@ -46,6 +44,16 @@ type UsePageRenameReturn = {
    * Get the current page name (basename) from item
    */
   getPageName: (item: ItemInstance<IPageForItem>) => string;
+
+  /**
+   * Check if item is in renaming mode
+   */
+  isRenaming: (item: ItemInstance<IPageForItem>) => boolean;
+
+  /**
+   * RenameInput component to use as AlternativeComponent
+   */
+  RenameAlternativeComponent: FC<TreeItemToolProps>;
 };
 
 /**
@@ -73,6 +81,24 @@ export const usePageRename = (): UsePageRenameReturn => {
     [inputValidator],
   );
 
+  const isRenaming = useCallback(
+    (item: ItemInstance<IPageForItem>): boolean => {
+      return item.isRenaming?.() ?? false;
+    },
+    [],
+  );
+
+  // RenameInput as AlternativeComponent
+  const RenameAlternativeComponent: FC<TreeItemToolProps> = useMemo(() => {
+    const Component: FC<TreeItemToolProps> = ({ item }) => (
+      <RenameInput
+        inputProps={item.getRenameInputProps()}
+        validateName={validateName}
+      />
+    );
+    return Component;
+  }, [validateName]);
+
   const rename = useCallback(
     async (
       item: ItemInstance<IPageForItem>,
@@ -129,5 +155,7 @@ export const usePageRename = (): UsePageRenameReturn => {
     rename,
     validateName,
     getPageName,
+    isRenaming,
+    RenameAlternativeComponent,
   };
 };