mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 03:29:02 +01:00 
			
		
		
		
	fix(react/settings): hook leak after closing tabs
This commit is contained in:
		
							parent
							
								
									3837466cb3
								
							
						
					
					
						commit
						73ff41f2b2
					
				| @ -2,6 +2,7 @@ import FlexContainer from "./flex_container.js"; | ||||
| import appContext, { type CommandData, type CommandListenerData, type EventData, type EventNames, type NoteSwitchedContext } from "../../components/app_context.js"; | ||||
| import type BasicWidget from "../basic_widget.js"; | ||||
| import type NoteContext from "../../components/note_context.js"; | ||||
| import Component from "../../components/component.js"; | ||||
| 
 | ||||
| interface NoteContextEvent { | ||||
|     noteContext: NoteContext; | ||||
| @ -152,6 +153,8 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> { | ||||
|         for (const ntxId of ntxIds) { | ||||
|             this.$widget.find(`[data-ntx-id="${ntxId}"]`).remove(); | ||||
| 
 | ||||
|             const widget = this.widgets[ntxId]; | ||||
|             recursiveCleanup(widget); | ||||
|             delete this.widgets[ntxId]; | ||||
|         } | ||||
|     } | ||||
| @ -237,3 +240,12 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> { | ||||
|         return Promise.all(promises); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| function recursiveCleanup(widget: Component) { | ||||
|     for (const child of widget.children) { | ||||
|         recursiveCleanup(child); | ||||
|     } | ||||
|     if ("cleanup" in widget && typeof widget.cleanup === "function") { | ||||
|         widget.cleanup(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -22,11 +22,18 @@ export default abstract class ReactBasicWidget extends BasicWidget { | ||||
|  * @returns the rendered wrapped DOM element. | ||||
|  */ | ||||
| export function renderReactWidget(parentComponent: Component, el: JSX.Element) { | ||||
|     const renderContainer = new DocumentFragment(); | ||||
|     return renderReactWidgetAtElement(parentComponent, el, new DocumentFragment()).children(); | ||||
| } | ||||
| 
 | ||||
| export function renderReactWidgetAtElement(parentComponent: Component, el: JSX.Element, container: Element | DocumentFragment) { | ||||
|     render(( | ||||
|         <ParentComponent.Provider value={parentComponent}> | ||||
|             {el} | ||||
|         </ParentComponent.Provider> | ||||
|     ), renderContainer); | ||||
|     return $(renderContainer.children) as JQuery<HTMLElement>; | ||||
|     ), container); | ||||
|     return $(container) as JQuery<HTMLElement>; | ||||
| } | ||||
| 
 | ||||
| export function disposeReactWidget(container: Element) { | ||||
|     render(null, container); | ||||
| } | ||||
| @ -68,9 +68,17 @@ export default function useTriliumEvent<T extends EventNames>(eventName: T, hand | ||||
|                 return; | ||||
|             } | ||||
|      | ||||
|             // Remove the event handler from the array.
 | ||||
|             const newEventHandlers = eventHandlers.filter(e => e !== handler); | ||||
|             registeredHandlers.get(parentWidget)?.set(eventName, newEventHandlers);         | ||||
|             // Remove the event handler from the array.            
 | ||||
|             const newEventHandlers = eventHandlers.filter(e => e !== handler);             | ||||
|             if (newEventHandlers.length) { | ||||
|                 registeredHandlers.get(parentWidget)?.set(eventName, newEventHandlers);         | ||||
|             } else { | ||||
|                 registeredHandlers.get(parentWidget)?.delete(eventName); | ||||
|             } | ||||
| 
 | ||||
|             if (!registeredHandlers.get(parentWidget)?.size) { | ||||
|                 registeredHandlers.delete(parentWidget); | ||||
|             } | ||||
|         }; | ||||
|     }, [ eventName, parentWidget, handler ]); | ||||
| } | ||||
|  | ||||
| @ -7,7 +7,7 @@ import { t } from "../../services/i18n.js"; | ||||
| import type BasicWidget from "../basic_widget.js"; | ||||
| import type { JSX } from "preact/jsx-runtime"; | ||||
| import AppearanceSettings from "./options/appearance.jsx"; | ||||
| import { renderReactWidget } from "../react/ReactBasicWidget.jsx"; | ||||
| import { disposeReactWidget, renderReactWidget, renderReactWidgetAtElement } from "../react/ReactBasicWidget.jsx"; | ||||
| import ImageSettings from "./options/images.jsx"; | ||||
| import AdvancedSettings from "./options/advanced.jsx"; | ||||
| import InternationalizationOptions from "./options/i18n.jsx"; | ||||
| @ -21,6 +21,7 @@ import TextNoteSettings from "./options/text_notes.jsx"; | ||||
| import CodeNoteSettings from "./options/code_notes.jsx"; | ||||
| import OtherSettings from "./options/other.jsx"; | ||||
| import BackendLogWidget from "./content/backend_log.js"; | ||||
| import { unmountComponentAtNode } from "preact/compat"; | ||||
| 
 | ||||
| const TPL = /*html*/`<div class="note-detail-content-widget note-detail-printable">
 | ||||
|     <style> | ||||
| @ -120,7 +121,18 @@ export default class ContentWidgetTypeWidget extends TypeWidget { | ||||
|         } | ||||
| 
 | ||||
|         // React widget.
 | ||||
|         this.$content.append(renderReactWidget(this, contentWidgets)); | ||||
|         renderReactWidgetAtElement(this, contentWidgets, this.$content[0]); | ||||
|     } | ||||
| 
 | ||||
|     cleanup(): void { | ||||
|         if (this.noteId) { | ||||
|             const contentWidgets = (CONTENT_WIDGETS as Record<string, (typeof NoteContextAwareWidget[] | JSX.Element)>)[this.noteId]; | ||||
|             if (contentWidgets && !Array.isArray(contentWidgets)) { | ||||
|                 disposeReactWidget(this.$content[0]); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         super.cleanup(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -101,4 +101,8 @@ export default abstract class TypeWidget extends NoteContextAwareWidget { | ||||
|             return Promise.resolve(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     cleanup(): void { | ||||
|         super.cleanup(); | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran