diff --git a/components/Dropdown.tsx.scss b/components/Dropdown.tsx.scss index d3fa004..7ca1522 100644 --- a/components/Dropdown.tsx.scss +++ b/components/Dropdown.tsx.scss @@ -3,7 +3,7 @@ font-size: 16px; width: 100%; - border-radius: 3px; + border-radius: 4px; color: var(--text-normal); background-color: var(--input-background); border: none; diff --git a/components/KeybindInput.tsx b/components/KeybindInput.tsx new file mode 100644 index 0000000..1f31753 --- /dev/null +++ b/components/KeybindInput.tsx @@ -0,0 +1,109 @@ +import { keyToStr, strToKey } from '../util/keyUtil.js' +import { css, classes } from './KeybindInput.tsx.scss' + +const { + solid: { + createSignal + }, + ui: { + Text, + injectCss + } +} = shelter + +interface Props { + onKeybindChange(keybind: number[]): void + + // style overrides + style?: string + disabled?: boolean +} + +let injectedCss = false + +export function KeybindInput(props: Props) { + if (!injectedCss) { + injectedCss = true + injectCss(css) + } + + const [recording, setRecording] = createSignal(false) + // numbers mean (in order) + const [keybind, setKeybind] = createSignal([]) + + const keyDown = (e) => { + // If the key is already in the keybind, don't add it again + if (keybind().includes(e.key) || keybind().includes(e.key.toLowerCase())) { + return + } + + // if ctrl, alt, or shift, add it to the front of the keybind + switch (e.key) { + case 'Control': + case 'Alt': + case 'Shift': + case 'Meta': + setKeybind([e.key, ...keybind()]) + break + default: + setKeybind([...keybind(), e.key.toLowerCase()]) + } + } + + const keyUp = (e) => { + setKeybind(keybind().filter((k) => k !== e.key && k !== e.key.toLowerCase())) + } + + const setRecordingState = () => { + if (recording()) { + // Remove all event listeners + window.removeEventListener('keydown', keyDown), + window.removeEventListener('keyup', keyUp) + + // Set the keybind + props.onKeybindChange(keybind()) + + setRecording(false) + + return + } + + // Clear the keybind + setKeybind([]) + + // Create event listeners to set the keybind based on what is being held down + // Order should be (if they are pressed): Ctrl -> Alt -> Shift -> Everything else + // If a key is released, it should be removed from the keybind + window.addEventListener('keydown', keyDown), + window.addEventListener('keyup', keyUp) + + setRecording(true) + } + + return ( +
+
+ + { + keybind().length ? keybind().map((k, i) => { + const key = k.length > 1 ? k : k.toUpperCase() + return i === keybind().length - 1 ? key : key + ' + ' + }) : 'No Keybind Set' + } + + +
+
{ + setRecordingState() + }} + > + {recording() ? 'Stop Recording' : 'Edit Keybind'} +
+
+ ) +} \ No newline at end of file diff --git a/components/KeybindInput.tsx.scss b/components/KeybindInput.tsx.scss new file mode 100644 index 0000000..66419d5 --- /dev/null +++ b/components/KeybindInput.tsx.scss @@ -0,0 +1,73 @@ +.keybindContainer { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + + width: 100%; + height: 40px; + + border-radius: 4px; + + background: var(--input-background); + color: var(--text-normal); + border: 1px solid transparent; + + padding: 4px; + + transition: all 0.2s; +} + +.keybindContainer:hover { + border: 1px solid var(--status-danger); +} + +.recording { + .keybindButton { + background: hsl(var(--red-400-hsl)/.1); + color: var(--status-danger); + } + + .keybindButton:hover { + background: hsl(var(--red-400-hsl)/.2); + } + + border: 1px solid var(--status-danger); +} + +.keybindInput { + background: transparent; + + display: flex; + align-items: center; +} + +.keybindPlaceholder { + color: var(--text-muted) !important; +} + +.keybindButton { + height: 30px; + width: 50%; + + margin: 0; + padding: 4px; + + border-radius: 4px; + + display: flex; + align-items: center; + + background: var(--button-secondary-background); + color: var(--white-500); + + border: 1px solid transparent; + + cursor: pointer; + + transition: all 0.2s; +} + +.keybindButton:hover { + background: var(--button-secondary-background-hover); +} \ No newline at end of file diff --git a/plugins/dorion-custom-keybinds/components/KeybindSection.tsx b/plugins/dorion-custom-keybinds/components/KeybindSection.tsx index 57af879..54a7337 100644 --- a/plugins/dorion-custom-keybinds/components/KeybindSection.tsx +++ b/plugins/dorion-custom-keybinds/components/KeybindSection.tsx @@ -1,5 +1,6 @@ import { css, classes } from './KeybindSection.tsx.scss' import { Dropdown } from '../../../components/Dropdown' +import { KeybindInput } from '../../../components/KeybindInput' const { ui: { @@ -38,15 +39,11 @@ export function KeybindSection(props) { { - return { - value: key, - label: value - } - })} + options={props.keybindActionTypes} onChange={(e) => { console.log(e) }} + style='width: 90%' > @@ -54,6 +51,13 @@ export function KeybindSection(props) {
Keybind
+ + { + console.log(keybind) + }} + style='width: 90%' + /> ) diff --git a/plugins/dorion-custom-keybinds/components/KeybindSection.tsx.scss b/plugins/dorion-custom-keybinds/components/KeybindSection.tsx.scss index ce643d0..1c79c81 100644 --- a/plugins/dorion-custom-keybinds/components/KeybindSection.tsx.scss +++ b/plugins/dorion-custom-keybinds/components/KeybindSection.tsx.scss @@ -10,7 +10,6 @@ .keybindArea { display: flex; flex-direction: column; - align-items } .actionSection { diff --git a/plugins/dorion-ptt/index.ts b/plugins/dorion-ptt/index.ts index 0f6a002..a1b3595 100644 --- a/plugins/dorion-ptt/index.ts +++ b/plugins/dorion-ptt/index.ts @@ -1,4 +1,4 @@ -import { keyToStr } from './keyUtil.js' +import { keyToStr } from '../../util/keyUtil.js' import { invoke, event } from '../../api/api.js' const { diff --git a/tsconfig.json b/tsconfig.json index 5712c81..d83b437 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -7,5 +7,5 @@ "module": "nodenext", "moduleResolution": "nodenext" }, - "include": ["plugins/**/*.ts", "plugins/**/*.tsx", "node_modules/@uwu/shelter-defs/**/*.d.ts", "plugins/clean-home/index.tsx"] + "include": ["plugins/**/*.ts", "plugins/**/*.tsx", "node_modules/@uwu/shelter-defs/**/*.d.ts", "plugins/clean-home/index.tsx", "util/keyUtil.ts"] } \ No newline at end of file diff --git a/plugins/dorion-ptt/keyUtil.ts b/util/keyUtil.ts similarity index 66% rename from plugins/dorion-ptt/keyUtil.ts rename to util/keyUtil.ts index 34dce09..f6c7ae2 100644 --- a/plugins/dorion-ptt/keyUtil.ts +++ b/util/keyUtil.ts @@ -11,6 +11,7 @@ const Keycode = { 220: 'BackSlash', 186: 'Semicolon', 222: 'Apostrophe', 188: 'Comma', 190: 'Dot', 191: 'Slash' } +// Convert a key code to a string export const keyToStr = (key: number) => { let keyStr = '' @@ -35,4 +36,33 @@ export const keyToStr = (key: number) => { } return keyStr +} + +// Convert a key string to a key code +export const strToKey = (str: string) => { + let key = 0 + + // get char code of uppercase letter + if (str >= 'A' && str <= 'Z') { + key = str.charCodeAt(0) + } + + // get char code of lowercase letter + if (str >= 'a' && str <= 'z') { + key = str.charCodeAt(0) - 32 + } + + // get char code of number + if (str >= '0' && str <= '9') { + key = str.charCodeAt(0) + } + + // Get everything else + for (const [k, v] of Object.entries(Keycode)) { + if (v === str) { + key = parseInt(k) + } + } + + return key } \ No newline at end of file