diff --git a/Data/WebUI/src/Borealis.css b/Data/WebUI/src/Borealis.css index 45b4a8a..abe4fde 100644 --- a/Data/WebUI/src/Borealis.css +++ b/Data/WebUI/src/Borealis.css @@ -93,3 +93,47 @@ label { } /* We rely on the TabIndicatorProps to show the underline highlight for active tabs. */ + +/* keyboard-dark-theme.css */ + +/* react-simple-keyboard dark theming */ +.hg-theme-dark { + background-color: #1e1e1e; + border: 1px solid #444; +} + +.hg-button { + background: #2c2c2c; + color: #ccc; + border: 1px solid #444; + font-size: 11px; +} + +.hg-button:hover { + background: #58a6ff; + color: #000; + border-color: #58a6ff; +} + +.borealis-keyboard .hg-button.hg-standardBtn { + border-radius: 3px; +} + +/* Force rows to appear horizontally */ +.simple-keyboard-main .hg-row { + display: flex !important; + flex-flow: row wrap; + justify-content: center; + } + +/* Slight spacing around each key (optional) */ +.simple-keyboard-main .hg-row .hg-button { + margin: 3px !important; + } + + /* Keep the entire keyboard from shrinking or going vertical */ + .simple-keyboard-main { + display: inline-block !important; + width: auto !important; + max-width: 1000px; /* or whatever max width you like */ + } \ No newline at end of file diff --git a/Data/WebUI/src/nodes/Image Processing/Node_BW_Threshold.jsx b/Data/WebUI/src/nodes/Image Processing/Node_BW_Threshold.jsx index a09d0f9..b2f983d 100644 --- a/Data/WebUI/src/nodes/Image Processing/Node_BW_Threshold.jsx +++ b/Data/WebUI/src/nodes/Image Processing/Node_BW_Threshold.jsx @@ -12,22 +12,45 @@ if (!window.BorealisUpdateRate) { const BWThresholdNode = ({ id, data }) => { const edges = useStore((state) => state.edges); - const [threshold, setThreshold] = useState(() => parseInt(data?.value, 10) || 128); + + // Attempt to parse threshold from data.value (if present), + // otherwise default to 128. + const initial = parseInt(data?.value, 10); + const [threshold, setThreshold] = useState( + isNaN(initial) ? 128 : initial + ); + const [renderValue, setRenderValue] = useState(""); const valueRef = useRef(""); const lastUpstreamRef = useRef(""); + // If the node is reimported and data.value changes externally, + // update the threshold accordingly. + useEffect(() => { + const newVal = parseInt(data?.value, 10); + if (!isNaN(newVal)) { + setThreshold(newVal); + } + }, [data?.value]); + const handleThresholdInput = (e) => { let val = parseInt(e.target.value, 10); - if (isNaN(val)) val = 128; + if (isNaN(val)) { + val = 128; + } val = Math.max(0, Math.min(255, val)); + // Keep the Node's data.value updated + data.value = val; + setThreshold(val); window.BorealisValueBus[id] = val; }; const applyThreshold = async (base64Data, cutoff) => { - if (!base64Data || typeof base64Data !== "string") return ""; + if (!base64Data || typeof base64Data !== "string") { + return ""; + } return new Promise((resolve) => { const img = new Image(); @@ -56,7 +79,7 @@ const BWThresholdNode = ({ id, data }) => { }; img.onerror = () => resolve(base64Data); - img.src = `data:image/png;base64,${base64Data}`; + img.src = "data:image/png;base64," + base64Data; }); }; @@ -105,10 +128,14 @@ const BWThresholdNode = ({ id, data }) => { // Reapply when threshold changes (even if image didn't) useEffect(() => { const inputEdge = edges.find(e => e.target === id); - if (!inputEdge?.source) return; + if (!inputEdge?.source) { + return; + } const upstreamValue = window.BorealisValueBus[inputEdge.source] ?? ""; - if (!upstreamValue) return; + if (!upstreamValue) { + return; + } applyThreshold(upstreamValue, threshold).then((result) => { valueRef.current = result; diff --git a/Data/WebUI/src/nodes/Macro Automation/Node_Macro_KeyPress.jsx b/Data/WebUI/src/nodes/Macro Automation/Node_Macro_KeyPress.jsx new file mode 100644 index 0000000..00a958a --- /dev/null +++ b/Data/WebUI/src/nodes/Macro Automation/Node_Macro_KeyPress.jsx @@ -0,0 +1,295 @@ +import React, { useState, useRef } from "react"; +import { Handle, Position } from "reactflow"; +import Keyboard from "react-simple-keyboard"; +import "react-simple-keyboard/build/css/index.css"; +import "../../Borealis.css"; + +if (!window.BorealisValueBus) window.BorealisValueBus = {}; +if (!window.BorealisUpdateRate) window.BorealisUpdateRate = 100; + +/** + * KeyPressNode: + * - Full keyboard with SHIFT toggling + * - Press F-keys, digits, letters, or symbols + * - Single key stored, overlay closes + * - SHIFT or CAPS toggles "default" <-> "shift" + */ + +const KeyPressNode = ({ id, data }) => { + const [selectedWindow, setSelectedWindow] = useState(data?.selectedWindow || ""); + const [keyPressed, setKeyPressed] = useState(data?.keyPressed || ""); + const [intervalMs, setIntervalMs] = useState(data?.intervalMs || 1000); + const [randomRangeEnabled, setRandomRangeEnabled] = useState(false); + const [randomMin, setRandomMin] = useState(750); + const [randomMax, setRandomMax] = useState(950); + + // Keyboard overlay + const [showKeyboard, setShowKeyboard] = useState(false); + const [layoutName, setLayoutName] = useState("default"); + + // A simple set of Windows for demonstration + const fakeWindows = ["Notepad", "Chrome", "Discord", "Visual Studio Code"]; + + // This function is triggered whenever the user taps a key on the virtual keyboard + const onKeyPress = (button) => { + // SHIFT or CAPS toggling: + if (button === "{shift}" || button === "{lock}") { + handleShift(); + return; + } + + // Example skip list: these won't be stored as final single key + const skipKeys = [ + "{bksp}", "{space}", "{tab}", "{enter}", "{escape}", + "{f1}", "{f2}", "{f3}", "{f4}", "{f5}", "{f6}", + "{f7}", "{f8}", "{f9}", "{f10}", "{f11}", "{f12}", + "{shift}", "{lock}" + ]; + + // If the pressed button is not in skipKeys, let's store it and close + if (!skipKeys.includes(button)) { + setKeyPressed(button); + setShowKeyboard(false); + } + }; + + // Toggle between "default" layout and "shift" layout + const handleShift = () => { + setLayoutName((prev) => (prev === "default" ? "shift" : "default")); + }; + + return ( +