diff --git a/src/main/managers/Store.ts b/src/main/managers/Store.ts
index 0025853a8..57fe4ecae 100644
--- a/src/main/managers/Store.ts
+++ b/src/main/managers/Store.ts
@@ -12,6 +12,7 @@ const schema: Schema = {
backupFrequency: { type: "number" },
language: { type: "string" },
darkMode: { type: "string" },
+ hideBluetoothExperimental: { type: "boolean" },
showDefaults: { type: "boolean" },
isStandardView: { type: "boolean" },
autoUpdate: { type: "boolean" },
@@ -21,6 +22,7 @@ const schema: Schema = {
backupFrequency: 0,
language: "english",
darkMode: "system",
+ hideBluetoothExperimental: false,
showDefaults: false,
isStandardView: true,
autoUpdate: undefined,
diff --git a/src/main/utils/udev.ts b/src/main/utils/udev.ts
index f0460b85e..62266c33c 100644
--- a/src/main/utils/udev.ts
+++ b/src/main/utils/udev.ts
@@ -3,7 +3,7 @@ import fs from "fs";
import * as sudo from "sudo-prompt";
import log from "electron-log/main";
-const udevRulesToWrite =`\
+const udevRulesToWrite = `\
# Dygma Raise
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="2200", MODE="0660", TAG+="uaccess"
# bootloader mode
@@ -44,7 +44,7 @@ const installUdev = (mainWindow: BrowserWindow) => {
};
const dialogOpts: MessageBoxOptions = {
type: "question",
- buttons: ["Cancel", "Install"],
+ buttons: ["Ignore", "Install"],
cancelId: 0,
defaultId: 1,
title: "Udev rules Installation",
diff --git a/src/renderer/components/atoms/AlertDialog.tsx b/src/renderer/components/atoms/AlertDialog.tsx
index e61cfac77..4dc91aaa5 100644
--- a/src/renderer/components/atoms/AlertDialog.tsx
+++ b/src/renderer/components/atoms/AlertDialog.tsx
@@ -5,7 +5,7 @@ import { cn } from "@Renderer/utils";
import { buttonVariants } from "@Renderer/components/atoms/Button";
interface ButtonVariantProps {
- buttonVariant: "default" | "destructive" | "outline" | "link" | "secondary" | "ghost";
+ buttonVariant: "default" | "primary" | "destructive" | "outline" | "link" | "secondary" | "ghost";
}
const AlertDialog = AlertDialogPrimitive.Root;
diff --git a/src/renderer/i18n/en.ts b/src/renderer/i18n/en.ts
index 8f92ca771..0b5d61a30 100644
--- a/src/renderer/i18n/en.ts
+++ b/src/renderer/i18n/en.ts
@@ -719,9 +719,13 @@ const English = {
useWithoutKeyboard: "Use without keyboard",
noDevicesFound: "No keyboards found!",
noDevicesFoundDescription: "[Black metal plays in background]",
- dialogDeleteTitle: "Are you absolutely sure?",
dialogDeleteDescription:
"This action can't be undone and will remove the keyboard from your Device List, deleting the names of your layers, macros and superkeys. The rest of your configuration will remain on the keyboard.",
+ dialogDeleteTitle: "",
+ dialogBluetoothExperimentalTitle: "IMPORTANT",
+ dialogBluetoothExperimentalDescription:
+ "Bazecor over Bluetooth is still an experimental feature; it doesn't work on all computers yet, and changes might not always be saved correctly to your keyboard.",
+ dialogBluetoothExperimentalDisclaimer: "If you experience these issues, please connect your neuron via USB to your computer.",
ReOrderList: "Re-order list",
},
keyboardSelect: {
@@ -794,7 +798,7 @@ const English = {
errorDuringProcessTitle: "Firmware update error!",
errorDuringProcessDescription: "Something went wrong! Please, retry the flashing procedure. 🫠",
flashCardTitle1: "Press and hold the top left key to start the firmware update.",
- flashCardTitleDefy1: "Press the top left key to start the firmware update.",
+ flashCardTitleDefy1: "Don't hold the key, just press & release to start the firmware update.",
flashCardTitle2: "Release the key when the software prompts",
flashCardHelp: "Why do I need to press and hold a key when updating the device firmware?",
flashCardHelpDefy: "Why do I need to press a key when updating the device firmware?",
diff --git a/src/renderer/modules/DeviceManager/CardDevice.tsx b/src/renderer/modules/DeviceManager/CardDevice.tsx
index 5d0ac423c..3342ec341 100644
--- a/src/renderer/modules/DeviceManager/CardDevice.tsx
+++ b/src/renderer/modules/DeviceManager/CardDevice.tsx
@@ -1,4 +1,4 @@
-import React, { forwardRef } from "react";
+import React, { forwardRef, useState } from "react";
import { SortableKnob } from "react-easy-sort";
import log from "electron-log/renderer";
@@ -8,6 +8,18 @@ import { DeviceListType } from "@Renderer/types/DeviceManager";
import { DevicePreview } from "@Renderer/modules/DevicePreview";
import { Button } from "@Renderer/components/atoms/Button";
import { i18n } from "@Renderer/i18n";
+import Store from "@Renderer/utils/Store";
+import {
+ AlertDialog,
+ AlertDialogAction,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@Renderer/components/atoms/AlertDialog";
+import { Switch } from "@Renderer/components/atoms/Switch";
interface CardDeviceProps {
device: DeviceListType;
@@ -16,8 +28,12 @@ interface CardDeviceProps {
handleConnection: (value: number, action: "connect" | "disconnect") => Promise;
}
+const store = Store.getStore();
+
const CardDevice = forwardRef((props, ref) => {
const { device, filterBy, openDialog, handleConnection } = props;
+ const [open, setOpen] = useState(false);
+ const [notShow, setNotShow] = useState(store.get("settings.hideBluetoothExperimental"));
const filterAttribute = (filter: any) => {
switch (filter) {
@@ -42,6 +58,11 @@ const CardDevice = forwardRef((props, ref) => {
}
};
+ const handleSetNotShow = (newValue: boolean) => {
+ setNotShow(newValue);
+ store.set("settings.hideBluetoothExperimental", newValue);
+ };
+
return (
((props, ref) => {
{device.available ? (
-
+ setOpen(true) : handleSetIsConnected}
+ >
{device.connected ? i18n.keyboardSelect.disconnect : "Configure"}
) : (
@@ -127,6 +152,40 @@ const CardDevice = forwardRef((props, ref) => {
*/}
+ {
+ if (isOpen === true) return;
+ setOpen(false);
+ }}
+ >
+
+
+ {i18n.deviceManager.dialogBluetoothExperimentalTitle}
+ {i18n.deviceManager.dialogBluetoothExperimentalDescription}
+ {i18n.deviceManager.dialogBluetoothExperimentalDisclaimer}
+
+
+ {`Don't ask me again`}
+
+ handleSetNotShow(!notShow)}
+ variant="default"
+ size="sm"
+ />
+
+
+
+ {`I'll use USB`}
+
+ {`Ok, let's go!`}
+
+
+
+
);
});
diff --git a/src/renderer/modules/KeysTabs/LayersTab.tsx b/src/renderer/modules/KeysTabs/LayersTab.tsx
index bfef54421..8e5ccdce9 100644
--- a/src/renderer/modules/KeysTabs/LayersTab.tsx
+++ b/src/renderer/modules/KeysTabs/LayersTab.tsx
@@ -403,6 +403,9 @@ const LayersTab = ({
Tap the key to perform a normal keypress (like space or enter) or hold it to shift to the selected
layer. This allows for efficient layer access without sacrificing key real estate.
+
+
+ Add key on tap only works for layers 1 to 8.
>
}
@@ -438,7 +441,9 @@ const LayersTab = ({
Tap the key to enter the selected layer for a single keypress; after that keypress, the software
automatically returns to the previous layer. You can also hold the key to stay in the layer while you
hold it. Double-tap it to lock into the layer; go back to the previous layer by tapping the key again.
- It's crucial that the same key in the target layer is set up as TRANSPARENT.
+
+
+ OneShot layers only work for layers 1 to 8.
>
}
diff --git a/src/renderer/types/store.ts b/src/renderer/types/store.ts
index defd16d97..4da184869 100644
--- a/src/renderer/types/store.ts
+++ b/src/renderer/types/store.ts
@@ -4,6 +4,7 @@ export interface StorageType {
backupFrequency: number;
language: string;
darkMode: string;
+ hideBluetoothExperimental?: boolean;
showDefaults: boolean;
isStandardView: boolean;
};
diff --git a/src/renderer/utils/Store.ts b/src/renderer/utils/Store.ts
index 987e447fa..f6b7a304b 100644
--- a/src/renderer/utils/Store.ts
+++ b/src/renderer/utils/Store.ts
@@ -12,6 +12,7 @@ const schema: Schema = {
backupFrequency: { type: "number" },
language: { type: "string" },
darkMode: { type: "string" },
+ hideBluetoothExperimental: { type: "boolean" },
showDefaults: { type: "boolean" },
isStandardView: { type: "boolean" },
autoUpdate: { type: "boolean" },
@@ -21,6 +22,7 @@ const schema: Schema = {
backupFrequency: 0,
language: "english",
darkMode: "system",
+ hideBluetoothExperimental: false,
showDefaults: false,
isStandardView: true,
autoUpdate: undefined,
diff --git a/src/renderer/views/MacroEditor.tsx b/src/renderer/views/MacroEditor.tsx
index 58c6d020b..791b7c392 100644
--- a/src/renderer/views/MacroEditor.tsx
+++ b/src/renderer/views/MacroEditor.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable react/jsx-no-bind */
-/* eslint-disable no-console */
/* eslint-disable no-bitwise */
/* Bazecor -- Kaleidoscope Command Center
* Copyright (C) 2018, 2019 Keyboardio, Inc.
@@ -218,7 +216,7 @@ function MacroEditor(props: MacroEditorProps) {
return mapped;
};
- function macrosMap(macros: MacrosType[]) {
+ const macrosMap = (macros: MacrosType[]) => {
const { macrosEraser } = state;
log.info(
"Macros map function",
@@ -258,9 +256,9 @@ function MacroEditor(props: MacroEditorProps) {
.join(" ");
log.info("MACROS GOING TO BE SAVED", result);
return result;
- }
+ };
- function addToActions(actions: MacroActionsType[]) {
+ const addToActions = (actions: MacroActionsType[]) => {
const { startContext } = props;
const { macros, selectedMacro } = state;
@@ -270,10 +268,10 @@ function MacroEditor(props: MacroEditorProps) {
state.modified = true;
setState({ ...state });
startContext();
- }
+ };
// Define updateActions function to update the actions of the selected macro
- function updateActions(actions: MacroActionsType[]) {
+ const updateActions = (actions: MacroActionsType[]) => {
const { startContext } = props;
const { macros, selectedMacro, modified } = state;
@@ -288,9 +286,9 @@ function MacroEditor(props: MacroEditorProps) {
state.macros = macrosList;
setState({ ...state });
}
- }
+ };
- function saveName(data: string) {
+ const saveName = (data: string) => {
const { startContext } = props;
const { macros, selectedMacro } = state;
const localMacros = [...macros];
@@ -299,28 +297,28 @@ function MacroEditor(props: MacroEditorProps) {
state.modified = true;
setState({ ...state });
startContext();
- }
+ };
- function updateScroll(scrollPos: number) {
+ const updateScroll = (scrollPos: number) => {
state.scrollPos = scrollPos;
setState({ ...state });
- }
+ };
- function changeSelected(id: number) {
+ const changeSelected = (id: number) => {
state.selectedMacro = id < 0 ? 0 : id;
setState({ ...state });
- }
+ };
- function updateMacros(recievedMacros: MacrosType[]) {
+ const updateMacros = (recievedMacros: MacrosType[]) => {
const { startContext } = props;
state.macros = recievedMacros;
state.modified = true;
state.usedMemory = recievedMacros.map(m => m.actions).flat().length;
setState({ ...state });
startContext();
- }
+ };
- function duplicateMacro() {
+ const duplicateMacro = () => {
const { macros, maxMacros, selectedMacro } = state;
if (macros.length >= maxMacros) {
return;
@@ -332,9 +330,9 @@ function MacroEditor(props: MacroEditorProps) {
macros.push(aux);
updateMacros(macros);
changeSelected(aux.id);
- }
+ };
- async function writeMacros() {
+ const writeMacros = async () => {
const { macros, neurons, neuronIdx, keymap, superkeys } = state;
const { setLoading, cancelContext } = props;
const { currentDevice } = deviceState;
@@ -372,19 +370,20 @@ function MacroEditor(props: MacroEditorProps) {
setLoading(false);
setIsSaving(false);
}
- }
+ };
- function toggleDeleteModal() {
+ const toggleDeleteModal = () => {
state.showDeleteModal = false;
state.futureMacros = [];
state.listToDelete = [];
state.listToDeleteS = [];
state.listToDeleteM = [];
setState({ ...state });
- }
+ };
function ActUponDelete(localstate?: MacroEditorInitialStateType) {
const { selectedList, listToDelete, listToDeleteS, listToDeleteM, keymap, superkeys } = state;
+ const { startContext } = props;
let macros = localstate ? localstate.futureMacros : state.futureMacros;
log.info("Checking list to delete macros", listToDeleteM, macros);
for (let i = 0; i < listToDelete.length; i += 1) {
@@ -419,19 +418,25 @@ function MacroEditor(props: MacroEditorProps) {
newMacro.actions = macro.actions.filter(x => x !== undefined);
return newMacro;
});
+ macros = macros.map((macro, idx) => {
+ const item = { ...macro };
+ item.id = idx;
+ return item;
+ });
log.info("result!", macros);
state.keymap = keymap;
state.superkeys = superkeys;
state.macros = macros;
state.modified = true;
setState({ ...state });
+ startContext();
toggleDeleteModal();
}
- function UpdateList(data: string) {
+ const UpdateList = (data: string) => {
state.selectedList = parseInt(data, 10);
setState({ ...state });
- }
+ };
function updateKeyboard(keyboardIdx: number, localMacros: MacrosType[]) {
const { macros, superkeys, keymap } = state;
@@ -483,7 +488,7 @@ function MacroEditor(props: MacroEditorProps) {
}
}
- function deleteMacro() {
+ const deleteMacro = () => {
const { macros, selectedMacro } = state;
if (macros.length === 0) {
return;
@@ -497,9 +502,9 @@ function MacroEditor(props: MacroEditorProps) {
return item;
});
updateKeyboard(selected, localMacros);
- }
+ };
- function addMacro(name: string) {
+ const addMacro = (name: string) => {
const { macros, maxMacros } = state;
if (macros.length >= maxMacros) {
return;
@@ -514,9 +519,9 @@ function MacroEditor(props: MacroEditorProps) {
});
updateMacros(aux);
changeSelected(newID);
- }
+ };
- function clearMacro() {
+ const clearMacro = () => {
const { macros, selectedMacro } = state;
if (macros.length === 0) {
return;
@@ -524,9 +529,9 @@ function MacroEditor(props: MacroEditorProps) {
const localMacros = JSON.parse(JSON.stringify(macros)) as MacrosType[];
localMacros[selectedMacro].actions = [];
updateMacros(localMacros);
- }
+ };
- function macroTranslator(raw: string) {
+ const macroTranslator = (raw: string) => {
const { storedMacros } = state;
const macrosArray = raw.split(" 0 0")[0].split(" ").map(Number);
@@ -599,7 +604,7 @@ function MacroEditor(props: MacroEditorProps) {
macro: macro.actions.map(k => keymapDB.parse(k.keyCode as number).label).join(" "),
};
});
- }
+ };
const loadMacros = async () => {
const { onDisconnect, cancelContext, setLoading } = props;
@@ -732,6 +737,7 @@ function MacroEditor(props: MacroEditorProps) {
listToDelete,
listToDeleteS,
listToDeleteM,
+ futureMacros,
usedMemory,
totalMemory,
showDeleteModal,
@@ -787,7 +793,7 @@ function MacroEditor(props: MacroEditorProps) {
No Key
- {macros.map(macro => (
+ {futureMacros.map(macro => (
{macro?.name ? `#${macro.id + 1}. ${macro?.name}` : `#${macro.id + 1}. No name`}
diff --git a/src/renderer/views/SuperkeysEditor.tsx b/src/renderer/views/SuperkeysEditor.tsx
index 52a531722..5c53ea74e 100644
--- a/src/renderer/views/SuperkeysEditor.tsx
+++ b/src/renderer/views/SuperkeysEditor.tsx
@@ -661,20 +661,21 @@ function SuperkeysEditor(props: SuperkeysEditorProps) {
const deleteSuperkey = () => {
const { superkeys, selectedSuper } = state;
- if (superkeys.length > 0) {
- let aux = JSON.parse(JSON.stringify(superkeys));
- const selected = selectedSuper;
- aux.splice(selected, 1);
- aux = aux.map((item: SuperkeysType, index: number) => {
- const newItem = item;
- newItem.id = index;
- return newItem;
- });
- if (selected >= superkeys.length - 1) {
- checkKBSuperkeys(aux, aux.length - 1, aux.length + 53980);
- } else {
- checkKBSuperkeys(aux, selected, selected + 53980);
- }
+ if (!Array.isArray(superkeys) || superkeys.length <= 0 || selectedSuper < 0) {
+ return;
+ }
+ let aux = JSON.parse(JSON.stringify(superkeys));
+ const selected = selectedSuper;
+ aux.splice(selected, 1);
+ aux = aux.map((item: SuperkeysType, index: number) => {
+ const newItem = item;
+ newItem.id = index;
+ return newItem;
+ });
+ if (selected >= superkeys.length - 1) {
+ checkKBSuperkeys(aux, aux.length - 1, aux.length + 53980);
+ } else {
+ checkKBSuperkeys(aux, selected, selected + 53980);
}
};