Refactor sidebar entry types and sorting logic in App.tsx
This commit is contained in:
72
src/App.tsx
72
src/App.tsx
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user