From ef58287c1631d8796c4838425a4d3938d00ef656 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Tue, 18 Jul 2023 08:08:24 +0200 Subject: [PATCH] playground: Merge `Editor` state variables (#5831) ## Summary This PR removes state variables that can be derived, merges related variables into a single state, and generally avoids `null` states. ## Test Plan I clicked through the playground locally --- playground/README.md | 2 +- playground/package.json | 1 + playground/src/Editor/Editor.tsx | 154 ++++++++++++++++--------------- 3 files changed, 83 insertions(+), 74 deletions(-) diff --git a/playground/README.md b/playground/README.md index 7b13420928..83d302fa8a 100644 --- a/playground/README.md +++ b/playground/README.md @@ -4,7 +4,7 @@ In-browser playground for Ruff. Available [https://play.ruff.rs/](https://play.r ## Getting started -- To build the WASM module, run `wasm-pack build ../crates/ruff_wasm --target web --out-dir ../../playground/src/pkg` +- To build the WASM module, run `npm run build:wasm` from the `./playground` directory. - Install TypeScript dependencies with: `npm install`. - Start the development server with: `npm run dev`. diff --git a/playground/package.json b/playground/package.json index 49692a375f..9361fb72a2 100644 --- a/playground/package.json +++ b/playground/package.json @@ -4,6 +4,7 @@ "version": "0.0.0", "type": "module", "scripts": { + "build:wasm": "wasm-pack build ../crates/ruff_wasm --target web --out-dir ../../playground/src/pkg", "build": "tsc && vite build", "check": "npm run lint && npm run tsc", "dev": "vite", diff --git a/playground/src/Editor/Editor.tsx b/playground/src/Editor/Editor.tsx index bdfdac648b..01436db4d6 100644 --- a/playground/src/Editor/Editor.tsx +++ b/playground/src/Editor/Editor.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useMemo, useState } from "react"; import { DEFAULT_PYTHON_SOURCE } from "../constants"; import init, { check, @@ -16,90 +16,98 @@ import MonacoThemes from "./MonacoThemes"; type Tab = "Source" | "Settings"; +interface Source { + pythonSource: string; + settingsSource: string; + revision: number; +} + +interface CheckResult { + diagnostics: Diagnostic[]; + error: string | null; +} + export default function Editor() { - const [initialized, setInitialized] = useState(false); - const [version, setVersion] = useState(null); + const [ruffVersion, setRuffVersion] = useState(null); + const [checkResult, setCheckResult] = useState({ + diagnostics: [], + error: null, + }); + const [source, setSource] = useState({ + pythonSource: "", + settingsSource: "", + revision: 0, + }); + const [tab, setTab] = useState("Source"); - const [edit, setEdit] = useState(0); - const [settingsSource, setSettingsSource] = useState(null); - const [pythonSource, setPythonSource] = useState(null); - const [diagnostics, setDiagnostics] = useState([]); - const [error, setError] = useState(null); const [theme, setTheme] = useTheme(); + const initialized = ruffVersion != null; + useEffect(() => { - init().then(() => setInitialized(true)); + init().then(() => { + setRuffVersion(currentVersion()); + + const [settingsSource, pythonSource] = restore() ?? [ + stringify(defaultSettings()), + DEFAULT_PYTHON_SOURCE, + ]; + + setSource({ + pythonSource, + revision: 0, + settingsSource, + }); + }); }, []); - useEffect(() => { - if (!initialized || settingsSource == null || pythonSource == null) { - return; - } - - let config: any; - let diagnostics: Diagnostic[]; - - try { - config = JSON.parse(settingsSource); - } catch (e) { - setDiagnostics([]); - setError((e as Error).message); - return; - } - - try { - diagnostics = check(pythonSource, config); - } catch (e) { - setError(e as string); - return; - } - - setError(null); - setDiagnostics(diagnostics); - }, [initialized, settingsSource, pythonSource]); - useEffect(() => { if (!initialized) { return; } - if (settingsSource == null || pythonSource == null) { - const payload = restore(); - if (payload) { - const [settingsSource, pythonSource] = payload; - setSettingsSource(settingsSource); - setPythonSource(pythonSource); - } else { - setSettingsSource(stringify(defaultSettings())); - setPythonSource(DEFAULT_PYTHON_SOURCE); - } - } - }, [initialized, settingsSource, pythonSource]); + const { settingsSource, pythonSource } = source; - useEffect(() => { + try { + const config = JSON.parse(settingsSource); + const diagnostics = check(pythonSource, config); + + setCheckResult({ + diagnostics, + error: null, + }); + } catch (e) { + setCheckResult({ + diagnostics: [], + error: (e as Error).message, + }); + } + }, [initialized, source]); + + const handleShare = useMemo(() => { if (!initialized) { - return; + return undefined; } - setVersion(currentVersion()); - }, [initialized]); - - const handleShare = useCallback(() => { - if (!initialized || settingsSource == null || pythonSource == null) { - return; - } - - persist(settingsSource, pythonSource); - }, [initialized, settingsSource, pythonSource]); + return () => { + persist(source.settingsSource, source.pythonSource); + }; + }, [source, initialized]); const handlePythonSourceChange = useCallback((pythonSource: string) => { - setEdit((edit) => edit + 1); - setPythonSource(pythonSource); + setSource((state) => ({ + ...state, + pythonSource, + revision: state.revision + 1, + })); }, []); const handleSettingsSourceChange = useCallback((settingsSource: string) => { - setEdit((edit) => edit + 1); - setSettingsSource(settingsSource); + setSource((state) => ({ + ...state, + settingsSource, + revision: state.revision + 1, + })); }, []); return ( @@ -109,37 +117,37 @@ export default function Editor() { } >
- {initialized && settingsSource != null && pythonSource != null ? ( + {initialized ? ( <> ) : null}
- {error && tab === "Source" ? ( + {checkResult.error && tab === "Source" ? (
- {error} + {checkResult.error}
) : null}