Merge pull request #618 from TriliumNext/feat/tweak-menus

Tweak menus
This commit is contained in:
Elian Doran 2024-11-20 19:12:43 +02:00 committed by GitHub
commit ae85bffd08
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 288 additions and 112 deletions

View File

@ -3,6 +3,7 @@ import keyboardActionService from '../services/keyboard_actions.js';
class ContextMenu { class ContextMenu {
constructor() { constructor() {
this.$widget = $("#context-menu-container"); this.$widget = $("#context-menu-container");
this.$widget.addClass("dropend");
this.dateContextMenuOpenedMs = 0; this.dateContextMenuOpenedMs = 0;
$(document).on('click', () => this.hide()); $(document).on('click', () => this.hide());
@ -11,6 +12,12 @@ class ContextMenu {
async show(options) { async show(options) {
this.options = options; this.options = options;
if (this.$widget.hasClass("show")) {
// The menu is already visible. Hide the menu then open it again
// at the new location to re-trigger the opening animation.
await this.hide();
}
this.$widget.empty(); this.$widget.empty();
this.addItems(this.$widget, options.items); this.addItems(this.$widget, options.items);
@ -142,18 +149,26 @@ class ContextMenu {
} }
} }
hide() { async hide() {
// this date checking comes from change in FF66 - https://github.com/zadam/trilium/issues/468 // this date checking comes from change in FF66 - https://github.com/zadam/trilium/issues/468
// "contextmenu" event also triggers "click" event which depending on the timing can close the just opened context menu // "contextmenu" event also triggers "click" event which depending on the timing can close the just opened context menu
// we might filter out right clicks, but then it's better if even right clicks close the context menu // we might filter out right clicks, but then it's better if even right clicks close the context menu
if (Date.now() - this.dateContextMenuOpenedMs > 300) { if (Date.now() - this.dateContextMenuOpenedMs > 300) {
// seems like if we hide the menu immediately, some clicks can get propagated to the underlying component // seems like if we hide the menu immediately, some clicks can get propagated to the underlying component
// see https://github.com/zadam/trilium/pull/3805 for details // see https://github.com/zadam/trilium/pull/3805 for details
setTimeout(() => this.$widget.hide(), 100); await timeout(100);
this.$widget.removeClass("show");
this.$widget.hide()
} }
} }
} }
function timeout(ms) {
return new Promise((accept, reject) => {
setTimeout(accept, ms);
});
}
const contextMenu = new ContextMenu(); const contextMenu = new ContextMenu();
export default contextMenu; export default contextMenu;

View File

@ -20,9 +20,13 @@ function setupContextMenu($image) {
{ {
title: "Copy reference to clipboard", title: "Copy reference to clipboard",
command: "copyImageReferenceToClipboard", command: "copyImageReferenceToClipboard",
uiIcon: "bx bx-empty" uiIcon: "bx bx-directions"
},
{
title: "Copy image to clipboard",
command: "copyImageToClipboard",
uiIcon: "bx bx-copy"
}, },
{ title: "Copy image to clipboard", command: "copyImageToClipboard", uiIcon: "bx bx-empty" },
], ],
selectMenuItemHandler: async ({ command }) => { selectMenuItemHandler: async ({ command }) => {
if (command === 'copyImageReferenceToClipboard') { if (command === 'copyImageReferenceToClipboard') {

View File

@ -37,18 +37,22 @@ export default class LauncherContextMenu {
const canBeReset = !canBeDeleted && note.isLaunchBarConfig(); const canBeReset = !canBeDeleted && note.isLaunchBarConfig();
return [ return [
(isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-note-launcher"), command: 'addNoteLauncher', uiIcon: "bx bx-plus" } : null, (isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-note-launcher"), command: 'addNoteLauncher', uiIcon: "bx bx-note" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-script-launcher"), command: 'addScriptLauncher', uiIcon: "bx bx-plus" } : null, (isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-script-launcher"), command: 'addScriptLauncher', uiIcon: "bx bx-code-curly" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-custom-widget"), command: 'addWidgetLauncher', uiIcon: "bx bx-plus" } : null, (isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-custom-widget"), command: 'addWidgetLauncher', uiIcon: "bx bx-customize" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-spacer"), command: 'addSpacerLauncher', uiIcon: "bx bx-plus" } : null, (isVisibleRoot || isAvailableRoot) ? { title: t("launcher_context_menu.add-spacer"), command: 'addSpacerLauncher', uiIcon: "bx bx-dots-horizontal" } : null,
(isVisibleRoot || isAvailableRoot) ? { title: "----" } : null, (isVisibleRoot || isAvailableRoot) ? { title: "----" } : null,
{ title: `${t("launcher_context_menu.delete")} <kbd data-command="deleteNotes"></kbd>`, command: "deleteNotes", uiIcon: "bx bx-trash", enabled: canBeDeleted },
{ title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-empty", enabled: canBeReset},
{ title: "----" },
isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null, isAvailableItem ? { title: t("launcher_context_menu.move-to-visible-launchers"), command: "moveLauncherToVisible", uiIcon: "bx bx-show", enabled: true } : null,
isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null, isVisibleItem ? { title: t("launcher_context_menu.move-to-available-launchers"), command: "moveLauncherToAvailable", uiIcon: "bx bx-hide", enabled: true } : null,
{ title: `${t("launcher_context_menu.duplicate-launcher")} <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty", (isVisibleItem || isAvailableItem) ? { title: "----" } : null,
enabled: isItem }
{ title: `${t("launcher_context_menu.duplicate-launcher")} <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: isItem },
{ title: `${t("launcher_context_menu.delete")} <kbd data-command="deleteNotes"></kbd>`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon", enabled: canBeDeleted },
{ title: "----" },
{ title: t("launcher_context_menu.reset"), command: "resetLauncher", uiIcon: "bx bx-reset destructive-action-icon", enabled: canBeReset}
].filter(row => row !== null); ].filter(row => row !== null);
} }

View File

@ -6,7 +6,7 @@ function openContextMenu(notePath, e, viewScope = {}, hoistedNoteId = null) {
x: e.pageX, x: e.pageX,
y: e.pageY, y: e.pageY,
items: [ items: [
{title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "bx bx-empty"}, {title: "Open note in a new tab", command: "openNoteInNewTab", uiIcon: "bx bx-link-external"},
{title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"}, {title: "Open note in a new split", command: "openNoteInNewSplit", uiIcon: "bx bx-dock-right"},
{title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"} {title: "Open note in a new window", command: "openNoteInNewWindow", uiIcon: "bx bx-window-open"}
], ],

View File

@ -49,56 +49,98 @@ export default class TreeContextMenu {
const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch; const insertNoteAfterEnabled = isNotRoot && !isHoisted && parentNotSearch;
return [ return [
{ title: `${t("tree-context-menu.open-in-a-new-tab")} <kbd>Ctrl+Click</kbd>`, command: "openInTab", uiIcon: "bx bx-empty", enabled: noSelectedNotes }, { title: `${t("tree-context-menu.open-in-a-new-tab")} <kbd>Ctrl+Click</kbd>`, command: "openInTab", uiIcon: "bx bx-link-external", enabled: noSelectedNotes },
{ title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes }, { title: t("tree-context-menu.open-in-a-new-split"), command: "openNoteInSplit", uiIcon: "bx bx-dock-right", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.insert-note-after")} <kbd data-command="createNoteAfter"></kbd>`, command: "insertNoteAfter", uiIcon: "bx bx-plus",
isHoisted ? null : { title: `${t("tree-context-menu.hoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bxs-chevrons-up", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: `${t("tree-context-menu.unhoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: "----" },
{ title: `${t("tree-context-menu.insert-note-after")}<kbd data-command="createNoteAfter"></kbd>`, command: "insertNoteAfter", uiIcon: "bx bx-plus",
items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null, items: insertNoteAfterEnabled ? await noteTypesService.getNoteTypeItems("insertNoteAfter") : null,
enabled: insertNoteAfterEnabled && noSelectedNotes && notOptions }, enabled: insertNoteAfterEnabled && noSelectedNotes && notOptions },
{ title: `${t("tree-context-menu.insert-child-note")} <kbd data-command="createNoteInto"></kbd>`, command: "insertChildNote", uiIcon: "bx bx-plus",
{ title: `${t("tree-context-menu.insert-child-note")}<kbd data-command="createNoteInto"></kbd>`, command: "insertChildNote", uiIcon: "bx bx-plus",
items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null, items: notSearch ? await noteTypesService.getNoteTypeItems("insertChildNote") : null,
enabled: notSearch && noSelectedNotes && notOptions }, enabled: notSearch && noSelectedNotes && notOptions },
{ title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`, command: "deleteNotes", uiIcon: "bx bx-trash",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptions },
{ title: "----" },
{ title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`, command: "searchInSubtree", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes },
isHoisted ? null : { title: `${t("tree-context-menu.hoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
!isHoisted || !isNotRoot ? null : { title: `${t("tree-context-menu.unhoist-note")} <kbd data-command="toggleNoteHoisting"></kbd>`, command: "toggleNoteHoisting", uiIcon: "bx bx-door-open" },
{ title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`, command: "editBranchPrefix", uiIcon: "bx bx-empty",
enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptions },
{ title: t("tree-context-menu.advanced"), uiIcon: "bx bx-empty", enabled: true, items: [
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`, command: "sortChildNotes", uiIcon: "bx bx-empty", enabled: noSelectedNotes && notSearch },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptions },
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-empty", enabled: isNotRoot && !isHoisted && notOptions },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-empty", enabled: true }
] },
{ title: "----" }, { title: "----" },
{ title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes }, { title: t("tree-context-menu.protect-subtree"), command: "protectSubtree", uiIcon: "bx bx-check-shield", enabled: noSelectedNotes },
{ title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes }, { title: t("tree-context-menu.unprotect-subtree"), command: "unprotectSubtree", uiIcon: "bx bx-shield", enabled: noSelectedNotes },
{ title: "----" }, { title: "----" },
{ title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
enabled: isNotRoot && !isHoisted },
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-empty", { title: t("tree-context-menu.advanced"), uiIcon: "bx bxs-wrench", enabled: true, items: [
enabled: isNotRoot && !isHoisted }, { title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus", enabled: true },
{ title: "----" },
{ title: `${t("tree-context-menu.edit-branch-prefix")} <kbd data-command="editBranchPrefix"></kbd>`, command: "editBranchPrefix", uiIcon: "bx bx-rename", enabled: isNotRoot && parentNotSearch && noSelectedNotes && notOptions },
{ title: t("tree-context-menu.convert-to-attachment"), command: "convertNoteToAttachment", uiIcon: "bx bx-paperclip", enabled: isNotRoot && !isHoisted && notOptions },
{ title: `${t("tree-context-menu.duplicate-subtree")} <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-outline", enabled: parentNotSearch && isNotRoot && !isHoisted && notOptions },
{ title: "----" },
{ title: `${t("tree-context-menu.expand-subtree")} <kbd data-command="expandSubtree"></kbd>`, command: "expandSubtree", uiIcon: "bx bx-expand", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.collapse-subtree")} <kbd data-command="collapseSubtree"></kbd>`, command: "collapseSubtree", uiIcon: "bx bx-collapse", enabled: noSelectedNotes },
{ title: `${t("tree-context-menu.sort-by")} <kbd data-command="sortChildNotes"></kbd>`, command: "sortChildNotes", uiIcon: "bx bx-sort-down", enabled: noSelectedNotes && notSearch },
{ title: "----" },
{ title: t("tree-context-menu.copy-note-path-to-clipboard"), command: "copyNotePathToClipboard", uiIcon: "bx bx-directions", enabled: true },
{ title: t("tree-context-menu.recent-changes-in-subtree"), command: "recentChangesInSubtree", uiIcon: "bx bx-history", enabled: noSelectedNotes && notOptions },
] },
{ title: "----" },
{ title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`, command: "cutNotesToClipboard", uiIcon: "bx bx-cut", { title: `${t("tree-context-menu.cut")} <kbd data-command="cutNotesToClipboard"></kbd>`, command: "cutNotesToClipboard", uiIcon: "bx bx-cut",
enabled: isNotRoot && !isHoisted && parentNotSearch }, enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`, command: "moveNotesTo", uiIcon: "bx bx-empty",
enabled: isNotRoot && !isHoisted && parentNotSearch }, { title: `${t("tree-context-menu.copy-clone")} <kbd data-command="copyNotesToClipboard"></kbd>`, command: "copyNotesToClipboard", uiIcon: "bx bx-copy",
enabled: isNotRoot && !isHoisted },
{ title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`, command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste", { title: `${t("tree-context-menu.paste-into")} <kbd data-command="pasteNotesFromClipboard"></kbd>`, command: "pasteNotesFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes }, enabled: !clipboard.isClipboardEmpty() && notSearch && noSelectedNotes },
{ title: t("tree-context-menu.paste-after"), command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste", { title: t("tree-context-menu.paste-after"), command: "pasteNotesAfterFromClipboard", uiIcon: "bx bx-paste",
enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes }, enabled: !clipboard.isClipboardEmpty() && isNotRoot && !isHoisted && parentNotSearch && noSelectedNotes },
{ title: `${t("tree-context-menu.duplicate-subtree")} <kbd data-command="duplicateSubtree">`, command: "duplicateSubtree", uiIcon: "bx bx-empty",
enabled: parentNotSearch && isNotRoot && !isHoisted && notOptions }, { title: `${t("tree-context-menu.move-to")} <kbd data-command="moveNotesTo"></kbd>`, command: "moveNotesTo", uiIcon: "bx bx-transfer",
enabled: isNotRoot && !isHoisted && parentNotSearch },
{ title: `${t("tree-context-menu.clone-to")} <kbd data-command="cloneNotesTo"></kbd>`, command: "cloneNotesTo", uiIcon: "bx bx-duplicate",
enabled: isNotRoot && !isHoisted },
{ title: `${t("tree-context-menu.delete")} <kbd data-command="deleteNotes"></kbd>`, command: "deleteNotes", uiIcon: "bx bx-trash destructive-action-icon",
enabled: isNotRoot && !isHoisted && parentNotSearch && notOptions },
{ title: "----" }, { title: "----" },
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-empty",
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-import",
enabled: notSearch && noSelectedNotes && notOptions }, enabled: notSearch && noSelectedNotes && notOptions },
{ title: t("tree-context-menu.import-into-note"), command: "importIntoNote", uiIcon: "bx bx-empty",
{ title: t("tree-context-menu.export"), command: "exportNote", uiIcon: "bx bx-export",
enabled: notSearch && noSelectedNotes && notOptions }, enabled: notSearch && noSelectedNotes && notOptions },
{ title: t("tree-context-menu.apply-bulk-actions"), command: "openBulkActionsDialog", uiIcon: "bx bx-list-plus",
enabled: true }
{ title: "----" },
{ title: `${t("tree-context-menu.search-in-subtree")} <kbd data-command="searchInSubtree"></kbd>`, command: "searchInSubtree", uiIcon: "bx bx-search",
enabled: notSearch && noSelectedNotes },
].filter(row => row !== null); ].filter(row => row !== null);
} }

View File

@ -39,22 +39,39 @@ const TPL = `
style="position: relative; top: 3px;"></button> style="position: relative; top: 3px;"></button>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
<li data-trigger-command="openAttachment" class="dropdown-item" <li data-trigger-command="openAttachment" class="dropdown-item"
title="${t('attachments_actions.open_externally_title')}"><span class="bx bx-link-external"></span> ${t('attachments_actions.open_externally')}</li> title="${t('attachments_actions.open_externally_title')}"><span class="bx bx-file-find"></span> ${t('attachments_actions.open_externally')}</li>
<li data-trigger-command="openAttachmentCustom" class="dropdown-item" <li data-trigger-command="openAttachmentCustom" class="dropdown-item"
title="${t('attachments_actions.open_custom_title')}"><span class="bx bx-customize"></span> ${t('attachments_actions.open_custom')}</li> title="${t('attachments_actions.open_custom_title')}"><span class="bx bx-customize"></span> ${t('attachments_actions.open_custom')}</li>
<li data-trigger-command="renameAttachment" class="dropdown-item">
<span class="bx bx-rename"></span> ${t('attachments_actions.rename_attachment')}</li>
<li data-trigger-command="copyAttachmentLinkToClipboard" class="dropdown-item"><span class="bx bx-copy">
</span> ${t('attachments_actions.copy_link_to_clipboard')}</li>
<li data-trigger-command="downloadAttachment" class="dropdown-item"> <li data-trigger-command="downloadAttachment" class="dropdown-item">
<span class="bx bx-download"></span> ${t('attachments_actions.download')}</li> <span class="bx bx-download"></span> ${t('attachments_actions.download')}</li>
<li data-trigger-command="copyAttachmentLinkToClipboard" class="dropdown-item"><span class="bx bx-link">
</span> ${t('attachments_actions.copy_link_to_clipboard')}</li>
<div class="dropdown-divider"></div>
<li data-trigger-command="uploadNewAttachmentRevision" class="dropdown-item"><span class="bx bx-upload"> <li data-trigger-command="uploadNewAttachmentRevision" class="dropdown-item"><span class="bx bx-upload">
</span> ${t('attachments_actions.upload_new_revision')}</li> </span> ${t('attachments_actions.upload_new_revision')}</li>
<li data-trigger-command="renameAttachment" class="dropdown-item">
<span class="bx bx-rename"></span> ${t('attachments_actions.rename_attachment')}</li>
<li data-trigger-command="deleteAttachment" class="dropdown-item">
<span class="bx bx-trash destructive-action-icon"></span> ${t('attachments_actions.delete_attachment')}</li>
<div class="dropdown-divider"></div>
<li data-trigger-command="convertAttachmentIntoNote" class="dropdown-item"><span class="bx bx-note"> <li data-trigger-command="convertAttachmentIntoNote" class="dropdown-item"><span class="bx bx-note">
</span> ${t('attachments_actions.convert_attachment_into_note')}</li> </span> ${t('attachments_actions.convert_attachment_into_note')}</li>
<li data-trigger-command="deleteAttachment" class="dropdown-item">
<span class="bx bx-trash"></span> ${t('attachments_actions.delete_attachment')}</li>
</div> </div>
<input type="file" class="attachment-upload-new-revision-input" style="display: none"> <input type="file" class="attachment-upload-new-revision-input" style="display: none">
@ -96,14 +113,14 @@ export default class AttachmentActionsWidget extends BasicWidget {
const $openAttachmentButton = this.$widget.find("[data-trigger-command='openAttachment']"); const $openAttachmentButton = this.$widget.find("[data-trigger-command='openAttachment']");
$openAttachmentButton $openAttachmentButton
.addClass("disabled") .addClass("disabled")
.append($('<span class="disabled-tooltip"> (?)</span>') .append($('<span class="bx bx-info-circle disabled-tooltip" />')
.attr("title", t('attachments_actions.open_externally_detail_page')) .attr("title", t('attachments_actions.open_externally_detail_page'))
); );
if (isElectron) { if (isElectron) {
const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']"); const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']");
$openAttachmentCustomButton $openAttachmentCustomButton
.addClass("disabled") .addClass("disabled")
.append($('<span class="disabled-tooltip"> (?)</span>') .append($('<span class="bx bx-info-circle disabled-tooltip" />')
.attr("title", t('attachments_actions.open_externally_detail_page')) .attr("title", t('attachments_actions.open_externally_detail_page'))
); );
} }
@ -112,7 +129,7 @@ export default class AttachmentActionsWidget extends BasicWidget {
const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']"); const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']");
$openAttachmentCustomButton $openAttachmentCustomButton
.addClass("disabled") .addClass("disabled")
.append($('<span class="disabled-tooltip"> (?)</span>') .append($('<span class="bx bx-info-circle disabled-tooltip" />')
.attr("title", t('attachments_actions.open_custom_client_only')) .attr("title", t('attachments_actions.open_custom_client_only'))
); );
} }

View File

@ -100,6 +100,8 @@ const TPL = `
position: relative; position: relative;
left: 0; left: 0;
top: 5px; top: 5px;
--dropdown-shadow-opacity: 0;
--submenu-opening-delay: 0;
} }
</style> </style>
@ -125,27 +127,17 @@ const TPL = `
</button> </button>
<ul class="dropdown-menu dropdown-menu-right"> <ul class="dropdown-menu dropdown-menu-right">
<li class="dropdown-item" data-trigger-command="showOptions">
<span class="bx bx-cog"></span>
${t('global_menu.options')}
</li>
<li class="dropdown-item" data-trigger-command="openNewWindow"> <li class="dropdown-item" data-trigger-command="openNewWindow">
<span class="bx bx-window-open"></span> <span class="bx bx-window-open"></span>
${t('global_menu.open_new_window')} ${t('global_menu.open_new_window')}
<kbd data-command="openNewWindow"></kbd> <kbd data-command="openNewWindow"></kbd>
</li> </li>
<li class="dropdown-item switch-to-mobile-version-button" data-trigger-command="switchToMobileVersion"> <li class="dropdown-item" data-trigger-command="showShareSubtree">
<span class="bx bx-mobile"></span> <span class="bx bx-share-alt"></span>
${t('global_menu.switch_to_mobile_version')} ${t('global_menu.show_shared_notes_subtree')}
</li> </li>
<li class="dropdown-item switch-to-desktop-version-button" data-trigger-command="switchToDesktopVersion">
<span class="bx bx-desktop"></span>
${t('global_menu.switch_to_desktop_version')}
</li>
<span class="zoom-container dropdown-item"> <span class="zoom-container dropdown-item">
<div> <div>
<span class="bx bx-empty"></span> <span class="bx bx-empty"></span>
@ -165,16 +157,23 @@ const TPL = `
</div> </div>
</span> </span>
<div class="dropdown-divider"></div>
<li class="dropdown-item switch-to-mobile-version-button" data-trigger-command="switchToMobileVersion">
<span class="bx bx-mobile"></span>
${t('global_menu.switch_to_mobile_version')}
</li>
<li class="dropdown-item switch-to-desktop-version-button" data-trigger-command="switchToDesktopVersion">
<span class="bx bx-desktop"></span>
${t('global_menu.switch_to_desktop_version')}
</li>
<li class="dropdown-item" data-trigger-command="showLaunchBarSubtree"> <li class="dropdown-item" data-trigger-command="showLaunchBarSubtree">
<span class="bx bx-sidebar"></span> <span class="bx bx-sidebar"></span>
${t('global_menu.configure_launchbar')} ${t('global_menu.configure_launchbar')}
</li> </li>
<li class="dropdown-item" data-trigger-command="showShareSubtree">
<span class="bx bx-share-alt"></span>
${t('global_menu.show_shared_notes_subtree')}
</li>
<li class="dropdown-item dropdown-submenu"> <li class="dropdown-item dropdown-submenu">
<span class="dropdown-toggle"> <span class="dropdown-toggle">
<span class="bx bx-chip"></span> <span class="bx bx-chip"></span>
@ -182,10 +181,22 @@ const TPL = `
</span> </span>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li class="dropdown-item open-dev-tools-button" data-trigger-command="openDevTools"> <li class="dropdown-item" data-trigger-command="showHiddenSubtree">
<span class="bx bx-bug-alt"></span> <span class="bx bx-hide"></span>
${t('global_menu.open_dev_tools')} ${t('global_menu.show_hidden_subtree')}
<kbd data-command="openDevTools"></kbd> </li>
<li class="dropdown-item" data-trigger-command="showSearchHistory">
<span class="bx bx-search-alt"></span>
${t('global_menu.open_search_history')}
</li>
<div class="dropdown-divider"></div>
<li class="dropdown-item" data-trigger-command="showBackendLog">
<span class="bx bx-detail"></span>
${t('global_menu.show_backend_log')}
<kbd data-command="showBackendLog"></kbd>
</li> </li>
<li class="dropdown-item" data-trigger-command="showSQLConsole"> <li class="dropdown-item" data-trigger-command="showSQLConsole">
@ -198,16 +209,13 @@ const TPL = `
<span class="bx bx-data"></span> <span class="bx bx-data"></span>
${t('global_menu.open_sql_console_history')} ${t('global_menu.open_sql_console_history')}
</li> </li>
<li class="dropdown-item" data-trigger-command="showSearchHistory"> <div class="dropdown-divider"></div>
<span class="bx bx-search-alt"></span>
${t('global_menu.open_search_history')} <li class="dropdown-item open-dev-tools-button" data-trigger-command="openDevTools">
</li> <span class="bx bx-bug-alt"></span>
${t('global_menu.open_dev_tools')}
<li class="dropdown-item" data-trigger-command="showBackendLog"> <kbd data-command="openDevTools"></kbd>
<span class="bx bx-detail"></span>
${t('global_menu.show_backend_log')}
<kbd data-command="showBackendLog"></kbd>
</li> </li>
<li class="dropdown-item" data-trigger-command="reloadFrontendApp" <li class="dropdown-item" data-trigger-command="reloadFrontendApp"
@ -217,13 +225,16 @@ const TPL = `
<kbd data-command="reloadFrontendApp"></kbd> <kbd data-command="reloadFrontendApp"></kbd>
</li> </li>
<li class="dropdown-item" data-trigger-command="showHiddenSubtree">
<span class="bx bx-hide"></span>
${t('global_menu.show_hidden_subtree')}
</li>
</ul> </ul>
</li> </li>
<li class="dropdown-item" data-trigger-command="showOptions">
<span class="bx bx-cog"></span>
${t('global_menu.options')}
</li>
<div class="dropdown-divider"></div>
<li class="dropdown-item show-help-button" data-trigger-command="showHelp"> <li class="dropdown-item show-help-button" data-trigger-command="showHelp">
<span class="bx bx-help-circle"></span> <span class="bx bx-help-circle"></span>
${t('global_menu.show_help')} ${t('global_menu.show_help')}
@ -241,6 +252,8 @@ const TPL = `
<span class="version-text"></span> <span class="version-text"></span>
</li> </li>
<div class="dropdown-divider"></div>
<li class="dropdown-item logout-button" data-trigger-command="logout"> <li class="dropdown-item logout-button" data-trigger-command="logout">
<span class="bx bx-log-out"></span> <span class="bx bx-log-out"></span>
${t('global_menu.logout')} ${t('global_menu.logout')}

View File

@ -42,32 +42,60 @@ const TPL = `
<li data-trigger-command="convertNoteIntoAttachment" class="dropdown-item"> <li data-trigger-command="convertNoteIntoAttachment" class="dropdown-item">
<span class="bx bx-paperclip"></span> ${t('note_actions.convert_into_attachment')} <span class="bx bx-paperclip"></span> ${t('note_actions.convert_into_attachment')}
</li> </li>
<li data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"> <li data-trigger-command="renderActiveNote" class="dropdown-item render-note-button">
<span class="bx bx-extension"></span> ${t('note_actions.re_render_note')}<kbd data-command="renderActiveNote"></kbd> <span class="bx bx-extension"></span> ${t('note_actions.re_render_note')}<kbd data-command="renderActiveNote"></kbd>
</li> </li>
<li data-trigger-command="findInText" class="dropdown-item find-in-text-button"> <li data-trigger-command="findInText" class="dropdown-item find-in-text-button">
<span class='bx bx-search'></span> ${t('note_actions.search_in_note')}<kbd data-command="findInText"></kbd> <span class='bx bx-search'></span> ${t('note_actions.search_in_note')}<kbd data-command="findInText"></kbd>
</li> </li>
<li data-trigger-command="showNoteSource" class="dropdown-item show-source-button">
<span class="bx bx-code"></span> ${t('note_actions.note_source')}<kbd data-command="showNoteSource"></kbd> <li data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button">
</li> <span class="bx bx-printer"></span> ${t('note_actions.print_note')}<kbd data-command="printActiveNote"></kbd></li>
<li data-trigger-command="showAttachments" class="dropdown-item show-attachments-button">
<span class="bx bx-paperclip"></span> ${t('note_actions.note_attachments')}<kbd data-command="showAttachments"></kbd>
</li> <div class="dropdown-divider"></div>
<li class="dropdown-item import-files-button"><span class="bx bx-import"></span> ${t('note_actions.import_files')}</li>
<li class="dropdown-item export-note-button"><span class="bx bx-export"></span> ${t('note_actions.export_note')}</li>
<div class="dropdown-divider"></div>
<li data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button" title="${t('note_actions.open_note_externally_title')}"> <li data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button" title="${t('note_actions.open_note_externally_title')}">
<span class="bx bx-link-external"></span> ${t('note_actions.open_note_externally')}<kbd data-command="openNoteExternally"></kbd> <span class="bx bx-file-find"></span> ${t('note_actions.open_note_externally')}<kbd data-command="openNoteExternally"></kbd>
</li> </li>
<li data-trigger-command="openNoteCustom" class="dropdown-item open-note-custom-button"> <li data-trigger-command="openNoteCustom" class="dropdown-item open-note-custom-button">
<span class="bx bx-customize"></span> ${t('note_actions.open_note_custom')}<kbd data-command="openNoteCustom"></kbd> <span class="bx bx-customize"></span> ${t('note_actions.open_note_custom')}<kbd data-command="openNoteCustom"></kbd>
</li> </li>
<li class="dropdown-item import-files-button"><span class="bx bx-import"></span> ${t('note_actions.import_files')}</li>
<li class="dropdown-item export-note-button"><span class="bx bx-export"></span> ${t('note_actions.export_note')}</li> <li data-trigger-command="showNoteSource" class="dropdown-item show-source-button">
<li class="dropdown-item delete-note-button"><span class="bx bx-trash"></span> ${t('note_actions.delete_note')}</li> <span class="bx bx-code"></span> ${t('note_actions.note_source')}<kbd data-command="showNoteSource"></kbd>
<li data-trigger-command="printActiveNote" class="dropdown-item print-active-note-button"> </li>
<span class="bx bx-printer"></span> ${t('note_actions.print_note')}<kbd data-command="printActiveNote"></kbd></li>
<div class="dropdown-divider"></div>
<li data-trigger-command="forceSaveRevision" class="dropdown-item save-revision-button"> <li data-trigger-command="forceSaveRevision" class="dropdown-item save-revision-button">
<span class="bx bx-save"></span> ${t('note_actions.save_revision')}<kbd data-command="forceSaveRevision"></kbd> <span class="bx bx-save"></span> ${t('note_actions.save_revision')}<kbd data-command="forceSaveRevision"></kbd>
</li> </li>
<li class="dropdown-item delete-note-button"><span class="bx bx-trash destructive-action-icon"></span> ${t('note_actions.delete_note')}</li>
<div class="dropdown-divider"></div>
<li data-trigger-command="showAttachments" class="dropdown-item show-attachments-button">
<span class="bx bx-paperclip"></span> ${t('note_actions.note_attachments')}<kbd data-command="showAttachments"></kbd>
</li>
</div> </div>
</div>`; </div>`;

View File

@ -54,7 +54,7 @@ const TPL = `
data-bs-toggle="dropdown" data-bs-display="static"> data-bs-toggle="dropdown" data-bs-display="static">
</button> </button>
<div class="revision-list dropdown-menu" style="position: static; height: 100%; overflow: auto;"></div> <div class="revision-list dropdown-menu static" style="position: static; height: 100%; overflow: auto;"></div>
</div> </div>
<div class="revision-content-wrapper"> <div class="revision-content-wrapper">

View File

@ -259,12 +259,14 @@ export default class TabRowWidget extends BasicWidget {
x: e.pageX, x: e.pageX,
y: e.pageY, y: e.pageY,
items: [ items: [
{title: t('tab_row.close'), command: "closeTab", uiIcon: "bx bx-x"}, {title: t('tab_row.close'), command: "closeTab", uiIcon: "bx bxs-x-circle"},
{title: t('tab_row.close_other_tabs'), command: "closeOtherTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.length !== 1}, {title: t('tab_row.close_other_tabs'), command: "closeOtherTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.length !== 1},
{title: t('tab_row.close_right_tabs'), command: "closeRightTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.at(-1).ntxId !== ntxId}, {title: t('tab_row.close_right_tabs'), command: "closeRightTabs", uiIcon: "bx bx-empty", enabled: appContext.tabManager.noteContexts.at(-1).ntxId !== ntxId},
{title: t('tab_row.close_all_tabs'), command: "closeAllTabs", uiIcon: "bx bx-empty"}, {title: t('tab_row.close_all_tabs'), command: "closeAllTabs", uiIcon: "bx bx-empty"},
{ title: "----" },
{title: t('tab_row.move_tab_to_new_window'), command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"} {title: "----"},
{title: t('tab_row.move_tab_to_new_window'), command: "moveTabToNewWindow", uiIcon: "bx bx-window-open"},
], ],
selectMenuItemHandler: ({command}) => { selectMenuItemHandler: ({command}) => {
this.triggerCommand(command, {ntxId}); this.triggerCommand(command, {ntxId});

View File

@ -19,6 +19,10 @@
--bs-table-bg: transparent !important; --bs-table-bg: transparent !important;
} }
:root {
--submenu-opening-delay: 300ms;
}
html { html {
/* this fixes FF filter vs. position fixed bug: https://github.com/zadam/trilium/issues/233 */ /* this fixes FF filter vs. position fixed bug: https://github.com/zadam/trilium/issues/233 */
height: 100%; height: 100%;
@ -229,7 +233,15 @@ div.ui-tooltip {
} }
.dropdown-divider { .dropdown-divider {
background-color: var(--menu-text-color); border-color: var(--dropdown-border-color);
}
@keyframes dropdown-menu-opening {
from {
opacity: 0;
} to {
opacity: 1;
}
} }
.dropdown-menu { .dropdown-menu {
@ -237,6 +249,26 @@ div.ui-tooltip {
color: var(--menu-text-color) !important; color: var(--menu-text-color) !important;
background-color: var(--menu-background-color) !important; background-color: var(--menu-background-color) !important;
font-size: inherit; font-size: inherit;
box-shadow: 0px 10px 20px rgba(0, 0, 0, var(--dropdown-shadow-opacity));
animation: dropdown-menu-opening 100ms ease-in;
}
@supports(animation-fill-mode: forwards) {
/* Delay the opening of submenus */
.dropdown-submenu .dropdown-menu {
opacity: 0;
animation-fill-mode: forwards;
animation-delay: var(--submenu-opening-delay);
}
}
.dropdown-menu.static {
box-shadow: unset;
}
.dropend .dropdown-toggle::after {
margin-left: .5em;
color: var(--muted-text-color);
} }
.dropdown-menu .disabled { .dropdown-menu .disabled {
@ -246,8 +278,15 @@ div.ui-tooltip {
.dropdown-menu .disabled .disabled-tooltip { .dropdown-menu .disabled .disabled-tooltip {
pointer-events: all; pointer-events: all;
color: var(--menu-text-color); margin-left: 8px;
font-size: .5em;
color: var(--disabled-tooltip-icon-color);
cursor: help; cursor: help;
opacity: .75;
}
.dropdown-menu .disabled .disabled-tooltip:hover {
opacity: 1;
} }
.dropdown-menu a:hover:not(.disabled), .dropdown-item:hover:not(.disabled) { .dropdown-menu a:hover:not(.disabled), .dropdown-item:hover:not(.disabled) {
@ -288,6 +327,10 @@ div.ui-tooltip {
outline: none; outline: none;
} }
.dropdown-item .destructive-action-icon {
color: var(--dropdown-item-icon-destructive-color);
}
.CodeMirror { .CodeMirror {
height: 100%; height: 100%;
background: inherit; background: inherit;
@ -1241,4 +1284,5 @@ textarea {
.empty-table-placeholder { .empty-table-placeholder {
text-align: center; text-align: center;
color: var(--muted-text-color); color: var(--muted-text-color);
} }

View File

@ -17,6 +17,10 @@
--main-text-color: #ccc; --main-text-color: #ccc;
--main-border-color: #aaa; --main-border-color: #aaa;
--dropdown-border-color: #555; --dropdown-border-color: #555;
--dropdown-shadow-opacity: .4;
--dropdown-item-icon-destructive-color: #de6e5b;
--disabled-tooltip-icon-color: #7fd2ef;
--accented-background-color: #555; --accented-background-color: #555;
--more-accented-background-color: #777; --more-accented-background-color: #777;

View File

@ -21,6 +21,9 @@ html {
--main-text-color: black; --main-text-color: black;
--main-border-color: #ccc; --main-border-color: #ccc;
--dropdown-border-color: #ccc; --dropdown-border-color: #ccc;
--dropdown-shadow-opacity: .2;
--dropdown-item-icon-destructive-color: #ec5138;
--disabled-tooltip-icon-color: #004382;
--accented-background-color: #f5f5f5; --accented-background-color: #f5f5f5;
--more-accented-background-color: #ddd; --more-accented-background-color: #ddd;