From b8134fb0d0c56ba9c0e6e538e3f01f23ca02dfc4 Mon Sep 17 00:00:00 2001 From: Antoine Guenet Date: Mon, 31 Aug 2020 10:07:13 +0200 Subject: [PATCH] [ADD] DevTools: tools to display the keystrokes for bug reporting --- packages/plugin-devtools/assets/DevTools.css | 22 +++++++ packages/plugin-devtools/assets/DevTools.xml | 5 +- .../src/components/DevToolsComponent.ts | 62 ++++++++++++++++++- packages/plugin-dom-layout/src/DomLayout.ts | 8 ++- 4 files changed, 93 insertions(+), 4 deletions(-) diff --git a/packages/plugin-devtools/assets/DevTools.css b/packages/plugin-devtools/assets/DevTools.css index 8c439fea8..cfb5a1813 100644 --- a/packages/plugin-devtools/assets/DevTools.css +++ b/packages/plugin-devtools/assets/DevTools.css @@ -360,3 +360,25 @@ devtools-info devtools-about devtools-id { color: #76526c; font-size: smaller; } + +/* Keystrokes display */ +#keys_log { + opacity: 0; + padding: 5px; + z-index: 100000; + margin: 25px; + position: fixed; + top: 0px; + background-color: #875A7B; + color: white; + font-size: 25px; + border: 1px solid #68465f; + border-radius: 10px; + -webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42); + -moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42); + box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42); +} +#keys_log.has-key { + transition: opacity .5s; + opacity: 1; +} diff --git a/packages/plugin-devtools/assets/DevTools.xml b/packages/plugin-devtools/assets/DevTools.xml index f35acfb9a..1ae5a36be 100644 --- a/packages/plugin-devtools/assets/DevTools.xml +++ b/packages/plugin-devtools/assets/DevTools.xml @@ -494,7 +494,10 @@ Modes - 🔍 + 🔍 + 🅺 diff --git a/packages/plugin-devtools/src/components/DevToolsComponent.ts b/packages/plugin-devtools/src/components/DevToolsComponent.ts index ccfc8b84b..b93258f0e 100644 --- a/packages/plugin-devtools/src/components/DevToolsComponent.ts +++ b/packages/plugin-devtools/src/components/DevToolsComponent.ts @@ -7,14 +7,17 @@ import { OwlComponent } from '../../../plugin-owl/src/OwlComponent'; import { CommandIdentifier, CommandParams } from '../../../core/src/Dispatcher'; import { nodeName } from '../../../utils/src/utils'; import { hooks } from '@odoo/owl'; +import { ProcessKeydownParams } from '../../../plugin-dom-layout/src/DomLayout'; -////////////////////////////// todo: use API /////////////////////////////////// +const keystrokeDiv = document.createElement('div'); +keystrokeDiv.id = 'keys_log'; interface DevToolsState { closed: boolean; // Are the devtools open? height: number; // In px currentTab: string; // Name of the current tab commands: Array<[CommandIdentifier, CommandParams]>; + displayKeystrokes: boolean; } export class DevToolsComponent extends OwlComponent { @@ -33,18 +36,34 @@ export class DevToolsComponent extends OwlComponent { currentTab: 'inspector', height: 300, commands: [], // Stack of all commands executed since init. + displayKeystrokes: false, }; - localStorage = ['closed', 'currentTab', 'height']; + localStorage = ['closed', 'currentTab', 'height', 'displayKeystrokes']; // For resizing/opening (see toggleClosed) _heightOnLastMousedown: number; async willStart(): Promise { this.env.editor.dispatcher.registerCommandHook('*', this.addCommand.bind(this)); this.env.editor.dispatcher.registerCommandHook('@commit', this.render.bind(this)); + this.env.editor.dispatcher.registerCommandHook( + '@layout-keydown', + this.displayKeystroke.bind(this), + ); return super.willStart(); } + async mounted(): Promise { + if (this.state.displayKeystrokes) { + if (!document.getElementById('keys_log')) { + document.body.appendChild(keystrokeDiv); + } + } + return super.mounted(); + } willUnmount(): void { this.state.commands = []; + if (this.state.displayKeystrokes && keystrokeDiv.parentNode === document.body) { + document.body.removeChild(keystrokeDiv); + } } //-------------------------------------------------------------------------- @@ -69,6 +88,45 @@ export class DevToolsComponent extends OwlComponent { this.state.currentTab = 'inspector'; (this.inspectorRef.comp as InspectorComponent)?.inspectDom(); } + /** + * Toggle display keystrokes. + */ + toggleKeystrokes(): void { + this.state.displayKeystrokes = !this.state.displayKeystrokes; + if (this.state.displayKeystrokes) { + if (!document.getElementById('keys_log')) { + document.body.appendChild(keystrokeDiv); + } + } else if (keystrokeDiv.parentNode === document.body) { + document.body.removeChild(keystrokeDiv); + } + } + /** + * Display the key hit on the screen. + * + * @param params + */ + displayKeystroke(params: ProcessKeydownParams): void { + if (!this.state.displayKeystrokes) return; + const ev = params.event; + keystrokeDiv.textContent = ''; + keystrokeDiv.className = ''; + if (['Control', 'Alt', 'Shift', 'Meta'].includes(ev.key)) { + keystrokeDiv.className = 'has-key'; + keystrokeDiv.textContent = `'${ev.key}'`; + } else if (ev.key) { + keystrokeDiv.className = 'has-key'; + const keyModifiers = [ + ev.metaKey ? 'Meta+' : false, + ev.ctrlKey ? 'Ctrl+' : false, + ev.shiftKey ? 'Shift+' : false, + ev.altKey ? 'Alt+' : false, + ] + .filter(mod => mod) + .join(''); + keystrokeDiv.textContent = `${keyModifiers}'${ev.key}'`; + } + } /** * Add the recent dispatching of the given command with the given arguments. */ diff --git a/packages/plugin-dom-layout/src/DomLayout.ts b/packages/plugin-dom-layout/src/DomLayout.ts index 404d13472..e557c8a8b 100644 --- a/packages/plugin-dom-layout/src/DomLayout.ts +++ b/packages/plugin-dom-layout/src/DomLayout.ts @@ -15,7 +15,7 @@ import { ZoneXmlDomParser } from './ZoneXmlDomParser'; import { LayoutContainerDomObjectRenderer } from './LayoutContainerDomObjectRenderer'; import { ZoneIdentifier, ZoneNode } from '../../plugin-layout/src/ZoneNode'; import { Keymap } from '../../plugin-keymap/src/Keymap'; -import { CommandIdentifier } from '../../core/src/Dispatcher'; +import { CommandIdentifier, CommandParams } from '../../core/src/Dispatcher'; import { ActionableDomObjectRenderer } from './ActionableDomObjectRenderer'; import { ActionableGroupDomObjectRenderer } from './ActionableGroupDomObjectRenderer'; import { ActionableGroupSelectItemDomObjectRenderer } from './ActionableGroupSelectItemDomObjectRenderer'; @@ -33,6 +33,9 @@ export interface DomLayoutConfig extends JWPluginConfig { componentZones?: [ComponentId, ZoneIdentifier[]][]; pressedActionablesClassName?: string; } +export interface ProcessKeydownParams extends CommandParams { + event: KeyboardEvent; +} export class DomLayout extends JWPlugin { static dependencies = [DomObjectRenderer, Parser, Renderer, Layout, Keymap]; @@ -129,6 +132,9 @@ export class DomLayout extends JWPl event: KeyboardEvent, processingContext: ExecutionContext = this.editor, ): Promise { + await this.editor.dispatcher.dispatchHooks('@layout-keydown', { + event: event, + } as ProcessKeydownParams); if ( this.focusedNode && ['INPUT', 'SELECT', 'TEXTAREA'].includes(nodeName(this.focusedNode))