diff --git a/featured/KeyHistory.js b/featured/KeyHistory.js index 1ba3a21..8d40988 100644 --- a/featured/KeyHistory.js +++ b/featured/KeyHistory.js @@ -1,6 +1,7 @@ // Name: Key History // ID: KeyHistoryExtension // By: Mistium +// Verson: 5 // Description: Store a list of previously pressed keys and clipboard events. // License: MPL-2.0 // This Source Code is subject to the terms of the Mozilla Public License, v2.0, @@ -17,9 +18,9 @@ class KeyHistoryExtension { constructor() { this.keyHistory = []; - this.pasted = false; this.max_key_history = 100; // Adjust the maximum number of keys to keep in history this.keybinds = ["Ctrl", "Shift", "Alt"]; + this.keysDown = []; this.pause = false; } @@ -34,6 +35,11 @@ blockType: Scratch.BlockType.REPORTER, text: "get recent keys", }, + { + opcode: "getFirstKey", + blockType: Scratch.BlockType.REPORTER, + text: "get first key", + }, { opcode: "deleteFirstKey", blockType: Scratch.BlockType.COMMAND, @@ -55,6 +61,7 @@ }, }, }, + "---", { opcode: "setMaxQueueSize", blockType: Scratch.BlockType.COMMAND, @@ -66,6 +73,17 @@ }, }, }, + { + opcode: "ignoreKeybinds", + blockType: Scratch.BlockType.COMMAND, + text: "ignore keys [KEYS]", + arguments: { + KEYS: { + type: Scratch.ArgumentType.STRING, + defaultValue: "[\"Ctrl\", \"Shift\", \"Alt\"]", + }, + }, + }, "---", { opcode: "enableKeyHistory", @@ -77,6 +95,46 @@ blockType: Scratch.BlockType.COMMAND, text: "disable key history", }, + "---", + { + opcode: "onKeyPressed", + blockType: Scratch.BlockType.EVENT, + text: "when key is pressed", + isEdgeActivated: false, + }, + { + opcode: "onKeyReleased", + blockType: Scratch.BlockType.EVENT, + text: "when key is released", + isEdgeActivated: false, + }, + { + opcode: "onTextPasted", + blockType: Scratch.BlockType.EVENT, + text: "when text is pasted", + isEdgeActivated: false, + }, + { + opcode: "lastKeyPressed", + blockType: Scratch.BlockType.REPORTER, + text: "last key pressed", + }, + { + opcode: "getKeysDown", + blockType: Scratch.BlockType.REPORTER, + text: "keys down", + }, + { + opcode: "iskeyPressed", + blockType: Scratch.BlockType.BOOLEAN, + text: "key [KEY] pressed?", + arguments: { + KEY: { + type: Scratch.ArgumentType.STRING, + defaultValue: "a", + }, + }, + }, ], }; } @@ -85,6 +143,10 @@ return JSON.stringify(this.keyHistory); } + getFirstKey() { + return Scratch.Cast.toString(this.keyHistory[0]); + } + deleteFirstKey() { if (this.keyHistory.length > 0) { this.keyHistory.shift(); @@ -96,50 +158,70 @@ } AddKey({ KEY }) { - this.addKeyToHistory("" + KEY); + this.addKeyToHistory(Scratch.Cast.toString(KEY)); } setMaxQueueSize({ LENGTH }) { - this.max_key_history = +LENGTH || 0; + this.max_key_history = Scratch.Cast.toNumber(LENGTH); } onKeyDown(event) { - // Check if Command (Cmd) or Control (Ctrl) keys are pressed - if (event.metaKey || event.ctrlKey) { - return; // Skip adding keys when Cmd or Ctrl are pressed + Scratch.vm.runtime.startHats('KeyHistoryExtension_onKeyPressed'); + + const key = Scratch.Cast.toString(event.key ?? "").toLowerCase(); + + // Only add the key if it's not already in keysDown + if (!this.keysDown.includes(key)) { + this.keysDown.push(key); } - - // Check if the pressed key is part of a keybind - if (this.isKeybind(event.key)) { - return; // Skip adding keybind keys to history + + if (event.metaKey || event.ctrlKey || this.isKeybind(key) || this.pause) { + return; } + + this.addKeyToHistory(key); + } - // Add the pressed key to the history - if (event.key && !this.pause) { - const key = event.key; - this.addKeyToHistory(key); + onKeyUp(event) { + Scratch.vm.runtime.startHats('KeyHistoryExtension_onKeyReleased'); + + // Convert the key to a string to ensure consistency + const key = Scratch.Cast.toString(event.key ?? "").toLowerCase(); + + // Find the index of the key in the keysDown array + const index = this.keysDown.indexOf(key); + + // Check if the key is actually in the array before trying to remove it + if (index !== -1) { + this.keysDown.splice(index, 1); } } + onPaste(event) { + Scratch.vm.runtime.startHats('KeyHistoryExtension_onTextPasted'); const pastedText = event.clipboardData.getData("text/plain"); - if (typeof pastedText === "string") { - this.addKeyToHistory("" + pastedText); - } + this.addKeyToHistory(Scratch.Cast.toString(pastedText)); + } + + ignoreKeybinds({ KEYS }) { + try { + this.keybinds = JSON.parse(KEYS); + } catch (e) {} } isKeybind(key) { - return this.keybinds.includes("" + key); + return this.keybinds.includes(Scratch.Cast.toString(key)); } addKeyToHistory(key) { // Check if the maximum history size is reached if (this.keyHistory.length >= this.max_key_history) { - this.keyHistory.pop(); // Remove the last element + this.keyHistory.shift(); // Remove the first element instead of pop } // Add the key to the end of the array - this.keyHistory.push("" + key); + this.keyHistory.push(Scratch.Cast.toString(key)); } enableKeyHistory() { @@ -149,6 +231,18 @@ disableKeyHistory() { this.pause = true; } + + lastKeyPressed() { + return Scratch.Cast.toString(this.keyHistory[this.keyHistory.length - 1] ?? ""); + } + + iskeyPressed({ KEY }) { + return this.keysDown.includes(Scratch.Cast.toString(KEY)); + } + + getKeysDown() { + return JSON.stringify(this.keysDown); + } } // Create an instance of the KeyHistoryExtension class @@ -159,6 +253,7 @@ // Listen for keydown events and call the onKeyDown method document.addEventListener("keydown", (event) => extension.onKeyDown(event)); + document.addEventListener("keyup", (event) => extension.onKeyUp(event)); // Corrected here // Listen for paste events and call the onPaste method document.addEventListener("paste", (event) => extension.onPaste(event));