From 64584401935738cd4c5039d98d288ffe80639bd5 Mon Sep 17 00:00:00 2001 From: Martin Fournier Date: Thu, 23 Dec 2021 09:11:08 -0500 Subject: [PATCH 1/9] Fix #2021: Handle sleeves xp in stats overview --- src/PersonObjects/formulas/skill.ts | 18 +++++++++++++++++- src/ui/React/StatsProgressBar.tsx | 10 ++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/PersonObjects/formulas/skill.ts b/src/PersonObjects/formulas/skill.ts index 2aa52bff4..c320cc526 100644 --- a/src/PersonObjects/formulas/skill.ts +++ b/src/PersonObjects/formulas/skill.ts @@ -17,6 +17,17 @@ export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress { if (nextExperience < 0) nextExperience = 0; const normalize = (value: number): number => ((value - baseExperience) * 100) / (nextExperience - baseExperience); + let progress = (nextExperience - baseExperience !== 0) ? normalize(exp) : 99.99; + + // Clamp progress: When sleeves are working out, the player gets way too much progress + if (progress < 0) progress = 0 + if (progress > 100) progress = 100; + + // Clamp floating point imprecisions + let currentExperience = exp - baseExperience; + let remainingExperience = nextExperience - exp; + if (currentExperience < 0) currentExperience = 0; + if (remainingExperience < 0) remainingExperience = 0; return { currentSkill, @@ -24,7 +35,9 @@ export function calculateSkillProgress(exp: number, mult = 1): ISkillProgress { baseExperience, experience: exp, nextExperience, - progress: (nextExperience - baseExperience !== 0) ? normalize(exp) : 99.99 + currentExperience, + remainingExperience, + progress } } @@ -34,6 +47,8 @@ export interface ISkillProgress { baseExperience: number; experience: number; nextExperience: number; + currentExperience: number; + remainingExperience: number; progress: number; } @@ -41,6 +56,7 @@ export function getEmptySkillProgress(): ISkillProgress { return { currentSkill: 0, nextSkill: 0, baseExperience: 0, experience: 0, nextExperience: 0, + currentExperience: 0, remainingExperience: 0, progress: 0, }; } diff --git a/src/ui/React/StatsProgressBar.tsx b/src/ui/React/StatsProgressBar.tsx index 085d5afca..1e583a7d5 100644 --- a/src/ui/React/StatsProgressBar.tsx +++ b/src/ui/React/StatsProgressBar.tsx @@ -9,6 +9,7 @@ interface IProgressProps { min: number; max: number; current: number; + remaining: number; progress: number; color?: React.CSSProperties["color"]; } @@ -18,14 +19,14 @@ interface IStatsOverviewCellProps { color?: React.CSSProperties["color"]; } -export function StatsProgressBar({ min, max, current, progress, color }: IProgressProps): React.ReactElement { +export function StatsProgressBar({ min, max, current, remaining, progress, color }: IProgressProps): React.ReactElement { const tooltip = ( Progress:  - {numeralWrapper.formatExp(current - min)} / {numeralWrapper.formatExp(max - min)} + {numeralWrapper.formatExp(current)} / {numeralWrapper.formatExp(max - min)}
Remaining:  - {numeralWrapper.formatExp(max - current)} ({progress.toFixed(2)}%) + {numeralWrapper.formatExp(remaining)} ({progress.toFixed(2)}%)
); @@ -58,7 +59,8 @@ export function StatsProgressOverviewCell({ progress: skill, color }: IStatsOver From 2d949c076b0b63a98b58db07f00a3148962ae550 Mon Sep 17 00:00:00 2001 From: theit8514 Date: Thu, 23 Dec 2021 21:29:53 -0500 Subject: [PATCH 2/9] Fix mv overwriting script files --- src/Terminal/commands/mv.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Terminal/commands/mv.ts b/src/Terminal/commands/mv.ts index 449f92cc8..9276f4bdb 100644 --- a/src/Terminal/commands/mv.ts +++ b/src/Terminal/commands/mv.ts @@ -53,7 +53,7 @@ export function mv( // Also, you can't convert between different file types if (isScriptFilename(source)) { const script = srcFile as Script; - if (!isScriptFilename(dest)) { + if (!isScriptFilename(destPath)) { terminal.error(`Source and destination files must have the same type`); return; } @@ -66,7 +66,7 @@ export function mv( if (destFile != null) { // Already exists, will be overwritten, so we'll delete it - const status = server.removeFile(dest); + const status = server.removeFile(destPath); if (!status.res) { terminal.error(`Something went wrong...please contact game dev (probably a bug)`); return; From 072653674e582071e4fb26f52b8b44ff9d478c50 Mon Sep 17 00:00:00 2001 From: Xynrati <84252507+Xynrati@users.noreply.github.com> Date: Fri, 24 Dec 2021 06:11:45 -0800 Subject: [PATCH 3/9] Removing old comment about removed parameter Because "no it don't" --- markdown/bitburner.ns.gethacktime.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/bitburner.ns.gethacktime.md b/markdown/bitburner.ns.gethacktime.md index f0b518f7d..34d6450f3 100644 --- a/markdown/bitburner.ns.gethacktime.md +++ b/markdown/bitburner.ns.gethacktime.md @@ -28,5 +28,5 @@ Returns the amount of time in milliseconds it takes to execute the hack Netscrip RAM cost: 0.05 GB -Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the hack time would be at different hacking levels. +Returns the amount of time in milliseconds it takes to execute the hack Netscript function on the target server. From 26ab62eea6ebb4b1ab27360362d1aa2b9ca86fc0 Mon Sep 17 00:00:00 2001 From: Xynrati <84252507+Xynrati@users.noreply.github.com> Date: Tue, 28 Dec 2021 08:04:50 -0800 Subject: [PATCH 4/9] More comments to be removed --- src/ScriptEditor/NetscriptDefinitions.d.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 4ea848098..9a60765ed 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -5487,8 +5487,6 @@ export interface NS extends Singularity { * The required time is increased by the security level of the target server and decreased by the player's hacking level. * * @param host - Host of target server. - * @param hackLvl - Optional hacking level for the calculation. Defaults to player’s current hacking level. - * @param intLvl - Optional intelligence level for the calculation. Defaults to player’s current intelligence level. (Intelligence is unlocked after obtaining Source-File 5). * @returns Returns the amount of time in milliseconds it takes to execute the hack Netscript function. Returns Infinity if called on a Hacknet Server. */ getHackTime(host: string): number; @@ -5503,8 +5501,6 @@ export interface NS extends Singularity { * The required time is increased by the security level of the target server and decreased by the player's hacking level. * * @param host - Host of target server. - * @param hackLvl - Optional hacking level for the calculation. Defaults to player’s current hacking level. - * @param intLvl - Optional intelligence level for the calculation. Defaults to player’s current intelligence level. (Intelligence is unlocked after obtaining Source-File 5). * @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server. */ getGrowTime(host: string): number; @@ -5519,8 +5515,6 @@ export interface NS extends Singularity { * The required time is increased by the security level of the target server and decreased by the player's hacking level. * * @param host - Host of target server. - * @param hackLvl - Optional hacking level for the calculation. Defaults to player’s current hacking level. - * @param intLvl - Optional intelligence level for the calculation. Defaults to player’s current intelligence level. (Intelligence is unlocked after obtaining Source-File 5). * @returns Returns the amount of time in milliseconds it takes to execute the grow Netscript function. Returns Infinity if called on a Hacknet Server. */ getWeakenTime(host: string): number; From 1b7a0224c50cfc34b02bbfdacf9ca08231cb648a Mon Sep 17 00:00:00 2001 From: dou Date: Wed, 29 Dec 2021 03:06:37 +1100 Subject: [PATCH 5/9] fix joes guns org name and stock name do not match. --- src/StockMarket/data/InitStockMetadata.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/StockMarket/data/InitStockMetadata.ts b/src/StockMarket/data/InitStockMetadata.ts index 8bcef396f..53e5a5852 100644 --- a/src/StockMarket/data/InitStockMetadata.ts +++ b/src/StockMarket/data/InitStockMetadata.ts @@ -779,7 +779,7 @@ export const InitStockMetadata: IConstructorParams[] = [ max: 350, min: 200, }, - name: "Joes Guns", + name: LocationName.Sector12JoesGuns, otlkMag: 1, spreadPerc: { divisor: 10, @@ -790,7 +790,7 @@ export const InitStockMetadata: IConstructorParams[] = [ max: 52e3, min: 15e3, }, - symbol: StockSymbols["Joes Guns"], + symbol: StockSymbols[LocationName.Sector12JoesGuns], }, { From f98968f8b2d2161b9248df51f390e1689873d778 Mon Sep 17 00:00:00 2001 From: Xynrati <84252507+Xynrati@users.noreply.github.com> Date: Tue, 28 Dec 2021 08:07:35 -0800 Subject: [PATCH 6/9] Update bitburner.ns.getgrowtime.md --- markdown/bitburner.ns.getgrowtime.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/bitburner.ns.getgrowtime.md b/markdown/bitburner.ns.getgrowtime.md index b62e13fb4..5637cf820 100644 --- a/markdown/bitburner.ns.getgrowtime.md +++ b/markdown/bitburner.ns.getgrowtime.md @@ -28,5 +28,5 @@ Returns the amount of time in milliseconds it takes to execute the grow Netscrip RAM cost: 0.05 GB -Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the grow time would be at different hacking levels. +Returns the amount of time in milliseconds it takes to execute the grow Netscript function on the target server. From ab5a2a82977fa52dabb381e54ce5d845ce572ee8 Mon Sep 17 00:00:00 2001 From: Xynrati <84252507+Xynrati@users.noreply.github.com> Date: Tue, 28 Dec 2021 08:07:56 -0800 Subject: [PATCH 7/9] Update bitburner.ns.getweakentime.md --- markdown/bitburner.ns.getweakentime.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/markdown/bitburner.ns.getweakentime.md b/markdown/bitburner.ns.getweakentime.md index 8b0d8d911..06b69cb95 100644 --- a/markdown/bitburner.ns.getweakentime.md +++ b/markdown/bitburner.ns.getweakentime.md @@ -28,5 +28,5 @@ Returns the amount of time in milliseconds it takes to execute the grow Netscrip RAM cost: 0.05 GB -Returns the amount of time in milliseconds it takes to execute the weaken() Netscript function on the target server. The function takes in an optional hackLvl parameter that can be specified to see what the weaken time would be at different hacking levels. +Returns the amount of time in milliseconds it takes to execute the weaken() Netscript function on the target server. From aaf1ad4ae584f129fe4d18a0d3eaefdb083a04e8 Mon Sep 17 00:00:00 2001 From: Alexander Morland Date: Tue, 28 Dec 2021 17:27:21 +0100 Subject: [PATCH 8/9] Fixed typo needed to fix docs --- src/ScriptEditor/NetscriptDefinitions.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ScriptEditor/NetscriptDefinitions.d.ts b/src/ScriptEditor/NetscriptDefinitions.d.ts index 1e46e57c8..8e4044915 100644 --- a/src/ScriptEditor/NetscriptDefinitions.d.ts +++ b/src/ScriptEditor/NetscriptDefinitions.d.ts @@ -2890,7 +2890,7 @@ export interface Bladeburner { } /** - * Coding Contact API + * Coding Contract API * @public */ export interface CodingContract { From 0fc95e62150267bcf539c37b8249d3445cfe5500 Mon Sep 17 00:00:00 2001 From: Olivier Gagnon Date: Wed, 29 Dec 2021 02:04:24 -0500 Subject: [PATCH 9/9] text editor improvements --- src/BitNode/BitNode.tsx | 2 +- src/NetscriptFunctions.ts | 8 +- src/Script/RamCalculations.ts | 1 - src/ScriptEditor/ui/ScriptEditorRoot.tsx | 170 +++++++++++------------ 4 files changed, 85 insertions(+), 96 deletions(-) diff --git a/src/BitNode/BitNode.tsx b/src/BitNode/BitNode.tsx index 48e2aa97f..c59a339de 100644 --- a/src/BitNode/BitNode.tsx +++ b/src/BitNode/BitNode.tsx @@ -745,7 +745,7 @@ export function initBitNodeMultipliers(p: IPlayer): void { BitNodeMultipliers.StaneksGiftPowerMultiplier = 0.5; BitNodeMultipliers.StaneksGiftExtraSize = 2; BitNodeMultipliers.GangSoftcap = 0.8; - BitNodeMultipliers.CorporationSoftCap = 0.9; + BitNodeMultipliers.CorporationSoftCap = 0.7; BitNodeMultipliers.WorldDaemonDifficulty = 2; break; case 10: // Digital Carbon diff --git a/src/NetscriptFunctions.ts b/src/NetscriptFunctions.ts index 83a4335ac..b70db75a0 100644 --- a/src/NetscriptFunctions.ts +++ b/src/NetscriptFunctions.ts @@ -64,7 +64,7 @@ import { NetscriptSleeve } from "./NetscriptFunctions/Sleeve"; import { NetscriptExtra } from "./NetscriptFunctions/Extra"; import { NetscriptHacknet } from "./NetscriptFunctions/Hacknet"; import { NetscriptStanek } from "./NetscriptFunctions/Stanek"; -import { NetscriptUserInterface } from './NetscriptFunctions/UserInterface'; +import { NetscriptUserInterface } from "./NetscriptFunctions/UserInterface"; import { NetscriptBladeburner } from "./NetscriptFunctions/Bladeburner"; import { NetscriptCodingContract } from "./NetscriptFunctions/CodingContract"; import { NetscriptCorporation } from "./NetscriptFunctions/Corporation"; @@ -2318,10 +2318,12 @@ export function NetscriptFunctions(workerScript: WorkerScript): NS { ...base, ...extra, }; - function getFunctionNames(obj: NS, prefix: string): string[] { + function getFunctionNames(obj: any, prefix: string): string[] { const functionNames: string[] = []; for (const [key, value] of Object.entries(obj)) { - if (typeof value == "function") { + if (key === "args") { + continue; + } else if (typeof value == "function") { functionNames.push(prefix + key); } else if (typeof value == "object") { functionNames.push(...getFunctionNames(value, key + ".")); diff --git a/src/Script/RamCalculations.ts b/src/Script/RamCalculations.ts index bf0bfe855..05920baf9 100644 --- a/src/Script/RamCalculations.ts +++ b/src/Script/RamCalculations.ts @@ -109,7 +109,6 @@ async function parseOnlyRamCalculate( for (const s of otherScripts) { if (areImportsEquals(s.filename, fn)) { script = s; - console.log(`${s.filename} ${fn}`); break; } } diff --git a/src/ScriptEditor/ui/ScriptEditorRoot.tsx b/src/ScriptEditor/ui/ScriptEditorRoot.tsx index 1d4653dd4..b2cc86304 100644 --- a/src/ScriptEditor/ui/ScriptEditorRoot.tsx +++ b/src/ScriptEditor/ui/ScriptEditorRoot.tsx @@ -93,26 +93,21 @@ class OpenScript { } } +let openScripts: OpenScript[] = []; +let currentScript: OpenScript | null = null; + // Called every time script editor is opened export function Root(props: IProps): React.ReactElement { + const setRerender = useState(false)[1]; + function rerender(): void { + setRerender((o) => !o); + } const editorRef = useRef(null); const monacoRef = useRef(null); const vimStatusRef = useRef(null); const [vimEditor, setVimEditor] = useState(null); const [editor, setEditor] = useState(null); - const [openScripts, setOpenScripts] = useState( - window.localStorage.getItem("scriptEditorOpenScripts") !== null - ? JSON.parse(window.localStorage.getItem("scriptEditorOpenScripts")!) - : [], - ); - - const [currentScript, setCurrentScript] = useState( - window.localStorage.getItem("scriptEditorCurrentScript") !== null - ? JSON.parse(window.localStorage.getItem("scriptEditorCurrentScript")!) - : null, - ); - const [ram, setRAM] = useState("RAM: ???"); const [updatingRam, setUpdatingRam] = useState(false); const [decorations, setDecorations] = useState([]); @@ -144,26 +139,6 @@ export function Root(props: IProps): React.ReactElement { }; }, []); - useEffect(() => { - // Save currentScript - window.localStorage.setItem( - "scriptEditorCurrentScript", - JSON.stringify(currentScript, (key, value) => { - if (key == "model") return undefined; - return value; - }), - ); - - // Save openScripts - window.localStorage.setItem( - "scriptEditorOpenScripts", - JSON.stringify(openScripts, (key, value) => { - if (key == "model") return undefined; - return value; - }), - ); - }, [currentScript, openScripts]); - useEffect(() => { if (currentScript !== null) { updateRAM(currentScript.code); @@ -171,23 +146,23 @@ export function Root(props: IProps): React.ReactElement { }, []); useEffect(() => { - function maybeSave(event: KeyboardEvent): void { + function keydown(event: KeyboardEvent): void { if (Settings.DisableHotkeys) return; //Ctrl + b - if (event.keyCode == 66 && (event.ctrlKey || event.metaKey)) { + if (event.code == "KeyB" && (event.ctrlKey || event.metaKey)) { event.preventDefault(); - save(); + props.router.toTerminal(); } // CTRL/CMD + S - if (event.code == `KeyS` && (event.ctrlKey || event.metaKey)) { + if (event.code == "KeyS" && (event.ctrlKey || event.metaKey)) { event.preventDefault(); event.stopPropagation(); save(); } } - document.addEventListener("keydown", maybeSave); - return () => document.removeEventListener("keydown", maybeSave); + document.addEventListener("keydown", keydown); + return () => document.removeEventListener("keydown", keydown); }); useEffect(() => { @@ -362,7 +337,7 @@ export function Root(props: IProps): React.ReactElement { regenerateModel(openScript); } - setCurrentScript(openScript); + currentScript = openScript; editorRef.current.setModel(openScript.model); editorRef.current.setPosition(openScript.lastPosition); editorRef.current.revealLineInCenter(openScript.lastPosition.lineNumber); @@ -376,14 +351,12 @@ export function Root(props: IProps): React.ReactElement { new monacoRef.current.Position(0, 0), monacoRef.current.editor.createModel(code, filename.endsWith(".txt") ? "plaintext" : "javascript"), ); - setOpenScripts((oldArray) => [...oldArray, newScript]); - setCurrentScript({ ...newScript }); + openScripts.push(newScript); + currentScript = { ...newScript }; editorRef.current.setModel(newScript.model); updateRAM(newScript.code); } } - } else { - console.log("here we need to load something if we can"); } editorRef.current.focus(); @@ -422,24 +395,26 @@ export function Root(props: IProps): React.ReactElement { function updateCode(newCode?: string): void { if (newCode === undefined) return; updateRAM(newCode); - if (editorRef.current !== null) { - const newPos = editorRef.current.getPosition(); - if (newPos === null) return; - setCurrentScript((oldScript) => ({ ...oldScript!, code: newCode, lastPosition: newPos! })); - if (currentScript !== null) { - const curIndex = openScripts.findIndex( - (script) => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname, - ); - const newArr = [...openScripts]; - const tempScript = currentScript; - tempScript.code = newCode; - newArr[curIndex] = tempScript; - setOpenScripts([...newArr]); - } - try { - infLoop(newCode); - } catch (err) {} + if (editorRef.current === null) return; + const newPos = editorRef.current.getPosition(); + if (newPos === null) return; + if (currentScript !== null) { + currentScript = { ...currentScript, code: newCode, lastPosition: newPos }; + const curIndex = openScripts.findIndex( + (script) => + currentScript !== null && + script.fileName === currentScript.fileName && + script.hostname === currentScript.hostname, + ); + const newArr = [...openScripts]; + const tempScript = currentScript; + tempScript.code = newCode; + newArr[curIndex] = tempScript; + openScripts = [...newArr]; } + try { + infLoop(newCode); + } catch (err) {} } function saveScript(scriptToSave: OpenScript): void { @@ -487,7 +462,7 @@ export function Root(props: IProps): React.ReactElement { function save(): void { if (currentScript === null) { - console.log("currentScript is null when it shouldn't be. Unabel to save script"); + console.error("currentScript is null when it shouldn't be. Unable to save script"); return; } // this is duplicate code with saving later. @@ -507,7 +482,6 @@ export function Root(props: IProps): React.ReactElement { iTutorialNextStep(); - props.router.toTerminal(); return; } @@ -536,7 +510,6 @@ export function Root(props: IProps): React.ReactElement { server.scripts, ); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); return; } } @@ -550,7 +523,6 @@ export function Root(props: IProps): React.ReactElement { if (server.textFiles[i].fn === currentScript.fileName) { server.textFiles[i].write(currentScript.code); if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); return; } } @@ -562,7 +534,6 @@ export function Root(props: IProps): React.ReactElement { } if (Settings.SaveGameOnFileSave) saveObject.saveGame(); - props.router.toTerminal(); } function reorder(list: Array, startIndex: number, endIndex: number): OpenScript[] { @@ -582,19 +553,22 @@ export function Root(props: IProps): React.ReactElement { const items = reorder(openScripts, result.source.index, result.destination.index); - setOpenScripts(items); + openScripts = items; } function onTabClick(index: number): void { if (currentScript !== null) { // Save currentScript to openScripts const curIndex = openScripts.findIndex( - (script) => script.fileName === currentScript.fileName && script.hostname === currentScript.hostname, + (script) => + currentScript !== null && + script.fileName === currentScript.fileName && + script.hostname === currentScript.hostname, ); openScripts[curIndex] = currentScript; } - setCurrentScript({ ...openScripts[index] }); + currentScript = { ...openScripts[index] }; if (editorRef.current !== null && openScripts[index] !== null) { if (openScripts[index].model === undefined || openScripts[index].model.isDisposed()) { @@ -609,25 +583,21 @@ export function Root(props: IProps): React.ReactElement { } } - async function onTabClose(index: number): Promise { + function onTabClose(index: number): void { // See if the script on the server is up to date const closingScript = openScripts[index]; - const savedOpenScripts: Array = JSON.parse(window.localStorage.getItem("scriptEditorOpenScripts")!); - const savedScriptIndex = savedOpenScripts.findIndex( + const savedScriptIndex = openScripts.findIndex( (script) => script.fileName === closingScript.fileName && script.hostname === closingScript.hostname, ); let savedScriptCode = ""; if (savedScriptIndex !== -1) { - savedScriptCode = savedOpenScripts[savedScriptIndex].code; + savedScriptCode = openScripts[savedScriptIndex].code; } + const server = GetServer(closingScript.hostname); + if (server === null) throw new Error(`Server '${closingScript.hostname}' should not be null, but it is.`); - const serverScriptIndex = GetServer(closingScript.hostname)?.scripts.findIndex( - (script) => script.filename === closingScript.fileName, - ); - if ( - serverScriptIndex === -1 || - savedScriptCode !== GetServer(closingScript.hostname)?.scripts[serverScriptIndex as number].code - ) { + const serverScriptIndex = server.scripts.findIndex((script) => script.filename === closingScript.fileName); + if (serverScriptIndex === -1 || savedScriptCode !== server.scripts[serverScriptIndex as number].code) { PromptEvent.emit({ txt: "Do you want to save changes to " + closingScript.fileName + "?", resolve: (result: boolean) => { @@ -641,15 +611,18 @@ export function Root(props: IProps): React.ReactElement { } if (openScripts.length > 1) { - setOpenScripts((oldScripts) => oldScripts.filter((value, i) => i !== index)); + openScripts = openScripts.filter((value, i) => i !== index); let indexOffset = -1; if (openScripts[index + indexOffset] === undefined) { indexOffset = 1; + if (openScripts[index + indexOffset] === undefined) { + indexOffset = 0; + } } // Change current script if we closed it - setCurrentScript(openScripts[index + indexOffset]); + currentScript = openScripts[index + indexOffset]; if (editorRef.current !== null) { if ( openScripts[index + indexOffset].model === undefined || @@ -664,14 +637,26 @@ export function Root(props: IProps): React.ReactElement { editorRef.current.revealLineInCenter(openScripts[index + indexOffset].lastPosition.lineNumber); editorRef.current.focus(); } + rerender(); } else { // No more scripts are open - setOpenScripts([]); - setCurrentScript(null); + openScripts = []; + currentScript = null; props.router.toTerminal(); } } + function dirty(index: number): string { + const openScript = openScripts[index]; + const server = GetServer(openScript.hostname); + if (server === null) throw new Error(`Server '${openScript.hostname}' should not be null, but it is.`); + + const serverScript = server.scripts.find((s) => s.filename === openScript.fileName); + if (serverScript === undefined) return " *"; + + return serverScript.code !== openScript.code ? " *" : ""; + } + // Toolbars are roughly 112px: // 8px body margin top // 38.5px filename tabs @@ -718,7 +703,6 @@ export function Root(props: IProps): React.ReactElement { }} > + + {" "} Documentation:{" "} @@ -825,10 +809,14 @@ export function Root(props: IProps): React.ReactElement { alignItems: "center", }} > -

-

No open files

-
Use "nano [File Name]" in the terminal to open files
-

+ + No open files + + Use `nano FILENAME` in +
+ the terminal to open files +
+
);