diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f71418..a956c81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - None +## [1.3.0] - 2021-03-09 + +### Added + +- User option (`Add tab behavior`) to force horizontal or vertical layout mode ([#2](https://github.com/benji300/joplin-note-tabs/issues/2)) +- User option (`Unpin active tab behavior`) to select behavior when unpinning the active tab ([#25](https://github.com/benji300/joplin-note-tabs/issues/25)) +- User option (`Force tabs layout`) to specify type (temporary or pinned) for new tabs ([#35](https://github.com/benji300/joplin-note-tabs/issues/35)) +- Ability to scroll tabs and breadcrums horizontally without holding `shift` key ([#34](https://github.com/benji300/joplin-note-tabs/issues/34)) + +### Changed + +- Ensure visibility of active tab, i.e. selected note ([#32](https://github.com/benji300/joplin-note-tabs/issues/32)) +- Plugin command labels (Removed `Tabs:` prefix) +- Breadcrumbs and navigation icon styles + +### Removed + +- User option (`Minimum breadcrumb width`) to specify minimum width of a single breadcrumb + ## [1.2.1] - 2021-02-23 ### Fixed diff --git a/README.md b/README.md index 881822f..ba2d597 100644 --- a/README.md +++ b/README.md @@ -103,17 +103,17 @@ By default the panel will be on the right side of the screen, this can be adjust This plugin provides additional commands as described in the following table. -| Command Label | Command ID | Description | Menu contexts | -| ------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | -| Tabs: Pin note | `tabsPinNote` | Pin selected note(s) to the tabs. | `Tools>Tabs`, `NoteListContext`, `EditorContext`, `Command palette` | -| Tabs: Unpin note | `tabsUnpinNote` | Unpin selected note(s) from the tabs. | `Tools>Tabs`, `Command palette` | -| Tabs: Switch to last active tab | `tabsSwitchLastActive` | Switch to the last active tab, i.e. to previous selected note. | `Tools>Tabs`, `Command palette` | -| Tabs: Switch to left tab | `tabsSwitchLeft` | Switch to the left tab next to the active, i.e. select the left note. | `Tools>Tabs`, `Command palette` | -| Tabs: Switch to right tab | `tabsSwitchRight` | Switch to the right tab next to the active, i.e. select the right note. | `Tools>Tabs`, `Command palette` | -| Tabs: Move tab left | `tabsMoveLeft` | Move active tab one position to the left. | `Tools>Tabs`, `Command palette` | -| Tabs: Move tab right | `tabsMoveRight` | Move active tab one position to the right. | `Tools>Tabs`, `Command palette` | -| Tabs: Remove all pinned tabs | `tabsClear` | Remove all pinned tabs. In case no note is selected, the tabs list might be empty afterwards. | `Tools>Tabs`, `Command palette` | -| Tabs: Toggle visibility | `tabsToggleVisibility` | Toggle panel visibility. | `Tools>Tabs`, `Command palette` | +| Command Label | Command ID | Description | Menu contexts | +| ------------------------- | ---------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | +| Pin note to Tabs | `tabsPinNote` | Pin selected note(s) to the tabs. | `Tools>Tabs`, `NoteListContext`, `EditorContext`, `Command palette` | +| Unpin note from Tabs | `tabsUnpinNote` | Unpin selected note(s) from the tabs. | `Tools>Tabs`, `Command palette` | +| Switch to last active Tab | `tabsSwitchLastActive` | Switch to the last active tab, i.e. to previous selected note. | `Tools>Tabs`, `Command palette` | +| Switch to left Tab | `tabsSwitchLeft` | Switch to the left tab next to the active, i.e. select the left note. | `Tools>Tabs`, `Command palette` | +| Switch to right Tab | `tabsSwitchRight` | Switch to the right tab next to the active, i.e. select the right note. | `Tools>Tabs`, `Command palette` | +| Move active Tab left | `tabsMoveLeft` | Move active tab one position to the left. | `Tools>Tabs`, `Command palette` | +| Move active Tab right | `tabsMoveRight` | Move active tab one position to the right. | `Tools>Tabs`, `Command palette` | +| Remove all pinned Tabs | `tabsClear` | Remove all pinned tabs. In case no note is selected, the tabs list might be empty afterwards. | `Tools>Tabs`, `Command palette` | +| Toggle Tabs visibility | `tabsToggleVisibility` | Toggle panel visibility. | `Tools>Tabs`, `Command palette` | ### Keyboard shortcuts diff --git a/package-lock.json b/package-lock.json index b6f06e2..fdb9f00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "joplin-plugin-note-tabs", - "version": "1.2.1", + "version": "1.3.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 3a1579b..d87ad87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "joplin-plugin-note-tabs", - "version": "1.2.1", + "version": "1.3.0", "description": "Allows to open several notes at once in tabs and pin them.", "author": "Benji300", "homepage": "https://github.com/benji300/joplin-note-tabs", diff --git a/src/index.ts b/src/index.ts index 73dfd7b..9f62fb7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { MenuItem, MenuItemLocation } from 'api/types'; import { ChangeEvent } from 'api/JoplinSettings'; import { NoteTabType, NoteTabs } from './noteTabs'; import { LastActiveNote } from './lastActiveNote'; -import { Settings } from './settings'; +import { Settings, UnpinBehavior, AddBehavior } from './settings'; import { Panel } from './panel'; joplin.plugins.register({ @@ -27,48 +27,127 @@ joplin.plugins.register({ //#region HELPERS /** - * Add note as temporary tab, if not already has one. + * Add note as tab, if not already has one. */ async function addTab(noteId: string) { if (tabs.hasTab(noteId)) return; - if (tabs.indexOfTemp >= 0) { - // replace existing temporary tab... - tabs.replaceTemp(noteId); + // depending on settings - either add directly as pinned tab + const addAsPinned: boolean = settings.hasAddBehavior(AddBehavior.Pinned); + if (addAsPinned) { + await pinTab(noteId, true); } else { - // or add as new temporary tab at the end - await tabs.add(noteId, NoteTabType.Temporary); + // or as temporay tab + if (tabs.indexOfTemp >= 0) { + // replace existing temporary tab... + tabs.replaceTemp(noteId); + } else { + // or add as new temporary tab at the end + await tabs.add(noteId, NoteTabType.Temporary); + } } } /** * Add new or pin tab for handled note. Optionally at the specified index of targetId. */ - async function pinTab(note: any, addAsNew: boolean, targetId?: string) { - // do not pin completed todos if auto unpin is enabled - if (settings.unpinCompletedTodos && note.is_todo && note.todo_completed) return; + async function pinTab(noteId: string, addAsNew: boolean, targetId?: string) { + const note: any = await DATA.get(['notes', noteId], { fields: ['id', 'is_todo', 'todo_completed'] }); - if (tabs.hasTab(note.id)) { - // if note has already a tab, change type to pinned - await tabs.changeType(note.id, NoteTabType.Pinned); - } else { - // otherwise add as new one - if (addAsNew) await tabs.add(note.id, NoteTabType.Pinned, targetId); + if (note) { + // do not pin completed todos if auto unpin is enabled + if (settings.unpinCompletedTodos && note.is_todo && note.todo_completed) return; + + if (tabs.hasTab(note.id)) { + // if note has already a tab, change type to pinned + await tabs.changeType(note.id, NoteTabType.Pinned); + } else { + // otherwise add as new one + if (addAsNew) { + await tabs.add(note.id, NoteTabType.Pinned, targetId); + } + } } } + /** + * Open last active note (tab) (if still exists). + */ + async function openLastActiveNote(): Promise { + if (lastActiveNote.length < 2) return false; + + const lastActiveNoteId = lastActiveNote.id; + // return if an already removed tab is about to be restored + if (tabs.indexOf(lastActiveNoteId) < 0) return false; + + await COMMANDS.execute('openNote', lastActiveNoteId); + return true; + } + + /** + * Switch to left tab. + */ + async function switchTabLeft(noteId: string): Promise { + const index: number = tabs.indexOf(noteId); + if (index <= 0) return false; + + await COMMANDS.execute('openNote', tabs.get(index - 1).id); + return true; + } + + /** + * Switch to right tab. + */ + async function switchTabRight(noteId: string): Promise { + const index: number = tabs.indexOf(noteId); + if (index < 0) return false; + if (index == tabs.length - 1) return false; + + await COMMANDS.execute('openNote', tabs.get(index + 1).id); + return true; + } + /** * Remove or unpin note with handled id. */ async function removeTab(noteId: string) { const selectedNote: any = await WORKSPACE.selectedNote(); - // remove tab completely - await tabs.delete(noteId); - - // if note is the selected note, add as temp tab or replace existing one + // if noteId is the selected note - try to select another note depending on the settings if (selectedNote && selectedNote.id == noteId) { - await addTab(noteId); + let selected: boolean = false; + + // try to select the appropriate tab + switch (settings.unpinBehavior) { + case UnpinBehavior.LastActive: + selected = await openLastActiveNote(); + if (selected) break; + // fallthrough if no last active found + case UnpinBehavior.LeftTab: + selected = await switchTabLeft(noteId); + if (selected) break; + // fallthrough if no right tab found + case UnpinBehavior.RightTab: + selected = await switchTabRight(noteId); + if (selected) break; + // try to select left tab + selected = await switchTabLeft(noteId); + default: + break; + } + + // then remove note from tabs + await tabs.delete(noteId); + + // if no one was selected before + if (!selected) { + // re-add removed note as tab at the end + await addTab(noteId); + } + } else { + + // else simply remove note from tabs + await tabs.delete(noteId); } } @@ -80,25 +159,18 @@ joplin.plugins.register({ // Desc: Pin the selected note(s) to the tabs await COMMANDS.register({ name: 'tabsPinNote', - label: 'Tabs: Pin note', + label: 'Pin note to Tabs', iconName: 'fas fa-thumbtack', - enabledCondition: "someNotesSelected", + enabledCondition: 'someNotesSelected', execute: async (noteIds: string[], targetId?: string) => { // get selected note ids and return if empty let selectedNoteIds = noteIds; if (!selectedNoteIds) selectedNoteIds = await WORKSPACE.selectedNoteIds(); if (!selectedNoteIds) return; - // Add all handled note ids as pinned tabs. Optionally at the specified index of targetId. + // add all handled notes as pinned tabs. Optionally at the specified index of targetId. for (const noteId of selectedNoteIds) { - try { - const note: any = await DATA.get(['notes', noteId], { fields: ['id', 'is_todo', 'todo_completed'] }); - if (note) { - pinTab(note, true, targetId); - } - } catch (error) { - continue; - } + await pinTab(noteId, true, targetId); } await panel.updateWebview(); } @@ -108,9 +180,9 @@ joplin.plugins.register({ // Desc: Unpin the selected note(s) from the tabs await COMMANDS.register({ name: 'tabsUnpinNote', - label: 'Tabs: Unpin note', + label: 'Unpin note from Tabs', iconName: 'fas fa-times', - enabledCondition: "someNotesSelected", + enabledCondition: 'someNotesSelected', execute: async (noteIds: string[]) => { // get selected note ids and return if empty let selectedNoteIds = noteIds; @@ -129,9 +201,9 @@ joplin.plugins.register({ // Desc: Move active tab to left await COMMANDS.register({ name: 'tabsMoveLeft', - label: 'Tabs: Move tab left', + label: 'Move active Tab left', iconName: 'fas fa-chevron-left', - enabledCondition: "oneNoteSelected", + enabledCondition: 'oneNoteSelected', execute: async () => { const selectedNote: any = await WORKSPACE.selectedNote(); if (!selectedNote) return; @@ -147,9 +219,9 @@ joplin.plugins.register({ // Desc: Move active tab to right await COMMANDS.register({ name: 'tabsMoveRight', - label: 'Tabs: Move tab right', + label: 'Move active Tab right', iconName: 'fas fa-chevron-right', - enabledCondition: "oneNoteSelected", + enabledCondition: 'oneNoteSelected', execute: async () => { const selectedNote: any = await WORKSPACE.selectedNote(); if (!selectedNote) return; @@ -165,17 +237,11 @@ joplin.plugins.register({ // Desc: Switch to last active tab await COMMANDS.register({ name: 'tabsSwitchLastActive', - label: 'Tabs: Switch to last active tab', + label: 'Switch to last active Tab', iconName: 'fas fa-step-backward', - enabledCondition: "oneNoteSelected", + enabledCondition: 'oneNoteSelected', execute: async () => { - if (lastActiveNote.length < 2) return; - - // get the last active note from the queue - const lastActiveNoteId = lastActiveNote.id; - - // select note with stored id - await COMMANDS.execute('openNote', lastActiveNoteId); + await openLastActiveNote(); // updateWebview() is called from onNoteSelectionChange event } }); @@ -184,19 +250,14 @@ joplin.plugins.register({ // Desc: Switch to left tab, i.e. select left note await COMMANDS.register({ name: 'tabsSwitchLeft', - label: 'Tabs: Switch to left tab', + label: 'Switch to left Tab', iconName: 'fas fa-step-backward', - enabledCondition: "oneNoteSelected", + enabledCondition: 'oneNoteSelected', execute: async () => { const selectedNote: any = await WORKSPACE.selectedNote(); if (!selectedNote) return; - // check if note is not already first, otherwise exit - const index: number = tabs.indexOf(selectedNote.id); - if (index <= 0) return; - - // get id of left note and select it - await COMMANDS.execute('openNote', tabs.get(index - 1).id); + await switchTabLeft(selectedNote.id); // updateWebview() is called from onNoteSelectionChange event } }); @@ -205,20 +266,14 @@ joplin.plugins.register({ // Desc: Switch to right tab, i.e. select right note await COMMANDS.register({ name: 'tabsSwitchRight', - label: 'Tabs: Switch to right tab', + label: 'Switch to right Tab', iconName: 'fas fa-step-forward', - enabledCondition: "oneNoteSelected", + enabledCondition: 'oneNoteSelected', execute: async () => { const selectedNote: any = await WORKSPACE.selectedNote(); if (!selectedNote) return; - // check if note is not already last, otherwise exit - const index: number = tabs.indexOf(selectedNote.id); - if (index < 0) return; - if (index == tabs.length - 1) return; - - // get id of right note and select it - await COMMANDS.execute('openNote', tabs.get(index + 1).id); + await switchTabRight(selectedNote.id); // updateWebview() is called from onNoteSelectionChange event } }); @@ -227,11 +282,11 @@ joplin.plugins.register({ // Desc: Remove all pinned tabs await COMMANDS.register({ name: 'tabsClear', - label: 'Tabs: Remove all pinned tabs', + label: 'Remove all pinned Tabs', iconName: 'fas fa-times', execute: async () => { // ask user before removing tabs - const result: number = await DIALOGS.showMessageBox(`Remove all pinned tabs?`); + const result: number = await DIALOGS.showMessageBox('Do you really want to remove all pinned tabs?'); if (result) return; await settings.clearTabs(); @@ -251,7 +306,7 @@ joplin.plugins.register({ // Desc: Toggle panel visibility await COMMANDS.register({ name: 'tabsToggleVisibility', - label: 'Tabs: Toggle visibility', + label: 'Toggle Tabs visibility', iconName: 'fas fa-eye-slash', execute: async () => { await panel.toggleVisibility(); @@ -261,39 +316,39 @@ joplin.plugins.register({ // prepare commands menu const commandsSubMenu: MenuItem[] = [ { - commandName: "tabsPinNote", - label: 'Pin note' + commandName: 'tabsPinNote', + label: 'Pin note to Tabs' }, { - commandName: "tabsUnpinNote", - label: 'Unpin note' + commandName: 'tabsUnpinNote', + label: 'Unpin note from Tabs' }, { - commandName: "tabsSwitchLastActive", - label: 'Switch to last active tab' + commandName: 'tabsSwitchLastActive', + label: 'Switch to last active Tab' }, { - commandName: "tabsSwitchLeft", - label: 'Switch to left tab' + commandName: 'tabsSwitchLeft', + label: 'Switch to left Tab' }, { - commandName: "tabsSwitchRight", - label: 'Switch to right tab' + commandName: 'tabsSwitchRight', + label: 'Switch to right Tab' }, { - commandName: "tabsMoveLeft", - label: 'Move tab left' + commandName: 'tabsMoveLeft', + label: 'Move active Tab left' }, { - commandName: "tabsMoveRight", - label: 'Move tab right' + commandName: 'tabsMoveRight', + label: 'Move active Tab right' }, { - commandName: "tabsClear", - label: 'Remove all pinned tabs' + commandName: 'tabsClear', + label: 'Remove all pinned Tabs' }, { - commandName: "tabsToggleVisibility", + commandName: 'tabsToggleVisibility', label: 'Toggle panel visibility' } ]; @@ -309,10 +364,9 @@ joplin.plugins.register({ //#region EVENTS - let onChangeCnt = 0; + // let onChangeCnt = 0; SETTINGS.onChange(async (event: ChangeEvent) => { - // TODO remove - console.debug(`onChange() hits: ${onChangeCnt++}`); + // console.debug(`onChange() hits: ${onChangeCnt++}`); await settings.read(event); await panel.updateWebview(); }); @@ -339,18 +393,18 @@ joplin.plugins.register({ WORKSPACE.onNoteChange(async (ev: any) => { try { if (ev) { - // note was updated (ItemChangeEventType.Update) + // note was changed (ItemChangeEventType.Update) if (ev.event == 2) { - // get handled note and return if null + // get changed note and return if null const note: any = await DATA.get(['notes', ev.id], { fields: ['id', 'is_todo', 'todo_completed'] }); if (note == null) return; - // if auto pin is enabled and handled, pin to tabs + // if auto pin is enabled, pin changed note to tabs if (settings.pinEditedNotes) - await pinTab(note, false); + await pinTab(note.id, false); - // if auto unpin is enabled and handled note is a completed todo... + // if auto unpin is enabled and changed note is a completed todo... if (settings.unpinCompletedTodos && note.is_todo && note.todo_completed) await removeTab(note.id); } diff --git a/src/manifest.json b/src/manifest.json index 38e3e68..d408b50 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,7 +2,7 @@ "manifest_version": 1, "id": "joplin.plugin.note.tabs", "app_min_version": "1.6.7", - "version": "1.2.1", + "version": "1.3.0", "name": "Note Tabs", "description": "Allows to open several notes at once in tabs and pin them.", "author": "Benji300", diff --git a/src/noteTabs.ts b/src/noteTabs.ts index d29cd9e..cd36606 100644 --- a/src/noteTabs.ts +++ b/src/noteTabs.ts @@ -10,28 +10,26 @@ export enum NoteTabType { } /** - * Helper class to work with note tabs array. + * Definition of note tab entries. + */ +interface INoteTab { + // Joplin note ID + id: string, + // Type of the tab + type: NoteTabType +} + +/** + * Helper class to work with note tabs. * - Read settings array once at startup. * - Then work on this.tabs array. */ export class NoteTabs { - - /** - * Temporary array to work with tabs. - * - * Definition of one tab entry: - * [{ - * "id": "note id", - * "type": NoteTabType - * }] - */ - // private _tabs: any[]; - private _settings: Settings; /** - * Initialization of NoteTabs. - */ + * Initialization of NoteTabs. + */ constructor(settings: Settings) { this._settings = settings; } @@ -41,7 +39,7 @@ export class NoteTabs { /** * All note tabs. */ - get tabs(): any[] { + get tabs(): INoteTab[] { return this._settings.noteTabs; } @@ -71,19 +69,31 @@ export class NoteTabs { } /** - * Inserts handled tab at specified index. + * Gets a value whether the handled index would lead to out of bound access. */ - private insertAtIndex(index: number, tab: any) { - if (index < 0 || tab === undefined) return; + private indexOutOfBounds(index: number): boolean { + return (index < 0 || index >= this.length); + } - this.tabs.splice(index, 0, tab); + static isTemporary(tab: INoteTab): boolean { + if (tab) { + return (tab.type === NoteTabType.Temporary); + } + return false; + } + + static isPinned(tab: INoteTab): boolean { + if (tab) { + return (tab.type === NoteTabType.Pinned); + } + return false; } /** * Gets the tab for the handled note. */ - get(index: number): any { - if (index < 0 || index >= this.length) return; + get(index: number): INoteTab { + if (this.indexOutOfBounds(index)) return; return this.tabs[index]; } @@ -105,12 +115,13 @@ export class NoteTabs { /** * Adds note as new tab at the end. */ - async add(noteId: string, noteType: NoteTabType, targetId?: string) { - if (noteId === undefined || noteType === undefined) return; + async add(newId: string, newType: NoteTabType, targetId?: string) { + if (newId === undefined || newType === undefined) return; - const newTab: any = { id: noteId, type: noteType }; - if (targetId) { - this.insertAtIndex(this.indexOf(targetId), newTab); + const index = this.indexOf(targetId); + const newTab: any = { id: newId, type: newType }; + if (index >= 0) { + this.tabs.splice(index, 0, newTab); } else { this.tabs.push(newTab); } @@ -121,12 +132,12 @@ export class NoteTabs { * Moves the tab on source index to the target index. */ async moveWithIndex(sourceIdx: number, targetIdx: number) { - if (sourceIdx < 0 || sourceIdx >= this.length) return; - if (targetIdx < 0 || targetIdx >= this.length) return; + if (this.indexOutOfBounds(sourceIdx)) return; + if (this.indexOutOfBounds(targetIdx)) return; const tab: any = this.tabs[sourceIdx]; this.tabs.splice(sourceIdx, 1); - this.insertAtIndex((targetIdx == 0 ? 0 : targetIdx), tab); + this.tabs.splice((targetIdx == 0 ? 0 : targetIdx), 0, tab); await this.store(); } @@ -169,7 +180,7 @@ export class NoteTabs { const index = this.indexOf(noteId); if (index >= 0) { this.tabs.splice(index, 1); + await this.store(); } - await this.store(); } } diff --git a/src/panel.ts b/src/panel.ts index b5ced03..d7fb42e 100644 --- a/src/panel.ts +++ b/src/panel.ts @@ -1,9 +1,8 @@ import joplin from 'api'; -import { NoteTabType, NoteTabs } from './noteTabs'; -import { Settings } from './settings'; +import { NoteTabs } from './noteTabs'; +import { Settings, LayoutMode } from './settings'; export class Panel { - private _panel: any; private _tabs: NoteTabs; private _settings: Settings; @@ -13,6 +12,14 @@ export class Panel { this._settings = settings; } + private get tabs() { + return this._tabs; + } + + private get sets() { + return this._settings; + } + private async toggleTodoState(noteId: string, checked: any) { try { const note: any = await joplin.data.get(['notes', noteId], { fields: ['id', 'is_todo', 'todo_completed'] }); @@ -27,6 +34,71 @@ export class Panel { } } + /** + * Register plugin panel and update webview for the first time. + */ + async register() { + this._panel = await joplin.views.panels.create('note.tabs.panel'); + await joplin.views.panels.addScript(this._panel, './assets/fontawesome/css/all.min.css'); + await joplin.views.panels.addScript(this._panel, './webview.css'); + if (this.sets.hasLayoutMode(LayoutMode.Auto)) { + await joplin.views.panels.addScript(this._panel, './webview_auto.css'); + } + if (this.sets.hasLayoutMode(LayoutMode.Vertical)) { + await joplin.views.panels.addScript(this._panel, './webview_vertical.css'); + } + await joplin.views.panels.addScript(this._panel, './webview.js'); + + // message handler + await joplin.views.panels.onMessage(this._panel, async (message: any) => { + if (message.name === 'tabsOpenFolder') { + await joplin.commands.execute('openFolder', message.id); + } + if (message.name === 'tabsOpen') { + await joplin.commands.execute('openNote', message.id); + } + if (message.name === 'tabsPinNote') { + let id: string[] = [message.id]; + await joplin.commands.execute('tabsPinNote', id); + } + if (message.name === 'tabsUnpinNote') { + let id: string[] = [message.id]; + await joplin.commands.execute('tabsUnpinNote', id); + } + if (message.name === 'tabsToggleTodo') { + await this.toggleTodoState(message.id, message.checked); + } + if (message.name === 'tabsMoveLeft') { + await joplin.commands.execute('tabsMoveLeft'); + } + if (message.name === 'tabsMoveRight') { + await joplin.commands.execute('tabsMoveRight'); + } + if (message.name === 'tabsBack') { + await joplin.commands.execute('historyBackward'); + } + if (message.name === 'tabsForward') { + await joplin.commands.execute('historyForward'); + } + if (message.name === 'tabsDrag') { + await this.tabs.moveWithId(message.sourceId, message.targetId); + await this.updateWebview(); + } + if (message.name === 'tabsDragNotes') { + await joplin.commands.execute('tabsPinNote', message.noteIds, message.targetId); + } + }); + + // set init message + await joplin.views.panels.setHtml(this._panel, ` +
+
+

Loading panel...

+
+
+ `); + } + /** * Gets an array of all parents starting from the handled parent_id. * Consider first entry is handled parent. @@ -44,12 +116,14 @@ export class Panel { return parents; } - // create HTML for each tab + /** + * Prepares HTML for all tabs + */ private async getNoteTabsHtml(selectedNote: any): Promise { - const showCompletedTodos: boolean = await this._settings.showCompletedTodos; + const showCompletedTodos: boolean = await this.sets.showCompletedTodos; const noteTabsHtml: any = []; - for (const noteTab of this._tabs.tabs) { + for (const noteTab of this.tabs.tabs) { let note: any = null; // get real note from database, if no longer exists remove tab and continue with next one @@ -58,7 +132,7 @@ export class Panel { // console.log(`add note: ${JSON.stringify(note)}`); } catch (error) { // console.log(`delete note: ${noteTab.id}`); - await this._tabs.delete(noteTab.id); + await this.tabs.delete(noteTab.id); continue; } @@ -67,24 +141,25 @@ export class Panel { if ((!showCompletedTodos) && note.todo_completed) continue; // prepare tab style attributes - const bg: string = (selectedNote && note.id == selectedNote.id) ? this._settings.actBackground : this._settings.background; - const fg: string = (selectedNote && note.id == selectedNote.id) ? this._settings.actForeground : this._settings.foreground; - const newTab: string = (noteTab.type == NoteTabType.Temporary) ? ' new' : ''; - const icon: string = (noteTab.type == NoteTabType.Pinned) ? 'fa-times' : 'fa-thumbtack'; - const iconTitle: string = (noteTab.type == NoteTabType.Pinned) ? 'Unpin' : 'Pin'; + const bg: string = (selectedNote && note.id == selectedNote.id) ? this.sets.actBackground : this.sets.background; + const fg: string = (selectedNote && note.id == selectedNote.id) ? this.sets.actForeground : this.sets.foreground; + const active:string = (selectedNote && note.id == selectedNote.id) ? 'active' :''; + const newTab: string = (NoteTabs.isTemporary(noteTab)) ? ' new' : ''; + const icon: string = (NoteTabs.isPinned(noteTab)) ? 'fa-times' : 'fa-thumbtack'; + const iconTitle: string = (NoteTabs.isPinned(noteTab)) ? 'Unpin' : 'Pin'; const textDecoration: string = (note.is_todo && note.todo_completed) ? 'line-through' : ''; // prepare checkbox for todo let checkboxHtml: string = ''; - if (this._settings.showTodoCheckboxes && note.is_todo) { + if (this.sets.showTodoCheckboxes && note.is_todo) { checkboxHtml = ``; } noteTabsHtml.push(` -