mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-25 03:29:51 +01:00
feat: upgrade tankopediaEphemeral
This commit is contained in:
1 parent
ac29d1ead0
commit
d287e66265
5 files changed
+83
-89
No files matched your search
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"trailingComma": "all",
|
|
||||||
"tabWidth": 2,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 80
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { produce } from 'immer';
|
import { produce } from "immer";
|
||||||
import { merge } from 'lodash-es';
|
import { merge } from "lodash-es";
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
interface ProviderProps<Arguments> {
|
interface ProviderProps<Arguments> {
|
||||||
args: Arguments;
|
args: Arguments;
|
||||||
@@ -15,19 +15,9 @@ export class Varuna<Type, Arguments = void> {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private creator: Type | ((...args: Arguments[]) => Type),
|
private creator: Type | ((...args: Arguments[]) => Type),
|
||||||
private persistence?: string,
|
private persistence?: string
|
||||||
) {
|
) {
|
||||||
if (typeof creator !== 'function') this.initialize(creator);
|
if (typeof creator !== "function") this.initialize(creator);
|
||||||
}
|
|
||||||
|
|
||||||
Provider({ args }: ProviderProps<Arguments>) {
|
|
||||||
if (typeof this.creator !== 'function') {
|
|
||||||
throw new Error('Provider must be used with a function creator');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initialize((this.creator as (...args: Arguments[]) => Type)(args));
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private initialize(initial: Type) {
|
private initialize(initial: Type) {
|
||||||
@@ -47,6 +37,16 @@ export class Varuna<Type, Arguments = void> {
|
|||||||
this._state = data;
|
this._state = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useInitialization(...args: Arguments[]) {
|
||||||
|
if (this.initialized) return;
|
||||||
|
|
||||||
|
if (typeof this.creator !== "function") {
|
||||||
|
throw new Error("Provider must be used with a function creator");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.initialize((this.creator as (...args: Arguments[]) => Type)(...args));
|
||||||
|
}
|
||||||
|
|
||||||
private dispatch() {
|
private dispatch() {
|
||||||
const state = this.state;
|
const state = this.state;
|
||||||
this.listeners.forEach((callback) => callback(state));
|
this.listeners.forEach((callback) => callback(state));
|
||||||
@@ -72,7 +72,7 @@ export class Varuna<Type, Arguments = void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private assertInitialized() {
|
private assertInitialized() {
|
||||||
if (!this.initialized) throw new Error('State used before initialization');
|
if (!this.initialized) throw new Error("State used before initialization");
|
||||||
}
|
}
|
||||||
|
|
||||||
get state() {
|
get state() {
|
||||||
@@ -92,7 +92,7 @@ export class Varuna<Type, Arguments = void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use<Slice = Type>(
|
use<Slice = Type>(
|
||||||
slicer: (state: Type) => Slice = (state) => state as unknown as Slice,
|
slicer: (state: Type) => Slice = (state) => state as unknown as Slice
|
||||||
) {
|
) {
|
||||||
const [slice, setSlice] = useState(slicer(this.state));
|
const [slice, setSlice] = useState(slicer(this.state));
|
||||||
useEffect(() => this.on(slicer, setSlice), []);
|
useEffect(() => this.on(slicer, setSlice), []);
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { Box, Flex, Heading } from '@radix-ui/themes';
|
import { Box, Flex, Heading } from "@radix-ui/themes";
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from "react";
|
||||||
import { GuessBackground } from '../../../components/GuessBackground';
|
import { GuessBackground } from "../../../components/GuessBackground";
|
||||||
import { Guesser } from '../../../components/Guesser';
|
import { Guesser } from "../../../components/Guesser";
|
||||||
import { GuessRenderer } from '../../../components/GuessRenderer';
|
import { GuessRenderer } from "../../../components/GuessRenderer";
|
||||||
import { GuessRendererLoader } from '../../../components/GuessRendererLoader';
|
import { GuessRendererLoader } from "../../../components/GuessRendererLoader";
|
||||||
import { awaitableModelDefinitions } from '../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from "../../../core/awaitables/modelDefinitions";
|
||||||
import { awaitableProvisionDefinitions } from '../../../core/awaitables/provisionDefinitions';
|
import { awaitableProvisionDefinitions } from "../../../core/awaitables/provisionDefinitions";
|
||||||
import { awaitableTankDefinitions } from '../../../core/awaitables/tankDefinitions';
|
import { awaitableTankDefinitions } from "../../../core/awaitables/tankDefinitions";
|
||||||
import {
|
import {
|
||||||
type LocaleAcceptorProps,
|
type LocaleAcceptorProps,
|
||||||
LocaleProvider,
|
LocaleProvider,
|
||||||
useLocale,
|
useLocale,
|
||||||
} from '../../../hooks/useLocale';
|
} from "../../../hooks/useLocale";
|
||||||
import { Duel } from '../../../stores/duel';
|
import { Duel } from "../../../stores/duel";
|
||||||
import { GuessEphemeral } from '../../../stores/guessEphemeral';
|
import { GuessEphemeral } from "../../../stores/guessEphemeral";
|
||||||
import { TankopediaEphemeral } from '../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from "../../../stores/tankopediaEphemeral";
|
||||||
|
|
||||||
const [tankDefinitions, modelDefinitions, provisionDefinitions] =
|
const [tankDefinitions, modelDefinitions, provisionDefinitions] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -42,13 +42,12 @@ function Container() {
|
|||||||
const tank = GuessEphemeral.use((state) => state.tank);
|
const tank = GuessEphemeral.use((state) => state.tank);
|
||||||
const model = modelDefinitions.models[tank.id];
|
const model = modelDefinitions.models[tank.id];
|
||||||
|
|
||||||
|
TankopediaEphemeral.useInitialization(model);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Duel.Provider data={{ tank, model, provisionDefinitions }}>
|
||||||
<TankopediaEphemeral.Provider args={model} />
|
<Content />
|
||||||
<Duel.Provider data={{ tank, model, provisionDefinitions }}>
|
</Duel.Provider>
|
||||||
<Content />
|
|
||||||
</Duel.Provider>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ function Content() {
|
|||||||
const isRevealed = guessState !== null;
|
const isRevealed = guessState !== null;
|
||||||
const name = unwrap(tank.name);
|
const name = unwrap(tank.name);
|
||||||
const fontSize = `min(48vh, ${55 / name.length}vw)`;
|
const fontSize = `min(48vh, ${55 / name.length}vw)`;
|
||||||
const transitionDuration = isRevealed ? '2s' : undefined;
|
const transitionDuration = isRevealed ? "2s" : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex flexGrow="1" position="relative" overflow="hidden">
|
<Flex flexGrow="1" position="relative" overflow="hidden">
|
||||||
@@ -70,14 +69,14 @@ function Content() {
|
|||||||
transitionDuration,
|
transitionDuration,
|
||||||
opacity: isRevealed ? 1 : 0,
|
opacity: isRevealed ? 1 : 0,
|
||||||
fontWeight: 900,
|
fontWeight: 900,
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
left: '50%',
|
left: "50%",
|
||||||
top: '50%',
|
top: "50%",
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: "translate(-50%, -50%)",
|
||||||
fontSize,
|
fontSize,
|
||||||
userSelect: 'none',
|
userSelect: "none",
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: "nowrap",
|
||||||
pointerEvents: 'none',
|
pointerEvents: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
@@ -101,14 +100,14 @@ function Content() {
|
|||||||
transitionDuration,
|
transitionDuration,
|
||||||
opacity: isRevealed ? 0.5 : 0,
|
opacity: isRevealed ? 0.5 : 0,
|
||||||
fontWeight: 900,
|
fontWeight: 900,
|
||||||
position: 'absolute',
|
position: "absolute",
|
||||||
left: '50%',
|
left: "50%",
|
||||||
top: '50%',
|
top: "50%",
|
||||||
transform: 'translate(-50%, -50%)',
|
transform: "translate(-50%, -50%)",
|
||||||
fontSize,
|
fontSize,
|
||||||
userSelect: 'none',
|
userSelect: "none",
|
||||||
whiteSpace: 'nowrap',
|
whiteSpace: "nowrap",
|
||||||
pointerEvents: 'none',
|
pointerEvents: "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
import { TankType } from '@blitzkit/core';
|
import { TankType } from "@blitzkit/core";
|
||||||
import { PageWrapper } from '../../../../components/PageWrapper';
|
import { PageWrapper } from "../../../../components/PageWrapper";
|
||||||
import { CalloutsSection } from '../../../../components/Tankopedia/CalloutsSection';
|
import { CalloutsSection } from "../../../../components/Tankopedia/CalloutsSection";
|
||||||
import { CharacteristicsSection } from '../../../../components/Tankopedia/CharacteristicsSection';
|
import { CharacteristicsSection } from "../../../../components/Tankopedia/CharacteristicsSection";
|
||||||
import { GameModeSection } from '../../../../components/Tankopedia/GameModeSection';
|
import { GameModeSection } from "../../../../components/Tankopedia/GameModeSection";
|
||||||
import { GuideSection } from '../../../../components/Tankopedia/GuideSection';
|
import { GuideSection } from "../../../../components/Tankopedia/GuideSection";
|
||||||
import { HeroSection } from '../../../../components/Tankopedia/HeroSection';
|
import { HeroSection } from "../../../../components/Tankopedia/HeroSection";
|
||||||
import { MetaSection } from '../../../../components/Tankopedia/MetaSection';
|
import { MetaSection } from "../../../../components/Tankopedia/MetaSection";
|
||||||
import { TechTreeSection } from '../../../../components/Tankopedia/TechTreeSection';
|
import { TechTreeSection } from "../../../../components/Tankopedia/TechTreeSection";
|
||||||
import { VideoSection } from '../../../../components/Tankopedia/VideoSection';
|
import { VideoSection } from "../../../../components/Tankopedia/VideoSection";
|
||||||
import { awaitableModelDefinitions } from '../../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from "../../../../core/awaitables/modelDefinitions";
|
||||||
import { awaitableProvisionDefinitions } from '../../../../core/awaitables/provisionDefinitions';
|
import { awaitableProvisionDefinitions } from "../../../../core/awaitables/provisionDefinitions";
|
||||||
import { awaitableTankDefinitions } from '../../../../core/awaitables/tankDefinitions';
|
import { awaitableTankDefinitions } from "../../../../core/awaitables/tankDefinitions";
|
||||||
import {
|
import {
|
||||||
LocaleProvider,
|
LocaleProvider,
|
||||||
type LocaleAcceptorProps,
|
type LocaleAcceptorProps,
|
||||||
} from '../../../../hooks/useLocale';
|
} from "../../../../hooks/useLocale";
|
||||||
import { App } from '../../../../stores/app';
|
import { App } from "../../../../stores/app";
|
||||||
import { Duel } from '../../../../stores/duel';
|
import { Duel } from "../../../../stores/duel";
|
||||||
import { TankopediaEphemeral } from '../../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from "../../../../stores/tankopediaEphemeral";
|
||||||
import { TankopediaPersistent } from '../../../../stores/tankopediaPersistent';
|
import { TankopediaPersistent } from "../../../../stores/tankopediaPersistent";
|
||||||
import type { MaybeSkeletonComponentProps } from '../../../../types/maybeSkeletonComponentProps';
|
import type { MaybeSkeletonComponentProps } from "../../../../types/maybeSkeletonComponentProps";
|
||||||
import type { TankGuide } from './index.astro';
|
import type { TankGuide } from "./index.astro";
|
||||||
|
|
||||||
type PageProps = MaybeSkeletonComponentProps &
|
type PageProps = MaybeSkeletonComponentProps &
|
||||||
LocaleAcceptorProps & {
|
LocaleAcceptorProps & {
|
||||||
@@ -39,9 +39,10 @@ export function Page({ id, skeleton, locale, guide }: PageProps) {
|
|||||||
const tank = tankDefinitions.tanks[id];
|
const tank = tankDefinitions.tanks[id];
|
||||||
const model = modelDefinitions.models[id];
|
const model = modelDefinitions.models[id];
|
||||||
|
|
||||||
|
TankopediaEphemeral.useInitialization(model);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LocaleProvider locale={locale}>
|
<LocaleProvider locale={locale}>
|
||||||
<TankopediaEphemeral.Provider args={model} />
|
|
||||||
<App.Provider>
|
<App.Provider>
|
||||||
<TankopediaPersistent.Provider>
|
<TankopediaPersistent.Provider>
|
||||||
<Duel.Provider
|
<Duel.Provider
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { TankSandbox } from '../../../../../components/Tankopedia/HeroSection/components/TankSandbox';
|
import { TankSandbox } from "../../../../../components/Tankopedia/HeroSection/components/TankSandbox";
|
||||||
import { awaitableModelDefinitions } from '../../../../../core/awaitables/modelDefinitions';
|
import { awaitableModelDefinitions } from "../../../../../core/awaitables/modelDefinitions";
|
||||||
import { awaitableProvisionDefinitions } from '../../../../../core/awaitables/provisionDefinitions';
|
import { awaitableProvisionDefinitions } from "../../../../../core/awaitables/provisionDefinitions";
|
||||||
import { awaitableTankDefinitions } from '../../../../../core/awaitables/tankDefinitions';
|
import { awaitableTankDefinitions } from "../../../../../core/awaitables/tankDefinitions";
|
||||||
import { LocaleProvider } from '../../../../../hooks/useLocale';
|
import { LocaleProvider } from "../../../../../hooks/useLocale";
|
||||||
import { App } from '../../../../../stores/app';
|
import { App } from "../../../../../stores/app";
|
||||||
import { Duel } from '../../../../../stores/duel';
|
import { Duel } from "../../../../../stores/duel";
|
||||||
import { TankopediaEphemeral } from '../../../../../stores/tankopediaEphemeral';
|
import { TankopediaEphemeral } from "../../../../../stores/tankopediaEphemeral";
|
||||||
import { TankopediaPersistent } from '../../../../../stores/tankopediaPersistent';
|
import { TankopediaPersistent } from "../../../../../stores/tankopediaPersistent";
|
||||||
|
|
||||||
const [provisionDefinitions, tankDefinitions, modelDefinitions] =
|
const [provisionDefinitions, tankDefinitions, modelDefinitions] =
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@@ -23,12 +23,13 @@ export function Page({ id }: PageProps) {
|
|||||||
const tank = tankDefinitions.tanks[id];
|
const tank = tankDefinitions.tanks[id];
|
||||||
const model = modelDefinitions.models[id];
|
const model = modelDefinitions.models[id];
|
||||||
|
|
||||||
|
TankopediaEphemeral.useInitialization(model);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LocaleProvider locale="en">
|
<LocaleProvider locale="en">
|
||||||
<App.Provider>
|
<App.Provider>
|
||||||
<TankopediaPersistent.Provider>
|
<TankopediaPersistent.Provider>
|
||||||
<Duel.Provider data={{ provisionDefinitions, model, tank }}>
|
<Duel.Provider data={{ provisionDefinitions, model, tank }}>
|
||||||
<TankopediaEphemeral.Provider args={model} />
|
|
||||||
<Content />
|
<Content />
|
||||||
</Duel.Provider>
|
</Duel.Provider>
|
||||||
</TankopediaPersistent.Provider>
|
</TankopediaPersistent.Provider>
|
||||||
|
|||||||
Reference in new issue
Block a user