From bf002c02ec578bc170dec4f75c179d2e51e655c9 Mon Sep 17 00:00:00 2001 From: megalodon2710 <103191372+megalodon2710@users.noreply.github.com> Date: Thu, 17 Apr 2025 16:10:19 +0200 Subject: [PATCH] feat(funbox): add layout mirror (@megalodon2710) (#6463) ### Description Added layout mirror item in the funbox with functionality. Tweaked how active funbox items are detected in the commandline (names included in other names no long appear as active if the item they're included in is active). ### Checks - [ ] Adding quotes? - [ ] Make sure to include translations for the quotes in the description (or another comment) so we can verify their content. - [ ] Adding a language or a theme? - [ ] If is a language, did you edit `_list.json`, `_groups.json` and add `languages.json`? - [ ] If is a theme, did you add the theme.css? - Also please add a screenshot of the theme, it would be extra awesome if you do so! - [X] Check if any open issues are related to this PR; if so, be sure to tag them below. - [X] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [X] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. Closes #5573 --------- Co-authored-by: jeffrey Co-authored-by: Miodec --- frontend/src/ts/commandline/commandline.ts | 18 +++++++--- frontend/src/ts/commandline/lists/funbox.ts | 3 +- frontend/src/ts/commandline/types.ts | 2 +- .../src/ts/controllers/input-controller.ts | 10 +++++- frontend/src/ts/elements/keymap.ts | 6 ++++ .../src/ts/test/funbox/funbox-functions.ts | 14 ++++++++ frontend/src/ts/test/layout-emulator.ts | 8 +++++ frontend/src/ts/utils/key-converter.ts | 33 +++++++++++++++++++ packages/funbox/src/list.ts | 9 ++++- packages/funbox/src/types.ts | 1 + 10 files changed, 95 insertions(+), 9 deletions(-) diff --git a/frontend/src/ts/commandline/commandline.ts b/frontend/src/ts/commandline/commandline.ts index ec27b45a5..0d94deaf4 100644 --- a/frontend/src/ts/commandline/commandline.ts +++ b/frontend/src/ts/commandline/commandline.ts @@ -352,9 +352,14 @@ async function showCommands(): Promise { configIcon = ``; } } else if (configKey !== undefined) { - const valueIsIncluded = - command.configValueMode === "include" && - ( + let isActive; + + if (command.configValueMode === "funbox") { + isActive = (Config[configKey] as string) + .split("#") + .includes(command.configValue as string); + } else if (command.configValueMode === "include") { + isActive = ( Config[configKey] as ( | string | number @@ -363,8 +368,11 @@ async function showCommands(): Promise { | undefined )[] ).includes(command.configValue); - const valueIsTheSame = Config[configKey] === command.configValue; - if (valueIsIncluded || valueIsTheSame) { + } else { + isActive = Config[configKey] === command.configValue; + } + + if (isActive) { firstActive = firstActive ?? index; configIcon = ``; } else { diff --git a/frontend/src/ts/commandline/lists/funbox.ts b/frontend/src/ts/commandline/lists/funbox.ts index f8c984bc3..9faf2fa9f 100644 --- a/frontend/src/ts/commandline/lists/funbox.ts +++ b/frontend/src/ts/commandline/lists/funbox.ts @@ -33,7 +33,8 @@ for (const funbox of getAllFunboxes()) { sticky: true, alias: funbox.alias, configValue: funbox.name, - configValueMode: "include", + //todo remove funbox mode once Config.funbox is changed to an array + configValueMode: "funbox", exec: (): void => { Funbox.toggleFunbox(funbox.name); ManualRestart.set(); diff --git a/frontend/src/ts/commandline/types.ts b/frontend/src/ts/commandline/types.ts index 4932b274d..8e382fdfc 100644 --- a/frontend/src/ts/commandline/types.ts +++ b/frontend/src/ts/commandline/types.ts @@ -25,7 +25,7 @@ export type Command = { defaultValue?: () => string; configKey?: keyof Config; configValue?: string | number | boolean | number[]; - configValueMode?: "include"; + configValueMode?: "include" | "funbox"; exec?: (options: CommandExecOptions) => void; hover?: () => void; available?: () => boolean; diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts index e5c261711..bedbdbdbc 100644 --- a/frontend/src/ts/controllers/input-controller.ts +++ b/frontend/src/ts/controllers/input-controller.ts @@ -39,6 +39,7 @@ import { findSingleActiveFunboxWithFunction, getActiveFunboxesWithFunction, isFunboxActiveWithProperty, + getActiveFunboxNames, } from "../test/funbox/list"; let dontInsertSpace = false; @@ -1128,14 +1129,21 @@ $(document).on("keydown", async (event) => { Config.oppositeShiftMode === "keymap" && Config.keymapLayout !== "overrideSync" ) { - const keymapLayout = await JSONData.getLayout(Config.keymapLayout).catch( + let keymapLayout = await JSONData.getLayout(Config.keymapLayout).catch( () => undefined ); + if (keymapLayout === undefined) { Notifications.add("Failed to load keymap layout", -1); return; } + + const funbox = getActiveFunboxNames().includes("layout_mirror"); + if (funbox) { + keymapLayout = KeyConverter.mirrorLayoutKeys(keymapLayout); + } + const keycode = KeyConverter.layoutKeyToKeycode(event.key, keymapLayout); correctShiftUsed = diff --git a/frontend/src/ts/elements/keymap.ts b/frontend/src/ts/elements/keymap.ts index ad99c667e..8f1fc31f8 100644 --- a/frontend/src/ts/elements/keymap.ts +++ b/frontend/src/ts/elements/keymap.ts @@ -13,6 +13,7 @@ import { capsState } from "../test/caps-warning"; import * as ShiftTracker from "../test/shift-tracker"; import * as AltTracker from "../test/alt-tracker"; import * as KeyConverter from "../utils/key-converter"; +import { getActiveFunboxNames } from "../test/funbox/list"; const stenoKeys: JSONData.Layout = { keymapShowTopRow: true, @@ -393,6 +394,11 @@ export async function refresh( layoutData = stenoKeys; } + const funbox = getActiveFunboxNames().includes("layout_mirror"); + if (funbox) { + layoutData = KeyConverter.mirrorLayoutKeys(layoutData); + } + const isISO = layoutData.type === "iso"; let keymapElement = ""; diff --git a/frontend/src/ts/test/funbox/funbox-functions.ts b/frontend/src/ts/test/funbox/funbox-functions.ts index 6e550f51c..4a4da520b 100644 --- a/frontend/src/ts/test/funbox/funbox-functions.ts +++ b/frontend/src/ts/test/funbox/funbox-functions.ts @@ -326,6 +326,20 @@ const list: Partial> = { return Strings.capitalizeFirstLetterOfEachWord(word); }, }, + layout_mirror: { + applyConfig(): void { + let layout = Config.layout; + if (Config.layout === "default") { + layout = "qwerty"; + } + UpdateConfig.setLayout(layout, true); + UpdateConfig.setKeymapLayout("overrideSync", true); + }, + rememberSettings(): void { + save("keymapMode", Config.keymapMode, UpdateConfig.setKeymapMode); + save("layout", Config.layout, UpdateConfig.setLayout); + }, + }, layoutfluid: { applyConfig(): void { const layout = Config.customLayoutfluid.split("#")[0] ?? "qwerty"; diff --git a/frontend/src/ts/test/layout-emulator.ts b/frontend/src/ts/test/layout-emulator.ts index ec6bc6984..18ca48bc6 100644 --- a/frontend/src/ts/test/layout-emulator.ts +++ b/frontend/src/ts/test/layout-emulator.ts @@ -3,6 +3,9 @@ import * as Misc from "../utils/misc"; import * as JSONData from "../utils/json-data"; import { capsState } from "./caps-warning"; import * as Notifications from "../elements/notifications"; +import * as KeyConverter from "../utils/key-converter"; + +import { getActiveFunboxNames } from "./funbox/list"; let isAltGrPressed = false; const isPunctuationPattern = /\p{P}/u; @@ -41,6 +44,11 @@ export async function getCharFromEvent( return null; } + const funbox = getActiveFunboxNames().includes("layout_mirror"); + if (funbox) { + layout = KeyConverter.mirrorLayoutKeys(layout); + } + let keyEventCodes: string[] = []; if (layout.type === "ansi") { diff --git a/frontend/src/ts/utils/key-converter.ts b/frontend/src/ts/utils/key-converter.ts index 7f34677b6..0acabb4d7 100644 --- a/frontend/src/ts/utils/key-converter.ts +++ b/frontend/src/ts/utils/key-converter.ts @@ -280,3 +280,36 @@ export function keycodeToKeyboardSide(keycode: Keycode): { return { leftSide: left, rightSide: right }; } + +/** + * Returns a copy of the given layout with the rows mirrored + * @param layout Layout object from our JSON data (e.g., `layouts["qwerty"]`) + * @returns layout Layout object from our JSON data (e.g., `layouts["qwerty"]`) + */ +export function mirrorLayoutKeys(layout: JSONData.Layout): JSONData.Layout { + const reverse_index = [11, 10, 10, 10, 10]; + const mirror_keys: JSONData.Keys = { + row1: [ + ...[...layout.keys.row1.slice(0, reverse_index[0])].reverse(), + ...layout.keys.row1.slice(reverse_index[0]), + ], + row2: [ + ...[...layout.keys.row2.slice(0, reverse_index[1])].reverse(), + ...layout.keys.row2.slice(reverse_index[1]), + ], + row3: [ + ...[...layout.keys.row3.slice(0, reverse_index[2])].reverse(), + ...layout.keys.row3.slice(reverse_index[2]), + ], + row4: [ + ...[...layout.keys.row4.slice(0, reverse_index[3])].reverse(), + ...layout.keys.row4.slice(reverse_index[3]), + ], + row5: [ + ...[...layout.keys.row5.slice(0, reverse_index[4])].reverse(), + ...layout.keys.row5.slice(reverse_index[4]), + ], + }; + const layoutCopy: JSONData.Layout = { ...layout, keys: mirror_keys }; + return layoutCopy; +} diff --git a/packages/funbox/src/list.ts b/packages/funbox/src/list.ts index bb8947204..5ea4a20c5 100644 --- a/packages/funbox/src/list.ts +++ b/packages/funbox/src/list.ts @@ -62,7 +62,6 @@ const list: Record = { }, frontendFunctions: ["applyConfig", "rememberSettings"], }, - tts: { canGetPb: true, difficultyLevel: 1, @@ -130,6 +129,14 @@ const list: Record = { frontendFunctions: ["alterText"], name: "capitals", }, + layout_mirror: { + description: "Mirror the keyboard layout", + canGetPb: true, + difficultyLevel: 1, + properties: ["changesLayout"], + frontendFunctions: ["applyConfig", "rememberSettings"], + name: "layout_mirror", + }, layoutfluid: { description: "Switch between layouts specified below proportionately to the length of the test.", diff --git a/packages/funbox/src/types.ts b/packages/funbox/src/types.ts index ff4463b2a..f9f065e85 100644 --- a/packages/funbox/src/types.ts +++ b/packages/funbox/src/types.ts @@ -10,6 +10,7 @@ export type FunboxName = | "arrows" | "rAnDoMcAsE" | "capitals" + | "layout_mirror" | "layoutfluid" | "earthquake" | "space_balls"