keyboard shortcuts for ribbon tabs

This commit is contained in:
zadam 2021-06-27 12:53:05 +02:00
parent 9e1c9782ff
commit 0351d7eff1
17 changed files with 195 additions and 38 deletions

3
TODO
View file

@ -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

View file

@ -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

View file

@ -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();

View file

@ -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');
}

View file

@ -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';
}

View file

@ -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';
}

View 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';
}

View file

@ -21,6 +21,10 @@ const TPL = `
</div>`;
export default class InheritedAttributesWidget extends NoteContextAwareWidget {
get name() {
return "inheritedAttributes";
}
constructor() {
super();

View file

@ -38,6 +38,10 @@ const TPL = `
</div>`;
export default class LinkMapWidget extends NoteContextAwareWidget {
get name() {
return "linkMap";
}
isEnabled() {
return this.note;
}

View file

@ -62,6 +62,10 @@ const TPL = `
</div>
`;
export default class NoteInfoWidget extends NoteContextAwareWidget {
get name() {
return "noteInfo";
}
isEnabled() {
return this.note;
}

View file

@ -36,6 +36,10 @@ const TPL = `
</div>`;
export default class NotePathsWidget extends NoteContextAwareWidget {
get name() {
return "notePaths";
}
isEnabled() {
return this.note;
}

View file

@ -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');

View file

@ -22,6 +22,10 @@ const TPL = `
`;
export default class OwnedAttributeListWidget extends NoteContextAwareWidget {
get name() {
return "ownedAttributes";
}
constructor() {
super();

View file

@ -35,6 +35,10 @@ const TPL = `
`;
export default class PromotedAttributesWidget extends NoteContextAwareWidget {
get name() {
return "promotedAttributes";
}
doRender() {
this.$widget = $(TPL);
this.contentSized();

View file

@ -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">

View file

@ -31,6 +31,10 @@ const TPL = `
`;
export default class SimilarNotesWidget extends NoteContextAwareWidget {
get name() {
return "similarNotes";
}
isEnabled() {
return super.isEnabled()
&& this.note.type !== 'search'

View file

@ -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"
},