2023-06-30 10:55:56 +02:00
|
|
|
/* eslint-disable multiline-comment-style */
|
|
|
|
|
2020-12-01 16:08:41 +02:00
|
|
|
import { ModelType } from '../../../BaseModel';
|
2020-11-05 18:58:23 +02:00
|
|
|
import eventManager from '../../../eventManager';
|
2021-01-04 18:49:59 +02:00
|
|
|
import Setting from '../../../models/Setting';
|
|
|
|
import { FolderEntity } from '../../database/types';
|
2020-12-01 16:08:41 +02:00
|
|
|
import makeListener from '../utils/makeListener';
|
2021-12-27 18:37:50 +02:00
|
|
|
import { Disposable, MenuItem } from './types';
|
2020-10-09 19:35:46 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @ignore
|
|
|
|
*/
|
2021-01-22 19:41:11 +02:00
|
|
|
import Note from '../../../models/Note';
|
2020-10-09 19:35:46 +02:00
|
|
|
|
2021-01-04 18:49:59 +02:00
|
|
|
/**
|
|
|
|
* @ignore
|
|
|
|
*/
|
2021-01-22 19:41:11 +02:00
|
|
|
import Folder from '../../../models/Folder';
|
2021-01-04 18:49:59 +02:00
|
|
|
|
2021-12-27 18:37:50 +02:00
|
|
|
export interface EditContextMenuFilterObject {
|
|
|
|
items: MenuItem[];
|
|
|
|
}
|
|
|
|
|
|
|
|
type FilterHandler<T> = (object: T)=> Promise<void>;
|
|
|
|
|
2020-12-01 16:08:41 +02:00
|
|
|
enum ItemChangeEventType {
|
|
|
|
Create = 1,
|
|
|
|
Update = 2,
|
|
|
|
Delete = 3,
|
|
|
|
}
|
|
|
|
|
|
|
|
interface ItemChangeEvent {
|
|
|
|
id: string;
|
|
|
|
event: ItemChangeEventType;
|
|
|
|
}
|
|
|
|
|
2020-12-08 21:03:22 +02:00
|
|
|
interface SyncStartEvent {
|
|
|
|
// Tells whether there were errors during sync or not. The log will
|
|
|
|
// have the complete information about any error.
|
|
|
|
withErrors: boolean;
|
|
|
|
}
|
|
|
|
|
2021-12-30 12:25:39 +02:00
|
|
|
interface ResourceChangeEvent {
|
|
|
|
id: string;
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:08:41 +02:00
|
|
|
type ItemChangeHandler = (event: ItemChangeEvent)=> void;
|
2020-12-08 21:03:22 +02:00
|
|
|
type SyncStartHandler = (event: SyncStartEvent)=> void;
|
2021-12-30 12:25:39 +02:00
|
|
|
type ResourceChangeHandler = (event: ResourceChangeEvent)=> void;
|
2020-12-01 16:08:41 +02:00
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
/**
|
2020-12-01 16:08:41 +02:00
|
|
|
* The workspace service provides access to all the parts of Joplin that
|
|
|
|
* are being worked on - i.e. the currently selected notes or notebooks as
|
|
|
|
* well as various related events, such as when a new note is selected, or
|
|
|
|
* when the note content changes.
|
2020-10-09 19:35:46 +02:00
|
|
|
*
|
2020-11-05 18:58:23 +02:00
|
|
|
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/packages/app-cli/tests/support/plugins)
|
2020-10-09 19:35:46 +02:00
|
|
|
*/
|
|
|
|
export default class JoplinWorkspace {
|
|
|
|
// TODO: unregister events when plugin is closed or disabled
|
|
|
|
|
|
|
|
private store: any;
|
|
|
|
|
2021-12-30 12:25:39 +02:00
|
|
|
public constructor(store: any) {
|
2020-10-09 19:35:46 +02:00
|
|
|
this.store = store;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when a new note or notes are selected.
|
|
|
|
*/
|
2023-06-30 11:30:29 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
2020-12-01 16:08:41 +02:00
|
|
|
public async onNoteSelectionChange(callback: Function): Promise<Disposable> {
|
2020-10-09 19:35:46 +02:00
|
|
|
eventManager.appStateOn('selectedNoteIds', callback);
|
2020-12-01 16:08:41 +02:00
|
|
|
|
|
|
|
return {};
|
|
|
|
|
|
|
|
// return {
|
|
|
|
// dispose: () => {
|
|
|
|
// eventManager.appStateOff('selectedNoteIds', callback);
|
|
|
|
// }
|
|
|
|
// };
|
2020-10-09 19:35:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when the content of a note changes.
|
2020-12-01 16:08:41 +02:00
|
|
|
* @deprecated Use `onNoteChange()` instead, which is reliably triggered whenever the note content, or any note property changes.
|
2020-10-09 19:35:46 +02:00
|
|
|
*/
|
2023-06-30 11:30:29 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
2020-12-01 16:08:41 +02:00
|
|
|
public async onNoteContentChange(callback: Function) {
|
2020-10-09 19:35:46 +02:00
|
|
|
eventManager.on('noteContentChange', callback);
|
|
|
|
}
|
|
|
|
|
2020-12-01 16:08:41 +02:00
|
|
|
/**
|
2021-02-07 17:29:36 +02:00
|
|
|
* Called when the content of the current note changes.
|
2020-12-01 16:08:41 +02:00
|
|
|
*/
|
|
|
|
public async onNoteChange(handler: ItemChangeHandler): Promise<Disposable> {
|
|
|
|
const wrapperHandler = (event: any) => {
|
|
|
|
if (event.itemType !== ModelType.Note) return;
|
2021-02-07 17:29:36 +02:00
|
|
|
if (!this.store.getState().selectedNoteIds.includes(event.itemId)) return;
|
2020-12-01 16:08:41 +02:00
|
|
|
|
|
|
|
handler({
|
|
|
|
id: event.itemId,
|
|
|
|
event: event.eventType,
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
return makeListener(eventManager, 'itemChange', wrapperHandler);
|
|
|
|
}
|
|
|
|
|
2021-12-30 12:25:39 +02:00
|
|
|
/**
|
|
|
|
* Called when a resource is changed. Currently this handled will not be
|
|
|
|
* called when a resource is added or deleted.
|
|
|
|
*/
|
|
|
|
public async onResourceChange(handler: ResourceChangeHandler): Promise<void> {
|
|
|
|
makeListener(eventManager, 'resourceChange', handler);
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
/**
|
|
|
|
* Called when an alarm associated with a to-do is triggered.
|
|
|
|
*/
|
2023-06-30 11:30:29 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
2020-12-08 21:03:22 +02:00
|
|
|
public async onNoteAlarmTrigger(handler: Function): Promise<Disposable> {
|
|
|
|
return makeListener(eventManager, 'noteAlarmTrigger', handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when the synchronisation process is starting.
|
|
|
|
*/
|
|
|
|
public async onSyncStart(handler: SyncStartHandler): Promise<Disposable> {
|
|
|
|
return makeListener(eventManager, 'syncStart', handler);
|
2020-10-09 19:35:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called when the synchronisation process has finished.
|
|
|
|
*/
|
2023-06-30 11:30:29 +02:00
|
|
|
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
2020-12-01 16:08:41 +02:00
|
|
|
public async onSyncComplete(callback: Function): Promise<Disposable> {
|
|
|
|
return makeListener(eventManager, 'syncComplete', callback);
|
2020-10-09 19:35:46 +02:00
|
|
|
}
|
|
|
|
|
2021-12-27 18:37:50 +02:00
|
|
|
/**
|
|
|
|
* Called just before the editor context menu is about to open. Allows
|
|
|
|
* adding items to it.
|
|
|
|
*/
|
|
|
|
public filterEditorContextMenu(handler: FilterHandler<EditContextMenuFilterObject>) {
|
|
|
|
eventManager.filterOn('editorContextMenu', handler);
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
/**
|
|
|
|
* Gets the currently selected note
|
|
|
|
*/
|
2020-12-01 16:08:41 +02:00
|
|
|
public async selectedNote(): Promise<any> {
|
2020-10-09 19:35:46 +02:00
|
|
|
const noteIds = this.store.getState().selectedNoteIds;
|
|
|
|
if (noteIds.length !== 1) { return null; }
|
|
|
|
return Note.load(noteIds[0]);
|
|
|
|
}
|
|
|
|
|
2021-01-04 18:49:59 +02:00
|
|
|
/**
|
|
|
|
* Gets the currently selected folder. In some cases, for example during
|
|
|
|
* search or when viewing a tag, no folder is actually selected in the user
|
|
|
|
* interface. In that case, that function would return the last selected
|
|
|
|
* folder.
|
|
|
|
*/
|
|
|
|
public async selectedFolder(): Promise<FolderEntity> {
|
|
|
|
const folderId = Setting.value('activeFolderId');
|
|
|
|
return folderId ? await Folder.load(folderId) : null;
|
|
|
|
}
|
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
/**
|
|
|
|
* Gets the IDs of the selected notes (can be zero, one, or many). Use the data API to retrieve information about these notes.
|
|
|
|
*/
|
2020-12-01 16:08:41 +02:00
|
|
|
public async selectedNoteIds(): Promise<string[]> {
|
2020-10-09 19:35:46 +02:00
|
|
|
return this.store.getState().selectedNoteIds.slice();
|
|
|
|
}
|
2021-12-27 18:37:50 +02:00
|
|
|
|
2020-10-09 19:35:46 +02:00
|
|
|
}
|