diff --git a/packages/core/src/blitzkit/index.ts b/packages/core/src/blitzkit/index.ts index e2e4d995e..3c687f118 100644 --- a/packages/core/src/blitzkit/index.ts +++ b/packages/core/src/blitzkit/index.ts @@ -30,11 +30,11 @@ export * from './normalizeBoundingBox'; // export * from './patientFetch'; // export * from './patientFetchJSON'; // export * from './progressiveStat'; -// export * from './provisionDefinitions'; +export * from './provisionDefinitions'; export * from './resolveDpm'; -// export * from './resolvePenetrationCoefficient'; +export * from './resolvePenetrationCoefficient'; // export * from './reviews'; -// export * from './skillDefinitions'; +export * from './skillDefinitions'; // export * from './sum'; export * from './superCompress'; export * from './superDecompress'; diff --git a/packages/core/src/blitzkit/provisionDefinitions.ts b/packages/core/src/blitzkit/provisionDefinitions.ts index 6d879731a..6d8451427 100644 --- a/packages/core/src/blitzkit/provisionDefinitions.ts +++ b/packages/core/src/blitzkit/provisionDefinitions.ts @@ -1,5 +1,5 @@ -import { TankFilterDefinition } from '@blitzkit/core'; import { asset } from './asset'; +import { TankFilterDefinition } from './consumableDefinitions'; import { fetchCdonLz4 } from './fetchCdonLz4'; export type ProvisionEntry = { diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 51d950bbe..628ad93da 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -3,7 +3,7 @@ export * from './blitzkit'; // export * from './blitzstars'; // export * from './databases'; export * from './imgur'; -// export * from './math'; +export * from './math'; export * from './patreon'; // export * from './protobuf'; export * from './statistics'; diff --git a/packages/website-legacy/package.json b/packages/website-legacy/package.json index 56aed9621..3e4104ec2 100644 --- a/packages/website-legacy/package.json +++ b/packages/website-legacy/package.json @@ -17,8 +17,6 @@ "lodash": "^4.17.21", "next": "^14.2.7", "three-stdlib": "^2.32.2", - "@react-three/drei": "^9.111.5", - "@react-three/fiber": "^8.17.6", "urlon": "^3.1.0", "react": "^18.3.1", "@vanilla-extract/css": "^1.15.5", @@ -29,7 +27,6 @@ "react-fuzzysort": "^1.0.1", "immer": "^10.1.1", "@vanilla-extract/dynamic": "^2.1.2", - "zustand": "^4.5.5" }, "devDependencies": { "@types/react-dom": "^18", diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx index 20b4a0929..157038b61 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx +++ b/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Content.tsx @@ -2,19 +2,19 @@ import { TIER_ROMAN_NUMERALS } from '@blitzkit/core'; import strings from '@blitzkit/core/lang/en-US.json'; import { invalidate } from '@react-three/fiber'; import { useEffect } from 'react'; +import { CalloutsSection } from '../../../../../../../website/src/components/Tankopedia/CalloutsSection'; +import { CharacteristicsSection } from '../../../../../../../website/src/components/Tankopedia/CharacteristicsSection'; +import { GameModeSection } from '../../../../../../../website/src/components/Tankopedia/GameModeSection'; +import { HeroSection } from '../../../../../../../website/src/components/Tankopedia/HeroSection'; +import { HistorySection } from '../../../../../../../website/src/components/Tankopedia/HistorySection'; +import { MetaSection } from '../../../../../../../website/src/components/Tankopedia/MetaSection'; +import { ShotDisplaySection } from '../../../../../../../website/src/components/Tankopedia/ShotDisplaySection'; +import { TechTreeSection } from '../../../../../../../website/src/components/Tankopedia/TechTreeSection'; import { AdMidSectionResponsive } from '../../../../../components/AdMidSectionResponsive'; import { PageWrapper } from '../../../../../components/PageWrapper'; import { useAdExempt } from '../../../../../hooks/useAdExempt'; import * as Duel from '../../../../../stores/duel'; import * as TankopediaEphemeral from '../../../../../stores/tankopediaEphemeral'; -import { CalloutsSection } from './CalloutsSection'; -import { HistorySection } from './HistorySection'; -import { CharacteristicsSection } from './Model/CharacteristicsSection'; -import { GameModeSection } from './Model/GameModeSection'; -import { HeroSection } from './Model/HeroSection'; -import { MetaSection } from './Model/MetaSection'; -import { TechTreeSection } from './Model/TechTreeSection'; -import { ShotDisplaySection } from './ShotDisplaySection'; import { VideoSection } from './VideoSection'; export function Content() { diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx b/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx index e0d1a78fa..ca2022b26 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx +++ b/packages/website-legacy/src/app/tools/tankopedia/[id]/page.tsx @@ -2,19 +2,19 @@ import { TIER_ROMAN_NUMERALS } from '@blitzkit/core'; import strings from '@blitzkit/core/lang/en-US.json'; import { invalidate } from '@react-three/fiber'; import { useEffect } from 'react'; +import { CalloutsSection } from '../../../../../../website/src/components/Tankopedia/CalloutsSection'; +import { CharacteristicsSection } from '../../../../../../website/src/components/Tankopedia/CharacteristicsSection'; +import { GameModeSection } from '../../../../../../website/src/components/Tankopedia/GameModeSection'; +import { HeroSection } from '../../../../../../website/src/components/Tankopedia/HeroSection'; +import { HistorySection } from '../../../../../../website/src/components/Tankopedia/HistorySection'; +import { MetaSection } from '../../../../../../website/src/components/Tankopedia/MetaSection'; +import { ShotDisplaySection } from '../../../../../../website/src/components/Tankopedia/ShotDisplaySection'; +import { TechTreeSection } from '../../../../../../website/src/components/Tankopedia/TechTreeSection'; import { AdMidSectionResponsive } from '../../../../components/AdMidSectionResponsive'; import { PageWrapper } from '../../../../components/PageWrapper'; import { useAdExempt } from '../../../../hooks/useAdExempt'; import * as Duel from '../../../../stores/duel'; import * as TankopediaEphemeral from '../../../../stores/tankopediaEphemeral'; -import { CalloutsSection } from './components/CalloutsSection'; -import { HistorySection } from './components/HistorySection'; -import { CharacteristicsSection } from './components/Model/CharacteristicsSection'; -import { GameModeSection } from './components/Model/GameModeSection'; -import { HeroSection } from './components/Model/HeroSection'; -import { MetaSection } from './components/Model/MetaSection'; -import { TechTreeSection } from './components/Model/TechTreeSection'; -import { ShotDisplaySection } from './components/ShotDisplaySection'; import { VideoSection } from './components/VideoSection'; export default function Page() { diff --git a/packages/website-legacy/tsconfig.json b/packages/website-legacy/tsconfig.json index b22de154d..682146c89 100644 --- a/packages/website-legacy/tsconfig.json +++ b/packages/website-legacy/tsconfig.json @@ -10,6 +10,13 @@ "include": [ "src/**/*", ".next/types/**/*.ts", - "../website/src/components/TankSearch/components/FilterControl.tsx" + "../website/src/components/TankSearch/components/FilterControl.tsx", + "../website/src/components/Tankopedia/HeroSection/index.tsx", + "../website/src/components/Tankopedia/GameModeSection.tsx", + "../website/src/components/Tankopedia/CharacteristicsSection.tsx", + "../website/src/components/Tankopedia/MetaSection", + "../website/src/components/Tankopedia/HistorySection.tsx", + "../website/src/components/Tankopedia/CalloutsSection.tsx", + "../website/src/components/Tankopedia/ShotDisplaySection.tsx" ] } diff --git a/packages/website/package.json b/packages/website/package.json index 08c09a1b5..db5bdeb2c 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -18,10 +18,13 @@ "@radix-ui/themes": "^3.1.3", "@vanilla-extract/css": "^1.15.5", "astro": "^4.15.6", + "@react-three/drei": "^9.111.5", + "@react-three/fiber": "^8.17.6", "astro-purgecss": "^4.6.0", "nanostores": "^0.11.3", "purgecss": "^6.0.0", "react": "^18.3.1", + "zustand": "^4.5.5", "react-dom": "^18.3.1", "react-promise-suspense": "^0.3.4" }, diff --git a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx index ebd92b17a..77ad279c1 100644 --- a/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx +++ b/packages/website/src/components/Armor/components/ArmorPlateDisplay.tsx @@ -9,11 +9,7 @@ import { } from '@radix-ui/themes'; import { Html } from '@react-three/drei'; import { useRef } from 'react'; -import { radToDeg } from 'three/src/math/MathUtils'; -import { resolveArmorIndex } from '../../../../../website-legacy/src/core/blitzkit/resolveArmorIndex'; -import * as App from '../../../../../website-legacy/src/stores/app'; -import * as Duel from '../../../../../website-legacy/src/stores/duel'; -import * as TankopediaEphemeral from '../../../../../website-legacy/src/stores/tankopediaEphemeral'; +import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; import { layerTypeNames } from './ShotDisplayCard'; import { ArmorType } from './SpacedArmorScene'; diff --git a/packages/website/src/components/Armor/components/ModelTankWrapper.tsx b/packages/website/src/components/Armor/components/ModelTankWrapper.tsx index def5d5c66..9d0a9bdfe 100644 --- a/packages/website/src/components/Armor/components/ModelTankWrapper.tsx +++ b/packages/website/src/components/Armor/components/ModelTankWrapper.tsx @@ -1,4 +1,4 @@ -import { GroupProps } from '@react-three/fiber'; +import type { GroupProps } from '@react-three/fiber'; import { forwardRef } from 'react'; import { Group } from 'three'; diff --git a/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx b/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx index 73b32a5ac..bffdeebe6 100644 --- a/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx +++ b/packages/website/src/components/Armor/components/PrimaryArmorScene.tsx @@ -1,12 +1,11 @@ import { memo, useRef } from 'react'; import { Group } from 'three'; -import { correctZYTuple } from '../../../../../website-legacy/src/core/blitz/correctZYTuple'; -import { nameToArmorId } from '../../../../../website-legacy/src/core/blitzkit/nameToArmorId'; -import { resolveArmor } from '../../../../../website-legacy/src/core/blitzkit/resolveThickness'; -import { useArmor } from '../../../../../website-legacy/src/hooks/useArmor'; -import { useTankModelDefinition } from '../../../../../website-legacy/src/hooks/useTankModelDefinition'; -import { useTankTransform } from '../../../../../website-legacy/src/hooks/useTankTransform'; -import * as Duel from '../../../../../website-legacy/src/stores/duel'; +import { correctZYTuple } from '../../../core/blitz/correctZYTuple'; +import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId'; +import { resolveArmor } from '../../../core/blitzkit/resolveThickness'; +import { useArmor } from '../../../hooks/useArmor'; +import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; +import { useTankTransform } from '../../../hooks/useTankTransform'; import { ModelTankWrapper } from './ModelTankWrapper'; import { PrimaryArmorSceneComponent } from './PrimaryArmorSceneComponent'; diff --git a/packages/website/src/components/Armor/components/SpacedArmorScene.tsx b/packages/website/src/components/Armor/components/SpacedArmorScene.tsx index 1313832b8..6b3482211 100644 --- a/packages/website/src/components/Armor/components/SpacedArmorScene.tsx +++ b/packages/website/src/components/Armor/components/SpacedArmorScene.tsx @@ -1,13 +1,12 @@ import { memo, useRef } from 'react'; import { Group, Plane, Scene, Vector3 } from 'three'; -import { correctZYTuple } from '../../../../../website-legacy/src/core/blitz/correctZYTuple'; -import { nameToArmorId } from '../../../../../website-legacy/src/core/blitzkit/nameToArmorId'; -import { resolveArmor } from '../../../../../website-legacy/src/core/blitzkit/resolveThickness'; -import { useArmor } from '../../../../../website-legacy/src/hooks/useArmor'; -import { useModel } from '../../../../../website-legacy/src/hooks/useModel'; -import { useTankModelDefinition } from '../../../../../website-legacy/src/hooks/useTankModelDefinition'; -import { useTankTransform } from '../../../../../website-legacy/src/hooks/useTankTransform'; -import * as Duel from '../../../../../website-legacy/src/stores/duel'; +import { correctZYTuple } from '../../../core/blitz/correctZYTuple'; +import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId'; +import { resolveArmor } from '../../../core/blitzkit/resolveThickness'; +import { useArmor } from '../../../hooks/useArmor'; +import { useModel } from '../../../hooks/useModel'; +import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; +import { useTankTransform } from '../../../hooks/useTankTransform'; import { ModelTankWrapper } from './ModelTankWrapper'; import { SpacedArmorSceneComponent } from './SpacedArmorSceneComponent'; 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 760d05198..075eb8658 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 @@ -1,7 +1,7 @@ import { - ShellDefinition, resolveNearPenetration, resolvePenetrationCoefficient, + type ShellDefinition, } from '@blitzkit/core'; import { useEffect } from 'react'; import { @@ -11,10 +11,10 @@ import { Plane, ShaderMaterial, } from 'three'; -import { ArmorUserData, ExternalModuleVariant } from '../..'; -import { hasEquipment } from '../../../../../../../../website-legacy/src/core/blitzkit/hasEquipment'; -import { jsxTree } from '../../../../../../../../website-legacy/src/core/blitzkit/jsxTree'; -import * as Duel from '../../../../../../../../website-legacy/src/stores/duel'; +import type { ArmorUserData, ExternalModuleVariant } from '../..'; +import { hasEquipment } from '../../../../../../core/blitzkit/hasEquipment'; +import { jsxTree } from '../../../../../../core/blitzkit/jsxTree'; +import { Duel, type EquipmentMatrix } from '../../../../../../stores/duel'; import { ArmorType } from '../../../SpacedArmorScene'; import fragmentShader from './shaders/fragment.glsl'; import vertexShader from './shaders/vertex.glsl'; @@ -56,7 +56,7 @@ export function SpacedArmorSubExternal({ ); } async function handleProtagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, + equipment: EquipmentMatrix, ) { const duel = duelStore.getState(); const hasEnhancedArmor = await hasEquipment( @@ -68,9 +68,7 @@ export function SpacedArmorSubExternal({ ? thickness * 1.03 : thickness; } - async function handleAntagonistEquipmentChange( - equipment: Duel.EquipmentMatrix, - ) { + async function handleAntagonistEquipmentChange(equipment: EquipmentMatrix) { const duel = duelStore.getState(); const shell = duel.antagonist.shell; const penetration = resolveNearPenetration(shell.penetration); diff --git a/packages/website/src/components/Armor/components/StaticArmor.tsx b/packages/website/src/components/Armor/components/StaticArmor.tsx index eccfaf02c..007c3d39c 100644 --- a/packages/website/src/components/Armor/components/StaticArmor.tsx +++ b/packages/website/src/components/Armor/components/StaticArmor.tsx @@ -1,20 +1,19 @@ import { normalizeAngleRad } from '@blitzkit/core'; -import { ThreeEvent, useThree } from '@react-three/fiber'; +import { useThree, type ThreeEvent } from '@react-three/fiber'; import { memo, useRef } from 'react'; import { Group, Plane, Vector2, Vector3 } from 'three'; -import { applyPitchYawLimits } from '../../../../../website-legacy/src/core/blitz/applyPitchYawLimits'; -import { correctZYTuple } from '../../../../../website-legacy/src/core/blitz/correctZYTuple'; -import { hasEquipment } from '../../../../../website-legacy/src/core/blitzkit/hasEquipment'; -import { modelTransformEvent } from '../../../../../website-legacy/src/core/blitzkit/modelTransform'; -import { nameToArmorId } from '../../../../../website-legacy/src/core/blitzkit/nameToArmorId'; -import { resolveArmor } from '../../../../../website-legacy/src/core/blitzkit/resolveThickness'; -import { useArmor } from '../../../../../website-legacy/src/hooks/useArmor'; -import { useModel } from '../../../../../website-legacy/src/hooks/useModel'; -import { useTankModelDefinition } from '../../../../../website-legacy/src/hooks/useTankModelDefinition'; -import { useTankTransform } from '../../../../../website-legacy/src/hooks/useTankTransform'; -import * as Duel from '../../../../../website-legacy/src/stores/duel'; -import * as TankopediaEphemeral from '../../../../../website-legacy/src/stores/tankopediaEphemeral'; -import * as TankopediaPersistent from '../../../../../website-legacy/src/stores/tankopediaPersistent'; +import { applyPitchYawLimits } from '../../../core/blitz/applyPitchYawLimits'; +import { correctZYTuple } from '../../../core/blitz/correctZYTuple'; +import { hasEquipment } from '../../../core/blitzkit/hasEquipment'; +import { modelTransformEvent } from '../../../core/blitzkit/modelTransform'; +import { nameToArmorId } from '../../../core/blitzkit/nameToArmorId'; +import { resolveArmor } from '../../../core/blitzkit/resolveThickness'; +import { useArmor } from '../../../hooks/useArmor'; +import { useModel } from '../../../hooks/useModel'; +import { useTankModelDefinition } from '../../../hooks/useTankModelDefinition'; +import { useTankTransform } from '../../../hooks/useTankTransform'; +import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral'; +import { TankopediaPersistent } from '../../../stores/tankopediaPersistent'; import { ModelTankWrapper } from './ModelTankWrapper'; import { ArmorType } from './SpacedArmorScene'; import { StaticArmorSceneComponent } from './StaticArmorSceneComponent'; @@ -56,13 +55,13 @@ export const StaticArmor = memo(({ thicknessRange }) => { ? undefined : gunModelDefinition.mask + hullOrigin.y + turretOrigin.y + gunOrigin.y; const showPrimaryArmor = TankopediaPersistent.use( - (state) => state.model.visual.showPrimaryArmor, + (state) => state.showPrimaryArmor, ); const showSpacedArmor = TankopediaPersistent.use( - (state) => state.model.visual.showSpacedArmor, + (state) => state.showSpacedArmor, ); const showExternalModules = TankopediaPersistent.use( - (state) => state.model.visual.showExternalModules, + (state) => state.showExternalModules, ); const isDynamicArmorActive = Duel.use((state) => state.protagonist.consumables.includes(73), diff --git a/packages/website/src/components/CrewSkillManager.tsx b/packages/website/src/components/CrewSkillManager.tsx index ee91e3b44..d0dbcca52 100644 --- a/packages/website/src/components/CrewSkillManager.tsx +++ b/packages/website/src/components/CrewSkillManager.tsx @@ -2,11 +2,10 @@ import { asset, permanentSkills, skillDefinitions, - Tier, TIER_ROMAN_NUMERALS, + type Tier, } from '@blitzkit/core'; import { Flex } from '@radix-ui/themes'; -import { use } from 'react'; import { GenericTankComponentButton } from './ModuleButtons/GenericTankComponentButton'; interface CrewSkillManagerProps { @@ -14,12 +13,12 @@ interface CrewSkillManagerProps { onChange?: (skillLevels: Record) => void; } +const awaitedSkillDefinitions = await skillDefinitions; + export function CrewSkillManager({ skillLevels, onChange, }: CrewSkillManagerProps) { - const awaitedSkillDefinitions = use(skillDefinitions); - return ( {Object.entries(awaitedSkillDefinitions.classes).map( diff --git a/packages/website/src/components/ModuleButtons/ConsumableButton.tsx b/packages/website/src/components/ModuleButtons/ConsumableButton.tsx index ff659e32e..29ec4fdb3 100644 --- a/packages/website/src/components/ModuleButtons/ConsumableButton.tsx +++ b/packages/website/src/components/ModuleButtons/ConsumableButton.tsx @@ -1,7 +1,6 @@ import { asset, consumableDefinitions } from '@blitzkit/core'; import { ClockIcon, ReloadIcon } from '@radix-ui/react-icons'; import { Flex, Text } from '@radix-ui/themes'; -import { use } from 'react'; import { useDelta } from '../../../../website-legacy/src/hooks/useDelta'; import { GenericTankComponentButton } from './GenericTankComponentButton'; import { TankComponentButtonProps } from './TankComponentButton'; @@ -12,13 +11,14 @@ interface ConsumableButtonProps extends TankComponentButtonProps { cooldown?: number; } +const awaitedConsumableDefinitions = await consumableDefinitions; + export function ConsumableButton({ consumable, cooldown, duration, ...props }: ConsumableButtonProps) { - const awaitedConsumableDefinitions = use(consumableDefinitions); const cooldownDelta = useDelta(cooldown ?? 0); const durationDelta = useDelta(duration ?? 0); diff --git a/packages/website/src/components/ModuleButtons/EquipmentButton.tsx b/packages/website/src/components/ModuleButtons/EquipmentButton.tsx index d722a1bc1..65709ae10 100644 --- a/packages/website/src/components/ModuleButtons/EquipmentButton.tsx +++ b/packages/website/src/components/ModuleButtons/EquipmentButton.tsx @@ -1,5 +1,4 @@ import { asset, equipmentDefinitions } from '@blitzkit/core'; -import { use } from 'react'; import { GenericTankComponentButton } from './GenericTankComponentButton'; import { TankComponentButtonProps } from './TankComponentButton'; @@ -7,9 +6,9 @@ interface EquipmentButtonProps extends TankComponentButtonProps { equipment: number; } -export function EquipmentButton({ equipment, ...props }: EquipmentButtonProps) { - const awaitedEquipmentDefinitions = use(equipmentDefinitions); +const awaitedEquipmentDefinitions = await equipmentDefinitions; +export function EquipmentButton({ equipment, ...props }: EquipmentButtonProps) { return ( - - - - - - - - event.preventDefault()} - > - {(patreonLogin.token || wargamingLogin.token) && ( - - - Logged in accounts - - - {patreonLogin.token && ( - - - Patreon - - - )} - - {wargamingLogin.token && ( - - - - }> - - - - - - )} - - )} - - {!patreonLogin.token !== !wargamingLogin.token && ( - - - - )} - - {(!patreonLogin.token || !wargamingLogin.token) && ( - - - Log in with... - - - {!patreonLogin.token && ( - - - - )} - - {!wargamingLogin.token && } - - )} - - - - ); -} diff --git a/packages/website/src/components/NavbarAccount/index.tsx b/packages/website/src/components/NavbarAccount/index.tsx new file mode 100644 index 000000000..9a97248ba --- /dev/null +++ b/packages/website/src/components/NavbarAccount/index.tsx @@ -0,0 +1,118 @@ +import { patreonLoginUrl } from '@blitzkit/core'; +import { useStore } from '@nanostores/react'; +import { PersonIcon } from '@radix-ui/react-icons'; +import { + Button, + Flex, + IconButton, + Inset, + Link, + Popover, + Separator, + Skeleton, + Text, +} from '@radix-ui/themes'; +import { Suspense } from 'react'; +import { App } from '../../stores/app'; +import { $patreonLogin } from '../../stores/patreonLogin'; +import { $wargamingLogin } from '../../stores/wargamingLogin'; +import { BlitzKitTheme } from '../BlitzKitTheme'; +import { PatreonIcon } from '../PatreonIcon'; +import { WargamingAccountName } from '../WargamingAccountName'; +import { WargamingIcon } from '../WargamingIcon'; +import { WargamingLoginButton } from '../WargamingLoginButton'; + +export function NavbarAccount() { + const patreon = useStore($patreonLogin); + const wargaming = useStore($wargamingLogin); + + return ( + + + + + + + + + + event.preventDefault()} + > + {(patreon.token || wargaming.token) && ( + + + Logged in accounts + + + {patreon.token && ( + + + Patreon + + + )} + + {wargaming.token && ( + + + + } + > + + + + + + )} + + )} + + {!patreon.token !== !wargaming.token && ( + + + + )} + + {(!patreon.token || !wargaming.token) && ( + + + Log in with... + + + {!patreon.token && ( + + + + )} + + {!wargaming.token && } + + )} + + + + + ); +} diff --git a/packages/website/src/components/Plugs.tsx b/packages/website/src/components/Plugs.tsx index e8d36ca1f..d2539592d 100644 --- a/packages/website/src/components/Plugs.tsx +++ b/packages/website/src/components/Plugs.tsx @@ -10,19 +10,13 @@ import { Separator, Text, } from '@radix-ui/themes'; -import { useLayoutEffect, useState } from 'react'; import { useAdExempt } from '../hooks/useAdExempt'; import { $patreonLogin } from '../stores/patreonLogin'; import { PatreonIcon } from './PatreonIcon'; export function Plugs() { - const [hasPatreon, setHasPatreon] = useState(false); const exempt = useAdExempt(); - const patreonLogin = useStore($patreonLogin); - - useLayoutEffect(() => { - setHasPatreon(patreonLogin !== undefined); - }, [patreonLogin]); + const hasPatreon = useStore($patreonLogin).token !== undefined; return ( state.protagonist.tank); - const awaitedGameDefinitions = use(gameDefinitions); - const awaitedConsumableDefinitions = use(consumableDefinitions); - const awaitedProvisionDefinitions = use(provisionDefinitions); const roles = Object.entries(tank.roles); if (roles.length === 0) return null; diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/components/DynamicArmorSwitcher.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx similarity index 86% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/components/DynamicArmorSwitcher.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx index a6fbbb246..b1fe8426d 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/components/DynamicArmorSwitcher.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/DynamicArmorSwitcher.tsx @@ -1,9 +1,8 @@ import { asset } from '@blitzkit/core'; import { IconButton } from '@radix-ui/themes'; import { invalidate } from '@react-three/fiber'; -import { useArmor } from '../../../../../../../../../hooks/useArmor'; -import * as Duel from '../../../../../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../../../../../stores/tankopediaEphemeral'; +import { useArmor } from '../../../../../../hooks/useArmor'; +import { TankopediaEphemeral } from '../../../../../../stores/tankopediaEphemeral'; export function DynamicArmorSwitcher() { const tank = Duel.use((state) => state.protagonist.tank); diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/QuickInputs/index.css.ts b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.css.ts similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/QuickInputs/index.css.ts rename to packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.css.ts diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/QuickInputs/index.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/Options/components/QuickInputs/index.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/index.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx similarity index 87% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/index.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx index 936776f61..4a05c40f2 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/Options/index.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/Options/index.tsx @@ -1,4 +1,11 @@ -import { asset, imgur, resolveNearPenetration, resolvePenetrationCoefficient, TIER_ROMAN_NUMERALS, uniqueGuns } from '@blitzkit/core'; +import { + asset, + imgur, + resolveNearPenetration, + resolvePenetrationCoefficient, + TIER_ROMAN_NUMERALS, + uniqueGuns, +} from '@blitzkit/core'; import { CameraIcon, CopyIcon, @@ -21,24 +28,22 @@ import { Tooltip, } from '@radix-ui/themes'; import { invalidate } from '@react-three/fiber'; -import { RefObject, useEffect, useState } from 'react'; -import { useEquipment } from '../../../../../../../../hooks/useEquipment'; -import { useFullScreen } from '../../../../../../../../hooks/useFullScreen'; -import { useFullscreenAvailability } from '../../../../../../../../hooks/useFullscreenAvailability'; -import * as App from '../../../../../../../../stores/app'; -import * as Duel from '../../../../../../../../stores/duel'; -import * as TankopediaEphemeral from '../../../../../../../../stores/tankopediaEphemeral'; -import * as TankopediaPersistent from '../../../../../../../../stores/tankopediaPersistent'; -import { TankopediaDisplay } from '../../../../../../../../stores/tankopediaPersistent/constants'; -import { TankSearch } from '../../../../../components/TankSearch'; -import { ENVIRONMENTS } from '../../../Lighting'; -import { QuickInputs } from '../../../QuickInputs'; -import { Thicknesses } from '../../../Thicknesses'; +import { type RefObject, useState } from 'react'; +import { ENVIRONMENTS } from '../../../../../constants/lightingEnvironments'; +import { Pose, poseEvent } from '../../../../../core/blitzkit/pose'; +import { useEquipment } from '../../../../../hooks/useEquipment'; +import { useFullScreen } from '../../../../../hooks/useFullScreen'; +import { useFullscreenAvailability } from '../../../../../hooks/useFullscreenAvailability'; +import { useStoreBoolean } from '../../../../../hooks/useStoreBoolean'; +import { useStoreKey } from '../../../../../hooks/useStoreKey'; +import { $app } from '../../../../../stores/app'; +import { $tankopediaPersistent } from '../../../../../stores/tankopediaPersistent'; +import { TankopediaDisplay } from '../../../../../stores/tankopediaPersistent/constants'; +import type { ThicknessRange } from '../../../../Armor/components/StaticArmor'; +import { ModuleButton } from '../../../../ModuleButtons/ModuleButton'; +import { SmallTankIcon } from '../../../../SmallTankIcon'; +import { TankSearch } from '../../../../TankSearch'; import { DynamicArmorSwitcher } from './components/DynamicArmorSwitcher'; -import { ThicknessRange } from '../../../../../../../../components/Armor/components/StaticArmor'; -import { ModuleButton } from '../../../../../../../../components/ModuleButtons/ModuleButton'; -import { SmallTankIcon } from '../../../../../../../../components/SmallTankIcon'; -import { poseEvent, Pose } from '../../../../../../../../core/blitzkit/pose'; interface OptionsProps { thicknessRange: ThicknessRange; @@ -46,31 +51,23 @@ interface OptionsProps { } export function Options({ thicknessRange, canvas }: OptionsProps) { - const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); - const mutateTankopediaPersistent = TankopediaPersistent.useMutation(); - const displayRaw = TankopediaPersistent.use((state) => state.display); - const [display, setDisplay] = useState( - TankopediaDisplay.Model, - ); + // const { display } = useStore($tankopediaPersistent, { keys: ['display'] }); + const display = useStoreKey($tankopediaPersistent, 'display'); const isFullScreen = useFullScreen(); - const showGrid = TankopediaPersistent.use( - (state) => state.model.visual.showGrid, + const showGrid = useStoreBoolean($tankopediaPersistent, 'showGrid'); + const showEnvironment = useStoreBoolean( + $tankopediaPersistent, + 'showEnvironment', ); - const showEnvironment = TankopediaPersistent.use( - (state) => state.model.visual.showEnvironment, + const greenPenetration = useStoreBoolean( + $tankopediaPersistent, + 'greenPenetration', ); - const greenPenetration = TankopediaPersistent.use( - (state) => state.model.visual.greenPenetration, - ); - const wireframe = TankopediaPersistent.use( - (state) => state.model.visual.wireframe, - ); - const opaque = TankopediaPersistent.use((state) => state.model.visual.opaque); + const wireframe = useStoreBoolean($tankopediaPersistent, 'wireframe'); + const opaque = useStoreBoolean($tankopediaPersistent, 'opaque'); const fullScreenAvailable = useFullscreenAvailability(); - const environment = TankopediaPersistent.use( - (state) => state.model.visual.environment, - ); - const developerMode = App.useDeferred(false, (state) => state.developerMode); + const environment = useStoreKey($tankopediaPersistent, 'environment'); + const developerMode = useStoreBoolean($app, 'developerMode'); const protagonistTank = Duel.use((state) => state.protagonist.tank); const antagonistGun = Duel.use((state) => state.antagonist.gun); const antagonistShell = Duel.use((state) => state.antagonist.shell); @@ -82,8 +79,6 @@ export function Options({ thicknessRange, canvas }: OptionsProps) { const hasEnhancedArmor = useEquipment(110); const antagonistUniqueGuns = uniqueGuns(antagonistTank.turrets); - useEffect(() => setDisplay(displayRaw), [displayRaw]); - return ( <> diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx similarity index 89% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx index b0f887d30..e53c0ce45 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TankSandbox.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandbox.tsx @@ -23,12 +23,12 @@ import * as Duel from '../../../../../../stores/duel'; import * as TankopediaEphemeral from '../../../../../../stores/tankopediaEphemeral'; import * as TankopediaPersistent from '../../../../../../stores/tankopediaPersistent'; import { TankopediaDisplay } from '../../../../../../stores/tankopediaPersistent/constants'; -import { Controls } from '../Control'; -import { Lighting } from '../Lighting'; -import { SceneProps } from '../SceneProps'; -import { AutoClear } from './AutoClear'; -import { ModelLoader } from './components/ModelLoader'; -import { TankModel } from './components/TankModel'; +import { Controls } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Control'; +import { Lighting } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Lighting'; +import { SceneProps } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/SceneProps'; +import { AutoClear } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/AutoClear'; +import { ModelLoader } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/ModelLoader'; +import { TankModel } from '../../../../../../website-legacy/src/app/tools/tankopedia/[id]/components/Model/components/TankModel'; interface TankSandboxProps { thicknessRange: ThicknessRange; diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TankSandboxLoader.tsx b/packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TankSandboxLoader.tsx rename to packages/website/src/components/Tankopedia/HeroSection/components/TankSandboxLoader.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx b/packages/website/src/components/Tankopedia/HeroSection/index.tsx similarity index 82% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx rename to packages/website/src/components/Tankopedia/HeroSection/index.tsx index a58106901..1f6855e99 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/HeroSection.tsx +++ b/packages/website/src/components/Tankopedia/HeroSection/index.tsx @@ -1,20 +1,25 @@ import { resolveNearPenetration, tankDefinitions } from '@blitzkit/core'; import { Box, Flex, Heading, Text } from '@radix-ui/themes'; -import { Suspense, use, useEffect, useMemo, useRef, useState } from 'react'; -import { ThicknessRange } from '../../../../../../components/Armor/components/StaticArmor'; -import { classIcons } from '../../../../../../components/ClassIcon'; -import { NAVBAR_HEIGHT } from '../../../../../../components/Navbar/index.css'; -import { Var } from '../../../../../../core/radix/var'; -import { useFullScreen } from '../../../../../../hooks/useFullScreen'; -import * as Duel from '../../../../../../stores/duel'; -import { TankSandbox } from './TankSandbox'; -import { TankSandboxLoader } from './TankSandboxLoader'; +import { Suspense, useEffect, useMemo, useRef, useState } from 'react'; +import { NAVBAR_HEIGHT } from '../../../constants/navbar'; +import { Var } from '../../../core/radix/var'; +import { useFullScreen } from '../../../hooks/useFullScreen'; +import type { ThicknessRange } from '../../Armor/components/StaticArmor'; +import { classIcons } from '../../ClassIcon'; import { Options } from './components/Options'; +import { TankSandbox } from './components/TankSandbox'; +import { TankSandboxLoader } from './components/TankSandboxLoader'; -export function HeroSection() { +const awaitedTankDefinitions = await tankDefinitions; + +interface HeroSectionProps { + id: number; +} + +export function HeroSection({ id }: HeroSectionProps) { const canvas = useRef(null); const isFullScreen = useFullScreen(); - const protagonist = Duel.use((state) => state.protagonist.tank); + const protagonist = awaitedTankDefinitions[id]; const Icon = classIcons[protagonist.class]; const [dummyLoader, setDummyLoader] = useState(true); const treeColor = @@ -23,7 +28,6 @@ export function HeroSection() { : protagonist.treeType === 'premium' ? 'amber' : undefined; - const awaitedTankDefinitions = use(tankDefinitions); const thicknessRange = useMemo(() => { const entries = Object.values(awaitedTankDefinitions); const filtered = entries.filter( diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/HistorySection.tsx b/packages/website/src/components/Tankopedia/HistorySection.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/HistorySection.tsx rename to packages/website/src/components/Tankopedia/HistorySection.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Listing.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Listing.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Listing.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Listing.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Stars/components/PartialStar.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Stars/components/PartialStar.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Stars/components/PartialStar.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Stars/components/PartialStar.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Stars/index.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Stars/index.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Stars/index.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Stars/index.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/components/StarRow.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Votes/components/StarRow.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/components/StarRow.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Votes/components/StarRow.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/components/VoteCaster.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Votes/components/VoteCaster.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/components/VoteCaster.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Votes/components/VoteCaster.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/index.tsx b/packages/website/src/components/Tankopedia/MetaSection/components/Votes/index.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/components/Votes/index.tsx rename to packages/website/src/components/Tankopedia/MetaSection/components/Votes/index.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/index.tsx b/packages/website/src/components/Tankopedia/MetaSection/index.tsx similarity index 97% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/index.tsx rename to packages/website/src/components/Tankopedia/MetaSection/index.tsx index 123cd61db..9693d1e91 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/MetaSection/index.tsx +++ b/packages/website/src/components/Tankopedia/MetaSection/index.tsx @@ -7,7 +7,7 @@ import { import strings from '@blitzkit/core/lang/en-US.json'; import { ChevronLeftIcon, MixIcon, UpdateIcon } from '@radix-ui/react-icons'; import { Button, Code, Dialog, Flex } from '@radix-ui/themes'; -import { use, useState } from 'react'; +import { useState } from 'react'; import { classIcons } from '../../../../../../../components/ClassIcon'; import { Link } from '../../../../../../../components/Link'; import { ScienceIcon } from '../../../../../../../components/ScienceIcon'; @@ -18,6 +18,9 @@ import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphe import { TankSearch } from '../../../../components/TankSearch'; import { Listing } from './components/Listing'; +const awaitedProvisionDefinitions = await provisionDefinitions; +const awaitedModelDefinitions = await modelDefinitions; + export function MetaSection() { const developerMode = App.useDeferred(false, (state) => state.developerMode); const protagonist = Duel.use((state) => state.protagonist.tank); @@ -29,9 +32,7 @@ export function MetaSection() { : [protagonist.id, antagonist.id]; const mutateDuel = Duel.useMutation(); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); - const awaitedProvisionDefinitions = use(provisionDefinitions); const [showSwapDialog, setShowSwapDialog] = useState(false); - const awaitedModelDefinitions = use(modelDefinitions); return ( diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx b/packages/website/src/components/Tankopedia/ShotDisplaySection.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/ShotDisplaySection.tsx rename to packages/website/src/components/Tankopedia/ShotDisplaySection.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Arrow.tsx b/packages/website/src/components/Tankopedia/TechTreeSection/components/Arrow.tsx similarity index 100% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Arrow.tsx rename to packages/website/src/components/Tankopedia/TechTreeSection/components/Arrow.tsx diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx b/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx similarity index 96% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx rename to packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx index e430dc12c..1c71f304c 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/components/Node.tsx +++ b/packages/website/src/components/Tankopedia/TechTreeSection/components/Node.tsx @@ -7,7 +7,6 @@ import { } from '@blitzkit/core'; import { Box, Flex, Text } from '@radix-ui/themes'; import Link from 'next/link'; -import { use } from 'react'; import * as TankopediaEphemeral from '../../../../../../../../stores/tankopediaEphemeral'; interface NodeProps { @@ -16,12 +15,13 @@ interface NodeProps { highlight?: boolean; } +const awaitedTankDefinitions = await tankDefinitions; +const awaitedAverageDefinitions = await averageDefinitions; + export function Node({ id, highlight, nextIds }: NodeProps) { const xpMultiplier = TankopediaEphemeral.use((state) => state.xpMultiplier); - const awaitedTankDefinitions = use(tankDefinitions); const tank = awaitedTankDefinitions[id]; const nextTanks = nextIds?.map((id) => awaitedTankDefinitions[id]); - const awaitedAverageDefinitions = use(averageDefinitions); const thisTankXp = tank.xp === undefined || tank.tier === 1 ? 0 : tank.xp! / xpMultiplier; const nextTanksXp = nextTanks?.reduce( diff --git a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx b/packages/website/src/components/Tankopedia/TechTreeSection/index.tsx similarity index 98% rename from packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx rename to packages/website/src/components/Tankopedia/TechTreeSection/index.tsx index 9991f4776..3c10cb058 100644 --- a/packages/website-legacy/src/app/tools/tankopedia/[id]/components/Model/TechTreeSection/index.tsx +++ b/packages/website/src/components/Tankopedia/TechTreeSection/index.tsx @@ -1,7 +1,7 @@ import { asset, imgur, tankDefinitions } from '@blitzkit/core'; import { CaretLeftIcon, CaretRightIcon, PlusIcon } from '@radix-ui/react-icons'; import { Flex, Heading, IconButton, ScrollArea, Text } from '@radix-ui/themes'; -import { Fragment, use, useEffect, useMemo, useRef, useState } from 'react'; +import { Fragment, useEffect, useMemo, useRef, useState } from 'react'; import * as Duel from '../../../../../../../stores/duel'; import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral'; import { Arrow } from './components/Arrow'; @@ -9,13 +9,14 @@ import { Node } from './components/Node'; type Line = number[]; +const awaitedTankDefinitions = await tankDefinitions; + export const XP_MULTIPLIERS = [1, 2, 3, 4, 5, 10]; export function TechTreeSection() { const xpMultiplier = TankopediaEphemeral.use((state) => state.xpMultiplier); const mutateTankopediaEphemeral = TankopediaEphemeral.useMutation(); const master = Duel.use((state) => state.protagonist.tank); - const awaitedTankDefinitions = use(tankDefinitions); const container = useRef(null); const lines = useMemo(() => { function extend(line: Line): Line[] { diff --git a/packages/website/src/components/WargamingAccountName.tsx b/packages/website/src/components/WargamingAccountName.tsx index e1fc3c19b..accb88c06 100644 --- a/packages/website/src/components/WargamingAccountName.tsx +++ b/packages/website/src/components/WargamingAccountName.tsx @@ -6,21 +6,21 @@ import usePromise from 'react-promise-suspense'; import { $wargamingLogin } from '../stores/wargamingLogin'; export function WargamingAccountName() { - const wargamingLogin = useStore($wargamingLogin); + const wargaming = useStore($wargamingLogin); const promise = useMemo(async () => { - if (!wargamingLogin.token) return null; + if (!wargaming.token) return null; const data = await getAccountInfo( - idToRegion(Number(wargamingLogin.id)), - Number(wargamingLogin.id), + idToRegion(Number(wargaming.id)), + Number(wargaming.id), [], { - access_token: wargamingLogin.token, + access_token: wargaming.token, }, ); return data?.nickname as string | undefined; - }, [wargamingLogin.token]); + }, [wargaming]); const nickname = usePromise(() => promise, []); return nickname ?? Unknown Account; diff --git a/packages/website/src/core/blitz/correctZYTuple.ts b/packages/website/src/core/blitz/correctZYTuple.ts index 7eeca33f6..99a536268 100644 --- a/packages/website/src/core/blitz/correctZYTuple.ts +++ b/packages/website/src/core/blitz/correctZYTuple.ts @@ -1,4 +1,4 @@ -import { Vector3, Vector3Tuple } from 'three'; +import { Vector3, type Vector3Tuple } from 'three'; import { rotateDavaVector } from './rotateDavaVector'; export function correctZYTuple(tuple: Vector3Tuple) { diff --git a/packages/website/src/core/blitzkit/jsxTree.tsx b/packages/website/src/core/blitzkit/jsxTree.tsx index 1b05e4c4c..4ae843b6c 100644 --- a/packages/website/src/core/blitzkit/jsxTree.tsx +++ b/packages/website/src/core/blitzkit/jsxTree.tsx @@ -1,4 +1,4 @@ -import { GroupProps, MeshProps } from '@react-three/fiber'; +import type { GroupProps, MeshProps } from '@react-three/fiber'; import { Mesh, Object3D } from 'three'; export function jsxTree( diff --git a/packages/website/src/core/zustand/createContextualSafeStore.tsx b/packages/website/src/core/zustand/createContextualStore.tsx similarity index 97% rename from packages/website/src/core/zustand/createContextualSafeStore.tsx rename to packages/website/src/core/zustand/createContextualStore.tsx index 902ab6764..ba5324990 100644 --- a/packages/website/src/core/zustand/createContextualSafeStore.tsx +++ b/packages/website/src/core/zustand/createContextualStore.tsx @@ -20,7 +20,7 @@ type ExtractState = S extends { ? T : never; -export function createContextualSafeStore< +export function createContextualStore< Store extends StoreApi, InitData, >(initialize: (data: InitData) => Store) { diff --git a/packages/website/src/hooks/useAdExempt.ts b/packages/website/src/hooks/useAdExempt.ts index bf0ad69aa..6dd27f712 100644 --- a/packages/website/src/hooks/useAdExempt.ts +++ b/packages/website/src/hooks/useAdExempt.ts @@ -5,17 +5,17 @@ import { $patreonLogin } from '../stores/patreonLogin'; let cache: Record> = {}; export function useAdExempt() { - const patreonLogin = useStore($patreonLogin); + const patreon = useStore($patreonLogin); const [exempt, setExempt] = useState(false); useLayoutEffect(() => { (async () => { - if (!patreonLogin.token) return setExempt(false); + if (!patreon.token) return setExempt(false); - if (!(patreonLogin.token in cache)) { - cache[patreonLogin.token] = new Promise(async (resolve) => { + if (!(patreon.token in cache)) { + cache[patreon.token] = new Promise(async (resolve) => { const response = await fetch( - `/api/patreon/membership/${patreonLogin.token}`, + `/api/patreon/membership/${patreon.token}`, { cache: 'force-cache' }, ); @@ -24,12 +24,12 @@ export function useAdExempt() { const json = await response.json(); const exempt = typeof json === 'boolean' && json; - cache[patreonLogin.token] = exempt; + cache[patreon.token] = exempt; resolve(exempt); }); } - setExempt(await cache[patreonLogin.token]); + setExempt(await cache[patreon.token]); })(); }, []); diff --git a/packages/website/src/hooks/useArmor.ts b/packages/website/src/hooks/useArmor.ts index 4dd0b160d..b68907e8e 100644 --- a/packages/website/src/hooks/useArmor.ts +++ b/packages/website/src/hooks/useArmor.ts @@ -1,6 +1,6 @@ import { asset } from '@blitzkit/core'; -import { ObjectMap, useLoader } from '@react-three/fiber'; -import { GLTF, GLTFLoader } from 'three-stdlib'; +import { type ObjectMap, useLoader } from '@react-three/fiber'; +import { type GLTF, GLTFLoader } from 'three-stdlib'; const cache: Record< number, diff --git a/packages/website/src/hooks/useAveragesExclusionRatio.ts b/packages/website/src/hooks/useAveragesExclusionRatio.ts index c5375356f..7b746a9c7 100644 --- a/packages/website/src/hooks/useAveragesExclusionRatio.ts +++ b/packages/website/src/hooks/useAveragesExclusionRatio.ts @@ -1,10 +1,9 @@ import { averageDefinitions, discoveredIdsDefinitions } from '@blitzkit/core'; -import { use } from 'react'; + +const awaitedDiscoveredIdsDefinitions = await discoveredIdsDefinitions; +const awaitedAverageDefinitions = await averageDefinitions; export function useAveragesExclusionRatio() { - const awaitedDiscoveredIdsDefinitions = use(discoveredIdsDefinitions); - const awaitedAverageDefinitions = use(averageDefinitions); - return ( awaitedDiscoveredIdsDefinitions.count / awaitedAverageDefinitions.samples.total diff --git a/packages/website/src/hooks/useEccentricity.ts b/packages/website/src/hooks/useEccentricity.ts index aa7d1d45c..57c6f2ba5 100644 --- a/packages/website/src/hooks/useEccentricity.ts +++ b/packages/website/src/hooks/useEccentricity.ts @@ -1,6 +1,6 @@ import { TankDefinition, tankDefinitions } from '@blitzkit/core'; import { sumBy } from 'lodash-es'; -import { use, useMemo } from 'react'; +import { useMemo } from 'react'; import * as Duel from '../stores/duel'; export enum UseEccentricityMode { @@ -8,8 +8,9 @@ export enum UseEccentricityMode { Class, } +const awaitedTankDefinitions = await tankDefinitions; + export function useEccentricity(mode: UseEccentricityMode) { - const awaitedTankDefinitions = use(tankDefinitions); const tank = Duel.use((state) => state.protagonist.tank); const similarTanks = useMemo( () => diff --git a/packages/website/src/hooks/useEquipment.ts b/packages/website/src/hooks/useEquipment.ts index c9cc931f5..f27a4748b 100644 --- a/packages/website/src/hooks/useEquipment.ts +++ b/packages/website/src/hooks/useEquipment.ts @@ -1,9 +1,10 @@ import { equipmentDefinitions } from '@blitzkit/core'; -import { use, useMemo } from 'react'; +import { useMemo } from 'react'; import * as Duel from '../stores/duel'; +const awaitedEquipmentDefinitions = await equipmentDefinitions; + export function useEquipment(id: number, antagonist = false) { - const awaitedEquipmentDefinitions = use(equipmentDefinitions); const member = Duel.use( (state) => state[antagonist ? 'antagonist' : 'protagonist']!, ); diff --git a/packages/website/src/hooks/useModel.ts b/packages/website/src/hooks/useModel.ts index d698c98f3..190f43161 100644 --- a/packages/website/src/hooks/useModel.ts +++ b/packages/website/src/hooks/useModel.ts @@ -1,7 +1,7 @@ import { asset } from '@blitzkit/core'; -import { ObjectMap, useLoader } from '@react-three/fiber'; +import { type ObjectMap, useLoader } from '@react-three/fiber'; import { Mesh, MeshStandardMaterial } from 'three'; -import { GLTF, GLTFLoader } from 'three-stdlib'; +import { type GLTF, GLTFLoader } from 'three-stdlib'; const cache: Record< number, diff --git a/packages/website/src/hooks/useOnScreen.ts b/packages/website/src/hooks/useOnScreen.ts index 27ec8b63e..0c70222eb 100644 --- a/packages/website/src/hooks/useOnScreen.ts +++ b/packages/website/src/hooks/useOnScreen.ts @@ -1,4 +1,4 @@ -import { RefObject, useEffect, useRef, useState } from 'react'; +import { type RefObject, useEffect, useRef, useState } from 'react'; /** * Thanks GuCier! diff --git a/packages/website/src/hooks/useStoreBoolean.ts b/packages/website/src/hooks/useStoreBoolean.ts new file mode 100644 index 000000000..343a006d0 --- /dev/null +++ b/packages/website/src/hooks/useStoreBoolean.ts @@ -0,0 +1,10 @@ +import { type StoreKeys } from '@nanostores/react'; +import type { Store } from 'nanostores'; +import { useStoreKey } from './useStoreKey'; + +export function useStoreBoolean( + store: Store, + key: StoreKeys>, +) { + return Boolean(useStoreKey(store, key)); +} diff --git a/packages/website/src/hooks/useStoreKey.ts b/packages/website/src/hooks/useStoreKey.ts new file mode 100644 index 000000000..e2b694aea --- /dev/null +++ b/packages/website/src/hooks/useStoreKey.ts @@ -0,0 +1,10 @@ +import { useStore, type StoreKeys } from '@nanostores/react'; +import type { Store } from 'nanostores'; + +export function useStoreKey>>( + store: Store, + key: Key, +) { + const state = useStore(store, { keys: [key] }); + return state[key]; +} diff --git a/packages/website/src/hooks/useTankTransform.ts b/packages/website/src/hooks/useTankTransform.ts index 271d6eed8..1469dcb61 100644 --- a/packages/website/src/hooks/useTankTransform.ts +++ b/packages/website/src/hooks/useTankTransform.ts @@ -1,5 +1,5 @@ import { I_HAT, J_HAT, K_HAT } from '@blitzkit/core'; -import { RefObject, useEffect } from 'react'; +import { type RefObject, useEffect } from 'react'; import { Euler, Group, Vector3 } from 'three'; import { degToRad } from 'three/src/math/MathUtils'; import { correctZYTuple } from '../core/blitz/correctZYTuple'; diff --git a/packages/website/src/pages/tools/tankopedia/[id]/index.astro b/packages/website/src/pages/tools/tankopedia/[id]/index.astro new file mode 100644 index 000000000..02104e96b --- /dev/null +++ b/packages/website/src/pages/tools/tankopedia/[id]/index.astro @@ -0,0 +1,17 @@ +--- +import { tankDefinitions } from '@blitzkit/core'; +import type { GetStaticPaths } from 'astro'; +import { Page } from './index'; + +export const getStaticPaths = (async () => { + const awaitedTankDefinitions = await tankDefinitions; + + return Object.values(awaitedTankDefinitions).map((tank) => ({ + params: { id: tank.id }, + })); +}) satisfies GetStaticPaths; + +const { id } = Astro.params; +--- + + diff --git a/packages/website/src/pages/tools/tankopedia/[id]/index.tsx b/packages/website/src/pages/tools/tankopedia/[id]/index.tsx new file mode 100644 index 000000000..7ff7bac9a --- /dev/null +++ b/packages/website/src/pages/tools/tankopedia/[id]/index.tsx @@ -0,0 +1,25 @@ +import { PageWrapper } from '../../../../components/PageWrapper'; +import { HeroSection } from '../../../../components/Tankopedia/HeroSection'; + +interface PageProps { + id: number; +} + +export function Page({ id }: PageProps) { + return ( + + + {/* + + + {!exempt && } + + + {!exempt && } + + + + {!exempt && } */} + + ); +} diff --git a/packages/website/src/stores/app/index.ts b/packages/website/src/stores/app/index.ts index 33d792b8d..06e289e74 100644 --- a/packages/website/src/stores/app/index.ts +++ b/packages/website/src/stores/app/index.ts @@ -1,23 +1,14 @@ -import lodash from 'lodash-es'; import { create } from 'zustand'; -import { persist } from 'zustand/middleware'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; -export interface App { +interface AppStore { developerMode: boolean; policiesAgreementIndex: number; } -export const { Provider, use, useMutation, useStore, useDeferred } = - createContextualSafeStore(() => - create()( - persist( - (set) => ({ - developerMode: false, - policiesAgreementIndex: -1, - logins: {}, - }), - { name: 'app', merge: (a, b) => lodash.merge(b, a) }, - ), - ), - ); +export const App = createContextualStore(() => + create()(() => ({ + developerMode: false, + policiesAgreementIndex: 0, + })), +); diff --git a/packages/website/src/stores/compareEphemeral.ts b/packages/website/src/stores/compareEphemeral.ts index ea8249003..2bb9c9df7 100644 --- a/packages/website/src/stores/compareEphemeral.ts +++ b/packages/website/src/stores/compareEphemeral.ts @@ -1,5 +1,6 @@ import { create } from 'zustand'; -import { DuelMember } from './duel'; +import { createContextualStore } from '../core/zustand/createContextualStore'; +import type { DuelMember } from './duel'; export interface CompareMember extends DuelMember { key: string; @@ -14,10 +15,10 @@ export interface CompareEphemeral { }; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => +export const { Provider, use, useMutation, useStore } = createContextualStore( + () => create()(() => ({ crewSkills: {}, members: [], })), - ); +); diff --git a/packages/website/src/stores/comparePersistent.ts b/packages/website/src/stores/comparePersistent.ts index 3b5c89c2b..28338863b 100644 --- a/packages/website/src/stores/comparePersistent.ts +++ b/packages/website/src/stores/comparePersistent.ts @@ -1,15 +1,15 @@ import lodash from 'lodash-es'; import { create } from 'zustand'; import { persist, subscribeWithSelector } from 'zustand/middleware'; -import { createContextualSafeStore } from '../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../core/zustand/createContextualStore'; export type DeltaMode = 'none' | 'percentage' | 'absolute'; export interface ComparePersistent { deltaMode: DeltaMode; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => +export const { Provider, use, useMutation, useStore } = createContextualStore( + () => create()( persist( subscribeWithSelector(() => ({ @@ -21,4 +21,4 @@ export const { Provider, use, useMutation, useStore } = }, ), ), - ); +); diff --git a/packages/website/src/stores/duel/index.ts b/packages/website/src/stores/duel/index.ts index e1da71f21..ae549d6e7 100644 --- a/packages/website/src/stores/duel/index.ts +++ b/packages/website/src/stores/duel/index.ts @@ -10,7 +10,7 @@ import { import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; import { tankToDuelMember } from '../../core/blitzkit/tankToDuelMember'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; type EquipmentMatrixItem = -1 | 0 | 1; type EquipmentMatrixRow = [ @@ -41,27 +41,26 @@ export interface DuelMember { cooldownBooster: number; } -export interface Duel { +export interface DuelStore { protagonist: DuelMember; antagonist: DuelMember; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore( - ({ - tank, - provisionDefinitions, - }: { - tank: TankDefinition; - provisionDefinitions: ProvisionDefinitions; - }) => { - const protagonist = tankToDuelMember(tank, provisionDefinitions); +export const Duel = createContextualStore( + ({ + tank, + provisionDefinitions, + }: { + tank: TankDefinition; + provisionDefinitions: ProvisionDefinitions; + }) => { + const protagonist = tankToDuelMember(tank, provisionDefinitions); - return create()( - subscribeWithSelector(() => ({ - protagonist, - antagonist: protagonist, - })), - ); - }, - ); + return create()( + subscribeWithSelector(() => ({ + protagonist, + antagonist: protagonist, + })), + ); + }, +); diff --git a/packages/website/src/stores/embedState/index.ts b/packages/website/src/stores/embedState/index.ts index f2379712c..f229a8ce4 100644 --- a/packages/website/src/stores/embedState/index.ts +++ b/packages/website/src/stores/embedState/index.ts @@ -1,6 +1,6 @@ import * as radixColors from '@radix-ui/colors'; import { create } from 'zustand'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; import { type EmbedConfigItemType, EmbedItemType, @@ -104,7 +104,6 @@ export type EmbedConfigItem = ( export type EmbedState = Record; -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore((init: EmbedState) => - create()(() => init), - ); +export const { Provider, use, useMutation, useStore } = createContextualStore( + (init: EmbedState) => create()(() => init), +); diff --git a/packages/website/src/stores/session.ts b/packages/website/src/stores/session.ts index 358d454ef..c33ff72a3 100644 --- a/packages/website/src/stores/session.ts +++ b/packages/website/src/stores/session.ts @@ -2,7 +2,7 @@ import { IndividualTankStats, Region, Stat } from '@blitzkit/core'; import lodash from 'lodash-es'; import { create } from 'zustand'; import { persist } from 'zustand/middleware'; -import { createContextualSafeStore } from '../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../core/zustand/createContextualStore'; interface SessionBase { columns: Stat[]; @@ -24,8 +24,8 @@ interface SessionNotTracking extends SessionBase { type Session = SessionTracking | SessionNotTracking; -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => +export const { Provider, use, useMutation, useStore } = createContextualStore( + () => create()( persist( (set) => ({ @@ -35,4 +35,4 @@ export const { Provider, use, useMutation, useStore } = { name: 'session-2', merge: (a, b) => lodash.merge(b, a) }, ), ), - ); +); diff --git a/packages/website/src/stores/tankPerformancePersistent/index.ts b/packages/website/src/stores/tankPerformancePersistent/index.ts index 01dcf20ce..6efe22227 100644 --- a/packages/website/src/stores/tankPerformancePersistent/index.ts +++ b/packages/website/src/stores/tankPerformancePersistent/index.ts @@ -1,15 +1,15 @@ import lodash from 'lodash-es'; import { create } from 'zustand'; import { persist, subscribeWithSelector } from 'zustand/middleware'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; import { PlayerCountPeriod } from './constants'; export interface TankPerformancePersistent { playerCountPeriod: PlayerCountPeriod; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => +export const { Provider, use, useMutation, useStore } = createContextualStore( + () => create()( persist( subscribeWithSelector(() => ({ @@ -18,4 +18,4 @@ export const { Provider, use, useMutation, useStore } = { name: 'tank-performance', merge: (a, b) => lodash.merge(b, a) }, ), ), - ); +); diff --git a/packages/website/src/stores/tankPerformanceSort/index.ts b/packages/website/src/stores/tankPerformanceSort/index.ts index a3c47e803..5269453a2 100644 --- a/packages/website/src/stores/tankPerformanceSort/index.ts +++ b/packages/website/src/stores/tankPerformanceSort/index.ts @@ -1,5 +1,5 @@ import { create } from 'zustand'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; import { TankPerformanceSortTypeNames } from './constants'; export type TankPerformanceSortType = keyof typeof TankPerformanceSortTypeNames; @@ -9,10 +9,10 @@ export interface TankPerformanceSort { direction: -1 | 1; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => +export const { Provider, use, useMutation, useStore } = createContextualStore( + () => create()(() => ({ type: 'winrate', direction: -1, })), - ); +); diff --git a/packages/website/src/stores/tankopediaEphemeral.ts b/packages/website/src/stores/tankopediaEphemeral.ts index 28cfd75e7..d4ea624c0 100644 --- a/packages/website/src/stores/tankopediaEphemeral.ts +++ b/packages/website/src/stores/tankopediaEphemeral.ts @@ -1,34 +1,11 @@ -import { ModelDefinition } from '@blitzkit/core'; +import type { ModelDefinition } from '@blitzkit/core'; import { Vector3 } from 'three'; import { create } from 'zustand'; import { subscribeWithSelector } from 'zustand/middleware'; -import { XP_MULTIPLIERS } from '../app/tools/tankopedia/[id]/components/Model/TechTreeSection'; import { ArmorType } from '../components/Armor/components/SpacedArmorScene'; -import { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent'; -import { createContextualSafeStore } from '../core/zustand/createContextualSafeStore'; - -interface TankopediaEphemeral { - shot?: Shot; - skills: Record; - controlsEnabled: boolean; - model: ModelDefinition; - editStatic: boolean; - highlightArmor?: { - editingPlate: boolean; - name: string; - point: Vector3; - thickness: number; - color: string; - } & ( - | { - type: ArmorType.Primary | ArmorType.Spaced; - thicknessAngled: number; - angle: number; - } - | { type: ArmorType.External } - ); - xpMultiplier: (typeof XP_MULTIPLIERS)[number]; -} +import type { ExternalModuleVariant } from '../components/Armor/components/SpacedArmorSceneComponent'; +import type { XP_MULTIPLIERS } from '../components/Tankopedia/TechTreeSection'; +import { createContextualStore } from '../core/zustand/createContextualStore'; export interface ShotLayerBase { index: number; @@ -89,8 +66,8 @@ export type ArmorPiercingLayer = gap: number; }; -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore((model: ModelDefinition) => +export const TankopediaEphemeral = createContextualStore( + (model: ModelDefinition) => create()( subscribeWithSelector(() => ({ editStatic: false, @@ -100,4 +77,27 @@ export const { Provider, use, useMutation, useStore } = xpMultiplier: 1, })), ), +); + +interface TankopediaEphemeral { + shot?: Shot; + skills: Record; + controlsEnabled: boolean; + model: ModelDefinition; + editStatic: boolean; + highlightArmor?: { + editingPlate: boolean; + name: string; + point: Vector3; + thickness: number; + color: string; + } & ( + | { + type: ArmorType.Primary | ArmorType.Spaced; + thicknessAngled: number; + angle: number; + } + | { type: ArmorType.External } ); + xpMultiplier: (typeof XP_MULTIPLIERS)[number]; +} diff --git a/packages/website/src/stores/tankopediaPersistent/index.ts b/packages/website/src/stores/tankopediaPersistent/index.ts index 80bfaf8af..1b60b4ab7 100644 --- a/packages/website/src/stores/tankopediaPersistent/index.ts +++ b/packages/website/src/stores/tankopediaPersistent/index.ts @@ -1,76 +1,53 @@ -import type { TankClass, Tier, TreeType } from '@blitzkit/core'; -import lodash from 'lodash-es'; +import * as lodash from 'lodash-es'; import { create } from 'zustand'; -import { persist, subscribeWithSelector } from 'zustand/middleware'; +import { persist } from 'zustand/middleware'; import { ENVIRONMENTS } from '../../constants/lightingEnvironments'; -import { createContextualSafeStore } from '../../core/zustand/createContextualSafeStore'; +import { createContextualStore } from '../../core/zustand/createContextualStore'; import { SORT_NAMES, TankopediaDisplay } from './constants'; export type TankopediaSortBy = keyof typeof SORT_NAMES; export type TankopediaSortDirection = 'ascending' | 'descending'; export type TankopediaTestTankDisplay = 'include' | 'exclude' | 'only'; -export interface TankopediaPersistent { - model: { - visual: { - wireframe: boolean; - opaque: boolean; - environment: (typeof ENVIRONMENTS)[number]; - showGrid: boolean; - greenPenetration: boolean; - showEnvironment: boolean; - showSpacedArmor: boolean; - showExternalModules: boolean; - showPrimaryArmor: boolean; - }; - }; + +export interface TankopediaPersistentStore { + wireframe: boolean; + opaque: boolean; + environment: (typeof ENVIRONMENTS)[number]; + showGrid: boolean; + greenPenetration: boolean; + showEnvironment: boolean; + showSpacedArmor: boolean; + showExternalModules: boolean; + showPrimaryArmor: boolean; + sort: { by: TankopediaSortBy; direction: TankopediaSortDirection; }; - filters: { - tiers: Tier[]; - types: TankClass[]; - treeTypes: TreeType[]; - nations: string[]; - test: TankopediaTestTankDisplay; - page: number; - }; + display: TankopediaDisplay; } -export const { Provider, use, useMutation, useStore } = - createContextualSafeStore(() => - create()( - persist( - subscribeWithSelector(() => ({ - model: { - visual: { - showSpacedArmor: true, - showExternalModules: true, - showPrimaryArmor: true, - wireframe: false, - opaque: false, - environment: ENVIRONMENTS[0], - showGrid: true, - greenPenetration: false, - showEnvironment: false, - }, - }, - sort: { - by: 'meta.none', - direction: 'descending', - }, - filters: { - tiers: [], - types: [], - treeTypes: [], - nations: [], - test: 'include', - page: 0, - }, - display: TankopediaDisplay.Model, - })), - { name: 'tankopedia', merge: (a, b) => lodash.merge(b, a) }, - ), +export const TankopediaPersistent = createContextualStore(() => + create()( + persist( + (set) => ({ + wireframe: false, + opaque: false, + environment: ENVIRONMENTS[0], + showGrid: true, + greenPenetration: true, + showEnvironment: true, + showSpacedArmor: true, + showExternalModules: true, + showPrimaryArmor: true, + sort: { + by: 'meta.none', + direction: 'ascending', + }, + display: TankopediaDisplay.Model, + }), + { name: 'tankopedia', merge: (a, b) => lodash.merge(b, a) }, ), - ); + ), +);