import { MetadataResponse, NoteSizeResponse, SubtreeSizeResponse } from "@triliumnext/commons"; import { useCallback, useEffect, useMemo, useState } from "preact/hooks"; import FNote from "../../entities/fnote"; import debounce from "../../services/debounce"; import { isExperimentalFeatureEnabled } from "../../services/experimental_features"; import { t } from "../../services/i18n"; import server from "../../services/server"; import { formatSize } from "../../services/utils"; import { formatDateTime } from "../../utils/formatters"; import { useTriliumEvent } from "../react/hooks"; import LinkButton from "../react/LinkButton"; import LoadingSpinner from "../react/LoadingSpinner"; const isNewLayout = isExperimentalFeatureEnabled("new-layout"); export default function NoteInfoTab({ note }: { note: FNote | null | undefined }) { const { metadata, ...sizeProps } = useNoteMetadata(note); return (
{note && ( <>
{t("note_info_widget.note_id")}: {note.noteId}
{!isNewLayout &&
{t("note_info_widget.created")}: {formatDateTime(metadata?.dateCreated)}
} {!isNewLayout &&
{t("note_info_widget.modified")}: {formatDateTime(metadata?.dateModified)}
}
{t("note_info_widget.type")}: {note.type}{' '} {note.mime && ({note.mime})}
{t("note_info_widget.note_size")}:
)}
); } export function NoteSizeWidget({ isLoading, noteSizeResponse, subtreeSizeResponse, requestSizeInfo }: Omit, "metadata">) { return <> {!isLoading && !noteSizeResponse && !subtreeSizeResponse && ( )} {formatSize(noteSizeResponse?.noteSize)} {" "} {subtreeSizeResponse && subtreeSizeResponse.subTreeNoteCount > 1 && {t("note_info_widget.subtree_size", { size: formatSize(subtreeSizeResponse.subTreeSize), count: subtreeSizeResponse.subTreeNoteCount })} } {isLoading && } ; } export function useNoteMetadata(note: FNote | null | undefined, debounceTime = 10_000) { const [ isLoading, setIsLoading ] = useState(false); const [ noteSizeResponse, setNoteSizeResponse ] = useState(); const [ subtreeSizeResponse, setSubtreeSizeResponse ] = useState(); const [ metadata, setMetadata ] = useState(); const refresh = useCallback(() => { if (note) { server.get(`notes/${note?.noteId}/metadata`).then(setMetadata); } setNoteSizeResponse(undefined); setSubtreeSizeResponse(undefined); setIsLoading(false); }, [ note ]); const debouncedRefresh = useMemo(() => debounce(refresh, debounceTime), [ refresh, debounceTime ]); function requestSizeInfo() { if (!note) return; setIsLoading(true); setTimeout(async () => { await Promise.allSettled([ server.get(`stats/note-size/${note.noteId}`).then(setNoteSizeResponse), server.get(`stats/subtree-size/${note.noteId}`).then(setSubtreeSizeResponse) ]); setIsLoading(false); }, 0); } useEffect(() => refresh(), [ refresh ]); useTriliumEvent("entitiesReloaded", ({ loadResults }) => { const noteId = note?.noteId; if (noteId && (loadResults.isNoteReloaded(noteId) || loadResults.isNoteContentReloaded(noteId))) { debouncedRefresh(); } }); return { isLoading, metadata, noteSizeResponse, subtreeSizeResponse, requestSizeInfo }; }