1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-12-17 23:27:48 +02:00
Files
joplin/packages/app-desktop/gui/NoteList/utils/useRenderedNotes.ts

84 lines
2.5 KiB
TypeScript
Raw Normal View History

2023-08-11 18:18:32 +01:00
import { useState } from 'react';
2023-08-14 23:58:22 +01:00
import { ListRenderer } from './types';
2023-08-11 18:18:32 +01:00
import { NoteEntity } from '@joplin/lib/services/database/types';
import useAsyncEffect from '@joplin/lib/hooks/useAsyncEffect';
import * as Mustache from 'mustache';
2023-08-12 15:45:19 +01:00
import { createHash } from 'crypto';
2023-08-14 23:58:22 +01:00
import getNoteTitleHtml from './getNoteTitleHtml';
import Note from '@joplin/lib/models/Note';
import prepareViewProps from './prepareViewProps';
2023-08-11 18:18:32 +01:00
interface RenderedNote {
id: string;
2023-08-12 15:45:19 +01:00
hash: string;
2023-08-11 18:18:32 +01:00
html: string;
}
2023-08-12 15:45:19 +01:00
const hashContent = (content: any) => {
return createHash('sha1').update(JSON.stringify(content)).digest('hex');
};
2023-08-19 09:32:53 +01:00
const useRenderedNotes = (startNoteIndex: number, endNoteIndex: number, notes: NoteEntity[], selectedNoteIds: string[], listRenderer: ListRenderer, highlightedWords: string[], watchedNoteFiles: string[]) => {
2023-08-12 15:45:19 +01:00
const [renderedNotes, setRenderedNotes] = useState<Record<string, RenderedNote>>({});
useAsyncEffect(async (event) => {
2023-08-16 20:57:55 +01:00
if (event.cancelled) return;
2023-08-13 12:21:12 +01:00
const renderNote = async (note: NoteEntity, noteIndex: number): Promise<void> => {
2023-08-19 09:32:53 +01:00
const isSelected = selectedNoteIds.includes(note.id);
const isWatched = watchedNoteFiles.includes(note.id);
// Note: with this hash we're assuming that the list renderer
// properties never changes. It means that later if we support
// dynamic list renderers, we should include these into the hash.
const viewHash = hashContent([
note.updated_time,
isSelected,
isWatched,
highlightedWords,
]);
2023-08-18 19:09:28 +01:00
if (renderedNotes[note.id] && renderedNotes[note.id].hash === viewHash) return null;
2023-08-14 23:58:22 +01:00
const titleHtml = getNoteTitleHtml(highlightedWords, Note.displayTitle(note));
const viewProps = await prepareViewProps(
2023-08-11 18:18:32 +01:00
listRenderer.dependencies,
note,
2023-08-19 09:32:53 +01:00
listRenderer.itemSize,
isSelected,
2023-08-14 23:58:22 +01:00
noteIndex,
2023-08-15 00:39:33 +01:00
titleHtml,
2023-08-19 09:32:53 +01:00
isWatched
2023-08-14 23:58:22 +01:00
);
const view = await listRenderer.onRenderNote(viewProps);
2023-08-11 18:18:32 +01:00
2023-08-12 15:45:19 +01:00
if (event.cancelled) return null;
setRenderedNotes(prev => {
if (prev[note.id] && prev[note.id].hash === viewHash) return prev;
return {
...prev,
[note.id]: {
id: note.id,
hash: viewHash,
html: Mustache.render(listRenderer.itemTemplate, view),
},
};
2023-08-11 18:18:32 +01:00
});
2023-08-12 15:45:19 +01:00
};
2023-08-11 18:18:32 +01:00
2023-08-12 15:45:19 +01:00
const promises: Promise<void>[] = [];
2023-08-18 19:09:28 +01:00
for (let i = startNoteIndex; i <= endNoteIndex; i++) {
promises.push(renderNote(notes[i], i));
2023-08-12 15:45:19 +01:00
}
2023-08-11 18:18:32 +01:00
2023-08-12 15:45:19 +01:00
await Promise.all(promises);
2023-08-19 09:32:53 +01:00
}, [startNoteIndex, endNoteIndex, notes, selectedNoteIds, listRenderer, renderedNotes, watchedNoteFiles]);
2023-08-11 18:18:32 +01:00
return renderedNotes;
};
export default useRenderedNotes;