Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard input support for webplayer #269

Open
wants to merge 11 commits into
base: develop
Choose a base branch
from
3 changes: 3 additions & 0 deletions src/components/HelpOverlay.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ export default (props) => {
<li>
<kbd>Shift</kbd> + <kbd>←</kbd> / <kbd>→</kbd> - rewind / fast-forward by 10%
</li>
<li>
<kbd>k</kbd> - toggle keystroke popup
</li>
<li>
<kbd>[</kbd> / <kbd>]</kbd> - jump to the previous / next marker
</li>
Expand Down
182 changes: 182 additions & 0 deletions src/components/KeystrokesOverlay.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
import { createSignal } from "solid-js";

const [isFading, setisFading] = createSignal(false);

const basic_seqs = {
"\\r": "Ret",
"\\t": "Tab",
"\\u001b": "Esc",
"^?": "Back",
"\\u000b": "Beep",
"\\u0001": "C-a",
"\\u0002": "C-b",
"\\u0003": "C-c",
"\\u0004": "C-d",
"\\u0005": "C-e",
"\\u0006": "C-f",
"\\u0007": "C-g",
"\\u0008": "C-h",
"\\u0009": "C-i",
"\\u0010": "C-j",
"\\u0011": "C-k",
"\\u0012": "C-l",
"\\u0013": "C-m",
"\\u0014": "C-n",
"\\u0015": "C-o",
"\\u0016": "C-p",
"\\u0017": "C-q",
"\\u0018": "C-r",
"\\u0019": "C-s",
"\\u0020": "C-t",
"\\u0021": "C-u",
"\\u0022": "C-v",
"\\u0023": "C-w",
"\\u0024": "C-x",
"\\u0025": "C-y",
"\\u0026": "C-z",
};

const singles = {
" ": "Spc",
};

const unicode_seq = {
"[3~": "Supr",
"[C": "Right",
OC: "Right",
"[1;3C": "A-Right",
"[D": "Left",
OD: "Left",
"[1;3D": "A-Left",
"[A": "Up",
OA: "Up",
"[1;3A": "A-Up",
"[B": "Down",
OB: "Down",
"[1;3B": "A-Down",
"[H": "Home",
"[5~": "PgUp",
"[57421u": "PgUp",
"[57421;1:3u": "PgUp",
"[57362u": "PgUp",
"[57362;1:3u": "PgUp",
"[6~": "PgDn",
"[57422u": "PgDn",
"[57422;1:3u": "PgDn",
OP: "F1",
"[P": "F1",
"[1;1:3P": "F1",
OQ: "F2",
"[Q": "F2",
"[1;1:3Q": "F2",
OR: "F3",
"[R": "F3",
"[1;1:3R": "F3",
OS: "F4",
"[S": "F4",
"[1;1:3S": "F4",
"[15~": "F5",
"[15;1:3~": "F5",
"[17~": "F6",
"[17;1:3~": "F6",
"[18~": "F7",
"[18;1:3~": "F7",
"[19~": "F8",
"[19;1:3~": "F8",
"[20~": "F9",
"[20;1:3~": "F9",
"[21~": "F10",
"[21;1:3~": "F10",
"[23~": "F11",
"[23;1:3~": "F11",
"[24~": "F12",
"[24;1:3~": "F12",
"[97;;97u": "A-a",
"[98;;98u": "A-b",
"[99;;99u": "A-c",
"[100;;100u": "A-d",
"[101;;101u": "A-e",
"[102;;102u": "A-f",
"[103;;103u": "A-g",
"[104;;104u": "A-h",
"[105;;105u": "A-i",
"[106;;106u": "A-j",
"[107;;107u": "A-k",
"[108;;108u": "A-l",
"[109;;109u": "A-m",
"[110;;110u": "A-n",
"[111;;111u": "A-o",
"[112;;112u": "A-p",
"[113;;113u": "A-q",
"[114;;114u": "A-r",
"[115;;115u": "A-s",
"[116;;116u": "A-t",
"[117;;117u": "A-u",
"[118;;118u": "A-v",
"[119;;119u": "A-w",
"[120;;120u": "A-x",
"[121;;121u": "A-y",
"[122;;122u": "A-z",
"[27u": "Esc",
};

function formatKeyCode(data, logger) {
let rep = JSON.stringify(data).slice(1, -1);
if (rep.length === 1) {
if (rep in singles) {
return singles[rep];
}
return rep;
}

if (rep in basic_seqs) {
return basic_seqs[rep];
}
if (rep.length < 6) {
logger.info("Short <" + rep + ">", rep.length);
return "";
}
rep = rep.slice(6);
if (rep.length === 1) {
if (rep in singles) {
return "A-" + singles[rep];
}
return "A-" + rep;
}
if (rep in unicode_seq) return unicode_seq[rep];

if (rep.slice.length < 10) logger.info("<" + rep + ">", rep.length);

return "";
}

export default (props) => {
function showKeyPress(data) {
if (data === null) {
props.hideKeyStroke();
return "";
}
var pressed_key = formatKeyCode(data.value, props.logger);

if (pressed_key === "") {
props.hideKeyStroke();
return "";
}
setisFading(false);
setTimeout(function () {
setisFading(true);
}, 20);
return pressed_key;
}
return (
<div
class={
isFading() ? "ap-overlay ap-overlay-keystrokes fading" : "ap-overlay ap-overlay-keystrokes"
}
>
<div>
<kbd>{showKeyPress(props.keystroke)}</kbd>
</div>
</div>
);
};
57 changes: 47 additions & 10 deletions src/components/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import LoaderOverlay from "./LoaderOverlay";
import InfoOverlay from "./InfoOverlay";
import StartOverlay from "./StartOverlay";
import HelpOverlay from "./HelpOverlay";
import KeystrokesOverlay from "./KeystrokesOverlay";

const CONTROL_BAR_HEIGHT = 32; // must match height of div.ap-control-bar in CSS

Expand All @@ -33,6 +34,7 @@ export default (props) => {
progress: null,
blink: true,
cursorHold: false,
hideKeystroke: props.hideKeystroke,
});

const [isPlaying, setIsPlaying] = createSignal(false);
Expand All @@ -52,7 +54,8 @@ export default (props) => {
const terminalCols = createMemo(() => terminalSize().cols || 80);
const terminalRows = createMemo(() => terminalSize().rows || 24);
const controlBarHeight = () => (props.controls === false ? 0 : CONTROL_BAR_HEIGHT);

const [isKeystrokeVisible, setisKeystrokeVisible] = createSignal(false);
const [keyStroke, setKeyStroke] = createSignal(null);
const controlsVisible = () =>
props.controls === true || (props.controls === "auto" && userActive());

Expand Down Expand Up @@ -97,18 +100,23 @@ export default (props) => {
}
}

core.addEventListener("init", ({ cols, rows, duration, theme, poster, markers }) => {
batch(() => {
resize({ cols, rows });
setDuration(duration);
setOriginalTheme(theme);
setMarkers(markers);
setPoster(poster);
});
});
core.addEventListener(
"init",
({ cols, rows, duration, theme, poster, markers, hideKeystroke }) => {
batch(() => {
resize({ cols, rows });
setDuration(duration);
setOriginalTheme(theme);
setMarkers(markers);
setPoster(poster);
setisKeystrokeVisible(!hideKeystroke);
});
},
);

core.addEventListener("play", () => {
setOverlay(null);
setisKeystrokeVisible(false);
});

core.addEventListener("playing", () => {
Expand All @@ -131,6 +139,7 @@ export default (props) => {
setIsPlaying(false);
onStopped();
setOverlay("loader");
setisKeystrokeVisible(false);
});
});

Expand All @@ -150,6 +159,7 @@ export default (props) => {
batch(() => {
setIsPlaying(false);
onStopped();
setisKeystrokeVisible(false);

if (message !== undefined) {
setInfoMessage(message);
Expand All @@ -162,6 +172,14 @@ export default (props) => {
setOverlay("error");
});

core.addEventListener("input", ({ data }) => {
if (state.hideKeystroke) {
return;
}
setisKeystrokeVisible(true);
setKeyStroke({ ms: Date.now(), value: data });
});

core.addEventListener("resize", resize);

core.addEventListener("reset", ({ cols, rows, theme }) => {
Expand All @@ -174,6 +192,7 @@ export default (props) => {

core.addEventListener("seeked", () => {
updateTime();
setisKeystrokeVisible(false);
});

core.addEventListener("terminalUpdate", () => {
Expand Down Expand Up @@ -226,6 +245,9 @@ export default (props) => {
resizeObserver.disconnect();
});

const hideKeyStroke = () => {
setisKeystrokeVisible(false);
};
const updateTerminal = () => {
const changedLines = core.getChangedLines();

Expand Down Expand Up @@ -323,6 +345,13 @@ export default (props) => {
core.pause();
setIsHelpVisible(true);
}
} else if (e.key == "k") {
if (state.hideKeystroke) {
setState("hideKeystroke", false);
} else {
setisKeystrokeVisible(false);
setState("hideKeystroke", true);
}
} else if (e.key == "ArrowLeft") {
if (e.shiftKey) {
core.seek("<<<");
Expand Down Expand Up @@ -500,6 +529,14 @@ export default (props) => {
ref={controlBarRef}
/>
</Show>
<Show when={isKeystrokeVisible()}>
<KeystrokesOverlay
fontFamily={props.terminalFontFamily}
keystroke={keyStroke()}
hideKeyStroke={hideKeyStroke}
logger={props.logger}
/>
</Show>
<Switch>
<Match when={overlay() == "start"}>
<StartOverlay onClick={() => core.play()} />
Expand Down
1 change: 1 addition & 0 deletions src/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ class Core {
this.markers = this.normalizeMarkers(opts.markers);
this.pauseOnMarkers = opts.pauseOnMarkers;
this.commandQueue = Promise.resolve();
this.hideKeystroke = opts.hideKeystroke ?? false;

this.eventHandlers = new Map([
["ended", []],
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ function create(src, elem, opts = {}) {
markers: opts.markers,
pauseOnMarkers: opts.pauseOnMarkers,
idleTimeLimit: opts.idleTimeLimit,
hideKeystroke: opts.hideKeystroke,
});

const metrics = measureTerminal(opts.terminalFontFamily, opts.terminalLineHeight);
Expand All @@ -59,6 +60,7 @@ function create(src, elem, opts = {}) {
terminalFontFamily: opts.terminalFontFamily,
terminalLineHeight: opts.terminalLineHeight,
theme: opts.theme,
hideKeystroke: opts.hideKeystroke ?? false,
...metrics,
};

Expand Down
Loading