From fa1715523eba8fccbb0a3ed957846561915a6672 Mon Sep 17 00:00:00 2001 From: Roland Date: Thu, 30 Jul 2026 13:13:39 -0600 Subject: [PATCH] ui: migrate Flasher.js off Semantic UI React Replace semantic-ui-react/Theme.js imports with the token-driven ui/ library: Tab -> Tabs, Segment -> Panel, Message/Label/Progress/Loader -> their ui equivalents, Table.* compound API, Confirm-free flows preserved exactly. Remove obsolete ThemeContext i/s/t spreads. Drop Flasher.js from semantic-baseline.json now that it no longer imports Semantic UI. Co-Authored-By: Claude Opus 5 (1M context) --- app/src/components/Flasher.js | 816 +++++++++++++++-------------- app/src/components/Flasher.test.js | 2 +- app/src/semantic-baseline.json | 1 - 3 files changed, 415 insertions(+), 404 deletions(-) diff --git a/app/src/components/Flasher.js b/app/src/components/Flasher.js index 17ba230c..fe125a69 100644 --- a/app/src/components/Flasher.js +++ b/app/src/components/Flasher.js @@ -1,27 +1,30 @@ -import React, {useContext, useEffect, useLayoutEffect, useRef, useState} from 'react'; +import React, {useEffect, useLayoutEffect, useRef, useState} from 'react'; import {Route, Routes} from "react-router"; -import {Checkbox, Label, Message, Select, Button as SButton, Icon as SIcon} from "semantic-ui-react"; import {ESPLoader, Transport} from "esptool-js"; import {useDropzone} from "react-dropzone"; import _ from "lodash"; import {encodeMediaPath, humanFileSize, PageContainer, useTitle} from "./Common"; import { Button, - darkTheme, + Checkbox, Divider, - Form, + Group, Header, Icon, - List, - Loader, + IconButton, + Label, + Loading, + Message, Modal, + Panel, Progress, - Segment, - Tab, + Select, + Stack, Table, - TextArea -} from "./Theme"; -import {ThemeContext} from "../contexts/contexts"; + Tabs, + Textarea, + TextInput, +} from "./ui"; import {deleteFlasherConfig, flasherSearch, getFlasherConfigs, saveFlasherConfig} from "../api"; // The suffix used to find flashable ESP32 firmware in the media directory. @@ -50,6 +53,10 @@ const KNOWN_ESP_CHIPS = [ // colors when they render at the same width. The first eight cover today's largest same-width group (the eight // 8-character ESP32-* names); the extras let a same-width group grow past eight before colors would repeat. // (Truly colorblind-distinct qualitative colors top out around ten, so beyond that distinctness is best-effort.) +// +// These are deliberately NOT theme tokens: this is a fixed categorical palette used to visually tell many ESP +// chip families apart, the same way a chart's series colors stay fixed regardless of theme. See the report to +// the user for the resulting night-mode tension (non-red hues on these chips, unlike the rest of the UI). const CHIP_COLORS = [ '#4477aa', '#ee6677', '#228833', '#ccbb44', '#66ccee', '#aa3377', '#bbbbbb', '#000000', '#ee7733', '#332288', '#999933', '#882255', @@ -115,10 +122,10 @@ export function espImageChipId(header) { // bundled into the frontend build, so this works fully offline once the page has loaded. const BAUD_OPTIONS = [ - {key: '115200', value: 115200, text: '115200 (safe)'}, - {key: '230400', value: 230400, text: '230400'}, - {key: '460800', value: 460800, text: '460800'}, - {key: '921600', value: 921600, text: '921600 (fast)'}, + {value: 115200, text: '115200 (safe)'}, + {value: 230400, text: '230400'}, + {value: 460800, text: '460800'}, + {value: 921600, text: '921600 (fast)'}, ]; // Web Serial is only available in a secure context (HTTPS or localhost) on Chromium-based browsers. @@ -218,10 +225,10 @@ export function withTimeout(promise, ms, message) { // How long to wait for a device to connect before giving up (esptool-js retries can otherwise stall the UI). const CONNECT_TIMEOUT_MS = 30_000; -// A read-only log TextArea that auto-scrolls to the newest output — but only when the user is already at the +// A read-only log Textarea that auto-scrolls to the newest output — but only when the user is already at the // bottom, so scrolling up to read earlier lines isn't yanked back down. Starts at the bottom on mount (e.g. when // a modal opens). -function AutoScrollLog({value, ...props}) { +function AutoScrollLog({value, style, ...props}) { const containerRef = useRef(null); const atBottomRef = useRef(true); @@ -241,13 +248,18 @@ function AutoScrollLog({value, ...props}) { }, [value]); return
-