feat(core): cache navigation collapsed state (#13315)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Refactor**
* Collapsible section state in navigation panels is now managed using a
unified path-based approach, enabling more consistent and centralized
control across desktop and mobile interfaces.
* The collapsed/expanded state of navigation sections and nodes is now
persistently tracked using hierarchical paths, improving reliability
across sessions and devices.
* Internal state management is streamlined, with local state replaced by
a shared service, resulting in more predictable navigation behavior.

* **Chores**
* Removed obsolete types and legacy section management logic for
improved maintainability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
EYHN
2025-07-25 18:19:21 +08:00
committed by GitHub
parent 7409940cc6
commit 1dd4bbbaba
26 changed files with 357 additions and 198 deletions
@@ -1,8 +1,5 @@
import { CategoryDivider } from '@affine/core/modules/app-sidebar/views';
import {
type CollapsibleSectionName,
NavigationPanelService,
} from '@affine/core/modules/navigation-panel';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import * as Collapsible from '@radix-ui/react-collapsible';
import { useLiveData, useService } from '@toeverything/infra';
import clsx from 'clsx';
@@ -17,7 +14,7 @@ import {
import { content, header, root } from './collapsible-section.css';
interface CollapsibleSectionProps extends PropsWithChildren {
name: CollapsibleSectionName;
path: string[];
title: string;
actions?: ReactNode;
@@ -33,7 +30,7 @@ interface CollapsibleSectionProps extends PropsWithChildren {
}
export const CollapsibleSection = ({
name,
path,
title,
actions,
children,
@@ -48,15 +45,15 @@ export const CollapsibleSection = ({
contentClassName,
contentStyle,
}: CollapsibleSectionProps) => {
const section = useService(NavigationPanelService).sections[name];
const navigationPanelService = useService(NavigationPanelService);
const collapsed = useLiveData(section.collapsed$);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const setCollapsed = useCallback(
(v: boolean) => {
section.setCollapsed(v);
navigationPanelService.setCollapsed(path, v);
},
[section]
[navigationPanelService, path]
);
return (
@@ -11,6 +11,7 @@ import {
} from '@affine/core/modules/collection';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
@@ -47,6 +48,7 @@ export const NavigationPanelCollectionNode = ({
operations: additionalOperations,
canDrop,
dropEffect,
parentPath,
}: {
collectionId: string;
} & GenericNavigationPanelNode) => {
@@ -55,10 +57,21 @@ export const NavigationPanelCollectionNode = ({
GlobalContextService,
WorkspaceDialogService,
});
const navigationPanelService = useService(NavigationPanelService);
const active =
useLiveData(globalContextService.globalContext.collectionId.$) ===
collectionId;
const [collapsed, setCollapsed] = useState(true);
const path = useMemo(
() => [...(parentPath ?? []), `collection-${collectionId}`],
[parentPath, collectionId]
);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const setCollapsed = useCallback(
(value: boolean) => {
navigationPanelService.setCollapsed(path, value);
},
[navigationPanelService, path]
);
const collectionService = useService(CollectionService);
const collection = useLiveData(collectionService.collection$(collectionId));
@@ -160,7 +173,7 @@ export const NavigationPanelCollectionNode = ({
const handleOpenCollapsed = useCallback(() => {
setCollapsed(false);
}, []);
}, [setCollapsed]);
const handleEditCollection = useCallback(() => {
if (!collection) {
@@ -217,15 +230,20 @@ export const NavigationPanelCollectionNode = ({
dropEffect={handleDropEffectOnCollection}
data-testid={`navigation-panel-collection-${collectionId}`}
>
<NavigationPanelCollectionNodeChildren collection={collection} />
<NavigationPanelCollectionNodeChildren
collection={collection}
path={path}
/>
</NavigationPanelTreeNode>
);
};
const NavigationPanelCollectionNodeChildren = ({
collection,
path,
}: {
collection: Collection;
path: string[];
}) => {
const t = useI18n();
const { collectionService } = useServices({
@@ -264,6 +282,7 @@ const NavigationPanelCollectionNodeChildren = ({
at: 'navigation-panel:collection:filtered-docs',
collectionId: collection.id,
}}
parentPath={path}
operations={
allowList.has(docId)
? [
@@ -14,6 +14,7 @@ import { DocDisplayMetaService } from '@affine/core/modules/doc-display-meta';
import { DocsSearchService } from '@affine/core/modules/docs-search';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import { GuardService } from '@affine/core/modules/permissions';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
@@ -46,6 +47,7 @@ export const NavigationPanelDocNode = ({
canDrop,
operations: additionalOperations,
dropEffect,
parentPath,
}: {
docId: string;
isLinked?: boolean;
@@ -67,11 +69,22 @@ export const NavigationPanelDocNode = ({
FeatureFlagService,
GuardService,
});
const navigationPanelService = useService(NavigationPanelService);
const { appSettings } = useAppSettingHelper();
const active =
useLiveData(globalContextService.globalContext.docId.$) === docId;
const [collapsed, setCollapsed] = useState(true);
const path = useMemo(
() => [...(parentPath ?? []), `doc-${docId}`],
[parentPath, docId]
);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const setCollapsed = useCallback(
(value: boolean) => {
navigationPanelService.setCollapsed(path, value);
},
[navigationPanelService, path]
);
const isCollapsed = appSettings.showLinkedDocInSidebar ? collapsed : true;
const docRecord = useLiveData(docsService.list.doc$(docId));
@@ -227,7 +240,7 @@ export const NavigationPanelDocNode = ({
openInfoModal: () => workspaceDialogService.open('doc-info', { docId }),
openNodeCollapsed: () => setCollapsed(false),
}),
[docId, workspaceDialogService]
[docId, setCollapsed, workspaceDialogService]
)
);
@@ -302,6 +315,7 @@ export const NavigationPanelDocNode = ({
at: 'navigation-panel:doc:linked-docs',
docId,
}}
parentPath={path}
isLinked
/>
))
@@ -13,6 +13,7 @@ import { usePageHelper } from '@affine/core/blocksuite/block-suite-page-list/uti
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { CompatibleFavoriteItemsAdapter } from '@affine/core/modules/favorite';
import { FeatureFlagService } from '@affine/core/modules/feature-flag';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import {
type FolderNode,
OrganizeService,
@@ -31,7 +32,7 @@ import {
RemoveFolderIcon,
TagsIcon,
} from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { useLiveData, useService, useServices } from '@toeverything/infra';
import { difference } from 'lodash-es';
import { useCallback, useMemo, useState } from 'react';
@@ -57,6 +58,7 @@ export const NavigationPanelFolderNode = ({
dropEffect,
canDrop,
reorderable,
parentPath,
}: {
defaultRenaming?: boolean;
nodeId: string;
@@ -104,6 +106,7 @@ export const NavigationPanelFolderNode = ({
dropEffect={dropEffect}
reorderable={reorderable}
canDrop={canDrop}
parentPath={parentPath}
/>
);
} else if (type === 'doc') {
@@ -117,6 +120,7 @@ export const NavigationPanelFolderNode = ({
canDrop={canDrop}
dropEffect={dropEffect}
operations={additionalOperations}
parentPath={parentPath}
/>
)
);
@@ -131,6 +135,7 @@ export const NavigationPanelFolderNode = ({
reorderable={reorderable}
dropEffect={dropEffect}
operations={additionalOperations}
parentPath={parentPath}
/>
)
);
@@ -145,6 +150,7 @@ export const NavigationPanelFolderNode = ({
reorderable
dropEffect={dropEffect}
operations={additionalOperations}
parentPath={parentPath}
/>
)
);
@@ -177,6 +183,7 @@ const NavigationPanelFolderNodeFolder = ({
canDrop,
dropEffect,
reorderable,
parentPath,
}: {
defaultRenaming?: boolean;
node: FolderNode;
@@ -189,11 +196,22 @@ const NavigationPanelFolderNodeFolder = ({
FeatureFlagService,
WorkspaceDialogService,
});
const navigationPanelService = useService(NavigationPanelService);
const name = useLiveData(node.name$);
const enableEmojiIcon = useLiveData(
featureFlagService.flags.enable_emoji_folder_icon.$
);
const [collapsed, setCollapsed] = useState(true);
const path = useMemo(
() => [...(parentPath ?? []), `folder-${node.id}`],
[parentPath, node.id]
);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const setCollapsed = useCallback(
(value: boolean) => {
navigationPanelService.setCollapsed(path, value);
},
[navigationPanelService, path]
);
const [newFolderId, setNewFolderId] = useState<string | null>(null);
const { createPage } = usePageHelper(
@@ -575,7 +593,7 @@ const NavigationPanelFolderNodeFolder = ({
target: 'doc',
});
setCollapsed(false);
}, [createPage, node]);
}, [createPage, node, setCollapsed]);
const handleCreateSubfolder = useCallback(() => {
const newFolderId = node.createFolder(
@@ -585,7 +603,7 @@ const NavigationPanelFolderNodeFolder = ({
track.$.navigationPanel.organize.createOrganizeItem({ type: 'folder' });
setCollapsed(false);
setNewFolderId(newFolderId);
}, [node, t]);
}, [node, setCollapsed, t]);
const handleAddToFolder = useCallback(
(type: 'doc' | 'collection' | 'tag') => {
@@ -628,7 +646,7 @@ const NavigationPanelFolderNodeFolder = ({
target: type,
});
},
[children, node, workspaceDialogService]
[children, node, setCollapsed, workspaceDialogService]
);
const folderOperations = useMemo(() => {
@@ -761,14 +779,17 @@ const NavigationPanelFolderNodeFolder = ({
[t]
);
const handleCollapsedChange = useCallback((collapsed: boolean) => {
if (collapsed) {
setNewFolderId(null); // reset new folder id to clear the renaming state
setCollapsed(true);
} else {
setCollapsed(false);
}
}, []);
const handleCollapsedChange = useCallback(
(collapsed: boolean) => {
if (collapsed) {
setNewFolderId(null); // reset new folder id to clear the renaming state
setCollapsed(true);
} else {
setCollapsed(false);
}
},
[setCollapsed]
);
return (
<NavigationPanelTreeNode
@@ -804,6 +825,7 @@ const NavigationPanelFolderNodeFolder = ({
at: 'navigation-panel:organize:folder-node',
nodeId: child.id as string,
}}
parentPath={path}
/>
))}
</NavigationPanelTreeNode>
@@ -4,14 +4,15 @@ import {
toast,
} from '@affine/component';
import { GlobalContextService } from '@affine/core/modules/global-context';
import { NavigationPanelService } from '@affine/core/modules/navigation-panel';
import type { Tag } from '@affine/core/modules/tag';
import { TagService } from '@affine/core/modules/tag';
import type { AffineDNDData } from '@affine/core/types/dnd';
import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { useLiveData, useServices } from '@toeverything/infra';
import { useLiveData, useService, useServices } from '@toeverything/infra';
import clsx from 'clsx';
import { useCallback, useMemo, useState } from 'react';
import { useCallback, useMemo } from 'react';
import {
NavigationPanelTreeNode,
@@ -31,6 +32,7 @@ export const NavigationPanelTagNode = ({
operations: additionalOperations,
dropEffect,
canDrop,
parentPath,
}: {
tagId: string;
} & GenericNavigationPanelNode) => {
@@ -39,9 +41,20 @@ export const NavigationPanelTagNode = ({
TagService,
GlobalContextService,
});
const navigationPanelService = useService(NavigationPanelService);
const active =
useLiveData(globalContextService.globalContext.tagId.$) === tagId;
const [collapsed, setCollapsed] = useState(true);
const path = useMemo(
() => [...(parentPath ?? []), `tag-${tagId}`],
[parentPath, tagId]
);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const setCollapsed = useCallback(
(value: boolean) => {
navigationPanelService.setCollapsed(path, value);
},
[navigationPanelService, path]
);
const tagRecord = useLiveData(tagService.tagList.tagByTagId$(tagId));
const tagColor = useLiveData(tagRecord?.color$);
@@ -154,7 +167,7 @@ export const NavigationPanelTagNode = ({
() => ({
openNodeCollapsed: () => setCollapsed(false),
}),
[]
[setCollapsed]
)
);
@@ -188,7 +201,7 @@ export const NavigationPanelTagNode = ({
dropEffect={handleDropEffectOnTag}
data-testid={`navigation-panel-tag-${tagId}`}
>
<NavigationPanelTagNodeDocs tag={tagRecord} />
<NavigationPanelTagNodeDocs tag={tagRecord} path={path} />
</NavigationPanelTreeNode>
);
};
@@ -198,7 +211,13 @@ export const NavigationPanelTagNode = ({
* 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 NavigationPanelTagNodeDocs = ({ tag }: { tag: Tag }) => {
export const NavigationPanelTagNodeDocs = ({
tag,
path,
}: {
tag: Tag;
path: string[];
}) => {
const tagDocIds = useLiveData(tag.pageIds$);
return tagDocIds.map(docId => (
@@ -209,6 +228,7 @@ export const NavigationPanelTagNodeDocs = ({ tag }: { tag: Tag }) => {
location={{
at: 'navigation-panel:tags:docs',
}}
parentPath={path}
/>
));
};
@@ -46,4 +46,9 @@ export interface GenericNavigationPanelNode {
* The drop effect to be used when an element is dropped over the node.
*/
dropEffect?: NavigationPanelTreeNodeDropEffect;
/**
* The path segments to the parent node in the navigation tree.
* Used to persist the node's collapsed/expanded state in cache storage.
*/
parentPath: string[];
}
@@ -6,7 +6,7 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { AddCollectionIcon } from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { NavigationPanelCollectionNode } from '../../nodes/collection';
@@ -22,10 +22,9 @@ export const NavigationPanelCollections = () => {
WorkbenchService,
NavigationPanelService,
});
const navigationPanelSection = navigationPanelService.sections.collections;
const collections = useLiveData(collectionService.collections$);
const { openPromptModal } = usePromptModal();
const path = useMemo(() => ['collections'], []);
const handleCreateCollection = useCallback(() => {
openPromptModal({
title: t['com.affine.editCollection.saveCollection'](),
@@ -49,20 +48,21 @@ export const NavigationPanelCollections = () => {
type: 'collection',
});
workbenchService.workbench.openCollection(id);
navigationPanelSection.setCollapsed(false);
navigationPanelService.setCollapsed(path, false);
},
});
}, [
collectionService,
navigationPanelSection,
navigationPanelService,
openPromptModal,
path,
t,
workbenchService.workbench,
]);
return (
<CollapsibleSection
name="collections"
path={path}
testId="navigation-panel-collections"
title={t['com.affine.rootAppSidebar.collections']()}
actions={
@@ -89,6 +89,7 @@ export const NavigationPanelCollections = () => {
location={{
at: 'navigation-panel:collection:list',
}}
parentPath={path}
/>
))}
</NavigationPanelTreeRoot>
@@ -17,7 +17,7 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { PlusIcon } from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { type MouseEventHandler, useCallback } from 'react';
import { type MouseEventHandler, useCallback, useMemo } from 'react';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { NavigationPanelCollectionNode } from '../../nodes/collection';
@@ -41,7 +41,7 @@ export const NavigationPanelFavorites = () => {
NavigationPanelService,
});
const navigationPanelSection = navigationPanelService.sections.favorites;
const path = useMemo(() => ['favorites'], []);
const favorites = useLiveData(favoriteService.favoriteList.sortedList$);
@@ -71,10 +71,10 @@ export const NavigationPanelFavorites = () => {
track.$.navigationPanel.favorites.drop({
type: data.source.data.entity.type,
});
navigationPanelSection.setCollapsed(false);
navigationPanelService.setCollapsed(path, false);
}
},
[navigationPanelSection, favoriteService.favoriteList]
[navigationPanelService, favoriteService.favoriteList, path]
);
const handleCreateNewFavoriteDoc: MouseEventHandler = useCallback(
@@ -85,9 +85,9 @@ export const NavigationPanelFavorites = () => {
newDoc.id,
favoriteService.favoriteList.indexAt('before')
);
navigationPanelSection.setCollapsed(false);
navigationPanelService.setCollapsed(path, false);
},
[createPage, navigationPanelSection, favoriteService.favoriteList]
[createPage, navigationPanelService, favoriteService.favoriteList, path]
);
const handleOnChildrenDrop = useCallback(
@@ -162,7 +162,7 @@ export const NavigationPanelFavorites = () => {
return (
<CollapsibleSection
name="favorites"
path={path}
title={t['com.affine.rootAppSidebar.favorites']()}
headerRef={dropTargetRef}
testId="navigation-panel-favorites"
@@ -202,6 +202,7 @@ export const NavigationPanelFavorites = () => {
key={favorite.id}
favorite={favorite}
onDrop={handleOnChildrenDrop}
parentPath={path}
/>
))}
</NavigationPanelTreeRoot>
@@ -215,11 +216,13 @@ const childLocation = {
const NavigationPanelFavoriteNode = ({
favorite,
onDrop,
parentPath,
}: {
favorite: {
id: string;
type: FavoriteSupportTypeUnion;
};
parentPath: string[];
onDrop: (
favorite: {
id: string;
@@ -242,6 +245,7 @@ const NavigationPanelFavoriteNode = ({
onDrop={handleOnChildrenDrop}
dropEffect={favoriteChildrenDropEffect}
canDrop={favoriteChildrenCanDrop}
parentPath={parentPath}
/>
) : favorite.type === 'tag' ? (
<NavigationPanelTagNode
@@ -251,6 +255,7 @@ const NavigationPanelFavoriteNode = ({
onDrop={handleOnChildrenDrop}
dropEffect={favoriteChildrenDropEffect}
canDrop={favoriteChildrenCanDrop}
parentPath={parentPath}
/>
) : favorite.type === 'folder' ? (
<NavigationPanelFolderNode
@@ -260,6 +265,7 @@ const NavigationPanelFavoriteNode = ({
onDrop={handleOnChildrenDrop}
dropEffect={favoriteChildrenDropEffect}
canDrop={favoriteChildrenCanDrop}
parentPath={parentPath}
/>
) : (
<NavigationPanelCollectionNode
@@ -269,6 +275,7 @@ const NavigationPanelFavoriteNode = ({
onDrop={handleOnChildrenDrop}
dropEffect={favoriteChildrenDropEffect}
canDrop={favoriteChildrenCanDrop}
parentPath={parentPath}
/>
);
};
@@ -5,7 +5,7 @@ import { Trans, useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { BroomIcon, HelpIcon } from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { useCallback } from 'react';
import { useCallback, useMemo } from 'react';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { NavigationPanelCollectionNode } from '../../nodes/collection';
@@ -25,6 +25,7 @@ export const NavigationPanelMigrationFavorites = () => {
const trashDocs = useLiveData(docsService.list.trashDocs$);
const migrated = useLiveData(migrationFavoriteItemsAdapter.migrated$);
const { openConfirmModal } = useConfirmModal();
const path = useMemo(() => ['migration-favorites'], []);
const favorites = useLiveData(
migrationFavoriteItemsAdapter.favorites$.map(favs => {
@@ -99,7 +100,7 @@ export const NavigationPanelMigrationFavorites = () => {
return (
<CollapsibleSection
name="migrationFavorites"
path={path}
className={styles.container}
title={t['com.affine.rootAppSidebar.migration-data']()}
actions={
@@ -126,6 +127,7 @@ export const NavigationPanelMigrationFavorites = () => {
<NavigationPanelMigrationFavoriteNode
key={favorite.id + ':' + i}
favorite={favorite}
parentPath={path}
/>
))}
</NavigationPanelTreeRoot>
@@ -138,11 +140,13 @@ const childLocation = {
};
const NavigationPanelMigrationFavoriteNode = ({
favorite,
parentPath,
}: {
favorite: {
id: string;
type: 'collection' | 'doc';
};
parentPath: string[];
}) => {
return favorite.type === 'doc' ? (
<NavigationPanelDocNode
@@ -151,6 +155,7 @@ const NavigationPanelMigrationFavoriteNode = ({
location={childLocation}
reorderable={false}
canDrop={false}
parentPath={parentPath}
/>
) : (
<NavigationPanelCollectionNode
@@ -159,6 +164,7 @@ const NavigationPanelMigrationFavoriteNode = ({
location={childLocation}
reorderable={false}
canDrop={false}
parentPath={parentPath}
/>
);
};
@@ -27,10 +27,9 @@ export const NavigationPanelOrganize = () => {
OrganizeService,
NavigationPanelService,
});
const navigationPanelSection = navigationPanelService.sections.organize;
const collapsed = useLiveData(navigationPanelSection.collapsed$);
const path = useMemo(() => ['organize'], []);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const [newFolderId, setNewFolderId] = useState<string | null>(null);
const t = useI18n();
const folderTree = organizeService.folderTree;
@@ -46,9 +45,9 @@ export const NavigationPanelOrganize = () => {
);
track.$.navigationPanel.organize.createOrganizeItem({ type: 'folder' });
setNewFolderId(newFolderId);
navigationPanelSection.setCollapsed(false);
navigationPanelService.setCollapsed(path, false);
return newFolderId;
}, [navigationPanelSection, rootFolder]);
}, [navigationPanelService, path, rootFolder]);
const handleOnChildrenDrop = useCallback(
(data: DropTargetDropEvent<AffineDNDData>, node?: FolderNode) => {
@@ -105,7 +104,7 @@ export const NavigationPanelOrganize = () => {
return (
<CollapsibleSection
name="organize"
path={path}
title={t['com.affine.rootAppSidebar.organize']()}
actions={
<IconButton
@@ -141,6 +140,7 @@ export const NavigationPanelOrganize = () => {
at: 'navigation-panel:organize:folder-node',
nodeId: child.id as string,
}}
parentPath={path}
/>
))}
</NavigationPanelTreeRoot>
@@ -5,7 +5,7 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track';
import { AddTagIcon } from '@blocksuite/icons/rc';
import { useLiveData, useServices } from '@toeverything/infra';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { CollapsibleSection } from '../../layouts/collapsible-section';
import { NavigationPanelTagNode } from '../../nodes/tag';
@@ -19,8 +19,8 @@ export const NavigationPanelTags = () => {
TagService,
NavigationPanelService,
});
const navigationPanelSection = navigationPanelService.sections.tags;
const collapsed = useLiveData(navigationPanelSection.collapsed$);
const path = useMemo(() => ['tags'], []);
const collapsed = useLiveData(navigationPanelService.collapsed$(path));
const [creating, setCreating] = useState(false);
const tags = useLiveData(tagService.tagList.tags$);
@@ -30,9 +30,9 @@ export const NavigationPanelTags = () => {
(name: string) => {
tagService.tagList.createTag(name, tagService.randomTagColor());
track.$.navigationPanel.organize.createOrganizeItem({ type: 'tag' });
navigationPanelSection.setCollapsed(false);
navigationPanelService.setCollapsed(path, false);
},
[navigationPanelSection, tagService]
[navigationPanelService, path, tagService]
);
useEffect(() => {
@@ -45,7 +45,7 @@ export const NavigationPanelTags = () => {
return (
<CollapsibleSection
name="tags"
path={path}
testId="navigation-panel-tags"
headerClassName={styles.draggedOverHighlight}
title={t['com.affine.rootAppSidebar.tags']()}
@@ -81,6 +81,7 @@ export const NavigationPanelTags = () => {
location={{
at: 'navigation-panel:tags:list',
}}
parentPath={path}
/>
))}
</NavigationPanelTreeRoot>