From b06824ebf3a90504ce15a72d46d897a77df02db1 Mon Sep 17 00:00:00 2001 From: hexxa Date: Fri, 11 Feb 2022 13:18:50 +0800 Subject: [PATCH] feat(fe/pane_login): login on enter keydown --- src/client/web/src/common/hotkeys.ts | 59 ++++++++++++++++++++ src/client/web/src/components/pane_login.tsx | 16 +++++- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 src/client/web/src/common/hotkeys.ts diff --git a/src/client/web/src/common/hotkeys.ts b/src/client/web/src/common/hotkeys.ts new file mode 100644 index 0000000..20a39a5 --- /dev/null +++ b/src/client/web/src/common/hotkeys.ts @@ -0,0 +1,59 @@ +import * as React from "react"; +import { Map } from "immutable"; + +export interface Hotkey { + key: string; + ctrl?: boolean; + shift?: boolean; + alt?: boolean; + meta?: boolean; + repeat?: boolean; + ev?: KeyboardEvent; +} + +export type HotkeyCb = (hotKey?: Hotkey) => void; + +export class HotkeyHandler { + private keyMap: Map; + + constructor() { + this.keyMap = Map(); + } + + getSign = (hk: Hotkey): string => { + let sign = hk.key; + sign = hk.ctrl != null && hk.ctrl ? `${sign}+ctrl` : sign; + sign = hk.shift != null && hk.shift ? `${sign}+shift` : sign; + sign = hk.alt != null && hk.alt ? `${sign}+alt` : sign; + sign = hk.meta != null && hk.meta ? `${sign}+meta` : sign; + sign = hk.repeat != null && hk.repeat ? `${sign}+repeat` : sign; + + return sign; + }; + + add = (hk: Hotkey, handler: HotkeyCb) => { + const sign = this.getSign(hk); + this.keyMap = this.keyMap.set(sign, handler); + }; + + handle = (ev: KeyboardEvent) => { + const hotKey = { + key: ev.key, + ctrl: ev.ctrlKey, + shift: ev.shiftKey, + alt: ev.altKey, + meta: ev.metaKey, + repeat: ev.repeat, + }; + const sign = this.getSign(hotKey); + + if (this.keyMap.has(sign)) { + const handler = this.keyMap.get(sign); + handler(hotKey); + } + }; + + printMap = () => { + console.log(this.keyMap.toMap()); + }; +} diff --git a/src/client/web/src/components/pane_login.tsx b/src/client/web/src/components/pane_login.tsx index 3157e98..729a2ba 100644 --- a/src/client/web/src/components/pane_login.tsx +++ b/src/client/web/src/components/pane_login.tsx @@ -1,5 +1,5 @@ import * as React from "react"; -import { List } from "immutable"; +import { List, Map } from "immutable"; import { ICoreState, MsgProps, UIProps } from "./core_state"; import { Flexbox } from "./layout/flexbox"; @@ -8,6 +8,7 @@ import { alertMsg } from "../common/env"; import { Quota, Preferences } from "../client"; import { getErrMsg } from "../common/utils"; import { ctrlOn, ctrlOff, loadingCtrl } from "../common/controls"; +import { HotkeyHandler } from "../common/hotkeys"; export interface ExtInfo { usedSpace: string; @@ -39,6 +40,8 @@ export interface State { export class AuthPane extends React.Component { private update: (updater: (prevState: ICoreState) => ICoreState) => void; + private hotkeyHandler: HotkeyHandler; + constructor(p: Props) { super(p); this.update = p.update; @@ -50,6 +53,17 @@ export class AuthPane extends React.Component { }; } + componentDidMount(): void { + this.hotkeyHandler = new HotkeyHandler(); + this.hotkeyHandler.add({ key: "Enter" }, this.login); + + document.addEventListener("keyup", this.hotkeyHandler.handle); + } + + componentWillUnmount() { + document.removeEventListener("keyup", this.hotkeyHandler.handle); + } + changeUser = (ev: React.ChangeEvent) => { this.setState({ user: ev.target.value }); };