Refactor sidebar entry types and sorting logic in App.tsx

This commit is contained in:
2026-02-01 01:55:47 +01:00
parent 4d61e4d5cc
commit d78911d17e

View File

@@ -66,6 +66,10 @@ type HistoryEntry = {
baseVersionId?: string | null; baseVersionId?: string | null;
}; };
type SidebarEntry =
| { kind: "folder"; item: Folder }
| { kind: "text"; item: Text };
const DEFAULT_TITLE = "Untitled Text"; const DEFAULT_TITLE = "Untitled Text";
const DEFAULT_FOLDER_NAME = "New Folder"; const DEFAULT_FOLDER_NAME = "New Folder";
@@ -182,11 +186,6 @@ export default function App() {
const showLineNumbersActive = showLineNumbers && !markdownPreview; const showLineNumbersActive = showLineNumbers && !markdownPreview;
const hasSearch = search.trim().length > 0; const hasSearch = search.trim().length > 0;
const sortByUpdated = useCallback(
<T extends { updated_at: number }>(a: T, b: T) => b.updated_at - a.updated_at,
[]
);
const folderById = useMemo(() => { const folderById = useMemo(() => {
const map = new Map<string, Folder>(); const map = new Map<string, Folder>();
for (const folder of folders) { for (const folder of folders) {
@@ -195,40 +194,6 @@ export default function App() {
return map; return map;
}, [folders]); }, [folders]);
const foldersByParent = useMemo(() => {
const map = new Map<string | null, Folder[]>();
for (const folder of folders) {
const key = folder.parent_id ?? null;
const list = map.get(key);
if (list) {
list.push(folder);
} else {
map.set(key, [folder]);
}
}
for (const [key, list] of map.entries()) {
map.set(key, [...list].sort(sortByUpdated));
}
return map;
}, [folders, sortByUpdated]);
const textsByFolder = useMemo(() => {
const map = new Map<string | null, Text[]>();
for (const text of texts) {
const key = text.folder_id ?? null;
const list = map.get(key);
if (list) {
list.push(text);
} else {
map.set(key, [text]);
}
}
for (const [key, list] of map.entries()) {
map.set(key, [...list].sort(sortByUpdated));
}
return map;
}, [texts, sortByUpdated]);
const visibleFolderIds = useMemo(() => { const visibleFolderIds = useMemo(() => {
if (!hasSearch) return null; if (!hasSearch) return null;
const visible = new Set<string>(); const visible = new Set<string>();
@@ -243,6 +208,35 @@ export default function App() {
return visible; return visible;
}, [folderById, hasSearch, texts]); }, [folderById, hasSearch, texts]);
const entriesByParent = useMemo(() => {
const map = new Map<string | null, SidebarEntry[]>();
const addEntry = (parentId: string | null, entry: SidebarEntry) => {
const list = map.get(parentId);
if (list) {
list.push(entry);
} else {
map.set(parentId, [entry]);
}
};
for (const folder of folders) {
if (hasSearch && visibleFolderIds && !visibleFolderIds.has(folder.id)) {
continue;
}
addEntry(folder.parent_id ?? null, { kind: "folder", item: folder });
}
for (const text of texts) {
addEntry(text.folder_id ?? null, { kind: "text", item: text });
}
for (const [key, list] of map.entries()) {
list.sort((a, b) => b.item.updated_at - a.item.updated_at);
map.set(key, list);
}
return map;
}, [folders, hasSearch, texts, visibleFolderIds]);
const handleMarkdownPreviewClick = useCallback( const handleMarkdownPreviewClick = useCallback(
(event: React.MouseEvent<HTMLDivElement>) => { (event: React.MouseEvent<HTMLDivElement>) => {
const target = event.target as HTMLElement | null; const target = event.target as HTMLElement | null;