Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BZDB Settings editor #50

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions scripts/fetch-bzdb-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ import { load } from 'js-yaml';
import fetch from 'node-fetch';
import { resolve } from 'path';

// @TODO Update this URL to use the `master` branch when this PR is merged
// https://github.com/BZFlag-Dev/bzflag.org/pull/42
const BZDB_DOCS_URL =
'https://raw.githubusercontent.com/BZFlag-Dev/bzflag.org/docs/bzdb/_data/bzdb_settings.yaml';
// prettier-ignore
const BZDB_DOCS_URL = 'https://raw.githubusercontent.com/BZFlag-Dev/bzflag.org/master/_data/bzdb_settings.yaml';

(async function () {
const rawBody = await (await fetch(BZDB_DOCS_URL)).text();
const json = load(rawBody);
const bzdbTypes: string[] = (json as any)['variables'].map(
(def: any) => def.name,
);
const json: any = load(rawBody);
const bzdbTypes: string[] = json['variables'].map((def: any) => def.name);

writeFileSync(
resolve(__dirname, '..', 'src', 'data', 'bzdb-documention.json'),
Expand Down
2 changes: 2 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useRecoilValue } from 'recoil';

import HixDocumentLoader from './Components/HixDocumentLoader';
import AboutModal from './Components/Modals/AboutModal';
import BZDBSettingsModal from './Components/Modals/BZDBSettingsModal';
import FlagSettingsModal from './Components/Modals/FlagSettingsModal';
import GameplaySettingsModal from './Components/Modals/GameplaySettingsModal';
import TeleporterLinkEditorModal from './Components/Modals/TeleporterLinkEditorModal';
Expand Down Expand Up @@ -45,6 +46,7 @@ const App: React.FC = () => {
{/* All of the app's modals (merely for organizational purposes) */}
<>
<AboutModal />
<BZDBSettingsModal />
<FlagSettingsModal />
<GameplaySettingsModal />
<TeleporterLinkEditorModal />
Expand Down
121 changes: 121 additions & 0 deletions src/Components/Form/BZDBEquationField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React, {
KeyboardEvent,
useEffect,
useMemo,
useRef,
useState,
} from 'react';

import keyboard from '../../Utilities/keyboard';
import BaseFormField, { FieldProps } from './BaseFormField';

interface Props extends FieldProps<string> {}

const KeysWeListenTo = [keyboard.UP, keyboard.DOWN];

const BZDBEquationField = ({
onChange,
onKeyDown,
onKeyUp,
value,
...props
}: Props) => {
const inputRef = useRef<HTMLInputElement>(null);
const [lastCursorPos, setLastCursorPos] = useState(0);
const numericalPositions = useMemo<[number, number][]>(() => {
const numbers = value.matchAll(/(-?[\d.])+/g);
const result: [number, number][] = [];

for (const number of numbers) {
if (number.index === undefined) {
continue;
}

result.push([number.index, number.index + number[0].length]);
}

return result;
}, [value]);
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (KeysWeListenTo.indexOf(event.key) >= 0) {
event.preventDefault();
}
};
const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {
// We don't have a reference yet, bail out
if (!inputRef.current) {
return;
}

// If we somehow don't have a starting point for our selection, bail out
const curPos = inputRef.current.selectionStart;
if (curPos === null) {
return;
}

// Pressed a key we don't care about
if (KeysWeListenTo.indexOf(event.key) === -1) {
return;
}

let start = -1;
let end = -1;

for (const position of numericalPositions) {
if (position[0] <= curPos && curPos <= position[1]) {
start = position[0];
end = position[1];

break;
}
}

// Our cursor isn't inside or near a numerical value, bail out
if (start === -1 || end === -1) {
return;
}

const curSel = value.substring(start, end);
const isFloat = curSel.includes('.');
const modVal = event.shiftKey ? 10 : 1;
let numVal = isFloat ? Number.parseFloat(curSel) : Number.parseInt(curSel);

if (event.key === keyboard.UP) {
numVal += modVal;
} else if (event.key === keyboard.DOWN) {
numVal -= modVal;
}

onChange(`${value.slice(0, start)}${numVal}${value.slice(end)}`);

// Save our cursor selection so that we can restore it after updates to our
// equation
setLastCursorPos(start);
};

useEffect(() => {
if (!inputRef.current || lastCursorPos === -1) {
return;
}

inputRef.current.setSelectionRange(lastCursorPos, lastCursorPos);
setLastCursorPos(-1);
}, [lastCursorPos, value]);

return (
<BaseFormField<string>
{...props}
castStrToType={(s) => s ?? ''}
castTypeToStr={(s) => s}
inputRef={inputRef}
onChange={onChange}
onKeyDown={handleKeyDown}
onKeyUp={handleKeyUp}
tag="input"
type="text"
value={value}
/>
);
};

export default BZDBEquationField;
7 changes: 7 additions & 0 deletions src/Components/Form/BaseFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import React, {
HTMLProps,
ReactNode,
SyntheticEvent,
Ref,
} from 'react';

import { classList } from '../../Utilities/cssClasses';
Expand Down Expand Up @@ -36,6 +37,7 @@ export interface FieldProps<T> extends Omit<BaseFieldProps, Blacklist> {
layout?: FieldLayout;
label: string;
labelProps?: HTMLProps<HTMLLabelElement>;
inputRef?: Ref<HTMLInputElement> | Ref<HTMLSelectElement>;
description?: string;
allowChange?: ValueValidator<T>;
onChange: (value: T) => void;
Expand Down Expand Up @@ -99,6 +101,7 @@ const BaseFormField = <T,>({
layout = FieldLayout.Stacked,
label,
labelProps = {},
inputRef = undefined,
allowChange = () => true,
onChange,
tag,
Expand Down Expand Up @@ -150,6 +153,10 @@ const BaseFormField = <T,>({
standardProps['value'] = castTypeToStr(value);
}

if (inputRef) {
standardProps.ref = inputRef;
}

return (
<div
className={classList([styles.wrapper, className])}
Expand Down
9 changes: 9 additions & 0 deletions src/Components/Modals/BZDBSettingsModal.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.modalBody {
display: flex;
}

.tabList {
[data-role='tab-list'] {
width: 300px;
}
}
Loading