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 { Size } from '@joplin/utils/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-15 00:39:33 +01:00
|
|
|
const useRenderedNotes = (startNoteIndex: number, endNoteIndex: number, notes: NoteEntity[], selectedNoteIds: string[], itemSize: Size, 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
|
|
|
const noteIds = notes.filter((_value, index) => {
|
|
|
|
|
return index >= startNoteIndex && index <= endNoteIndex;
|
|
|
|
|
}).map(note => note.id);
|
|
|
|
|
|
|
|
|
|
const fullNotes = await Note.loadItemsByIds(noteIds);
|
|
|
|
|
if (event.cancelled) return;
|
|
|
|
|
|
2023-08-13 12:21:12 +01:00
|
|
|
const renderNote = async (note: NoteEntity, noteIndex: number): Promise<void> => {
|
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,
|
|
|
|
|
itemSize,
|
2023-08-13 12:21:12 +01:00
|
|
|
selectedNoteIds.includes(note.id),
|
2023-08-14 23:58:22 +01:00
|
|
|
noteIndex,
|
2023-08-15 00:39:33 +01:00
|
|
|
titleHtml,
|
|
|
|
|
watchedNoteFiles.includes(note.id)
|
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;
|
|
|
|
|
|
|
|
|
|
const viewHash = hashContent(view);
|
|
|
|
|
|
|
|
|
|
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-16 20:57:55 +01:00
|
|
|
for (let i = 0; i < fullNotes.length; i++) {
|
|
|
|
|
promises.push(renderNote(fullNotes[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-15 00:39:33 +01:00
|
|
|
}, [startNoteIndex, endNoteIndex, notes, selectedNoteIds, itemSize, listRenderer, watchedNoteFiles]);
|
2023-08-11 18:18:32 +01:00
|
|
|
|
|
|
|
|
return renderedNotes;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default useRenderedNotes;
|