mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	keyboard shortcuts for ribbon tabs
This commit is contained in:
		
							
								
								
									
										3
									
								
								TODO
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								TODO
									
									
									
									
									
								
							@@ -1,7 +1,4 @@
 | 
			
		||||
- all ribbon tabs should have assignable shortcut
 | 
			
		||||
- new icon
 | 
			
		||||
- green theme
 | 
			
		||||
- polish becca entities API
 | 
			
		||||
- separate private and public APIs in becca entities
 | 
			
		||||
- handle FIXMEs
 | 
			
		||||
- fix Steel Blue example
 | 
			
		||||
 
 | 
			
		||||
@@ -3,3 +3,8 @@
 | 
			
		||||
- isDeleted = 0 by default
 | 
			
		||||
- rename openTabs to openNoteContexts
 | 
			
		||||
- migrate black theme to dark theme
 | 
			
		||||
- unify readOnly handling to a single attribute:
 | 
			
		||||
  * readOnly - like now
 | 
			
		||||
  * readOnly=auto - like without readOnly (used to override inherited readOnly)
 | 
			
		||||
  * readOnly=never - like autoReadOnlyDisabled
 | 
			
		||||
- remove focusOnAttributesKeyboardShortcut
 | 
			
		||||
 
 | 
			
		||||
@@ -161,31 +161,34 @@ export default class RibbonContainer extends NoteContextAwareWidget {
 | 
			
		||||
        this.$tabContainer.on('click', '.ribbon-tab-title', e => {
 | 
			
		||||
            const $ribbonTitle = $(e.target).closest('.ribbon-tab-title');
 | 
			
		||||
 | 
			
		||||
            const activate = !$ribbonTitle.hasClass("active");
 | 
			
		||||
 | 
			
		||||
            this.$tabContainer.find('.ribbon-tab-title').removeClass("active");
 | 
			
		||||
            this.$bodyContainer.find('.ribbon-body').removeClass("active");
 | 
			
		||||
 | 
			
		||||
            if (activate) {
 | 
			
		||||
                const ribbonComponendId = $ribbonTitle.attr('data-ribbon-component-id');
 | 
			
		||||
 | 
			
		||||
                this.lastActiveComponentId = ribbonComponendId;
 | 
			
		||||
 | 
			
		||||
                this.$tabContainer.find(`.ribbon-tab-title[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
 | 
			
		||||
                this.$bodyContainer.find(`.ribbon-body[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
 | 
			
		||||
 | 
			
		||||
                const activeChild = this.getActiveRibbonWidget();
 | 
			
		||||
 | 
			
		||||
                if (activeChild) {
 | 
			
		||||
                    activeChild.handleEvent('noteSwitched', {noteContext: this.noteContext, notePath: this.notePath});
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                this.lastActiveComponentId = null;
 | 
			
		||||
            }
 | 
			
		||||
            this.toggleRibbonTab($ribbonTitle);
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toggleRibbonTab($ribbonTitle) {
 | 
			
		||||
        const activate = !$ribbonTitle.hasClass("active");
 | 
			
		||||
 | 
			
		||||
        this.$tabContainer.find('.ribbon-tab-title').removeClass("active");
 | 
			
		||||
        this.$bodyContainer.find('.ribbon-body').removeClass("active");
 | 
			
		||||
 | 
			
		||||
        if (activate) {
 | 
			
		||||
            const ribbonComponendId = $ribbonTitle.attr('data-ribbon-component-id');
 | 
			
		||||
 | 
			
		||||
            this.lastActiveComponentId = ribbonComponendId;
 | 
			
		||||
 | 
			
		||||
            this.$tabContainer.find(`.ribbon-tab-title[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
 | 
			
		||||
            this.$bodyContainer.find(`.ribbon-body[data-ribbon-component-id="${ribbonComponendId}"]`).addClass("active");
 | 
			
		||||
 | 
			
		||||
            const activeChild = this.getActiveRibbonWidget();
 | 
			
		||||
 | 
			
		||||
            if (activeChild) {
 | 
			
		||||
                activeChild.handleEvent('noteSwitched', {noteContext: this.noteContext, notePath: this.notePath});
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            this.lastActiveComponentId = null;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async refreshWithNote(note, noExplicitActivation = false) {
 | 
			
		||||
        this.lastNoteType = note.type;
 | 
			
		||||
 | 
			
		||||
@@ -202,6 +205,7 @@ export default class RibbonContainer extends NoteContextAwareWidget {
 | 
			
		||||
 | 
			
		||||
            const $ribbonTitle = $('<div class="ribbon-tab-title">')
 | 
			
		||||
                .attr('data-ribbon-component-id', ribbonWidget.componentId)
 | 
			
		||||
                .attr('data-ribbon-component-name', ribbonWidget.name)
 | 
			
		||||
                .append($('<span class="ribbon-tab-title-icon">')
 | 
			
		||||
                            .addClass(ret.icon)
 | 
			
		||||
                            .attr("title", ret.title))
 | 
			
		||||
@@ -234,10 +238,56 @@ export default class RibbonContainer extends NoteContextAwareWidget {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isRibbonTabActive(name) {
 | 
			
		||||
        const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`);
 | 
			
		||||
 | 
			
		||||
        return $ribbonComponent.hasClass("active");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    refreshRibbonContainerCommand() {
 | 
			
		||||
        this.refreshWithNote(this.note, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ensureOwnedAttributesAreOpen(ntxId) {
 | 
			
		||||
        if (this.isNoteContext(ntxId) && !this.isRibbonTabActive('ownedAttributes')) {
 | 
			
		||||
            this.toggleRibbonTabWithName('ownedAttributes', ntxId);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addNewLabelEvent({ntxId}) {
 | 
			
		||||
        this.ensureOwnedAttributesAreOpen(ntxId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addNewRelationEvent({ntxId}) {
 | 
			
		||||
        this.ensureOwnedAttributesAreOpen(ntxId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    toggleRibbonTabWithName(name, ntxId) {
 | 
			
		||||
        if (!this.isNoteContext(ntxId)) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const $ribbonComponent = this.$widget.find(`.ribbon-tab-title[data-ribbon-component-name='${name}']`);
 | 
			
		||||
 | 
			
		||||
        if ($ribbonComponent) {
 | 
			
		||||
            this.toggleRibbonTab($ribbonComponent);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    handleEvent(name, data) {
 | 
			
		||||
        const PREFIX = "toggleRibbonTab";
 | 
			
		||||
 | 
			
		||||
        if (name.startsWith(PREFIX)) {
 | 
			
		||||
            let componentName = name.substr(PREFIX.length);
 | 
			
		||||
            componentName = componentName[0].toLowerCase() + componentName.substr(1);
 | 
			
		||||
 | 
			
		||||
            this.toggleRibbonTabWithName(componentName, data.ntxId);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return super.handleEvent(name, data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async handleEventInChildren(name, data) {
 | 
			
		||||
        if (['activeContextChanged', 'setNoteContext'].includes(name)) {
 | 
			
		||||
            // won't trigger .refresh();
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,10 @@ export default class BasicPropertiesWidget extends NoteContextAwareWidget {
 | 
			
		||||
        this.child(this.noteTypeWidget, this.protectedNoteSwitchWidget, this.editabilitySelectWidget);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "basicProperties";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note && (this.note.type === 'text' || this.note.type === 'code');
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -42,6 +42,10 @@ const TPL = `
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
export default class BookPropertiesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "bookProperties";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note && this.note.type === 'book';
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -55,6 +55,10 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class FilePropertiesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "fileProperties";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note && this.note.type === 'file';
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,10 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class ImagePropertiesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "imageProperties";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note && this.note.type === 'image';
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,10 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class InheritedAttributesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "inheritedAttributes";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,10 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class LinkMapWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "linkMap";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -62,6 +62,10 @@ const TPL = `
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
export default class NoteInfoWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "noteInfo";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,10 @@ const TPL = `
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
export default class NotePathsWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "notePaths";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,9 @@ const TPL = `
 | 
			
		||||
    </div>
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * TODO: figure out better name or conceptualize better.
 | 
			
		||||
 */
 | 
			
		||||
export default class NotePropertiesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return this.note && !!this.note.getLabelValue('pageUrl');
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,10 @@ const TPL = `
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export default class OwnedAttributeListWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "ownedAttributes";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,10 @@ const TPL = `
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "promotedAttributes";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    doRender() {
 | 
			
		||||
        this.$widget = $(TPL);
 | 
			
		||||
        this.contentSized();
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,6 @@ import Limit from "../search_options/limit.js";
 | 
			
		||||
import DeleteNoteRevisionsSearchAction from "../search_actions/delete_note_revisions.js";
 | 
			
		||||
import Debug from "../search_options/debug.js";
 | 
			
		||||
import appContext from "../../services/app_context.js";
 | 
			
		||||
import toast from "../../services/toast.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="search-definition-widget">
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,10 @@ const TPL = `
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export default class SimilarNotesWidget extends NoteContextAwareWidget {
 | 
			
		||||
    get name() {
 | 
			
		||||
        return "similarNotes";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEnabled() {
 | 
			
		||||
        return super.isEnabled()
 | 
			
		||||
            && this.note.type !== 'search'
 | 
			
		||||
 
 | 
			
		||||
@@ -236,12 +236,6 @@ const DEFAULT_KEYBOARD_ACTIONS = [
 | 
			
		||||
        description: "Shows Note Source dialog",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "showLinkMap",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Shows Link Map dialog",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "showOptions",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
@@ -324,12 +318,6 @@ const DEFAULT_KEYBOARD_ACTIONS = [
 | 
			
		||||
        separator: "Attributes (labels & relations)"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "focusOnAttributes",
 | 
			
		||||
        defaultShortcuts: ["Alt+A"],
 | 
			
		||||
        description: "Put focus into attribute editor",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "addNewLabel",
 | 
			
		||||
        defaultShortcuts: ["Alt+L"],
 | 
			
		||||
@@ -343,6 +331,77 @@ const DEFAULT_KEYBOARD_ACTIONS = [
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        separator: "Ribbon tabs"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabBasicProperties",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Basic Properties",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabBookProperties",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Book Properties",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabFileProperties",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle File Properties",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabImageProperties",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Image Properties",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabOwnedAttributes",
 | 
			
		||||
        defaultShortcuts: ["Alt+A"],
 | 
			
		||||
        description: "Toggle Owned Attributes",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabInheritedAttributes",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Inherited Attributes",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabPromotedAttributes",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Promoted Attributes",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabLinkMap",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Link Map",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabNoteInfo",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Note Info",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabNotePaths",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Note Paths",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        actionName: "toggleRibbonTabSimilarNotes",
 | 
			
		||||
        defaultShortcuts: [],
 | 
			
		||||
        description: "Toggle Similar Notes",
 | 
			
		||||
        scope: "window"
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
        separator: "Other"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user