From c3087abe02c3dca5af6a87eabf7096442e0dcb90 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 00:52:03 +0200 Subject: [PATCH 01/22] Enable multiple keyboard layouts for paste text from host --- config.go | 2 + jsonrpc.go | 14 ++ ui/src/components/popovers/PasteModal.tsx | 38 ++++- ui/src/hooks/stores.ts | 7 +- ui/src/keyboardLayouts.ts | 12 ++ ui/src/keyboardLayouts/de_CH.ts | 140 ++++++++++++++++++ ui/src/keyboardLayouts/en_US.ts | 102 +++++++++++++ ui/src/keyboardMappings.ts | 105 +------------ ui/src/main.tsx | 15 +- .../routes/devices.$id.settings.keyboard.tsx | 77 ++++++++++ ui/src/routes/devices.$id.settings.mouse.tsx | 2 +- ui/src/routes/devices.$id.settings.tsx | 14 +- 12 files changed, 413 insertions(+), 115 deletions(-) create mode 100644 ui/src/keyboardLayouts.ts create mode 100644 ui/src/keyboardLayouts/de_CH.ts create mode 100644 ui/src/keyboardLayouts/en_US.ts create mode 100644 ui/src/routes/devices.$id.settings.keyboard.tsx diff --git a/config.go b/config.go index 23d4c84..f8daef5 100644 --- a/config.go +++ b/config.go @@ -87,6 +87,7 @@ type Config struct { LocalAuthMode string `json:"localAuthMode"` //TODO: fix it with migration WakeOnLanDevices []WakeOnLanDevice `json:"wake_on_lan_devices"` KeyboardMacros []KeyboardMacro `json:"keyboard_macros"` + KeyboardLayout string `json:"keyboard_layout"` EdidString string `json:"hdmi_edid_string"` ActiveExtension string `json:"active_extension"` DisplayMaxBrightness int `json:"display_max_brightness"` @@ -107,6 +108,7 @@ var defaultConfig = &Config{ AutoUpdateEnabled: true, // Set a default value ActiveExtension: "", KeyboardMacros: []KeyboardMacro{}, + KeyboardLayout: "en-US", DisplayMaxBrightness: 64, DisplayDimAfterSec: 120, // 2 minutes DisplayOffAfterSec: 1800, // 30 minutes diff --git a/jsonrpc.go b/jsonrpc.go index d35f635..13280d9 100644 --- a/jsonrpc.go +++ b/jsonrpc.go @@ -863,6 +863,18 @@ func rpcSetScrollSensitivity(sensitivity string) error { return nil } +func rpcGetKeyboardLayout() (string, error) { + return config.KeyboardLayout, nil +} + +func rpcSetKeyboardLayout(layout string) error { + config.KeyboardLayout = layout + if err := SaveConfig(); err != nil { + return fmt.Errorf("failed to save config: %w", err) + } + return nil +} + func getKeyboardMacros() (interface{}, error) { macros := make([]KeyboardMacro, len(config.KeyboardMacros)) copy(macros, config.KeyboardMacros) @@ -1028,6 +1040,8 @@ var rpcHandlers = map[string]RPCHandler{ "setCloudUrl": {Func: rpcSetCloudUrl, Params: []string{"apiUrl", "appUrl"}}, "getScrollSensitivity": {Func: rpcGetScrollSensitivity}, "setScrollSensitivity": {Func: rpcSetScrollSensitivity, Params: []string{"sensitivity"}}, + "getKeyboardLayout": {Func: rpcGetKeyboardLayout}, + "setKeyboardLayout": {Func: rpcSetKeyboardLayout, Params: []string{"layout"}}, "getKeyboardMacros": {Func: getKeyboardMacros}, "setKeyboardMacros": {Func: setKeyboardMacros, Params: []string{"params"}}, } diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index 643f55b..9e3d9ee 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -8,8 +8,9 @@ import { GridCard } from "@components/Card"; import { TextAreaWithLabel } from "@components/TextArea"; import { SettingsPageHeader } from "@components/SettingsPageheader"; import { useJsonRpc } from "@/hooks/useJsonRpc"; -import { useHidStore, useRTCStore, useUiStore } from "@/hooks/stores"; -import { chars, keys, modifiers } from "@/keyboardMappings"; +import { useHidStore, useRTCStore, useUiStore, useDeviceSettingsStore } from "@/hooks/stores"; +import { keys, modifiers } from "@/keyboardMappings"; +import { layouts, chars } from "@/keyboardLayouts"; import notifications from "@/notifications"; const hidKeyboardPayload = (keys: number[], modifier: number) => { @@ -27,6 +28,11 @@ export default function PasteModal() { const [invalidChars, setInvalidChars] = useState([]); const close = useClose(); + const keyboardLayout = useDeviceSettingsStore(state => state.keyboardLayout); + const setKeyboardLayout = useDeviceSettingsStore( + state => state.setKeyboardLayout, + ); + const onCancelPasteMode = useCallback(() => { setPasteMode(false); setDisableVideoFocusTrap(false); @@ -42,13 +48,25 @@ export default function PasteModal() { try { for (const char of text) { - const { key, shift } = chars[char] ?? {}; + const { key, shift, altRight, space, capsLock } = chars[keyboardLayout][char] ?? {}; if (!key) continue; + const keyz = [keys[key]]; + if (space) { + keyz.push(keys["Space"]); + } + if (capsLock) { + keyz.unshift(keys["CapsLock"]); + keyz.push(keys["CapsLock"]); + } + + const modz = shift ? modifiers["ShiftLeft"] : 0 + | (altRight ? modifiers["AltRight"] : 0); + await new Promise((resolve, reject) => { send( "keyboardReport", - hidKeyboardPayload([keys[key]], shift ? modifiers["ShiftLeft"] : 0), + hidKeyboardPayload(keyz, modz), params => { if ("error" in params) return reject(params.error); send("keyboardReport", hidKeyboardPayload([], 0), params => { @@ -69,6 +87,11 @@ export default function PasteModal() { if (TextAreaRef.current) { TextAreaRef.current.focus(); } + + send("getKeyboardLayout", {}, resp => { + if ("error" in resp) return; + setKeyboardLayout(resp.result as string); + }); }, []); return ( @@ -113,7 +136,7 @@ export default function PasteModal() { // @ts-expect-error TS doesn't recognize Intl.Segmenter in some environments [...new Intl.Segmenter().segment(value)] .map(x => x.segment) - .filter(char => !chars[char]), + .filter(char => !chars[keyboardLayout][char]), ), ]; @@ -132,6 +155,11 @@ export default function PasteModal() { )} +
+

+ Sending key codes for keyboard layout {layouts[keyboardLayout]} +

+
diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index db1fd04..dc97ccf 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -336,6 +336,8 @@ export interface DeviceSettingsState { trackpadThreshold: number; scrollSensitivity: "low" | "default" | "high"; setScrollSensitivity: (sensitivity: DeviceSettingsState["scrollSensitivity"]) => void; + keyboardLayout: string; + setKeyboardLayout: (layout: string) => void; } export const useDeviceSettingsStore = create(set => ({ @@ -397,6 +399,9 @@ export const useDeviceSettingsStore = create(set => ({ scrollSensitivity: sensitivity, }); }, + + keyboardLayout: "en-US", + setKeyboardLayout: layout => set({ keyboardLayout: layout }), })); export interface RemoteVirtualMediaState { @@ -893,4 +898,4 @@ export const useMacrosStore = create((set, get) => ({ set({ loading: false }); } } -})); \ No newline at end of file +})); diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts new file mode 100644 index 0000000..15c3be4 --- /dev/null +++ b/ui/src/keyboardLayouts.ts @@ -0,0 +1,12 @@ +import { chars as chars_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" + +export const layouts = { + "en_US": "English (US)", + "de_CH": "Swiss German" +} as Record; + +export const chars = { + "en_US": chars_en_US, + "de_CH": chars_de_CH, +} as Record>; diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts new file mode 100644 index 0000000..405feb8 --- /dev/null +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -0,0 +1,140 @@ +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "æ": { key: "KeyA", altRight: true }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + "ð": { key: "KeyD", altRight: true }, + e: { key: "KeyE" }, + f: { key: "KeyF" }, + "đ": { key: "KeyF", altRight: true }, + g: { key: "KeyG" }, + "ŋ": { key: "KeyG", altRight: true }, + h: { key: "KeyH" }, + "ħ": { key: "KeyH", altRight: true }, + i: { key: "KeyI" }, + "→": { key: "KeyI", altRight: true }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + "ĸ": { key: "KeyK", altRight: true }, + l: { key: "KeyL" }, + "ł": { key: "KeyL", altRight: true }, + m: { key: "KeyM" }, + "µ": { key: "KeyM", altRight: true }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "œ": { key: "KeyO", altRight: true }, + p: { key: "KeyP" }, + "þ": { key: "KeyP", altRight: true }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + "¶": { key: "KeyR", altRight: true }, + s: { key: "KeyS" }, + "ß": { key: "KeyS", altRight: true }, + t: { key: "KeyT" }, + "ŧ": { key: "KeyT", altRight: true }, + u: { key: "KeyU" }, + "↓": { key: "KeyU", altRight: true }, + v: { key: "KeyV" }, + "„": { key: "KeyV", altRight: true }, + w: { key: "KeyW" }, + "ſ": { key: "KeyW", altRight: true }, + x: { key: "KeyX" }, + "»": { key: "KeyX", altRight: true }, + y: { key: "KeyZ" }, + "←": { key: "KeyZ", altRight: true }, + z: { key: "KeyY" }, + "«": { key: "KeyY", altRight: true }, + "§": { key: "Backquote" }, + "°": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "+": { key: "Digit1", shift: true }, + "|": { key: "Digit1", altRight: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "*": { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "ç": { key: "Digit4", shift: true }, + "¼": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + "½": { key: "Digit5", altRight: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + "¬": { key: "Digit6", altRight: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "¢": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "^": { key: "Equal", space: true }, // dead key + "`": { key: "Equal", shift: true }, + "~": { key: "Equal", altRight: true, space: true }, // dead key + "ü": { key: "BracketLeft" }, + "è": { key: "BracketLeft", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "Ü": { key: "BracketLeft", capsLock: true }, + "!": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "ö": { key: "Semicolon" }, + "é": { key: "Semicolon", shift: true }, + "Ö": { key: "Semicolon", capsLock: true }, + "ä": { key: "Quote" }, + "à": { key: "Quote", shift: true }, + "{": { key: "Quote", altRight: true }, + "Ä": { key: "Quote", capsLock: true }, + "$": { key: "Backslash" }, + "£": { key: "Backslash", shift: true }, + "}": { key: "Backslash", altRight: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + "•": { key: "Comma", altRight: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "·": { key: "Period", altRight: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "\\": { key: "IntlBackslash", altRight: true }, + "€": { key: "KeyE", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record diff --git a/ui/src/keyboardLayouts/en_US.ts b/ui/src/keyboardLayouts/en_US.ts new file mode 100644 index 0000000..57c9eef --- /dev/null +++ b/ui/src/keyboardLayouts/en_US.ts @@ -0,0 +1,102 @@ +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA", shift: false }, + b: { key: "KeyB", shift: false }, + c: { key: "KeyC", shift: false }, + d: { key: "KeyD", shift: false }, + e: { key: "KeyE", shift: false }, + f: { key: "KeyF", shift: false }, + g: { key: "KeyG", shift: false }, + h: { key: "KeyH", shift: false }, + i: { key: "KeyI", shift: false }, + j: { key: "KeyJ", shift: false }, + k: { key: "KeyK", shift: false }, + l: { key: "KeyL", shift: false }, + m: { key: "KeyM", shift: false }, + n: { key: "KeyN", shift: false }, + o: { key: "KeyO", shift: false }, + p: { key: "KeyP", shift: false }, + q: { key: "KeyQ", shift: false }, + r: { key: "KeyR", shift: false }, + s: { key: "KeyS", shift: false }, + t: { key: "KeyT", shift: false }, + u: { key: "KeyU", shift: false }, + v: { key: "KeyV", shift: false }, + w: { key: "KeyW", shift: false }, + x: { key: "KeyX", shift: false }, + y: { key: "KeyY", shift: false }, + z: { key: "KeyZ", shift: false }, + 1: { key: "Digit1", shift: false }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2", shift: false }, + "@": { key: "Digit2", shift: true }, + 3: { key: "Digit3", shift: false }, + "#": { key: "Digit3", shift: true }, + 4: { key: "Digit4", shift: false }, + $: { key: "Digit4", shift: true }, + "%": { key: "Digit5", shift: true }, + 5: { key: "Digit5", shift: false }, + "^": { key: "Digit6", shift: true }, + 6: { key: "Digit6", shift: false }, + "&": { key: "Digit7", shift: true }, + 7: { key: "Digit7", shift: false }, + "*": { key: "Digit8", shift: true }, + 8: { key: "Digit8", shift: false }, + "(": { key: "Digit9", shift: true }, + 9: { key: "Digit9", shift: false }, + ")": { key: "Digit0", shift: true }, + 0: { key: "Digit0", shift: false }, + "-": { key: "Minus", shift: false }, + _: { key: "Minus", shift: true }, + "=": { key: "Equal", shift: false }, + "+": { key: "Equal", shift: true }, + "'": { key: "Quote", shift: false }, + '"': { key: "Quote", shift: true }, + ",": { key: "Comma", shift: false }, + "<": { key: "Comma", shift: true }, + "/": { key: "Slash", shift: false }, + "?": { key: "Slash", shift: true }, + ".": { key: "Period", shift: false }, + ">": { key: "Period", shift: true }, + ";": { key: "Semicolon", shift: false }, + ":": { key: "Semicolon", shift: true }, + "[": { key: "BracketLeft", shift: false }, + "{": { key: "BracketLeft", shift: true }, + "]": { key: "BracketRight", shift: false }, + "}": { key: "BracketRight", shift: true }, + "\\": { key: "Backslash", shift: false }, + "|": { key: "Backslash", shift: true }, + "`": { key: "Backquote", shift: false }, + "~": { key: "Backquote", shift: true }, + "§": { key: "IntlBackslash", shift: false }, + "±": { key: "IntlBackslash", shift: true }, + " ": { key: "Space", shift: false }, + "\n": { key: "Enter", shift: false }, + Enter: { key: "Enter", shift: false }, + Tab: { key: "Tab", shift: false }, +} as Record diff --git a/ui/src/keyboardMappings.ts b/ui/src/keyboardMappings.ts index 347939a..c98efeb 100644 --- a/ui/src/keyboardMappings.ts +++ b/ui/src/keyboardMappings.ts @@ -43,7 +43,7 @@ export const keys = { F13: 0x68, Home: 0x4a, Insert: 0x49, - IntlBackslash: 0x31, + IntlBackslash: 0x64, KeyA: 0x04, KeyB: 0x05, KeyC: 0x06, @@ -99,109 +99,6 @@ export const keys = { Tab: 0x2b, } as Record; -export const chars = { - A: { key: "KeyA", shift: true }, - B: { key: "KeyB", shift: true }, - C: { key: "KeyC", shift: true }, - D: { key: "KeyD", shift: true }, - E: { key: "KeyE", shift: true }, - F: { key: "KeyF", shift: true }, - G: { key: "KeyG", shift: true }, - H: { key: "KeyH", shift: true }, - I: { key: "KeyI", shift: true }, - J: { key: "KeyJ", shift: true }, - K: { key: "KeyK", shift: true }, - L: { key: "KeyL", shift: true }, - M: { key: "KeyM", shift: true }, - N: { key: "KeyN", shift: true }, - O: { key: "KeyO", shift: true }, - P: { key: "KeyP", shift: true }, - Q: { key: "KeyQ", shift: true }, - R: { key: "KeyR", shift: true }, - S: { key: "KeyS", shift: true }, - T: { key: "KeyT", shift: true }, - U: { key: "KeyU", shift: true }, - V: { key: "KeyV", shift: true }, - W: { key: "KeyW", shift: true }, - X: { key: "KeyX", shift: true }, - Y: { key: "KeyY", shift: true }, - Z: { key: "KeyZ", shift: true }, - a: { key: "KeyA", shift: false }, - b: { key: "KeyB", shift: false }, - c: { key: "KeyC", shift: false }, - d: { key: "KeyD", shift: false }, - e: { key: "KeyE", shift: false }, - f: { key: "KeyF", shift: false }, - g: { key: "KeyG", shift: false }, - h: { key: "KeyH", shift: false }, - i: { key: "KeyI", shift: false }, - j: { key: "KeyJ", shift: false }, - k: { key: "KeyK", shift: false }, - l: { key: "KeyL", shift: false }, - m: { key: "KeyM", shift: false }, - n: { key: "KeyN", shift: false }, - o: { key: "KeyO", shift: false }, - p: { key: "KeyP", shift: false }, - q: { key: "KeyQ", shift: false }, - r: { key: "KeyR", shift: false }, - s: { key: "KeyS", shift: false }, - t: { key: "KeyT", shift: false }, - u: { key: "KeyU", shift: false }, - v: { key: "KeyV", shift: false }, - w: { key: "KeyW", shift: false }, - x: { key: "KeyX", shift: false }, - y: { key: "KeyY", shift: false }, - z: { key: "KeyZ", shift: false }, - 1: { key: "Digit1", shift: false }, - "!": { key: "Digit1", shift: true }, - 2: { key: "Digit2", shift: false }, - "@": { key: "Digit2", shift: true }, - 3: { key: "Digit3", shift: false }, - "#": { key: "Digit3", shift: true }, - 4: { key: "Digit4", shift: false }, - $: { key: "Digit4", shift: true }, - "%": { key: "Digit5", shift: true }, - 5: { key: "Digit5", shift: false }, - "^": { key: "Digit6", shift: true }, - 6: { key: "Digit6", shift: false }, - "&": { key: "Digit7", shift: true }, - 7: { key: "Digit7", shift: false }, - "*": { key: "Digit8", shift: true }, - 8: { key: "Digit8", shift: false }, - "(": { key: "Digit9", shift: true }, - 9: { key: "Digit9", shift: false }, - ")": { key: "Digit0", shift: true }, - 0: { key: "Digit0", shift: false }, - "-": { key: "Minus", shift: false }, - _: { key: "Minus", shift: true }, - "=": { key: "Equal", shift: false }, - "+": { key: "Equal", shift: true }, - "'": { key: "Quote", shift: false }, - '"': { key: "Quote", shift: true }, - ",": { key: "Comma", shift: false }, - "<": { key: "Comma", shift: true }, - "/": { key: "Slash", shift: false }, - "?": { key: "Slash", shift: true }, - ".": { key: "Period", shift: false }, - ">": { key: "Period", shift: true }, - ";": { key: "Semicolon", shift: false }, - ":": { key: "Semicolon", shift: true }, - "[": { key: "BracketLeft", shift: false }, - "{": { key: "BracketLeft", shift: true }, - "]": { key: "BracketRight", shift: false }, - "}": { key: "BracketRight", shift: true }, - "\\": { key: "Backslash", shift: false }, - "|": { key: "Backslash", shift: true }, - "`": { key: "Backquote", shift: false }, - "~": { key: "Backquote", shift: true }, - "§": { key: "IntlBackslash", shift: false }, - "±": { key: "IntlBackslash", shift: true }, - " ": { key: "Space", shift: false }, - "\n": { key: "Enter", shift: false }, - Enter: { key: "Enter", shift: false }, - Tab: { key: "Tab", shift: false }, -} as Record; - export const modifiers = { ControlLeft: 0x01, ControlRight: 0x10, diff --git a/ui/src/main.tsx b/ui/src/main.tsx index f4bdd34..18ae323 100644 --- a/ui/src/main.tsx +++ b/ui/src/main.tsx @@ -32,7 +32,8 @@ import { CLOUD_API, DEVICE_API } from "./ui.config"; import OtherSessionRoute from "./routes/devices.$id.other-session"; import MountRoute from "./routes/devices.$id.mount"; import * as SettingsRoute from "./routes/devices.$id.settings"; -import SettingsKeyboardMouseRoute from "./routes/devices.$id.settings.mouse"; +import SettingsMouseRoute from "./routes/devices.$id.settings.mouse"; +import SettingsKeyboardRoute from "./routes/devices.$id.settings.keyboard"; import api from "./api"; import * as SettingsIndexRoute from "./routes/devices.$id.settings._index"; import SettingsAdvancedRoute from "./routes/devices.$id.settings.advanced"; @@ -147,7 +148,11 @@ if (isOnDevice) { }, { path: "mouse", - element: , + element: , + }, + { + path: "keyboard", + element: , }, { path: "advanced", @@ -276,7 +281,11 @@ if (isOnDevice) { }, { path: "mouse", - element: , + element: , + }, + { + path: "keyboard", + element: , }, { path: "advanced", diff --git a/ui/src/routes/devices.$id.settings.keyboard.tsx b/ui/src/routes/devices.$id.settings.keyboard.tsx new file mode 100644 index 0000000..b4981af --- /dev/null +++ b/ui/src/routes/devices.$id.settings.keyboard.tsx @@ -0,0 +1,77 @@ +import { useCallback, useEffect } from "react"; + +import { useDeviceSettingsStore } from "@/hooks/stores"; +import { useJsonRpc } from "@/hooks/useJsonRpc"; +import notifications from "@/notifications"; +import { SettingsPageHeader } from "@components/SettingsPageheader"; +import { layouts } from "@/keyboardLayouts"; + +import { FeatureFlag } from "../components/FeatureFlag"; +import { SelectMenuBasic } from "../components/SelectMenuBasic"; + +import { SettingsItem } from "./devices.$id.settings"; + +export default function SettingsKeyboardRoute() { + const keyboardLayout = useDeviceSettingsStore(state => state.keyboardLayout); + const setKeyboardLayout = useDeviceSettingsStore( + state => state.setKeyboardLayout, + ); + + const layoutOptions = Object.entries(layouts).map(([code, language]) => { return { value: code, label: language } }) + + const [send] = useJsonRpc(); + + useEffect(() => { + send("getKeyboardLayout", {}, resp => { + if ("error" in resp) return; + setKeyboardLayout(resp.result as string); + }); + }, []); + + const onKeyboardLayoutChange = useCallback( + (e: React.ChangeEvent) => { + const layout = e.target.value; + send("setKeyboardLayout", { layout }, resp => { + if ("error" in resp) { + notifications.error( + `Failed to set keyboard layout: ${resp.error.data || "Unknown error"}`, + ); + } + notifications.success("Keyboard layout set successfully"); + setKeyboardLayout(layout); + }); + }, + [send, setKeyboardLayout], + ); + + return ( +
+ + +
+ + { /* this menu item could be renamed to plain "Keyboard layout" in the future, when also the virtual keyboard layout mappings are being implemented */ } + + + +

+ Pasting text sends individual key strokes to the target device. The keyboard layout determines which key codes are being sent. Ensure that the keyboard layout in JetKVM matches the settings in the operating system. +

+
+
+
+ ); +} diff --git a/ui/src/routes/devices.$id.settings.mouse.tsx b/ui/src/routes/devices.$id.settings.mouse.tsx index d6223d0..14cc890 100644 --- a/ui/src/routes/devices.$id.settings.mouse.tsx +++ b/ui/src/routes/devices.$id.settings.mouse.tsx @@ -18,7 +18,7 @@ import { SettingsItem } from "./devices.$id.settings"; type ScrollSensitivity = "low" | "default" | "high"; -export default function SettingsKeyboardMouseRoute() { +export default function SettingsMouseRoute() { const hideCursor = useSettingsStore(state => state.isCursorHidden); const setHideCursor = useSettingsStore(state => state.setCursorVisibility); diff --git a/ui/src/routes/devices.$id.settings.tsx b/ui/src/routes/devices.$id.settings.tsx index f8e5262..182f873 100644 --- a/ui/src/routes/devices.$id.settings.tsx +++ b/ui/src/routes/devices.$id.settings.tsx @@ -1,6 +1,7 @@ import { NavLink, Outlet, useLocation } from "react-router-dom"; import { LuSettings, + LuMouse, LuKeyboard, LuVideo, LuCpu, @@ -148,11 +149,22 @@ export default function SettingsRoute() { className={({ isActive }) => (isActive ? "active" : "")} >
- +

Mouse

+
+ (isActive ? "active" : "")} + > +
+ +

Keyboard

+
+
+
Date: Fri, 2 May 2025 01:32:12 +0200 Subject: [PATCH 02/22] Trema is the more robust method for capital umlauts --- ui/src/components/popovers/PasteModal.tsx | 44 ++++++++++++++--------- ui/src/keyboardLayouts.ts | 2 +- ui/src/keyboardLayouts/de_CH.ts | 8 ++--- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index 9e3d9ee..543af00 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -48,34 +48,44 @@ export default function PasteModal() { try { for (const char of text) { - const { key, shift, altRight, space, capsLock } = chars[keyboardLayout][char] ?? {}; + const { key, shift, altRight, space, capsLock, trema } = chars[keyboardLayout][char] ?? {}; if (!key) continue; - const keyz = [keys[key]]; + const keyz = [ keys[key] ]; + const modz = [ shift ? modifiers["ShiftLeft"] : 0 + | (altRight ? modifiers["AltRight"] : 0) ]; + if (space) { keyz.push(keys["Space"]); + modz.push(0); } if (capsLock) { keyz.unshift(keys["CapsLock"]); + modz.unshift(0); + keyz.push(keys["CapsLock"]); + modz.push(0); + } + if (trema) { + keyz.unshift(keys["BracketRight"]); // trema ¨ + modz.unshift(0) } - const modz = shift ? modifiers["ShiftLeft"] : 0 - | (altRight ? modifiers["AltRight"] : 0); - - await new Promise((resolve, reject) => { - send( - "keyboardReport", - hidKeyboardPayload(keyz, modz), - params => { - if ("error" in params) return reject(params.error); - send("keyboardReport", hidKeyboardPayload([], 0), params => { + for (const [index, keyy] of keyz.entries()) { + await new Promise((resolve, reject) => { + send( + "keyboardReport", + hidKeyboardPayload([keyy], modz[index]), + params => { if ("error" in params) return reject(params.error); - resolve(); - }); - }, - ); - }); + send("keyboardReport", hidKeyboardPayload([], 0), params => { + if ("error" in params) return reject(params.error); + resolve(); + }); + }, + ); + }); + } } } catch (error) { console.error(error); diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 15c3be4..a995e3d 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -9,4 +9,4 @@ export const layouts = { export const chars = { "en_US": chars_en_US, "de_CH": chars_de_CH, -} as Record>; +} as Record>; diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts index 405feb8..893ebe4 100644 --- a/ui/src/keyboardLayouts/de_CH.ts +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -1,5 +1,6 @@ export const chars = { A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, trema: true }, B: { key: "KeyB", shift: true }, C: { key: "KeyC", shift: true }, D: { key: "KeyD", shift: true }, @@ -14,12 +15,14 @@ export const chars = { M: { key: "KeyM", shift: true }, N: { key: "KeyN", shift: true }, O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, trema: true }, P: { key: "KeyP", shift: true }, Q: { key: "KeyQ", shift: true }, R: { key: "KeyR", shift: true }, S: { key: "KeyS", shift: true }, T: { key: "KeyT", shift: true }, U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, trema: true }, V: { key: "KeyV", shift: true }, W: { key: "KeyW", shift: true }, X: { key: "KeyX", shift: true }, @@ -108,16 +111,13 @@ export const chars = { "ü": { key: "BracketLeft" }, "è": { key: "BracketLeft", shift: true }, "[": { key: "BracketLeft", altRight: true }, - "Ü": { key: "BracketLeft", capsLock: true }, "!": { key: "BracketRight", shift: true }, "]": { key: "BracketRight", altRight: true }, "ö": { key: "Semicolon" }, "é": { key: "Semicolon", shift: true }, - "Ö": { key: "Semicolon", capsLock: true }, "ä": { key: "Quote" }, "à": { key: "Quote", shift: true }, "{": { key: "Quote", altRight: true }, - "Ä": { key: "Quote", capsLock: true }, "$": { key: "Backslash" }, "£": { key: "Backslash", shift: true }, "}": { key: "Backslash", altRight: true }, @@ -137,4 +137,4 @@ export const chars = { "\n": { key: "Enter" }, Enter: { key: "Enter" }, Tab: { key: "Tab" }, -} as Record +} as Record From 34f48f9beaa9b48bc6fd965a72069a6183bfce50 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 01:51:20 +0200 Subject: [PATCH 03/22] Improve error handling and pre-loading --- ui/src/components/popovers/PasteModal.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index 543af00..6d74004 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -33,6 +33,13 @@ export default function PasteModal() { state => state.setKeyboardLayout, ); + useEffect(() => { + send("getKeyboardLayout", {}, resp => { + if ("error" in resp) return; + setKeyboardLayout(resp.result as string); + }); + }, []); + const onCancelPasteMode = useCallback(() => { setPasteMode(false); setDisableVideoFocusTrap(false); @@ -48,6 +55,9 @@ export default function PasteModal() { try { for (const char of text) { + if (!keyboardLayout) continue; + if (!chars[keyboardLayout]) continue; + const { key, shift, altRight, space, capsLock, trema } = chars[keyboardLayout][char] ?? {}; if (!key) continue; @@ -97,11 +107,6 @@ export default function PasteModal() { if (TextAreaRef.current) { TextAreaRef.current.focus(); } - - send("getKeyboardLayout", {}, resp => { - if ("error" in resp) return; - setKeyboardLayout(resp.result as string); - }); }, []); return ( From 2be96d327c053f4d10636153f3e241c4d4c042e5 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 02:09:08 +0200 Subject: [PATCH 04/22] Fix default value --- config.go | 2 +- ui/src/hooks/stores.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.go b/config.go index f8daef5..86c64e5 100644 --- a/config.go +++ b/config.go @@ -108,7 +108,7 @@ var defaultConfig = &Config{ AutoUpdateEnabled: true, // Set a default value ActiveExtension: "", KeyboardMacros: []KeyboardMacro{}, - KeyboardLayout: "en-US", + KeyboardLayout: "en_US", DisplayMaxBrightness: 64, DisplayDimAfterSec: 120, // 2 minutes DisplayOffAfterSec: 1800, // 30 minutes diff --git a/ui/src/hooks/stores.ts b/ui/src/hooks/stores.ts index dc97ccf..14b8bb1 100644 --- a/ui/src/hooks/stores.ts +++ b/ui/src/hooks/stores.ts @@ -400,7 +400,7 @@ export const useDeviceSettingsStore = create(set => ({ }); }, - keyboardLayout: "en-US", + keyboardLayout: "en_US", setKeyboardLayout: layout => set({ keyboardLayout: layout }), })); From 3887f7e5b5e1d4ae51f650dd1f277fc140f6c48d Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 17:53:19 +0200 Subject: [PATCH 05/22] Improve accent handling --- ui/src/components/popovers/PasteModal.tsx | 34 ++++++------ ui/src/keyboardLayouts.ts | 5 +- ui/src/keyboardLayouts/de_CH.ts | 63 ++++++++++++++++++++--- ui/src/keyboardLayouts/en_US.ts | 4 +- 4 files changed, 80 insertions(+), 26 deletions(-) diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index 6d74004..b2d00fe 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -17,6 +17,12 @@ const hidKeyboardPayload = (keys: number[], modifier: number) => { return { keys, modifier }; }; +const modifierCode = (shift?: boolean, altRight?: boolean) => { + return shift ? modifiers["ShiftLeft"] : 0 + | (altRight ? modifiers["AltRight"] : 0) +} +const noModifier = 0 + export default function PasteModal() { const TextAreaRef = useRef(null); const setPasteMode = useHidStore(state => state.setPasteModeEnabled); @@ -58,34 +64,26 @@ export default function PasteModal() { if (!keyboardLayout) continue; if (!chars[keyboardLayout]) continue; - const { key, shift, altRight, space, capsLock, trema } = chars[keyboardLayout][char] ?? {}; + const { key, shift, altRight, deadKey, accentKey } = chars[keyboardLayout][char] if (!key) continue; const keyz = [ keys[key] ]; - const modz = [ shift ? modifiers["ShiftLeft"] : 0 - | (altRight ? modifiers["AltRight"] : 0) ]; + const modz = [ modifierCode(shift, altRight) ]; - if (space) { + if (deadKey) { keyz.push(keys["Space"]); - modz.push(0); + modz.push(noModifier); } - if (capsLock) { - keyz.unshift(keys["CapsLock"]); - modz.unshift(0); - - keyz.push(keys["CapsLock"]); - modz.push(0); - } - if (trema) { - keyz.unshift(keys["BracketRight"]); // trema ¨ - modz.unshift(0) + if (accentKey) { + keyz.unshift(keys[accentKey.key]) + modz.unshift(modifierCode(accentKey.shift, accentKey.altRight)) } - for (const [index, keyy] of keyz.entries()) { + for (const [index, kei] of keyz.entries()) { await new Promise((resolve, reject) => { send( "keyboardReport", - hidKeyboardPayload([keyy], modz[index]), + hidKeyboardPayload([kei], modz[index]), params => { if ("error" in params) return reject(params.error); send("keyboardReport", hidKeyboardPayload([], 0), params => { @@ -172,7 +170,7 @@ export default function PasteModal() {

- Sending key codes for keyboard layout {layouts[keyboardLayout]} + Sending key codes using keyboard layout {layouts[keyboardLayout]}

diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index a995e3d..170a71f 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,6 +1,9 @@ import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" +type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } +export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } + export const layouts = { "en_US": "English (US)", "de_CH": "Swiss German" @@ -9,4 +12,4 @@ export const layouts = { export const chars = { "en_US": chars_en_US, "de_CH": chars_de_CH, -} as Record>; +} as Record> diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts index 893ebe4..519b2ad 100644 --- a/ui/src/keyboardLayouts/de_CH.ts +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -1,40 +1,78 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Equal" } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Equal", altRight: true } // tilde, mark ~ placed above the letter + export const chars = { A: { key: "KeyA", shift: true }, - "Ä": { key: "KeyA", shift: true, trema: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + "Æ": { key: "KeyA", shift: true, altRight: true }, B: { key: "KeyB", shift: true }, C: { key: "KeyC", shift: true }, D: { key: "KeyD", shift: true }, E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, F: { key: "KeyF", shift: true }, G: { key: "KeyG", shift: true }, H: { key: "KeyH", shift: true }, I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, J: { key: "KeyJ", shift: true }, K: { key: "KeyK", shift: true }, L: { key: "KeyL", shift: true }, M: { key: "KeyM", shift: true }, N: { key: "KeyN", shift: true }, O: { key: "KeyO", shift: true }, - "Ö": { key: "KeyO", shift: true, trema: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + "Œ": { key: "KeyO", shift: true, altRight: true }, P: { key: "KeyP", shift: true }, Q: { key: "KeyQ", shift: true }, R: { key: "KeyR", shift: true }, S: { key: "KeyS", shift: true }, T: { key: "KeyT", shift: true }, U: { key: "KeyU", shift: true }, - "Ü": { key: "KeyU", shift: true, trema: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, V: { key: "KeyV", shift: true }, W: { key: "KeyW", shift: true }, X: { key: "KeyX", shift: true }, Y: { key: "KeyZ", shift: true }, Z: { key: "KeyY", shift: true }, a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "ã": { key: "KeyA", accentKey: keyTilde }, "æ": { key: "KeyA", altRight: true }, b: { key: "KeyB" }, c: { key: "KeyC" }, d: { key: "KeyD" }, "ð": { key: "KeyD", altRight: true }, e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, f: { key: "KeyF" }, "đ": { key: "KeyF", altRight: true }, g: { key: "KeyG" }, @@ -42,6 +80,11 @@ export const chars = { h: { key: "KeyH" }, "ħ": { key: "KeyH", altRight: true }, i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, "→": { key: "KeyI", altRight: true }, j: { key: "KeyJ" }, k: { key: "KeyK" }, @@ -52,6 +95,10 @@ export const chars = { "µ": { key: "KeyM", altRight: true }, n: { key: "KeyN" }, o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, "œ": { key: "KeyO", altRight: true }, p: { key: "KeyP" }, "þ": { key: "KeyP", altRight: true }, @@ -63,6 +110,10 @@ export const chars = { t: { key: "KeyT" }, "ŧ": { key: "KeyT", altRight: true }, u: { key: "KeyU" }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, "↓": { key: "KeyU", altRight: true }, v: { key: "KeyV" }, "„": { key: "KeyV", altRight: true }, @@ -105,9 +156,9 @@ export const chars = { "=": { key: "Digit0", shift: true }, "'": { key: "Minus" }, "?": { key: "Minus", shift: true }, - "^": { key: "Equal", space: true }, // dead key + "^": { key: "Equal", deadKey: true }, "`": { key: "Equal", shift: true }, - "~": { key: "Equal", altRight: true, space: true }, // dead key + "~": { key: "Equal", altRight: true, deadKey: true }, "ü": { key: "BracketLeft" }, "è": { key: "BracketLeft", shift: true }, "[": { key: "BracketLeft", altRight: true }, @@ -137,4 +188,4 @@ export const chars = { "\n": { key: "Enter" }, Enter: { key: "Enter" }, Tab: { key: "Tab" }, -} as Record +} as Record; diff --git a/ui/src/keyboardLayouts/en_US.ts b/ui/src/keyboardLayouts/en_US.ts index 57c9eef..07014ff 100644 --- a/ui/src/keyboardLayouts/en_US.ts +++ b/ui/src/keyboardLayouts/en_US.ts @@ -1,3 +1,5 @@ +import { KeyCombo } from "../keyboardLayouts" + export const chars = { A: { key: "KeyA", shift: true }, B: { key: "KeyB", shift: true }, @@ -99,4 +101,4 @@ export const chars = { "\n": { key: "Enter", shift: false }, Enter: { key: "Enter", shift: false }, Tab: { key: "Tab", shift: false }, -} as Record +} as Record From 341b70ff0a390e2c8589cbd9b02c2bc662804af5 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 21:00:41 +0200 Subject: [PATCH 06/22] Remove obscure Alt-Gr keys, unsure if they are supported everywhere --- ui/src/keyboardLayouts/de_CH.ts | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts index 519b2ad..2b1019e 100644 --- a/ui/src/keyboardLayouts/de_CH.ts +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -13,7 +13,6 @@ export const chars = { "Â": { key: "KeyA", shift: true, accentKey: keyHat }, "À": { key: "KeyA", shift: true, accentKey: keyGrave }, "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, - "Æ": { key: "KeyA", shift: true, altRight: true }, B: { key: "KeyB", shift: true }, C: { key: "KeyC", shift: true }, D: { key: "KeyD", shift: true }, @@ -43,7 +42,6 @@ export const chars = { "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, - "Œ": { key: "KeyO", shift: true, altRight: true }, P: { key: "KeyP", shift: true }, Q: { key: "KeyQ", shift: true }, R: { key: "KeyR", shift: true }, @@ -64,67 +62,47 @@ export const chars = { "á": { key: "KeyA", accentKey: keyAcute }, "â": { key: "KeyA", accentKey: keyHat }, "ã": { key: "KeyA", accentKey: keyTilde }, - "æ": { key: "KeyA", altRight: true }, b: { key: "KeyB" }, c: { key: "KeyC" }, d: { key: "KeyD" }, - "ð": { key: "KeyD", altRight: true }, e: { key: "KeyE" }, "ë": { key: "KeyE", accentKey: keyTrema }, "ê": { key: "KeyE", accentKey: keyHat }, "ẽ": { key: "KeyE", accentKey: keyTilde }, f: { key: "KeyF" }, - "đ": { key: "KeyF", altRight: true }, g: { key: "KeyG" }, - "ŋ": { key: "KeyG", altRight: true }, h: { key: "KeyH" }, - "ħ": { key: "KeyH", altRight: true }, i: { key: "KeyI" }, "ï": { key: "KeyI", accentKey: keyTrema }, "í": { key: "KeyI", accentKey: keyAcute }, "î": { key: "KeyI", accentKey: keyHat }, "ì": { key: "KeyI", accentKey: keyGrave }, "ĩ": { key: "KeyI", accentKey: keyTilde }, - "→": { key: "KeyI", altRight: true }, j: { key: "KeyJ" }, k: { key: "KeyK" }, - "ĸ": { key: "KeyK", altRight: true }, l: { key: "KeyL" }, - "ł": { key: "KeyL", altRight: true }, m: { key: "KeyM" }, - "µ": { key: "KeyM", altRight: true }, n: { key: "KeyN" }, o: { key: "KeyO" }, "ó": { key: "KeyO", accentKey: keyAcute }, "ô": { key: "KeyO", accentKey: keyHat }, "ò": { key: "KeyO", accentKey: keyGrave }, "õ": { key: "KeyO", accentKey: keyTilde }, - "œ": { key: "KeyO", altRight: true }, p: { key: "KeyP" }, - "þ": { key: "KeyP", altRight: true }, q: { key: "KeyQ" }, r: { key: "KeyR" }, - "¶": { key: "KeyR", altRight: true }, s: { key: "KeyS" }, - "ß": { key: "KeyS", altRight: true }, t: { key: "KeyT" }, - "ŧ": { key: "KeyT", altRight: true }, u: { key: "KeyU" }, "ú": { key: "KeyU", accentKey: keyAcute }, "û": { key: "KeyU", accentKey: keyHat }, "ù": { key: "KeyU", accentKey: keyGrave }, "ũ": { key: "KeyU", accentKey: keyTilde }, - "↓": { key: "KeyU", altRight: true }, v: { key: "KeyV" }, - "„": { key: "KeyV", altRight: true }, w: { key: "KeyW" }, - "ſ": { key: "KeyW", altRight: true }, x: { key: "KeyX" }, - "»": { key: "KeyX", altRight: true }, y: { key: "KeyZ" }, - "←": { key: "KeyZ", altRight: true }, z: { key: "KeyY" }, - "«": { key: "KeyY", altRight: true }, "§": { key: "Backquote" }, "°": { key: "Backquote", shift: true }, 1: { key: "Digit1" }, @@ -138,18 +116,14 @@ export const chars = { "#": { key: "Digit3", altRight: true }, 4: { key: "Digit4" }, "ç": { key: "Digit4", shift: true }, - "¼": { key: "Digit4", altRight: true }, 5: { key: "Digit5" }, "%": { key: "Digit5", shift: true }, - "½": { key: "Digit5", altRight: true }, 6: { key: "Digit6" }, "&": { key: "Digit6", shift: true }, - "¬": { key: "Digit6", altRight: true }, 7: { key: "Digit7" }, "/": { key: "Digit7", shift: true }, 8: { key: "Digit8" }, "(": { key: "Digit8", shift: true }, - "¢": { key: "Digit8", altRight: true }, 9: { key: "Digit9" }, ")": { key: "Digit9", shift: true }, 0: { key: "Digit0" }, @@ -174,10 +148,8 @@ export const chars = { "}": { key: "Backslash", altRight: true }, ",": { key: "Comma" }, ";": { key: "Comma", shift: true }, - "•": { key: "Comma", altRight: true }, ".": { key: "Period" }, ":": { key: "Period", shift: true }, - "·": { key: "Period", altRight: true }, "-": { key: "Slash" }, "_": { key: "Slash", shift: true }, "<": { key: "IntlBackslash" }, From baed361ae6957cf62fe2a88fe86a139b219c9154 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 21:19:51 +0200 Subject: [PATCH 07/22] Add Swiss French --- ui/src/keyboardLayouts.ts | 3 +++ ui/src/keyboardLayouts/fr_CH.ts | 12 ++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 ui/src/keyboardLayouts/fr_CH.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 170a71f..fc28955 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,4 +1,5 @@ import { chars as chars_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } @@ -6,10 +7,12 @@ export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } export const layouts = { "en_US": "English (US)", + "fr_CH": "Swiss French", "de_CH": "Swiss German" } as Record; export const chars = { "en_US": chars_en_US, + "fr_CH": chars_fr_CH, "de_CH": chars_de_CH, } as Record> diff --git a/ui/src/keyboardLayouts/fr_CH.ts b/ui/src/keyboardLayouts/fr_CH.ts new file mode 100644 index 0000000..02f2b69 --- /dev/null +++ b/ui/src/keyboardLayouts/fr_CH.ts @@ -0,0 +1,12 @@ +import { KeyCombo } from "../keyboardLayouts" +import { chars as chars_de_CH } from "./de_CH" + +export const chars = { + ...chars_de_CH, + "è": { key: "BracketLeft" }, + "ü": { key: "BracketLeft", shift: true }, + "é": { key: "Semicolon" }, + "ö": { key: "Semicolon", shift: true }, + "à": { key: "Quote" }, + "ä": { key: "Quote", shift: true }, +} as Record; From 77ce41a5ea41f3e1168654adb041900cdccb738b Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 22:11:10 +0200 Subject: [PATCH 08/22] Change line ordering --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/de_CH.ts | 2 +- ui/src/keyboardLayouts/de_DE.ts | 150 ++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 ui/src/keyboardLayouts/de_DE.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index fc28955..69b3ea9 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,4 +1,5 @@ import { chars as chars_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" @@ -7,12 +8,14 @@ export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } export const layouts = { "en_US": "English (US)", + "de_DE": "German", "fr_CH": "Swiss French", "de_CH": "Swiss German" } as Record; export const chars = { "en_US": chars_en_US, + "de_DE": chars_de_DE, "fr_CH": chars_fr_CH, "de_CH": chars_de_CH, } as Record> diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts index 2b1019e..c822a7f 100644 --- a/ui/src/keyboardLayouts/de_CH.ts +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -69,6 +69,7 @@ export const chars = { "ë": { key: "KeyE", accentKey: keyTrema }, "ê": { key: "KeyE", accentKey: keyHat }, "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, f: { key: "KeyF" }, g: { key: "KeyG" }, h: { key: "KeyH" }, @@ -155,7 +156,6 @@ export const chars = { "<": { key: "IntlBackslash" }, ">": { key: "IntlBackslash", shift: true }, "\\": { key: "IntlBackslash", altRight: true }, - "€": { key: "KeyE", altRight: true }, " ": { key: "Space" }, "\n": { key: "Enter" }, Enter: { key: "Enter" }, diff --git a/ui/src/keyboardLayouts/de_DE.ts b/ui/src/keyboardLayouts/de_DE.ts new file mode 100644 index 0000000..2082f7a --- /dev/null +++ b/ui/src/keyboardLayouts/de_DE.ts @@ -0,0 +1,150 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave}, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "é": { key: "KeyE", accentKey: keyAcute}, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + "µ": { key: "KeyM", altRight: true }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + "@": { key: "KeyQ", altRight: true }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "°": { key: "Backquote", shift: true }, + "^": { key: "Backquote", deadKey: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "²": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "§": { key: "Digit3", shift: true }, + "³": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "ß": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Minus", altRight: true }, + "´": { key: "Equal", deadKey: true }, + "`": { key: "Equal", shift: true, deadKey: true }, + "ü": { key: "BracketLeft" }, + "Ü": { key: "BracketLeft", shift: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "~": { key: "BracketRight", altRight: true }, + "ö": { key: "Semicolon" }, + "Ö": { key: "Semicolon", shift: true }, + "ä": { key: "Quote" }, + "Ä": { key: "Quote", shift: true }, + "#": { key: "Backslash" }, + "'": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "|": { key: "IntlBackslash", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From a364a06a3abb683a04214354c124fdf61fa06864 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 22:12:54 +0200 Subject: [PATCH 09/22] Fix whitespace --- ui/src/keyboardLayouts/de_DE.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/keyboardLayouts/de_DE.ts b/ui/src/keyboardLayouts/de_DE.ts index 2082f7a..08a58d3 100644 --- a/ui/src/keyboardLayouts/de_DE.ts +++ b/ui/src/keyboardLayouts/de_DE.ts @@ -91,7 +91,7 @@ export const chars = { y: { key: "KeyZ" }, z: { key: "KeyY" }, "°": { key: "Backquote", shift: true }, - "^": { key: "Backquote", deadKey: true }, + "^": { key: "Backquote", deadKey: true }, 1: { key: "Digit1" }, "!": { key: "Digit1", shift: true }, 2: { key: "Digit2" }, From 33905e6378cf2b71c4d6631d59cfc952e43112ac Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 22:55:21 +0200 Subject: [PATCH 10/22] Add French (France) --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/fr_FR.ts | 137 ++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 ui/src/keyboardLayouts/fr_FR.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 69b3ea9..2c0eeda 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,4 +1,5 @@ import { chars as chars_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" @@ -8,6 +9,7 @@ export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } export const layouts = { "en_US": "English (US)", + "fr_FR": "French", "de_DE": "German", "fr_CH": "Swiss French", "de_CH": "Swiss German" @@ -15,6 +17,7 @@ export const layouts = { export const chars = { "en_US": chars_en_US, + "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, "fr_CH": chars_fr_CH, "de_CH": chars_de_CH, diff --git a/ui/src/keyboardLayouts/fr_FR.ts b/ui/src/keyboardLayouts/fr_FR.ts new file mode 100644 index 0000000..9d66d16 --- /dev/null +++ b/ui/src/keyboardLayouts/fr_FR.ts @@ -0,0 +1,137 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel +const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter + +export const chars = { + A: { key: "KeyQ", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "Semicolon", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyA", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyZ", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyW", shift: true }, + a: { key: "KeyQ" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "â": { key: "KeyA", accentKey: keyHat }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "î": { key: "KeyI", accentKey: keyHat }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "Semicolon" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, + "ô": { key: "KeyO", accentKey: keyHat }, + p: { key: "KeyP" }, + q: { key: "KeyA" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "û": { key: "KeyU", accentKey: keyHat }, + v: { key: "KeyV" }, + w: { key: "KeyZ" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyW" }, + "²": { key: "Backquote" }, + "&": { key: "Digit1" }, + 1: { key: "Digit1", shift: true }, + "é": { key: "Digit2" }, + 2: { key: "Digit2", shift: true }, + "~": { key: "Digit2", altRight: true }, + "\"": { key: "Digit3" }, + 3: { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + "'": { key: "Digit4" }, + 4: { key: "Digit4", shift: true }, + "{": { key: "Digit4", altRight: true }, + "(": { key: "Digit5" }, + 5: { key: "Digit5", shift: true }, + "[": { key: "Digit5", altRight: true }, + "-": { key: "Digit6" }, + 6: { key: "Digit6", shift: true }, + "|": { key: "Digit6", altRight: true }, + "è": { key: "Digit7" }, + 7: { key: "Digit7", shift: true }, + "`": { key: "Digit7", altRight: true }, + "_": { key: "Digit8" }, + 8: { key: "Digit8", shift: true }, + "\\": { key: "Digit8", altRight: true }, + "ç": { key: "Digit9" }, + 9: { key: "Digit9", shift: true }, + "^": { key: "Digit9", altRight: true }, + "à": { key: "Digit0" }, + 0: { key: "Digit0", shift: true }, + "@": { key: "Digit0", altRight: true }, + ")": { key: "Minus" }, + "°": { key: "Minus", shift: true }, + "]": { key: "Minus", altRight: true }, + "=": { key: "Equal" }, + "+": { key: "Equal", shift: true }, + "}": { key: "Equal", altRight: true }, + "$": { key: "BracketRight" }, + "£": { key: "BracketRight", shift: true }, + "¤": { key: "BracketRight", altRight: true }, + "ù": { key: "Quote" }, + "%": { key: "Quote", shift: true }, + "*": { key: "Backslash" }, + "µ": { key: "Backslash", shift: true }, + ",": { key: "KeyM" }, + "?": { key: "KeyM", shift: true }, + ";": { key: "Comma" }, + ".": { key: "Comma", shift: true }, + ":": { key: "Period" }, + "/": { key: "Period", shift: true }, + "!": { key: "Slash" }, + "§": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From 5447e3434df46b8e4ca8a5413ff47d7bdaaec846 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 22:55:46 +0200 Subject: [PATCH 11/22] Add English (UK) --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/en_UK.ts | 105 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 ui/src/keyboardLayouts/en_UK.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 2c0eeda..de66f8d 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,3 +1,4 @@ +import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" @@ -8,6 +9,7 @@ type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } export const layouts = { + "en_UK": "English (UK)", "en_US": "English (US)", "fr_FR": "French", "de_DE": "German", @@ -16,6 +18,7 @@ export const layouts = { } as Record; export const chars = { + "en_UK": chars_en_UK, "en_US": chars_en_US, "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, diff --git a/ui/src/keyboardLayouts/en_UK.ts b/ui/src/keyboardLayouts/en_UK.ts new file mode 100644 index 0000000..49d623f --- /dev/null +++ b/ui/src/keyboardLayouts/en_UK.ts @@ -0,0 +1,105 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + 3: { key: "Digit3" }, + "£": { key: "Digit3", shift: true }, + 4: { key: "Digit4" }, + $: { key: "Digit4", shift: true }, + "€": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "^": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "&": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "*": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + "(": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + ")": { key: "Digit0", shift: true }, + "-": { key: "Minus" }, + _: { key: "Minus", shift: true }, + "=": { key: "Equal" }, + "+": { key: "Equal", shift: true }, + "'": { key: "Quote" }, + '@': { key: "Quote", shift: true }, + ",": { key: "Comma" }, + "<": { key: "Comma", shift: true }, + "/": { key: "Slash" }, + "?": { key: "Slash", shift: true }, + ".": { key: "Period" }, + ">": { key: "Period", shift: true }, + ";": { key: "Semicolon" }, + ":": { key: "Semicolon", shift: true }, + "[": { key: "BracketLeft" }, + "{": { key: "BracketLeft", shift: true }, + "]": { key: "BracketRight" }, + "}": { key: "BracketRight", shift: true }, + "#": { key: "Backslash" }, + "~": { key: "Backslash", shift: true }, + "`": { key: "Backquote" }, + "¬": { key: "Backquote", shift: true }, + "\\": { key: "IntlBackslash" }, + "|": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record From 98485430ebcd75bfa333c2498da9b21fe963a397 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 23:18:56 +0200 Subject: [PATCH 12/22] Add Swedish --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/sv_SE.ts | 162 ++++++++++++++++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 ui/src/keyboardLayouts/sv_SE.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index de66f8d..98c2bbd 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -2,6 +2,7 @@ import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_sv_SE } from "@/keyboardLayouts/sv_SE" import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" @@ -13,6 +14,7 @@ export const layouts = { "en_US": "English (US)", "fr_FR": "French", "de_DE": "German", + "sv_SE": "Swedish", "fr_CH": "Swiss French", "de_CH": "Swiss German" } as Record; @@ -22,6 +24,7 @@ export const chars = { "en_US": chars_en_US, "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, + "sv_SE": chars_sv_SE, "fr_CH": chars_fr_CH, "de_CH": chars_de_CH, } as Record> diff --git a/ui/src/keyboardLayouts/sv_SE.ts b/ui/src/keyboardLayouts/sv_SE.ts new file mode 100644 index 0000000..79e9771 --- /dev/null +++ b/ui/src/keyboardLayouts/sv_SE.ts @@ -0,0 +1,162 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "§": { key: "Backquote" }, + "½": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "#": { key: "Digit3", shift: true }, + "£": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "¤": { key: "Digit4", shift: true }, + "$": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "+": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Minus", altRight: true }, + "å": { key: "BracketLeft" }, + "Å": { key: "BracketLeft", shift: true }, + "ö": { key: "Semicolon" }, + "Ö": { key: "Semicolon", shift: true }, + "ä": { key: "Quote" }, + "Ä": { key: "Quote", shift: true }, + "'": { key: "Backslash" }, + "*": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + "|": { key: "IntlBackslash", altRight: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From 1a85f4d8ad692f66214f5c9ea79e05047f04ceff Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Fri, 2 May 2025 23:56:52 +0200 Subject: [PATCH 13/22] Add Spanish --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/es_ES.ts | 164 ++++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 ui/src/keyboardLayouts/es_ES.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 98c2bbd..723e855 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -2,6 +2,7 @@ import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_es_ES } from "@/keyboardLayouts/es_ES" import { chars as chars_sv_SE } from "@/keyboardLayouts/sv_SE" import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" @@ -14,6 +15,7 @@ export const layouts = { "en_US": "English (US)", "fr_FR": "French", "de_DE": "German", + "es_ES": "Spanish", "sv_SE": "Swedish", "fr_CH": "Swiss French", "de_CH": "Swiss German" @@ -24,6 +26,7 @@ export const chars = { "en_US": chars_en_US, "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, + "es_ES": chars_es_ES, "sv_SE": chars_sv_SE, "fr_CH": chars_fr_CH, "de_CH": chars_de_CH, diff --git a/ui/src/keyboardLayouts/es_ES.ts b/ui/src/keyboardLayouts/es_ES.ts new file mode 100644 index 0000000..9a53d93 --- /dev/null +++ b/ui/src/keyboardLayouts/es_ES.ts @@ -0,0 +1,164 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "BracketRight" } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Key4", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + "º": { key: "Backquote" }, + "ª": { key: "Backquote", shift: true }, + "\\": { key: "Backquote", altRight: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + "|": { key: "Digit1", altRight: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "·": { key: "Digit3", shift: true }, + "#": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + "¬": { key: "Digit6", altRight: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "¡": { key: "Equal", deadKey: true }, + "¿": { key: "Equal", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "ñ": { key: "Semicolon" }, + "Ñ": { key: "Semicolon", shift: true }, + "{": { key: "Quote", altRight: true }, + "ç": { key: "Backslash" }, + "Ç": { key: "Backslash", shift: true }, + "}": { key: "Backslash", altRight: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From c5b80761ce3259d024620a8e06b19c0f3a9d6011 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sat, 3 May 2025 00:20:22 +0200 Subject: [PATCH 14/22] Fix fr_FR special characters --- ui/src/keyboardLayouts/fr_FR.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/keyboardLayouts/fr_FR.ts b/ui/src/keyboardLayouts/fr_FR.ts index 9d66d16..755deb1 100644 --- a/ui/src/keyboardLayouts/fr_FR.ts +++ b/ui/src/keyboardLayouts/fr_FR.ts @@ -5,8 +5,8 @@ const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ export const chars = { A: { key: "KeyQ", shift: true }, - "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, - "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "Ä": { key: "KeyQ", shift: true, accentKey: keyTrema }, + "Â": { key: "KeyQ", shift: true, accentKey: keyHat }, B: { key: "KeyB", shift: true }, C: { key: "KeyC", shift: true }, D: { key: "KeyD", shift: true }, @@ -41,8 +41,8 @@ export const chars = { Y: { key: "KeyY", shift: true }, Z: { key: "KeyW", shift: true }, a: { key: "KeyQ" }, - "ä": { key: "KeyA", accentKey: keyTrema }, - "â": { key: "KeyA", accentKey: keyHat }, + "ä": { key: "KeyQ", accentKey: keyTrema }, + "â": { key: "KeyQ", accentKey: keyHat }, b: { key: "KeyB" }, c: { key: "KeyC" }, d: { key: "KeyD" }, From 842fd220721f72c21902dac440087ec0edbf28c1 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sat, 3 May 2025 00:50:40 +0200 Subject: [PATCH 15/22] Add more keys to Spanish --- ui/src/keyboardLayouts/es_ES.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ui/src/keyboardLayouts/es_ES.ts b/ui/src/keyboardLayouts/es_ES.ts index 9a53d93..9e34bea 100644 --- a/ui/src/keyboardLayouts/es_ES.ts +++ b/ui/src/keyboardLayouts/es_ES.ts @@ -89,6 +89,7 @@ export const chars = { m: { key: "KeyM" }, n: { key: "KeyN" }, o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, "ó": { key: "KeyO", accentKey: keyAcute }, "ô": { key: "KeyO", accentKey: keyHat }, "ò": { key: "KeyO", accentKey: keyGrave }, @@ -99,6 +100,7 @@ export const chars = { s: { key: "KeyS" }, t: { key: "KeyT" }, u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, "ú": { key: "KeyU", accentKey: keyAcute }, "û": { key: "KeyU", accentKey: keyHat }, "ù": { key: "KeyU", accentKey: keyGrave }, From 435746f35e244d385d190940b0e7b9df95f996bf Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sat, 3 May 2025 22:41:17 +0200 Subject: [PATCH 16/22] Remove default value shift: false --- ui/src/keyboardLayouts/en_US.ts | 104 ++++++++++++++++---------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/ui/src/keyboardLayouts/en_US.ts b/ui/src/keyboardLayouts/en_US.ts index 07014ff..652b8fe 100644 --- a/ui/src/keyboardLayouts/en_US.ts +++ b/ui/src/keyboardLayouts/en_US.ts @@ -27,78 +27,78 @@ export const chars = { X: { key: "KeyX", shift: true }, Y: { key: "KeyY", shift: true }, Z: { key: "KeyZ", shift: true }, - a: { key: "KeyA", shift: false }, - b: { key: "KeyB", shift: false }, - c: { key: "KeyC", shift: false }, - d: { key: "KeyD", shift: false }, - e: { key: "KeyE", shift: false }, - f: { key: "KeyF", shift: false }, - g: { key: "KeyG", shift: false }, - h: { key: "KeyH", shift: false }, - i: { key: "KeyI", shift: false }, - j: { key: "KeyJ", shift: false }, - k: { key: "KeyK", shift: false }, - l: { key: "KeyL", shift: false }, - m: { key: "KeyM", shift: false }, - n: { key: "KeyN", shift: false }, - o: { key: "KeyO", shift: false }, - p: { key: "KeyP", shift: false }, - q: { key: "KeyQ", shift: false }, - r: { key: "KeyR", shift: false }, - s: { key: "KeyS", shift: false }, - t: { key: "KeyT", shift: false }, - u: { key: "KeyU", shift: false }, - v: { key: "KeyV", shift: false }, - w: { key: "KeyW", shift: false }, - x: { key: "KeyX", shift: false }, - y: { key: "KeyY", shift: false }, - z: { key: "KeyZ", shift: false }, - 1: { key: "Digit1", shift: false }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + 1: { key: "Digit1" }, "!": { key: "Digit1", shift: true }, - 2: { key: "Digit2", shift: false }, + 2: { key: "Digit2" }, "@": { key: "Digit2", shift: true }, - 3: { key: "Digit3", shift: false }, + 3: { key: "Digit3" }, "#": { key: "Digit3", shift: true }, - 4: { key: "Digit4", shift: false }, + 4: { key: "Digit4" }, $: { key: "Digit4", shift: true }, "%": { key: "Digit5", shift: true }, - 5: { key: "Digit5", shift: false }, + 5: { key: "Digit5" }, "^": { key: "Digit6", shift: true }, - 6: { key: "Digit6", shift: false }, + 6: { key: "Digit6" }, "&": { key: "Digit7", shift: true }, - 7: { key: "Digit7", shift: false }, + 7: { key: "Digit7" }, "*": { key: "Digit8", shift: true }, - 8: { key: "Digit8", shift: false }, + 8: { key: "Digit8" }, "(": { key: "Digit9", shift: true }, - 9: { key: "Digit9", shift: false }, + 9: { key: "Digit9" }, ")": { key: "Digit0", shift: true }, - 0: { key: "Digit0", shift: false }, - "-": { key: "Minus", shift: false }, + 0: { key: "Digit0" }, + "-": { key: "Minus" }, _: { key: "Minus", shift: true }, - "=": { key: "Equal", shift: false }, + "=": { key: "Equal" }, "+": { key: "Equal", shift: true }, - "'": { key: "Quote", shift: false }, + "'": { key: "Quote" }, '"': { key: "Quote", shift: true }, - ",": { key: "Comma", shift: false }, + ",": { key: "Comma" }, "<": { key: "Comma", shift: true }, - "/": { key: "Slash", shift: false }, + "/": { key: "Slash" }, "?": { key: "Slash", shift: true }, - ".": { key: "Period", shift: false }, + ".": { key: "Period" }, ">": { key: "Period", shift: true }, - ";": { key: "Semicolon", shift: false }, + ";": { key: "Semicolon" }, ":": { key: "Semicolon", shift: true }, - "[": { key: "BracketLeft", shift: false }, + "[": { key: "BracketLeft" }, "{": { key: "BracketLeft", shift: true }, - "]": { key: "BracketRight", shift: false }, + "]": { key: "BracketRight" }, "}": { key: "BracketRight", shift: true }, - "\\": { key: "Backslash", shift: false }, + "\\": { key: "Backslash" }, "|": { key: "Backslash", shift: true }, - "`": { key: "Backquote", shift: false }, + "`": { key: "Backquote" }, "~": { key: "Backquote", shift: true }, - "§": { key: "IntlBackslash", shift: false }, + "§": { key: "IntlBackslash" }, "±": { key: "IntlBackslash", shift: true }, - " ": { key: "Space", shift: false }, - "\n": { key: "Enter", shift: false }, - Enter: { key: "Enter", shift: false }, - Tab: { key: "Tab", shift: false }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, } as Record From 7c2b91a9c4155f1934f74ae134bae1e970543aec Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sat, 3 May 2025 23:56:56 +0200 Subject: [PATCH 17/22] Add Norwegian --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/nb_NO.ts | 165 ++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 ui/src/keyboardLayouts/nb_NO.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 723e855..ce77e9f 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -2,6 +2,7 @@ import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_nb_NO } from "@/keyboardLayouts/nb_NO" import { chars as chars_es_ES } from "@/keyboardLayouts/es_ES" import { chars as chars_sv_SE } from "@/keyboardLayouts/sv_SE" import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" @@ -15,6 +16,7 @@ export const layouts = { "en_US": "English (US)", "fr_FR": "French", "de_DE": "German", + "nb_NO": "Norwegian", "es_ES": "Spanish", "sv_SE": "Swedish", "fr_CH": "Swiss French", @@ -26,6 +28,7 @@ export const chars = { "en_US": chars_en_US, "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, + "nb_NO": chars_nb_NO, "es_ES": chars_es_ES, "sv_SE": chars_sv_SE, "fr_CH": chars_fr_CH, diff --git a/ui/src/keyboardLayouts/nb_NO.ts b/ui/src/keyboardLayouts/nb_NO.ts new file mode 100644 index 0000000..de18561 --- /dev/null +++ b/ui/src/keyboardLayouts/nb_NO.ts @@ -0,0 +1,165 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "BracketRight", altRight: true } // tilde, mark ~ placed above the letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyZ", shift: true }, + Z: { key: "KeyY", shift: true }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "á": { key: "KeyA", accentKey: keyAcute }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "é": { key: "KeyE", accentKey: keyAcute }, + "ê": { key: "KeyE", accentKey: keyHat }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "í": { key: "KeyI", accentKey: keyAcute }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + "ö": { key: "KeyO", accentKey: keyTrema }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "ú": { key: "KeyU", accentKey: keyAcute }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyZ" }, + z: { key: "KeyY" }, + "|": { key: "Backquote" }, + "§": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + "@": { key: "Digit2", altRight: true }, + 3: { key: "Digit3" }, + "#": { key: "Digit3", shift: true }, + "£": { key: "Digit3", altRight: true }, + 4: { key: "Digit4" }, + "¤": { key: "Digit4", shift: true }, + "$": { key: "Digit4", altRight: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + "{": { key: "Digit7", altRight: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + "[": { key: "Digit8", altRight: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + "]": { key: "Digit9", altRight: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "}": { key: "Digit0", altRight: true }, + "+": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "\\": { key: "Equal" }, + "å": { key: "BracketLeft" }, + "Å": { key: "BracketLeft", shift: true }, + "ø": { key: "Semicolon" }, + "Ø": { key: "Semicolon", shift: true }, + "æ": { key: "Quote" }, + "Æ": { key: "Quote", shift: true }, + "'": { key: "Backslash" }, + "*": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From 2f048ef38ffe2297b017cba5cc5cc17be112e4d0 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sun, 4 May 2025 00:25:55 +0200 Subject: [PATCH 18/22] =?UTF-8?q?Operator=20precedence=20=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui/src/components/popovers/PasteModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index b2d00fe..e2068d4 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -18,7 +18,7 @@ const hidKeyboardPayload = (keys: number[], modifier: number) => { }; const modifierCode = (shift?: boolean, altRight?: boolean) => { - return shift ? modifiers["ShiftLeft"] : 0 + return (shift ? modifiers["ShiftLeft"] : 0) | (altRight ? modifiers["AltRight"] : 0) } const noModifier = 0 From e4ddc952d1f776625911888c608b4c5487e61bce Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sun, 4 May 2025 00:26:32 +0200 Subject: [PATCH 19/22] Add Italian --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/it_IT.ts | 111 ++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) create mode 100644 ui/src/keyboardLayouts/it_IT.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index ce77e9f..000dfbe 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -2,6 +2,7 @@ import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_it_IT } from "@/keyboardLayouts/it_IT" import { chars as chars_nb_NO } from "@/keyboardLayouts/nb_NO" import { chars as chars_es_ES } from "@/keyboardLayouts/es_ES" import { chars as chars_sv_SE } from "@/keyboardLayouts/sv_SE" @@ -16,6 +17,7 @@ export const layouts = { "en_US": "English (US)", "fr_FR": "French", "de_DE": "German", + "it_IT": "Italian", "nb_NO": "Norwegian", "es_ES": "Spanish", "sv_SE": "Swedish", @@ -28,6 +30,7 @@ export const chars = { "en_US": chars_en_US, "fr_FR": chars_fr_FR, "de_DE": chars_de_DE, + "it_IT": chars_it_IT, "nb_NO": chars_nb_NO, "es_ES": chars_es_ES, "sv_SE": chars_sv_SE, diff --git a/ui/src/keyboardLayouts/it_IT.ts b/ui/src/keyboardLayouts/it_IT.ts new file mode 100644 index 0000000..fa87e11 --- /dev/null +++ b/ui/src/keyboardLayouts/it_IT.ts @@ -0,0 +1,111 @@ +import { KeyCombo } from "../keyboardLayouts" + +export const chars = { + A: { key: "KeyA", shift: true }, + B: { key: "KeyB", shift: true }, + C: { key: "KeyC", shift: true }, + D: { key: "KeyD", shift: true }, + E: { key: "KeyE", shift: true }, + F: { key: "KeyF", shift: true }, + G: { key: "KeyG", shift: true }, + H: { key: "KeyH", shift: true }, + I: { key: "KeyI", shift: true }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + O: { key: "KeyO", shift: true }, + P: { key: "KeyP", shift: true }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + S: { key: "KeyS", shift: true }, + T: { key: "KeyT", shift: true }, + U: { key: "KeyU", shift: true }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + X: { key: "KeyX", shift: true }, + Y: { key: "KeyY", shift: true }, + Z: { key: "KeyZ", shift: true }, + a: { key: "KeyA" }, + b: { key: "KeyB" }, + c: { key: "KeyC" }, + d: { key: "KeyD" }, + e: { key: "KeyE" }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + g: { key: "KeyG" }, + h: { key: "KeyH" }, + i: { key: "KeyI" }, + j: { key: "KeyJ" }, + k: { key: "KeyK" }, + l: { key: "KeyL" }, + m: { key: "KeyM" }, + n: { key: "KeyN" }, + o: { key: "KeyO" }, + p: { key: "KeyP" }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + s: { key: "KeyS" }, + t: { key: "KeyT" }, + u: { key: "KeyU" }, + v: { key: "KeyV" }, + w: { key: "KeyW" }, + x: { key: "KeyX" }, + y: { key: "KeyY" }, + z: { key: "KeyZ" }, + "\\": { key: "Backquote" }, + "|": { key: "Backquote", shift: true }, + 1: { key: "Digit1" }, + "!": { key: "Digit1", shift: true }, + 2: { key: "Digit2" }, + "\"": { key: "Digit2", shift: true }, + 3: { key: "Digit3" }, + "£": { key: "Digit3", shift: true }, + 4: { key: "Digit4" }, + "$": { key: "Digit4", shift: true }, + 5: { key: "Digit5" }, + "%": { key: "Digit5", shift: true }, + 6: { key: "Digit6" }, + "&": { key: "Digit6", shift: true }, + 7: { key: "Digit7" }, + "/": { key: "Digit7", shift: true }, + 8: { key: "Digit8" }, + "(": { key: "Digit8", shift: true }, + 9: { key: "Digit9" }, + ")": { key: "Digit9", shift: true }, + 0: { key: "Digit0" }, + "=": { key: "Digit0", shift: true }, + "'": { key: "Minus" }, + "?": { key: "Minus", shift: true }, + "ì": { key: "Equal" }, + "^": { key: "Equal", shift: true }, + "è": { key: "BracketLeft" }, + "é": { key: "BracketLeft", shift: true }, + "[": { key: "BracketLeft", altRight: true }, + "{": { key: "BracketLeft", shift: true, altRight: true }, + "+": { key: "BracketRight" }, + "*": { key: "BracketRight", shift: true }, + "]": { key: "BracketRight", altRight: true }, + "}": { key: "BracketRight", shift: true, altRight: true }, + "ò": { key: "Semicolon" }, + "ç": { key: "Semicolon", shift: true }, + "@": { key: "Semicolon", altRight: true }, + "à": { key: "Quote" }, + "°": { key: "Quote", shift: true }, + "#": { key: "Quote", altRight: true }, + "ù": { key: "Backslash" }, + "§": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + ";": { key: "Comma", shift: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "<": { key: "IntlBackslash" }, + ">": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From aeaed88af5b5e447bd314d69d50a5d5adf710a07 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Sun, 4 May 2025 02:37:51 +0200 Subject: [PATCH 20/22] Add Czech --- ui/src/keyboardLayouts.ts | 3 + ui/src/keyboardLayouts/cs_CZ.ts | 242 ++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+) create mode 100644 ui/src/keyboardLayouts/cs_CZ.ts diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 000dfbe..35d5703 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,3 +1,4 @@ +import { chars as chars_cs_CZ } from "@/keyboardLayouts/cs_CZ" import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" import { chars as chars_en_US } from "@/keyboardLayouts/en_US" import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" @@ -13,6 +14,7 @@ type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } export const layouts = { + "cs_CZ": "Czech", "en_UK": "English (UK)", "en_US": "English (US)", "fr_FR": "French", @@ -26,6 +28,7 @@ export const layouts = { } as Record; export const chars = { + "cs_CZ": chars_cs_CZ, "en_UK": chars_en_UK, "en_US": chars_en_US, "fr_FR": chars_fr_FR, diff --git a/ui/src/keyboardLayouts/cs_CZ.ts b/ui/src/keyboardLayouts/cs_CZ.ts new file mode 100644 index 0000000..e889e32 --- /dev/null +++ b/ui/src/keyboardLayouts/cs_CZ.ts @@ -0,0 +1,242 @@ +import { KeyCombo } from "../keyboardLayouts" + +const keyTrema = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel +const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter +const keyHat = { key: "Digit3", shift: true, altRight: true } // accent circonflexe (accent hat), mark ^ placed above the letter +const keyCaron = { key: "Equal", shift: true } // caron or haček (inverted hat), mark ˇ placed above the letter +const keyGrave = { key: "Digit7", shift: true, altRight: true } // accent grave, mark ` placed above the letter +const keyTilde = { key: "Digit1", shift: true, altRight: true } // tilde, mark ~ placed above the letter +const keyRing = { key: "Backquote", shift: true } // kroužek (little ring), mark ° placed above the letter +const keyOverdot = { key: "Digit8", shift: true, altRight: true } // overdot (dot above), mark ˙ placed above the letter +const keyHook = { key: "Digit6", shift: true, altRight: true } // ogonoek (little hook), mark ˛ placed beneath a letter +const keyCedille = { key: "Equal", shift: true, altRight: true } // accent cedille (cedilla), mark ¸ placed beneath a letter + +export const chars = { + A: { key: "KeyA", shift: true }, + "Ä": { key: "KeyA", shift: true, accentKey: keyTrema }, + "Á": { key: "KeyA", shift: true, accentKey: keyAcute }, + "Â": { key: "KeyA", shift: true, accentKey: keyHat }, + "À": { key: "KeyA", shift: true, accentKey: keyGrave }, + "Ã": { key: "KeyA", shift: true, accentKey: keyTilde }, + "Ȧ": { key: "KeyA", shift: true, accentKey: keyOverdot }, + "Ą": { key: "KeyA", shift: true, accentKey: keyHook }, + B: { key: "KeyB", shift: true }, + "Ḃ": { key: "KeyB", shift: true, accentKEy: keyOverdot }, + C: { key: "KeyC", shift: true }, + "Č": { key: "KeyC", shift: true, accentKey: keyCaron }, + "Ċ": { key: "KeyC", shift: true, accentKey: keyOverdot }, + "Ç": { key: "KeyC", shift: true, accentKey: keyCedille }, + D: { key: "KeyD", shift: true }, + "Ď": { key: "KeyD", shift: true, accentKey: keyCaron }, + "Ḋ": { key: "KeyD", shift: true, accentKey: keyOverdot }, + E: { key: "KeyE", shift: true }, + "Ë": { key: "KeyE", shift: true, accentKey: keyTrema }, + "É": { key: "KeyE", shift: true, accentKey: keyAcute }, + "Ê": { key: "KeyE", shift: true, accentKey: keyHat }, + "Ě": { key: "KeyE", shift: true, accentKey: keyCaron }, + "È": { key: "KeyE", shift: true, accentKey: keyGrave }, + "Ẽ": { key: "KeyE", shift: true, accentKey: keyTilde }, + "Ė": { key: "KeyE", shift: true, accentKEy: keyOverdot }, + "Ę": { key: "KeyE", shift: true, accentKey: keyHook }, + F: { key: "KeyF", shift: true }, + "Ḟ": { key: "KeyF", shift: true, accentKey: keyOverdot }, + G: { key: "KeyG", shift: true }, + "Ġ": { key: "KeyG", shift: true, accentKey: keyOverdot }, + H: { key: "KeyH", shift: true }, + "Ḣ": { key: "KeyH", shift: true, accentKey: keyOverdot }, + I: { key: "KeyI", shift: true }, + "Ï": { key: "KeyI", shift: true, accentKey: keyTrema }, + "Í": { key: "KeyI", shift: true, accentKey: keyAcute }, + "Î": { key: "KeyI", shift: true, accentKey: keyHat }, + "Ì": { key: "KeyI", shift: true, accentKey: keyGrave }, + "Ĩ": { key: "KeyI", shift: true, accentKey: keyTilde }, + "İ": { key: "KeyI", shift: true, accentKey: keyOverdot }, + "Į": { key: "KeyI", shift: true, accentKey: keyHook }, + J: { key: "KeyJ", shift: true }, + K: { key: "KeyK", shift: true }, + L: { key: "KeyL", shift: true }, + "Ŀ": { key: "KeyL", shift: true }, + M: { key: "KeyM", shift: true }, + "Ṁ": { key: "KeyM", shift: true }, + N: { key: "KeyN", shift: true }, + "Ň": { key: "KeyN", shift: true, accentKey: keyCaron }, + "Ñ": { key: "KeyN", shift: true, accentKey: keyTilde }, + "Ṅ": { key: "KeyN", shift: true, accentKEy: keyOverdot }, + O: { key: "KeyO", shift: true }, + "Ö": { key: "KeyO", shift: true, accentKey: keyTrema }, + "Ó": { key: "KeyO", shift: true, accentKey: keyAcute }, + "Ô": { key: "KeyO", shift: true, accentKey: keyHat }, + "Ò": { key: "KeyO", shift: true, accentKey: keyGrave }, + "Õ": { key: "KeyO", shift: true, accentKey: keyTilde }, + "Ȯ": { key: "KeyO", shift: true, accentKey: keyOverdot }, + "Ǫ": { key: "KeyO", shift: true, accentKey: keyHook }, + P: { key: "KeyP", shift: true }, + "Ṗ": { key: "KeyP", shift: true, accentKey: keyOverdot }, + Q: { key: "KeyQ", shift: true }, + R: { key: "KeyR", shift: true }, + "Ř": { key: "KeyR", shift: true, accentKey: keyCaron }, + "Ṙ": { key: "KeyR", shift: true, accentKey: keyOverdot }, + S: { key: "KeyS", shift: true }, + "Š": { key: "KeyS", shift: true, accentKey: keyCaron }, + "Ṡ": { key: "KeyS", shift: true, accentKey: keyOverdot }, + T: { key: "KeyT", shift: true }, + "Ť": { key: "KeyT", shift: true, accentKey: keyCaron }, + "Ṫ": { key: "KeyT", shift: true, accentKey: keyOverdot }, + U: { key: "KeyU", shift: true }, + "Ü": { key: "KeyU", shift: true, accentKey: keyTrema }, + "Ú": { key: "KeyU", shift: true, accentKey: keyAcute }, + "Û": { key: "KeyU", shift: true, accentKey: keyHat }, + "Ù": { key: "KeyU", shift: true, accentKey: keyGrave }, + "Ũ": { key: "KeyU", shift: true, accentKey: keyTilde }, + "Ů": { key: "KeyU", shift: true, accentKey: keyRing }, + "Ų": { key: "KeyU", shift: true, accentKey: keyHook }, + V: { key: "KeyV", shift: true }, + W: { key: "KeyW", shift: true }, + "Ẇ": { key: "KeyW", shift: true, accentKey: keyOverdot }, + X: { key: "KeyX", shift: true }, + "Ẋ": { key: "KeyX", shift: true, accentKey: keyOverdot }, + Y: { key: "KeyY", shift: true }, + "Ý": { key: "KeyY", shift: true, accentKey: keyAcute }, + "Ẏ": { key: "KeyY", shift: true, accentKey: keyOverdot }, + Z: { key: "KeyZ", shift: true }, + "Ż": { key: "KeyZ", shift: true, accentKey: keyOverdot }, + a: { key: "KeyA" }, + "ä": { key: "KeyA", accentKey: keyTrema }, + "â": { key: "KeyA", accentKey: keyHat }, + "à": { key: "KeyA", accentKey: keyGrave }, + "ã": { key: "KeyA", accentKey: keyTilde }, + "ȧ": { key: "KeyA", accentKey: keyOverdot }, + "ą": { key: "KeyA", accentKey: keyHook }, + b: { key: "KeyB" }, + "{": { key: "KeyB", altRight: true }, + "ḃ": { key: "KeyB", accentKey: keyOverdot }, + c: { key: "KeyC" }, + "&": { key: "KeyC", altRight: true }, + "ç": { key: "KeyC", accentKey: keyCedille }, + "ċ": { key: "KeyC", accentKey: keyOverdot }, + d: { key: "KeyD" }, + "ď": { key: "KeyD", accentKey: keyCaron }, + "ḋ": { key: "KeyD", accentKey: keyOverdot }, + "Đ": { key: "KeyD", altRight: true }, + e: { key: "KeyE" }, + "ë": { key: "KeyE", accentKey: keyTrema }, + "ê": { key: "KeyE", accentKey: keyHat }, + "ẽ": { key: "KeyE", accentKey: keyTilde }, + "è": { key: "KeyE", accentKey: keyGrave }, + "ė": { key: "KeyE", accentKey: keyOverdot }, + "ę": { key: "KeyE", accentKey: keyHook }, + "€": { key: "KeyE", altRight: true }, + f: { key: "KeyF" }, + "ḟ": { key: "KeyF", accentKey: keyOverdot }, + "[": { key: "KeyF", altRight: true }, + g: { key: "KeyG" }, + "ġ": { key: "KeyG", accentKey: keyOverdot }, + "]": { key: "KeyF", altRight: true }, + h: { key: "KeyH" }, + "ḣ": { key: "KeyH", accentKey: keyOverdot }, + i: { key: "KeyI" }, + "ï": { key: "KeyI", accentKey: keyTrema }, + "î": { key: "KeyI", accentKey: keyHat }, + "ì": { key: "KeyI", accentKey: keyGrave }, + "ĩ": { key: "KeyI", accentKey: keyTilde }, + "ı": { key: "KeyI", accentKey: keyOverdot }, + "į": { key: "KeyI", accentKey: keyHook }, + j: { key: "KeyJ" }, + "ȷ": { key: "KeyJ", accentKey: keyOverdot }, + k: { key: "KeyK" }, + "ł": { key: "KeyK", altRight: true }, + l: { key: "KeyL" }, + "ŀ": { key: "KeyL", accentKey: keyOverdot }, + "Ł": { key: "KeyL", altRight: true }, + m: { key: "KeyM" }, + "ṁ": { key: "KeyM", accentKey: keyOverdot }, + n: { key: "KeyN" }, + "}": { key: "KeyN", altRight: true }, + "ň": { key: "KeyN", accentKey: keyCaron }, + "ñ": { key: "KeyN", accentKey: keyTilde }, + "ṅ": { key: "KeyN", accentKey: keyOverdot }, + o: { key: "KeyO" }, + "ö": { key: "Key0", accentKey: keyTrema }, + "ó": { key: "KeyO", accentKey: keyAcute }, + "ô": { key: "KeyO", accentKey: keyHat }, + "ò": { key: "KeyO", accentKey: keyGrave }, + "õ": { key: "KeyO", accentKey: keyTilde }, + "ȯ": { key: "KeyO", accentKey: keyOverdot }, + "ǫ": { key: "KeyO", accentKey: keyHook }, + p: { key: "KeyP" }, + "ṗ": { key: "KeyP", accentKey: keyOverdot }, + q: { key: "KeyQ" }, + r: { key: "KeyR" }, + "ṙ": { key: "KeyR", accentKey: keyOverdot }, + s: { key: "KeyS" }, + "ṡ": { key: "KeyS", accentKey: keyOverdot }, + "đ": { key: "KeyS", altRight: true }, + t: { key: "KeyT" }, + "ť": { key: "KeyT", accentKey: keyCaron }, + "ṫ": { key: "KeyT", accentKey: keyOverdot }, + u: { key: "KeyU" }, + "ü": { key: "KeyU", accentKey: keyTrema }, + "û": { key: "KeyU", accentKey: keyHat }, + "ù": { key: "KeyU", accentKey: keyGrave }, + "ũ": { key: "KeyU", accentKey: keyTilde }, + "ų": { key: "KeyU", accentKey: keyHook }, + v: { key: "KeyV" }, + "@": { key: "KeyV", altRight: true }, + w: { key: "KeyW" }, + "ẇ": { key: "KeyW", accentKey: keyOverdot }, + x: { key: "KeyX" }, + "#": { key: "KeyX", altRight: true }, + "ẋ": { key: "KeyX", accentKey: keyOverdot }, + y: { key: "KeyY" }, + "ẏ": { key: "KeyY", accentKey: keyOverdot }, + z: { key: "KeyZ" }, + "ż": { key: "KeyZ", accentKey: keyOverdot }, + ";": { key: "Backquote" }, + "°": { key: "Backquote", shift: true, deadKey: true }, + "+": { key: "Digit1" }, + 1: { key: "Digit1", shift: true }, + "ě": { key: "Digit2" }, + 2: { key: "Digit2", shift: true }, + "š": { key: "Digit3" }, + 3: { key: "Digit3", shift: true }, + "č": { key: "Digit4" }, + 4: { key: "Digit4", shift: true }, + "ř": { key: "Digit5" }, + 5: { key: "Digit5", shift: true }, + "ž": { key: "Digit6" }, + 6: { key: "Digit6", shift: true }, + "ý": { key: "Digit7" }, + 7: { key: "Digit7", shift: true }, + "á": { key: "Digit8" }, + 8: { key: "Digit8", shift: true }, + "í": { key: "Digit9" }, + 9: { key: "Digit9", shift: true }, + "é": { key: "Digit0" }, + 0: { key: "Digit0", shift: true }, + "=": { key: "Minus" }, + "%": { key: "Minus", shift: true }, + "ú": { key: "BracketLeft" }, + "/": { key: "BracketLeft", shift: true }, + ")": { key: "BracketRight" }, + "(": { key: "BracketRight", shift: true }, + "ů": { key: "Semicolon" }, + "\"": { key: "Semicolon", shift: true }, + "§": { key: "Quote" }, + "!": { key: "Quote", shift: true }, + "'": { key: "Backslash", shift: true }, + ",": { key: "Comma" }, + "?": { key: "Comma", shift: true }, + "<": { key: "Comma", altRight: true }, + ".": { key: "Period" }, + ":": { key: "Period", shift: true }, + ">": { key: "Period", altRight: true }, + "-": { key: "Slash" }, + "_": { key: "Slash", shift: true }, + "*": { key: "Slash", altRight: true }, + "\\": { key: "IntlBackslash" }, + "|": { key: "IntlBackslash", shift: true }, + " ": { key: "Space" }, + "\n": { key: "Enter" }, + Enter: { key: "Enter" }, + Tab: { key: "Tab" }, +} as Record; From 4d840b65a9904de906b928e4930a58df43ae4a7b Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Thu, 8 May 2025 20:25:53 +0200 Subject: [PATCH 21/22] Move guard statements outside of loop --- ui/src/components/popovers/PasteModal.tsx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/src/components/popovers/PasteModal.tsx b/ui/src/components/popovers/PasteModal.tsx index e2068d4..d557306 100644 --- a/ui/src/components/popovers/PasteModal.tsx +++ b/ui/src/components/popovers/PasteModal.tsx @@ -56,14 +56,13 @@ export default function PasteModal() { setPasteMode(false); setDisableVideoFocusTrap(false); if (rpcDataChannel?.readyState !== "open" || !TextAreaRef.current) return; + if (!keyboardLayout) return; + if (!chars[keyboardLayout]) return; const text = TextAreaRef.current.value; try { for (const char of text) { - if (!keyboardLayout) continue; - if (!chars[keyboardLayout]) continue; - const { key, shift, altRight, deadKey, accentKey } = chars[keyboardLayout][char] if (!key) continue; From 48240eebe05c3182f824d8e63e05e8840a5a6097 Mon Sep 17 00:00:00 2001 From: Daniel Lorch Date: Thu, 8 May 2025 20:26:59 +0200 Subject: [PATCH 22/22] Move language name definitions into the keyboard layout files --- ui/src/keyboardLayouts.ts | 74 ++++++++++++++++----------------- ui/src/keyboardLayouts/cs_CZ.ts | 2 + ui/src/keyboardLayouts/de_CH.ts | 2 + ui/src/keyboardLayouts/de_DE.ts | 2 + ui/src/keyboardLayouts/en_UK.ts | 2 + ui/src/keyboardLayouts/en_US.ts | 2 + ui/src/keyboardLayouts/es_ES.ts | 2 + ui/src/keyboardLayouts/fr_CH.ts | 2 + ui/src/keyboardLayouts/fr_FR.ts | 2 + ui/src/keyboardLayouts/it_IT.ts | 2 + ui/src/keyboardLayouts/nb_NO.ts | 2 + ui/src/keyboardLayouts/sv_SE.ts | 2 + 12 files changed, 59 insertions(+), 37 deletions(-) diff --git a/ui/src/keyboardLayouts.ts b/ui/src/keyboardLayouts.ts index 35d5703..8dc0dec 100644 --- a/ui/src/keyboardLayouts.ts +++ b/ui/src/keyboardLayouts.ts @@ -1,42 +1,42 @@ -import { chars as chars_cs_CZ } from "@/keyboardLayouts/cs_CZ" -import { chars as chars_en_UK } from "@/keyboardLayouts/en_UK" -import { chars as chars_en_US } from "@/keyboardLayouts/en_US" -import { chars as chars_fr_FR } from "@/keyboardLayouts/fr_FR" -import { chars as chars_de_DE } from "@/keyboardLayouts/de_DE" -import { chars as chars_it_IT } from "@/keyboardLayouts/it_IT" -import { chars as chars_nb_NO } from "@/keyboardLayouts/nb_NO" -import { chars as chars_es_ES } from "@/keyboardLayouts/es_ES" -import { chars as chars_sv_SE } from "@/keyboardLayouts/sv_SE" -import { chars as chars_fr_CH } from "@/keyboardLayouts/fr_CH" -import { chars as chars_de_CH } from "@/keyboardLayouts/de_CH" +import { chars as chars_cs_CZ, name as name_cs_CZ } from "@/keyboardLayouts/cs_CZ" +import { chars as chars_en_UK, name as name_en_UK } from "@/keyboardLayouts/en_UK" +import { chars as chars_en_US, name as name_en_US } from "@/keyboardLayouts/en_US" +import { chars as chars_fr_FR, name as name_fr_FR } from "@/keyboardLayouts/fr_FR" +import { chars as chars_de_DE, name as name_de_DE } from "@/keyboardLayouts/de_DE" +import { chars as chars_it_IT, name as name_it_IT } from "@/keyboardLayouts/it_IT" +import { chars as chars_nb_NO, name as name_nb_NO } from "@/keyboardLayouts/nb_NO" +import { chars as chars_es_ES, name as name_es_ES } from "@/keyboardLayouts/es_ES" +import { chars as chars_sv_SE, name as name_sv_SE } from "@/keyboardLayouts/sv_SE" +import { chars as chars_fr_CH, name as name_fr_CH } from "@/keyboardLayouts/fr_CH" +import { chars as chars_de_CH, name as name_de_CH } from "@/keyboardLayouts/de_CH" type KeyInfo = { key: string | number; shift?: boolean, altRight?: boolean } export type KeyCombo = KeyInfo & { deadKey?: boolean, accentKey?: KeyInfo } -export const layouts = { - "cs_CZ": "Czech", - "en_UK": "English (UK)", - "en_US": "English (US)", - "fr_FR": "French", - "de_DE": "German", - "it_IT": "Italian", - "nb_NO": "Norwegian", - "es_ES": "Spanish", - "sv_SE": "Swedish", - "fr_CH": "Swiss French", - "de_CH": "Swiss German" -} as Record; +export const layouts: Record = { + cs_CZ: name_cs_CZ, + en_UK: name_en_UK, + en_US: name_en_US, + fr_FR: name_fr_FR, + de_DE: name_de_DE, + it_IT: name_it_IT, + nb_NO: name_nb_NO, + es_ES: name_es_ES, + sv_SE: name_sv_SE, + fr_CH: name_fr_CH, + de_CH: name_de_CH, +} -export const chars = { - "cs_CZ": chars_cs_CZ, - "en_UK": chars_en_UK, - "en_US": chars_en_US, - "fr_FR": chars_fr_FR, - "de_DE": chars_de_DE, - "it_IT": chars_it_IT, - "nb_NO": chars_nb_NO, - "es_ES": chars_es_ES, - "sv_SE": chars_sv_SE, - "fr_CH": chars_fr_CH, - "de_CH": chars_de_CH, -} as Record> +export const chars: Record> = { + cs_CZ: chars_cs_CZ, + en_UK: chars_en_UK, + en_US: chars_en_US, + fr_FR: chars_fr_FR, + de_DE: chars_de_DE, + it_IT: chars_it_IT, + nb_NO: chars_nb_NO, + es_ES: chars_es_ES, + sv_SE: chars_sv_SE, + fr_CH: chars_fr_CH, + de_CH: chars_de_CH, +}; diff --git a/ui/src/keyboardLayouts/cs_CZ.ts b/ui/src/keyboardLayouts/cs_CZ.ts index e889e32..ee2799c 100644 --- a/ui/src/keyboardLayouts/cs_CZ.ts +++ b/ui/src/keyboardLayouts/cs_CZ.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Czech"; + const keyTrema = { key: "Backslash" } // tréma (umlaut), two dots placed above a vowel const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "Digit3", shift: true, altRight: true } // accent circonflexe (accent hat), mark ^ placed above the letter diff --git a/ui/src/keyboardLayouts/de_CH.ts b/ui/src/keyboardLayouts/de_CH.ts index c822a7f..c3f1f8c 100644 --- a/ui/src/keyboardLayouts/de_CH.ts +++ b/ui/src/keyboardLayouts/de_CH.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Swiss German"; + const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyAcute = { key: "Minus", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "Equal" } // accent circonflexe (accent hat), mark ^ placed above the letter diff --git a/ui/src/keyboardLayouts/de_DE.ts b/ui/src/keyboardLayouts/de_DE.ts index 08a58d3..2833909 100644 --- a/ui/src/keyboardLayouts/de_DE.ts +++ b/ui/src/keyboardLayouts/de_DE.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "German"; + const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "Backquote" } // accent circonflexe (accent hat), mark ^ placed above the letter const keyGrave = { key: "Equal", shift: true } // accent grave, mark ` placed above the letter diff --git a/ui/src/keyboardLayouts/en_UK.ts b/ui/src/keyboardLayouts/en_UK.ts index 49d623f..ed0c8dd 100644 --- a/ui/src/keyboardLayouts/en_UK.ts +++ b/ui/src/keyboardLayouts/en_UK.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "English (UK)"; + export const chars = { A: { key: "KeyA", shift: true }, B: { key: "KeyB", shift: true }, diff --git a/ui/src/keyboardLayouts/en_US.ts b/ui/src/keyboardLayouts/en_US.ts index 652b8fe..3ae1c2e 100644 --- a/ui/src/keyboardLayouts/en_US.ts +++ b/ui/src/keyboardLayouts/en_US.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "English (US)"; + export const chars = { A: { key: "KeyA", shift: true }, B: { key: "KeyB", shift: true }, diff --git a/ui/src/keyboardLayouts/es_ES.ts b/ui/src/keyboardLayouts/es_ES.ts index 9e34bea..f979205 100644 --- a/ui/src/keyboardLayouts/es_ES.ts +++ b/ui/src/keyboardLayouts/es_ES.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Spanish"; + const keyTrema = { key: "Quote", shift: true } // tréma (umlaut), two dots placed above a vowel const keyAcute = { key: "Quote" } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter diff --git a/ui/src/keyboardLayouts/fr_CH.ts b/ui/src/keyboardLayouts/fr_CH.ts index 02f2b69..e47af1d 100644 --- a/ui/src/keyboardLayouts/fr_CH.ts +++ b/ui/src/keyboardLayouts/fr_CH.ts @@ -1,6 +1,8 @@ import { KeyCombo } from "../keyboardLayouts" import { chars as chars_de_CH } from "./de_CH" +export const name = "Swiss French"; + export const chars = { ...chars_de_CH, "è": { key: "BracketLeft" }, diff --git a/ui/src/keyboardLayouts/fr_FR.ts b/ui/src/keyboardLayouts/fr_FR.ts index 755deb1..a489807 100644 --- a/ui/src/keyboardLayouts/fr_FR.ts +++ b/ui/src/keyboardLayouts/fr_FR.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "French"; + const keyTrema = { key: "BracketLeft", shift: true } // tréma (umlaut), two dots placed above a vowel const keyHat = { key: "BracketLeft" } // accent circonflexe (accent hat), mark ^ placed above the letter diff --git a/ui/src/keyboardLayouts/it_IT.ts b/ui/src/keyboardLayouts/it_IT.ts index fa87e11..012734c 100644 --- a/ui/src/keyboardLayouts/it_IT.ts +++ b/ui/src/keyboardLayouts/it_IT.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Italian"; + export const chars = { A: { key: "KeyA", shift: true }, B: { key: "KeyB", shift: true }, diff --git a/ui/src/keyboardLayouts/nb_NO.ts b/ui/src/keyboardLayouts/nb_NO.ts index de18561..1507ed3 100644 --- a/ui/src/keyboardLayouts/nb_NO.ts +++ b/ui/src/keyboardLayouts/nb_NO.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Norwegian"; + const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyAcute = { key: "Equal", altRight: true } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter diff --git a/ui/src/keyboardLayouts/sv_SE.ts b/ui/src/keyboardLayouts/sv_SE.ts index 79e9771..d2af302 100644 --- a/ui/src/keyboardLayouts/sv_SE.ts +++ b/ui/src/keyboardLayouts/sv_SE.ts @@ -1,5 +1,7 @@ import { KeyCombo } from "../keyboardLayouts" +export const name = "Swedish"; + const keyTrema = { key: "BracketRight" } // tréma (umlaut), two dots placed above a vowel const keyAcute = { key: "Equal" } // accent aigu (acute accent), mark ´ placed above the letter const keyHat = { key: "BracketRight", shift: true } // accent circonflexe (accent hat), mark ^ placed above the letter