pages235/src/react/KeybindingsCustom.tsx
gguio 6bf1085fbe
feat: Key binds screen (#108)
---------

Co-authored-by: gguio <nikvish150@gmail.com>
Co-authored-by: Vitaly <vital2580@icloud.com>
2024-05-18 22:51:35 +03:00

171 lines
5.1 KiB
TypeScript

import { useEffect, useState, useContext } from 'react'
import { customCommandsConfig } from '../customCommands'
import { ButtonWithMatchesAlert, Context } from './KeybindingsScreen'
import Button from './Button'
import styles from './KeybindingsScreen.module.css'
import Input from './Input'
export type CustomCommand = {
keys: undefined | string[]
gamepad: undefined | string[]
type: string
inputs: any[]
}
export type CustomCommandsMap = Record<string, CustomCommand>
export default (
{
customCommands,
updateCurrBind,
resetBinding,
}: {
customCommands: CustomCommandsMap,
updateCurrBind: (group: string, action: string) => void,
resetBinding: (group: string, action: string, inputType: string) => void,
}
) => {
const { userConfig, setUserConfig } = useContext(Context)
const [customConfig, setCustomConfig] = useState<any>({ ...customCommands })
useEffect(() => {
setUserConfig({ ...userConfig, custom: { ...customConfig } })
}, [customConfig])
const addNewCommand = (type: string) => {
// max key + 1
const newKey = String(Math.max(...Object.keys(customConfig).map(Number).filter(key => !isNaN(key)), 0) + 1)
setCustomConfig(prev => {
const newCustomConf = { ...prev }
newCustomConf[newKey] = {
keys: undefined as string[] | undefined,
gamepad: undefined as string[] | undefined,
type,
inputs: [] as any[]
}
return newCustomConf
})
}
return <>
<div className={styles.group}>
{Object.entries(customCommandsConfig).map(([group, { input }]) => (
<div key={`group-container-${group}`} className={styles.group}>
<div key={`category-${group}`} className={styles['group-category']}>{group}</div>
{Object.entries(customConfig).filter(([key, data]) => data.type === group).map((commandData, indexOption) => {
return <CustomCommandContainer
key={indexOption}
indexOption={indexOption}
commandData={commandData}
updateCurrBind={updateCurrBind}
groupData={[group, { input }]}
setCustomConfig={setCustomConfig}
resetBinding={resetBinding}
/>
})}
<Button
onClick={() => addNewCommand(group)}
icon={'pixelarticons:add-box'}
style={{
alignSelf: 'center'
}}
/>
</div>
))}
</div>
</>
}
const CustomCommandContainer = (
{
indexOption,
commandData,
updateCurrBind,
setCustomConfig,
resetBinding,
groupData
}
) => {
const { userConfig } = useContext(Context)
const [commandKey, { keys, gamepad, inputs }] = commandData
const [group, { input }] = groupData
const setInputValue = (optionKey, indexInput, value) => {
setCustomConfig(prev => {
const newConfig = { ...prev }
newConfig[optionKey].inputs = [...prev[optionKey].inputs]
newConfig[optionKey].inputs[indexInput] = value
return newConfig
})
}
return <div style={{ padding: '10px' }}>
{input.map((obj, indexInput) => {
const config = typeof obj === 'function' ? obj(inputs) : obj
if (!config) return null
return config.type === 'select'
? <select key={indexInput} onChange={(e) => {
setInputValue(commandKey, indexInput, e.target.value)
}}>{config.options.map((option) => <option key={option} value={option}>{option}</option>)}</select>
: <Input key={indexInput} rootStyles={{ width: '99%' }} placeholder={config.placeholder} value={inputs[indexInput] ?? ''} onChange={(e) => setInputValue(commandKey, indexInput, e.target.value)} />
})}
<div className={styles.actionBinds}>
{
userConfig?.['custom']?.[commandKey]?.keys ? <Button
onClick={() => {
updateCurrBind(group, commandKey)
resetBinding('custom', commandKey, 'keyboard')
}}
className={styles['undo-keyboard']}
icon={'pixelarticons:undo'}
/>
: null}
{[0, 1].map((key, index) => <ButtonWithMatchesAlert
key={`custom-keyboard-${group}-${commandKey}-${index}`}
group={'custom'}
action={commandKey}
index={index}
inputType={'keyboard'}
keys={keys}
gamepad={gamepad}
/>
)}
<div style={{ marginRight: 'auto' }} ></div>
{
userConfig?.['custom']?.[commandKey]?.gamepad ? <Button
onClick={() => {
updateCurrBind(group, commandKey)
resetBinding('custom', commandKey, 'gamepad')
}}
className={styles['undo-keyboard']}
icon={'pixelarticons:undo'}
/>
: null}
<ButtonWithMatchesAlert
group={'custom'}
action={commandKey}
index={0}
inputType={'gamepad'}
keys={keys}
gamepad={gamepad}
/>
<Button
onClick={() => {
setCustomConfig(prev => {
const { [commandKey]: commandToRemove, ...newConfig } = prev
return newConfig
})
}}
style={{ color: 'red' }}
icon={'pixelarticons:delete'}
/>
</div>
</div>
}