mirror of
https://github.com/zadam/trilium.git
synced 2024-12-29 11:24:45 +08:00
shortcut improvements
This commit is contained in:
parent
70552d58ac
commit
6883b71ce7
31 changed files with 248 additions and 94 deletions
1
db/migrations/0203__set_notes_as_doc_type.sql
Normal file
1
db/migrations/0203__set_notes_as_doc_type.sql
Normal file
|
@ -0,0 +1 @@
|
|||
UPDATE notes SET type = 'doc' WHERE noteId IN ('share, hidden', 'sqlconsole', 'search');
|
1
src/public/app/doc_notes/hidden.html
Normal file
1
src/public/app/doc_notes/hidden.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>Hidden tree is used to record various application-level data which can stay most of the time hidden from the user view.</p>
|
1
src/public/app/doc_notes/share.html
Normal file
1
src/public/app/doc_notes/share.html
Normal file
|
@ -0,0 +1 @@
|
|||
<p>Here you can find all shared notes.</p>
|
|
@ -21,7 +21,8 @@ const NOTE_TYPE_ICONS = {
|
|||
"mermaid": "bx bx-selection",
|
||||
"canvas": "bx bx-pen",
|
||||
"web-view": "bx bx-globe-alt",
|
||||
"shortcut": "bx bx-up-arrow-circle"
|
||||
"shortcut": "bx bx-up-arrow-circle",
|
||||
"doc": "bx bx-file-doc"
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import treeService from '../services/tree.js';
|
||||
import froca from "../services/froca.js";
|
||||
import contextMenu from "./context_menu.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
import server from "../services/server.js";
|
||||
|
||||
export default class ShortcutContextMenu {
|
||||
/**
|
||||
|
@ -25,12 +27,13 @@ export default class ShortcutContextMenu {
|
|||
const note = await froca.getNote(this.node.data.noteId);
|
||||
const parentNoteId = this.node.getParent().data.noteId;
|
||||
|
||||
const isLbRoot = note.noteId === 'lb_root';
|
||||
const isVisibleRoot = note.noteId === 'lb_visibleshortcuts';
|
||||
const isAvailableRoot = note.noteId === 'lb_availableshortcuts';
|
||||
const isVisibleItem = parentNoteId === 'lb_visibleshortcuts';
|
||||
const isAvailableItem = parentNoteId === 'lb_availableshortcuts';
|
||||
const isItem = isVisibleItem || isAvailableItem;
|
||||
const canBeDeleted = !note.noteId.startsWith("lb_");
|
||||
const canBeReset = note.noteId.startsWith("lb_");
|
||||
|
||||
return [
|
||||
(isVisibleRoot || isAvailableRoot) ? { title: 'Add note shortcut', command: 'addNoteShortcut', uiIcon: "bx bx-plus" } : null,
|
||||
|
@ -38,8 +41,8 @@ export default class ShortcutContextMenu {
|
|||
(isVisibleRoot || isAvailableRoot) ? { title: 'Add widget shortcut', command: 'addWidgetShortcut', uiIcon: "bx bx-plus" } : null,
|
||||
(isVisibleRoot || isAvailableRoot) ? { title: 'Add spacer', command: 'addSpacerShortcut', uiIcon: "bx bx-plus" } : null,
|
||||
(isVisibleRoot || isAvailableRoot) ? { title: "----" } : null,
|
||||
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash",
|
||||
enabled: !isLbRoot}, // allow everything to be deleted as a form of a reset. Root can't be deleted because it's a hoisted note
|
||||
{ title: 'Delete <kbd data-command="deleteNotes"></kbd>', command: "deleteNotes", uiIcon: "bx bx-trash", enabled: canBeDeleted },
|
||||
{ title: 'Reset', command: "resetShortcut", uiIcon: "bx bx-empty", enabled: canBeReset},
|
||||
{ title: "----" },
|
||||
isAvailableItem ? { title: 'Move to visible shortcuts', command: "moveShortcutToVisible", uiIcon: "bx bx-show", enabled: true } : null,
|
||||
isVisibleItem ? { title: 'Move to available shortcuts', command: "moveShortcutToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
|
||||
|
@ -49,6 +52,18 @@ export default class ShortcutContextMenu {
|
|||
}
|
||||
|
||||
async selectMenuItemHandler({command}) {
|
||||
if (command === 'resetShortcut') {
|
||||
const confirmed = await dialogService.confirm(`Do you really want to reset "${this.node.title}"?
|
||||
All data / settings in this shortcut (and its children) will be lost
|
||||
and the shortcut will be returned to its original location.`);
|
||||
|
||||
if (confirmed) {
|
||||
await server.post(`special-notes/shortcuts/${this.node.data.noteId}/reset`);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.treeWidget.triggerCommand(command, {
|
||||
node: this.node,
|
||||
notePath: treeService.getNotePath(this.node),
|
||||
|
|
|
@ -10,8 +10,8 @@ async function moveBeforeBranch(branchIdsToMove, beforeBranchId) {
|
|||
branchIdsToMove = filterRootNote(branchIdsToMove);
|
||||
branchIdsToMove = filterSearchBranches(branchIdsToMove);
|
||||
|
||||
if (beforeBranchId === 'root') {
|
||||
toastService.showError('Cannot move notes before root note.');
|
||||
if (['root', 'lb_root', 'lb_availableshortcuts', 'lb_visibleshortcuts'].includes(beforeBranchId)) {
|
||||
toastService.showError('Cannot move notes here.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -31,8 +31,16 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
|
|||
|
||||
const afterNote = await froca.getBranch(afterBranchId).getNote();
|
||||
|
||||
if (afterNote.noteId === 'root' || afterNote.noteId === hoistedNoteService.getHoistedNoteId()) {
|
||||
toastService.showError('Cannot move notes after root note.');
|
||||
const forbiddenNoteIds = [
|
||||
'root',
|
||||
hoistedNoteService.getHoistedNoteId(),
|
||||
'lb_root',
|
||||
'lb_availableshortcuts',
|
||||
'lb_visibleshortcuts'
|
||||
];
|
||||
|
||||
if (forbiddenNoteIds.includes(afterNote.noteId)) {
|
||||
toastService.showError('Cannot move notes here.');
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -49,6 +57,11 @@ async function moveAfterBranch(branchIdsToMove, afterBranchId) {
|
|||
}
|
||||
|
||||
async function moveToParentNote(branchIdsToMove, newParentBranchId) {
|
||||
if (newParentBranchId === 'lb_root') {
|
||||
toastService.showError('Cannot move notes here.');
|
||||
return;
|
||||
}
|
||||
|
||||
branchIdsToMove = filterRootNote(branchIdsToMove);
|
||||
|
||||
for (const branchIdToMove of branchIdsToMove) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import appContext from "../services/app_context.js";
|
||||
import appContext from "./app_context.js";
|
||||
|
||||
async function info(message) {
|
||||
return new Promise(res =>
|
|
@ -1,6 +1,6 @@
|
|||
import appContext from "./app_context.js";
|
||||
import treeService from "./tree.js";
|
||||
import dialogService from "../widgets/dialog.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import froca from "./froca.js";
|
||||
|
||||
function getHoistedNoteId() {
|
||||
|
|
|
@ -74,7 +74,13 @@ export default class RootCommandExecutor extends Component {
|
|||
|
||||
async showLaunchBarShortcutsCommand() {
|
||||
await appContext.tabManager.openContextWithNote('lb_root', true, null, 'lb_root');
|
||||
}
|
||||
|
||||
async showShareSubtreeCommand() {
|
||||
await appContext.tabManager.openContextWithNote('share', true, null, 'share');
|
||||
}
|
||||
|
||||
async showHiddenSubtreeCommand() {
|
||||
await appContext.tabManager.openContextWithNote('hidden', true, null, 'hidden');
|
||||
}
|
||||
}
|
||||
|
|
40
src/public/app/widgets/buttons/button_from_note.js
Normal file
40
src/public/app/widgets/buttons/button_from_note.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
import ButtonWidget from "./button_widget.js";
|
||||
import froca from "../../services/froca.js";
|
||||
import attributeService from "../../services/attributes.js";
|
||||
|
||||
export default class ButtonFromNoteWidget extends ButtonWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.settings.buttonNoteId = null;
|
||||
}
|
||||
|
||||
buttonNoteId(noteId) {
|
||||
this.settings.buttonNoteId = noteId;
|
||||
return this;
|
||||
}
|
||||
|
||||
doRender() {
|
||||
super.doRender();
|
||||
|
||||
this.updateIcon();
|
||||
}
|
||||
|
||||
updateIcon() {
|
||||
froca.getNote(this.settings.buttonNoteId).then(note => {
|
||||
this.settings.icon = note.getLabelValue("iconClass");
|
||||
|
||||
this.refreshIcon();
|
||||
});
|
||||
}
|
||||
|
||||
entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.getAttributes(this.componentId).find(attr =>
|
||||
attr.type === 'label'
|
||||
&& attr.name === 'iconClass'
|
||||
&& attributeService.isAffecting(attr, this.note))) {
|
||||
|
||||
this.updateIcon();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -18,7 +18,12 @@ export default class ButtonWidget extends NoteContextAwareWidget {
|
|||
super();
|
||||
|
||||
this.settings = {
|
||||
titlePlacement: 'right'
|
||||
titlePlacement: 'right',
|
||||
title: null,
|
||||
icon: null,
|
||||
command: null,
|
||||
onClick: null,
|
||||
onContextMenu: null
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,6 +44,14 @@ export default class ButtonWidget extends NoteContextAwareWidget {
|
|||
});
|
||||
}
|
||||
|
||||
if (this.settings.onContextMenu) {
|
||||
this.$widget.on("contextmenu", e => {
|
||||
this.$widget.tooltip("hide");
|
||||
|
||||
this.settings.onContextMenu(e);
|
||||
});
|
||||
}
|
||||
|
||||
this.$widget.attr("data-placement", this.settings.titlePlacement);
|
||||
|
||||
this.$widget.tooltip({
|
||||
|
@ -70,8 +83,7 @@ export default class ButtonWidget extends NoteContextAwareWidget {
|
|||
}
|
||||
}
|
||||
|
||||
this.$widget
|
||||
.addClass(this.settings.icon);
|
||||
this.$widget.addClass(this.settings.icon);
|
||||
}
|
||||
|
||||
initialRenderCompleteEvent() {
|
||||
|
@ -102,4 +114,8 @@ export default class ButtonWidget extends NoteContextAwareWidget {
|
|||
this.settings.onClick = handler;
|
||||
return this;
|
||||
}
|
||||
|
||||
onContextMenu(handler) {
|
||||
this.settings.onContextMenu = handler;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,11 +124,16 @@ const TPL = `
|
|||
<kbd ></kbd>
|
||||
</li>
|
||||
|
||||
<li class="dropdown-item options-button" data-trigger-command="showLaunchBarShortcuts">
|
||||
<li class="dropdown-item" data-trigger-command="showLaunchBarShortcuts">
|
||||
<span class="bx bx-sidebar"></span>
|
||||
Configure launchbar shortcuts
|
||||
</li>
|
||||
|
||||
<li class="dropdown-item" data-trigger-command="showShareSubtree">
|
||||
<span class="bx bx-share-alt"></span>
|
||||
Show share subtree
|
||||
</li>
|
||||
|
||||
<li class="dropdown-item dropdown-submenu">
|
||||
<span class="dropdown-toggle">
|
||||
<span class="bx bx-empty"></span>
|
||||
|
@ -160,6 +165,11 @@ const TPL = `
|
|||
Reload frontend
|
||||
<kbd data-command="reloadFrontendApp"></kbd>
|
||||
</li>
|
||||
|
||||
<li class="dropdown-item" data-trigger-command="showHiddenSubtree">
|
||||
<span class="bx bx-empty"></span>
|
||||
Show hidden subtree
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
|
|
|
@ -1,48 +1,17 @@
|
|||
import BasicWidget from "./basic_widget.js";
|
||||
import utils from "../services/utils.js";
|
||||
import contextMenu from "../menus/context_menu.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import utils from "../../../services/utils.js";
|
||||
import contextMenu from "../../../menus/context_menu.js";
|
||||
import treeService from "../../../services/tree.js";
|
||||
import ButtonFromNoteWidget from "../button_from_note.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="history-navigation">
|
||||
<style>
|
||||
.history-navigation {
|
||||
margin: 0 15px 0 5px;
|
||||
export default class AbstractHistoryNavigationWidget extends ButtonFromNoteWidget {
|
||||
isEnabled() {
|
||||
return super.isEnabled() && utils.isElectron();
|
||||
}
|
||||
</style>
|
||||
|
||||
<a title="Go to previous note." data-trigger-command="backInNoteHistory" class="icon-action bx bx-left-arrow-circle"></a>
|
||||
|
||||
<a title="Go to next note." data-trigger-command="forwardInNoteHistory" class="icon-action bx bx-right-arrow-circle"></a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
export default class HistoryNavigationWidget extends BasicWidget {
|
||||
doRender() {
|
||||
if (!utils.isElectron()) {
|
||||
this.$widget = $("<div>");
|
||||
return;
|
||||
}
|
||||
super.doRender();
|
||||
|
||||
this.$widget = $(TPL);
|
||||
|
||||
const contextMenuHandler = e => {
|
||||
e.preventDefault();
|
||||
|
||||
if (this.webContents.history.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.showContextMenu(e);
|
||||
};
|
||||
|
||||
this.$backInHistory = this.$widget.find("[data-trigger-command='backInNoteHistory']");
|
||||
this.$backInHistory.on('contextmenu', contextMenuHandler);
|
||||
|
||||
this.$forwardInHistory = this.$widget.find("[data-trigger-command='forwardInNoteHistory']");
|
||||
this.$forwardInHistory.on('contextmenu', contextMenuHandler);
|
||||
|
||||
this.webContents = utils.dynamicRequire('@electron/remote').webContents;
|
||||
this.webContents = utils.dynamicRequire('@electron/remote').getCurrentWebContents();
|
||||
|
||||
// without this the history is preserved across frontend reloads
|
||||
this.webContents.clearHistory();
|
||||
|
@ -51,6 +20,16 @@ export default class HistoryNavigationWidget extends BasicWidget {
|
|||
}
|
||||
|
||||
async showContextMenu(e) {
|
||||
e.preventDefault();
|
||||
|
||||
// API is broken and will be replaced: https://github.com/electron/electron/issues/33899
|
||||
// until then no context menu
|
||||
return;
|
||||
|
||||
if (this.webContents.history.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
let items = [];
|
||||
|
||||
const activeIndex = this.webContents.getActiveIndex();
|
14
src/public/app/widgets/buttons/history/history_back.js
Normal file
14
src/public/app/widgets/buttons/history/history_back.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import AbstractHistoryNavigationWidget from "./abstract_history.js";
|
||||
|
||||
export default class BackInHistoryButtonWidget extends AbstractHistoryNavigationWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.icon('bx-left-arrow-circle')
|
||||
.title("Go to previous note.")
|
||||
.command("backInNoteHistory")
|
||||
.titlePlacement("right")
|
||||
.buttonNoteId('lb_backinhistory')
|
||||
.onContextMenu(e => this.showContextMenu(e));
|
||||
}
|
||||
}
|
14
src/public/app/widgets/buttons/history/history_forward.js
Normal file
14
src/public/app/widgets/buttons/history/history_forward.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import AbstractHistoryNavigationWidget from "./abstract_history.js";
|
||||
|
||||
export default class ForwardInHistoryButtonWidget extends AbstractHistoryNavigationWidget {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.icon('bx-left-arrow-circle')
|
||||
.title("Go to next note.")
|
||||
.command("forwardInNoteHistory")
|
||||
.titlePlacement("right")
|
||||
.buttonNoteId('lb_forwardinhistory')
|
||||
.onContextMenu(e => this.showContextMenu(e));
|
||||
}
|
||||
}
|
|
@ -11,6 +11,6 @@ export default class NoteRevisionsButton extends ButtonWidget {
|
|||
}
|
||||
|
||||
isEnabled() {
|
||||
return super.isEnabled() && this.note?.type !== 'shortcut';
|
||||
return super.isEnabled() && !['shortcut', 'doc'].includes(this.note?.type);
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import ButtonWidget from "./button_widget.js";
|
||||
|
||||
export default class ShowNoteSourceButton extends ButtonWidget {
|
||||
isEnabled() {
|
||||
return super.isEnabled() && this.note && ['text', 'relation-map'].includes(this.note.type);
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.icon('bx bx-code')
|
||||
.title("Show Note Source")
|
||||
.command("openNoteSourceDialog")
|
||||
.titlePlacement("bottom");
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@ import SpacerWidget from "../spacer.js";
|
|||
import BookmarkButtons from "../bookmark_buttons.js";
|
||||
import ProtectedSessionStatusWidget from "../buttons/protected_session_status.js";
|
||||
import SyncStatusWidget from "../sync_status.js";
|
||||
import BackInHistoryButtonWidget from "../buttons/history/history_back.js";
|
||||
import ForwardInHistoryButtonWidget from "../buttons/history/history_forward.js";
|
||||
|
||||
export default class ShortcutContainer extends FlexContainer {
|
||||
constructor() {
|
||||
|
@ -63,6 +65,10 @@ export default class ShortcutContainer extends FlexContainer {
|
|||
this.child(new ProtectedSessionStatusWidget());
|
||||
} else if (builtinWidget === 'syncStatus') {
|
||||
this.child(new SyncStatusWidget());
|
||||
} else if (builtinWidget === 'backInHistoryButton') {
|
||||
this.child(new BackInHistoryButtonWidget());
|
||||
} else if (builtinWidget === 'forwardInHistoryButton') {
|
||||
this.child(new ForwardInHistoryButtonWidget());
|
||||
} else {
|
||||
console.log(`Unrecognized builtin widget ${builtinWidget} for shortcut ${shortcut.noteId} "${shortcut.title}"`);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import libraryLoader from "../../services/library_loader.js";
|
|||
import openService from "../../services/open.js";
|
||||
import protectedSessionHolder from "../../services/protected_session_holder.js";
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
import dialogService from "../dialog.js";
|
||||
import dialogService from "../../services/dialog.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="note-revisions-dialog modal fade mx-auto" tabindex="-1" role="dialog">
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import server from "../../../services/server.js";
|
||||
import dialogService from "../../dialog.js";
|
||||
import dialogService from "../../../services/dialog.js";
|
||||
import toastService from "../../../services/toast.js";
|
||||
import OptionsTab from "./options_tab.js";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import server from "../../../services/server.js";
|
||||
import utils from "../../../services/utils.js";
|
||||
import dialogService from "../../dialog.js";
|
||||
import dialogService from "../../../services/dialog.js";
|
||||
import OptionsTab from "./options_tab.js";
|
||||
|
||||
const TPL = `
|
||||
|
|
|
@ -6,7 +6,7 @@ import froca from "../../services/froca.js";
|
|||
import appContext from "../../services/app_context.js";
|
||||
import hoistedNoteService from "../../services/hoisted_note.js";
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
import dialogService from "../dialog.js";
|
||||
import dialogService from "../../services/dialog.js";
|
||||
import toastService from "../../services/toast.js";
|
||||
|
||||
const TPL = `
|
||||
|
|
|
@ -17,7 +17,7 @@ import linkService from "../services/link.js";
|
|||
import syncService from "../services/sync.js";
|
||||
import options from "../services/options.js";
|
||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="tree-wrapper">
|
||||
|
@ -368,7 +368,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget {
|
|||
},
|
||||
beforeActivate: (event, data) => {
|
||||
// hidden subtree is hidden hackily, prevent activating it e.g. by keyboard
|
||||
return data.node.data.noteId !== 'hidden';
|
||||
return hoistedNoteService.getHoistedNoteId() === 'hidden' || data.node.data.noteId !== 'hidden';
|
||||
},
|
||||
activate: async (event, data) => {
|
||||
// click event won't propagate so let's close context menu manually
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import server from '../services/server.js';
|
||||
import mimeTypesService from '../services/mime_types.js';
|
||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
|
||||
const NOTE_TYPES = [
|
||||
{ type: "file", title: "File", selectable: false },
|
||||
|
@ -9,6 +9,7 @@ const NOTE_TYPES = [
|
|||
{ type: "search", title: "Saved Search", selectable: false },
|
||||
{ type: "note-map", mime: '', title: "Note Map", selectable: false },
|
||||
{ type: "shortcut", mime: '', title: "Shortcut", selectable: false },
|
||||
{ type: "doc", mime: '', title: "Doc", selectable: false },
|
||||
|
||||
{ type: "text", mime: "text/html", title: "Text", selectable: true },
|
||||
{ type: "relation-map", mime: "application/json", title: "Relation Map", selectable: true },
|
||||
|
|
|
@ -3,7 +3,7 @@ import branchService from "../services/branches.js";
|
|||
import server from "../services/server.js";
|
||||
import utils from "../services/utils.js";
|
||||
import syncService from "../services/sync.js";
|
||||
import dialogService from "./dialog.js";
|
||||
import dialogService from "../services/dialog.js";
|
||||
|
||||
export default class SharedSwitchWidget extends SwitchWidget {
|
||||
isEnabled() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import TypeWidget from "./type_widget.js";
|
|||
import appContext from "../../services/app_context.js";
|
||||
import utils from "../../services/utils.js";
|
||||
import froca from "../../services/froca.js";
|
||||
import dialogService from "../../widgets/dialog.js";
|
||||
import dialogService from "../../services/dialog.js";
|
||||
|
||||
const uniDirectionalOverlays = [
|
||||
[ "Arrow", {
|
||||
|
|
|
@ -70,6 +70,10 @@ function createShortcut(req) {
|
|||
return specialNotesService.createShortcut(req.params.parentNoteId, req.params.type);
|
||||
}
|
||||
|
||||
function resetShortcut(req) {
|
||||
return specialNotesService.resetShortcut(req.params.noteId);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getInboxNote,
|
||||
getDayNote,
|
||||
|
@ -81,5 +85,6 @@ module.exports = {
|
|||
saveSqlConsole,
|
||||
createSearchNote,
|
||||
saveSearchNote,
|
||||
createShortcut
|
||||
createShortcut,
|
||||
resetShortcut
|
||||
};
|
||||
|
|
|
@ -326,6 +326,7 @@ function register(app) {
|
|||
apiRoute(POST, '/api/special-notes/save-sql-console', specialNotesRoute.saveSqlConsole);
|
||||
apiRoute(POST, '/api/special-notes/search-note', specialNotesRoute.createSearchNote);
|
||||
apiRoute(POST, '/api/special-notes/save-search-note', specialNotesRoute.saveSearchNote);
|
||||
apiRoute(POST, '/api/special-notes/shortcuts/:noteId/reset', specialNotesRoute.resetShortcut);
|
||||
apiRoute(POST, '/api/special-notes/shortcuts/:parentNoteId/:type', specialNotesRoute.createShortcut);
|
||||
|
||||
// :filename is not used by trilium, but instead used for "save as" to assign a human-readable filename
|
||||
|
|
|
@ -4,7 +4,7 @@ const build = require('./build');
|
|||
const packageJson = require('../../package');
|
||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||
|
||||
const APP_DB_VERSION = 202;
|
||||
const APP_DB_VERSION = 203;
|
||||
const SYNC_VERSION = 27;
|
||||
const CLIPPER_PROTOCOL_VERSION = "1.0";
|
||||
|
||||
|
|
|
@ -11,5 +11,6 @@ module.exports = [
|
|||
'mermaid',
|
||||
'canvas',
|
||||
'web-view',
|
||||
'shortcut'
|
||||
'shortcut',
|
||||
'doc'
|
||||
];
|
||||
|
|
|
@ -37,7 +37,7 @@ function getHiddenRoot() {
|
|||
branchId: 'hidden',
|
||||
noteId: 'hidden',
|
||||
title: 'hidden',
|
||||
type: 'text',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: 'root'
|
||||
}).note;
|
||||
|
@ -46,6 +46,11 @@ function getHiddenRoot() {
|
|||
// the flag is not inherited to the children
|
||||
hidden.addLabel('archived', "", false);
|
||||
hidden.addLabel('excludeFromNoteMap', "", true);
|
||||
hidden.addLabel('iconClass', "bx bx-chip", false);
|
||||
}
|
||||
|
||||
if (!hidden.hasOwnedLabel("docName")) {
|
||||
hidden.addLabel("docName", "hidden");
|
||||
}
|
||||
|
||||
return hidden;
|
||||
|
@ -59,7 +64,7 @@ function getSearchRoot() {
|
|||
branchId: 'search',
|
||||
noteId: 'search',
|
||||
title: 'search',
|
||||
type: 'text',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: getHiddenRoot().noteId
|
||||
}).note;
|
||||
|
@ -95,10 +100,12 @@ function getSqlConsoleRoot() {
|
|||
branchId: 'sqlconsole',
|
||||
noteId: 'sqlconsole',
|
||||
title: 'SQL Console',
|
||||
type: 'text',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: getHiddenRoot().noteId
|
||||
}).note;
|
||||
|
||||
sqlConsoleRoot.addLabel('iconClass', 'bx bx-data');
|
||||
}
|
||||
|
||||
return sqlConsoleRoot;
|
||||
|
@ -114,6 +121,7 @@ function createSqlConsole() {
|
|||
});
|
||||
|
||||
note.setLabel("sqlConsole", dateUtils.localNowDate());
|
||||
note.setLabel('iconClass', 'bx bx-data');
|
||||
|
||||
return note;
|
||||
}
|
||||
|
@ -199,12 +207,16 @@ function getShareRoot() {
|
|||
branchId: 'share',
|
||||
noteId: 'share',
|
||||
title: 'Shared notes',
|
||||
type: 'text',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: hiddenRoot.noteId
|
||||
}).note;
|
||||
}
|
||||
|
||||
if (!shareRoot.hasOwnedLabel("docName")) {
|
||||
shareRoot.addLabel("docName", "share");
|
||||
}
|
||||
|
||||
return shareRoot;
|
||||
}
|
||||
|
||||
|
@ -233,7 +245,7 @@ function getLaunchBarRoot() {
|
|||
branchId: 'lb_root',
|
||||
noteId: 'lb_root',
|
||||
title: 'Launch bar',
|
||||
type: 'shortcut',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: getHiddenRoot().noteId
|
||||
}).note;
|
||||
|
@ -253,7 +265,7 @@ function getLaunchBarAvailableShortcutsRoot() {
|
|||
branchId: 'lb_availableshortcuts',
|
||||
noteId: 'lb_availableshortcuts',
|
||||
title: 'Available shortcuts',
|
||||
type: 'shortcut',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: getLaunchBarRoot().noteId
|
||||
}).note;
|
||||
|
@ -279,7 +291,7 @@ function getLaunchBarVisibleShortcutsRoot() {
|
|||
branchId: 'lb_visibleshortcuts',
|
||||
noteId: 'lb_visibleshortcuts',
|
||||
title: 'Visible shortcuts',
|
||||
type: 'shortcut',
|
||||
type: 'doc',
|
||||
content: '',
|
||||
parentNoteId: getLaunchBarRoot().noteId
|
||||
}).note;
|
||||
|
@ -298,11 +310,11 @@ function getLaunchBarVisibleShortcutsRoot() {
|
|||
}
|
||||
|
||||
const shortcuts = [
|
||||
// visible shortcuts:
|
||||
{ id: 'lb_newnote', command: 'createNoteIntoInbox', title: 'New note', icon: 'bx bx-file-blank', isVisible: true },
|
||||
{ id: 'lb_search', command: 'searchNotes', title: 'Search notes', icon: 'bx bx-search', isVisible: true },
|
||||
{ id: 'lb_jumpto', command: 'jumpToNote', title: 'Jump to note', icon: 'bx bx-send', isVisible: true },
|
||||
{ id: 'lb_notemap', targetNoteId: 'globalnotemap', title: 'Note map', icon: 'bx bx-map-alt', isVisible: true },
|
||||
{ id: 'lb_recentchanges', command: 'showRecentChanges', title: 'Recent changes', icon: 'bx bx-history', isVisible: false },
|
||||
{ id: 'lb_calendar', builtinWidget: 'calendar', title: 'Calendar', icon: 'bx bx-calendar', isVisible: true },
|
||||
{ id: 'lb_spacer1', builtinWidget: 'spacer', title: 'Spacer', icon: 'bx bx-move-vertical', isVisible: true, labels: [
|
||||
{ type: "number", name: "baseSize", value: "40" },
|
||||
|
@ -316,6 +328,11 @@ const shortcuts = [
|
|||
] },
|
||||
{ id: 'lb_protectedsession', builtinWidget: 'protectedSession', title: 'Protected session', icon: 'bx bx bx-shield-quarter', isVisible: true },
|
||||
{ id: 'lb_syncstatus', builtinWidget: 'syncStatus', title: 'Sync status', icon: 'bx bx-wifi', isVisible: true },
|
||||
|
||||
// available shortcuts:
|
||||
{ id: 'lb_recentchanges', command: 'showRecentChanges', title: 'Recent changes', icon: 'bx bx-history', isVisible: false },
|
||||
{ id: 'lb_backinhistory', builtinWidget: 'backInHistoryButton', title: 'Back in history', icon: 'bx bxs-left-arrow-square', isVisible: false },
|
||||
{ id: 'lb_forwardinhistory', builtinWidget: 'forwardInHistoryButton', title: 'Forward in history', icon: 'bx bxs-right-arrow-square', isVisible: false },
|
||||
];
|
||||
|
||||
function createMissingSpecialNotes() {
|
||||
|
@ -324,7 +341,8 @@ function createMissingSpecialNotes() {
|
|||
getBulkActionNote();
|
||||
getLaunchBarRoot();
|
||||
getLaunchBarAvailableShortcutsRoot();
|
||||
getLaunchBarVisibleShortcutsRoot()
|
||||
getLaunchBarVisibleShortcutsRoot();
|
||||
getShareRoot();
|
||||
|
||||
for (const shortcut of shortcuts) {
|
||||
let note = becca.getNote(shortcut.id);
|
||||
|
@ -333,7 +351,10 @@ function createMissingSpecialNotes() {
|
|||
continue;
|
||||
}
|
||||
|
||||
const parentNoteId = shortcut.isVisible ? getLaunchBarVisibleShortcutsRoot().noteId : getLaunchBarAvailableShortcutsRoot().noteId;
|
||||
const parentNoteId = shortcut.isVisible
|
||||
? getLaunchBarVisibleShortcutsRoot().noteId
|
||||
: getLaunchBarAvailableShortcutsRoot().noteId;
|
||||
|
||||
note = noteService.createNewNote({
|
||||
noteId: shortcut.id,
|
||||
title: shortcut.title,
|
||||
|
@ -428,6 +449,29 @@ function createShortcut(parentNoteId, type) {
|
|||
};
|
||||
}
|
||||
|
||||
function resetShortcut(noteId) {
|
||||
if (noteId.startsWith('lb_')) {
|
||||
const note = becca.getNote(noteId);
|
||||
|
||||
if (note) {
|
||||
if (noteId === 'lb_root') {
|
||||
// deleting hoisted notes are not allowed, so we just reset the children
|
||||
for (const childNote of note.getChildNotes()) {
|
||||
childNote.deleteNote();
|
||||
}
|
||||
} else {
|
||||
note.deleteNote();
|
||||
}
|
||||
} else {
|
||||
log.info(`Note ${noteId} has not been found and cannot be reset.`);
|
||||
}
|
||||
} else {
|
||||
log.info(`Note ${noteId} is not a resettable shortcut note.`);
|
||||
}
|
||||
|
||||
createMissingSpecialNotes();
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getInboxNote,
|
||||
createSqlConsole,
|
||||
|
@ -438,5 +482,6 @@ module.exports = {
|
|||
getShareRoot,
|
||||
getHiddenRoot,
|
||||
getBulkActionNote,
|
||||
createShortcut
|
||||
createShortcut,
|
||||
resetShortcut
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue