Skip to content

Commit

Permalink
Add cube display to dashboard
Browse files Browse the repository at this point in the history
  • Loading branch information
simonkellly committed May 16, 2024
1 parent 4634c72 commit a6ffdc5
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 59 deletions.
39 changes: 28 additions & 11 deletions src/components/cubing/twisty.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,50 @@
import * as Cubing from 'cubing/twisty';
import { useEffect, useRef } from 'react';
import cube from '/cube-colors.png';
import { useEffect, useRef, useState } from 'react';
import cubeImage from '/cube-colors.png';
import { cn } from '@/lib/utils';
import { useStore } from '@tanstack/react-store';
import { CubeStore } from '@/lib/smartCube';
import { MoveEvent } from 'cubing/bluetooth';

export default function Twisty() {
export default function Twisty({ className }: { className: string }) {
const containerRef = useRef<HTMLDivElement>(null);
const [player, setPlayer] = useState<Cubing.TwistyPlayer | null>(null);
const algs = useStore(CubeStore, (state) => state.appliedMoves);

useEffect(() => {
if (!containerRef.current) return;
console.log('Twisty mounted');
const newViewer = new Cubing.TwistyPlayer({
visualization: 'auto',
experimentalSetupAnchor: 'end',
alg: "y' y' U' E D R2 r2 F2 B2 U E D' R2 L2' z2 S2 U U D D S2 F2' B2",
background: 'none',
hintFacelets: 'none',
controlPanel: 'none',
cameraLatitude: 45,
cameraLongitude: 0,
tempoScale: 1.5,
cameraLatitude: 25,
cameraLongitude: 25,
tempoScale: 2,
experimentalStickering: 'picture',
experimentalSprite: cube,
experimentalSprite: cubeImage,
});

newViewer.style.width = '100%';
newViewer.style.height = '100%';

newViewer.play();
containerRef.current?.replaceChildren(newViewer);
setPlayer(newViewer);
}, [containerRef]);

return <div className="flex w-64 h-64" ref={containerRef} />;
useEffect(() => {
if (!player) return;

const modifiedPlayer = (player as unknown as { APPLIEDMOVES: Set<MoveEvent> | undefined});
const alreadyApplied = modifiedPlayer.APPLIEDMOVES ??= new Set();
algs.forEach((alg) => {
if (alreadyApplied.has(alg)) return;
player.experimentalAddAlgLeaf(alg.latestAlgLeaf);
alreadyApplied.add(alg);
});
}, [player, algs]);

const classes = cn('flex', className);
return <div className={classes} ref={containerRef} />;
}
18 changes: 17 additions & 1 deletion src/lib/smartCube.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
import { Store } from '@tanstack/store';
import * as Bluetooth from 'cubing/bluetooth';

const initialState: { cube: Bluetooth.BluetoothPuzzle | null } = {
const initialState: {
cube: Bluetooth.BluetoothPuzzle | null,
appliedMoves: Bluetooth.MoveEvent[],
} = {
cube: null,
appliedMoves: [],
};

export const CubeStore = new Store(initialState);

export const setPuzzle = (cube: Bluetooth.BluetoothPuzzle | null) => {
CubeStore.setState((state) => ({ ...state, cube, appliedMoves: [] }));
if (!cube) return;
cube.addAlgLeafListener((alg) => {
CubeStore.setState((state) => ({
...state,
appliedMoves: [...state.appliedMoves, alg],
}));
});
};

17 changes: 2 additions & 15 deletions src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,30 +21,20 @@ import {
BluetoothConnected as BTConnected,
} from 'lucide-react';
import React from 'react';
import { Suspense, lazy } from 'react';
import { Button } from '@/components/ui/button';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { CubeStore } from '@/lib/smartCube';
import { CubeStore, setPuzzle } from '@/lib/smartCube';
import { cn } from '@/lib/utils';
import { routeTree } from '@/routeTree.gen';
import bldNinjaLogo from '/bldninja-logo-v1.svg';

type ValidRoutes = ParseRoute<typeof routeTree>['fullPath'];

const TanStackRouterDevtools =
process.env.NODE_ENV === 'production'
? () => null
: lazy(() =>
import('@tanstack/router-devtools').then(res => ({
default: res.TanStackRouterDevtools,
}))
);

function SidebarButton({
label,
icon,
Expand Down Expand Up @@ -87,7 +77,7 @@ function CubeStatus() {
try {
newCube = await Bluetooth.connectSmartPuzzle();
} finally {
CubeStore.setState(state => ({ ...state, cube: newCube }));
setPuzzle(newCube);
}
};

Expand Down Expand Up @@ -152,9 +142,6 @@ export const Route = createRootRoute({
</main>
</div>
</div>
<Suspense>
<TanStackRouterDevtools position="bottom-right" />
</Suspense>
</TooltipProvider>
),
});
56 changes: 27 additions & 29 deletions src/routes/dashboard.lazy.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,39 @@
import { Button } from '@/components/ui/button';
import { CubeStore } from '@/lib/smartCube';
import { createLazyFileRoute } from '@tanstack/react-router';
import { useStore } from '@tanstack/react-store';
import { GanCube } from 'cubing/bluetooth';

export const Route = createLazyFileRoute('/dashboard')({
component: Dashboard,
});

function Dashboard() {
const cube = useStore(CubeStore, state => state.cube);

if (cube === null) return <></>
import Twisty from '@/components/cubing/twisty';
import { CubeStore } from '@/lib/smartCube';
import { useStore } from '@tanstack/react-store';

const action = async () => {
if (!(cube instanceof GanCube)) return;
const ganCube = cube as GanCube;
console.log((await ganCube.getPattern()).toJSON());
await ganCube.reset();
console.log((await ganCube.getPattern()).toJSON());
};
function CubeName() {
const cube = useStore(CubeStore, state => state.cube);
return <>{cube?.name() ?? "Connected Cube"}</>
}

function Dashboard() {

return (
<>
Connected Cube {cube.name()}
<br />
<Button variant="secondary" onClick={action}>
Do Things!
</Button>
</>
<div className="h-full w-full flex flex-col">
<h2 className="text-2xl font-medium text-center p-4 flex-none">
Uw Bw Rw Lw' Uw U Lw2 L Dw' U' Uw2 B2 Lw L D2 Lw Uw' Fw' Rw Bw D2 L2 Dw' Fw'
F U2 Fw2 U2 Dw' Lw2 Fw2 F Rw' Uw' Dw Lw' F' R U' F U' Dw2 Lw F U2 R2 Bw L2
Lw2 Bw2 Fw' L2 B Uw L Lw2 U Dw' Lw Rw
</h2>
<div className="flex grow h-full items-center">
<h1 className="text-8xl font-bold text-white text-center m-auto">1:13.84</h1>
</div>
<div className="w-full grid grid-cols-3">
<fieldset className="rounded-lg border p-4 m-4 hover:bg-muted">
<legend className="-ml-1 px-1 text-sm font-medium">
<CubeName />
</legend>
<Twisty className="w-full h-64 m-auto" />
</fieldset>
</div>
</div>
);

// return (
// <div className="flex flex-col items-center justify-center w-screen h-[calc(100vh-57px)]gap-6">
// <div className="text-3xl font-bold mb-6">R2 U2 F2 R2 B2 D2 L2 D2</div>
// <div className="text-8xl font-bold">12.34</div>
// <Button className="w-full max-w-[200px]">Start/Stop</Button>
// </div>
// );
}
4 changes: 1 addition & 3 deletions src/routes/twisty.lazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ export const Route = createLazyFileRoute('/twisty')({

function TwistyExample() {
return (
<div className="w-64 h-64">
<Twisty />
</div>
<Twisty className="w-64 h-64" />
);
}

0 comments on commit a6ffdc5

Please sign in to comment.