You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-13 00:10:37 +02:00
Mobile: Plugins: Fix event listener memory leak when disabling/uninstalling plugins (#10280)
Co-authored-by: Laurent Cozic <laurent22@users.noreply.github.com>
This commit is contained in:
@ -49,7 +49,7 @@ export default class Joplin {
|
||||
this.data_ = new JoplinData(plugin);
|
||||
this.plugins_ = new JoplinPlugins(plugin);
|
||||
this.imaging_ = new JoplinImaging(implementation.imaging);
|
||||
this.workspace_ = new JoplinWorkspace(store);
|
||||
this.workspace_ = new JoplinWorkspace(plugin, store);
|
||||
this.filters_ = new JoplinFilters();
|
||||
this.commands_ = new JoplinCommands();
|
||||
this.views_ = new JoplinViews(implementation.joplin.views, plugin, store);
|
||||
|
@ -5,6 +5,7 @@ import Setting, { SettingItem as InternalSettingItem, SettingSectionSource } fro
|
||||
import Plugin from '../Plugin';
|
||||
import getPluginNamespacedSettingKey from '../utils/getPluginNamespacedSettingKey';
|
||||
import getPluginSettingKeyPrefix from '../utils/getPluginSettingKeyPrefix';
|
||||
import makeListener from '../utils/makeListener';
|
||||
import { SettingItem, SettingSection } from './types';
|
||||
|
||||
// That's all the plugin as of 27/08/21 - any new plugin after that will not be
|
||||
@ -180,12 +181,13 @@ export default class JoplinSettings {
|
||||
*/
|
||||
public async onChange(handler: ChangeHandler): Promise<void> {
|
||||
// Filter out keys that are not related to this plugin
|
||||
eventManager.on(EventName.SettingsChange, (event: ChangeEvent) => {
|
||||
const listener = (event: ChangeEvent) => {
|
||||
const keys = event.keys
|
||||
.filter(k => k.indexOf(getPluginSettingKeyPrefix(this.plugin_.id)) === 0)
|
||||
.map(k => k.substr(getPluginSettingKeyPrefix(this.plugin_.id).length));
|
||||
if (!keys.length) return;
|
||||
handler({ keys });
|
||||
});
|
||||
};
|
||||
makeListener(this.plugin_, eventManager, EventName.SettingsChange, listener);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable multiline-comment-style */
|
||||
|
||||
import Plugin from '../Plugin';
|
||||
import { ModelType } from '../../../BaseModel';
|
||||
import eventManager, { EventName } from '../../../eventManager';
|
||||
import Setting from '../../../models/Setting';
|
||||
@ -76,14 +77,14 @@ type ResourceChangeHandler = WorkspaceEventHandler<ResourceChangeEvent>;
|
||||
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
|
||||
*/
|
||||
export default class JoplinWorkspace {
|
||||
// TODO: unregister events when plugin is closed or disabled
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
private store: any;
|
||||
private plugin: Plugin;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
public constructor(store: any) {
|
||||
public constructor(plugin: Plugin, store: any) {
|
||||
this.store = store;
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,6 +93,10 @@ export default class JoplinWorkspace {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
public async onNoteSelectionChange(callback: WorkspaceEventHandler<NoteSelectionChangeEvent>): Promise<Disposable> {
|
||||
eventManager.appStateOn('selectedNoteIds', callback);
|
||||
const dispose = () => {
|
||||
eventManager.appStateOff('selectedNoteIds', callback);
|
||||
};
|
||||
this.plugin.addOnUnloadListener(dispose);
|
||||
|
||||
return {};
|
||||
|
||||
@ -108,6 +113,10 @@ export default class JoplinWorkspace {
|
||||
*/
|
||||
public async onNoteContentChange(callback: WorkspaceEventHandler<NoteContentChangeEvent>) {
|
||||
eventManager.on(EventName.NoteContentChange, callback);
|
||||
const dispose = () => {
|
||||
eventManager.off(EventName.NoteContentChange, callback);
|
||||
};
|
||||
this.plugin.addOnUnloadListener(dispose);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -125,7 +134,7 @@ export default class JoplinWorkspace {
|
||||
});
|
||||
};
|
||||
|
||||
return makeListener(eventManager, EventName.ItemChange, wrapperHandler);
|
||||
return makeListener(this.plugin, eventManager, EventName.ItemChange, wrapperHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,28 +142,28 @@ export default class JoplinWorkspace {
|
||||
* called when a resource is added or deleted.
|
||||
*/
|
||||
public async onResourceChange(handler: ResourceChangeHandler): Promise<void> {
|
||||
makeListener(eventManager, EventName.ResourceChange, handler);
|
||||
makeListener(this.plugin, eventManager, EventName.ResourceChange, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an alarm associated with a to-do is triggered.
|
||||
*/
|
||||
public async onNoteAlarmTrigger(handler: WorkspaceEventHandler<NoteAlarmTriggerEvent>): Promise<Disposable> {
|
||||
return makeListener(eventManager, EventName.NoteAlarmTrigger, handler);
|
||||
return makeListener(this.plugin, eventManager, EventName.NoteAlarmTrigger, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the synchronisation process is starting.
|
||||
*/
|
||||
public async onSyncStart(handler: SyncStartHandler): Promise<Disposable> {
|
||||
return makeListener(eventManager, EventName.SyncStart, handler);
|
||||
return makeListener(this.plugin, eventManager, EventName.SyncStart, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the synchronisation process has finished.
|
||||
*/
|
||||
public async onSyncComplete(callback: WorkspaceEventHandler<SyncCompleteEvent>): Promise<Disposable> {
|
||||
return makeListener(eventManager, EventName.SyncComplete, callback);
|
||||
return makeListener(this.plugin, eventManager, EventName.SyncComplete, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -165,6 +174,9 @@ export default class JoplinWorkspace {
|
||||
*/
|
||||
public filterEditorContextMenu(handler: FilterHandler<EditContextMenuFilterObject>) {
|
||||
eventManager.filterOn('editorContextMenu', handler);
|
||||
this.plugin.addOnUnloadListener(() => {
|
||||
eventManager.filterOff('editorContextMenu', handler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user