From 0406a4a4644dea3ddc1c48826b7c5f5bd2bc0024 Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Thu, 30 Nov 2023 21:49:57 +0100 Subject: [PATCH] feat: integrate "default characters" into character selection (#30) --- .../EsiCharacterSelection.stories.tsx | 9 ++- .../EsiCharacterSelection.tsx | 10 +-- src/EsiProvider/EsiProvider.stories.tsx | 10 ++- src/EsiProvider/EsiProvider.tsx | 63 ++++++++++++++++++- src/HullListing/HullListing.stories.tsx | 2 +- 5 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/EsiCharacterSelection/EsiCharacterSelection.stories.tsx b/src/EsiCharacterSelection/EsiCharacterSelection.stories.tsx index 5b31b68..d178b84 100644 --- a/src/EsiCharacterSelection/EsiCharacterSelection.stories.tsx +++ b/src/EsiCharacterSelection/EsiCharacterSelection.stories.tsx @@ -3,6 +3,7 @@ import React from "react"; import { EsiProvider } from '../EsiProvider'; import { EsiCharacterSelection } from './'; +import { EveDataProvider } from '../EveDataProvider'; const meta: Meta = { component: EsiCharacterSelection, @@ -15,9 +16,11 @@ type Story = StoryObj; const withEsiProvider: Decorator> = (Story) => { return ( - - - + + + + + ); } diff --git a/src/EsiCharacterSelection/EsiCharacterSelection.tsx b/src/EsiCharacterSelection/EsiCharacterSelection.tsx index 7cd0a27..25418cb 100644 --- a/src/EsiCharacterSelection/EsiCharacterSelection.tsx +++ b/src/EsiCharacterSelection/EsiCharacterSelection.tsx @@ -13,17 +13,9 @@ import styles from "./EsiCharacterSelection.module.css"; export const EsiCharacterSelection = () => { const esi = React.useContext(EsiContext); - if (Object.keys(esi.characters ?? {}).length === 0) { - return
- -
- } - return
diff --git a/src/EsiProvider/EsiProvider.stories.tsx b/src/EsiProvider/EsiProvider.stories.tsx index 3691686..d536174 100644 --- a/src/EsiProvider/EsiProvider.stories.tsx +++ b/src/EsiProvider/EsiProvider.stories.tsx @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from "react"; import { EsiContext, EsiProvider } from './'; +import { EveDataProvider } from '../EveDataProvider'; const meta: Meta = { component: EsiProvider, @@ -33,10 +34,13 @@ const TestEsi = () => { export const Default: Story = { args: { + setSkills: (skills: Record) => { console.log(skills); } }, render: (args) => ( - - - + + + + + ), }; diff --git a/src/EsiProvider/EsiProvider.tsx b/src/EsiProvider/EsiProvider.tsx index e0a615a..229a9ba 100644 --- a/src/EsiProvider/EsiProvider.tsx +++ b/src/EsiProvider/EsiProvider.tsx @@ -6,6 +6,7 @@ import { EsiFit } from "../ShipSnapshotProvider"; import { getAccessToken } from "./EsiAccessToken"; import { getSkills } from "./EsiSkills"; import { getCharFittings } from "./EsiFittings"; +import { EveDataContext } from "../EveDataProvider"; export interface EsiCharacter { name: string; @@ -41,6 +42,8 @@ export const EsiContext = React.createContext({ }); export interface EsiProps { + /** Callback to call when skills are changed. */ + setSkills: (skills: Record) => void; /** Children that can use this provider. */ children: React.ReactNode; } @@ -75,6 +78,8 @@ const useLocalStorage = function (key: string, initialValue: T) { * Keeps track (in local storage) of ESI characters and their refresh token. */ export const EsiProvider = (props: EsiProps) => { + const eveData = React.useContext(EveDataContext); + const [esi, setEsi] = React.useState({ loaded: undefined, characters: {}, @@ -137,10 +142,43 @@ export const EsiProvider = (props: EsiProps) => { }, [esiPrivate.accessTokens, esiPrivate.refreshTokens]); React.useEffect(() => { + if (!eveData.loaded) return; + const characterId = esi.currentCharacter; if (characterId === undefined) return; /* Skills already fetched? We won't do it again till the user reloads. */ - if (esi.characters[characterId]?.skills !== undefined) return; + const currentSkills = esi.characters[characterId]?.skills; + if (currentSkills !== undefined) { + props.setSkills(currentSkills); + return; + } + + if (characterId === '.all-0' || characterId === '.all-5') { + const level = characterId === '.all-0' ? 0 : 5; + + const skills: Record = {}; + for (const typeId in eveData.typeIDs) { + if (eveData?.typeIDs?.[typeId].categoryID !== 16) continue; + skills[typeId] = level; + } + + setEsi((oldEsi: Esi) => { + return { + ...oldEsi, + characters: { + ...oldEsi.characters, + [characterId]: { + ...oldEsi.characters[characterId], + skills, + charFittings: [], + }, + }, + }; + }); + + props.setSkills(skills); + return; + } ensureAccessToken(characterId).then((accessToken) => { if (accessToken === undefined) return; @@ -148,6 +186,13 @@ export const EsiProvider = (props: EsiProps) => { getSkills(characterId, accessToken).then((skills) => { if (skills === undefined) return; + /* Ensure all skills are set; also those not learnt. */ + for (const typeId in eveData.typeIDs) { + if (eveData?.typeIDs?.[typeId].categoryID !== 16) continue; + if (skills[typeId] !== undefined) continue; + skills[typeId] = 0; + } + setEsi((oldEsi: Esi) => { return { ...oldEsi, @@ -160,6 +205,8 @@ export const EsiProvider = (props: EsiProps) => { }, }; }); + + props.setSkills(skills); }); getCharFittings(characterId, accessToken).then((charFittings) => { @@ -182,7 +229,7 @@ export const EsiProvider = (props: EsiProps) => { /* We only update when currentCharacter changes, and ignore all others. */ // eslint-disable-next-line react-hooks/exhaustive-deps - }, [esi.currentCharacter]); + }, [esi.currentCharacter, eveData.loaded]); React.useEffect(() => { if (typeof window === 'undefined') return; @@ -265,9 +312,19 @@ export const EsiProvider = (props: EsiProps) => { } async function startup() { + const charactersDefault = { + '.all-0': { + name: 'Default character - All Skills L0', + }, + '.all-5': { + name: 'Default character - All Skills L5', + }, + ...characters, + }; + setEsi({ loaded: true, - characters, + characters: charactersDefault, currentCharacter, changeCharacter, login, diff --git a/src/HullListing/HullListing.stories.tsx b/src/HullListing/HullListing.stories.tsx index 96c4bbb..fb54419 100644 --- a/src/HullListing/HullListing.stories.tsx +++ b/src/HullListing/HullListing.stories.tsx @@ -21,7 +21,7 @@ type Story = StoryObj; const withEsiProvider: Decorator<{ changeHull: (typeId: number) => void, changeFit: (fit: EsiFit) => void }> = (Story, context) => { return ( - +