1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Desktop: Re-render note when resources are changed (#10459)

This commit is contained in:
Henry Heino 2024-05-28 03:30:56 -07:00 committed by GitHub
parent b0d0e641ea
commit b8caf08fac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 11 deletions

View File

@ -1,7 +1,9 @@
import Note from '@joplin/lib/models/Note'; import Note from '@joplin/lib/models/Note';
import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils'; import { setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
import { renderHook } from '@testing-library/react-hooks'; import { act, renderHook } from '@testing-library/react-hooks';
import useFormNote, { HookDependencies } from './useFormNote'; import useFormNote, { HookDependencies } from './useFormNote';
import shim from '@joplin/lib/shim';
import Resource from '@joplin/lib/models/Resource';
const defaultFormNoteProps: HookDependencies = { const defaultFormNoteProps: HookDependencies = {
syncStarted: false, syncStarted: false,
@ -75,6 +77,8 @@ describe('useFormNote', () => {
title: 'Test Note!', title: 'Test Note!',
}); });
}); });
formNote.unmount();
}); });
// It seems this test is crashing the worker on CI (out of memory), so disabling it for now. // It seems this test is crashing the worker on CI (out of memory), so disabling it for now.
@ -109,4 +113,43 @@ describe('useFormNote', () => {
// }); // });
// }); // });
test('should refresh resource infos when changed outside the editor', async () => {
let note = await Note.save({});
note = await shim.attachFileToNote(note, __filename);
const resourceIds = Note.linkedItemIds(note.body);
const resource = await Resource.load(resourceIds[0]);
const makeFormNoteProps = (syncStarted: boolean, decryptionStarted: boolean): HookDependencies => {
return {
...defaultFormNoteProps,
syncStarted,
decryptionStarted,
noteId: note.id,
};
};
const formNote = renderHook(props => useFormNote(props), {
initialProps: makeFormNoteProps(true, false),
});
await formNote.waitFor(() => {
return Object.values(formNote.result.current.resourceInfos).length > 0;
});
const initialResourceInfos = formNote.result.current.resourceInfos;
expect(initialResourceInfos).toMatchObject({
[resource.id]: { item: { id: resource.id } },
});
await act(async () => {
await Resource.save({ ...resource, filename: 'test.ts' });
});
await formNote.waitFor(() => {
const resourceInfo = formNote.result.current.resourceInfos[resource.id];
expect(resourceInfo.item).toMatchObject({
id: resource.id, filename: 'test.ts',
});
});
formNote.unmount();
});
}); });

View File

@ -6,15 +6,15 @@ import { handleResourceDownloadMode } from './resourceHandling';
import { splitHtml } from '@joplin/renderer/HtmlToHtml'; import { splitHtml } from '@joplin/renderer/HtmlToHtml';
import Setting from '@joplin/lib/models/Setting'; import Setting from '@joplin/lib/models/Setting';
import usePrevious from '../../hooks/usePrevious'; import usePrevious from '../../hooks/usePrevious';
import ResourceEditWatcher from '@joplin/lib/services/ResourceEditWatcher/index';
import { MarkupToHtml } from '@joplin/renderer'; import { MarkupToHtml } from '@joplin/renderer';
import Note from '@joplin/lib/models/Note'; import Note from '@joplin/lib/models/Note';
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher'; import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
import { NoteEntity } from '@joplin/lib/services/database/types'; import { NoteEntity } from '@joplin/lib/services/database/types';
import { focus } from '@joplin/lib/utils/focusHandler'; import { focus } from '@joplin/lib/utils/focusHandler';
import Logger from '@joplin/utils/Logger'; import Logger from '@joplin/utils/Logger';
import eventManager, { EventName } from '@joplin/lib/eventManager';
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
const logger = Logger.create('useFormNote'); const logger = Logger.create('useFormNote');
@ -37,20 +37,18 @@ export interface HookDependencies {
type MapFormNoteCallback = (previousFormNote: FormNote)=> FormNote; type MapFormNoteCallback = (previousFormNote: FormNote)=> FormNote;
export type OnSetFormNote = (newFormNote: FormNote|MapFormNoteCallback)=> void; export type OnSetFormNote = (newFormNote: FormNote|MapFormNoteCallback)=> void;
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied function installResourceChangeHandler(onResourceChangeHandler: ()=> void) {
function installResourceChangeHandler(onResourceChangeHandler: Function) {
ResourceFetcher.instance().on('downloadComplete', onResourceChangeHandler); ResourceFetcher.instance().on('downloadComplete', onResourceChangeHandler);
ResourceFetcher.instance().on('downloadStarted', onResourceChangeHandler); ResourceFetcher.instance().on('downloadStarted', onResourceChangeHandler);
DecryptionWorker.instance().on('resourceDecrypted', onResourceChangeHandler); DecryptionWorker.instance().on('resourceDecrypted', onResourceChangeHandler);
ResourceEditWatcher.instance().on('resourceChange', onResourceChangeHandler); eventManager.on(EventName.ResourceChange, onResourceChangeHandler);
} }
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied function uninstallResourceChangeHandler(onResourceChangeHandler: ()=> void) {
function uninstallResourceChangeHandler(onResourceChangeHandler: Function) {
ResourceFetcher.instance().off('downloadComplete', onResourceChangeHandler); ResourceFetcher.instance().off('downloadComplete', onResourceChangeHandler);
ResourceFetcher.instance().off('downloadStarted', onResourceChangeHandler); ResourceFetcher.instance().off('downloadStarted', onResourceChangeHandler);
DecryptionWorker.instance().off('resourceDecrypted', onResourceChangeHandler); DecryptionWorker.instance().off('resourceDecrypted', onResourceChangeHandler);
ResourceEditWatcher.instance().off('resourceChange', onResourceChangeHandler); eventManager.off(EventName.ResourceChange, onResourceChangeHandler);
} }
function resourceInfosChanged(a: ResourceInfos, b: ResourceInfos): boolean { function resourceInfosChanged(a: ResourceInfos, b: ResourceInfos): boolean {
@ -258,7 +256,8 @@ export default function useFormNote(dependencies: HookDependencies) {
const resourceIds = await Note.linkedResourceIds(formNote.body); const resourceIds = await Note.linkedResourceIds(formNote.body);
if (!event || resourceIds.indexOf(event.id) >= 0) { if (!event || resourceIds.indexOf(event.id) >= 0) {
clearResourceCache(); clearResourceCache();
setResourceInfos(await attachedResources(formNote.body)); const newResourceInfos = await attachedResources(formNote.body);
setResourceInfos(newResourceInfos);
} }
}, [formNote.body]); }, [formNote.body]);

View File

@ -637,7 +637,7 @@ export default class Resource extends BaseItem {
} }
const output = await super.save(resource, options); const output = await super.save(resource, options);
if (isNew) eventManager.emit(EventName.ResourceCreate); eventManager.emit(isNew ? EventName.ResourceCreate : EventName.ResourceChange, { id: output.id });
return output; return output;
} }