From 30e87743fce77292ac02bc7d27917be88acad159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Tue, 2 Sep 2025 16:24:13 -0500 Subject: [PATCH] feat: upgrade rest of them --- packages/varuna/src/index.ts | 6 +- .../Armor/components/ArmorPlateDisplay.tsx | 5 +- .../PrimaryArmorSceneComponent/index.tsx | 58 ++++---- .../SpacedArmorSubExternal/index.tsx | 28 ++-- .../components/SpacedArmorSubSpaced/index.tsx | 28 ++-- .../SpacedArmorSceneComponent/index.tsx | 12 +- .../Armor/components/StaticArmor.tsx | 29 ++-- .../website/src/components/Checks/index.tsx | 64 ++++----- .../website/src/components/Embeds/Boolean.tsx | 10 +- .../website/src/components/Embeds/Color.tsx | 9 +- .../website/src/components/Embeds/Enum.tsx | 13 +- .../src/components/Embeds/GenerateURL.tsx | 45 +++--- .../website/src/components/Embeds/Import.tsx | 17 ++- .../website/src/components/Embeds/Radius.tsx | 14 +- .../src/components/Embeds/RichText.tsx | 29 ++-- .../website/src/components/Embeds/Size.tsx | 10 +- .../src/components/Embeds/SizeWithout0.tsx | 12 +- .../website/src/components/Embeds/Slider.tsx | 12 +- .../src/components/Embeds/TextController.tsx | 10 +- .../src/components/GuessBackground/index.tsx | 3 +- .../src/components/HomePageHotTanks.tsx | 21 ++- .../src/components/NavbarAccount/index.tsx | 133 ++++++++---------- .../src/components/Performance/Header.tsx | 24 ++-- packages/website/src/components/Plugs.tsx | 25 ++-- .../website/src/components/TankCard/index.tsx | 42 +++--- .../TankSearch/components/RecentlyViewed.tsx | 7 +- .../src/components/TankSearch/index.tsx | 4 +- .../components/Tankopedia/CalloutsSection.tsx | 27 ++-- .../components/Cursor/index.tsx | 57 ++++---- .../Characteristics/components/Firepower.tsx | 53 ++++--- .../GunFlexibilityVisualizer/index.tsx | 91 ++++++------ .../components/ShellSwitcher.tsx | 22 +-- .../components/Consumables.tsx | 33 +++-- .../components/Equipment.tsx | 19 ++- .../components/Miscellaneous.tsx | 37 +++-- .../components/Modules.tsx | 89 ++++++------ .../components/Provisions.tsx | 19 ++- .../components/DynamicArmorSwitcher.tsx | 3 +- .../Options/components/Thicknesses.tsx | 7 +- .../HeroSection/components/Options/index.tsx | 14 +- .../TankSandbox/components/Control.tsx | 10 +- .../TankSandbox/components/TankModel.tsx | 19 ++- .../Tankopedia/HeroSection/index.tsx | 13 +- .../Votes/components/VoteCaster.tsx | 53 ++++--- .../core/zustand/createContextualStore.tsx | 87 ------------ .../[...locale]/auth/[provider]/_index.tsx | 38 ++--- .../src/pages/[...locale]/compare/_index.tsx | 8 +- .../[...locale]/embed/[embed]/_index.tsx | 101 +++++++------ .../[...locale]/embed/[embed]/host/_index.tsx | 30 ++-- .../src/pages/[...locale]/embed/_index.tsx | 114 +++++++-------- .../src/pages/[...locale]/guess/_index.tsx | 18 +-- .../pages/[...locale]/performance/_index.tsx | 19 ++- .../src/pages/[...locale]/settings/_index.tsx | 21 ++- .../pages/[...locale]/tanks/[slug]/_index.tsx | 46 +++--- .../src/pages/[...locale]/tanks/_index.tsx | 16 +-- .../pages/[...locale]/tier-list/_index.tsx | 19 ++- .../api/tankopedia/tank-icon/[id]/_index.tsx | 22 +-- packages/website/src/stores/app/index.ts | 25 ++-- packages/website/src/stores/charts.ts | 15 -- packages/website/src/stores/duel/index.ts | 39 ++--- .../website/src/stores/embedState/index.ts | 27 ++-- .../src/stores/tankPerformanceSort/index.ts | 15 +- .../src/stores/tankopediaPersistent/index.ts | 51 +++---- 63 files changed, 824 insertions(+), 1123 deletions(-) delete mode 100644 packages/website/src/core/zustand/createContextualStore.tsx delete mode 100644 packages/website/src/stores/charts.ts diff --git a/packages/varuna/src/index.ts b/packages/varuna/src/index.ts index 1286e5503..b640eb393 100644 --- a/packages/varuna/src/index.ts +++ b/packages/varuna/src/index.ts @@ -94,8 +94,12 @@ export class Varuna { use( slicer: (state: Type) => Slice = (state) => state as unknown as Slice ) { + return this.useDeferred(slicer, slicer(this.state)); + } + + useDeferred(slicer: (state: Type) => Slice, initial: Slice) { const instance = this; - const [slice, setSlice] = useState(slicer(this.state)); + const [slice, setSlice] = useState(initial); useEffect(() => instance.on(slicer, setSlice), []); diff --git a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx index 3dc063948..9bbc2e524 100644 --- a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx +++ b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx @@ -20,7 +20,6 @@ import { ArmorType } from "./SpacedArmorScene"; export function ArmorPlateDisplay() { const highlightArmor = Tankopedia.use((state) => state.highlightArmor); const developerMode = App.useDeferred((state) => state.developerMode, false); - const duelStore = Duel.useStore(); const input = useRef(null); if (highlightArmor === undefined) return null; @@ -93,7 +92,7 @@ export function ArmorPlateDisplay() { Tankopedia.mutate((draft) => { draft.highlightArmor = undefined; - const { protagonist } = duelStore.getState(); + const { protagonist } = Duel.state; const tank = draft.model; const turret = tank.turrets[protagonist.turret.id]; const gun = turret.guns[protagonist.gun.id]; @@ -142,7 +141,7 @@ export function ArmorPlateDisplay() { draft.highlightArmor = undefined; const initialState = Tankopedia.initial; - const { protagonist } = duelStore.getState(); + const { protagonist } = Duel.state; const tank = draft.model; const initialTank = initialState.model; const turret = tank.turrets[protagonist.turret.id]; diff --git a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx index 6b59e27e9..c1220e84d 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorSceneComponent/index.tsx @@ -41,8 +41,6 @@ export function PrimaryArmorSceneComponent({ node, thickness, }: PrimaryArmorSceneComponentProps) { - const tankopediaPersistentStore = TankopediaPersistent.useStore(); - const duelStore = Duel.useStore(); const material = new ShaderMaterial({ fragmentShader, vertexShader, @@ -80,9 +78,9 @@ export function PrimaryArmorSceneComponent({ useEffect(() => { function handleShellChange() { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; material.uniforms.caliber.value = shell.caliber; material.uniforms.ricochet.value = degToRad( @@ -96,8 +94,14 @@ export function PrimaryArmorSceneComponent({ material.uniforms.damage.value = shell.armor_damage; material.uniforms.explosionRadius.value = shell.explosion_radius; - handleProtagonistEquipmentChange(duel.protagonist.equipmentMatrix, true); - handleAntagonistEquipmentChange(duel.antagonist.equipmentMatrix, true); + handleProtagonistEquipmentChange( + Duel.state.protagonist.equipmentMatrix, + true + ); + handleAntagonistEquipmentChange( + Duel.state.antagonist.equipmentMatrix, + true + ); invalidate(); } @@ -118,10 +122,9 @@ export function PrimaryArmorSceneComponent({ equipment: EquipmentMatrix, noInvalidate = false ) { - const duel = duelStore.getState(); const hasEnhancedArmor = hasEquipment( 110, - duel.protagonist.tank.equipment_preset, + Duel.state.protagonist.tank.equipment_preset, equipment ); material.uniforms.thickness.value = hasEnhancedArmor @@ -134,13 +137,13 @@ export function PrimaryArmorSceneComponent({ equipment: EquipmentMatrix, noInvalidate = false ) { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; const penetration = shell.penetration.near; const hasCalibratedShells = hasEquipment( 103, - duel.antagonist.tank.equipment_preset, + Duel.state.antagonist.tank.equipment_preset, equipment ); @@ -151,40 +154,33 @@ export function PrimaryArmorSceneComponent({ if (!noInvalidate) invalidate(); } - const initialState = tankopediaPersistentStore.getState(); - handleShellChange(); - handleGreenPenetrationChange(initialState.greenPenetration); - handleAdvancedHighlightingChange(initialState.advancedHighlighting); - handleOpaqueChange(initialState.opaque); - handleWireframeChange(initialState.wireframe); - handleProtagonistEquipmentChange( - duelStore.getState().protagonist.equipmentMatrix - ); - handleAntagonistEquipmentChange( - duelStore.getState().antagonist.equipmentMatrix + handleGreenPenetrationChange(TankopediaPersistent.state.greenPenetration); + handleAdvancedHighlightingChange( + TankopediaPersistent.state.advancedHighlighting ); + handleOpaqueChange(TankopediaPersistent.state.opaque); + handleWireframeChange(TankopediaPersistent.state.wireframe); + handleProtagonistEquipmentChange(Duel.state.protagonist.equipmentMatrix); + handleAntagonistEquipmentChange(Duel.state.antagonist.equipmentMatrix); const unsubscribes = [ - duelStore.subscribe((state) => state.antagonist.shell, handleShellChange), + Duel.on((state) => state.antagonist.shell, handleShellChange), Tankopedia.on((state) => state.customShell, handleShellChange), - tankopediaPersistentStore.subscribe( + TankopediaPersistent.on( (state) => state.greenPenetration, handleGreenPenetrationChange ), - tankopediaPersistentStore.subscribe( + TankopediaPersistent.on( (state) => state.advancedHighlighting, handleAdvancedHighlightingChange ), - tankopediaPersistentStore.subscribe( - (state) => state.opaque, - handleOpaqueChange - ), - duelStore.subscribe( + TankopediaPersistent.on((state) => state.opaque, handleOpaqueChange), + Duel.on( (state) => state.protagonist.equipmentMatrix, (equipment) => handleProtagonistEquipmentChange(equipment) ), - duelStore.subscribe( + Duel.on( (state) => state.antagonist.equipmentMatrix, (equipment) => handleAntagonistEquipmentChange(equipment) ), diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx index 8d26029a6..7e1e22390 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubExternal/index.tsx @@ -29,7 +29,6 @@ export function SpacedArmorSubExternal({ variant, clip, }: SpacedArmorSubExternalProps) { - const duelStore = Duel.useStore(); const material = new ShaderMaterial({ fragmentShader, vertexShader, @@ -48,16 +47,15 @@ export function SpacedArmorSubExternal({ useEffect(() => { function handleShellChange() { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; material.uniforms.penetration.value = shell.penetration.near; } function handleProtagonistEquipmentChange(equipment: EquipmentMatrix) { - const duel = duelStore.getState(); const hasEnhancedArmor = hasEquipment( 110, - duel.protagonist.tank.equipment_preset, + Duel.state.protagonist.tank.equipment_preset, equipment ); material.uniforms.thickness.value = hasEnhancedArmor @@ -65,13 +63,13 @@ export function SpacedArmorSubExternal({ : thickness; } function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; const penetration = shell.penetration.near; const hasCalibratedShells = hasEquipment( 103, - duel.antagonist.tank.equipment_preset, + Duel.state.antagonist.tank.equipment_preset, equipment ); @@ -81,21 +79,17 @@ export function SpacedArmorSubExternal({ } handleShellChange(); - handleProtagonistEquipmentChange( - duelStore.getState().protagonist.equipmentMatrix - ); - handleAntagonistEquipmentChange( - duelStore.getState().antagonist.equipmentMatrix - ); + handleProtagonistEquipmentChange(Duel.state.protagonist.equipmentMatrix); + handleAntagonistEquipmentChange(Duel.state.antagonist.equipmentMatrix); const unsubscribes = [ - duelStore.subscribe((state) => state.antagonist.shell, handleShellChange), + Duel.on((state) => state.antagonist.shell, handleShellChange), Tankopedia.on((state) => state.customShell, handleShellChange), - duelStore.subscribe( + Duel.on( (state) => state.protagonist.equipmentMatrix, handleProtagonistEquipmentChange ), - duelStore.subscribe( + Duel.on( (state) => state.antagonist.equipmentMatrix, handleAntagonistEquipmentChange ), diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx index b01b59aab..6e451c9e1 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/components/SpacedArmorSubSpaced/index.tsx @@ -30,7 +30,6 @@ export function SpacedArmorSubSpaced({ node, thickness, }: SpacedArmorSubSpacedProps) { - const duelStore = Duel.useStore(); const material = new ShaderMaterial({ fragmentShader, vertexShader, @@ -50,9 +49,9 @@ export function SpacedArmorSubSpaced({ useEffect(() => { function handleShellChange() { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; material.uniforms.penetration.value = shell.penetration.near; material.uniforms.caliber.value = shell.caliber; @@ -64,10 +63,9 @@ export function SpacedArmorSubSpaced({ ); } function handleProtagonistEquipmentChange(equipment: EquipmentMatrix) { - const duel = duelStore.getState(); const hasEnhancedArmor = hasEquipment( 110, - duel.protagonist.tank.equipment_preset, + Duel.state.protagonist.tank.equipment_preset, equipment ); material.uniforms.thickness.value = hasEnhancedArmor @@ -75,13 +73,13 @@ export function SpacedArmorSubSpaced({ : thickness; } function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) { - const duel = duelStore.getState(); const tankopediaEphemeral = Tankopedia.state; - const shell = tankopediaEphemeral.customShell ?? duel.antagonist.shell; + const shell = + tankopediaEphemeral.customShell ?? Duel.state.antagonist.shell; const penetration = shell.penetration.near; const hasCalibratedShells = hasEquipment( 103, - duel.antagonist.tank.equipment_preset, + Duel.state.antagonist.tank.equipment_preset, equipment ); @@ -91,21 +89,17 @@ export function SpacedArmorSubSpaced({ } handleShellChange(); - handleProtagonistEquipmentChange( - duelStore.getState().protagonist.equipmentMatrix - ); - handleAntagonistEquipmentChange( - duelStore.getState().antagonist.equipmentMatrix - ); + handleProtagonistEquipmentChange(Duel.state.protagonist.equipmentMatrix); + handleAntagonistEquipmentChange(Duel.state.antagonist.equipmentMatrix); const unsubscribes = [ - duelStore.subscribe((state) => state.antagonist.shell, handleShellChange), + Duel.on((state) => state.antagonist.shell, handleShellChange), Tankopedia.on((state) => state.customShell, handleShellChange), - duelStore.subscribe( + Duel.on( (state) => state.protagonist.equipmentMatrix, handleProtagonistEquipmentChange ), - duelStore.subscribe( + Duel.on( (state) => state.antagonist.equipmentMatrix, handleAntagonistEquipmentChange ), diff --git a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx index e5000774d..4c42180fc 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorSceneComponent/index.tsx @@ -76,7 +76,6 @@ export function SpacedArmorSceneComponent({ clip, ...props }: SpacedArmorSceneComponentProps) { - const duelStore = Duel.useStore(); const camera = useThree((state) => state.camera); const shoot = useCallback( @@ -86,9 +85,8 @@ export function SpacedArmorSceneComponent({ allowRicochet: boolean, remainingPenetrationInput?: number ) => { - const { antagonist, protagonist } = duelStore.getState(); const { customShell } = Tankopedia.state; - const shell = customShell ?? antagonist.shell; + const shell = customShell ?? Duel.state.antagonist.shell; const cameraNormal = camera.position.clone().sub(point).normalize(); const shot: Shot = { splashRadius: @@ -104,13 +102,13 @@ export function SpacedArmorSceneComponent({ const hasCalibratedShells = hasEquipment( 103, - antagonist.tank.equipment_preset, - antagonist.equipmentMatrix + Duel.state.antagonist.tank.equipment_preset, + Duel.state.antagonist.equipmentMatrix ); const hasEnhancedArmor = hasEquipment( 110, - protagonist.tank.equipment_preset, - protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const penetration = shell.penetration.near * diff --git a/packages/website/src/components/Armor/components/StaticArmor.tsx b/packages/website/src/components/Armor/components/StaticArmor.tsx index cbe3ec134..5226d626d 100644 --- a/packages/website/src/components/Armor/components/StaticArmor.tsx +++ b/packages/website/src/components/Armor/components/StaticArmor.tsx @@ -46,7 +46,7 @@ export const StaticArmor = memo(({ thicknessRange }) => { const turretOrigin = correctZYTuple(tankModelDefinition.turret_origin); const gunOrigin = correctZYTuple(turretModelDefinition.gun_origin); const canvas = useThree((state) => state.gl.domElement); - const duelStore = Duel.useStore(); + const maskOrigin = gunModelDefinition.mask === undefined ? undefined @@ -165,16 +165,15 @@ export const StaticArmor = memo(({ thicknessRange }) => { window.addEventListener("pointerup", handlePointerUp); } function handlePointerMove(event: PointerEvent) { - const duel = duelStore.getState(); const hasImprovedVerticalStabilizer = hasEquipment( 122, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const hasDownImprovedVerticalStabilizer = hasEquipment( 124, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const boundingRect = canvas.getBoundingClientRect(); @@ -258,16 +257,15 @@ export const StaticArmor = memo(({ thicknessRange }) => { window.addEventListener("pointerup", handlePointerUp); } function handlePointerMove(event: PointerEvent) { - const duel = duelStore.getState(); const hasImprovedVerticalStabilizer = hasEquipment( 122, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const hasDownImprovedVerticalStabilizer = hasEquipment( 124, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const boundingRect = canvas.getBoundingClientRect(); delta.set(event.clientX, event.clientY).sub(position); @@ -339,16 +337,15 @@ export const StaticArmor = memo(({ thicknessRange }) => { window.addEventListener("pointerup", handlePointerUp); } function handlePointerMove(event: PointerEvent) { - const duel = duelStore.getState(); const hasImprovedVerticalStabilizer = hasEquipment( 122, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const hasDownImprovedVerticalStabilizer = hasEquipment( 124, - duel.protagonist.tank.equipment_preset, - duel.protagonist.equipmentMatrix + Duel.state.protagonist.tank.equipment_preset, + Duel.state.protagonist.equipmentMatrix ); const boundingRect = canvas.getBoundingClientRect(); delta.set(event.clientX, event.clientY).sub(position); diff --git a/packages/website/src/components/Checks/index.tsx b/packages/website/src/components/Checks/index.tsx index 7cbbfcaeb..539f99042 100644 --- a/packages/website/src/components/Checks/index.tsx +++ b/packages/website/src/components/Checks/index.tsx @@ -1,19 +1,19 @@ -import { assertSecret, idToRegion } from '@blitzkit/core'; -import { Button, Flex, Heading, Text } from '@radix-ui/themes'; -import { useEffect, useState } from 'react'; +import { assertSecret, idToRegion } from "@blitzkit/core"; +import { Button, Flex, Heading, Text } from "@radix-ui/themes"; +import { useEffect, useState } from "react"; import { LocaleProvider, useLocale, type LocaleAcceptorProps, -} from '../../hooks/useLocale'; -import { App } from '../../stores/app'; -import { CURRENT_POLICIES_AGREEMENT_INDEX } from '../../stores/app/constants'; -import { LinkI18n } from '../LinkI18n'; -import './index.css'; +} from "../../hooks/useLocale"; +import { App } from "../../stores/app"; +import { CURRENT_POLICIES_AGREEMENT_INDEX } from "../../stores/app/constants"; +import { LinkI18n } from "../LinkI18n"; +import "./index.css"; type Extension = | { - status: 'ok'; + status: "ok"; data: { access_token: string; account_id: number; @@ -21,15 +21,13 @@ type Extension = }; } | { - status: 'error'; + status: "error"; }; export function Checks({ locale }: LocaleAcceptorProps) { return ( - - - + ); } @@ -40,19 +38,17 @@ export function Checks({ locale }: LocaleAcceptorProps) { function Content() { const { locale } = useLocale(); const logins = App.use((state) => state.logins); - const mutateApp = App.useMutation(); - const appStore = App.useStore(); const policiesAgreementIndex = App.use( - (state) => state.policiesAgreementIndex, + (state) => state.policiesAgreementIndex ); - const isLegal = window.location.pathname.startsWith('/legal'); + const isLegal = window.location.pathname.startsWith("/legal"); const [showPoliciesAgreement, setShowPoliciesAgreement] = useState(false); useEffect(() => { function unsubscribe() { - window.removeEventListener('scroll', show); - window.removeEventListener('pointermove', show); - window.removeEventListener('pointerdown', show); + window.removeEventListener("scroll", show); + window.removeEventListener("pointermove", show); + window.removeEventListener("pointerdown", show); } function show() { @@ -64,9 +60,9 @@ function Content() { policiesAgreementIndex !== CURRENT_POLICIES_AGREEMENT_INDEX && !isLegal ) { - window.addEventListener('scroll', show); - window.addEventListener('pointermove', show); - window.addEventListener('pointerdown', show); + window.addEventListener("scroll", show); + window.addEventListener("pointermove", show); + window.addEventListener("pointerdown", show); } return unsubscribe; @@ -78,25 +74,25 @@ function Content() { const expiresInDays = expiresIn / 1000 / 60 / 60 / 24; if (expiresInDays < 0) { - mutateApp((draft) => { + App.mutate((draft) => { draft.logins.wargaming = undefined; }); } else if (expiresInDays < 7) { - const { wargaming } = appStore.getState().logins; + const { wargaming } = App.state.logins; if (!wargaming) return; fetch( `https://api.worldoftanks.${idToRegion( - wargaming.id, + wargaming.id )}/wot/auth/prolongate/?application_id=${assertSecret( - import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID, - )}&access_token=${wargaming.token}`, + import.meta.env.PUBLIC_WARGAMING_APPLICATION_ID + )}&access_token=${wargaming.token}` ) .then((response) => response.json() as Promise) .then((json) => { - mutateApp((draft) => { - if (json.status === 'error') { + App.mutate((draft) => { + if (json.status === "error") { draft.logins.wargaming = undefined; } else { draft.logins.wargaming = { @@ -126,11 +122,11 @@ function Content() { This website utilizes cookies to perform analytics and personalize - your experience. You can learn more through{' '} + your experience. You can learn more through{" "} our privacy policy - . By using BlitzKit, you also agree to our{' '} + . By using BlitzKit, you also agree to our{" "} terms of service @@ -141,8 +137,8 @@ function Content() { @@ -144,7 +143,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { - + { @@ -156,7 +155,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { {literals( strings.website.tools.embed.configuration.export.generate .success.info, - [`${copyUser?.nickname}`], + [`${copyUser?.nickname}`] )} @@ -170,7 +169,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { setSearchDialogOpen(true); }} > - {' '} + {" "} { strings.website.tools.embed.configuration.export.generate .success.back @@ -181,12 +180,10 @@ export function GenerateURL({ embed }: GenerateURLProps) { copy={() => { if (!copyUser) return; - const state = embedStateStore.getState(); - const initial = embedStateStore.getInitialState(); const shallowState: EmbedStateStore = {}; - Object.entries(state).forEach(([key, value]) => { - if (value !== initial[key]) { + Object.entries(EmbedState.state).forEach(([key, value]) => { + if (value !== EmbedState.initial[key]) { shallowState[key] = value; } }); @@ -202,7 +199,7 @@ export function GenerateURL({ embed }: GenerateURLProps) { return `${location.origin}/embed/${embed}/host?${searchParams.toString()}`; }} > - {' '} + {" "} { strings.website.tools.embed.configuration.export.generate .success.copy diff --git a/packages/website/src/components/Embeds/Import.tsx b/packages/website/src/components/Embeds/Import.tsx index 9c45952d2..237128993 100644 --- a/packages/website/src/components/Embeds/Import.tsx +++ b/packages/website/src/components/Embeds/Import.tsx @@ -6,17 +6,16 @@ import { Text, TextField, Tooltip, -} from '@radix-ui/themes'; -import { useRef, useState } from 'react'; -import { parse } from 'urlon'; -import { useLocale } from '../../hooks/useLocale'; -import { EmbedState } from '../../stores/embedState'; +} from "@radix-ui/themes"; +import { useRef, useState } from "react"; +import { parse } from "urlon"; +import { useLocale } from "../../hooks/useLocale"; +import { EmbedState } from "../../stores/embedState"; export function Import() { const importInput = useRef(null); const [showInvalidURLPrompt, setShowInvalidURLPrompt] = useState(false); const [showConfirmation, setConfirmation] = useState(false); - const mutateEmbedState = EmbedState.useMutation(); const { strings } = useLocale(); return ( @@ -64,15 +63,15 @@ export function Import() { try { const url = new URL(importInput.current.value); - const state = url.searchParams.get('state'); + const state = url.searchParams.get("state"); if (state === null) throw undefined; const json = parse(state); - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { Object.assign(draft, json); }); - importInput.current.value = ''; + importInput.current.value = ""; setConfirmation(true); setTimeout(() => setConfirmation(false), 2000); } catch { diff --git a/packages/website/src/components/Embeds/Radius.tsx b/packages/website/src/components/Embeds/Radius.tsx index 28009a46a..f7c76775c 100644 --- a/packages/website/src/components/Embeds/Radius.tsx +++ b/packages/website/src/components/Embeds/Radius.tsx @@ -1,10 +1,8 @@ -import { Slider } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState, type RadixRadius } from '../../stores/embedState'; +import { Slider } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState, type RadixRadius } from "../../stores/embedState"; export function Radius({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - return ( { const radius = state[configKey] as RadixRadius; - return radius === 'full' ? 5 : parseInt(radius); + return radius === "full" ? 5 : parseInt(radius); }), ]} onValueChange={([value]) => { - mutateEmbedState((draft) => { - draft[configKey] = value === 5 ? 'full' : `${value}`; + EmbedState.mutate((draft) => { + draft[configKey] = value === 5 ? "full" : `${value}`; }); }} /> diff --git a/packages/website/src/components/Embeds/RichText.tsx b/packages/website/src/components/Embeds/RichText.tsx index 1894b969a..469be74e6 100644 --- a/packages/website/src/components/Embeds/RichText.tsx +++ b/packages/website/src/components/Embeds/RichText.tsx @@ -1,21 +1,18 @@ -import { FontBoldIcon, FontSizeIcon } from '@radix-ui/react-icons'; -import { Flex, Slider, Text } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState, type RadixSizeWithout0 } from '../../stores/embedState'; +import { FontBoldIcon, FontSizeIcon } from "@radix-ui/react-icons"; +import { Flex, Slider, Text } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState, type RadixSizeWithout0 } from "../../stores/embedState"; import { radixTextWeights, type EmbedConfigItemType, type EmbedItemType, -} from '../../stores/embedState/constants'; -import { ColorControllerRaw } from './ColorControllerRaw'; +} from "../../stores/embedState/constants"; +import { ColorControllerRaw } from "./ColorControllerRaw"; export function RichText({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); const state = EmbedState.use( (state) => - state[ - configKey - ] as EmbedConfigItemType['default'], + state[configKey] as EmbedConfigItemType["default"] ); return ( @@ -24,11 +21,11 @@ export function RichText({ configKey }: EmbedPreviewControllerProps) { { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { ( draft[ configKey - ] as EmbedConfigItemType['default'] + ] as EmbedConfigItemType["default"] ).color = value; }); }} @@ -45,11 +42,11 @@ export function RichText({ configKey }: EmbedPreviewControllerProps) { max={9} value={[Number(state.size)]} onValueChange={([value]) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { ( draft[ configKey - ] as EmbedConfigItemType['default'] + ] as EmbedConfigItemType["default"] ).size = `${value}` as RadixSizeWithout0; }); }} @@ -66,11 +63,11 @@ export function RichText({ configKey }: EmbedPreviewControllerProps) { max={radixTextWeights.length - 1} value={[radixTextWeights.indexOf(state.weight)]} onValueChange={([value]) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { ( draft[ configKey - ] as EmbedConfigItemType['default'] + ] as EmbedConfigItemType["default"] ).weight = radixTextWeights[value]; }); }} diff --git a/packages/website/src/components/Embeds/Size.tsx b/packages/website/src/components/Embeds/Size.tsx index 39a54ea40..8a28ecdf7 100644 --- a/packages/website/src/components/Embeds/Size.tsx +++ b/packages/website/src/components/Embeds/Size.tsx @@ -1,10 +1,8 @@ -import { Slider } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState, type RadixSize } from '../../stores/embedState'; +import { Slider } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState, type RadixSize } from "../../stores/embedState"; export function Size({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - return ( parseInt(state[configKey] as RadixSize)), ]} onValueChange={([value]) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { draft[configKey] = `${value}`; }); }} diff --git a/packages/website/src/components/Embeds/SizeWithout0.tsx b/packages/website/src/components/Embeds/SizeWithout0.tsx index 02f155661..b2ae6356e 100644 --- a/packages/website/src/components/Embeds/SizeWithout0.tsx +++ b/packages/website/src/components/Embeds/SizeWithout0.tsx @@ -1,10 +1,8 @@ -import { Slider } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState, type RadixSizeWithout0 } from '../../stores/embedState'; +import { Slider } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState, type RadixSizeWithout0 } from "../../stores/embedState"; export function SizeWithout0({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - return ( - parseInt(state[configKey] as RadixSizeWithout0), + parseInt(state[configKey] as RadixSizeWithout0) ), ]} onValueChange={([value]) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { draft[configKey] = `${value}`; }); }} diff --git a/packages/website/src/components/Embeds/Slider.tsx b/packages/website/src/components/Embeds/Slider.tsx index d45f085d5..0302fe82e 100644 --- a/packages/website/src/components/Embeds/Slider.tsx +++ b/packages/website/src/components/Embeds/Slider.tsx @@ -1,10 +1,10 @@ -import { Slider as RadixSlider } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState, type RadixSize } from '../../stores/embedState'; +import { Slider as RadixSlider } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState, type RadixSize } from "../../stores/embedState"; import type { EmbedConfigItemType, EmbedItemType, -} from '../../stores/embedState/constants'; +} from "../../stores/embedState/constants"; export function Slider({ configKey, @@ -12,8 +12,6 @@ export function Slider({ }: EmbedPreviewControllerProps & { config: EmbedConfigItemType; }) { - const mutateEmbedState = EmbedState.useMutation(); - return ( parseInt(state[configKey] as RadixSize)), ]} onValueChange={([value]) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { draft[configKey] = value; }); }} diff --git a/packages/website/src/components/Embeds/TextController.tsx b/packages/website/src/components/Embeds/TextController.tsx index 91ae643b5..b7f6d4bc8 100644 --- a/packages/website/src/components/Embeds/TextController.tsx +++ b/packages/website/src/components/Embeds/TextController.tsx @@ -1,17 +1,15 @@ -import { TextField } from '@radix-ui/themes'; -import type { EmbedPreviewControllerProps } from '../../pages/[...locale]/embed/[embed]/_index'; -import { EmbedState } from '../../stores/embedState'; +import { TextField } from "@radix-ui/themes"; +import type { EmbedPreviewControllerProps } from "../../pages/[...locale]/embed/[embed]/_index"; +import { EmbedState } from "../../stores/embedState"; export function TextController({ configKey }: EmbedPreviewControllerProps) { - const mutateEmbedState = EmbedState.useMutation(); - return ( state[configKey] as string)} onChange={(event) => { - mutateEmbedState((draft) => { + EmbedState.mutate((draft) => { draft[configKey] = event.target.value; }); }} diff --git a/packages/website/src/components/GuessBackground/index.tsx b/packages/website/src/components/GuessBackground/index.tsx index 447098f65..6923b9fbe 100644 --- a/packages/website/src/components/GuessBackground/index.tsx +++ b/packages/website/src/components/GuessBackground/index.tsx @@ -17,10 +17,9 @@ const [modelDefinitions, provisionDefinitions] = await Promise.all([ export function GuessBackground() { const guessState = Guess.use((state) => state.guessState); const tank = Guess.use((state) => state.tank); - const mutateDuel = Duel.useMutation(); useEffect(() => { - mutateDuel((state) => { + Duel.mutate((state) => { state.protagonist = tankToDuelMember(tank, provisionDefinitions); }); Tankopedia.mutate((state) => { diff --git a/packages/website/src/components/HomePageHotTanks.tsx b/packages/website/src/components/HomePageHotTanks.tsx index 9a326cf49..f15506e4e 100644 --- a/packages/website/src/components/HomePageHotTanks.tsx +++ b/packages/website/src/components/HomePageHotTanks.tsx @@ -1,15 +1,14 @@ -import { literals } from '@blitzkit/i18n/src/literals'; -import { EyeOpenIcon } from '@radix-ui/react-icons'; -import { Box, Flex, Heading, Text } from '@radix-ui/themes'; -import { awaitablePopularTanks } from '../core/awaitables/popularTanks'; -import { awaitableTankDefinitions } from '../core/awaitables/tankDefinitions'; +import { literals } from "@blitzkit/i18n/src/literals"; +import { EyeOpenIcon } from "@radix-ui/react-icons"; +import { Box, Flex, Heading, Text } from "@radix-ui/themes"; +import { awaitablePopularTanks } from "../core/awaitables/popularTanks"; +import { awaitableTankDefinitions } from "../core/awaitables/tankDefinitions"; import { LocaleProvider, useLocale, type LocaleAcceptorProps, -} from '../hooks/useLocale'; -import { TankopediaPersistent } from '../stores/tankopediaPersistent'; -import { TankCard } from './TankCard'; +} from "../hooks/useLocale"; +import { TankCard } from "./TankCard"; const [tankDefinitions, popularTanks] = await Promise.all([ awaitableTankDefinitions, @@ -19,9 +18,7 @@ const [tankDefinitions, popularTanks] = await Promise.all([ export function HomePageHotTanks({ locale }: LocaleAcceptorProps) { return ( - - - + ); } @@ -35,7 +32,7 @@ function Content() { {strings.website.home.hot_tanks.title} - {literals(strings.website.home.hot_tanks.subtitle, ['7'])} + {literals(strings.website.home.hot_tanks.subtitle, ["7"])} diff --git a/packages/website/src/components/NavbarAccount/index.tsx b/packages/website/src/components/NavbarAccount/index.tsx index 41e457268..d150be2dd 100644 --- a/packages/website/src/components/NavbarAccount/index.tsx +++ b/packages/website/src/components/NavbarAccount/index.tsx @@ -1,4 +1,4 @@ -import { PersonIcon } from '@radix-ui/react-icons'; +import { PersonIcon } from "@radix-ui/react-icons"; import { Button, Flex, @@ -6,91 +6,78 @@ import { Popover, Skeleton, Text, -} from '@radix-ui/themes'; -import { Suspense } from 'react'; -import { App } from '../../stores/app'; -import { BlitzKitTheme } from '../BlitzKitTheme'; -import { WargamingAccountName } from '../WargamingAccountName'; -import { WargamingIcon } from '../WargamingIcon'; -import { WargamingLoginButton } from '../WargamingLoginButton'; +} from "@radix-ui/themes"; +import { Suspense } from "react"; +import { App } from "../../stores/app"; +import { BlitzKitTheme } from "../BlitzKitTheme"; +import { WargamingAccountName } from "../WargamingAccountName"; +import { WargamingIcon } from "../WargamingIcon"; +import { WargamingLoginButton } from "../WargamingLoginButton"; export function NavbarAccount() { - return ( - - - - ); -} - -function Content() { const logins = App.use((state) => state.logins); - const mutateApp = App.useMutation(); return ( - - - - - - - + + + + + + - - event.preventDefault()} - > - {logins.wargaming && ( - - - Logged in accounts - + + event.preventDefault()} + > + {logins.wargaming && ( + + + Logged in accounts + - {logins.wargaming && ( - - - - } - > - - - - - - )} - - )} + {logins.wargaming && ( + + + + }> + + + + + + )} + + )} - {/* {!logins. !== !logins.wargaming && ( + {/* {!logins. !== !logins.wargaming && ( )} */} - {!logins.wargaming && ( - - - Log in with... - + {!logins.wargaming && ( + + + Log in with... + - {!logins.wargaming && } - - )} - - - - + {!logins.wargaming && } + + )} + + + ); } diff --git a/packages/website/src/components/Performance/Header.tsx b/packages/website/src/components/Performance/Header.tsx index fbbfb5b39..4ab8a23bc 100644 --- a/packages/website/src/components/Performance/Header.tsx +++ b/packages/website/src/components/Performance/Header.tsx @@ -2,16 +2,15 @@ import { CaretDownIcon, CaretSortIcon, CaretUpIcon, -} from '@radix-ui/react-icons'; -import { Button, Flex, Table } from '@radix-ui/themes'; -import { useLocale } from '../../hooks/useLocale'; -import { TankPerformanceSort } from '../../stores/tankPerformanceSort'; -import { TankPerformanceSortTypeNamesArray } from '../../stores/tankPerformanceSort/constants'; -import { StickyColumnHeaderCell } from '../StickyColumnHeaderCell'; +} from "@radix-ui/react-icons"; +import { Button, Flex, Table } from "@radix-ui/themes"; +import { useLocale } from "../../hooks/useLocale"; +import { TankPerformanceSort } from "../../stores/tankPerformanceSort"; +import { TankPerformanceSortTypeNamesArray } from "../../stores/tankPerformanceSort/constants"; +import { StickyColumnHeaderCell } from "../StickyColumnHeaderCell"; export function Header() { const sort = TankPerformanceSort.use(); - const store = TankPerformanceSort.useStore(); const { strings } = useLocale(); return ( @@ -34,13 +33,18 @@ export function Header() { @@ -211,11 +204,11 @@ function Content({ embed }: PageProps) { return ( { @@ -229,7 +222,7 @@ function Content({ embed }: PageProps) { gap="2" align="center" flexGrow="1" - justify={oneLiner ? 'end' : undefined} + justify={oneLiner ? "end" : undefined} > {control} @@ -250,9 +243,9 @@ function Content({ embed }: PageProps) { direction="column" height="100%" style={{ - borderRadius: 'var(--radius-3)', - overflow: 'hidden', - boxShadow: 'var(--shadow-3)', + borderRadius: "var(--radius-3)", + overflow: "hidden", + boxShadow: "var(--shadow-3)", }} > diff --git a/packages/website/src/pages/[...locale]/embed/[embed]/host/_index.tsx b/packages/website/src/pages/[...locale]/embed/[embed]/host/_index.tsx index 755f5b248..17691f545 100644 --- a/packages/website/src/pages/[...locale]/embed/[embed]/host/_index.tsx +++ b/packages/website/src/pages/[...locale]/embed/[embed]/host/_index.tsx @@ -1,22 +1,22 @@ -import { Box } from '@radix-ui/themes'; -import { useMemo } from 'react'; -import { parse } from 'urlon'; -import { BlitzKitTheme } from '../../../../../components/BlitzKitTheme'; +import { Box } from "@radix-ui/themes"; +import { useMemo } from "react"; +import { parse } from "urlon"; +import { BlitzKitTheme } from "../../../../../components/BlitzKitTheme"; import { embedConfigurations, embedRenderers, extractEmbedConfigDefaults, -} from '../../../../../constants/embeds'; +} from "../../../../../constants/embeds"; import { LocaleProvider, type LocaleAcceptorProps, -} from '../../../../../hooks/useLocale'; +} from "../../../../../hooks/useLocale"; import { EmbedState, type EmbedConfig, type ExtractEmbedConfigTypes, -} from '../../../../../stores/embedState'; -import { useEmbedStateCurry } from '../../../../../stores/embedState/utilities'; +} from "../../../../../stores/embedState"; +import { useEmbedStateCurry } from "../../../../../stores/embedState/utilities"; interface PageProps { embed: keyof typeof embedConfigurations; @@ -25,7 +25,7 @@ interface PageProps { export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) { const state = useMemo(() => { const params = new URLSearchParams(window.location.search); - const stateRaw = params.get('state'); + const stateRaw = params.get("state"); const partialState = stateRaw === null ? {} : parse(stateRaw); const state = { ...extractEmbedConfigDefaults(embedConfigurations[embed]), @@ -35,11 +35,11 @@ export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) { return state; }, [embed]); + EmbedState.useInitialization(state); + return ( - - - + ); } @@ -47,11 +47,11 @@ export function Page({ embed, locale }: PageProps & LocaleAcceptorProps) { function Content({ embed }: PageProps) { const Renderer = embedRenderers[embed]; const { useEmbedState } = useEmbedStateCurry(); - const width = useEmbedState('width'); - const height = useEmbedState('height'); + const width = useEmbedState("width"); + const height = useEmbedState("height"); return ( - + diff --git a/packages/website/src/pages/[...locale]/embed/_index.tsx b/packages/website/src/pages/[...locale]/embed/_index.tsx index 47cd697b4..73f504434 100644 --- a/packages/website/src/pages/[...locale]/embed/_index.tsx +++ b/packages/website/src/pages/[...locale]/embed/_index.tsx @@ -1,26 +1,19 @@ -import { Box, Flex, Link, Text } from '@radix-ui/themes'; -import { PreviewWrapper } from '../../../components/Embeds/PreviewWrapper'; -import { LinkI18n } from '../../../components/LinkI18n'; -import { PageWrapper } from '../../../components/PageWrapper'; -import { - embedConfigurations, - extractEmbedConfigDefaults, -} from '../../../constants/embeds'; -import { Var } from '../../../core/radix/var'; +import { Box, Flex, Link, Text } from "@radix-ui/themes"; +import { PreviewWrapper } from "../../../components/Embeds/PreviewWrapper"; +import { LinkI18n } from "../../../components/LinkI18n"; +import { PageWrapper } from "../../../components/PageWrapper"; +import { embedConfigurations } from "../../../constants/embeds"; +import { Var } from "../../../core/radix/var"; import { type LocaleAcceptorProps, LocaleProvider, useLocale, -} from '../../../hooks/useLocale'; -import { App } from '../../../stores/app'; -import { EmbedState } from '../../../stores/embedState'; +} from "../../../hooks/useLocale"; export function Page({ locale }: LocaleAcceptorProps) { return ( - - - + ); } @@ -31,7 +24,7 @@ function Content() { return ( - {strings.website.tools.embed.coming_soon}{' '} + {strings.website.tools.embed.coming_soon}{" "} - {Object.entries(embedConfigurations).map(([embed, config]) => ( - ( + - - + + { + strings.website.tools.embed.types[ + embed as keyof typeof strings.website.tools.embed.types + ].name + } + + + + - - - { - strings.website.tools.embed.types[ - embed as keyof typeof strings.website.tools.embed.types - ].name - } - - - - - - - - - + + + + ))} diff --git a/packages/website/src/pages/[...locale]/guess/_index.tsx b/packages/website/src/pages/[...locale]/guess/_index.tsx index 8edd06879..86a2b046b 100644 --- a/packages/website/src/pages/[...locale]/guess/_index.tsx +++ b/packages/website/src/pages/[...locale]/guess/_index.tsx @@ -5,7 +5,6 @@ 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, @@ -16,12 +15,10 @@ import { Duel } from "../../../stores/duel"; import { Guess, GuessState } from "../../../stores/guess"; import { Tankopedia } from "../../../stores/tankopedia"; -const [tankDefinitions, modelDefinitions, provisionDefinitions] = - await Promise.all([ - awaitableTankDefinitions, - awaitableModelDefinitions, - awaitableProvisionDefinitions, - ]); +const [tankDefinitions, modelDefinitions] = await Promise.all([ + awaitableTankDefinitions, + awaitableModelDefinitions, +]); const ids = Object.keys(tankDefinitions.tanks); @@ -43,12 +40,9 @@ function Container() { const model = modelDefinitions.models[tank.id]; Tankopedia.useInitialization(model); + Duel.useInitialization({ tank, model }); - return ( - - - - ); + return ; } function Content() { diff --git a/packages/website/src/pages/[...locale]/performance/_index.tsx b/packages/website/src/pages/[...locale]/performance/_index.tsx index 3f5b6fdd2..0fa497d1f 100644 --- a/packages/website/src/pages/[...locale]/performance/_index.tsx +++ b/packages/website/src/pages/[...locale]/performance/_index.tsx @@ -1,23 +1,20 @@ -import { PageWrapper } from '../../../components/PageWrapper'; -import { PerformanceInfo } from '../../../components/Performance/PerformanceInfo'; -import { PlayerCountControl } from '../../../components/Performance/PlayerCountControl'; -import { TankTable } from '../../../components/Performance/Table'; -import { FilterControl } from '../../../components/TankSearch/components/FilterControl'; +import { PageWrapper } from "../../../components/PageWrapper"; +import { PerformanceInfo } from "../../../components/Performance/PerformanceInfo"; +import { PlayerCountControl } from "../../../components/Performance/PlayerCountControl"; +import { TankTable } from "../../../components/Performance/Table"; +import { FilterControl } from "../../../components/TankSearch/components/FilterControl"; import { LocaleProvider, type LocaleAcceptorProps, -} from '../../../hooks/useLocale'; -import { TankPerformanceSort } from '../../../stores/tankPerformanceSort'; -import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonComponentProps'; +} from "../../../hooks/useLocale"; +import type { MaybeSkeletonComponentProps } from "../../../types/maybeSkeletonComponentProps"; type PageProps = MaybeSkeletonComponentProps & LocaleAcceptorProps; export function Page({ skeleton, locale }: PageProps) { return ( - - - + ); } diff --git a/packages/website/src/pages/[...locale]/settings/_index.tsx b/packages/website/src/pages/[...locale]/settings/_index.tsx index db74d3b03..48a97d3f5 100644 --- a/packages/website/src/pages/[...locale]/settings/_index.tsx +++ b/packages/website/src/pages/[...locale]/settings/_index.tsx @@ -1,27 +1,24 @@ -import { DEFAULT_LOCALE } from '@blitzkit/i18n'; -import { Flex, Switch, Text } from '@radix-ui/themes'; -import { LocaleSwitcher } from '../../../components/LocaleSwitcher'; -import { PageWrapper } from '../../../components/PageWrapper'; +import { DEFAULT_LOCALE } from "@blitzkit/i18n"; +import { Flex, Switch, Text } from "@radix-ui/themes"; +import { LocaleSwitcher } from "../../../components/LocaleSwitcher"; +import { PageWrapper } from "../../../components/PageWrapper"; import { LocaleProvider, useLocale, type LocaleAcceptorProps, -} from '../../../hooks/useLocale'; -import { App } from '../../../stores/app'; +} from "../../../hooks/useLocale"; +import { App } from "../../../stores/app"; export function Page({ locale = DEFAULT_LOCALE }: LocaleAcceptorProps) { return ( - - - + ); } function Content({ locale }: LocaleAcceptorProps) { const developerMode = App.useDeferred((state) => state.developerMode, false); - const appStore = App.useStore(); const { strings } = useLocale(); return ( @@ -33,7 +30,9 @@ function Content({ locale }: LocaleAcceptorProps) { variant="classic" checked={developerMode} onCheckedChange={(checked) => - appStore.setState({ developerMode: checked }) + App.mutate((draft) => { + draft.developerMode = checked; + }) } /> diff --git a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx index 5b4e0fe50..b8db6c973 100644 --- a/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx +++ b/packages/website/src/pages/[...locale]/tanks/[slug]/_index.tsx @@ -9,16 +9,13 @@ 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 { Tankopedia } from "../../../../stores/tankopedia"; -import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent"; import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps"; import type { TankGuide } from "./index.astro"; @@ -28,41 +25,32 @@ type PageProps = MaybeSkeletonComponentProps & guide?: TankGuide; }; -const [tankDefinitions, provisionDefinitions, modelDefinitions] = - await Promise.all([ - awaitableTankDefinitions, - awaitableProvisionDefinitions, - awaitableModelDefinitions, - ]); +const [tankDefinitions, modelDefinitions] = await Promise.all([ + awaitableTankDefinitions, + awaitableModelDefinitions, +]); export function Page({ id, skeleton, locale, guide }: PageProps) { const tank = tankDefinitions.tanks[id]; const model = modelDefinitions.models[id]; Tankopedia.useInitialization(model); + Duel.useInitialization({ tank, model }); return ( - - - - - - - - {tank.type === TankType.RESEARCHABLE && !tank.deprecated && ( - - )} - - - {guide && } - - - - - + + + + + {tank.type === TankType.RESEARCHABLE && !tank.deprecated && ( + + )} + + + {guide && } + + ); } diff --git a/packages/website/src/pages/[...locale]/tanks/_index.tsx b/packages/website/src/pages/[...locale]/tanks/_index.tsx index 00813f68c..f5b22a310 100644 --- a/packages/website/src/pages/[...locale]/tanks/_index.tsx +++ b/packages/website/src/pages/[...locale]/tanks/_index.tsx @@ -1,12 +1,10 @@ -import { PageWrapper } from '../../../components/PageWrapper'; -import { TankSearch } from '../../../components/TankSearch'; +import { PageWrapper } from "../../../components/PageWrapper"; +import { TankSearch } from "../../../components/TankSearch"; import { LocaleProvider, type LocaleAcceptorProps, -} from '../../../hooks/useLocale'; -import { App } from '../../../stores/app'; -import { TankopediaPersistent } from '../../../stores/tankopediaPersistent'; -import type { MaybeSkeletonComponentProps } from '../../../types/maybeSkeletonComponentProps'; +} from "../../../hooks/useLocale"; +import type { MaybeSkeletonComponentProps } from "../../../types/maybeSkeletonComponentProps"; export function Page({ locale, @@ -15,11 +13,7 @@ export function Page({ return ( - - - - - + ); diff --git a/packages/website/src/pages/[...locale]/tier-list/_index.tsx b/packages/website/src/pages/[...locale]/tier-list/_index.tsx index d5ff92235..37429bd3c 100644 --- a/packages/website/src/pages/[...locale]/tier-list/_index.tsx +++ b/packages/website/src/pages/[...locale]/tier-list/_index.tsx @@ -1,21 +1,18 @@ -import { PageWrapper } from '../../../components/PageWrapper'; -import { FilterControl } from '../../../components/TankSearch/components/FilterControl'; -import { TierListControls } from '../../../components/TierList/Controls'; -import { TierListTable } from '../../../components/TierList/Table'; -import { TierListTiles } from '../../../components/TierList/Tiles'; -import { URLManager } from '../../../components/TierList/URLManager'; +import { PageWrapper } from "../../../components/PageWrapper"; +import { FilterControl } from "../../../components/TankSearch/components/FilterControl"; +import { TierListControls } from "../../../components/TierList/Controls"; +import { TierListTable } from "../../../components/TierList/Table"; +import { TierListTiles } from "../../../components/TierList/Tiles"; +import { URLManager } from "../../../components/TierList/URLManager"; import { LocaleProvider, type LocaleAcceptorProps, -} from '../../../hooks/useLocale'; -import { TankopediaPersistent } from '../../../stores/tankopediaPersistent'; +} from "../../../hooks/useLocale"; export function Page({ locale }: LocaleAcceptorProps) { return ( - - - + ); } diff --git a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx index 59ed743e7..598cc77b6 100644 --- a/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx +++ b/packages/website/src/pages/api/tankopedia/tank-icon/[id]/_index.tsx @@ -1,19 +1,14 @@ import { TankSandbox } from "../../../../../components/Tankopedia/HeroSection/components/TankSandbox"; import { awaitableModelDefinitions } from "../../../../../core/awaitables/modelDefinitions"; -import { awaitableProvisionDefinitions } from "../../../../../core/awaitables/provisionDefinitions"; import { awaitableTankDefinitions } from "../../../../../core/awaitables/tankDefinitions"; import { LocaleProvider } from "../../../../../hooks/useLocale"; -import { App } from "../../../../../stores/app"; import { Duel } from "../../../../../stores/duel"; import { Tankopedia } from "../../../../../stores/tankopedia"; -import { TankopediaPersistent } from "../../../../../stores/tankopediaPersistent"; -const [provisionDefinitions, tankDefinitions, modelDefinitions] = - await Promise.all([ - awaitableProvisionDefinitions, - awaitableTankDefinitions, - awaitableModelDefinitions, - ]); +const [tankDefinitions, modelDefinitions] = await Promise.all([ + awaitableTankDefinitions, + awaitableModelDefinitions, +]); interface PageProps { id: number; @@ -24,16 +19,11 @@ export function Page({ id }: PageProps) { const model = modelDefinitions.models[id]; Tankopedia.useInitialization(model); + Duel.useInitialization({ tank, model }); return ( - - - - - - - + ); } diff --git a/packages/website/src/stores/app/index.ts b/packages/website/src/stores/app/index.ts index d6e044e1d..bb441ef0a 100644 --- a/packages/website/src/stores/app/index.ts +++ b/packages/website/src/stores/app/index.ts @@ -1,7 +1,4 @@ -import { merge } from 'lodash-es'; -import { create } from 'zustand'; -import { persist, subscribeWithSelector } from 'zustand/middleware'; -import { createContextualStore } from '../../core/zustand/createContextualStore'; +import { Varuna } from "varuna"; export interface WargamingLogin { token: string; @@ -9,7 +6,7 @@ export interface WargamingLogin { expires: number; } -interface AppStore { +interface App { developerMode: boolean; policiesAgreementIndex: number; logins: { @@ -17,15 +14,11 @@ interface AppStore { }; } -export const App = createContextualStore(() => - create()( - persist( - subscribeWithSelector(() => ({ - developerMode: false, - policiesAgreementIndex: -1, - logins: {}, - })), - { name: 'app', merge: (a, b) => merge(b, a) }, - ), - ), +export const App = new Varuna( + { + developerMode: false, + policiesAgreementIndex: -1, + logins: {}, + }, + "app-2" ); diff --git a/packages/website/src/stores/charts.ts b/packages/website/src/stores/charts.ts deleted file mode 100644 index 862bc552b..000000000 --- a/packages/website/src/stores/charts.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Samples } from '@blitzkit/core'; -import { create } from 'zustand'; -import { createContextualStore } from '../core/zustand/createContextualStore'; - -export interface Charts { - period: ChartsPeriod; -} - -export type ChartsPeriod = keyof Samples; - -export const Charts = createContextualStore(() => - create()(() => ({ - period: 'd_30', - })), -); diff --git a/packages/website/src/stores/duel/index.ts b/packages/website/src/stores/duel/index.ts index 35d131b34..899856328 100644 --- a/packages/website/src/stores/duel/index.ts +++ b/packages/website/src/stores/duel/index.ts @@ -2,16 +2,14 @@ import { ModelDefinition, type EngineDefinition, type GunDefinition, - type ProvisionDefinitions, type ShellDefinition, type TankDefinition, type TrackDefinition, type TurretDefinition, -} from '@blitzkit/core'; -import { create } from 'zustand'; -import { subscribeWithSelector } from 'zustand/middleware'; -import { tankToDuelMember } from '../../core/blitzkit/tankToDuelMember'; -import { createContextualStore } from '../../core/zustand/createContextualStore'; +} from "@blitzkit/core"; +import { Varuna } from "varuna"; +import { awaitableProvisionDefinitions } from "../../core/awaitables/provisionDefinitions"; +import { tankToDuelMember } from "../../core/blitzkit/tankToDuelMember"; type EquipmentMatrixItem = -1 | 0 | 1; type EquipmentMatrixRow = [ @@ -45,24 +43,13 @@ export interface DuelStore { antagonist: DuelMember; } -export const Duel = createContextualStore( - ({ - tank, - model, - provisionDefinitions, - }: { - tank: TankDefinition; - model: ModelDefinition; - provisionDefinitions: ProvisionDefinitions; - }) => { - const protagonist = tankToDuelMember(tank, provisionDefinitions); +const provisionDefinitions = await awaitableProvisionDefinitions; - return create()( - subscribeWithSelector(() => ({ - protagonist, - model, - antagonist: protagonist, - })), - ); - }, -); +export const Duel = new Varuna< + DuelStore, + { tank: TankDefinition; model: ModelDefinition } +>(({ tank, model }) => { + const protagonist = tankToDuelMember(tank, provisionDefinitions); + + return { protagonist, antagonist: protagonist, model }; +}); diff --git a/packages/website/src/stores/embedState/index.ts b/packages/website/src/stores/embedState/index.ts index 28412a65d..04abd855c 100644 --- a/packages/website/src/stores/embedState/index.ts +++ b/packages/website/src/stores/embedState/index.ts @@ -1,16 +1,15 @@ -import * as radixColors from '@radix-ui/colors'; -import { create } from 'zustand'; -import { createContextualStore } from '../../core/zustand/createContextualStore'; +import * as radixColors from "@radix-ui/colors"; +import { Varuna } from "varuna"; import { type EmbedConfigItemType, EmbedItemType, radixGrays, radixTextWeights, -} from './constants'; +} from "./constants"; export type RadixSize = `${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`; -export type RadixSizeWithout0 = Exclude; -export type RadixRadius = `${1 | 2 | 3 | 4}` | 'full'; +export type RadixSizeWithout0 = Exclude; +export type RadixRadius = `${1 | 2 | 3 | 4}` | "full"; export type RadixTextWeight = (typeof radixTextWeights)[number]; export type RadixColorCompound = { base: RadixColor; @@ -18,7 +17,7 @@ export type RadixColorCompound = { }; export type RadixTextColor = | Exclude - | 'gray' + | "gray" | undefined; export type RadixColorVariantRaw = `${ | 1 @@ -33,17 +32,17 @@ export type RadixColorVariantRaw = `${ | 10 | 11 | 12}`; -export type RadixColorVariant = `${'' | 'a'}${RadixColorVariantRaw}`; +export type RadixColorVariant = `${"" | "a"}${RadixColorVariantRaw}`; export type RadixColor = Exclude< keyof typeof radixColors, - `${string}${'A' | 'P3' | 'Dark'}` + `${string}${"A" | "P3" | "Dark"}` >; export type RadixColorGrays = (typeof radixGrays)[number]; export type ExtractEmbedConfigTypes = { [Key in keyof Config]: ({ - type: Config[Key]['type']; - } & EmbedConfigItem)['default']; + type: Config[Key]["type"]; + } & EmbedConfigItem)["default"]; }; export type EmbedConfig = { @@ -102,8 +101,8 @@ export type EmbedConfigItem = ( pad?: boolean; }; -export type EmbedStateStore = Record; +export type EmbedStateStore = Record; -export const EmbedState = createContextualStore((init: EmbedStateStore) => - create()(() => init), +export const EmbedState = new Varuna( + (data) => data ); diff --git a/packages/website/src/stores/tankPerformanceSort/index.ts b/packages/website/src/stores/tankPerformanceSort/index.ts index 78b16ce84..3e9006d06 100644 --- a/packages/website/src/stores/tankPerformanceSort/index.ts +++ b/packages/website/src/stores/tankPerformanceSort/index.ts @@ -1,6 +1,5 @@ -import type en from '@blitzkit/i18n/strings/en.json'; -import { create } from 'zustand'; -import { createContextualStore } from '../../core/zustand/createContextualStore'; +import type en from "@blitzkit/i18n/strings/en.json"; +import { Varuna } from "varuna"; export type TankPerformanceSortType = keyof typeof en.website.tools.performance.table.stats; @@ -10,9 +9,7 @@ export interface TankPerformanceSort { direction: -1 | 1; } -export const TankPerformanceSort = createContextualStore(() => - create()(() => ({ - type: 'winrate', - direction: -1, - })), -); +export const TankPerformanceSort = new Varuna({ + type: "winrate", + direction: -1, +}); diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts index f825e8be7..1b1cc2839 100644 --- a/packages/website/src/stores/tankopediaPersistent/index.ts +++ b/packages/website/src/stores/tankopediaPersistent/index.ts @@ -1,14 +1,11 @@ -import type en from '@blitzkit/i18n/strings/en.json'; -import * as lodash from 'lodash-es'; -import { create } from 'zustand'; -import { persist, subscribeWithSelector } from 'zustand/middleware'; -import { createContextualStore } from '../../core/zustand/createContextualStore'; +import type en from "@blitzkit/i18n/strings/en.json"; +import { Varuna } from "varuna"; export type TankopediaSortBy = keyof typeof en.website.common.tank_search.sort; -export type TankopediaSortDirection = 'ascending' | 'descending'; -export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only'; +export type TankopediaSortDirection = "ascending" | "descending"; +export type TankopediaTestTankDisplay = "include" | "exclude" | "only"; -export interface TankopediaPersistentStore { +export interface TankopediaPersistent { wireframe: boolean; opaque: boolean; advancedHighlighting: boolean; @@ -25,25 +22,21 @@ export interface TankopediaPersistentStore { }; } -export const TankopediaPersistent = createContextualStore(() => - create()( - persist( - subscribeWithSelector(() => ({ - hideTankModelUnderArmor: false, - wireframe: false, - opaque: false, - advancedHighlighting: false, - greenPenetration: false, - showSpacedArmor: true, - showExternalModules: true, - showPrimaryArmor: true, - recentlyViewed: [], - sort: { - by: 'meta.none', - direction: 'ascending', - }, - })), - { name: 'tankopedia', merge: (a, b) => lodash.merge(b, a) }, - ), - ), +export const TankopediaPersistent = new Varuna( + { + hideTankModelUnderArmor: false, + wireframe: false, + opaque: false, + advancedHighlighting: false, + greenPenetration: false, + showSpacedArmor: true, + showExternalModules: true, + showPrimaryArmor: true, + recentlyViewed: [], + sort: { + by: "meta.none", + direction: "ascending", + }, + }, + "tankopedia-2" );