Skip to content

Commit b523714

Browse files
authored
fix: improve keyboard shortcuts (and non working help dialog) (#413)
1 parent eae376e commit b523714

12 files changed

Lines changed: 105 additions & 69 deletions

File tree

internal/frontend/lobby.js

Lines changed: 56 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
import KeyboardManager from "./resources/keyboardManager.js"
2+
13
String.prototype.format = function () {
24
return [...arguments].reduce((p, c) => p.replace(/%s/, c), this);
35
};
46

57
const discordInstanceId = getCookie("discord-instance-id");
68
const rootPath = `${discordInstanceId ? ".proxy/" : ""}{{.RootPath}}`;
9+
const keyboardManager = new KeyboardManager();
710

811
let socketIsConnecting = false;
912
let hasSocketEverConnected = false;
@@ -151,7 +154,7 @@ function createDialogButton(text) {
151154
function createDialogButtonBar(...buttons) {
152155
const buttonBar = document.createElement("div");
153156
buttonBar.classList.add("button-bar");
154-
buttons.forEach(buttonBar.appendChild);
157+
buttons.forEach((button) => buttonBar.appendChild(button));
155158
return buttonBar;
156159
}
157160

@@ -171,18 +174,17 @@ function showHelpDialog() {
171174
const controlsLabel = document.createElement("b");
172175
controlsLabel.innerText = '{{.Translation.Get "controls"}}';
173176

174-
const controlsTextOne = document.createElement("p");
175-
controlsTextOne.innerText = '{{.Translation.Get "switch-tools-intro"}}:';
176-
177-
const controlsTextTwo = document.createElement("p");
178-
controlsTextTwo.innerHTML =
179-
'{{.Translation.Get "pencil"}}: <kbd>Q</kbd><br/>' +
180-
'{{.Translation.Get "fill-bucket"}}: <kbd>W</kbd><br/>' +
181-
'{{.Translation.Get "eraser"}}: <kbd>E</kbd><br/>';
182-
183-
const controlsTextThree = document.createElement("p");
184-
controlsTextThree.innerHTML =
185-
'{{printf (.Translation.Get "switch-pencil-sizes") "<kbd>1</kbd>" "<kbd>4</kbd>"}}';
177+
const undoModifierKeysString = keyboardManager.get("undoModifier").split("+").map(k => `<kbd>${k}</kbd>`).join("+");
178+
const controlsText = document.createElement("div");
179+
controlsText.classList.add("help-controls-grid");
180+
controlsText.innerHTML =
181+
`
182+
<span>{{.Translation.Get "pencil"}}</span><span dir="ltr"><kbd>${keyboardManager.get("pen")}</kbd></span>
183+
<span>{{.Translation.Get "fill-bucket"}}</span><span dir="ltr"><kbd>${keyboardManager.get("bucket")}</kbd></span>
184+
<span>{{.Translation.Get "eraser"}}</span><span dir="ltr"><kbd>${keyboardManager.get("rubber")}</kbd></span>
185+
<span>{{.Translation.Get "undo-help-message"}}</span><span dir="ltr">${undoModifierKeysString}+<kbd>${keyboardManager.get("undo")}</kbd></span>
186+
<span>{{.Translation.Get "switch-pencil-sizes"}}</span><span dir="ltr"><kbd>${keyboardManager.get("size8")}</kbd>-<kbd>${keyboardManager.get("size32")}</kbd></span>
187+
`;
186188

187189
const closeButton = createDialogButton('{{.Translation.Get "close"}}');
188190
closeButton.addEventListener("click", () => {
@@ -197,9 +199,7 @@ function showHelpDialog() {
197199

198200
const dialogContent = document.createElement("div");
199201
dialogContent.appendChild(controlsLabel);
200-
dialogContent.appendChild(controlsTextOne);
201-
dialogContent.appendChild(controlsTextTwo);
202-
dialogContent.appendChild(controlsTextThree);
202+
dialogContent.appendChild(controlsText);
203203
dialogContent.appendChild(footer);
204204

205205
showDialog(
@@ -452,6 +452,22 @@ const toolButtonPen = document.getElementById("tool-type-pencil");
452452
const toolButtonRubber = document.getElementById("tool-type-rubber");
453453
const toolButtonFill = document.getElementById("tool-type-fill");
454454

455+
const pencilImage = document.getElementById("use-pencil-button-image");
456+
const eraserImage = document.getElementById("use-eraser-button-image");
457+
const bucketImage = document.getElementById("use-fill-bucket-button-image");
458+
const undoImage = document.getElementById("undo-button-image");
459+
const size8buttonWrapper = document.getElementById("size-8-button-wrapper");
460+
const size16buttonWrapper = document.getElementById("size-16-button-wrapper");
461+
const size24buttonWrapper = document.getElementById("size-24-button-wrapper");
462+
const size32buttonWrapper = document.getElementById("size-32-button-wrapper");
463+
464+
465+
pencilImage.setAttribute("title", `${pencilImage.getAttribute("title")} (${keyboardManager.get("pencil")})`);
466+
eraserImage.setAttribute("title", `${eraserImage.getAttribute("title")} (${keyboardManager.get("rubber")})`);
467+
bucketImage.setAttribute("title", `${bucketImage.getAttribute("title")} (${keyboardManager.get("bucket")})`);
468+
undoImage.setAttribute("title", `${undoImage.getAttribute("title")} (${keyboardManager.get("undoModifier")}+${keyboardManager.get("undo")})`);
469+
470+
455471
if (sizeButton8.checked) {
456472
setLineWidthNoUpdate(8);
457473
} else if (sizeButton16.checked) {
@@ -516,34 +532,19 @@ function setLineWidth(value) {
516532
setLineWidthNoUpdate(value);
517533
updateDrawingStateUI();
518534
}
535+
519536
sizeButton8.addEventListener("change", () => setLineWidth(8));
520-
document
521-
.getElementById("size-8-button-wrapper")
522-
.addEventListener("mouseup", sizeButton8.click);
523-
document
524-
.getElementById("size-8-button-wrapper")
525-
.addEventListener("mousedown", sizeButton8.click);
537+
size8buttonWrapper.addEventListener("mouseup", sizeButton8.click);
538+
size8buttonWrapper.addEventListener("mousedown", sizeButton8.click);
526539
sizeButton16.addEventListener("change", () => setLineWidth(16));
527-
document
528-
.getElementById("size-16-button-wrapper")
529-
.addEventListener("mouseup", sizeButton16.click);
530-
document
531-
.getElementById("size-16-button-wrapper")
532-
.addEventListener("mousedown", sizeButton16.click);
540+
size16buttonWrapper.addEventListener("mouseup", sizeButton16.click);
541+
size16buttonWrapper.addEventListener("mousedown", sizeButton16.click);
533542
sizeButton24.addEventListener("change", () => setLineWidth(24));
534-
document
535-
.getElementById("size-24-button-wrapper")
536-
.addEventListener("mouseup", sizeButton24.click);
537-
document
538-
.getElementById("size-24-button-wrapper")
539-
.addEventListener("mousedown", sizeButton24.click);
543+
size24buttonWrapper.addEventListener("mouseup", sizeButton24.click);
544+
size24buttonWrapper.addEventListener("mousedown", sizeButton24.click);
540545
sizeButton32.addEventListener("change", () => setLineWidth(32));
541-
document
542-
.getElementById("size-32-button-wrapper")
543-
.addEventListener("mouseup", sizeButton32.click);
544-
document
545-
.getElementById("size-32-button-wrapper")
546-
.addEventListener("mousedown", sizeButton32.click);
546+
size32buttonWrapper.addEventListener("mouseup", sizeButton32.click);
547+
size32buttonWrapper.addEventListener("mousedown", sizeButton32.click);
547548

548549
function setLineWidthNoUpdate(value) {
549550
localLineWidth = value;
@@ -1890,6 +1891,13 @@ function isAnyDialogVisible() {
18901891
return false;
18911892
}
18921893

1894+
function getModifierKey(event, modifierKey) {
1895+
// Split by "+" and ensure every specified modifier property is true on the event.
1896+
// e.g. "ctrl+shift" checks event.ctrlKey AND event.shiftKey
1897+
return modifierKey.split("+").every(modifier => event[`${modifier}Key`]);
1898+
}
1899+
1900+
18931901
function onKeyDown(event) {
18941902
//Avoid firing actions if the user is in the chat.
18951903
if (document.activeElement instanceof HTMLInputElement) {
@@ -1907,28 +1915,28 @@ function onKeyDown(event) {
19071915
//find it better than having to find specific keys on your
19081916
//keyboard. Especially for people that aren't used to typing
19091917
//without looking at their keyboard, this might help.
1910-
if (event.key === "q") {
1918+
if (event.key === keyboardManager.get("pen")) {
19111919
toolButtonPen.click();
19121920
chooseTool(pen);
1913-
} else if (event.key === "w") {
1921+
} else if (event.key === keyboardManager.get("bucket")) {
19141922
toolButtonFill.click();
19151923
chooseTool(fillBucket);
1916-
} else if (event.key === "e") {
1924+
} else if (event.key === keyboardManager.get("rubber")){
19171925
toolButtonRubber.click();
19181926
chooseTool(rubber);
1919-
} else if (event.key === "1") {
1927+
} else if (event.key === keyboardManager.get("size8")) {
19201928
sizeButton8.click();
19211929
setLineWidth(8);
1922-
} else if (event.key === "2") {
1930+
} else if (event.key === keyboardManager.get("size16")) {
19231931
sizeButton16.click();
19241932
setLineWidth(16);
1925-
} else if (event.key === "3") {
1933+
} else if (event.key === keyboardManager.get("size24")) {
19261934
sizeButton24.click();
19271935
setLineWidth(24);
1928-
} else if (event.key === "4") {
1936+
} else if (event.key === keyboardManager.get("size32")) {
19291937
sizeButton32.click();
19301938
setLineWidth(32);
1931-
} else if (event.key === "z" && event.ctrlKey) {
1939+
} else if (getModifierKey(event, keyboardManager.get("undoModifier")) && event.key.toLowerCase() === keyboardManager.get("undo")) {
19321940
undoAndSendEvent();
19331941
}
19341942
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class KeyboardManager {
2+
constructor() {
3+
this.keys = {
4+
bucket: "w",
5+
pen: "q",
6+
rubber: "e",
7+
size8: "1",
8+
size16: "2",
9+
size24: "3",
10+
size32: "4",
11+
undo: "z",
12+
13+
// multiple modifiers should be separated by +, for example "ctrl+shift"
14+
undoModifier: "ctrl",
15+
}
16+
}
17+
18+
get(key) {
19+
return this.keys[key]
20+
}
21+
}
22+
23+
export default KeyboardManager;

internal/frontend/resources/lobby.css

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ kbd {
4747
display: inline-block;
4848
font-size: 0.85em;
4949
font-weight: 700;
50-
line-height: 1;
5150
vertical-align: middle;
5251
padding: 2px 4px;
5352
white-space: nowrap;
53+
width: fit-content;
5454
}
5555

5656
@media only screen and (max-width: 812px),
@@ -811,3 +811,14 @@ kbd {
811811
gap: 10px;
812812
font-size: 1rem !important;
813813
}
814+
815+
#help-dialog {
816+
width: 16%;
817+
}
818+
819+
.help-controls-grid {
820+
display: grid;
821+
grid-template-columns: max-content auto;
822+
gap: 0.25rem 1rem;
823+
margin-top: 0.5rem;
824+
}

internal/frontend/templates/lobby.html

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@
298298
<input id="tool-type-pencil" class="custom-check-or-radio line-width-button" type="radio"
299299
name="tool-type" checked>
300300
<div id="tool-type-pencil-wrapper" class="line-width-button-content">
301-
<img title="{{.Translation.Get "use-pencil"}}" alt="{{.Translation.Get "use-pencil"}}"
301+
<img id="use-pencil-button-image" title="{{.Translation.Get "use-pencil"}} " alt="{{.Translation.Get "use-pencil"}}"
302302
src='{{.RootPath}}/resources/{{.WithCacheBust "pencil.svg"}}'
303303
style="transform: scaleX(-1)" />
304304
</div>
@@ -307,16 +307,16 @@
307307
<input id="tool-type-fill" class="custom-check-or-radio line-width-button" type="radio"
308308
name="tool-type">
309309
<div id="tool-type-fill-wrapper" class="line-width-button-content">
310-
<img alt="{{.Translation.Get "use-fill-bucket"}}"
311-
title="{{.Translation.Get "use-fill-bucket"}}"
310+
<img id="use-fill-bucket-button-image" alt="{{.Translation.Get "use-fill-bucket"}}"
311+
title="{{.Translation.Get "use-fill-bucket"}} "
312312
src='{{.RootPath}}/resources/{{.WithCacheBust "fill.svg"}}' />
313313
</div>
314314
</label>
315315
<label for="tool-type-rubber">
316316
<input id="tool-type-rubber" class="custom-check-or-radio line-width-button" type="radio"
317317
name="tool-type">
318318
<div id="tool-type-rubber-wrapper" class="line-width-button-content">
319-
<img alt="{{.Translation.Get "use-eraser"}}" title="{{.Translation.Get "use-eraser"}}"
319+
<img id="use-eraser-button-image" alt="{{.Translation.Get "use-eraser"}}" title="{{.Translation.Get "use-eraser"}} "
320320
src='{{.RootPath}}/resources/{{.WithCacheBust "rubber.svg"}}' />
321321
</div>
322322
</label>
@@ -327,7 +327,7 @@
327327
name="line-width" checked>
328328
<div id="size-8-button-wrapper" class="line-width-button-content"
329329
alt="{{printf (.Translation.Get "change-pencil-size-to") "8"}}"
330-
title="{{printf (.Translation.Get "change-pencil-size-to") "8"}}">
330+
title="{{printf (.Translation.Get "change-pencil-size-to") "8"}} ">
331331
<div class="dot" style="width: 8px; height: 8px"></div>
332332
</div>
333333
</label>
@@ -336,7 +336,7 @@
336336
name="line-width">
337337
<div id="size-16-button-wrapper" class="line-width-button-content"
338338
alt="{{printf (.Translation.Get "change-pencil-size-to") "16"}}"
339-
title="{{printf (.Translation.Get "change-pencil-size-to") "16"}}">
339+
title="{{printf (.Translation.Get "change-pencil-size-to") "16"}} ">
340340
<div class="dot" style="width: 16px; height: 16px"></div>
341341
</div>
342342
</label>
@@ -345,7 +345,7 @@
345345
name="line-width">
346346
<div id="size-24-button-wrapper" class="line-width-button-content"
347347
alt="{{printf (.Translation.Get "change-pencil-size-to") "24"}}"
348-
title="{{printf (.Translation.Get "change-pencil-size-to") "24"}}">
348+
title="{{printf (.Translation.Get "change-pencil-size-to") "24"}} ">
349349
<div class="dot" style="width: 24px; height: 24px"></div>
350350
</div>
351351
</label>
@@ -354,7 +354,7 @@
354354
name="line-width">
355355
<div id="size-32-button-wrapper" class="line-width-button-content"
356356
alt="{{printf (.Translation.Get "change-pencil-size-to") "32"}}"
357-
title="{{printf (.Translation.Get "change-pencil-size-to") "32"}}">
357+
title="{{printf (.Translation.Get "change-pencil-size-to") "32"}} ">
358358
<div class="dot" style="width: 32px; height: 32px"></div>
359359
</div>
360360
</label>
@@ -368,7 +368,7 @@
368368
<!--We won't make this button easier to click, as there's no going back. -->
369369
<button id="undo-button" class="canvas-button toolbox-group" alt="{{.Translation.Get "undo"}}"
370370
title="{{.Translation.Get "undo"}}">
371-
<img alt="{{.Translation.Get "undo"}}" title="{{.Translation.Get "undo"}}"
371+
<img id="undo-button-image" alt="{{.Translation.Get "undo"}}" title="{{.Translation.Get "undo"}} "
372372
src='{{.RootPath}}/resources/{{.WithCacheBust "undo.svg"}}' />
373373
</button>
374374
</div>
@@ -382,7 +382,7 @@
382382
</div>
383383

384384
<script type="text/javascript" src='{{.RootPath}}/resources/{{.WithCacheBust "draw.js"}}'></script>
385-
<script type="text/javascript" src='{{.RootPath}}/{{.WithCacheBust "lobby.js"}}'></script>
385+
<script type="module" src='{{.RootPath}}/{{.WithCacheBust "lobby.js"}}'></script>
386386
</body>
387387

388388
</html>

internal/translations/ar.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ func initArabicTranslation() *Translation {
117117
translation.put("pencil", "القلم")
118118
translation.put("eraser", "الممحاة")
119119
translation.put("fill-bucket", "الملء بالدلو")
120-
translation.put("switch-tools-intro", "يمكنك التحويل بين الأدوات بواسطة الاختصارات")
121120
translation.put("switch-pencil-sizes", "يمكنك التغيير بين احجام القلم من %s إلى %s.")
122121

123122
// Generic words

internal/translations/de_DE.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ func initGermanTranslation() {
110110
translation.put("pencil", "Stift")
111111
translation.put("eraser", "Radiergummi")
112112
translation.put("fill-bucket", "Fülleimer")
113-
translation.put("switch-tools-intro", "Zwischen den Werkzeugen kannst du mit Tastaturkürzel wechseln")
114113
translation.put("switch-pencil-sizes", "Die Stiftgröße kannst du mit den Tasten %s bis %s verändern.")
115114

116115
// Generic words

internal/translations/en_us.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,8 @@ func initEnglishTranslation() *Translation {
128128
translation.put("pencil", "Pencil")
129129
translation.put("eraser", "Eraser")
130130
translation.put("fill-bucket", "Fill bucket")
131-
translation.put("switch-tools-intro", "You can switch between tools using shortcuts")
132-
translation.put("switch-pencil-sizes", "You can also switch between pencil sizes using keys %s to %s.")
131+
translation.put("switch-pencil-sizes", "Tool sizes")
132+
translation.put("undo-help-message", "Undo")
133133

134134
// Generic words
135135
// "close" as in "closing the window"

internal/translations/es_ES.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ func initSpainTranslation() {
116116
translation.put("pencil", "Lápiz")
117117
translation.put("eraser", "Borrador")
118118
translation.put("fill-bucket", "Llenar el cubo")
119-
translation.put("switch-tools-intro", "Puede cambiar entre herramientas mediante atajos")
120119
translation.put("switch-pencil-sizes", "También puedes cambiar entre tamaños de lápiz usando teclas %s para %s.")
121120

122121
// Generic words

internal/translations/fa.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ func initPersianTranslation() *Translation {
127127
translation.put("pencil", "قلم")
128128
translation.put("eraser", "پاک‌کن")
129129
translation.put("fill-bucket", "سطل رنگ")
130-
translation.put("switch-tools-intro", "شما می‌تونید ابزارها رو با استفاده از کلیدای میانبر عوض کنید")
131130
translation.put("switch-pencil-sizes", "همچنین می‌تونید اندازه قلم رو با کلیدای %s تا %s عوض کنید.")
132131

133132
// Generic words

internal/translations/fr_FR.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,6 @@ func initFrenchTranslation() *Translation {
128128
translation.put("pencil", "Crayon")
129129
translation.put("eraser", "Gomme")
130130
translation.put("fill-bucket", "Pot de peinture")
131-
translation.put("switch-tools-intro", "Vous pouvez changer d'outil à l'aide des raccourcis")
132131
translation.put("switch-pencil-sizes", "Vous pouvez aussi changer la taille du crayon avec les touches %s à %s.")
133132

134133
// Generic words

0 commit comments

Comments
 (0)