Skip to content
This repository was archived by the owner on May 5, 2021. It is now read-only.

Commit a2d2d1d

Browse files
committed
[ADD] DevTools: tools to display the keystrokes for bug reporting
1 parent a975be9 commit a2d2d1d

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

packages/plugin-devtools/assets/DevTools.css

+22
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,25 @@ devtools-info devtools-about devtools-id {
360360
color: #76526c;
361361
font-size: smaller;
362362
}
363+
364+
/* Keystrokes display */
365+
#keys_log {
366+
opacity: 0;
367+
padding: 5px;
368+
z-index: 100000;
369+
margin: 25px;
370+
position: fixed;
371+
top: 0px;
372+
background-color: #875A7B;
373+
color: white;
374+
font-size: 25px;
375+
border: 1px solid #68465f;
376+
border-radius: 10px;
377+
-webkit-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42);
378+
-moz-box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42);
379+
box-shadow: 2px 2px 5px 0px rgba(0,0,0,0.42);
380+
}
381+
#keys_log.has-key {
382+
transition: opacity .5s;
383+
opacity: 1;
384+
}

packages/plugin-devtools/assets/DevTools.xml

+3
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@
495495
selected: state.currentTab == 'modes',
496496
}">Modes</devtools-button>
497497
<devtools-button t-on-click="inspectDom()">&#128269;</devtools-button>
498+
<devtools-button t-on-click="toggleKeystrokes()" t-att-class="{
499+
selected: state.displayKeystrokes,
500+
}" title="Log keystrokes" style="position: absolute; right: 0;">🅺</devtools-button>
498501
</devtools-navbar>
499502
<t t-if="!state.closed">
500503
<InspectorComponent isOpen="state.currentTab == 'inspector'" t-ref="inspector"/>

packages/plugin-devtools/src/components/DevToolsComponent.ts

+60-2
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@ import { OwlComponent } from '../../../plugin-owl/src/OwlComponent';
77
import { CommandIdentifier, CommandParams } from '../../../core/src/Dispatcher';
88
import { nodeName } from '../../../utils/src/utils';
99
import { hooks } from '@odoo/owl';
10+
import { ProcessKeydownParams } from '../../../plugin-dom-layout/src/DomLayout';
1011

11-
////////////////////////////// todo: use API ///////////////////////////////////
12+
const keystrokeDiv = document.createElement('div');
13+
keystrokeDiv.id = 'keys_log';
1214

1315
interface DevToolsState {
1416
closed: boolean; // Are the devtools open?
1517
height: number; // In px
1618
currentTab: string; // Name of the current tab
1719
commands: Array<[CommandIdentifier, CommandParams]>;
20+
displayKeystrokes: boolean;
1821
}
1922

2023
export class DevToolsComponent<T = {}> extends OwlComponent<T> {
@@ -33,18 +36,34 @@ export class DevToolsComponent<T = {}> extends OwlComponent<T> {
3336
currentTab: 'inspector',
3437
height: 300,
3538
commands: [], // Stack of all commands executed since init.
39+
displayKeystrokes: false,
3640
};
37-
localStorage = ['closed', 'currentTab', 'height'];
41+
localStorage = ['closed', 'currentTab', 'height', 'displayKeystrokes'];
3842
// For resizing/opening (see toggleClosed)
3943
_heightOnLastMousedown: number;
4044

4145
async willStart(): Promise<void> {
4246
this.env.editor.dispatcher.registerCommandHook('*', this.addCommand.bind(this));
4347
this.env.editor.dispatcher.registerCommandHook('@commit', this.render.bind(this));
48+
this.env.editor.dispatcher.registerCommandHook(
49+
'@layout-keydown',
50+
this.displayKeystroke.bind(this),
51+
);
4452
return super.willStart();
4553
}
54+
async mounted(): Promise<void> {
55+
if (this.state.displayKeystrokes) {
56+
if (!document.getElementById('keys_log')) {
57+
document.body.appendChild(keystrokeDiv);
58+
}
59+
}
60+
return super.mounted();
61+
}
4662
willUnmount(): void {
4763
this.state.commands = [];
64+
if (this.state.displayKeystrokes && keystrokeDiv.parentNode === document.body) {
65+
document.body.removeChild(keystrokeDiv);
66+
}
4867
}
4968

5069
//--------------------------------------------------------------------------
@@ -69,6 +88,45 @@ export class DevToolsComponent<T = {}> extends OwlComponent<T> {
6988
this.state.currentTab = 'inspector';
7089
(this.inspectorRef.comp as InspectorComponent)?.inspectDom();
7190
}
91+
/**
92+
* Toggle display keystrokes.
93+
*/
94+
toggleKeystrokes(): void {
95+
this.state.displayKeystrokes = !this.state.displayKeystrokes;
96+
if (this.state.displayKeystrokes) {
97+
if (!document.getElementById('keys_log')) {
98+
document.body.appendChild(keystrokeDiv);
99+
}
100+
} else if (keystrokeDiv.parentNode === document.body) {
101+
document.body.removeChild(keystrokeDiv);
102+
}
103+
}
104+
/**
105+
* Display the key hit on the screen.
106+
*
107+
* @param params
108+
*/
109+
displayKeystroke(params: ProcessKeydownParams): void {
110+
if (!this.state.displayKeystrokes) return;
111+
const ev = params.event;
112+
keystrokeDiv.textContent = '';
113+
keystrokeDiv.className = '';
114+
if (['Control', 'Alt', 'Shift', 'Meta'].includes(ev.key)) {
115+
keystrokeDiv.className = 'has-key';
116+
keystrokeDiv.textContent = `'${ev.key}'`;
117+
} else if (ev.key) {
118+
keystrokeDiv.className = 'has-key';
119+
const keyModifiers = [
120+
ev.metaKey ? 'Meta+' : false,
121+
ev.ctrlKey ? 'Ctrl+' : false,
122+
ev.shiftKey ? 'Shift+' : false,
123+
ev.altKey ? 'Alt+' : false,
124+
]
125+
.filter(mod => mod)
126+
.join('');
127+
keystrokeDiv.textContent = `${keyModifiers}'${ev.key}'`;
128+
}
129+
}
72130
/**
73131
* Add the recent dispatching of the given command with the given arguments.
74132
*/

packages/plugin-dom-layout/src/DomLayout.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ZoneXmlDomParser } from './ZoneXmlDomParser';
1515
import { LayoutContainerDomObjectRenderer } from './LayoutContainerDomObjectRenderer';
1616
import { ZoneIdentifier, ZoneNode } from '../../plugin-layout/src/ZoneNode';
1717
import { Keymap } from '../../plugin-keymap/src/Keymap';
18-
import { CommandIdentifier } from '../../core/src/Dispatcher';
18+
import { CommandIdentifier, CommandParams } from '../../core/src/Dispatcher';
1919
import { ActionableDomObjectRenderer } from './ActionableDomObjectRenderer';
2020
import { ActionableGroupDomObjectRenderer } from './ActionableGroupDomObjectRenderer';
2121
import { ActionableGroupSelectItemDomObjectRenderer } from './ActionableGroupSelectItemDomObjectRenderer';
@@ -33,6 +33,9 @@ export interface DomLayoutConfig extends JWPluginConfig {
3333
componentZones?: [ComponentId, ZoneIdentifier[]][];
3434
pressedActionablesClassName?: string;
3535
}
36+
export interface ProcessKeydownParams extends CommandParams {
37+
event: KeyboardEvent;
38+
}
3639

3740
export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPlugin<T> {
3841
static dependencies = [DomObjectRenderer, Parser, Renderer, Layout, Keymap];
@@ -129,6 +132,9 @@ export class DomLayout<T extends DomLayoutConfig = DomLayoutConfig> extends JWPl
129132
event: KeyboardEvent,
130133
processingContext: ExecutionContext = this.editor,
131134
): Promise<CommandIdentifier> {
135+
await this.editor.dispatcher.dispatchHooks('@layout-keydown', {
136+
event: event,
137+
} as ProcessKeydownParams);
132138
if (
133139
this.focusedNode &&
134140
['INPUT', 'SELECT', 'TEXTAREA'].includes(nodeName(this.focusedNode))

0 commit comments

Comments
 (0)