diff --git a/src/api/backup/Backup.ts b/src/api/backup/Backup.ts index 0a93d686..cee53329 100644 --- a/src/api/backup/Backup.ts +++ b/src/api/backup/Backup.ts @@ -6,7 +6,14 @@ import { Neuron } from "@Renderer/types/neurons"; import { BackupType } from "@Renderer/types/backups"; import { VirtualType } from "@Renderer/types/virtual"; import Device from "../comms/Device"; -import { rgb2w } from "../color"; +import { + convertColormapRtoR2, + convertKeymapRtoR2, + convertPaletteRtoR2, + parseColormapRaw, + parseKeymapRaw, + parsePaletteRaw, +} from "../parsers"; // eslint-disable-next-line @typescript-eslint/no-var-requires const glob = require(`glob`); @@ -288,7 +295,7 @@ export default class Backup { static convertRaiseToRaise2 = (backup: BackupType, dev: Device) => { log.info("converting Raise Backup to Raise2"); const keyLayerSize = 80; - const ColorLayerSize = 132; + const colorLayerSize = 132; const localBackup: BackupType = JSON.parse(JSON.stringify(backup)); localBackup.neuron.device = dev.device; @@ -296,123 +303,15 @@ export default class Backup { const paletteIndex = localBackup.backup.findIndex(c => c.command === "palette"); const colormapIndex = localBackup.backup.findIndex(c => c.command === "colormap.map"); - const custom = localBackup.backup[keymapIndex].data - .split(" ") - .filter(v => v.length > 0) - .map((k: string) => parseInt(k, 10)) - .reduce((resultArray, item, index) => { - const localResult = resultArray; - const chunkIndex = Math.floor(index / keyLayerSize); + const custom = parseKeymapRaw(localBackup.backup[keymapIndex].data, keyLayerSize); + const palette = parsePaletteRaw(localBackup.backup[paletteIndex].data, false); + const colormap = parseColormapRaw(localBackup.backup[colormapIndex].data, colorLayerSize); - if (!localResult[chunkIndex]) { - localResult[chunkIndex] = []; // start a new chunk - } - localResult[chunkIndex].push(item); - return localResult; - }, []); - // log.info("CONVERSION 1:", paletteIndex, colormapIndex); - const palette = localBackup.backup[paletteIndex].data - .split(" ") - .filter(v => v.length > 0) - .map((k: string) => parseInt(k, 10)) - .reduce((resultArray, item, index) => { - const localResult = resultArray; - const chunkIndex = Math.floor(index / 3); - - if (!localResult[chunkIndex]) { - localResult[chunkIndex] = []; // start a new chunk - } - localResult[chunkIndex].push(item); - return localResult; - }, []) - .map(color => ({ - r: color[0], - g: color[1], - b: color[2], - rgb: `rgb(${color[0]}, ${color[1]}, ${color[2]})`, - })); - // log.info("CONVERSION 2:", palette); - const colormap = localBackup.backup[colormapIndex].data - .split(" ") - .filter(v => v.length > 0) - .map((k: string) => parseInt(k, 10)) - .reduce((resultArray, item, index) => { - const localResult = resultArray; - const chunkIndex = Math.floor(index / ColorLayerSize); - - if (!localResult[chunkIndex]) { - localResult[chunkIndex] = []; // start a new chunk - } - localResult[chunkIndex].push(item); - return localResult; - }, []); - - // log.info("CONVERSION 3:", colormap); - const keymapFinal = custom.map((layer: number[]) => { - let localLayer = [...layer]; - // restoring thumbcluster - const preT = localLayer.slice(0, 69); - const remT = localLayer[69]; - const movT = localLayer.slice(70, 72); - const restT = localLayer.slice(72); - localLayer = preT.concat(movT.concat(remT)).concat(restT); - - // if ansi - if (dev.device.info.keyboardType === "ANSI") { - // Move enter (31<>47) - const symbolK = localLayer[31]; - const enterK = localLayer[47]; - - localLayer[31] = enterK; - localLayer[47] = symbolK; - // Move shift (48<>49) - const shiftK = localLayer[48]; - const extraK = localLayer[49]; - - localLayer[48] = extraK; - localLayer[49] = shiftK; - } - - // if layout !== layout, solve shift & enter - return localLayer; - }); - - // log.info("CONVERSION 4:", colormap); - const colormapFinal = colormap.map((layer: number[]) => { - const color = layer[130]; - const rest = layer.slice(0, -1); - const result = rest.concat(new Array(45).fill(color)); - - if (dev.device.info.keyboardType === "ANSI") { - // Move enter (31<>47) - const symbolC = result[40]; - const enterC = result[48]; - - result[40] = enterC; - result[48] = symbolC; - } - - if (dev.device.info.keyboardType === "ANSI" && backup.neuron.device.info.keyboardType === "ISO") { - // Move shift (48<>49) - const shiftC = result[19]; - const extraC = result[20]; - - result[20] = extraC; - result[19] = shiftC; - } - - return result; - }); - - // log.info("CONVERSION 5:", colormap); - const paletteFinal = palette - .map(color => { - const rgbw = rgb2w(color); - return [rgbw.r, rgbw.g, rgbw.b, rgbw.w]; - }) - .flat() - .map(v => v.toString()) - .join(" "); + const keymapFinal = custom.map((layer: number[]) => convertKeymapRtoR2(layer, dev.device.info.keyboardType)); + const colormapFinal = colormap.map((layer: number[]) => + convertColormapRtoR2(layer, dev.device.info.keyboardType, backup.neuron.device.info.keyboardType), + ); + const paletteFinal = palette.map(color => convertPaletteRtoR2(color)); // log.info("CONVERSION 6:", paletteFinal, colormapFinal); localBackup.backup[colormapIndex].data = colormapFinal @@ -423,7 +322,10 @@ export default class Backup { .flat() .map(k => k.toString()) .join(" "); - localBackup.backup[paletteIndex].data = paletteFinal; + localBackup.backup[paletteIndex].data = paletteFinal + .flat() + .map(v => v.toString()) + .join(" "); log.info("Final Backup:", localBackup.backup); return localBackup.backup; diff --git a/src/api/parsers/colormap.ts b/src/api/parsers/colormap.ts new file mode 100644 index 00000000..fb8249e3 --- /dev/null +++ b/src/api/parsers/colormap.ts @@ -0,0 +1,15 @@ +export const parseColormapRaw = (colormap: string, ColorLayerSize: number): number[][] => + colormap + .split(" ") + .filter(v => v.length > 0) + .map((k: string) => parseInt(k, 10)) + .reduce((resultArray, item, index) => { + const localResult: number[][] = resultArray; + const chunkIndex = Math.floor(index / ColorLayerSize); + + if (!localResult[chunkIndex]) { + localResult[chunkIndex] = []; // start a new chunk + } + localResult[chunkIndex].push(item); + return localResult; + }, []); diff --git a/src/api/parsers/conversions/raiseToRaise2.ts b/src/api/parsers/conversions/raiseToRaise2.ts new file mode 100644 index 00000000..6910f041 --- /dev/null +++ b/src/api/parsers/conversions/raiseToRaise2.ts @@ -0,0 +1,62 @@ +import { PaletteType } from "@Renderer/types/layout"; +import { rgb2w } from "../../color"; + +export const convertKeymapRtoR2 = (layer: number[], keyboardType: string) => { + let localLayer = [...layer]; + // restoring thumbcluster + const preT = localLayer.slice(0, 69); + const remT = localLayer[69]; + const movT = localLayer.slice(70, 72); + const restT = localLayer.slice(72); + localLayer = preT.concat(movT.concat(remT)).concat(restT); + + // if ansi + if (keyboardType === "ANSI") { + // Move enter (31<>47) + const symbolK = localLayer[31]; + const enterK = localLayer[47]; + + localLayer[31] = enterK; + localLayer[47] = symbolK; + // Move shift (48<>49) + const shiftK = localLayer[48]; + const extraK = localLayer[49]; + + localLayer[48] = extraK; + localLayer[49] = shiftK; + } + + // if layout !== layout, solve shift & enter + return localLayer; +}; + +export const convertColormapRtoR2 = (layer: number[], keyboardType: string, backupKeyboardType: string) => { + const color = layer[130]; + const rest = layer.slice(0, -1); + const result = rest.concat(new Array(45).fill(color)); + + if (keyboardType === "ANSI") { + // Move enter (31<>47) + const symbolC = result[40]; + const enterC = result[48]; + + result[40] = enterC; + result[48] = symbolC; + } + + if (keyboardType === "ANSI" && backupKeyboardType === "ISO") { + // Move shift (48<>49) + const shiftC = result[19]; + const extraC = result[20]; + + result[20] = extraC; + result[19] = shiftC; + } + + return result; +}; + +export const convertPaletteRtoR2 = (color: PaletteType) => { + const rgbw = rgb2w(color); + return [rgbw.r, rgbw.g, rgbw.b, rgbw.w]; +}; diff --git a/src/api/parsers/index.ts b/src/api/parsers/index.ts new file mode 100644 index 00000000..a092943c --- /dev/null +++ b/src/api/parsers/index.ts @@ -0,0 +1,23 @@ +// Parsers +import { parseKeymapRaw, serializeKeymap } from "./keymap"; +import { parsePaletteRaw } from "./palette"; +import { parseColormapRaw } from "./colormap"; +import { parseMacrosRaw, serializeMacros } from "./macros"; +import { parseSuperkeysRaw, serializeSuperkeys } from "./superkeys"; + +// Converters +import { convertKeymapRtoR2, convertColormapRtoR2, convertPaletteRtoR2 } from "./conversions/raiseToRaise2"; + +export { + parseKeymapRaw, + serializeKeymap, + parsePaletteRaw, + parseColormapRaw, + parseMacrosRaw, + serializeMacros, + parseSuperkeysRaw, + serializeSuperkeys, + convertKeymapRtoR2, + convertColormapRtoR2, + convertPaletteRtoR2, +}; diff --git a/src/api/parsers/keymap.ts b/src/api/parsers/keymap.ts new file mode 100644 index 00000000..41287f2e --- /dev/null +++ b/src/api/parsers/keymap.ts @@ -0,0 +1,26 @@ +import { KeyType } from "@Renderer/types/layout"; +import { KeymapDB } from "../keymap"; + +const keymapDB = new KeymapDB(); + +export const parseKeymapRaw = (keymap: string, keyLayerSize: number): number[][] => + keymap + .split(" ") + .filter(v => v.length > 0) + .map((k: string) => parseInt(k, 10)) + .reduce((resultArray, item, index) => { + const localResult = resultArray; + const chunkIndex = Math.floor(index / keyLayerSize); + + if (!localResult[chunkIndex]) { + localResult[chunkIndex] = []; // start a new chunk + } + localResult[chunkIndex].push(item); + return localResult; + }, []); + +export const serializeKeymap = (keymap: KeyType[][]) => + keymap + .flat() + .map(k => (typeof k === "number" ? String(k) : keymapDB.serialize(k).toString())) + .join(" "); diff --git a/src/api/parsers/macros.ts b/src/api/parsers/macros.ts new file mode 100644 index 00000000..39dbcec4 --- /dev/null +++ b/src/api/parsers/macros.ts @@ -0,0 +1,121 @@ +/* eslint-disable no-bitwise */ +import { MacroActionsType, MacrosType } from "@Renderer/types/macros"; +import { KeymapDB } from "../keymap"; + +const macrosEraser = (tMem: number) => Array(tMem).fill("255").join(" "); + +export const parseMacrosRaw = (raw: string, storedMacros?: MacrosType[]) => { + const keymapDB = new KeymapDB(); + const macrosArray = raw.split(" 0 0")[0].split(" ").map(Number); + + // Translate received macros to human readable text + const macros: MacrosType[] = []; + let iter = 0; + // macros are `0` terminated or when end of macrosArray has been reached, the outer loop + // must cycle once more than the inner + while (iter <= macrosArray.length) { + const actions: MacroActionsType[] = []; + while (iter < macrosArray.length) { + const type = macrosArray[iter]; + if (type === 0) { + break; + } + + switch (type) { + case 1: + actions.push({ + type, + keyCode: [ + (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], + (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], + ], + }); + break; + case 2: + case 3: + case 4: + case 5: + actions.push({ type, keyCode: (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)] }); + break; + case 6: + case 7: + case 8: + actions.push({ type, keyCode: macrosArray[(iter += 1)] }); + break; + default: + break; + } + + iter += 1; + } + macros.push({ + actions, + name: "", + macro: "", + }); + iter += 1; + } + macros.forEach((m, idx) => { + const aux = m; + aux.id = idx; + macros[idx] = aux; + }); + + // TODO: Check if stored macros match the received ones, if they match, retrieve name and apply it to current macros + const stored = storedMacros; + if (stored === undefined || stored.length === 0) { + return macros; + } + return macros.map((macro, i) => { + if (stored.length < i) { + return macro; + } + + return { + ...macro, + name: stored[i]?.name, + macro: macro.actions.map(k => keymapDB.parse(k.keyCode as number).label).join(" "), + }; + }); +}; + +export const serializeMacros = (macros: MacrosType[], tMem: number) => { + // log.info( + // "Macros map function", + // macros, + // macrosEraser, + // macros.length === 0, + // macros.length === 1 && Array.isArray(macros[0].actions), + // ); + if (macros.length === 0 || (macros.length === 1 && !Array.isArray(macros[0].actions))) { + return macrosEraser(tMem); + } + const mapAction = (action: MacroActionsType): number[] => { + switch (action.type) { + case 1: + return [ + action.type, + (action.keyCode as number[])[0] >> 8, + (action.keyCode as number[])[0] & 255, + (action.keyCode as number[])[1] >> 8, + (action.keyCode as number[])[1] & 255, + ]; + case 2: + case 3: + case 4: + case 5: + return [action.type, (action.keyCode as number) >> 8, (action.keyCode as number) & 255]; + default: + return [action.type, action.keyCode as number]; + } + }; + const result: string = macros + .map(macro => macro.actions.map((action: MacroActionsType) => mapAction(action)).concat([0])) + .flat() + .concat([0]) + .join(" ") + .split(",") + .join(" "); + // log.info("MACROS GOING TO BE SAVED", result); + return result; +}; diff --git a/src/api/parsers/palette.ts b/src/api/parsers/palette.ts new file mode 100644 index 00000000..1b7f7b26 --- /dev/null +++ b/src/api/parsers/palette.ts @@ -0,0 +1,47 @@ +import { rgbw2b } from "../color"; + +export const parsePaletteRaw = (palette: string, isRGBW: boolean) => + isRGBW + ? palette + .split(" ") + .filter(v => v.length > 0) + .map((k: string) => parseInt(k, 10)) + .reduce((resultArray, item, index) => { + const localResult = resultArray; + const chunkIndex = Math.floor(index / 4); + + if (!localResult[chunkIndex]) { + localResult[chunkIndex] = []; // start a new chunk + } + localResult[chunkIndex].push(item); + return localResult; + }, []) + .map(color => { + const coloraux = rgbw2b({ r: color[0], g: color[1], b: color[2], w: color[3] }); + return { + r: coloraux.r, + g: coloraux.g, + b: coloraux.b, + rgb: coloraux.rgb, + }; + }) + : palette + .split(" ") + .filter(v => v.length > 0) + .map((k: string) => parseInt(k, 10)) + .reduce((resultArray, item, index) => { + const localResult = resultArray; + const chunkIndex = Math.floor(index / 3); + + if (!localResult[chunkIndex]) { + localResult[chunkIndex] = []; // start a new chunk + } + localResult[chunkIndex].push(item); + return localResult; + }, []) + .map(color => ({ + r: color[0], + g: color[1], + b: color[2], + rgb: `rgb(${color[0]}, ${color[1]}, ${color[2]})`, + })); diff --git a/src/api/parsers/superkeys.ts b/src/api/parsers/superkeys.ts new file mode 100644 index 00000000..b5f7e94c --- /dev/null +++ b/src/api/parsers/superkeys.ts @@ -0,0 +1,79 @@ +import log from "electron-log/renderer"; +import { SuperkeysType } from "@Renderer/types/superkeys"; + +export const parseSuperkeysRaw = (raw: string, stored: SuperkeysType[]) => { + const superArray = raw.split(" 0 0")[0].split(" ").map(Number); + + let superkey: number[] = []; + const superkeys: SuperkeysType[] = []; + let iter = 0; + let superindex = 0; + + if (superArray.length < 1) { + log.warn("Discarded Superkeys due to short length of string", raw, raw.length); + return []; + } + // log.info(raw, raw.length); + while (superArray.length > iter) { + // log.info(iter, raw[iter], superkey); + if (superArray[iter] === 0) { + superkeys[superindex] = { actions: superkey, name: "", id: superindex }; + superindex += 1; + superkey = []; + } else { + superkey.push(superArray[iter]); + } + iter += 1; + } + superkeys[superindex] = { actions: superkey, name: "", id: superindex }; + + if (superkeys[0].actions.length === 0 || superkeys[0].actions.length > 5) { + log.warn(`Superkeys were empty`); + return []; + } + // log.info(`Got Superkeys:${JSON.stringify(superkeys)} from ${raw}`); + // TODO: Check if stored superKeys match the received ones, if they match, retrieve name and apply it to current superKeys + let finalSuper: SuperkeysType[] = []; + finalSuper = superkeys.map((superky, i) => { + const superk = superky; + if (stored.length > i && stored.length > 0) { + const aux = superk; + aux.name = stored[i].name; + return aux; + } + return superk; + }); + log.info("final superkeys", finalSuper); + return finalSuper; +}; + +export const serializeSuperkeys = (superkeys: SuperkeysType[]) => { + if ( + superkeys.length === 0 || + (superkeys.length === 1 && superkeys[0].actions.length === 0) || + (superkeys.length === 1 && superkeys[0].actions.length === 1 && superkeys[0].actions[0] === 0) + ) { + return Array(512).fill("65535").join(" "); + } + let keyMap = JSON.parse(JSON.stringify(superkeys)); + // log.info("First", JSON.stringify(keyMap)); + keyMap = keyMap.map((sky: SuperkeysType) => { + const sk = sky; + sk.actions = sk.actions.map(act => { + if (act === 0 || act === null || act === undefined) return 1; + return act; + }); + if (sk.actions.length < 5) sk.actions = sk.actions.concat(Array(5 - sk.actions.length).fill(1)); + return sk; + }); + // log.info("Third", JSON.parse(JSON.stringify(keyMap))); + const mapped = keyMap + .map((superkey: SuperkeysType) => superkey.actions.filter(act => act !== 0).concat([0])) + .flat() + .concat([0]) + .join(" ") + .split(",") + .join(" "); + log.info("Mapped superkeys: ", mapped, keyMap); + return mapped; +}; diff --git a/src/renderer/modules/KeysTabs/SuperkeysTab.tsx b/src/renderer/modules/KeysTabs/SuperkeysTab.tsx index 50ab3746..179f412f 100644 --- a/src/renderer/modules/KeysTabs/SuperkeysTab.tsx +++ b/src/renderer/modules/KeysTabs/SuperkeysTab.tsx @@ -181,23 +181,22 @@ const SuperkeysTab = ({ macros, keyCode, onKeySelect, superkeys, disabled }: Sup {superkeys[selected.current] !== undefined ? (
{superKeysActions.map((item, index) => ( - <> +
} title={item.title} description="" elementActive={false} - onClick={() => console.log("onClick")} + onClick={() => "onClick"} macros={macros} keymapDB={keymapDB} - updateAction={() => console.log("update action")} + updateAction={() => "update action"} variant="subtle" /> - +
))}
) : null} diff --git a/src/renderer/types/dygmaDefs.ts b/src/renderer/types/dygmaDefs.ts index 01a3e746..322d9f21 100644 --- a/src/renderer/types/dygmaDefs.ts +++ b/src/renderer/types/dygmaDefs.ts @@ -1,14 +1,16 @@ +export type DygmaDeviceInfoType = { + vendor: "Dygma"; + product: "Raise" | "Defy" | "Raise2"; + keyboardType: string; + displayName: string; + urls: { + name: string; + url: string; + }[]; +}; + export type DygmaDeviceType = { - info: { - vendor: "Dygma"; - product: "Raise" | "Defy" | "Raise2"; - keyboardType: string; - displayName: string; - urls: { - name: string; - url: string; - }[]; - }; + info: DygmaDeviceInfoType; usb: { vendorId: number; productId: number; diff --git a/src/renderer/types/macroEditor.ts b/src/renderer/types/macroEditor.ts index 00325468..9902a4b9 100644 --- a/src/renderer/types/macroEditor.ts +++ b/src/renderer/types/macroEditor.ts @@ -34,8 +34,9 @@ export interface MacroEditorInitialStateType { macros: MacrosType[]; superkeys: SuperkeysType[]; storedMacros: MacrosType[]; + storedSuper: SuperkeysType[]; neurons: Neuron[]; - neuronIdx: number; + neuronID: string; maxMacros: number; modified: boolean; selectedMacro: number; diff --git a/src/renderer/types/superkeyseditor.ts b/src/renderer/types/superkeyseditor.ts index 5b9db43d..89312b22 100644 --- a/src/renderer/types/superkeyseditor.ts +++ b/src/renderer/types/superkeyseditor.ts @@ -32,6 +32,7 @@ export interface SuperkeysEditorInitialStateType { macros: MacrosType[]; superkeys: SuperkeysType[]; storedMacros: MacrosType[]; + storedSuper: SuperkeysType[]; neurons: Neuron[]; neuronID: string; kbtype: string; diff --git a/src/renderer/views/LayoutEditor.tsx b/src/renderer/views/LayoutEditor.tsx index 82fcd880..ef3d33d3 100644 --- a/src/renderer/views/LayoutEditor.tsx +++ b/src/renderer/views/LayoutEditor.tsx @@ -35,7 +35,7 @@ import { useDevice } from "@Renderer/DeviceContext"; import { LayerType, Neuron } from "@Renderer/types/neurons"; import { ColormapType, KeymapType, KeyType, LayoutEditorProps, PaletteType, SegmentedKeyType } from "@Renderer/types/layout"; import { SuperkeysType } from "@Renderer/types/superkeys"; -import { MacroActionsType, MacrosType } from "@Renderer/types/macros"; +import { MacrosType } from "@Renderer/types/macros"; import { DeviceClass } from "@Renderer/types/devices"; // Modules @@ -53,10 +53,21 @@ import { i18n } from "@Renderer/i18n"; import Store from "@Renderer/utils/Store"; import getLanguage from "@Renderer/utils/language"; import { ClearLayerDialog } from "@Renderer/components/molecules/CustomModal/ClearLayerDialog"; +import { DygmaDeviceInfoType } from "@Renderer/types/dygmaDefs"; import BlankTable from "../../api/keymap/db/blanks"; import Keymap, { KeymapDB } from "../../api/keymap"; -import { rgb2w, rgbw2b } from "../../api/color"; +import { rgb2w } from "../../api/color"; import Backup from "../../api/backup"; +import { + convertColormapRtoR2, + convertKeymapRtoR2, + parseColormapRaw, + parseKeymapRaw, + parseMacrosRaw, + parsePaletteRaw, + parseSuperkeysRaw, + serializeKeymap, +} from "../../api/parsers"; const store = Store.getStore(); @@ -519,237 +530,15 @@ const LayoutEditor = (props: LayoutEditorProps) => { store.set("neurons", neurons); }; - const superTranslator = (raw: string, sSuper: SuperkeysType[]): SuperkeysType[] => { - const superArray = raw.split(" 0 0")[0].split(" ").map(Number); - - let skAction: number[] = []; - const sKeys: SuperkeysType[] = []; - let iter = 0; - let superindex = 0; - - if (superArray.length < 1) { - log.info("Discarded Superkeys due to short length of string", raw, raw.length); - return []; - } - while (superArray.length > iter) { - // log.info(iter, raw[iter], superkey); - if (superArray[iter] === 0) { - sKeys[superindex] = { actions: skAction, name: "", id: superindex }; - superindex += 1; - skAction = []; - } else { - skAction.push(superArray[iter]); - } - iter += 1; - } - sKeys[superindex] = { actions: skAction, name: "", id: superindex }; - - if (sKeys[0].actions.length === 0 || sKeys[0].actions.length > 5) { - log.info(`Superkeys were empty`); - return []; - } - log.info(`Got Superkeys:${JSON.stringify(sKeys)} from ${raw}`); - // TODO: Check if stored superKeys match the received ones, if they match, retrieve name and apply it to current superKeys - let finalSuper: SuperkeysType[] = []; - finalSuper = sKeys.map((superky, i) => { - const superk = superky; - superk.id = i; - if (sSuper.length > i && sSuper.length > 0) { - const aux = superk; - aux.name = sSuper[i].name; - return aux; - } - return superk; - }); - log.info("final superkeys", finalSuper); - return finalSuper; - }; - - const macroTranslator = useCallback( - (raw: string | number[], storeMacros: MacrosType[]) => { - if (raw === "") { - return [ - { - actions: [ - { keyCode: 229, type: 6, id: 0 }, - { keyCode: 11, type: 8, id: 1 }, - { keyCode: 229, type: 7, id: 2 }, - { keyCode: 8, type: 8, id: 3 }, - { keyCode: 28, type: 8, id: 4 }, - { keyCode: 54, type: 8, id: 5 }, - { keyCode: 44, type: 8, id: 6 }, - { keyCode: 229, type: 6, id: 7 }, - { keyCode: 7, type: 8, id: 8 }, - { keyCode: 229, type: 7, id: 9 }, - { keyCode: 28, type: 8, id: 10 }, - { keyCode: 10, type: 8, id: 11 }, - { keyCode: 16, type: 8, id: 12 }, - { keyCode: 4, type: 8, id: 13 }, - { keyCode: 23, type: 8, id: 14 }, - { keyCode: 8, type: 8, id: 15 }, - ], - id: 0, - macro: "RIGHT SHIFT H RIGHT SHIFT E Y , SPACE RIGHT SHIFT D RIGHT SHIFT Y G M A T E", - name: "Hey, Dygmate!", - }, - ]; - } - // Translate received macros to human readable text - let i = 0; - let iter = 0; - let kcs = 0; - let type = 0; - let keyCode = []; - let actions = new Array(); - const mcros = new Array(); - actions = []; - while (raw.length > iter) { - if (kcs > 0) { - keyCode.push((raw as number[])[iter]); - kcs -= 1; - } else { - if (iter !== 0 && type !== 0) { - actions.push({ - type, - keyCode, - id: undefined, - }); - keyCode = []; - } - type = (raw as number[])[iter]; - switch (type) { - case 0: - kcs = 0; - mcros[i] = { actions, id: i, name: "", macro: "" }; - i += 1; - actions = []; - break; - case 1: - kcs = 4; - break; - case 2: - case 3: - case 4: - case 5: - kcs = 2; - break; - default: - kcs = 1; - } - } - iter += 1; - } - actions.push({ - type, - keyCode, - id: undefined, - }); - mcros[i] = { - actions, - id: i, - name: "", - macro: "", - }; - const localMacros = mcros.map(m => { - const aux: MacroActionsType[] = m.actions.map((action, idx) => { - if (Array.isArray(action.keyCode)) - switch (action.type) { - case 1: - return { - type: action.type, - keyCode: [(action.keyCode[0] << 8) + action.keyCode[1], (action.keyCode[2] << 8) + action.keyCode[3]], - id: idx, - }; - case 2: - case 3: - case 4: - case 5: - return { - type: action.type, - keyCode: (action.keyCode[0] << 8) + action.keyCode[1], - id: idx, - }; - default: - return { - type: action.type, - keyCode: action.keyCode[0], - id: idx, - }; - } - return action; - }); - return { ...m, actions: aux }; - }); - // TODO: Check if stored macros match the received ones, if they match, retrieve name and apply it to current macros - let finalMacros = []; - log.info("Checking Macros", localMacros, storeMacros); - if (storeMacros === undefined) { - return localMacros; - } - finalMacros = localMacros.map((m, idx) => { - if (storeMacros.length > idx && storeMacros.length > 0) { - const aux = m; - aux.name = storeMacros[idx].name; - aux.macro = m.actions.map(k => keymapDB.parse(k.keyCode as number).label).join(" "); - return aux; - } - return m; - }); - - return finalMacros; - }, - [keymapDB], - ); - const getColormap = useCallback(async (): Promise => { const { currentDevice } = state; const layerSize = currentDevice.device.keyboardUnderglow.rows * currentDevice.device.keyboardUnderglow.columns; - const chunk = (a: number[], chunkSize: number) => { - const R = []; - for (let i = 0; i < a.length; i += chunkSize) R.push(a.slice(i, i + chunkSize)); - return R; - }; - const paletteData = (await currentDevice?.command("palette")) as string; const colorMapData = (await currentDevice?.command("colormap.map")) as string; - const plette = - currentDevice?.device.RGBWMode !== true - ? chunk( - paletteData - .split(" ") - .filter((v: string) => v.length > 0) - .map((k: string) => parseInt(k, 10)), - 3, - ).map(color => ({ - r: color[0], - g: color[1], - b: color[2], - rgb: `rgb(${color[0]}, ${color[1]}, ${color[2]})`, - })) - : chunk( - paletteData - .split(" ") - .filter((v: string) => v.length > 0) - .map((k: string) => parseInt(k, 10)), - 4, - ).map(color => { - const coloraux = rgbw2b({ r: color[0], g: color[1], b: color[2], w: color[3] }); - return { - r: coloraux.r, - g: coloraux.g, - b: coloraux.b, - rgb: coloraux.rgb, - }; - }); - - const colMap = chunk( - colorMapData - .split(" ") - .filter((v: string) => v.length > 0) - .map((k: string) => parseInt(k, 10)), - layerSize, - ); + const plette = parsePaletteRaw(paletteData, currentDevice?.device.RGBWMode); + log.info("PARSED PALETTE: ", paletteData, plette, currentDevice?.device.RGBWMode); + const colMap = parseColormapRaw(colorMapData, layerSize); return { palette: plette, @@ -941,34 +730,8 @@ const LayoutEditor = (props: LayoutEditorProps) => { }; const layerSize = currentDevice.device.keyboard.rows * currentDevice.device.keyboard.columns; - KeyMap.custom = custom - .split(" ") - .filter(v => v.length > 0) - .map((k: string) => keymapDB.parse(parseInt(k, 10))) - .reduce((resultArray, item, index) => { - const localResult = resultArray; - const chunkIndex = Math.floor(index / layerSize); - - if (!localResult[chunkIndex]) { - localResult[chunkIndex] = []; // start a new chunk - } - localResult[chunkIndex].push(item); - return localResult; - }, []); - KeyMap.default = defaults - .split(" ") - .filter(v => v.length > 0) - .map((k: string) => keymapDB.parse(parseInt(k, 10))) - .reduce((resultArray, item, index) => { - const localResult = resultArray; - const chunkIndex = Math.floor(index / layerSize); - - if (!localResult[chunkIndex]) { - localResult[chunkIndex] = []; // start a new chunk - } - localResult[chunkIndex].push(item); - return localResult; - }, []); + KeyMap.custom = parseKeymapRaw(custom, layerSize).map(l => l.map((k: number) => keymapDB.parse(k))); + KeyMap.default = parseKeymapRaw(defaults, layerSize).map(l => l.map((k: number) => keymapDB.parse(k))); KeyMap.onlyCustom = onlyCustom; let empty = true; @@ -999,18 +762,13 @@ const LayoutEditor = (props: LayoutEditorProps) => { // loading Macros setScanningStep(7); - let raw: string | number[] = (await currentDevice?.command("macros.map")) as string; - if (raw.search(" 0 0") !== -1) { - raw = raw.split(" 0 0")[0].split(" ").map(Number); - } else { - raw = ""; - } - const parsedMacros = macroTranslator(raw, neuronData.storedMacros); + const rawMacros = (await currentDevice?.command("macros.map")) as string; + const parsedMacros = parseMacrosRaw(rawMacros, neuronData.storedMacros); // Loading Superkeys setScanningStep(8); - const raw2: string = (await currentDevice?.command("superkeys.map")) as string; - const parsedSuper = superTranslator(raw2, neuronData.storedSuper); + const rawSuper = (await currentDevice?.command("superkeys.map")) as string; + const parsedSuper = parseSuperkeysRaw(rawSuper, neuronData.storedSuper); setScanningStep(9); let showMM = false; @@ -1050,7 +808,7 @@ const LayoutEditor = (props: LayoutEditorProps) => { onDisconnect(); } }, - [state, setLoading, AnalizeChipID, restoredOk, getColormap, macroTranslator, handleSetRestoredOk, keymapDB, onDisconnect], + [state, setLoading, AnalizeChipID, restoredOk, getColormap, handleSetRestoredOk, keymapDB, onDisconnect], ); const onKeyChange = (keyCode: number) => { @@ -1158,8 +916,7 @@ const LayoutEditor = (props: LayoutEditorProps) => { try { setLoading(true); setIsSaving(true); - const args = flatten(keymap.custom).map(k => keymapDB.serialize(k).toString()); - await currentDevice?.command("keymap.custom", ...args); + await currentDevice?.command("keymap.custom", serializeKeymap(keymap.custom)); await currentDevice?.command("keymap.onlyCustom", keymap.onlyCustom ? "1" : "0"); await updateColormap(currentDevice, colorMap); await updatePalette(currentDevice, palette); @@ -1429,12 +1186,15 @@ const LayoutEditor = (props: LayoutEditorProps) => { }; const importLayer = (data: { + device: DygmaDeviceInfoType; + language: string; layerNames: LayerType[]; layerName: string; keymap: KeyType[]; colormap: number[]; palette: PaletteType[]; }) => { + const { currentDevice } = state; log.info("not loading the palette: ", palette); // if (data.palette.length > 0) state.palette = data.palette; const lNames = layerNames.slice(); @@ -1447,19 +1207,30 @@ const LayoutEditor = (props: LayoutEditorProps) => { } setLayerNames(lNames); } - const parsedKeymap = data.keymap.map(key => { - let localKey = key; - if (typeof localKey.extraLabel === "object" || typeof localKey.label === "object") - localKey = keymapDB.parse(localKey.keyCode); - return localKey; - }); + let cleanKeymap: KeyType[]; + let cleanColormap: number[]; + if (currentDevice?.device.info.product === "Raise2" && data.device.product === "Raise") { + cleanKeymap = convertKeymapRtoR2( + data.keymap.map(k => k.keyCode), + currentDevice?.device.info.keyboardType, + ).map(k => keymapDB.parse(k)); + cleanColormap = convertColormapRtoR2(data.colormap, currentDevice?.device.info.keyboardType, data.device.keyboardType); + } else { + cleanKeymap = data.keymap.map(key => { + let localKey = key; + if (typeof localKey.extraLabel === "object" || typeof localKey.label === "object") + localKey = keymapDB.parse(localKey.keyCode); + return localKey; + }); + cleanColormap = data.colormap; + } if (data.keymap.length > 0 && data.colormap.length > 0) { if (keymap.onlyCustom) { if (currentLayer >= 0) { const newKeymap = keymap.custom.slice(); - newKeymap[currentLayer] = parsedKeymap; + newKeymap[currentLayer] = cleanKeymap; const newColormap = colorMap.slice(); - newColormap[currentLayer] = data.colormap.slice(); + newColormap[currentLayer] = cleanColormap; setKeymap({ default: keymap.default, custom: newKeymap, @@ -1470,9 +1241,9 @@ const LayoutEditor = (props: LayoutEditorProps) => { } else if (currentLayer >= keymap.default.length) { const defLength = keymap.default.length; const newKeymap = keymap.custom.slice(); - newKeymap[currentLayer - defLength] = parsedKeymap; + newKeymap[currentLayer - defLength] = cleanKeymap; const newColormap = colorMap.slice(); - newColormap[currentLayer - defLength] = data.colormap.slice(); + newColormap[currentLayer - defLength] = cleanColormap; setKeymap({ default: keymap.default, diff --git a/src/renderer/views/MacroEditor.tsx b/src/renderer/views/MacroEditor.tsx index e65e2e70..20fa8205 100644 --- a/src/renderer/views/MacroEditor.tsx +++ b/src/renderer/views/MacroEditor.tsx @@ -34,7 +34,6 @@ import { } from "@Renderer/types/macroEditor"; import { Neuron } from "@Renderer/types/neurons"; import { KeymapType } from "@Renderer/types/layout"; -import { SuperkeysType } from "@Renderer/types/superkeys"; import { MacroActionsType, MacrosType } from "@Renderer/types/macros"; // Components @@ -59,6 +58,14 @@ import Keymap, { KeymapDB } from "../../api/keymap"; import Store from "../utils/Store"; import getLanguage from "../utils/language"; +import { + parseKeymapRaw, + serializeKeymap, + parseMacrosRaw, + parseSuperkeysRaw, + serializeMacros, + serializeSuperkeys, +} from "../../api/parsers"; const store = Store.getStore(); @@ -108,15 +115,14 @@ function MacroEditor(props: MacroEditorProps) { const bkp = new Backup(); const [isSaving, setIsSaving] = useState(false); - const flatten = (arr: unknown[]) => [].concat(...arr); - const initialState: MacroEditorInitialStateType = { keymap: undefined, macros: [], superkeys: [], storedMacros: [], + storedSuper: [], neurons: [], - neuronIdx: 0, + neuronID: "", maxMacros: 128, modified: false, selectedMacro: 0, @@ -138,126 +144,6 @@ function MacroEditor(props: MacroEditorProps) { const { state: deviceState } = useDevice(); const timelineRef = useRef(null); - const superTranslator = (raw: string) => { - const { neurons, neuronIdx } = state; - const superArray = raw.split(" 0 0")[0].split(" ").map(Number); - - let skAction: number[] = []; - const superkeys: SuperkeysType[] = []; - let iter = 0; - let superindex = 0; - - if (superArray.length < 1) { - log.info("Discarded Superkeys due to short length of string", raw, raw.length); - return [{ actions: [53, 2101, 1077, 41, 0], name: "Welcome to superkeys", id: superindex }]; - } - while (superArray.length > iter) { - // log.info(iter, raw[iter], superkey); - if (superArray[iter] === 0) { - superkeys[superindex] = { actions: skAction, name: "", id: superindex }; - superindex += 1; - skAction = []; - } else { - skAction.push(superArray[iter]); - } - iter += 1; - } - superkeys[superindex] = { actions: skAction, name: "", id: superindex }; - - if (superkeys[0].actions.length === 0 || superkeys[0].actions.length > 5) { - log.info(`Superkeys were empty`); - return []; - } - log.info(`Got Superkeys:${JSON.stringify(superkeys)} from ${raw}`); - // TODO: Check if stored superKeys match the received ones, if they match, retrieve name and apply it to current superKeys - let finalSuper: SuperkeysType[] = []; - const stored = neurons[neuronIdx].superkeys; - finalSuper = superkeys.map((superky, i) => { - const superk = superky; - superk.id = i; - if (stored.length > i && stored.length > 0) { - const aux = superk; - aux.name = stored[i].name; - return aux; - } - return superk; - }); - log.info("final superkeys", finalSuper); - return finalSuper; - }; - - const superkeyMap = (superkeys: SuperkeysType[]) => { - if ( - superkeys.length === 0 || - (superkeys.length === 1 && superkeys[0].actions.length === 0) || - (superkeys.length === 1 && superkeys[0].actions.length === 1 && superkeys[0].actions[0] === 0) - ) { - return Array(512).fill("65535").join(" "); - } - let keyMap = JSON.parse(JSON.stringify(superkeys)); - // log.info("First", JSON.stringify(keyMap)); - keyMap = keyMap.map((sky: SuperkeysType) => { - const sk = sky; - sk.actions = sk.actions.map(act => { - if (act === 0 || act === null || act === undefined) return 1; - return act; - }); - if (sk.actions.length < 5) sk.actions = sk.actions.concat(Array(5 - sk.actions.length).fill(1)); - return sk; - }); - const mapped = keyMap - .map((superkey: SuperkeysType) => superkey.actions.filter(act => act !== 0).concat([0])) - .flat() - .concat([0]) - .join(" ") - .split(",") - .join(" "); - log.info("Mapped superkeys: ", mapped, keyMap); - return mapped; - }; - - const macrosMap = (macros: MacrosType[]) => { - const { macrosEraser } = state; - log.info( - "Macros map function", - macros, - macrosEraser, - macros.length === 0, - macros.length === 1 && Array.isArray(macros[0].actions), - ); - if (macros.length === 0 || (macros.length === 1 && !Array.isArray(macros[0].actions))) { - return macrosEraser; - } - const mapAction = (action: MacroActionsType): number[] => { - switch (action.type) { - case 1: - return [ - action.type, - (action.keyCode as number[])[0] >> 8, - (action.keyCode as number[])[0] & 255, - (action.keyCode as number[])[1] >> 8, - (action.keyCode as number[])[1] & 255, - ]; - case 2: - case 3: - case 4: - case 5: - return [action.type, (action.keyCode as number) >> 8, (action.keyCode as number) & 255]; - default: - return [action.type, action.keyCode as number]; - } - }; - const result: string = macros - .map(macro => macro.actions.map((action: MacroActionsType) => mapAction(action)).concat([0])) - .flat() - .concat([0]) - .join(" ") - .split(",") - .join(" "); - log.info("MACROS GOING TO BE SAVED", result); - return result; - }; - const addToActions = (actions: MacroActionsType[]) => { const { startContext } = props; const { macros, selectedMacro } = state; @@ -333,7 +219,7 @@ function MacroEditor(props: MacroEditorProps) { }; const writeMacros = async () => { - const { macros, neurons, neuronIdx, keymap, superkeys } = state; + const { macros, neurons, neuronID, keymap, superkeys } = state; const { setLoading, cancelContext } = props; const { currentDevice } = deviceState; setIsSaving(true); @@ -341,15 +227,15 @@ function MacroEditor(props: MacroEditorProps) { log.info("saving Macros:", macros, keymap, superkeys); const newMacros = macros; const localNeurons = [...neurons]; - localNeurons[neuronIdx].macros = newMacros; + localNeurons[localNeurons.findIndex(n => n.id === neuronID)].macros = newMacros; store.set("neurons", localNeurons); try { - await currentDevice.command("macros.map", macrosMap(newMacros)); - const args = flatten(keymap.custom).map(k => keymapDB.serialize(k).toString()); - await currentDevice.command("keymap.custom", ...args); - await currentDevice.command("superkeys.map", superkeyMap(superkeys)); + await currentDevice.command("macros.map", serializeMacros(newMacros, state.totalMemory)); + log.info(keymap.custom); + await currentDevice.command("keymap.custom", serializeKeymap(keymap.custom)); + await currentDevice.command("superkeys.map", serializeSuperkeys(superkeys)); const commands = await Backup.Commands(currentDevice); - const backup = await bkp.DoBackup(commands, neurons[neuronIdx].id, currentDevice); + const backup = await bkp.DoBackup(commands, neurons[neurons.findIndex(n => n.id === neuronID)].id, currentDevice); Backup.SaveBackup(backup, currentDevice); toast.success(} />, { autoClose: 2000, @@ -531,81 +417,6 @@ function MacroEditor(props: MacroEditorProps) { updateMacros(localMacros); }; - const macroTranslator = (raw: string) => { - const { storedMacros } = state; - const macrosArray = raw.split(" 0 0")[0].split(" ").map(Number); - - // Translate received macros to human readable text - const macros: MacrosType[] = []; - let iter = 0; - // macros are `0` terminated or when end of macrosArray has been reached, the outer loop - // must cycle once more than the inner - while (iter <= macrosArray.length) { - const actions: MacroActionsType[] = []; - while (iter < macrosArray.length) { - const type = macrosArray[iter]; - if (type === 0) { - break; - } - - switch (type) { - case 1: - actions.push({ - type, - keyCode: [ - (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], - (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], - ], - }); - break; - case 2: - case 3: - case 4: - case 5: - actions.push({ type, keyCode: (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)] }); - break; - case 6: - case 7: - case 8: - actions.push({ type, keyCode: macrosArray[(iter += 1)] }); - break; - default: - break; - } - - iter += 1; - } - macros.push({ - actions, - name: "", - macro: "", - }); - iter += 1; - } - macros.forEach((m, idx) => { - const aux = m; - aux.id = idx; - macros[idx] = aux; - }); - - // TODO: Check if stored macros match the received ones, if they match, retrieve name and apply it to current macros - const stored = storedMacros; - if (stored === undefined || stored.length === 0) { - return macros; - } - return macros.map((macro, i) => { - if (stored.length < i) { - return macro; - } - - return { - ...macro, - name: stored[i]?.name, - macro: macro.actions.map(k => keymapDB.parse(k.keyCode as number).label).join(" "), - }; - }); - }; - const loadMacros = async () => { const { onDisconnect, cancelContext, setLoading } = props; const { currentDevice } = deviceState; @@ -618,8 +429,9 @@ function MacroEditor(props: MacroEditorProps) { chipID = chipID.replace(/\s/g, ""); const neurons = store.get("neurons") as Neuron[]; state.neurons = neurons; - state.neuronIdx = neurons.findIndex(n => n.id === chipID); - state.storedMacros = neurons[state.neuronIdx].macros; + state.neuronID = chipID; + state.storedMacros = neurons[neurons.findIndex(n => n.id === chipID)].macros; + state.storedSuper = neurons[neurons.findIndex(n => n.id === chipID)].superkeys; setState({ ...state }); const deviceLang = { ...currentDevice.device, language: true }; currentDevice.commands.keymap = new Keymap(deviceLang); @@ -645,41 +457,14 @@ function MacroEditor(props: MacroEditorProps) { const custom = await currentDevice.command("keymap.custom"); const onlyCustom = Boolean(parseInt(await currentDevice.command("keymap.onlyCustom"), 10)); const keymap: KeymapType = { custom: undefined, default: undefined, onlyCustom: false }; - const layerSize = currentDevice.device.keyboard.rows * currentDevice.device.keyboard.columns; - keymap.custom = custom - .split(" ") - .filter(v => v.length > 0) - .map(k => keymapDB.parse(parseInt(k, 10))) - .reduce((resultArray, item, index) => { - const localResultArray = resultArray; - const chunkIndex = Math.floor(index / layerSize); - - if (!localResultArray[chunkIndex]) { - localResultArray[chunkIndex] = []; // start a new chunk - } - localResultArray[chunkIndex].push(item); - return localResultArray; - }, []); - keymap.default = defaults - .split(" ") - .filter(v => v.length > 0) - .map(k => keymapDB.parse(parseInt(k, 10))) - .reduce((resultArray, item, index) => { - const localResultArray = resultArray; - const chunkIndex = Math.floor(index / layerSize); - - if (!localResultArray[chunkIndex]) { - localResultArray[chunkIndex] = []; // start a new chunk - } - localResultArray[chunkIndex].push(item); - return localResultArray; - }, []); + keymap.custom = parseKeymapRaw(custom, layerSize).map(l => l.map(k => keymapDB.parse(k))); + keymap.default = parseKeymapRaw(defaults, layerSize).map(l => l.map(k => keymapDB.parse(k))); keymap.onlyCustom = onlyCustom; const macrosRaw = await currentDevice.command("macros.map"); - const parsedMacros = macroTranslator(macrosRaw); + const parsedMacros = parseMacrosRaw(macrosRaw, state.storedMacros); const supersRaw = await currentDevice.command("superkeys.map"); - const parsedSuper = superTranslator(supersRaw); + const parsedSuper = parseSuperkeysRaw(supersRaw, state.storedSuper); state.macros = parsedMacros; state.superkeys = parsedSuper; state.keymap = keymap; @@ -687,7 +472,6 @@ function MacroEditor(props: MacroEditorProps) { state.modified = false; state.usedMemory = parsedMacros.map(m => m.actions).flat().length; state.totalMemory = tMem; - state.macrosEraser = Array(tMem).fill("255").join(" "); state.loading = false; setState({ ...state }); cancelContext(); diff --git a/src/renderer/views/SuperkeysEditor.tsx b/src/renderer/views/SuperkeysEditor.tsx index 85d4e95c..b2e61768 100644 --- a/src/renderer/views/SuperkeysEditor.tsx +++ b/src/renderer/views/SuperkeysEditor.tsx @@ -40,7 +40,6 @@ import { KeyPickerKeyboard } from "@Renderer/modules/KeyPickerKeyboard"; // Types import { SuperkeysEditorInitialStateType, SuperkeysEditorProps } from "@Renderer/types/superkeyseditor"; -import { MacrosType } from "@Renderer/types/macros"; import { SuperkeysType } from "@Renderer/types/superkeys"; import { Neuron } from "@Renderer/types/neurons"; import { KeymapType } from "@Renderer/types/layout"; @@ -52,6 +51,7 @@ import Store from "@Renderer/utils/Store"; import getLanguage from "@Renderer/utils/language"; import Keymap, { KeymapDB } from "../../api/keymap"; import Backup from "../../api/backup"; +import { parseMacrosRaw, parseSuperkeysRaw, serializeKeymap, serializeSuperkeys } from "../../api/parsers"; const store = Store.getStore(); @@ -92,39 +92,12 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { const [isSaving, setIsSaving] = useState(false); const [mouseWheel, setMouseWheel] = useState(0); - const flatten = (arr: unknown[]) => [].concat(...arr); - - const defaultMacro = [ - { - actions: [ - { keyCode: 229, type: 6, id: 0 }, - { keyCode: 11, type: 8, id: 1 }, - { keyCode: 229, type: 7, id: 2 }, - { keyCode: 8, type: 8, id: 3 }, - { keyCode: 28, type: 8, id: 4 }, - { keyCode: 54, type: 8, id: 5 }, - { keyCode: 44, type: 8, id: 6 }, - { keyCode: 229, type: 6, id: 7 }, - { keyCode: 7, type: 8, id: 8 }, - { keyCode: 229, type: 7, id: 9 }, - { keyCode: 28, type: 8, id: 10 }, - { keyCode: 10, type: 8, id: 11 }, - { keyCode: 16, type: 8, id: 12 }, - { keyCode: 4, type: 8, id: 13 }, - { keyCode: 23, type: 8, id: 14 }, - { keyCode: 8, type: 8, id: 15 }, - ], - id: 0, - macro: "RIGHT SHIFT H RIGHT SHIFT E Y , SPACE RIGHT SHIFT D RIGHT SHIFT Y G M A T E", - name: "Hey, Dygmate!", - }, - ]; - const initialState: SuperkeysEditorInitialStateType = { keymap: undefined, macros: [], superkeys: [], storedMacros: [], + storedSuper: [], neurons: [], neuronID: "", kbtype: "iso", @@ -144,132 +117,6 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { const [state, setState] = useState(initialState); const { state: deviceState } = useDevice(); - const macroTranslator = (raw: string) => { - const { storedMacros } = state; - if (typeof raw === "string" && raw.search(" 0 0") === -1) { - return defaultMacro; - } - const macrosArray = raw.split(" 0 0")[0].split(" ").map(Number); - - // Translate received macros to human readable text - const macros = []; - let iter = 0; - // macros are `0` terminated or when end of macrosArray has been reached, the outer loop - // must cycle once more than the inner - while (iter <= macrosArray.length) { - const actions = []; - while (iter < macrosArray.length) { - const type = macrosArray[iter]; - if (type === 0) { - break; - } - - switch (type) { - case 1: - actions.push({ - type, - keyCode: [ - (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], - (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)], - ], - }); - break; - case 2: - case 3: - case 4: - case 5: - actions.push({ type, keyCode: (macrosArray[(iter += 1)] << 8) + macrosArray[(iter += 1)] }); - break; - case 6: - case 7: - case 8: - actions.push({ type, keyCode: macrosArray[(iter += 1)] }); - break; - default: - break; - } - - iter += 1; - } - macros.push({ - actions, - name: "", - macro: "", - }); - iter += 1; - } - macros.forEach((m, idx) => { - const aux: MacrosType = m; - aux.id = idx; - macros[idx] = aux; - }); - - // TODO: Check if stored macros match the received ones, if they match, retrieve name and apply it to current macros - const stored = storedMacros; - if (stored === undefined || stored.length === 0) { - return macros; - } - return macros.map((macro, i) => { - if (stored.length < i) { - return macro; - } - - return { - ...macro, - name: stored[i]?.name, - macro: macro.actions.map(k => keymapDB.parse(k.keyCode as number).label).join(" "), - }; - }); - }; - - const superTranslator = (raw: string) => { - const { neurons, neuronID } = state; - const superArray = raw.split(" 0 0")[0].split(" ").map(Number); - - let superkey: number[] = []; - const superkeys: SuperkeysType[] = []; - let iter = 0; - let superindex = 0; - - if (superArray.length < 1) { - log.info("Discarded Superkeys due to short length of string", raw, raw.length); - return [{ actions: [53, 2101, 1077, 41, 0], name: "Welcome to superkeys", id: superindex }]; - } - // log.info(raw, raw.length); - while (superArray.length > iter) { - // log.info(iter, raw[iter], superkey); - if (superArray[iter] === 0) { - superkeys[superindex] = { actions: superkey, name: "", id: superindex }; - superindex += 1; - superkey = []; - } else { - superkey.push(superArray[iter]); - } - iter += 1; - } - superkeys[superindex] = { actions: superkey, name: "", id: superindex }; - - if (superkeys[0].actions.length === 0 || superkeys[0].actions.length > 5) { - log.info(`Superkeys were empty`); - return []; - } - log.info(`Got Superkeys:${JSON.stringify(superkeys)} from ${raw}`); - // TODO: Check if stored superKeys match the received ones, if they match, retrieve name and apply it to current superKeys - let finalSuper: SuperkeysType[] = []; - const stored = neurons.find(n => n.id === neuronID).superkeys; - finalSuper = superkeys.map((superky, i) => { - const superk = superky; - if (stored.length > i && stored.length > 0) { - const aux = superk; - aux.name = stored[i].name; - return aux; - } - return superk; - }); - log.info("final superkeys", finalSuper); - return finalSuper; - }; - const onKeyChange = (keyCode: number) => { const { superkeys, selectedSuper, selectedAction } = state; const { startContext } = props; @@ -300,6 +147,7 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { state.neurons = neurons; state.neuronID = chipID; state.storedMacros = neuron.macros; + state.storedSuper = neuron.superkeys; setState({ ...state }); const deviceLang = { ...currentDevice.device, language: true }; currentDevice.commands.keymap = new Keymap(deviceLang); @@ -347,9 +195,9 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { keymap.onlyCustom = onlyCustom; // Macros const macrosRaw = await currentDevice.command("macros.map"); - const parsedMacros = macroTranslator(macrosRaw); + const parsedMacros = parseMacrosRaw(macrosRaw, state.storedMacros); const supersRaw = await currentDevice.command("superkeys.map"); - const parsedSuper = superTranslator(supersRaw); + const parsedSuper = parseSuperkeysRaw(supersRaw, state.storedSuper); state.modified = false; state.macros = parsedMacros; state.superkeys = parsedSuper; @@ -370,37 +218,6 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { return true; }; - const superkeyMap = (superkeys: SuperkeysType[]) => { - if ( - superkeys.length === 0 || - (superkeys.length === 1 && superkeys[0].actions.length === 0) || - (superkeys.length === 1 && superkeys[0].actions.length === 1 && superkeys[0].actions[0] === 0) - ) { - return Array(512).fill("65535").join(" "); - } - let keyMap = JSON.parse(JSON.stringify(superkeys)); - log.info("First", JSON.stringify(keyMap)); - keyMap = keyMap.map((sky: SuperkeysType) => { - const sk = sky; - sk.actions = sk.actions.map(act => { - if (act === 0 || act === null || act === undefined) return 1; - return act; - }); - if (sk.actions.length < 5) sk.actions = sk.actions.concat(Array(5 - sk.actions.length).fill(1)); - return sk; - }); - log.info("Third", JSON.parse(JSON.stringify(keyMap))); - const mapped = keyMap - .map((superkey: SuperkeysType) => superkey.actions.filter(act => act !== 0).concat([0])) - .flat() - .concat([0]) - .join(" ") - .split(",") - .join(" "); - log.info("Mapped superkeys: ", mapped, keyMap); - return mapped; - }; - const changeSelected = (id: number) => { state.selectedSuper = id < 0 ? 0 : id; state.selectedAction = -1; @@ -465,15 +282,11 @@ function SuperkeysEditor(props: SuperkeysEditorProps) { log.info("Loaded neurons: ", JSON.stringify(localNeurons)); try { store.set("neurons", localNeurons); - const sendSK = superkeyMap(superkeys); + const sendSK = serializeSuperkeys(superkeys); log.info("Mod superK", sendSK); await currentDevice.command("superkeys.map", sendSK); if (modifiedKeymap) { - const args = flatten(keymap.custom) - .map(k => keymapDB.serialize(k)) - .join(" "); - log.info("Mod keymap", args); - await currentDevice.command("keymap.custom", args); + await currentDevice.command("keymap.custom", serializeKeymap(keymap.custom)); } state.modified = false; state.modifiedKeymap = false;