Skip to content

Commit

Permalink
The settings update
Browse files Browse the repository at this point in the history
  • Loading branch information
imkunet committed Mar 11, 2024
1 parent 1a37281 commit b33d18c
Show file tree
Hide file tree
Showing 13 changed files with 295 additions and 118 deletions.
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100
"printWidth": 100,
"plugins": ["prettier-plugin-css-order"]
}
Binary file modified bun.lockb
Binary file not shown.
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"solid-icons": "^1.1.0",
"solid-js": "^1.8.15",
"solid-motionone": "^1.0.0",
"zod": "^3.22.4"
"zod": "^3.22.4",
"zod_utilz": "^0.8.2"
},
"devDependencies": {
"@types/node": "^20.11.24",
Expand All @@ -25,6 +26,7 @@
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-solid": "^0.13.1",
"prettier": "^3.2.5",
"prettier-plugin-css-order": "^2.0.1",
"typescript": "^5.2.2",
"vite": "^5.1.4",
"vite-plugin-solid": "^2.10.1",
Expand Down
9 changes: 4 additions & 5 deletions src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Accessor, Setter, Show } from 'solid-js';
import { Accessor, Show } from 'solid-js';
import { Motion, Presence } from 'solid-motionone';
import { TbDice } from 'solid-icons/tb';

Expand All @@ -7,9 +7,8 @@ interface FooterProps {
inGame: Accessor<boolean>;
twoMode: Accessor<boolean>;

setTwoMode: Setter<boolean>;

reset: () => void;
setOrToggleTwoMode: (two: boolean) => void;
}

export default function Footer(props: FooterProps) {
Expand All @@ -22,7 +21,7 @@ export default function Footer(props: FooterProps) {
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.9, opacity: 0 }}
>
<div onClick={() => props.setTwoMode(false)}>
<div onClick={() => props.setOrToggleTwoMode(false)}>
<Motion.div
animate={{
opacity: props.twoMode() ? 0.5 : 1.0,
Expand All @@ -34,7 +33,7 @@ export default function Footer(props: FooterProps) {
<div />
</Motion.div>
</div>
<div onClick={() => props.setTwoMode(true)}>
<div onClick={() => props.setOrToggleTwoMode(true)}>
<Motion.div
animate={{
opacity: !props.twoMode() ? 0.5 : 1.0,
Expand Down
70 changes: 43 additions & 27 deletions src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TbCpu, TbDice, TbTrash } from 'solid-icons/tb';
import { Accessor } from 'solid-js';
import { Accessor, Setter, Show } from 'solid-js';
import { TbCpu, TbDice, TbSettings, TbTrash } from 'solid-icons/tb';
import { Motion } from 'solid-motionone';
import { Settings } from '@/utils/settings';

interface HeaderProps {
inGame: Accessor<boolean>;
Expand All @@ -9,6 +10,9 @@ interface HeaderProps {
solutionShown: Accessor<boolean>;
solved: Accessor<boolean>;
wizard: Accessor<boolean>;
settings: Accessor<Settings>;

setSettingsOpen: Setter<boolean>;

solve: () => void;
trash: () => void;
Expand All @@ -22,12 +26,16 @@ export default function Header(props: HeaderProps) {
<img src="/favicon.svg" />
<h1>dominogod</h1>
</div>
<a target="_blank" href="https://dominofit.isotropic.us/">
go play the original by isotropic.us »
</a>
<Show when={!props.settings().hideEndorsement}>
<a target="_blank" href="https://dominofit.isotropic.us/">
go play the original by isotropic.us »
</a>
</Show>
<div class="util-bar">
<h3>
{!props.inGame() ? '∞' : ((props.currentTime() - props.startTime()) / 1000).toFixed(1)}{' '}
{!props.inGame() || (props.settings().hideTime && !props.solved())
? '∞'
: ((props.currentTime() - props.startTime()) / 1000).toFixed(1)}{' '}
{props.solutionShown() && (
<Motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }}>
🤖
Expand All @@ -44,29 +52,37 @@ export default function Header(props: HeaderProps) {
</Motion.span>
)}
</h3>

<div class="button-bar">
<button onClick={() => props.solve()}>
<TbCpu
style={{
color:
props.solutionShown() || !props.inGame()
? 'var(--color-text-disabled)'
: 'var(--color-text-secondary)',
transition: 'color 250ms',
}}
/>
</button>
<button onClick={() => props.trash()}>
<TbTrash
style={{
color:
props.solved() || !props.inGame()
? 'var(--color-text-disabled)'
: 'var(--color-text-secondary)',
transition: 'color 250ms',
}}
/>
<button onClick={() => props.setSettingsOpen(true)}>
<TbSettings />
</button>
<Show when={props.settings().showSolveButton}>
<button onClick={() => props.solve()}>
<TbCpu
style={{
color:
props.solutionShown() || !props.inGame()
? 'var(--color-text-disabled)'
: 'var(--color-text-secondary)',
transition: 'color 250ms',
}}
/>
</button>
</Show>
<Show when={!props.settings().hideTrash}>
<button onClick={() => props.trash()}>
<TbTrash
style={{
color:
props.solved() || !props.inGame()
? 'var(--color-text-disabled)'
: 'var(--color-text-secondary)',
transition: 'color 250ms',
}}
/>
</button>
</Show>
<button onClick={() => props.reset()}>
<TbDice style={{ color: 'var(--color-text-secondary)' }} />
</button>
Expand Down
Empty file removed src/components/Settings.tsx
Empty file.
83 changes: 83 additions & 0 deletions src/components/SettingsPanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import '@/styles/settings.css';
import { Accessor, For, Setter, Show } from 'solid-js';
import { Motion, Presence } from 'solid-motionone';
import { Settings, saveSettings, settingsDescription } from '@/utils/settings';
import { TbSettings, TbX } from 'solid-icons/tb';

interface SettingsProps {
settings: Accessor<Settings>;
settingsOpen: Accessor<boolean>;

setSettings: Setter<Settings>;
setSettingsOpen: Setter<boolean>;
}

export default function SettingsPanel(props: SettingsProps) {
const closeSettings = () => props.setSettingsOpen(false);

const set = (settings: Settings) => {
saveSettings(settings);
props.setSettings({ ...settings });
};

return (
<>
<Presence exitBeforeEnter>
<Show when={props.settingsOpen()}>
<Motion.div
class="settings-background"
onClick={closeSettings}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
>
<Motion.div
class="settings-container"
onClick={(e) => e.stopPropagation()}
initial={{ y: 10 }}
animate={{ y: 0 }}
exit={{ y: 10 }}
transition={{ duration: 0.25 }}
>
<div class="settings-bar">
<h1>
<TbSettings />
Settings
</h1>
<h1 onClick={closeSettings}>
<TbX />
</h1>
</div>

{/*this has to be busted but like idk the idiomatic way*/}
<For each={Object.keys(props.settings()) as (keyof Settings)[]}>
{(v) => {
const settings = props.settings();
const setting = settings[v];
const settingType = typeof setting;
return (
<div class="setting">
<h2>{settingsDescription[v][0]}</h2>
<p>{settingsDescription[v][1]}</p>
{settingType === 'boolean' && (
<input
type="checkbox"
checked={setting}
onChange={() => {
settings[v] = !setting;
set(settings);
}}
/>
)}
</div>
);
}}
</For>
</Motion.div>
</Motion.div>
</Show>
</Presence>
</>
);
}
29 changes: 25 additions & 4 deletions src/pages/Game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@ import { playDingSound, playPlaceSound } from '@/utils/audio';
import Board from '@/components/Board';
import Footer from '@/components/Footer';
import Header from '@/components/Header';
import { Portal } from 'solid-js/web';
import SettingsPanel from '@/components/SettingsPanel';
import Version from '@/components/Version';
import { clamp } from '@/utils/math';
import { loadSettings } from '@/utils/settings';

export default function Game() {
// audio engine stuff
Expand Down Expand Up @@ -45,6 +48,10 @@ export default function Game() {
const [wizard, setWizard] = createSignal(true);
const [solutionShown, setSolutionShown] = createSignal(false);

// settings
const [settingsOpen, setSettingsOpen] = createSignal(false);
const [settings, setSettings] = createSignal(loadSettings());

const inGame = () => startTime() != -1;
const isOccupied = (x: number, y: number): boolean => {
if (isOutOfBounds(x, y)) return true;
Expand All @@ -55,6 +62,8 @@ export default function Game() {
if (twoMode()) return !isOccupied(x + 1, y);
return !isOccupied(x, y + 1);
};
const setOrToggleTwoMode = (two: boolean) =>
settings().strictControls ? setTwoMode(two) : toggleTwoMode();
const toggleTwoMode = () => setTwoMode(!twoMode());
const rawCoordinates = (): [number, number, number, number] | null => {
const mouse = relativeMouseXY();
Expand Down Expand Up @@ -152,12 +161,14 @@ export default function Game() {
onMount(() => {
const keyHandler = (event: KeyboardEvent) => {
if (!inGame()) return;
if (event.key == 'r') {
if (event.key == 'r' || event.key == 'R') {
event.preventDefault();
reset();
}
if (event.repeat) return;
if (event.key == '1' || event.key == '2' || event.key == ' ') toggleTwoMode();
if (event.key == '1') return setOrToggleTwoMode(false);
if (event.key == '2') return setOrToggleTwoMode(true);
if (event.key == ' ') toggleTwoMode();
};
document.addEventListener('keydown', keyHandler);

Expand Down Expand Up @@ -310,14 +321,24 @@ export default function Game() {

return (
<>
<div class="game">
<Portal>
<SettingsPanel
settings={settings}
settingsOpen={settingsOpen}
setSettings={setSettings}
setSettingsOpen={setSettingsOpen}
/>
</Portal>
<div class={`game ${settings().colorBlindMode ? 'colorblind' : ''}`}>
<Header
inGame={inGame}
currentTime={currentTime}
startTime={startTime}
solutionShown={solutionShown}
solved={solved}
wizard={wizard}
settings={settings}
setSettingsOpen={setSettingsOpen}
solve={solve}
trash={trash}
reset={reset}
Expand Down Expand Up @@ -364,7 +385,7 @@ export default function Game() {
solved={solved}
inGame={inGame}
twoMode={twoMode}
setTwoMode={setTwoMode}
setOrToggleTwoMode={setOrToggleTwoMode}
reset={reset}
/>
</div>
Expand Down
Loading

0 comments on commit b33d18c

Please sign in to comment.