feat: Added command palette for quick actions and switching between items (#2933) [skip e2e]
* wip: command palette * use code instead of key * show recent items above commands * refactor * fix command * add placeholder * Tab/Shift-Tab to switch tabs * Fix test * Add menu item to general account menu * if shortcut_id is available, use that as the id * make toggle fn more stable * small naming changes * fix name * Close open modals and popovers when opening command palette * use stable ids + make sure selectedNotesCount only changes when the count actually changes * display all commands, even ones in recents list
This commit is contained in:
@@ -41,3 +41,4 @@ export const OPEN_PREFERENCES_COMMAND = createKeyboardCommand('OPEN_PREFERENCES_
|
||||
export const CHANGE_EDITOR_WIDTH_COMMAND = createKeyboardCommand('CHANGE_EDITOR_WIDTH_COMMAND')
|
||||
|
||||
export const TOGGLE_KEYBOARD_SHORTCUTS_MODAL = createKeyboardCommand('TOGGLE_KEYBOARD_SHORTCUTS_MODAL')
|
||||
export const TOGGLE_COMMAND_PALETTE = createKeyboardCommand('TOGGLE_COMMAND_PALETTE')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Environment, Platform } from '@standardnotes/snjs'
|
||||
import { Environment, Platform, UuidGenerator } from '@standardnotes/snjs'
|
||||
import { eventMatchesKeyAndModifiers } from './eventMatchesKeyAndModifiers'
|
||||
import { KeyboardCommand } from './KeyboardCommands'
|
||||
import { KeyboardKeyEvent } from './KeyboardKeyEvent'
|
||||
@@ -28,6 +28,20 @@ export class KeyboardService {
|
||||
}
|
||||
}
|
||||
|
||||
private isDisabled = false
|
||||
/**
|
||||
* When called, the service will stop triggering command handlers
|
||||
* on keydown/keyup events. Useful when you need to handle events
|
||||
* yourself while keeping the rest of behaviours inert.
|
||||
* Make sure to call {@link enableEventHandling} once done.
|
||||
*/
|
||||
public disableEventHandling() {
|
||||
this.isDisabled = true
|
||||
}
|
||||
public enableEventHandling() {
|
||||
this.isDisabled = false
|
||||
}
|
||||
|
||||
get isMac() {
|
||||
return this.platform === Platform.MacDesktop || this.platform === Platform.MacWeb
|
||||
}
|
||||
@@ -116,6 +130,9 @@ export class KeyboardService {
|
||||
}
|
||||
|
||||
private handleKeyboardEvent(event: KeyboardEvent, keyEvent: KeyboardKeyEvent): void {
|
||||
if (this.isDisabled) {
|
||||
return
|
||||
}
|
||||
for (const command of this.commandMap.keys()) {
|
||||
const shortcut = this.commandMap.get(command)
|
||||
if (!shortcut) {
|
||||
@@ -243,6 +260,7 @@ export class KeyboardService {
|
||||
...shortcut,
|
||||
category: handler.category,
|
||||
description: handler.description,
|
||||
id: UuidGenerator.GenerateUuid(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,11 +268,12 @@ export class KeyboardService {
|
||||
* Register help item for a keyboard shortcut that is handled outside of the KeyboardService,
|
||||
* for example by a library like Lexical.
|
||||
*/
|
||||
registerExternalKeyboardShortcutHelpItem(item: KeyboardShortcutHelpItem): () => void {
|
||||
this.keyboardShortcutHelpItems.add(item)
|
||||
registerExternalKeyboardShortcutHelpItem(item: Omit<KeyboardShortcutHelpItem, 'id'>): () => void {
|
||||
const itemWithId = { ...item, id: UuidGenerator.GenerateUuid() }
|
||||
this.keyboardShortcutHelpItems.add(itemWithId)
|
||||
|
||||
return () => {
|
||||
this.keyboardShortcutHelpItems.delete(item)
|
||||
this.keyboardShortcutHelpItems.delete(itemWithId)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +281,7 @@ export class KeyboardService {
|
||||
* Register help item for a keyboard shortcut that is handled outside of the KeyboardService,
|
||||
* for example by a library like Lexical.
|
||||
*/
|
||||
registerExternalKeyboardShortcutHelpItems(items: KeyboardShortcutHelpItem[]): () => void {
|
||||
registerExternalKeyboardShortcutHelpItems(items: Omit<KeyboardShortcutHelpItem, 'id'>[]): () => void {
|
||||
const disposers = items.map((item) => this.registerExternalKeyboardShortcutHelpItem(item))
|
||||
|
||||
return () => {
|
||||
|
||||
@@ -21,8 +21,9 @@ export type PlatformedKeyboardShortcut = KeyboardShortcut & {
|
||||
|
||||
export type KeyboardShortcutCategory = 'General' | 'Notes list' | 'Current note' | 'Super notes' | 'Formatting'
|
||||
|
||||
export type KeyboardShortcutHelpItem = Omit<PlatformedKeyboardShortcut, 'command'> & {
|
||||
export interface KeyboardShortcutHelpItem extends Omit<PlatformedKeyboardShortcut, 'command'> {
|
||||
command?: KeyboardCommand
|
||||
category: KeyboardShortcutCategory
|
||||
description: string
|
||||
id: string
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
CHANGE_EDITOR_WIDTH_COMMAND,
|
||||
SUPER_TOGGLE_TOOLBAR,
|
||||
TOGGLE_KEYBOARD_SHORTCUTS_MODAL,
|
||||
TOGGLE_COMMAND_PALETTE,
|
||||
} from './KeyboardCommands'
|
||||
import { KeyboardKey } from './KeyboardKey'
|
||||
import { KeyboardModifier, getPrimaryModifier } from './KeyboardModifier'
|
||||
@@ -108,7 +109,7 @@ export function getKeyboardShortcuts(platform: Platform, _environment: Environme
|
||||
},
|
||||
{
|
||||
command: CHANGE_EDITOR_COMMAND,
|
||||
key: '/',
|
||||
key: '?',
|
||||
modifiers: [primaryModifier, KeyboardModifier.Shift],
|
||||
preventDefault: true,
|
||||
},
|
||||
@@ -200,5 +201,10 @@ export function getKeyboardShortcuts(platform: Platform, _environment: Environme
|
||||
key: '/',
|
||||
modifiers: [primaryModifier],
|
||||
},
|
||||
{
|
||||
command: TOGGLE_COMMAND_PALETTE,
|
||||
code: 'Semicolon',
|
||||
modifiers: [primaryModifier, KeyboardModifier.Shift],
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function keyboardCharacterForKeyOrCode(keyOrCode: string) {
|
||||
export function keyboardCharacterForKeyOrCode(keyOrCode: string, shiftKey = false) {
|
||||
if (keyOrCode.startsWith('Digit')) {
|
||||
return keyOrCode.replace('Digit', '')
|
||||
}
|
||||
@@ -14,6 +14,8 @@ export function keyboardCharacterForKeyOrCode(keyOrCode: string) {
|
||||
return '←'
|
||||
case 'ArrowRight':
|
||||
return '→'
|
||||
case 'Semicolon':
|
||||
return shiftKey ? ':' : ';'
|
||||
default:
|
||||
return keyOrCode
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user