From 8512557e76ceeb6d79aa8fad8b3ec6caf2b4b80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com> Date: Mon, 28 Oct 2024 10:30:53 -0500 Subject: [PATCH] feat: host functionality --- .../Embeds/PreviewWrapper/index.tsx | 6 +- .../src/components/Embeds/breakdown.tsx | 65 +++++++++++++++---- .../website/src/components/TanksEmbed.tsx | 28 ++++---- .../pages/tools/embed/[embed]/host/_index.tsx | 6 +- .../src/stores/embedBreakdownPersistent.ts | 16 +++++ .../src/stores/embedState/utilities.ts | 6 +- 6 files changed, 93 insertions(+), 34 deletions(-) create mode 100644 packages/website/src/stores/embedBreakdownPersistent.ts diff --git a/packages/website/src/components/Embeds/PreviewWrapper/index.tsx b/packages/website/src/components/Embeds/PreviewWrapper/index.tsx index 96d34475f..69302cc20 100644 --- a/packages/website/src/components/Embeds/PreviewWrapper/index.tsx +++ b/packages/website/src/components/Embeds/PreviewWrapper/index.tsx @@ -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(null); diff --git a/packages/website/src/components/Embeds/breakdown.tsx b/packages/website/src/components/Embeds/breakdown.tsx index 1f19c877c..12fb612ae 100644 --- a/packages/website/src/components/Embeds/breakdown.tsx +++ b/packages/website/src/components/Embeds/breakdown.tsx @@ -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(); + const { useEmbedState } = useEmbedStateCurry(); return ( - {useState('showTotal') && } + {useEmbedState('showTotal') && } - {tanks.slice(0, useState('listMaxTanks')).map((tank) => ( + {tanks.slice(0, useEmbedState('listMaxTanks')).map((tank) => ( ))} @@ -28,15 +36,48 @@ export function BreakdownPreview() { } export function BreakdownRenderer() { - const { useState } = useEmbedStateCurry(); + return ( + + + + ); +} + +function BreakdownRendererContent() { + const { useEmbedState } = useEmbedStateCurry(); + const params = new URLSearchParams(window.location.search); + const id = Number(params.get('id')); + const tankStatsA = EmbedBreakdownPersistent.use((state) => state[id] ?? []); + const [tankStatsB, setTankStatsB] = useState([]); + 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 ( - {useState('showTotal') && } + {useEmbedState('showTotal') && } - {tanks.slice(0, useState('listMaxTanks')).map((tank) => ( - - ))} + {diff.slice(0, useEmbedState('listMaxTanks')).map((diff) => { + const tank = tankDefinitions.tanks[diff.tank_id]; + + return ; + })} ); } diff --git a/packages/website/src/components/TanksEmbed.tsx b/packages/website/src/components/TanksEmbed.tsx index 428e95abf..8eaa7de7d 100644 --- a/packages/website/src/components/TanksEmbed.tsx +++ b/packages/website/src/components/TanksEmbed.tsx @@ -25,10 +25,10 @@ interface BreakdownEmbedWrapperProps { export function BreakdownEmbedWrapper({ children, }: BreakdownEmbedWrapperProps) { - const { useState } = useEmbedStateCurry(); + const { useEmbedState } = useEmbedStateCurry(); return ( - + {children} ); @@ -39,7 +39,7 @@ interface BreakdownEmbedCardProps { } export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) { - const { useState, useRichText } = + const { useEmbedState, useRichText } = useEmbedStateCurry(); 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'), }} > - {useState('cardTitleClassIcon') && tank !== null && ( + {useEmbedState('cardTitleClassIcon') && tank !== null && ( <> {tank.class === TankClass.LIGHT && ( @@ -98,18 +98,20 @@ export function BreakdownEmbedCard({ tank }: BreakdownEmbedCardProps) { - + {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 ( diff --git a/packages/website/src/pages/tools/embed/[embed]/host/_index.tsx b/packages/website/src/pages/tools/embed/[embed]/host/_index.tsx index 1cb3ab97c..74b70a5a0 100644 --- a/packages/website/src/pages/tools/embed/[embed]/host/_index.tsx +++ b/packages/website/src/pages/tools/embed/[embed]/host/_index.tsx @@ -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 ( diff --git a/packages/website/src/stores/embedBreakdownPersistent.ts b/packages/website/src/stores/embedBreakdownPersistent.ts new file mode 100644 index 000000000..76ec9c965 --- /dev/null +++ b/packages/website/src/stores/embedBreakdownPersistent.ts @@ -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; + +export const EmbedBreakdownPersistent = createContextualStore(() => + create()( + persist(() => ({}), { + name: 'embed-breakdown', + merge: (a, b) => lodash.merge(b, a), + }), + ), +); diff --git a/packages/website/src/stores/embedState/utilities.ts b/packages/website/src/stores/embedState/utilities.ts index 9b2579a1d..adb92cb80 100644 --- a/packages/website/src/stores/embedState/utilities.ts +++ b/packages/website/src/stores/embedState/utilities.ts @@ -3,7 +3,7 @@ import { EmbedState, type EmbedConfig, type ExtractEmbedConfigTypes } from '.'; import type { EmbedConfigItemType, EmbedItemType } from './constants'; export function useEmbedStateCurry() { - function useState(key: Key) { + function useEmbedState(key: Key) { return EmbedState.use((state) => { return (state as ExtractEmbedConfigTypes)[key]; }); @@ -16,7 +16,7 @@ export function useEmbedStateCurry() { : never; }[keyof Config], >(key: Key) { - const { color, ...state } = useState( + const { color, ...state } = useEmbedState( key, ) as EmbedConfigItemType['default']; @@ -26,5 +26,5 @@ export function useEmbedStateCurry() { } satisfies TextProps; } - return { useState, useRichText }; + return { useEmbedState, useRichText }; }