converted tree_keybindings.js into proper commands

This commit is contained in:
zadam 2020-02-16 22:14:28 +01:00
parent 8ca9ad3497
commit 4330dc47a0
8 changed files with 179 additions and 221 deletions

View File

@ -123,5 +123,6 @@ export default {
triggerAction, triggerAction,
getAction, getAction,
updateDisplayedShortcuts, updateDisplayedShortcuts,
setupActionsForElement setupActionsForElement,
getActionsForScope
}; };

View File

@ -1,207 +0,0 @@
import treeChangesService from "./branches.js";
import treeService from "./tree.js";
import hoistedNoteService from "./hoisted_note.js";
import clipboard from "./clipboard.js";
import utils from "./utils.js";
import keyboardActionService from "./keyboard_actions.js";
import appContext from "./app_context.js";
/**
* @param {NoteTreeWidget} treeWidget
*/
function getFixedKeyBindings(treeWidget) {
return {
// code below shouldn't be necessary normally, however there's some problem with interaction with context menu plugin
// after opening context menu, standard shortcuts don't work, but they are detected here
// so we essentially takeover the standard handling with our implementation.
"left": node => {
node.navigate($.ui.keyCode.LEFT, true).then(treeWidget.clearSelectedNodes);
return false;
},
"right": node => {
node.navigate($.ui.keyCode.RIGHT, true).then(treeWidget.clearSelectedNodes);
return false;
},
"up": node => {
node.navigate($.ui.keyCode.UP, true).then(treeWidget.clearSelectedNodes);
return false;
},
"down": node => {
node.navigate($.ui.keyCode.DOWN, true).then(treeWidget.clearSelectedNodes);
return false;
}
};
}
/**
* @param {NoteTreeWidget} treeWidget
* @param {FancytreeNode} node
*/
function getSelectedOrActiveBranchIds(treeWidget, node) {
const nodes = treeWidget.getSelectedOrActiveNodes(node);
return nodes.map(node => node.data.branchId);
}
/**
* @param {NoteTreeWidget} treeWidget
*/
function getTemplates(treeWidget) {
return {
"deleteNotes": node => {
const branchIds = getSelectedOrActiveBranchIds(treeWidget, node);
treeChangesService.deleteNotes(treeWidget, branchIds);
},
"moveNoteUp": node => {
const beforeNode = node.getPrevSibling();
if (beforeNode !== null) {
treeChangesService.moveBeforeBranch([node.data.branchId], beforeNode.data.branchId);
}
return false;
},
"moveNoteDown": node => {
const afterNode = node.getNextSibling();
if (afterNode !== null) {
treeChangesService.moveAfterBranch([node.data.branchId], afterNode.data.branchId);
}
return false;
},
"moveNoteUpInHierarchy": node => {
treeChangesService.moveNodeUpInHierarchy(node);
return false;
},
"moveNoteDownInHierarchy": node => {
const toNode = node.getPrevSibling();
if (toNode !== null) {
treeChangesService.moveToParentNote([node.data.branchId], toNode.data.noteId);
}
return false;
},
"addNoteAboveToSelection": () => {
const node = treeWidget.getFocusedNode();
if (!node) {
return;
}
if (node.isActive()) {
node.setSelected(true);
}
const prevSibling = node.getPrevSibling();
if (prevSibling) {
prevSibling.setActive(true, {noEvents: true});
if (prevSibling.isSelected()) {
node.setSelected(false);
}
prevSibling.setSelected(true);
}
return false;
},
"addNoteBelowToSelection": () => {
const node = treeWidget.getFocusedNode();
if (!node) {
return;
}
if (node.isActive()) {
node.setSelected(true);
}
const nextSibling = node.getNextSibling();
if (nextSibling) {
nextSibling.setActive(true, {noEvents: true});
if (nextSibling.isSelected()) {
node.setSelected(false);
}
nextSibling.setSelected(true);
}
return false;
},
"collapseSubtree": node => {
treeWidget.collapseTree(node);
},
"sortChildNotes": node => {
treeService.sortAlphabetically(node.data.noteId);
return false;
},
"selectAllNotesInParent": node => {
for (const child of node.getParent().getChildren()) {
child.setSelected(true);
}
return false;
},
"copyNotesToClipboard": node => {
clipboard.copy(getSelectedOrActiveBranchIds(treeWidget, node));
return false;
},
"cutNotesToClipboard": node => {
clipboard.cut(getSelectedOrActiveBranchIds(treeWidget, node));
return false;
},
"pasteNotesFromClipboard": node => {
clipboard.pasteInto(node.data.noteId);
return false;
},
"editNoteTitle": node => {
appContext.triggerEvent('focusOnTitle');
return false;
},
"activateParentNote": node => {
if (!hoistedNoteService.isRootNode(node)) {
node.getParent().setActive().then(treeWidget.clearSelectedNodes);
}
}
};
}
/**
* @param {NoteTreeWidget} treeWidget
*/
async function getKeyboardBindings(treeWidget) {
const bindings = Object.assign({}, getFixedKeyBindings(treeWidget));
const templates = getTemplates(treeWidget);
for (const actionName in templates) {
const action = await keyboardActionService.getAction(actionName);
for (const shortcut of action.effectiveShortcuts || []) {
const normalizedShortcut = utils.normalizeShortcut(shortcut);
bindings[normalizedShortcut] = templates[actionName];
}
}
return bindings;
}
export default {
getKeyboardBindings
};

View File

@ -91,7 +91,7 @@ export default class NoteDetailWidget extends TabAwareWidget {
return this.tabContext && this.tabContext.isActive(); return this.tabContext && this.tabContext.isActive();
} }
async refresh() {console.log("REFRESH DETAIL"); async refresh() {
if (!this.isEnabled()) { if (!this.isEnabled()) {
this.toggle(false); this.toggle(false);
return; return;

View File

@ -72,7 +72,7 @@ export default class NoteTitleWidget extends TabAwareWidget {
} }
} }
focusAndSelectTitleEvent() { focusAndSelectTitleCommand() {
if (this.tabContext && this.tabContext.isActive()) { if (this.tabContext && this.tabContext.isActive()) {
this.$noteTitle this.$noteTitle
.trigger('focus') .trigger('focus')

View File

@ -2,7 +2,6 @@ import hoistedNoteService from "../services/hoisted_note.js";
import treeService from "../services/tree.js"; import treeService from "../services/tree.js";
import utils from "../services/utils.js"; import utils from "../services/utils.js";
import contextMenuWidget from "../services/context_menu.js"; import contextMenuWidget from "../services/context_menu.js";
import treeKeyBindingService from "../services/tree_keybindings.js";
import treeCache from "../services/tree_cache.js"; import treeCache from "../services/tree_cache.js";
import treeBuilder from "../services/tree_builder.js"; import treeBuilder from "../services/tree_builder.js";
import TreeContextMenu from "../services/tree_context_menu.js"; import TreeContextMenu from "../services/tree_context_menu.js";
@ -13,6 +12,8 @@ import server from "../services/server.js";
import noteCreateService from "../services/note_create.js"; import noteCreateService from "../services/note_create.js";
import toastService from "../services/toast.js"; import toastService from "../services/toast.js";
import appContext from "../services/app_context.js"; import appContext from "../services/app_context.js";
import keyboardActionsService from "../services/keyboard_actions.js";
import clipboard from "../services/clipboard.js";
const TPL = ` const TPL = `
<div class="tree"> <div class="tree">
@ -29,7 +30,7 @@ const TPL = `
</div> </div>
`; `;
export default class NoteTreeWidget extends TabAwareWidget { export default class Notethis extends TabAwareWidget {
constructor(appContext, parent) { constructor(appContext, parent) {
super(appContext, parent); super(appContext, parent);
@ -112,7 +113,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
expand: (event, data) => this.setExpandedToServer(data.node.data.branchId, true), expand: (event, data) => this.setExpandedToServer(data.node.data.branchId, true),
collapse: (event, data) => this.setExpandedToServer(data.node.data.branchId, false), collapse: (event, data) => this.setExpandedToServer(data.node.data.branchId, false),
hotkeys: { hotkeys: {
keydown: await treeKeyBindingService.getKeyboardBindings(this) keydown: await this.getHotKeys()
}, },
dnd5: { dnd5: {
autoExpandMS: 600, autoExpandMS: 600,
@ -406,9 +407,9 @@ export default class NoteTreeWidget extends TabAwareWidget {
await this.tree.reload(notes); await this.tree.reload(notes);
} }
createTopLevelNoteEvent() { noteCreateService.createNewTopLevelNote(); } createTopLevelNoteCommand() { noteCreateService.createNewTopLevelNote(); }
collapseTreeEvent() { this.collapseTree(); } collapseTreeCommand() { this.collapseTree(); }
isEnabled() { isEnabled() {
return this.tabContext && this.tabContext.isActive(); return this.tabContext && this.tabContext.isActive();
@ -547,7 +548,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
} }
} }
async createNoteAfterEvent() { async createNoteAfterCommand() {
const node = this.getActiveNode(); const node = this.getActiveNode();
const parentNoteId = node.data.parentNoteId; const parentNoteId = node.data.parentNoteId;
const isProtected = await treeService.getParentProtectedStatus(node); const isProtected = await treeService.getParentProtectedStatus(node);
@ -564,7 +565,7 @@ export default class NoteTreeWidget extends TabAwareWidget {
}); });
} }
async createNoteIntoEvent() { async createNoteIntoCommand() {
const node = this.getActiveNode(); const node = this.getActiveNode();
if (node) { if (node) {
@ -629,4 +630,165 @@ export default class NoteTreeWidget extends TabAwareWidget {
this.triggerCommand('moveBranchIdsTo', {branchIds: selectedOrActiveBranchIds}); this.triggerCommand('moveBranchIdsTo', {branchIds: selectedOrActiveBranchIds});
} }
async getHotKeys() {
const actions = await keyboardActionsService.getActionsForScope('note-tree');
const hotKeyMap = {
// code below shouldn't be necessary normally, however there's some problem with interaction with context menu plugin
// after opening context menu, standard shortcuts don't work, but they are detected here
// so we essentially takeover the standard handling with our implementation.
"left": node => {
node.navigate($.ui.keyCode.LEFT, true).then(this.clearSelectedNodes);
return false;
},
"right": node => {
node.navigate($.ui.keyCode.RIGHT, true).then(this.clearSelectedNodes);
return false;
},
"up": node => {
node.navigate($.ui.keyCode.UP, true).then(this.clearSelectedNodes);
return false;
},
"down": node => {
node.navigate($.ui.keyCode.DOWN, true).then(this.clearSelectedNodes);
return false;
}
};
for (const action of actions) {
for (const shortcut of action.effectiveShortcuts) {
hotKeyMap[shortcut] = node => this.triggerCommand(action.actionName, {node});
}
}
}
/**
* @param {FancytreeNode} node
*/
getSelectedOrActiveBranchIds(node) {
const nodes = this.getSelectedOrActiveNodes(node);
return nodes.map(node => node.data.branchId);
}
deleteNotesCommand({node}) {
const branchIds = this.getSelectedOrActiveBranchIds(node);
treeChangesService.deleteNotes(this, branchIds);
}
moveNoteUpCommand({node}) {
const beforeNode = node.getPrevSibling();
if (beforeNode !== null) {
treeChangesService.moveBeforeBranch([node.data.branchId], beforeNode.data.branchId);
}
}
moveNoteDownCommand({node}) {
const afterNode = node.getNextSibling();
if (afterNode !== null) {
treeChangesService.moveAfterBranch([node.data.branchId], afterNode.data.branchId);
}
}
moveNoteUpInHierarchyCommand({node}) {
treeChangesService.moveNodeUpInHierarchy(node);
}
moveNoteDownInHierarchyCommand({node}) {
const toNode = node.getPrevSibling();
if (toNode !== null) {
treeChangesService.moveToParentNote([node.data.branchId], toNode.data.noteId);
}
}
addNoteAboveToSelectionCommand() {
const node = this.getFocusedNode();
if (!node) {
return;
}
if (node.isActive()) {
node.setSelected(true);
}
const prevSibling = node.getPrevSibling();
if (prevSibling) {
prevSibling.setActive(true, {noEvents: true});
if (prevSibling.isSelected()) {
node.setSelected(false);
}
prevSibling.setSelected(true);
}
}
addNoteBelowToSelectionCommand() {
const node = this.getFocusedNode();
if (!node) {
return;
}
if (node.isActive()) {
node.setSelected(true);
}
const nextSibling = node.getNextSibling();
if (nextSibling) {
nextSibling.setActive(true, {noEvents: true});
if (nextSibling.isSelected()) {
node.setSelected(false);
}
nextSibling.setSelected(true);
}
}
collapseSubtreeCommand({node}) {
this.collapseTree(node);
}
sortChildNotesCommand({node}) {
treeService.sortAlphabetically(node.data.noteId);
}
selectAllNotesInParentCommand({node}) {
for (const child of node.getParent().getChildren()) {
child.setSelected(true);
}
}
copyNotesToClipboardCommand({node}) {
clipboard.copy(this.getSelectedOrActiveBranchIds(node));
}
cutNotesToClipboardCommand({node}) {
clipboard.cut(this.getSelectedOrActiveBranchIds(node));
}
pasteNotesFromClipboardCommand({node}) {
clipboard.pasteInto(node.data.noteId);
}
editNoteTitleCommand({node}) {
appContext.triggerEvent('focusOnTitle');
}
activateParentNoteCommand({node}) {
if (!hoistedNoteService.isRootNode(node)) {
node.getParent().setActive().then(this.clearSelectedNodes);
}
}
} }

View File

@ -130,8 +130,9 @@ export default class NoteTypeWidget extends TabAwareWidget {
} }
async confirmChangeIfContent() { async confirmChangeIfContent() {
// FIXME const noteComplement = await this.tabContext.getNoteComplement();
if (!this.tabContext.getComponent().getContent()) {
if (!noteComplement.content || !noteComplement.content.trim().length) {
return true; return true;
} }

View File

@ -159,7 +159,7 @@ export default class SearchBoxWidget extends BasicWidget {
} }
} }
searchNotesEvent() { searchNotesCommand() {
this.toggleSearchEvent(); this.toggleSearchEvent();
} }
@ -167,7 +167,7 @@ export default class SearchBoxWidget extends BasicWidget {
this.$searchInput.val(""); this.$searchInput.val("");
} }
searchInSubtreeEvent({noteId}) { searchInSubtreeCommand({noteId}) {
noteId = noteId || appContext.tabManager.getActiveTabNoteId(); noteId = noteId || appContext.tabManager.getActiveTabNoteId();
this.toggle(true); this.toggle(true);

View File

@ -248,6 +248,7 @@ function BackendScriptApi(currentNote, apiParams) {
/** /**
* @method * @method
* @deprecated please use createNote() API method instead
* *
* @param {string} parentNoteId - create new note under this parent * @param {string} parentNoteId - create new note under this parent
* @param {string} title * @param {string} title