import { useMemo } from 'react'; import { FolderListItem, HeaderId, HeaderListItem, ListItem, ListItemType, TagListItem } from '../types'; import { FolderEntity, TagsWithNoteCountEntity } from '@joplin/lib/services/database/types'; import { buildFolderTree, renderFolders, renderTags } from '@joplin/lib/components/shared/side-menu-shared'; import { _ } from '@joplin/lib/locale'; import toggleHeader from './utils/toggleHeader'; import Folder from '@joplin/lib/models/Folder'; import Tag from '@joplin/lib/models/Tag'; interface Props { tags: TagsWithNoteCountEntity[]; folders: FolderEntity[]; collapsedFolderIds: string[]; folderHeaderIsExpanded: boolean; tagHeaderIsExpanded: boolean; } const useSidebarListData = (props: Props): ListItem[] => { const tagItems = useMemo(() => { return renderTags(props.tags, (tag): TagListItem => { return { kind: ListItemType.Tag, label: Tag.displayTitle(tag), tag, key: tag.id, depth: 1, hasChildren: false, }; }); }, [props.tags]); const folderTree = useMemo(() => { return buildFolderTree(props.folders); }, [props.folders]); const folderItems = useMemo(() => { const renderProps = { folderTree, collapsedFolderIds: props.collapsedFolderIds, }; return renderFolders(renderProps, (folder, hasChildren, depth): FolderListItem => { return { kind: ListItemType.Folder, label: Folder.displayTitle(folder), folder, hasChildren, // The toplevel headers have depth 1, so the toplevel notebook needs // depth 2. depth: depth + 1, key: folder.id, }; }); }, [folderTree, props.collapsedFolderIds]); return useMemo(() => { const foldersHeader: HeaderListItem = { kind: ListItemType.Header, label: _('Notebooks'), iconName: 'icon-notebooks', expanded: props.folderHeaderIsExpanded, id: HeaderId.FolderHeader, key: HeaderId.FolderHeader, onClick: toggleHeader, extraProps: { ['data-folder-id']: '', }, supportsFolderDrop: true, depth: 1, hasChildren: folderItems.items.length > 0, }; const foldersSectionContent: ListItem[] = props.folderHeaderIsExpanded ? [ { kind: ListItemType.AllNotes, label: _('All notes'), key: 'all-notes', depth: 2, hasChildren: false }, ...folderItems.items, { kind: ListItemType.Spacer, label: '', key: 'after-folders-spacer', depth: 1, hasChildren: false }, ] : []; const tagsHeader: HeaderListItem = { kind: ListItemType.Header, label: _('Tags'), iconName: 'icon-tags', expanded: props.tagHeaderIsExpanded, id: HeaderId.TagHeader, key: HeaderId.TagHeader, onClick: toggleHeader, extraProps: { }, supportsFolderDrop: false, depth: 1, hasChildren: tagItems.items.length > 0, }; const tagsSectionContent: ListItem[] = props.tagHeaderIsExpanded ? tagItems.items : []; const items: ListItem[] = [ foldersHeader, ...foldersSectionContent, tagsHeader, ...tagsSectionContent, ]; return items; }, [tagItems, folderItems, props.folderHeaderIsExpanded, props.tagHeaderIsExpanded]); }; export default useSidebarListData;