From d00ed1f4eebf37849b300b36c7c6aca09accdf5b Mon Sep 17 00:00:00 2001 From: omuretsu <84951833+Snarling@users.noreply.github.com> Date: Mon, 2 Jan 2023 08:54:18 -0500 Subject: [PATCH] sync overview updates Using EventEmitter. Also get rid of ShownContext as it is no longer needed with this event based rerender. --- src/ui/React/CharacterOverview.tsx | 50 +++++++++++++----------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/src/ui/React/CharacterOverview.tsx b/src/ui/React/CharacterOverview.tsx index 07ed99fe9..d631cf28c 100644 --- a/src/ui/React/CharacterOverview.tsx +++ b/src/ui/React/CharacterOverview.tsx @@ -1,5 +1,5 @@ // Root React Component for the Corporation UI -import React, { useMemo, useState, useEffect, createContext, useContext } from "react"; +import React, { useMemo, useState, useEffect } from "react"; import { Theme, useTheme } from "@mui/material/styles"; import makeStyles from "@mui/styles/makeStyles"; @@ -40,10 +40,11 @@ import { ActionIdentifier } from "../../Bladeburner/ActionIdentifier"; import { Bladeburner } from "../../Bladeburner/Bladeburner"; import { Skills } from "../../PersonObjects/Skills"; import { calculateSkillProgress } from "../../PersonObjects/formulas/skill"; +import { EventEmitter } from "../../utils/EventEmitter"; type SkillRowName = "Hack" | "Str" | "Def" | "Dex" | "Agi" | "Cha" | "Int"; type RowName = SkillRowName | "HP" | "Money"; -const ShownContext = createContext(true); //Context for whether to update components +const OverviewEventEmitter = new EventEmitter(); // These values aren't displayed, they're just used for comparison to check if state has changed const valUpdaters: Record any> = { @@ -97,17 +98,15 @@ interface SkillBarProps { color?: string; } function SkillBar({ name, color }: SkillBarProps): React.ReactElement { - const shown = useContext(ShownContext); const [mult, setMult] = useState(skillMultUpdaters[name]?.()); const [progress, setProgress] = useState(calculateSkillProgress(Player.exp[skillNameMap[name]], mult)); useEffect(() => { - if (!shown) return; - const interval = setInterval(() => { + const clearSubscription = OverviewEventEmitter.subscribe(() => { setMult(skillMultUpdaters[name]()); setProgress(calculateSkillProgress(Player.exp[skillNameMap[name] as keyof Skills], mult)); - }, 600); - return () => clearInterval(interval); - }, [shown]); + }); + return clearSubscription; + }, []); return ( @@ -122,12 +121,10 @@ interface ValProps { export function Val({ name, color }: ValProps): React.ReactElement { //val isn't actually used here, the update of val just forces a refresh of the formattedVal that gets shown const setVal = useState(valUpdaters[name]())[1]; - const shown = useContext(ShownContext); useEffect(() => { - if (!shown) return; - const interval = setInterval(() => setVal(valUpdaters[name]()), 600); - return () => clearInterval(interval); - }, [shown]); + const clearSubscription = OverviewEventEmitter.subscribe(() => setVal(valUpdaters[name]())); + return clearSubscription; + }, []); return {formattedVals[name]()}; } @@ -172,17 +169,18 @@ export function CharacterOverview({ parentOpen, save, killScripts }: OverviewPro const [hasIntelligence, setHasIntelligence] = useState(Player.skills.intelligence > 0); const [showBars, setShowBars] = useState(!Settings.DisableOverviewProgressBars); useEffect(() => { + if (!parentOpen) return; // No rerendering if overview is hidden, for performance const interval = setInterval(() => { - //Todo: Consider making these event-based instead of requiring interval polling? setHasIntelligence(Player.skills.intelligence > 0); setShowBars(!Settings.DisableOverviewProgressBars); - }, 1000); + OverviewEventEmitter.emit(); // Tell every other updating component to update as well + }, 600); return () => clearInterval(interval); - }, []); + }, [parentOpen]); const classes = useStyles(); const theme = useTheme(); return ( - + <> @@ -236,7 +234,7 @@ export function CharacterOverview({ parentOpen, save, killScripts }: OverviewPro setKillOpen(false)} killScripts={killScripts} /> - + ); } @@ -251,14 +249,12 @@ function ActionText(props: { action: ActionIdentifier }): React.ReactElement { } function BladeburnerText(): React.ReactElement { - const shown = useContext(ShownContext); const classes = useStyles(); const setRerender = useState(false)[1]; useEffect(() => { - if (!shown) return; - const interval = setInterval(() => setRerender((old) => !old), 600); - return () => clearInterval(interval); - }, [shown]); + const clearSubscription = OverviewEventEmitter.subscribe(() => setRerender((old) => !old)); + return clearSubscription; + }, []); const action = Player.bladeburner?.action; return useMemo( @@ -330,13 +326,11 @@ function WorkInProgressOverview({ tooltip, children, header }: WorkInProgressOve } function Work(): React.ReactElement { - const shown = useContext(ShownContext); const setRerender = useState(false)[1]; useEffect(() => { - if (!shown) return; - const interval = setInterval(() => setRerender((old) => !old), 600); - return () => clearInterval(interval); - }, [shown]); + const clearSubscription = OverviewEventEmitter.subscribe(() => setRerender((old) => !old)); + return clearSubscription; + }, []); if (Player.currentWork === null || Player.focus) return <>;