feat: host functionality

This commit is contained in:
TrèsAbhi committed 2024-10-28 10:30:53 -05:00
1 parent 3c7a10a949
commit 8512557e76
6 files changed
+93 -34

No files matched your search

@@ -9,9 +9,9 @@ interface PreviewWrapperProps {
}
export function PreviewWrapper({ name }: PreviewWrapperProps) {
const { useState } = useEmbedStateCurry();
const width = useState('width');
const height = useState('height');
const { useEmbedState } = useEmbedStateCurry();
const width = useEmbedState('width');
const height = useEmbedState('height');
const Preview = embedPreviews[name];
const wrapper = useRef<HTMLDivElement>(null);
@@ -1,6 +1,15 @@
import { compositeStatsKeys, fetchTankDefinitions } from '@blitzkit/core';
import {
compositeStatsKeys,
deltaTankStats,
fetchTankDefinitions,
getTankStats,
idToRegion,
type IndividualTankStats,
} from '@blitzkit/core';
import strings from '@blitzkit/core/lang/en-US.json';
import { useEffect, useMemo, useState } from 'react';
import { breakdownConfig } from '../../constants/embeds';
import { EmbedBreakdownPersistent } from '../../stores/embedBreakdownPersistent';
import { useEmbedStateCurry } from '../../stores/embedState/utilities';
import { BreakdownEmbedCard, BreakdownEmbedWrapper } from '../TanksEmbed';
@@ -9,18 +18,17 @@ export const compositeStatsKeysOptions = compositeStatsKeys.map((value) => ({
value,
}));
const tanks = await fetchTankDefinitions().then((tanks) =>
Object.values(tanks.tanks),
);
const tankDefinitions = await fetchTankDefinitions();
const tanks = Object.values(tankDefinitions);
export function BreakdownPreview() {
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
const { useEmbedState } = useEmbedStateCurry<typeof breakdownConfig>();
return (
<BreakdownEmbedWrapper>
{useState('showTotal') && <BreakdownEmbedCard tank={null} />}
{useEmbedState('showTotal') && <BreakdownEmbedCard tank={null} />}
{tanks.slice(0, useState('listMaxTanks')).map((tank) => (
{tanks.slice(0, useEmbedState('listMaxTanks')).map((tank) => (
<BreakdownEmbedCard key={tank.id} tank={tank} />
))}
</BreakdownEmbedWrapper>
@@ -28,15 +36,48 @@ export function BreakdownPreview() {
}
export function BreakdownRenderer() {
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
return (
<EmbedBreakdownPersistent.Provider>
<BreakdownRendererContent />
</EmbedBreakdownPersistent.Provider>
);
}
function BreakdownRendererContent() {
const { useEmbedState } = useEmbedStateCurry<typeof breakdownConfig>();
const params = new URLSearchParams(window.location.search);
const id = Number(params.get('id'));
const tankStatsA = EmbedBreakdownPersistent.use((state) => state[id] ?? []);
const [tankStatsB, setTankStatsB] = useState<IndividualTankStats[]>([]);
const diff = useMemo(
() =>
deltaTankStats(tankStatsA, tankStatsB).sort(
(a, b) => b.last_battle_time - a.last_battle_time,
),
[tankStatsB],
);
useEffect(() => {
const interval = setInterval(async () => {
const newB = await getTankStats(idToRegion(id), id);
if (newB === null) return;
setTankStatsB(newB);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<BreakdownEmbedWrapper>
{useState('showTotal') && <BreakdownEmbedCard tank={null} />}
{useEmbedState('showTotal') && <BreakdownEmbedCard tank={null} />}
{tanks.slice(0, useState('listMaxTanks')).map((tank) => (
<BreakdownEmbedCard key={tank.id} tank={tank} />
))}
{diff.slice(0, useEmbedState('listMaxTanks')).map((diff) => {
const tank = tankDefinitions.tanks[diff.tank_id];
return <BreakdownEmbedCard key={tank.id} tank={tank} />;
})}
</BreakdownEmbedWrapper>
);
}
+15 -13
View File
@@ -25,10 +25,10 @@ interface BreakdownEmbedWrapperProps {
export function BreakdownEmbedWrapper({
children,
}: BreakdownEmbedWrapperProps) {
const { useState } = useEmbedStateCurry<typeof breakdownConfig>();
const { useEmbedState } = useEmbedStateCurry<typeof breakdownConfig>();
return (
<Flex direction="column" gap={useState('listGap')} height="100%">
<Flex direction="column" gap={useEmbedState('listGap')} height="100%">
{children}
</Flex>
);
@@ -39,7 +39,7 @@ interface BreakdownEmbedCardProps {
}
export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
const { useState, useRichText } =
const { useEmbedState, useRichText } =
useEmbedStateCurry<typeof breakdownConfig>();
return (
@@ -47,17 +47,17 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
flexShrink="0"
direction="column"
style={{
borderRadius: toRadiusVar(useState('cardRadius')),
borderRadius: toRadiusVar(useEmbedState('cardRadius')),
overflow: 'hidden',
backgroundColor: useState('cardBodyBackgroundColor'),
backgroundColor: useEmbedState('cardBodyBackgroundColor'),
}}
>
<Flex
justify="center"
style={{
backgroundColor: useState('cardHeaderBackgroundColor'),
backgroundColor: useEmbedState('cardHeaderBackgroundColor'),
}}
p={useState('cardHeaderPadding')}
p={useEmbedState('cardHeaderPadding')}
>
<Text
{...{
@@ -66,7 +66,7 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
tank === null
? undefined
: tank.type === TankType.RESEARCHABLE ||
!useState('cardTitleTypeColor')
!useEmbedState('cardTitleTypeColor')
? undefined
: {
color:
@@ -77,7 +77,7 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
}}
>
<Flex align="center" gap="1">
{useState('cardTitleClassIcon') && tank !== null && (
{useEmbedState('cardTitleClassIcon') && tank !== null && (
<>
{tank.class === TankClass.LIGHT && (
<ClassLight width="1em" height="1em" />
@@ -98,18 +98,20 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) {
</Text>
</Flex>
<Flex p={useState('cardBodyPadding')}>
<Flex p={useEmbedState('cardBodyPadding')}>
{times(4, (index) => {
const column = (index + 1) as 1 | 2 | 3 | 4;
const columnState = useState(`column${column}`) as CompositeStatsKey;
const customLabel = useState(`column${column}CustomLabel`);
const columnState = useEmbedState(
`column${column}`,
) as CompositeStatsKey;
const customLabel = useEmbedState(`column${column}CustomLabel`);
return (
<Flex
key={column}
direction="column"
align="center"
gap={useState('columnGap')}
gap={useEmbedState('columnGap')}
flexGrow="1"
>
<Text {...useRichText('columnValue')}>
@@ -40,9 +40,9 @@ export function Page({ embed }: PageProps) {
function Content({ embed }: PageProps) {
const Renderer = embedRenderers[embed];
const { useState } = useEmbedStateCurry();
const width = useState('width');
const height = useState('height');
const { useEmbedState } = useEmbedStateCurry();
const width = useEmbedState('width');
const height = useEmbedState('height');
return (
<BlitzKitTheme style={{ background: 'transparent' }}>
@@ -0,0 +1,16 @@
import { type IndividualTankStats } from '@blitzkit/core';
import * as lodash from 'lodash-es';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { createContextualStore } from '../core/zustand/createContextualStore';
type EmbedBreakdownPersistentStore = Record<number, IndividualTankStats[]>;
export const EmbedBreakdownPersistent = createContextualStore(() =>
create<EmbedBreakdownPersistentStore>()(
persist(() => ({}), {
name: 'embed-breakdown',
merge: (a, b) => lodash.merge(b, a),
}),
),
);
@@ -3,7 +3,7 @@ import { EmbedState, type EmbedConfig, type ExtractEmbedConfigTypes } from '.';
import type { EmbedConfigItemType, EmbedItemType } from './constants';
export function useEmbedStateCurry<Config extends EmbedConfig>() {
function useState<Key extends keyof Config>(key: Key) {
function useEmbedState<Key extends keyof Config>(key: Key) {
return EmbedState.use((state) => {
return (state as ExtractEmbedConfigTypes<Config>)[key];
});
@@ -16,7 +16,7 @@ export function useEmbedStateCurry<Config extends EmbedConfig>() {
: never;
}[keyof Config],
>(key: Key) {
const { color, ...state } = useState(
const { color, ...state } = useEmbedState(
key,
) as EmbedConfigItemType<EmbedItemType.RichText>['default'];
@@ -26,5 +26,5 @@ export function useEmbedStateCurry<Config extends EmbedConfig>() {
} satisfies TextProps;
}
return { useState, useRichText };
return { useEmbedState, useRichText };
}