From d287e662652498855537701e5ed64c56e9552063 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 1 Sep 2025 19:01:01 -0500 Subject: [PATCH] feat: upgrade tankopediaEphemeral --- .prettierrc | 7 -- packages/varuna/src/index.ts | 34 +++++----- .../src/pages/[...locale]/guess/_index.tsx | 67 +++++++++---------- .../pages/[...locale]/tanks/[slug]/_index.tsx | 43 ++++++------ .../api/tankopedia/tank-icon/[id]/_index.tsx | 21 +++--- 5 files changed, 83 insertions(+), 89 deletions(-) delete mode 100644 .prettierrc diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 4d4fc7b81..000000000 --- a/.prettierrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "trailingComma": "all", - "tabWidth": 2, - "semi": true, - "singleQuote": true, - "printWidth": 80 -} diff --git a/packages/varuna/src/index.ts b/packages/varuna/src/index.ts index 4cb201bf6..5c29a29a6 100644 --- a/packages/varuna/src/index.ts +++ b/packages/varuna/src/index.ts @@ -1,6 +1,6 @@ -import { produce } from 'immer'; -import { merge } from 'lodash-es'; -import { useEffect, useState } from 'react'; +import { produce } from "immer"; +import { merge } from "lodash-es"; +import { useEffect, useState } from "react"; interface ProviderProps { args: Arguments; @@ -15,19 +15,9 @@ export class Varuna { constructor( private creator: Type | ((...args: Arguments[]) => Type), - private persistence?: string, + private persistence?: string ) { - if (typeof creator !== 'function') this.initialize(creator); - } - - Provider({ args }: ProviderProps) { - if (typeof this.creator !== 'function') { - throw new Error('Provider must be used with a function creator'); - } - - this.initialize((this.creator as (...args: Arguments[]) => Type)(args)); - - return null; + if (typeof creator !== "function") this.initialize(creator); } private initialize(initial: Type) { @@ -47,6 +37,16 @@ export class Varuna { this._state = data; } + useInitialization(...args: Arguments[]) { + if (this.initialized) return; + + if (typeof this.creator !== "function") { + throw new Error("Provider must be used with a function creator"); + } + + this.initialize((this.creator as (...args: Arguments[]) => Type)(...args)); + } + private dispatch() { const state = this.state; this.listeners.forEach((callback) => callback(state)); @@ -72,7 +72,7 @@ export class Varuna { } private assertInitialized() { - if (!this.initialized) throw new Error('State used before initialization'); + if (!this.initialized) throw new Error("State used before initialization"); } get state() { @@ -92,7 +92,7 @@ export class Varuna { } use( - slicer: (state: Type) => Slice = (state) => state as unknown as Slice, + slicer: (state: Type) => Slice = (state) => state as unknown as Slice ) { const [slice, setSlice] = useState(slicer(this.state)); useEffect(() => this.on(slicer, setSlice), []); diff --git a/packages/website/src/pages/[...locale]/guess/_index.tsx b/packages/website/src/pages/[...locale]/guess/_index.tsx index 6df16772e..9a4aac7b1 100644 --- a/packages/website/src/pages/[...locale]/guess/_index.tsx +++ b/packages/website/src/pages/[...locale]/guess/_index.tsx @@ -1,20 +1,20 @@ -import { Box, Flex, Heading } from '@radix-ui/themes'; -import { Suspense } from 'react'; -import { GuessBackground } from '../../../components/GuessBackground'; -import { Guesser } from '../../../components/Guesser'; -import { GuessRenderer } from '../../../components/GuessRenderer'; -import { GuessRendererLoader } from '../../../components/GuessRendererLoader'; -import { awaitableModelDefinitions } from '../../../core/awaitables/modelDefinitions'; -import { awaitableProvisionDefinitions } from '../../../core/awaitables/provisionDefinitions'; -import { awaitableTankDefinitions } from '../../../core/awaitables/tankDefinitions'; +import { Box, Flex, Heading } from "@radix-ui/themes"; +import { Suspense } from "react"; +import { GuessBackground } from "../../../components/GuessBackground"; +import { Guesser } from "../../../components/Guesser"; +import { GuessRenderer } from "../../../components/GuessRenderer"; +import { GuessRendererLoader } from "../../../components/GuessRendererLoader"; +import { awaitableModelDefinitions } from "../../../core/awaitables/modelDefinitions"; +import { awaitableProvisionDefinitions } from "../../../core/awaitables/provisionDefinitions"; +import { awaitableTankDefinitions } from "../../../core/awaitables/tankDefinitions"; import { type LocaleAcceptorProps, LocaleProvider, useLocale, -} from '../../../hooks/useLocale'; -import { Duel } from '../../../stores/duel'; -import { GuessEphemeral } from '../../../stores/guessEphemeral'; -import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; +} from "../../../hooks/useLocale"; +import { Duel } from "../../../stores/duel"; +import { GuessEphemeral } from "../../../stores/guessEphemeral"; +import { TankopediaEphemeral } from "../../../stores/tankopediaEphemeral"; const [tankDefinitions, modelDefinitions, provisionDefinitions] = await Promise.all([ @@ -42,13 +42,12 @@ function Container() { const tank = GuessEphemeral.use((state) => state.tank); const model = modelDefinitions.models[tank.id]; + TankopediaEphemeral.useInitialization(model); + return ( - <> - - - - - + + + ); } @@ -59,7 +58,7 @@ function Content() { const isRevealed = guessState !== null; const name = unwrap(tank.name); const fontSize = `min(48vh, ${55 / name.length}vw)`; - const transitionDuration = isRevealed ? '2s' : undefined; + const transitionDuration = isRevealed ? "2s" : undefined; return ( @@ -70,14 +69,14 @@ function Content() { transitionDuration, opacity: isRevealed ? 1 : 0, fontWeight: 900, - position: 'absolute', - left: '50%', - top: '50%', - transform: 'translate(-50%, -50%)', + position: "absolute", + left: "50%", + top: "50%", + transform: "translate(-50%, -50%)", fontSize, - userSelect: 'none', - whiteSpace: 'nowrap', - pointerEvents: 'none', + userSelect: "none", + whiteSpace: "nowrap", + pointerEvents: "none", }} > {name} @@ -101,14 +100,14 @@ function Content() { transitionDuration, opacity: isRevealed ? 0.5 : 0, fontWeight: 900, - position: 'absolute', - left: '50%', - top: '50%', - transform: 'translate(-50%, -50%)', + position: "absolute", + left: "50%", + top: "50%", + transform: "translate(-50%, -50%)", fontSize, - userSelect: 'none', - whiteSpace: 'nowrap', - pointerEvents: 'none', + userSelect: "none", + whiteSpace: "nowrap", + pointerEvents: "none", }} > {name} diff --git a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx index 49088757b..2ab6ef7cc 100644 --- a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx @@ -1,26 +1,26 @@ -import { TankType } from '@blitzkit/core'; -import { PageWrapper } from '../../../../components/PageWrapper'; -import { CalloutsSection } from '../../../../components/Tankopedia/CalloutsSection'; -import { CharacteristicsSection } from '../../../../components/Tankopedia/CharacteristicsSection'; -import { GameModeSection } from '../../../../components/Tankopedia/GameModeSection'; -import { GuideSection } from '../../../../components/Tankopedia/GuideSection'; -import { HeroSection } from '../../../../components/Tankopedia/HeroSection'; -import { MetaSection } from '../../../../components/Tankopedia/MetaSection'; -import { TechTreeSection } from '../../../../components/Tankopedia/TechTreeSection'; -import { VideoSection } from '../../../../components/Tankopedia/VideoSection'; -import { awaitableModelDefinitions } from '../../../../core/awaitables/modelDefinitions'; -import { awaitableProvisionDefinitions } from '../../../../core/awaitables/provisionDefinitions'; -import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions'; +import { TankType } from "@blitzkit/core"; +import { PageWrapper } from "../../../../components/PageWrapper"; +import { CalloutsSection } from "../../../../components/Tankopedia/CalloutsSection"; +import { CharacteristicsSection } from "../../../../components/Tankopedia/CharacteristicsSection"; +import { GameModeSection } from "../../../../components/Tankopedia/GameModeSection"; +import { GuideSection } from "../../../../components/Tankopedia/GuideSection"; +import { HeroSection } from "../../../../components/Tankopedia/HeroSection"; +import { MetaSection } from "../../../../components/Tankopedia/MetaSection"; +import { TechTreeSection } from "../../../../components/Tankopedia/TechTreeSection"; +import { VideoSection } from "../../../../components/Tankopedia/VideoSection"; +import { awaitableModelDefinitions } from "../../../../core/awaitables/modelDefinitions"; +import { awaitableProvisionDefinitions } from "../../../../core/awaitables/provisionDefinitions"; +import { awaitableTankDefinitions } from "../../../../core/awaitables/tankDefinitions"; import { LocaleProvider, type LocaleAcceptorProps, -} from '../../../../hooks/useLocale'; -import { App } from '../../../../stores/app'; -import { Duel } from '../../../../stores/duel'; -import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral'; -import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent'; -import type { MaybeSkeletonComponentProps } from '../../../../types/maybeSkeletonComponentProps'; -import type { TankGuide } from './index.astro'; +} from "../../../../hooks/useLocale"; +import { App } from "../../../../stores/app"; +import { Duel } from "../../../../stores/duel"; +import { TankopediaEphemeral } from "../../../../stores/tankopediaEphemeral"; +import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent"; +import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps"; +import type { TankGuide } from "./index.astro"; type PageProps = MaybeSkeletonComponentProps & LocaleAcceptorProps & { @@ -39,9 +39,10 @@ export function Page({ id, skeleton, locale, guide }: PageProps) { const tank = tankDefinitions.tanks[id]; const model = modelDefinitions.models[id]; + TankopediaEphemeral.useInitialization(model); + return ( - -