mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Desktop: Fixes #11129: Improve performance by allowing note list background timers to be cancelled (#11133)
This commit is contained in:
parent
42ab9ecd95
commit
eda2c69334
@ -374,6 +374,7 @@ packages/app-desktop/gui/NoteListItem/utils/useItemElement.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useItemEventHandlers.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useOnContextMenu.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRenderedNote.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRootElement.test.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRootElement.js
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js
|
||||
packages/app-desktop/gui/NotePropertiesDialog.js
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -351,6 +351,7 @@ packages/app-desktop/gui/NoteListItem/utils/useItemElement.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useItemEventHandlers.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useOnContextMenu.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRenderedNote.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRootElement.test.js
|
||||
packages/app-desktop/gui/NoteListItem/utils/useRootElement.js
|
||||
packages/app-desktop/gui/NoteListWrapper/NoteListWrapper.js
|
||||
packages/app-desktop/gui/NotePropertiesDialog.js
|
||||
|
@ -0,0 +1,55 @@
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
import useRootElement from './useRootElement';
|
||||
|
||||
describe('useRootElement', () => {
|
||||
beforeEach(() => {
|
||||
jest.useFakeTimers({ advanceTimers: true });
|
||||
});
|
||||
|
||||
test('should find an element with a matching ID', async () => {
|
||||
const testElement = document.createElement('div');
|
||||
testElement.id = 'test-element-id';
|
||||
document.body.appendChild(testElement);
|
||||
|
||||
const { result } = renderHook(useRootElement, {
|
||||
initialProps: testElement.id,
|
||||
});
|
||||
await act(async () => {
|
||||
await jest.advanceTimersByTimeAsync(100);
|
||||
});
|
||||
expect(result.current).toBe(testElement);
|
||||
|
||||
testElement.remove();
|
||||
});
|
||||
|
||||
test('should redo the element search when the elementId prop changes', async () => {
|
||||
const testElement = document.createElement('div');
|
||||
document.body.appendChild(testElement);
|
||||
|
||||
const { rerender, result } = renderHook(useRootElement, {
|
||||
initialProps: 'some-id-here',
|
||||
});
|
||||
await jest.advanceTimersByTimeAsync(100);
|
||||
expect(result.current).toBe(null);
|
||||
|
||||
// Searching for another non-existent ID: Should not match
|
||||
rerender('updated-id');
|
||||
await jest.advanceTimersByTimeAsync(100);
|
||||
expect(result.current).toBe(null);
|
||||
|
||||
// Should not match the first element if its ID is set to the original (search
|
||||
// should be cancelled).
|
||||
testElement.id = 'some-id-here';
|
||||
await jest.advanceTimersByTimeAsync(100);
|
||||
expect(result.current).toBe(null);
|
||||
|
||||
// Should match if the element ID changes to the updated ID.
|
||||
await act(async () => {
|
||||
testElement.id = 'updated-id';
|
||||
await jest.advanceTimersByTimeAsync(100);
|
||||
});
|
||||
expect(result.current).toBe(testElement);
|
||||
|
||||
testElement.remove();
|
||||
});
|
||||
});
|
@ -6,7 +6,7 @@ const useRootElement = (elementId: string) => {
|
||||
const [rootElement, setRootElement] = useState<HTMLDivElement>(null);
|
||||
|
||||
useAsyncEffect(async (event) => {
|
||||
const element = await waitForElement(document, elementId);
|
||||
const element = await waitForElement(document, elementId, event);
|
||||
if (event.cancelled) return;
|
||||
setRootElement(element);
|
||||
}, [document, elementId]);
|
||||
|
@ -24,9 +24,9 @@ jest.mock('@electron/remote', () => {
|
||||
|
||||
// Import after mocking problematic libraries
|
||||
const { afterEachCleanUp, afterAllCleanUp } = require('@joplin/lib/testing/test-utils.js');
|
||||
const React = require('react');
|
||||
|
||||
|
||||
shimInit({ nodeSqlite: sqlite3 });
|
||||
shimInit({ nodeSqlite: sqlite3, React });
|
||||
|
||||
afterEach(async () => {
|
||||
await afterEachCleanUp();
|
||||
|
@ -7,13 +7,15 @@ export const isInsideContainer = (node: any, className: string): boolean => {
|
||||
return false;
|
||||
};
|
||||
|
||||
interface CancelEvent { cancelled: boolean }
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
export const waitForElement = async (parent: any, id: string): Promise<any> => {
|
||||
export const waitForElement = async (parent: any, id: string, cancelEvent?: CancelEvent): Promise<any> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const iid = setInterval(() => {
|
||||
try {
|
||||
const element = parent.getElementById(id);
|
||||
if (element) {
|
||||
if (element || cancelEvent?.cancelled) {
|
||||
clearInterval(iid);
|
||||
resolve(element);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user