added settings
This commit is contained in:
parent
0b251c566c
commit
99e7325edb
|
|
@ -291,6 +291,7 @@ export const game = {
|
|||
if (finished) return;
|
||||
if (!isValid(serverGame, x, y)) return;
|
||||
if (isRevealed[x][y]) return;
|
||||
serverGame.isFlagged[x][y] = false;
|
||||
serverGame.isQuestionMark[x][y] = true;
|
||||
},
|
||||
clearTile: (serverGame: ServerGame, x: number, y: number) => {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
"@radix-ui/react-dialog": "^1.1.1",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.1",
|
||||
"@radix-ui/react-popover": "^1.1.1",
|
||||
"@radix-ui/react-switch": "^1.1.0",
|
||||
"@tailwindcss/vite": "^4.0.0-alpha.24",
|
||||
"@tanstack/react-query": "^5.56.2",
|
||||
"@tanstack/react-query-devtools": "^5.0.0-alpha.91",
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import Hr from "./components/Hr";
|
|||
import NavLink from "./components/NavLink";
|
||||
import { useMediaQuery } from "@uidotdev/usehooks";
|
||||
import Header from "./components/Header";
|
||||
import { Tag } from "./components/Tag";
|
||||
|
||||
const drawerWidth = 256;
|
||||
const drawerWidthWithPadding = drawerWidth;
|
||||
|
|
@ -67,7 +68,7 @@ const Shell: React.FC<PropsWithChildren> = ({ children }) => {
|
|||
</NavLink>
|
||||
<NavLink href="/settings">
|
||||
<Settings />
|
||||
Settings
|
||||
Settings <Tag size="sm">NEW</Tag>
|
||||
</NavLink>
|
||||
<Hr />
|
||||
<div className="grow" />
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { useWSMutation } from "../../hooks";
|
|||
import { useAtom } from "jotai";
|
||||
import { loginTokenAtom } from "../../atoms";
|
||||
import PasswordInput from "./PasswordInput";
|
||||
import { wsClient } from "../../wsClient";
|
||||
|
||||
const LoginButton = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
@ -57,8 +58,11 @@ const LoginButton = () => {
|
|||
onClick={() => {
|
||||
login
|
||||
.mutateAsync({ username, password })
|
||||
.then((res) => {
|
||||
.then(async (res) => {
|
||||
setToken(res.token);
|
||||
await wsClient.dispatch("user.loginWithToken", {
|
||||
token: JSON.parse(res.token),
|
||||
});
|
||||
queryClient.invalidateQueries();
|
||||
})
|
||||
.catch((e) => {
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import { useAtom } from "jotai";
|
|||
import { loginTokenAtom } from "../../atoms";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import PasswordInput from "./PasswordInput";
|
||||
import { wsClient } from "../../wsClient";
|
||||
|
||||
const RegisterButton = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
@ -57,8 +58,11 @@ const RegisterButton = () => {
|
|||
onClick={() => {
|
||||
register
|
||||
.mutateAsync({ username, password })
|
||||
.then((res) => {
|
||||
.then(async (res) => {
|
||||
setToken(res.token);
|
||||
await wsClient.dispatch("user.loginWithToken", {
|
||||
token: JSON.parse(res.token),
|
||||
});
|
||||
queryClient.invalidateQueries();
|
||||
})
|
||||
.catch((e) => {
|
||||
|
|
|
|||
|
|
@ -239,7 +239,8 @@ const Tile = ({
|
|||
: false;
|
||||
const isFlagged = game.isFlagged[i][j];
|
||||
const isQuestionMark = game.isQuestionMark[i][j];
|
||||
const base = isRevealed ? (
|
||||
const base =
|
||||
isRevealed || isMine ? (
|
||||
<Sprite key="b" texture={theme.revealed} />
|
||||
) : (
|
||||
<Sprite key="b" texture={theme.tile} />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
||||
import { cn } from "../lib/utils";
|
||||
|
||||
const Switch = React.forwardRef<
|
||||
React.ElementRef<typeof SwitchPrimitives.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SwitchPrimitives.Root
|
||||
className={cn(
|
||||
"peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
<SwitchPrimitives.Thumb
|
||||
className={cn(
|
||||
"pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0",
|
||||
)}
|
||||
/>
|
||||
</SwitchPrimitives.Root>
|
||||
));
|
||||
Switch.displayName = SwitchPrimitives.Root.displayName;
|
||||
|
||||
export { Switch };
|
||||
|
|
@ -16,7 +16,7 @@ const tagVariants = cva("font-semibold py-2 px-4 rounded-md flex gap-2", {
|
|||
},
|
||||
size: {
|
||||
default: "h-10 py-2 px-4",
|
||||
sm: "h-9 px-3 rounded-md",
|
||||
sm: "h-7 py-2 px-2 rounded-md text-xs",
|
||||
lg: "h-11 px-8 rounded-md",
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
@import "tailwindcss";
|
||||
|
||||
@theme {
|
||||
--color-primary: rgb(251, 21, 242);
|
||||
--color-primary: #D9AFD9;
|
||||
--color-input: color-mix(in srgb, var(--color-white, #fff) 20%, transparent);
|
||||
--color-background: black;
|
||||
--bg-brand: -webkit-linear-gradient(225deg, rgb(251, 175, 21), rgb(251, 21, 242),
|
||||
rgb(21, 198, 251)) 0% 0% / 100% 300%;
|
||||
--bg-secondary: linear-gradient(90deg, #D9AFD9 0%, #97D9E1 100%) 0% 0% / 100% 300%;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import { Route, Switch } from "wouter";
|
|||
import Endless from "./views/endless/Endless.tsx";
|
||||
import { queryClient } from "./queryClient.ts";
|
||||
import Home from "./views/home/Home.tsx";
|
||||
import Settings from "./views/settings/Settings.tsx";
|
||||
|
||||
connectWS();
|
||||
|
||||
|
|
@ -43,12 +44,7 @@ setup().then(() => {
|
|||
<h2 className="text-white/80 text-2xl">Comming Soon</h2>
|
||||
)}
|
||||
/>
|
||||
<Route
|
||||
path="/settings"
|
||||
component={() => (
|
||||
<h2 className="text-white/80 text-2xl">Comming Soon</h2>
|
||||
)}
|
||||
/>
|
||||
<Route path="/settings" component={Settings} />
|
||||
</Switch>
|
||||
{/* <App /> */}
|
||||
</Shell>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const Endless = () => {
|
|||
setGameId(undefined);
|
||||
};
|
||||
}, [setGameId]);
|
||||
console.log("set", setGameId);
|
||||
|
||||
return game ? (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
import { ReactNode } from "react";
|
||||
import { Switch } from "../../components/Switch";
|
||||
import { useWSMutation, useWSQuery } from "../../hooks";
|
||||
|
||||
interface BoolSettingProps {
|
||||
label: string;
|
||||
description: ReactNode;
|
||||
value: boolean;
|
||||
onChange: (value: boolean) => void;
|
||||
}
|
||||
|
||||
const BoolSetting: React.FC<BoolSettingProps> = ({
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
onChange,
|
||||
}) => (
|
||||
<div className="flex border-white/20 border-1 text-white/80 p-4 rounded-md justify-between items-end">
|
||||
<div className="flex gap-4 flex-col">
|
||||
<label className="text-white/90 text-lg">{label}</label>
|
||||
<p className="text-white/70 text-sm">{description}</p>
|
||||
</div>
|
||||
<Switch checked={value} onCheckedChange={onChange} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const Settings = () => {
|
||||
const { data: settings, refetch } = useWSQuery("user.getSettings", null);
|
||||
const updateSettings = useWSMutation("user.updateSettings");
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="max-w-[650px] mx-auto flex flex-col gap-8">
|
||||
<h2 className="text-white/90 text-xl">Settings</h2>
|
||||
<div className="flex flex-col gap-4 ">
|
||||
<BoolSetting
|
||||
label="Place Question Mark"
|
||||
description={
|
||||
<>
|
||||
You can place a question mark on a tile after placing a flag.
|
||||
<br />
|
||||
Just right click again on the tile.
|
||||
</>
|
||||
}
|
||||
value={settings?.placeQuestionMark ?? false}
|
||||
onChange={async (value) => {
|
||||
await updateSettings.mutateAsync({ placeQuestionMark: value });
|
||||
refetch();
|
||||
}}
|
||||
/>
|
||||
<BoolSetting
|
||||
label="Long Press On Desktop"
|
||||
description={
|
||||
<>
|
||||
You can long press on a tile to reveal it. This is useful for
|
||||
touch devices.
|
||||
</>
|
||||
}
|
||||
value={settings?.longPressOnDesktop ?? false}
|
||||
onChange={async (value) => {
|
||||
updateSettings.mutateAsync({ longPressOnDesktop: value });
|
||||
refetch();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Settings;
|
||||
Loading…
Reference in New Issue