refactor(core): rename explorer to navigation-panel (#11876)

This commit is contained in:
EYHN
2025-04-22 12:47:35 +08:00
committed by GitHub
parent f918573ba8
commit e4d6833296
104 changed files with 913 additions and 769 deletions

View File

@@ -1,5 +0,0 @@
export { CollapsibleSection } from './layouts/collapsible-section';
export { ExplorerCollections } from './sections/collections';
export { ExplorerFavorites } from './sections/favorites';
export { ExplorerOrganize } from './sections/organize';
export { ExplorerTags } from './sections/tags';

View File

@@ -0,0 +1,5 @@
export { CollapsibleSection } from './layouts/collapsible-section';
export { NavigationPanelCollections } from './sections/collections';
export { NavigationPanelFavorites } from './sections/favorites';
export { NavigationPanelOrganize } from './sections/organize';
export { NavigationPanelTags } from './sections/tags';

View File

@@ -1,4 +1,4 @@
import { ExplorerTreeContext } from '@affine/core/modules/explorer';
import { NavigationPanelTreeContext } from '@affine/core/desktop/components/navigation-panel';
import { PlusIcon } from '@blocksuite/icons/rc';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
@@ -21,7 +21,7 @@ export const AddItemPlaceholder = ({
className,
...attrs
}: AddItemPlaceholderProps) => {
const context = useContext(ExplorerTreeContext);
const context = useContext(NavigationPanelTreeContext);
const level = context?.level ?? 0;
return (

View File

@@ -1,7 +1,7 @@
import {
type CollapsibleSectionName,
ExplorerService,
} from '@affine/core/modules/explorer';
NavigationPanelService,
} from '@affine/core/modules/navigation-panel';
import { ToggleRightIcon } from '@blocksuite/icons/rc';
import * as Collapsible from '@radix-ui/react-collapsible';
import { useLiveData, useService } from '@toeverything/infra';
@@ -86,7 +86,7 @@ export const CollapsibleSection = ({
children,
...attrs
}: CollapsibleSectionProps) => {
const section = useService(ExplorerService).sections[name];
const section = useService(NavigationPanelService).sections[name];
const collapsed = useLiveData(section.collapsed$);
const setCollapsed = useCallback(

View File

@@ -1,9 +1,9 @@
import { MenuItem, notify } from '@affine/component';
import { filterPage } from '@affine/core/components/page-list';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { CollectionService } from '@affine/core/modules/collection';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { DocsService } from '@affine/core/modules/doc';
import type { NodeOperation } from '@affine/core/modules/explorer';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { ShareDocsListService } from '@affine/core/modules/share-doc';
@@ -17,16 +17,16 @@ import { LiveData, useLiveData, useServices } from '@toeverything/infra';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { ExplorerTreeNode } from '../../tree/node';
import { ExplorerDocNode } from '../doc';
import { NavigationPanelTreeNode } from '../../tree/node';
import { NavigationPanelDocNode } from '../doc';
import {
useExplorerCollectionNodeOperations,
useExplorerCollectionNodeOperationsMenu,
useNavigationPanelCollectionNodeOperations,
useNavigationPanelCollectionNodeOperationsMenu,
} from './operations';
const CollectionIcon = () => <ViewLayersIcon />;
export const ExplorerCollectionNode = ({
export const NavigationPanelCollectionNode = ({
collectionId,
operations: additionalOperations,
}: {
@@ -60,16 +60,17 @@ export const ExplorerCollectionNode = ({
});
}, [collection, workspaceDialogService]);
const collectionOperations = useExplorerCollectionNodeOperationsMenu(
collectionId,
handleOpenCollapsed,
handleEditCollection
);
const { handleAddDocToCollection } = useExplorerCollectionNodeOperations(
const collectionOperations = useNavigationPanelCollectionNodeOperationsMenu(
collectionId,
handleOpenCollapsed,
handleEditCollection
);
const { handleAddDocToCollection } =
useNavigationPanelCollectionNodeOperations(
collectionId,
handleOpenCollapsed,
handleEditCollection
);
const finalOperations = useMemo(() => {
if (additionalOperations) {
@@ -83,7 +84,7 @@ export const ExplorerCollectionNode = ({
}
return (
<ExplorerTreeNode
<NavigationPanelTreeNode
icon={CollectionIcon}
name={collection.name || t['Untitled']()}
collapsed={collapsed}
@@ -91,17 +92,17 @@ export const ExplorerCollectionNode = ({
to={`/collection/${collection.id}`}
active={active}
operations={finalOperations}
data-testid={`explorer-collection-${collectionId}`}
data-testid={`navigation-panel-collection-${collectionId}`}
>
<ExplorerCollectionNodeChildren
<NavigationPanelCollectionNodeChildren
collection={collection}
onAddDoc={handleAddDocToCollection}
/>
</ExplorerTreeNode>
</NavigationPanelTreeNode>
);
};
const ExplorerCollectionNodeChildren = ({
const NavigationPanelCollectionNodeChildren = ({
collection,
onAddDoc,
}: {
@@ -174,7 +175,7 @@ const ExplorerCollectionNodeChildren = ({
return (
<>
{filtered.map(doc => (
<ExplorerDocNode
<NavigationPanelDocNode
key={doc.id}
docId={doc.id}
operations={

View File

@@ -8,8 +8,8 @@ import {
import { usePageHelper } from '@affine/core/blocksuite/block-suite-page-list/utils';
import { useDeleteCollectionInfo } from '@affine/core/components/hooks/affine/use-delete-collection-info';
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { CollectionService } from '@affine/core/modules/collection';
import type { NodeOperation } from '@affine/core/modules/explorer';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
import { WorkbenchService } from '@affine/core/modules/workbench';
import { WorkspaceService } from '@affine/core/modules/workspace';
@@ -27,7 +27,7 @@ import { useCallback, useMemo } from 'react';
import { CollectionRenameSubMenu } from './dialog';
export const useExplorerCollectionNodeOperations = (
export const useNavigationPanelCollectionNodeOperations = (
collectionId: string,
onOpenCollapsed: () => void,
onOpenEdit: () => void
@@ -154,7 +154,7 @@ export const useExplorerCollectionNodeOperations = (
);
};
export const useExplorerCollectionNodeOperationsMenu = (
export const useNavigationPanelCollectionNodeOperationsMenu = (
collectionId: string,
onOpenCollapsed: () => void,
onOpenEdit: () => void
@@ -170,7 +170,7 @@ export const useExplorerCollectionNodeOperationsMenu = (
handleShowEdit,
handleToggleFavoriteCollection,
handleRename,
} = useExplorerCollectionNodeOperations(
} = useNavigationPanelCollectionNodeOperations(
collectionId,
onOpenCollapsed,
onOpenEdit

View File

@@ -1,10 +1,10 @@
import { Loading } from '@affine/component';
import { Guard } from '@affine/core/components/guard';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { DocsService } from '@affine/core/modules/doc';
import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
import { DocsSearchService } from '@affine/core/modules/docs-search';
import type { NodeOperation } from '@affine/core/modules/explorer';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { useI18n } from '@affine/i18n';
@@ -18,14 +18,14 @@ import {
import { useCallback, useLayoutEffect, useMemo, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { ExplorerTreeNode } from '../../tree/node';
import { NavigationPanelTreeNode } from '../../tree/node';
import {
useExplorerDocNodeOperations,
useExplorerDocNodeOperationsMenu,
useNavigationPanelDocNodeOperations,
useNavigationPanelDocNodeOperationsMenu,
} from './operations';
import * as styles from './styles.css';
export const ExplorerDocNode = ({
export const NavigationPanelDocNode = ({
docId,
isLinked,
operations: additionalOperations,
@@ -105,8 +105,11 @@ export const ExplorerDocNode = ({
}),
[docId, workspaceDialogService]
);
const operations = useExplorerDocNodeOperationsMenu(docId, option);
const { handleAddLinkedPage } = useExplorerDocNodeOperations(docId, option);
const operations = useNavigationPanelDocNodeOperationsMenu(docId, option);
const { handleAddLinkedPage } = useNavigationPanelDocNodeOperations(
docId,
option
);
const finalOperations = useMemo(() => {
if (additionalOperations) {
@@ -120,7 +123,7 @@ export const ExplorerDocNode = ({
}
return (
<ExplorerTreeNode
<NavigationPanelTreeNode
icon={Icon}
name={t.t(docTitle)}
extractEmojiAsIcon={enableEmojiIcon}
@@ -137,13 +140,13 @@ export const ExplorerDocNode = ({
)
}
operations={finalOperations}
data-testid={`explorer-doc-${docId}`}
data-testid={`navigation-panel-doc-${docId}`}
>
<Guard docId={docId} permission="Doc_Read">
{canRead =>
canRead
? children?.map((child, index) => (
<ExplorerDocNode
<NavigationPanelDocNode
key={`${child.docId}-${index}`}
docId={child.docId}
isLinked
@@ -162,6 +165,6 @@ export const ExplorerDocNode = ({
) : null
}
</Guard>
</ExplorerTreeNode>
</NavigationPanelTreeNode>
);
};

View File

@@ -10,8 +10,8 @@ import { Guard } from '@affine/core/components/guard';
import { useBlockSuiteMetaHelper } from '@affine/core/components/hooks/affine/use-block-suite-meta-helper';
import { useAsyncCallback } from '@affine/core/components/hooks/affine-async-hooks';
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { DocsService } from '@affine/core/modules/doc';
import type { NodeOperation } from '@affine/core/modules/explorer';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
import { WorkbenchService } from '@affine/core/modules/workbench';
import { WorkspaceService } from '@affine/core/modules/workspace';
@@ -31,7 +31,7 @@ import { useCallback, useMemo } from 'react';
import { DocFrameScope, DocInfoSheet } from '../../../doc-info';
import { DocRenameSubMenu } from './dialog';
export const useExplorerDocNodeOperations = (
export const useNavigationPanelDocNodeOperations = (
docId: string,
options: {
openNodeCollapsed: () => void;
@@ -160,7 +160,7 @@ export const useExplorerDocNodeOperations = (
);
};
export const useExplorerDocNodeOperationsMenu = (
export const useNavigationPanelDocNodeOperationsMenu = (
docId: string,
options: {
openInfoModal: () => void;
@@ -176,7 +176,7 @@ export const useExplorerDocNodeOperationsMenu = (
handleOpenInNewTab,
handleMoveToTrash,
handleRename,
} = useExplorerDocNodeOperations(docId, options);
} = useNavigationPanelDocNodeOperations(docId, options);
const docService = useService(DocsService);
const docRecord = useLiveData(docService.list.doc$(docId));

View File

@@ -7,11 +7,11 @@ import {
notify,
} from '@affine/component';
import { usePageHelper } from '@affine/core/blocksuite/block-suite-page-list/utils';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import type {
ExplorerTreeNodeIcon,
NavigationPanelTreeNodeIcon,
NodeOperation,
} from '@affine/core/modules/explorer';
} from '@affine/core/desktop/components/navigation-panel';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import {
@@ -36,14 +36,14 @@ import { difference } from 'lodash-es';
import { useCallback, useMemo, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { ExplorerTreeNode } from '../../tree/node';
import { ExplorerCollectionNode } from '../collection';
import { ExplorerDocNode } from '../doc';
import { ExplorerTagNode } from '../tag';
import { NavigationPanelTreeNode } from '../../tree/node';
import { NavigationPanelCollectionNode } from '../collection';
import { NavigationPanelDocNode } from '../doc';
import { NavigationPanelTagNode } from '../tag';
import { FolderCreateTip, FolderRenameSubMenu } from './dialog';
import { FavoriteFolderOperation } from './operations';
export const ExplorerFolderNode = ({
export const NavigationPanelFolderNode = ({
nodeId,
operations,
}: {
@@ -75,27 +75,34 @@ export const ExplorerFolderNode = ({
if (type === 'folder') {
return (
<ExplorerFolderNodeFolder node={node} operations={additionalOperations} />
<NavigationPanelFolderNodeFolder
node={node}
operations={additionalOperations}
/>
);
}
if (!data) return null;
if (type === 'doc') {
return <ExplorerDocNode docId={data} operations={additionalOperations} />;
return (
<NavigationPanelDocNode docId={data} operations={additionalOperations} />
);
} else if (type === 'collection') {
return (
<ExplorerCollectionNode
<NavigationPanelCollectionNode
collectionId={data}
operations={additionalOperations}
/>
);
} else if (type === 'tag') {
return <ExplorerTagNode tagId={data} operations={additionalOperations} />;
return (
<NavigationPanelTagNode tagId={data} operations={additionalOperations} />
);
}
return;
};
const ExplorerFolderIcon: ExplorerTreeNodeIcon = ({
const NavigationPanelFolderIcon: NavigationPanelTreeNodeIcon = ({
collapsed,
className,
draggedOver,
@@ -109,7 +116,7 @@ const ExplorerFolderIcon: ExplorerTreeNodeIcon = ({
/>
);
const ExplorerFolderNodeFolder = ({
const NavigationPanelFolderNodeFolder = ({
node,
operations: additionalOperations,
}: {
@@ -390,19 +397,19 @@ const ExplorerFolderNodeFolder = ({
}, []);
return (
<ExplorerTreeNode
icon={ExplorerFolderIcon}
<NavigationPanelTreeNode
icon={NavigationPanelFolderIcon}
name={name}
extractEmojiAsIcon={enableEmojiIcon}
collapsed={collapsed}
setCollapsed={handleCollapsedChange}
operations={finalOperations}
data-testid={`explorer-folder-${node.id}`}
data-testid={`navigation-panel-folder-${node.id}`}
aria-label={name}
data-role="explorer-folder"
data-role="navigation-panel-folder"
>
{children.map(child => (
<ExplorerFolderNode
<NavigationPanelFolderNode
key={child.id}
nodeId={child.id as string}
operations={childrenOperations}
@@ -413,6 +420,6 @@ const ExplorerFolderNodeFolder = ({
onClick={handleNewDoc}
data-testid="new-folder-in-folder-button"
/>
</ExplorerTreeNode>
</NavigationPanelTreeNode>
);
};

View File

@@ -1,4 +1,4 @@
import type { NodeOperation } from '@affine/core/modules/explorer';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { GlobalContextService } from '@affine/core/modules/global-context';
import type { Tag } from '@affine/core/modules/tag';
import { TagService } from '@affine/core/modules/tag';
@@ -8,15 +8,15 @@ import clsx from 'clsx';
import { useCallback, useMemo, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { ExplorerTreeNode } from '../../tree/node';
import { ExplorerDocNode } from '../doc';
import { NavigationPanelTreeNode } from '../../tree/node';
import { NavigationPanelDocNode } from '../doc';
import {
useExplorerTagNodeOperations,
useExplorerTagNodeOperationsMenu,
useNavigationPanelTagNodeOperations,
useNavigationPanelTagNodeOperationsMenu,
} from './operations';
import * as styles from './styles.css';
export const ExplorerTagNode = ({
export const NavigationPanelTagNode = ({
tagId,
operations: additionalOperations,
}: {
@@ -41,7 +41,7 @@ export const ExplorerTagNode = ({
return (
<div className={clsx(styles.tagIconContainer, className)}>
<div
data-testid="explorer-tag-icon-dot"
data-testid="navigation-panel-tag-icon-dot"
className={styles.tagIcon}
style={{
backgroundColor: tagColor,
@@ -59,8 +59,8 @@ export const ExplorerTagNode = ({
}),
[]
);
const operations = useExplorerTagNodeOperationsMenu(tagId, option);
const { handleNewDoc } = useExplorerTagNodeOperations(tagId, option);
const operations = useNavigationPanelTagNodeOperationsMenu(tagId, option);
const { handleNewDoc } = useNavigationPanelTagNodeOperations(tagId, option);
const finalOperations = useMemo(() => {
if (additionalOperations) {
@@ -74,7 +74,7 @@ export const ExplorerTagNode = ({
}
return (
<ExplorerTreeNode
<NavigationPanelTreeNode
icon={Icon}
name={tagName || t['Untitled']()}
collapsed={collapsed}
@@ -82,12 +82,12 @@ export const ExplorerTagNode = ({
to={`/tag/${tagId}`}
active={active}
operations={finalOperations}
data-testid={`explorer-tag-${tagId}`}
data-testid={`navigation-panel-tag-${tagId}`}
aria-label={tagName}
data-role="explorer-tag"
data-role="navigation-panel-tag"
>
<ExplorerTagNodeDocs tag={tagRecord} onNewDoc={handleNewDoc} />
</ExplorerTreeNode>
<NavigationPanelTagNodeDocs tag={tagRecord} onNewDoc={handleNewDoc} />
</NavigationPanelTreeNode>
);
};
@@ -96,7 +96,7 @@ export const ExplorerTagNode = ({
* so we split the tag node children into a separate component,
* so it won't be rendered when the tag node is collapsed.
*/
export const ExplorerTagNodeDocs = ({
export const NavigationPanelTagNodeDocs = ({
tag,
onNewDoc,
}: {
@@ -109,7 +109,7 @@ export const ExplorerTagNodeDocs = ({
return (
<>
{tagDocIds.map(docId => (
<ExplorerDocNode key={docId} docId={docId} />
<NavigationPanelDocNode key={docId} docId={docId} />
))}
<AddItemPlaceholder label={t['New Page']()} onClick={onNewDoc} />
</>

View File

@@ -7,9 +7,9 @@ import {
} from '@affine/component';
import { usePageHelper } from '@affine/core/blocksuite/block-suite-page-list/utils';
import { IsFavoriteIcon } from '@affine/core/components/pure/icons';
import type { NodeOperation } from '@affine/core/desktop/components/navigation-panel';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { DocsService } from '@affine/core/modules/doc';
import type { NodeOperation } from '@affine/core/modules/explorer';
import { FavoriteService } from '@affine/core/modules/favorite';
import { GlobalCacheService } from '@affine/core/modules/storage';
import { TagService } from '@affine/core/modules/tag';
@@ -28,7 +28,7 @@ import { useCallback, useMemo } from 'react';
import { TagRenameSubMenu } from './dialog';
export const useExplorerTagNodeOperations = (
export const useNavigationPanelTagNodeOperations = (
tagId: string,
{
openNodeCollapsed,
@@ -211,7 +211,7 @@ export const useExplorerTagNodeOperations = (
]
);
};
export const useExplorerTagNodeOperationsMenu = (
export const useNavigationPanelTagNodeOperationsMenu = (
tagId: string,
option: {
openNodeCollapsed: () => void;
@@ -226,7 +226,7 @@ export const useExplorerTagNodeOperationsMenu = (
handleToggleFavoriteTag,
handleChangeNameOrColor,
handleOpenDocSelector,
} = useExplorerTagNodeOperations(tagId, option);
} = useNavigationPanelTagNodeOperations(tagId, option);
return useMemo(
() => [

View File

@@ -1,8 +1,8 @@
import { usePromptModal } from '@affine/component';
import { createEmptyCollection } from '@affine/core/components/page-list/use-collection-manager';
import { NavigationPanelTreeRoot } from '@affine/core/desktop/components/navigation-panel';
import { CollectionService } from '@affine/core/modules/collection';
import { ExplorerService } from '@affine/core/modules/explorer';
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import { WorkbenchService } from '@affine/core/modules/workbench';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
@@ -13,17 +13,18 @@ import { useCallback } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { ExplorerCollectionNode } from '../../nodes/collection';
import { NavigationPanelCollectionNode } from '../../nodes/collection';
import * as styles from './index.css';
export const ExplorerCollections = () => {
export const NavigationPanelCollections = () => {
const t = useI18n();
const { collectionService, workbenchService, explorerService } = useServices({
CollectionService,
WorkbenchService,
ExplorerService,
});
const explorerSection = explorerService.sections.collections;
const { collectionService, workbenchService, navigationPanelService } =
useServices({
CollectionService,
WorkbenchService,
NavigationPanelService,
});
const navigationPanelSection = navigationPanelService.sections.collections;
const collections = useLiveData(collectionService.collections$);
const { openPromptModal } = usePromptModal();
@@ -51,12 +52,12 @@ export const ExplorerCollections = () => {
type: 'collection',
});
workbenchService.workbench.openCollection(id);
explorerSection.setCollapsed(false);
navigationPanelSection.setCollapsed(false);
},
});
}, [
collectionService,
explorerSection,
navigationPanelSection,
openPromptModal,
t,
workbenchService.workbench,
@@ -65,23 +66,23 @@ export const ExplorerCollections = () => {
return (
<CollapsibleSection
name="collections"
testId="explorer-collections"
testId="navigation-panel-collections"
title={t['com.affine.rootAppSidebar.collections']()}
>
<ExplorerTreeRoot>
<NavigationPanelTreeRoot>
{collections.map(collection => (
<ExplorerCollectionNode
<NavigationPanelCollectionNode
key={collection.id}
collectionId={collection.id}
/>
))}
<AddItemPlaceholder
icon={<AddCollectionIcon />}
data-testid="explorer-bar-add-collection-button"
data-testid="navigation-panel-bar-add-collection-button"
label={t['com.affine.rootAppSidebar.collection.new']()}
onClick={() => handleCreateCollection()}
/>
</ExplorerTreeRoot>
</NavigationPanelTreeRoot>
</CollapsibleSection>
);
};

View File

@@ -1,10 +1,8 @@
import { usePageHelper } from '@affine/core/blocksuite/block-suite-page-list/utils';
import {
ExplorerService,
ExplorerTreeRoot,
} from '@affine/core/modules/explorer';
import { NavigationPanelTreeRoot } from '@affine/core/desktop/components/navigation-panel';
import type { FavoriteSupportTypeUnion } from '@affine/core/modules/favorite';
import { FavoriteService } from '@affine/core/modules/favorite';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import { WorkspaceService } from '@affine/core/modules/workspace';
import { useI18n } from '@affine/i18n';
import { useLiveData, useServices } from '@toeverything/infra';
@@ -12,20 +10,21 @@ import { useCallback } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { ExplorerCollectionNode } from '../../nodes/collection';
import { ExplorerDocNode } from '../../nodes/doc';
import { ExplorerFolderNode } from '../../nodes/folder';
import { ExplorerTagNode } from '../../nodes/tag';
import { NavigationPanelCollectionNode } from '../../nodes/collection';
import { NavigationPanelDocNode } from '../../nodes/doc';
import { NavigationPanelFolderNode } from '../../nodes/folder';
import { NavigationPanelTagNode } from '../../nodes/tag';
export const ExplorerFavorites = () => {
const { favoriteService, workspaceService, explorerService } = useServices({
FavoriteService,
WorkspaceService,
ExplorerService,
});
export const NavigationPanelFavorites = () => {
const { favoriteService, workspaceService, navigationPanelService } =
useServices({
FavoriteService,
WorkspaceService,
NavigationPanelService,
});
const t = useI18n();
const explorerSection = explorerService.sections.favorites;
const navigationPanelSection = navigationPanelService.sections.favorites;
const favorites = useLiveData(favoriteService.favoriteList.sortedList$);
const isLoading = useLiveData(favoriteService.favoriteList.isLoading$);
const { createPage } = usePageHelper(
@@ -39,28 +38,28 @@ export const ExplorerFavorites = () => {
newDoc.id,
favoriteService.favoriteList.indexAt('before')
);
explorerSection.setCollapsed(false);
}, [createPage, explorerSection, favoriteService.favoriteList]);
navigationPanelSection.setCollapsed(false);
}, [createPage, navigationPanelSection, favoriteService.favoriteList]);
return (
<CollapsibleSection
name="favorites"
title={t['com.affine.rootAppSidebar.favorites']()}
testId="explorer-favorites"
headerTestId="explorer-favorite-category-divider"
testId="navigation-panel-favorites"
headerTestId="navigation-panel-favorite-category-divider"
>
<ExplorerTreeRoot placeholder={isLoading ? 'Loading' : null}>
<NavigationPanelTreeRoot placeholder={isLoading ? 'Loading' : null}>
{favorites.map(favorite => (
<FavoriteNode key={favorite.id} favorite={favorite} />
))}
<AddItemPlaceholder
data-testid="explorer-bar-add-favorite-button"
data-testid="navigation-panel-bar-add-favorite-button"
data-event-props="$.navigationPanel.favorites.createDoc"
data-event-args-control="addFavorite"
onClick={handleCreateNewFavoriteDoc}
label={t['New Page']()}
/>
</ExplorerTreeRoot>
</NavigationPanelTreeRoot>
</CollapsibleSection>
);
};
@@ -74,12 +73,12 @@ export const FavoriteNode = ({
};
}) => {
return favorite.type === 'doc' ? (
<ExplorerDocNode docId={favorite.id} />
<NavigationPanelDocNode docId={favorite.id} />
) : favorite.type === 'tag' ? (
<ExplorerTagNode tagId={favorite.id} />
<NavigationPanelTagNode tagId={favorite.id} />
) : favorite.type === 'folder' ? (
<ExplorerFolderNode nodeId={favorite.id} />
<NavigationPanelFolderNode nodeId={favorite.id} />
) : (
<ExplorerCollectionNode collectionId={favorite.id} />
<NavigationPanelCollectionNode collectionId={favorite.id} />
);
};

View File

@@ -1,8 +1,6 @@
import { Skeleton } from '@affine/component';
import {
ExplorerService,
ExplorerTreeRoot,
} from '@affine/core/modules/explorer';
import { NavigationPanelTreeRoot } from '@affine/core/desktop/components/navigation-panel';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import { OrganizeService } from '@affine/core/modules/organize';
import { useI18n } from '@affine/i18n';
import track from '@affine/track';
@@ -12,15 +10,15 @@ import { useCallback, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { ExplorerFolderNode } from '../../nodes/folder';
import { NavigationPanelFolderNode } from '../../nodes/folder';
import { FolderCreateTip, FolderRenameDialog } from '../../nodes/folder/dialog';
export const ExplorerOrganize = () => {
const { organizeService, explorerService } = useServices({
export const NavigationPanelOrganize = () => {
const { organizeService, navigationPanelService } = useServices({
OrganizeService,
ExplorerService,
NavigationPanelService,
});
const explorerSection = explorerService.sections.organize;
const navigationPanelSection = navigationPanelService.sections.organize;
const [openNewFolderDialog, setOpenNewFolderDialog] = useState(false);
const t = useI18n();
@@ -38,10 +36,10 @@ export const ExplorerOrganize = () => {
rootFolder.indexAt('before')
);
track.$.navigationPanel.organize.createOrganizeItem({ type: 'folder' });
explorerSection.setCollapsed(false);
navigationPanelSection.setCollapsed(false);
return newFolderId;
},
[explorerSection, rootFolder]
[navigationPanelSection, rootFolder]
);
return (
@@ -50,17 +48,20 @@ export const ExplorerOrganize = () => {
title={t['com.affine.rootAppSidebar.organize']()}
>
{/* TODO(@CatsJuice): Organize loading UI */}
<ExplorerTreeRoot placeholder={isLoading ? <Skeleton /> : null}>
<NavigationPanelTreeRoot placeholder={isLoading ? <Skeleton /> : null}>
{folders.map(child => (
<ExplorerFolderNode key={child.id} nodeId={child.id as string} />
<NavigationPanelFolderNode
key={child.id}
nodeId={child.id as string}
/>
))}
<AddItemPlaceholder
icon={<AddOrganizeIcon />}
data-testid="explorer-bar-add-organize-button"
data-testid="navigation-panel-bar-add-organize-button"
label={t['com.affine.rootAppSidebar.organize.add-folder']()}
onClick={() => setOpenNewFolderDialog(true)}
/>
</ExplorerTreeRoot>
</NavigationPanelTreeRoot>
<FolderRenameDialog
open={openNewFolderDialog}
onConfirm={handleCreateFolder}

View File

@@ -1,5 +1,5 @@
import { ExplorerService } from '@affine/core/modules/explorer';
import { ExplorerTreeRoot } from '@affine/core/modules/explorer/views/tree';
import { NavigationPanelTreeRoot } from '@affine/core/desktop/components/navigation-panel';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import { TagService } from '@affine/core/modules/tag';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
@@ -9,7 +9,7 @@ import { useCallback, useState } from 'react';
import { AddItemPlaceholder } from '../../layouts/add-item-placeholder';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { ExplorerTagNode } from '../../nodes/tag';
import { NavigationPanelTagNode } from '../../nodes/tag';
import { TagRenameDialog } from '../../nodes/tag/dialog';
export const TagDesc = ({ input }: { input: string }) => {
@@ -20,12 +20,12 @@ export const TagDesc = ({ input }: { input: string }) => {
: t['com.affine.m.explorer.tag.new-tip-empty']();
};
export const ExplorerTags = () => {
const { tagService, explorerService } = useServices({
export const NavigationPanelTags = () => {
const { tagService, navigationPanelService } = useServices({
TagService,
ExplorerService,
NavigationPanelService,
});
const explorerSection = explorerService.sections.tags;
const navigationPanelSection = navigationPanelService.sections.tags;
const tags = useLiveData(tagService.tagList.tags$);
const [showNewTagDialog, setShowNewTagDialog] = useState(false);
@@ -36,9 +36,9 @@ export const ExplorerTags = () => {
setShowNewTagDialog(false);
tagService.tagList.createTag(name, color);
track.$.navigationPanel.organize.createOrganizeItem({ type: 'tag' });
explorerSection.setCollapsed(false);
navigationPanelSection.setCollapsed(false);
},
[explorerSection, tagService]
[navigationPanelSection, tagService]
);
return (
@@ -46,13 +46,13 @@ export const ExplorerTags = () => {
name="tags"
title={t['com.affine.rootAppSidebar.tags']()}
>
<ExplorerTreeRoot>
<NavigationPanelTreeRoot>
{tags.map(tag => (
<ExplorerTagNode key={tag.id} tagId={tag.id} />
<NavigationPanelTagNode key={tag.id} tagId={tag.id} />
))}
<AddItemPlaceholder
icon={<AddTagIcon />}
data-testid="explorer-add-tag-button"
data-testid="navigation-panel-add-tag-button"
onClick={() => setShowNewTagDialog(true)}
label={t[
'com.affine.rootAppSidebar.explorer.tag-section-add-tooltip'
@@ -65,7 +65,7 @@ export const ExplorerTags = () => {
enableAnimation
descRenderer={TagDesc}
/>
</ExplorerTreeRoot>
</NavigationPanelTreeRoot>
</CollapsibleSection>
);
};

View File

@@ -1,6 +1,8 @@
import { MobileMenu } from '@affine/component';
import type { BaseExplorerTreeNodeProps } from '@affine/core/modules/explorer';
import { ExplorerTreeContext } from '@affine/core/modules/explorer';
import {
type BaseNavigationPanelTreeNodeProps,
NavigationPanelTreeContext,
} from '@affine/core/desktop/components/navigation-panel';
import { WorkbenchLink } from '@affine/core/modules/workbench';
import { extractEmojiIcon } from '@affine/core/utils';
import { ArrowDownSmallIcon, MoreHorizontalIcon } from '@blocksuite/icons/rc';
@@ -18,9 +20,10 @@ import {
import { SwipeMenu } from '../../swipe-menu';
import * as styles from './node.css';
interface ExplorerTreeNodeProps extends BaseExplorerTreeNodeProps {}
interface NavigationPanelTreeNodeProps
extends BaseNavigationPanelTreeNodeProps {}
export const ExplorerTreeNode = ({
export const NavigationPanelTreeNode = ({
children,
icon: Icon,
name: rawName,
@@ -37,8 +40,8 @@ export const ExplorerTreeNode = ({
childrenPlaceholder,
linkComponent: LinkComponent = WorkbenchLink,
...otherProps
}: ExplorerTreeNodeProps) => {
const context = useContext(ExplorerTreeContext);
}: NavigationPanelTreeNodeProps) => {
const context = useContext(NavigationPanelTreeContext);
const level = context?.level ?? 0;
// If no onClick or to is provided, clicking on the node will toggle the collapse state
const clickForCollapse = !onClick && !to && !disabled;
@@ -141,7 +144,7 @@ export const ExplorerTreeNode = ({
<div
data-disabled={disabled}
onClick={handleCollapsedChange}
data-testid="explorer-collapsed-button"
data-testid="navigation-panel-collapsed-button"
className={styles.collapsedIconContainer}
>
<ArrowDownSmallIcon
@@ -197,9 +200,9 @@ export const ExplorerTreeNode = ({
<div className={styles.collapseContentPlaceholder}>
{childCount === 0 && !collapsed && childrenPlaceholder}
</div>
<ExplorerTreeContext.Provider value={contextValue}>
<NavigationPanelTreeContext.Provider value={contextValue}>
{collapsed ? null : children}
</ExplorerTreeContext.Provider>
</NavigationPanelTreeContext.Provider>
</Collapsible.Content>
</Collapsible.Root>
);

View File

@@ -0,0 +1,10 @@
import { style } from '@vanilla-extract/css';
export const placeholder = style({
display: 'none',
selectors: {
'&:only-child': {
display: 'initial',
},
},
});

View File

@@ -0,0 +1,43 @@
import {
NavigationPanelTreeContext,
type NodeOperation,
} from '@affine/core/desktop/components/navigation-panel';
import { useMemo, useState } from 'react';
import * as styles from './root.css';
export const NavigationPanelTreeRoot = ({
children,
childrenOperations = [],
placeholder,
}: {
children?: React.ReactNode;
childrenOperations?: NodeOperation[];
className?: string;
placeholder?: React.ReactNode;
}) => {
const [childCount, setChildCount] = useState(0);
const contextValue = useMemo(() => {
return {
operations: childrenOperations,
level: 0,
registerChild: () => {
setChildCount(c => c + 1);
return () => setChildCount(c => c - 1);
},
};
}, [childrenOperations]);
return (
// <div> is for placeholder:last-child selector
<div>
{/* For lastInGroup check, the placeholder must be placed above all children in the dom */}
<div className={styles.placeholder}>
{childCount === 0 && placeholder}
</div>
<NavigationPanelTreeContext.Provider value={contextValue}>
{children}
</NavigationPanelTreeContext.Provider>
</div>
);
};

View File

@@ -2,11 +2,11 @@ import { SafeArea, useThemeColorV2 } from '@affine/component';
import { AppTabs } from '../../components';
import {
ExplorerCollections,
ExplorerFavorites,
ExplorerOrganize,
ExplorerTags,
} from '../../components/explorer';
NavigationPanelCollections,
NavigationPanelFavorites,
NavigationPanelOrganize,
NavigationPanelTags,
} from '../../components/navigation';
import { HomeHeader, RecentDocs } from '../../views';
export const Component = () => {
@@ -25,10 +25,10 @@ export const Component = () => {
padding: '0 8px 32px 8px',
}}
>
<ExplorerFavorites />
<ExplorerOrganize />
<ExplorerCollections />
<ExplorerTags />
<NavigationPanelFavorites />
<NavigationPanelOrganize />
<NavigationPanelCollections />
<NavigationPanelTags />
</div>
</SafeArea>
<AppTabs />

View File

@@ -4,7 +4,7 @@ import { useService } from '@toeverything/infra';
import { useMemo } from 'react';
import { DocCard } from '../../components/doc-card';
import { CollapsibleSection } from '../../components/explorer';
import { CollapsibleSection } from '../../components/navigation';
import * as styles from './styles.css';
export const RecentDocs = ({ max = 5 }: { max?: number }) => {