From 50639faa1d9f6e9c47158767cdaf7a26c2509b9a Mon Sep 17 00:00:00 2001 From: Sergi Meseguer Date: Tue, 19 Nov 2024 00:45:06 +0100 Subject: [PATCH] impr(layouts): add basic support for thumb alpha keys (@zigotica) (#6023) --- frontend/scripts/json-validation.cjs | 8 +-- frontend/src/styles/keymap.scss | 104 +++++++++++++++++++++++---- frontend/src/ts/elements/keymap.ts | 87 +++++++++++++++++++--- frontend/static/layouts/_list.json | 55 ++++++++++++++ 4 files changed, 227 insertions(+), 27 deletions(-) diff --git a/frontend/scripts/json-validation.cjs b/frontend/scripts/json-validation.cjs index 2fd24b947f11..67ec3e375022 100644 --- a/frontend/scripts/json-validation.cjs +++ b/frontend/scripts/json-validation.cjs @@ -236,9 +236,9 @@ function validateOthers() { }, row5: { type: "array", - items: { type: "string", minLength: 1, maxLength: 1 }, + items: { type: "string", minLength: 1, maxLength: 2 }, minItems: 1, - maxItems: 1, + maxItems: 2, }, }, required: ["row1", "row2", "row3", "row4", "row5"], @@ -280,9 +280,9 @@ function validateOthers() { }, row5: { type: "array", - items: { type: "string", minLength: 1, maxLength: 1 }, + items: { type: "string", minLength: 1, maxLength: 2 }, minItems: 1, - maxItems: 1, + maxItems: 2, }, }, required: ["row1", "row2", "row3", "row4", "row5"], diff --git a/frontend/src/styles/keymap.scss b/frontend/src/styles/keymap.scss index d4148435a08b..078df6d6ceb8 100644 --- a/frontend/src/styles/keymap.scss +++ b/frontend/src/styles/keymap.scss @@ -101,7 +101,7 @@ .r5 { display: grid; grid-template-columns: 3.5fr 6fr 3.5fr; - font-size: 0.5rem; + font-size: 1rem; // &.matrixSpace { // // grid-template-columns: 6.75fr 1.9fr 6.75fr; // grid-template-columns: 6.9fr 4.6fr 6.9fr; // wider spacebar @@ -110,6 +110,24 @@ // // grid-template-columns: 6.75fr 1.9fr 6.75fr; // grid-template-columns: 4fr 7.5fr 4fr; // } + .keySpace { + // since we can potentially have alphas in r5, + // we keep font-size: 1rem; for alphas to look the same as other rows, + // but reduce it again to 0.5rem for space, so layout name fits. + font-size: 0.5rem; + } + + &[data-row5-has-alpha="true"] { + // space-alpha + &[data-row5-grid="3-1"] { + grid-template-columns: 4fr 4fr 1fr 4fr; + } + + // alpha-space + &[data-row5-grid="1-3"] { + grid-template-columns: 4fr 1fr 4fr 4fr; + } + } } &.matrix { .r1, @@ -121,6 +139,18 @@ .r5 { grid-template-columns: 1fr 3fr 4fr 3fr 1fr; + + &[data-row5-has-alpha="true"] { + // space-alpha + &[data-row5-grid="3-1"] { + grid-template-columns: 1fr 2fr 3fr 1fr 5fr; + } + + // alpha-space + &[data-row5-grid="1-3"] { + grid-template-columns: 2fr 3fr 1fr 3fr 3fr; + } + } } } &.split { @@ -152,6 +182,18 @@ } .r5 { grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr; + + &[data-row5-has-alpha="true"] { + // space-alpha + &[data-row5-grid="3-1"] { + grid-template-columns: 5fr 3fr 1fr 1fr 6.5fr; + } + + // alpha-space + &[data-row5-grid="1-3"] { + grid-template-columns: 7fr 1fr 1fr 3fr 4.5fr; + } + } } .keySpace.right { opacity: 1; @@ -180,6 +222,18 @@ .r5 { grid-template-columns: 1fr 2fr 3fr 1fr 3fr 2fr 1fr; + + &[data-row5-has-alpha="true"] { + // space-alpha + &[data-row5-grid="3-1"] { + grid-template-columns: 2fr 1fr 3fr 1fr 1fr 2fr 3fr; + } + + // alpha-space + &[data-row5-grid="1-3"] { + grid-template-columns: 4fr 1fr 1fr 1fr 3fr 1fr 2fr; + } + } } .keySpace.right { opacity: 1; @@ -433,20 +487,42 @@ } .r5 { grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr; - } - .keySpace.right { - opacity: 1; - } - div.keySpace { - transform: rotate(10deg); - margin-left: -5%; - margin-top: 21%; - } - div.keySpace.right { - transform: rotate(-10deg); - margin-left: -33%; - margin-top: 20%; + // rotation/position of r5 keys moved under .r5 styles + // and made generic to left/right to account for alphas + div.keymapKey.left { + transform: rotate(10deg); + margin-left: -5%; + margin-top: 21%; + } + div.keymapKey.right { + opacity: 1; + transform: rotate(-10deg); + margin-left: -33%; + margin-top: 20%; + } + + &[data-row5-has-alpha="true"] { + // space-alpha + &[data-row5-grid="3-1"] { + grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr; + + div.keymapKey.right { + margin-left: -30%; + margin-top: 25%; + } + } + + // alpha-space + &[data-row5-grid="1-3"] { + grid-template-columns: 5fr 3fr 1fr 3fr 4.5fr; + + div.keymapKey.left { + margin-left: 50%; + margin-top: 25%; + } + } + } } div#KeyBackslash.keymapKey { visibility: hidden; diff --git a/frontend/src/ts/elements/keymap.ts b/frontend/src/ts/elements/keymap.ts index 1c2c11e7f842..ed58159afdbd 100644 --- a/frontend/src/ts/elements/keymap.ts +++ b/frontend/src/ts/elements/keymap.ts @@ -113,6 +113,8 @@ export async function refresh( if (Config.keymapMode === "off") return; if (ActivePage.get() !== "test") return; if (!layoutName) return; + let r5_grid = ""; + let hasAlphas = false; try { let layouts; try { @@ -153,6 +155,8 @@ export async function refresh( const isSteno = Config.keymapStyle === "steno" || Config.keymapStyle === "steno_matrix"; + const isAlice = Config.keymapStyle === "alice"; + if (isSteno) { lts = stenoKeys; } @@ -203,19 +207,76 @@ export async function refresh( if (row === "row5") { if (isSteno) continue; - const layoutDisplay = layoutString.replace(/_/g, " "); + let layoutDisplay = layoutString.replace(/_/g, " "); let letterStyle = ""; if (Config.keymapLegendStyle === "blank") { letterStyle = `style="display: none;"`; } + /* ROW 5 in alternate keymaps allow for alphas in thumb keys. + * These keymaps MUST include two keys in row 5, + * an alpha and a space, or a space and an alpha. + * Alpha key is rendered with the regular alpha size. + * Layout name is automatically added in the space key. + * Visual keymap will be: + * 1-3 for 1 alpha and 1 space + * 3-1 for 1 space and 1 alpha + * Together with the data-row5-has-alpha="true", + * these two will be used to edit the CSS grid layout. + * 3-3 for two spaces of size 3. This will not be used to edit CSS, + * since it means a traditional layout, can keep current CSS grid. + * It is just created for simplicity in the for loop below. + * */ + // If only one space, add another + if (rowKeys.length === 1 && rowKeys[0] === " ") { + rowKeys[1] = rowKeys[0]; + } + // If only one alpha, add one space and place it on the left + if (rowKeys.length === 1 && rowKeys[0] !== " ") { + rowKeys[1] = " "; + rowKeys.reverse(); + } + // If two alphas equal, replace one with a space on the left + if ( + rowKeys.length > 1 && + rowKeys[0] !== " " && + rowKeys[0] === rowKeys[1] + ) { + rowKeys[0] = " "; + } + const alphas = (v: string): boolean => v !== " "; + hasAlphas = rowKeys.some(alphas); + rowElement += "
"; - rowElement += `
-
${layoutDisplay}
-
`; - rowElement += `
`; - rowElement += `
-
-
`; + + for (let i = 0; i < rowKeys.length; i++) { + const key = rowKeys[i] as string; + let keyDisplay = key[0] as string; + if (Config.keymapLegendStyle === "uppercase") { + keyDisplay = keyDisplay.toUpperCase(); + } + const keyVisualValue = key.replace('"', """); + // these are used to keep grid layout but magically hide keys using opacity: + let side = i < 1 ? "left" : "right"; + // we won't use this trick for alternate layouts, unless Alice (for rotation): + if (hasAlphas && !isAlice) side = ""; + if (i === 1) { + rowElement += `
`; + r5_grid += "-"; + } + if (keyVisualValue === " ") { + rowElement += `
+
${layoutDisplay}
+
`; + r5_grid += "3"; + // potential second space in next loop iterations will be empty: + layoutDisplay = ""; + } else { + rowElement += `
+
${keyDisplay}
+
`; + r5_grid += "1"; + } + } } else { for (let i = 0; i < rowKeys.length; i++) { if (row === "row2" && i === 12) continue; @@ -309,7 +370,15 @@ export async function refresh( } } - keymapElement += `
${rowElement}
`; + if (row === "row5") { + keymapElement += `
${rowElement}
`; + } else { + keymapElement += `
${rowElement}
`; + } } // ); diff --git a/frontend/static/layouts/_list.json b/frontend/static/layouts/_list.json index 67a0682ef175..f26065dccc04 100644 --- a/frontend/static/layouts/_list.json +++ b/frontend/static/layouts/_list.json @@ -2112,5 +2112,60 @@ "row4": [",<", "/?", ".>", "hH", ";:", "jJ", "yY", "kK", "xX", "wW"], "row5": [" "] } + }, + "anishtro": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["qQ", "lL", "uU", "cC", "jJ", "kK", "pP", "mM", "wW", ";:", "[{", "]}", "\\|"], + "row3": ["aA", "nN", "iI", "sS", "vV", "bB", "hH", "tT", "rR", "oO", "'\""], + "row4": [",<", ".>", "yY", "gG", "xX", "zZ", "fF", "dD", "'\"", "-_"], + "row5": ["eE", " "] + } + }, + "BEAKL_Zi": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["zZ", "yY", "oO", "uU", ";:", "gG", "dD", "nN", "mM", "xX", "[{", "]}", "\\|"], + "row3": ["qQ", "hH", "eE", "aA", ".>", "cC", "tT", "rR", "sS", "wW", "'\""], + "row4": ["jJ", "-_", "'\"", "kK", ",<", "bB", "pP", "lL", "fF", "vV"], + "row5": ["iI", " "] + } + }, + "MALTRON": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["qQ", "pP", "yY", "cC", "bB", "vV", "mM", "uU", "zZ", "lL", "[{", "]}", "\\|"], + "row3": ["aA", "nN", "iI", "sS", "fF", "dD", "tT", "hH", "oO", "rR", "'\""], + "row4": [",<", ".>", "jJ", "gG", "'\"", "/?", "wW", "kK", "-_", "xX"], + "row5": ["eE", " "] + } + }, + "PRSTEN": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["`~", "wW", "cC", "dD", "fF", "qQ", "lL", "uU", "yY", ";:", "[{", "]}", "\\|"], + "row3": ["pP", "rR", "sS", "tT", "gG", "mM", "nN", "aA", "iI", "oO", "'\""], + "row4": ["xX", "hH", "vV", "bB", "[{", ",<", "jJ", "kK", "zZ", ".>"], + "row5": [" ", "eE"] + } + }, + "RSTHD": { + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": ["`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+"], + "row2": ["jJ", "cC", "yY", "fF", "kK", "zZ", "lL", ",<", "uU", "qQ", "[{", "]}", "\\|"], + "row3": ["rR", "sS", "tT", "hH", "dD", "mM", "nN", "aA", "iI", "oO", "'\""], + "row4": ["/?", "vV", "gG", "pP", "bB", "xX", "wW", ".>", ";:", "-_"], + "row5": ["eE", " "] + } } }