diff --git a/apps/sr-frontend/src/app/Character.tsx b/apps/sr-frontend/src/app/Character.tsx index 3131061ea0..c67d4f772b 100644 --- a/apps/sr-frontend/src/app/Character.tsx +++ b/apps/sr-frontend/src/app/Character.tsx @@ -6,17 +6,27 @@ import { srCalculatorWithEntries, } from '@genshin-optimizer/sr-formula' import { - CharacterContext, useCharacter, + useCharacterContext, useCharacterReducer, } from '@genshin-optimizer/sr-ui' import { CardThemed } from '@genshin-optimizer/ui-common' -import { Box, CardContent, Stack, TextField, Typography } from '@mui/material' +import { ExpandMore } from '@mui/icons-material' +import { + Accordion, + AccordionDetails, + AccordionSummary, + Box, + CardContent, + Stack, + TextField, + Typography, +} from '@mui/material' import { Container } from '@mui/system' -import { useContext, useMemo } from 'react' +import { useMemo } from 'react' export default function Character() { - const { characterKey } = useContext(CharacterContext) + const { characterKey } = useCharacterContext() const character = useCharacter(characterKey) const charReducer = useCharacterReducer(characterKey) @@ -45,7 +55,7 @@ export default function Character() { label="Level" variant="outlined" inputProps={{ min: 1, max: 90 }} - value={character?.level} + value={character?.level || 0} onChange={(e) => charReducer({ level: parseInt(e.target.value) })} /> charReducer({ ascension: parseInt(e.target.value) as AscensionKey, }) } /> - {( - [ - ['ATK', 'atk'], - ['DEF', 'def'], - ['HP', 'hp'], - ['SPD', 'spd'], - ] as const - ).map(([txt, skey]) => ( - - {txt}: {calc?.compute(self.stat[skey].src('char')).val} - - ))} + + }> + Basic stats for all chars + + + {( + [ + ['ATK', 'atk'], + ['DEF', 'def'], + ['HP', 'hp'], + ['SPD', 'spd'], + ] as const + ).map(([txt, skey]) => ( + + {txt}: {calc?.compute(self.stat[skey].src('char')).val} + + ))} + + diff --git a/apps/sr-frontend/src/app/CharacterSelector.tsx b/apps/sr-frontend/src/app/CharacterSelector.tsx index a9a47c9f5f..15f49ce678 100644 --- a/apps/sr-frontend/src/app/CharacterSelector.tsx +++ b/apps/sr-frontend/src/app/CharacterSelector.tsx @@ -1,13 +1,12 @@ import { CharacterAutocomplete, - CharacterContext, + useCharacterContext, } from '@genshin-optimizer/sr-ui' import { CardThemed } from '@genshin-optimizer/ui-common' import { CardContent, Container } from '@mui/material' -import { useContext } from 'react' export default function CharacterSelector() { - const { characterKey, setCharacterKey } = useContext(CharacterContext) + const { characterKey, setCharacterKey } = useCharacterContext() return ( diff --git a/apps/sr-frontend/src/app/Database.tsx b/apps/sr-frontend/src/app/Database.tsx index a74d484633..9a6af05539 100644 --- a/apps/sr-frontend/src/app/Database.tsx +++ b/apps/sr-frontend/src/app/Database.tsx @@ -1,6 +1,6 @@ import { SandboxStorage } from '@genshin-optimizer/database' -import { DatabaseContext } from '@genshin-optimizer/sr-ui' import { SroDatabase } from '@genshin-optimizer/sr-db' +import { useDatabaseContext } from '@genshin-optimizer/sr-ui' import { CardThemed, DropdownButton } from '@genshin-optimizer/ui-common' import { range } from '@genshin-optimizer/util' import { @@ -12,14 +12,10 @@ import { Typography, } from '@mui/material' import type { ChangeEvent } from 'react' -import { useCallback, useContext, useEffect, useMemo, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' export default function Database() { - const { - database: mainDB, - databases, - setDatabase, - } = useContext(DatabaseContext) + const { database: mainDB, databases, setDatabase } = useDatabaseContext() const [index, setIndex] = useState(0) const database = databases[index] const current = database === mainDB diff --git a/libs/sr-ui/src/Character/CharacterAutocomplete.tsx b/libs/sr-ui/src/Character/CharacterAutocomplete.tsx index 6decd7d86b..ea8fbc0fb6 100644 --- a/libs/sr-ui/src/Character/CharacterAutocomplete.tsx +++ b/libs/sr-ui/src/Character/CharacterAutocomplete.tsx @@ -5,8 +5,8 @@ import type { GeneralAutocompleteOption } from '@genshin-optimizer/ui-common' import { GeneralAutocomplete } from '@genshin-optimizer/ui-common' import { objKeyMap } from '@genshin-optimizer/util' import { Skeleton } from '@mui/material' -import { Suspense, useContext, useEffect, useMemo } from 'react' -import { DatabaseContext } from '../Context' +import { Suspense, useEffect, useMemo } from 'react' +import { useDatabaseContext } from '../Context' type CharacterAutocompleteProps = { charKey: CharacterKey | '' @@ -16,7 +16,7 @@ export function CharacterAutocomplete({ charKey, setCharKey, }: CharacterAutocompleteProps) { - const { database } = useContext(DatabaseContext) + const { database } = useDatabaseContext() const [charListDirty, setCharListDirty] = useForceUpdate() useEffect( () => database.chars.followAny(() => setCharListDirty()), diff --git a/libs/sr-ui/src/Context/CharacterContext.tsx b/libs/sr-ui/src/Context/CharacterContext.tsx index 5c829709ca..65889ba0b3 100644 --- a/libs/sr-ui/src/Context/CharacterContext.tsx +++ b/libs/sr-ui/src/Context/CharacterContext.tsx @@ -1,12 +1,16 @@ import type { CharacterKey } from '@genshin-optimizer/sr-consts' import type { ReactNode } from 'react' -import { createContext, useMemo, useState } from 'react' -export type CharacterContextObj = { +import { createContext, useContext, useMemo, useState } from 'react' +type CharacterContextObj = { characterKey: CharacterKey | '' setCharacterKey: (key: CharacterKey | '') => void } -export const CharacterContext = createContext({} as CharacterContextObj) +const CharacterContext = createContext({} as CharacterContextObj) + +export function useCharacterContext() { + return useContext(CharacterContext) +} export function CharacterProvider({ children }: { children: ReactNode }) { const [characterKey, setCharacterKey] = useState('') diff --git a/libs/sr-ui/src/Context/DatabaseContext.tsx b/libs/sr-ui/src/Context/DatabaseContext.tsx index 427a7da573..f490af0d86 100644 --- a/libs/sr-ui/src/Context/DatabaseContext.tsx +++ b/libs/sr-ui/src/Context/DatabaseContext.tsx @@ -1,14 +1,25 @@ import { DBLocalStorage, SandboxStorage } from '@genshin-optimizer/database' import { SroDatabase } from '@genshin-optimizer/sr-db' import type { ReactNode } from 'react' -import { createContext, useCallback, useMemo, useState } from 'react' +import { + createContext, + useCallback, + useContext, + useMemo, + useState, +} from 'react' type DatabaseContextObj = { databases: SroDatabase[] setDatabase: (index: number, db: SroDatabase) => void database: SroDatabase } -export const DatabaseContext = createContext({} as DatabaseContextObj) + +const DatabaseContext = createContext({} as DatabaseContextObj) + +export function useDatabaseContext() { + return useContext(DatabaseContext) +} export function DatabaseProvider({ children }: { children: ReactNode }) { const dbIndex = parseInt(localStorage.getItem('sro_dbIndex') || '1') diff --git a/libs/sr-ui/src/Hook/index.ts b/libs/sr-ui/src/Hook/index.ts index 3aff06f210..a050be2e76 100644 --- a/libs/sr-ui/src/Hook/index.ts +++ b/libs/sr-ui/src/Hook/index.ts @@ -1,2 +1,3 @@ export * from './useCharacter' export * from './useCharacterReducer' +export * from './useLightCone' diff --git a/libs/sr-ui/src/Hook/useCharacter.ts b/libs/sr-ui/src/Hook/useCharacter.ts index c685d703cf..065e046194 100644 --- a/libs/sr-ui/src/Hook/useCharacter.ts +++ b/libs/sr-ui/src/Hook/useCharacter.ts @@ -1,9 +1,9 @@ import type { CharacterKey } from '@genshin-optimizer/sr-consts' -import { useContext, useEffect, useState } from 'react' -import { DatabaseContext } from '../Context' +import { useEffect, useState } from 'react' +import { useDatabaseContext } from '../Context' export function useCharacter(characterKey: CharacterKey | '' | undefined = '') { - const { database } = useContext(DatabaseContext) + const { database } = useDatabaseContext() const [character, setCharacter] = useState(database.chars.get(characterKey)) useEffect( () => setCharacter(database.chars.get(characterKey)), diff --git a/libs/sr-ui/src/Hook/useCharacterReducer.ts b/libs/sr-ui/src/Hook/useCharacterReducer.ts index 2c0a49d0a5..9557a52005 100644 --- a/libs/sr-ui/src/Hook/useCharacterReducer.ts +++ b/libs/sr-ui/src/Hook/useCharacterReducer.ts @@ -1,7 +1,7 @@ import type { CharacterKey } from '@genshin-optimizer/sr-consts' import type { ICachedSroCharacter } from '@genshin-optimizer/sr-db' -import { useCallback, useContext } from 'react' -import { DatabaseContext } from '../Context' +import { useCallback } from 'react' +import { useDatabaseContext } from '../Context' type characterTeamAction = { type: 'team' @@ -13,7 +13,7 @@ export type characterReducerAction = | Partial export function useCharacterReducer(characterKey: CharacterKey | '') { - const { database } = useContext(DatabaseContext) + const { database } = useDatabaseContext() return useCallback( (action: characterReducerAction): void => { diff --git a/libs/sr-ui/src/Hook/useLightCone.ts b/libs/sr-ui/src/Hook/useLightCone.ts new file mode 100644 index 0000000000..e10f4b546b --- /dev/null +++ b/libs/sr-ui/src/Hook/useLightCone.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from 'react' +import { useDatabaseContext } from '../Context' + +export function useLightCone(lightConeId: string | '' | undefined = '') { + const { database } = useDatabaseContext() + const [lightCone, setLightCone] = useState( + database.lightCones.get(lightConeId) + ) + useEffect( + () => setLightCone(database.lightCones.get(lightConeId)), + [database, lightConeId] + ) + useEffect( + () => + lightConeId + ? database.lightCones.follow( + lightConeId, + (_k, r, v) => (r === 'update' || r === 'remove') && setLightCone(v) + ) + : undefined, + [lightConeId, setLightCone, database] + ) + return lightCone +}