You've already forked joplin
							
							
				mirror of
				https://github.com/laurent22/joplin.git
				synced 2025-10-31 00:07:48 +02:00 
			
		
		
		
	Desktop: Fixes #11129: Improve performance by allowing note list background timers to be cancelled (#11133)
This commit is contained in:
		| @@ -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); | ||||
| 				} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user