import "./ListOrGridView.css"; import { Card, CardSection } from "../../react/Card"; import { useEffect, useRef, useState } from "preact/hooks"; import FNote from "../../../entities/fnote"; import attribute_renderer from "../../../services/attribute_renderer"; import content_renderer from "../../../services/content_renderer"; import { t } from "../../../services/i18n"; import link from "../../../services/link"; import CollectionProperties from "../../note_bars/CollectionProperties"; import { useImperativeSearchHighlighlighting, useNoteLabel, useNoteLabelBoolean, useNoteProperty } from "../../react/hooks"; import Icon from "../../react/Icon"; import NoteLink from "../../react/NoteLink"; import { ViewModeProps } from "../interface"; import { Pager, usePagination } from "../Pagination"; import { filterChildNotes, useFilteredNoteIds } from "./utils"; import { JSX } from "preact/jsx-runtime"; import { clsx } from "clsx"; export function ListView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) { const expandDepth = useExpansionDepth(note); const noteIds = useFilteredNoteIds(note, unfilteredNoteIds); const { pageNotes, ...pagination } = usePagination(note, noteIds); const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived"); const noteType = useNoteProperty(note, "type"); const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? ""); return (
} /> { noteIds.length > 0 &&
{!hasCollectionProperties && } {pageNotes?.map(childNote => ( ))}
}
); } export function GridView({ note, noteIds: unfilteredNoteIds, highlightedTokens }: ViewModeProps<{}>) { const noteIds = useFilteredNoteIds(note, unfilteredNoteIds); const { pageNotes, ...pagination } = usePagination(note, noteIds); const [ includeArchived ] = useNoteLabelBoolean(note, "includeArchived"); const noteType = useNoteProperty(note, "type"); const hasCollectionProperties = [ "book", "search" ].includes(noteType ?? ""); return (
} />
{!hasCollectionProperties && }
); } function ListNoteCard({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: { note: FNote, parentNote: FNote, currentLevel: number, expandDepth: number, highlightedTokens: string[] | null | undefined; includeArchived: boolean; }) { const [ isExpanded, setExpanded ] = useState(currentLevel <= expandDepth); const notePath = getNotePath(parentNote, note); // Reset expand state if switching to another note, or if user manually toggled expansion state. useEffect(() => setExpanded(currentLevel <= expandDepth), [ note, currentLevel, expandDepth ]); let subSections: JSX.Element | undefined = undefined; if (isExpanded) { subSections = <> } return (
setExpanded(!isExpanded)}/>
); } function GridNoteCard({ note, parentNote, highlightedTokens, includeArchived }: { note: FNote, parentNote: FNote, highlightedTokens: string[] | null | undefined, includeArchived: boolean }) { const titleRef = useRef(null); const [ noteTitle, setNoteTitle ] = useState(); const notePath = getNotePath(parentNote, note); return (
link.goToLink(e)} >
); } function NoteAttributes({ note }: { note: FNote }) { const ref = useRef(null); useEffect(() => { attribute_renderer.renderNormalAttributes(note).then(({$renderedAttributes}) => { ref.current?.replaceChildren(...$renderedAttributes); }); }, [ note ]); return ; } export function NoteContent({ note, trim, noChildrenList, highlightedTokens, includeArchivedNotes }: { note: FNote; trim?: boolean; noChildrenList?: boolean; highlightedTokens: string[] | null | undefined; includeArchivedNotes: boolean; }) { const contentRef = useRef(null); const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens); const [ready, setReady] = useState(false); const [noteType, setNoteType] = useState("none"); useEffect(() => { content_renderer.getRenderedContent(note, { trim, noChildrenList, noIncludedNotes: true, includeArchivedNotes }) .then(({ $renderedContent, type }) => { if (!contentRef.current) return; if ($renderedContent[0].innerHTML) { contentRef.current.replaceChildren(...$renderedContent); } else { contentRef.current.replaceChildren(); } highlightSearch(contentRef.current); setNoteType(type); setReady(true); }) .catch(e => { console.warn(`Caught error while rendering note '${note.noteId}' of type '${note.type}'`); console.error(e); contentRef.current?.replaceChildren(t("collections.rendering_error")); setReady(true); }); }, [ note, highlightedTokens ]); return
; } function NoteChildren({ note, parentNote, highlightedTokens, currentLevel, expandDepth, includeArchived }: { note: FNote, parentNote: FNote, currentLevel: number, expandDepth: number, highlightedTokens: string[] | null | undefined includeArchived: boolean; }) { const [ childNotes, setChildNotes ] = useState(); useEffect(() => { filterChildNotes(note, includeArchived).then(setChildNotes); }, [ note, includeArchived ]); return childNotes?.map(childNote => ); } function getNotePath(parentNote: FNote, childNote: FNote) { if (parentNote.type === "search") { // for search note parent, we want to display a non-search path return childNote.noteId; } return `${parentNote.noteId}/${childNote.noteId}`; } function useExpansionDepth(note: FNote) { const [ expandDepth ] = useNoteLabel(note, "expanded"); if (expandDepth === null || expandDepth === undefined) { // not defined return 0; } else if (expandDepth === "") { // defined without value return 1; } else if (expandDepth === "all") { return Number.MAX_SAFE_INTEGER; } return parseInt(expandDepth, 10); }