From 8b69f8c93c5302dd86c4a37d5438f4873fbe1f32 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Wed, 30 Apr 2025 13:07:40 +0200 Subject: [PATCH] Small refactoring --- cmake/misc/node-pre-script.js | 6 +- page/src/App.tsx | 4 +- page/src/Playground.tsx | 318 ++++++++++-------- page/src/components/settings-menu.tsx | 6 +- ...emExplorer.tsx => filesystem-explorer.tsx} | 22 +- .../src/{LandingPage.tsx => landing-page.tsx} | 0 6 files changed, 207 insertions(+), 149 deletions(-) rename page/src/{FilesystemExplorer.tsx => filesystem-explorer.tsx} (97%) rename page/src/{LandingPage.tsx => landing-page.tsx} (100%) diff --git a/cmake/misc/node-pre-script.js b/cmake/misc/node-pre-script.js index ee8eb4ee..de622d94 100644 --- a/cmake/misc/node-pre-script.js +++ b/cmake/misc/node-pre-script.js @@ -1,3 +1,3 @@ -Module['preRun'] = () => { - ENV = process.env; -}; +Module["preRun"] = () => { + ENV = process.env; +}; diff --git a/page/src/App.tsx b/page/src/App.tsx index e71e2107..ce332ae1 100644 --- a/page/src/App.tsx +++ b/page/src/App.tsx @@ -1,8 +1,8 @@ import { ThemeProvider } from "@/components/theme-provider"; import { TooltipProvider } from "@/components/ui/tooltip"; import { HashRouter, Route, Routes, Navigate } from "react-router-dom"; -import { Playground } from "./Playground"; -import { LandingPage } from "./LandingPage"; +import { Playground } from "./playground"; +import { LandingPage } from "./landing-page"; import "@fontsource/inter/100.css"; import "@fontsource/inter/200.css"; diff --git a/page/src/Playground.tsx b/page/src/Playground.tsx index 92df9544..80f5320e 100644 --- a/page/src/Playground.tsx +++ b/page/src/Playground.tsx @@ -1,7 +1,6 @@ -import { useState, useRef, useReducer } from "react"; -import { Output } from "@/components/output"; +import React from "react"; -import { Separator } from "@/components/ui/separator"; +import { Output } from "@/components/output"; import { Emulator, EmulationState } from "./emulator"; import { Filesystem, setupFilesystem } from "./filesystem"; @@ -13,7 +12,7 @@ import { PopoverTrigger, } from "@/components/ui/popover"; -import { createDefaultSettings } from "./settings"; +import { createDefaultSettings, Settings } from "./settings"; import { SettingsMenu } from "@/components/settings-menu"; import { PlayFill, StopFill, GearFill, PauseFill } from "react-bootstrap-icons"; @@ -30,176 +29,229 @@ import { DrawerHeader, DrawerTitle, } from "@/components/ui/drawer"; -import { FilesystemExplorer } from "./FilesystemExplorer"; +import { FilesystemExplorer } from "./filesystem-explorer"; -export function Playground() { - const output = useRef(null); - const [settings, setSettings] = useState(createDefaultSettings()); - const [emulator, setEmulator] = useState(null); - const [drawerOpen, setDrawerOpen] = useState(false); - const [filesystem, setFilesystem] = useState(null); - const [filesystemPromise, setFilesystemPromise] = - useState | null>(null); - const [, forceUpdate] = useReducer((x) => x + 1, 0); +interface PlaygroundProps {} +interface PlaygroundState { + settings: Settings; + filesystemPromise: Promise | null; + filesystem: Filesystem | null; + emulator: Emulator | null; + drawerOpen: boolean; +} - async function resetFilesys() { - const fs = await initFilesys(); - await fs.delete(); +export class Playground extends React.Component< + PlaygroundProps, + PlaygroundState +> { + private output: React.RefObject; - setFilesystemPromise(null); - setFilesystem(null); - setDrawerOpen(false); + constructor(props: PlaygroundProps) { + super(props); - output.current?.clear(); + this.output = React.createRef(); + + this.start = this.start.bind(this); + this.resetFilesys = this.resetFilesys.bind(this); + this.createEmulator = this.createEmulator.bind(this); + this.toggleEmulatorState = this.toggleEmulatorState.bind(this); + + this.state = { + settings: createDefaultSettings(), + filesystemPromise: null, + filesystem: null, + emulator: null, + drawerOpen: false, + }; } - function initFilesys() { - if (filesystemPromise) { - return filesystemPromise; + async resetFilesys() { + if (!this.state.filesystem) { + return; + } + + await this.state.filesystem.delete(); + + this.setState({ + filesystemPromise: null, + filesystem: null, + drawerOpen: false, + }); + + this.output.current?.clear(); + } + + initFilesys() { + if (this.state.filesystemPromise) { + return this.state.filesystemPromise; } const promise = new Promise((resolve) => { - logLine("Loading filesystem..."); + this.logLine("Loading filesystem..."); setupFilesystem((current, total, file) => { - logLine(`Processing filesystem (${current}/${total}): ${file}`); + this.logLine(`Processing filesystem (${current}/${total}): ${file}`); }).then(resolve); }); - promise.then(setFilesystem); - setFilesystemPromise(promise); + promise.then((filesystem) => this.setState({ filesystem })); + this.setState({ filesystemPromise: promise }); return promise; } - async function start() { - await initFilesys(); - setDrawerOpen(true); + setDrawerOpen(drawerOpen: boolean) { + this.setState({ drawerOpen }); } - function logLine(line: string) { - output.current?.logLine(line); + async start() { + await this.initFilesys(); + this.setDrawerOpen(true); } - function logLines(lines: string[]) { - output.current?.logLines(lines); + logLine(line: string) { + this.output.current?.logLine(line); } - function isEmulatorPaused() { - return emulator && emulator.getState() == EmulationState.Paused; + logLines(lines: string[]) { + this.output.current?.logLines(lines); } - function toggleEmulatorState() { - if (isEmulatorPaused()) { - emulator?.resume(); + isEmulatorPaused() { + return ( + this.state.emulator && + this.state.emulator.getState() == EmulationState.Paused + ); + } + + toggleEmulatorState() { + if (this.isEmulatorPaused()) { + this.state.emulator?.resume(); } else { - emulator?.pause(); + this.state.emulator?.pause(); } } - async function createEmulator(userFile: string) { - emulator?.stop(); - output.current?.clear(); + async createEmulator(userFile: string) { + this.state.emulator?.stop(); + this.output.current?.clear(); - setDrawerOpen(false); + this.setDrawerOpen(false); - logLine("Starting emulation..."); + this.logLine("Starting emulation..."); - if (filesystemPromise) { - await filesystemPromise; + if (this.state.filesystemPromise) { + await this.state.filesystemPromise; } - const new_emulator = new Emulator(logLines, (_) => forceUpdate()); - new_emulator.onTerminate().then(() => setEmulator(null)); - setEmulator(new_emulator); + const new_emulator = new Emulator( + (l) => this.logLines(l), + (_) => this.forceUpdate(), + ); + new_emulator.onTerminate().then(() => this.setState({ emulator: null })); - new_emulator.start(settings, userFile); + this.setState({ emulator: new_emulator }); + + new_emulator.start(this.state.settings, userFile); } - return ( - <> -
-
-
- + render() { + return ( + <> +
+
+
+ - - + + + + + + + + this.setState({ settings: s })} + /> + + + + {!this.state.filesystem ? ( + <> ) : ( - <> - Pause - + this.setState({ drawerOpen: o })} + > + + + + Filesystem Explorer + + + Filesystem Explorer + + + + + + + )} - - - - - - - - - - - {!filesystem ? ( - <> - ) : ( - - - - - Filesystem Explorer - - - Filesystem Explorer - - - - - - - - )} - -
- +
+ +
+
+
+
-
-
-
-
- - ); + + ); + } } diff --git a/page/src/components/settings-menu.tsx b/page/src/components/settings-menu.tsx index aa80d528..06a0dac4 100644 --- a/page/src/components/settings-menu.tsx +++ b/page/src/components/settings-menu.tsx @@ -24,8 +24,10 @@ export class SettingsMenu extends React.Component { this.setState(() => settings); } - componentDidUpdate() { - this.props.onChange(this.state); + componentDidUpdate(_: SettingsMenuProps, oldSettings: Settings) { + if (JSON.stringify(oldSettings) !== JSON.stringify(this.state)) { + this.props.onChange(this.state); + } } render() { diff --git a/page/src/FilesystemExplorer.tsx b/page/src/filesystem-explorer.tsx similarity index 97% rename from page/src/FilesystemExplorer.tsx rename to page/src/filesystem-explorer.tsx index 4c8e8a9a..b3d24df9 100644 --- a/page/src/FilesystemExplorer.tsx +++ b/page/src/filesystem-explorer.tsx @@ -485,7 +485,7 @@ export class FilesystemExplorer extends React.Component< _renderBreadcrumbElements() { const elements = generateBreadcrumbElements(this.state.path); - return elements.map((e, index) => { + const nodes = elements.map((e, index) => { if (index == this.state.path.length) { return ( @@ -498,16 +498,20 @@ export class FilesystemExplorer extends React.Component< const navigate = () => this.setState({ path: e.targetPath }); return ( - <> - - - {e.node} - - - - + + + {e.node} + + ); }); + + return [ + ...nodes.map((n, index) => [ + n, + , + ]), + ].slice(0, -1); } _renderBreadCrumb() { diff --git a/page/src/LandingPage.tsx b/page/src/landing-page.tsx similarity index 100% rename from page/src/LandingPage.tsx rename to page/src/landing-page.tsx