This commit is contained in:
Adorian Doran 2025-10-03 16:49:20 +03:00
commit 1d373bc7d5
6 changed files with 37 additions and 15 deletions

View File

@ -148,13 +148,21 @@ describe("shortcuts", () => {
expect(matchesShortcut(event, "a")).toBe(false); expect(matchesShortcut(event, "a")).toBe(false);
}); });
it("should match function keys even with no modifiers", () => { it("should match some keys even with no modifiers", () => {
// Bare function keys
let event = createKeyboardEvent({ key: "F1", code: "F1" }); let event = createKeyboardEvent({ key: "F1", code: "F1" });
expect(matchesShortcut(event, "F1")).toBeTruthy(); expect(matchesShortcut(event, "F1")).toBeTruthy();
expect(matchesShortcut(event, "f1")).toBeTruthy(); expect(matchesShortcut(event, "f1")).toBeTruthy();
// Function keys with shift
event = createKeyboardEvent({ key: "F1", code: "F1", shiftKey: true }); event = createKeyboardEvent({ key: "F1", code: "F1", shiftKey: true });
expect(matchesShortcut(event, "Shift+F1")).toBeTruthy(); expect(matchesShortcut(event, "Shift+F1")).toBeTruthy();
// Special keys
for (const keyCode of [ "Delete", "Enter" ]) {
event = createKeyboardEvent({ key: keyCode, code: keyCode });
expect(matchesShortcut(event, keyCode), `Key ${keyCode}`).toBeTruthy();
}
}); });
it("should handle alternative modifier names", () => { it("should handle alternative modifier names", () => {

View File

@ -36,10 +36,19 @@ const keyMap: { [key: string]: string[] } = {
}; };
// Function keys // Function keys
const functionKeyCodes: string[] = [];
for (let i = 1; i <= 19; i++) { for (let i = 1; i <= 19; i++) {
keyMap[`f${i}`] = [`F${i}`]; const keyCode = `F${i}`;
functionKeyCodes.push(keyCode);
keyMap[`f${i}`] = [ keyCode ];
} }
const KEYCODES_WITH_NO_MODIFIER = new Set([
"Delete",
"Enter",
...functionKeyCodes
]);
/** /**
* Check if IME (Input Method Editor) is composing * Check if IME (Input Method Editor) is composing
* This is used to prevent keyboard shortcuts from firing during IME composition * This is used to prevent keyboard shortcuts from firing during IME composition
@ -163,8 +172,8 @@ export function matchesShortcut(e: KeyboardEvent, shortcut: string): boolean {
const expectedMeta = modifiers.includes('meta') || modifiers.includes('cmd') || modifiers.includes('command'); const expectedMeta = modifiers.includes('meta') || modifiers.includes('cmd') || modifiers.includes('command');
// Refuse key combinations that don't include modifiers because they interfere with the normal usage of the application. // Refuse key combinations that don't include modifiers because they interfere with the normal usage of the application.
// Function keys are an exception. // Some keys such as function keys are an exception.
if (!(expectedCtrl || expectedAlt || expectedShift || expectedMeta) && !/f\d+/.test(key)) { if (!(expectedCtrl || expectedAlt || expectedShift || expectedMeta) && !KEYCODES_WITH_NO_MODIFIER.has(e.code)) {
return false; return false;
} }

View File

@ -31,7 +31,7 @@
#center-pane > *:not(.split-note-container-widget), #center-pane > *:not(.split-note-container-widget),
#right-pane, #right-pane,
.title-row .note-icon-widget, .title-row .note-icon-widget,
.title-row .button-widget, .title-row .icon-action,
.ribbon-container, .ribbon-container,
.promoted-attributes-widget, .promoted-attributes-widget,
.scroll-padding-widget, .scroll-padding-widget,

View File

@ -51,6 +51,7 @@ const TAB_CONFIGURATION = numberObjectsInPlace<TabConfiguration>([
show: ({ note }) => note?.type === "text" && options.get("textNoteEditorType") === "ckeditor-classic", show: ({ note }) => note?.type === "text" && options.get("textNoteEditorType") === "ckeditor-classic",
toggleCommand: "toggleRibbonTabClassicEditor", toggleCommand: "toggleRibbonTabClassicEditor",
content: FormattingToolbar, content: FormattingToolbar,
activate: true,
stayInDom: true stayInDom: true
}, },
{ {

View File

@ -90,6 +90,7 @@ export default function AppearanceSettings() {
{isElectron() && <ElectronIntegration /> } {isElectron() && <ElectronIntegration /> }
<Performance /> <Performance />
<MaxContentWidth /> <MaxContentWidth />
<RibbonOptions />
<RelatedSettings items={[ <RelatedSettings items={[
{ {
title: t("settings_appearance.related_code_blocks"), title: t("settings_appearance.related_code_blocks"),
@ -305,3 +306,16 @@ function MaxContentWidth() {
</OptionsSection> </OptionsSection>
) )
} }
function RibbonOptions() {
const [ editedNotesOpenInRibbon, setEditedNotesOpenInRibbon ] = useTriliumOptionBool("editedNotesOpenInRibbon");
return (
<OptionsSection title={t('ribbon.widgets')}>
<FormCheckbox
label={t('ribbon.edited_notes_message')}
currentValue={editedNotesOpenInRibbon} onChange={setEditedNotesOpenInRibbon}
/>
</OptionsSection>
)
}

View File

@ -45,14 +45,4 @@ export default class ReadOnlyCodeTypeWidget extends AbstractCodeTypeWidget {
readOnly: true readOnly: true
}; };
} }
async executeWithContentElementEvent({ resolve, ntxId }: EventData<"executeWithContentElement">) {
if (!this.isNoteContext(ntxId)) {
return;
}
await this.initialized;
resolve(this.$editor);
}
} }