From 521fb8f613a4641d3171d20063c0868a37efb8a9 Mon Sep 17 00:00:00 2001 From: Jaime Idolpx Date: Wed, 10 Jun 2026 20:13:03 -0400 Subject: [PATCH] fix(GeneralPage): update section title from "General Settings" to "Preferences" for clarity --- src/app/components/GeneralPage.tsx | 2 +- src/app/components/SerialConsolePage.tsx | 110 ++++------------------- webdav3.py | 2 +- 3 files changed, 21 insertions(+), 93 deletions(-) diff --git a/src/app/components/GeneralPage.tsx b/src/app/components/GeneralPage.tsx index 6a8f87b..1507814 100644 --- a/src/app/components/GeneralPage.tsx +++ b/src/app/components/GeneralPage.tsx @@ -42,7 +42,7 @@ export default function GeneralPage({ config, setConfig }: GeneralPageProps) { return (
-

General Settings

+

Preferences

diff --git a/src/app/components/SerialConsolePage.tsx b/src/app/components/SerialConsolePage.tsx index 8658f0d..3d58d81 100644 --- a/src/app/components/SerialConsolePage.tsx +++ b/src/app/components/SerialConsolePage.tsx @@ -1,21 +1,23 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; import { Terminal } from '@xterm/xterm'; import { FitAddon } from '@xterm/addon-fit'; import '@xterm/xterm/css/xterm.css'; -import { ChevronLeft, Plug, Radio, RotateCcw, Unplug } from 'lucide-react'; +import { ChevronLeft, Radio, RotateCcw } from 'lucide-react'; +import { useWs } from '../ws'; interface Props { onBack: () => void; } -type ConnStatus = 'disconnected' | 'connecting' | 'connected' | 'error'; - export default function SerialConsolePage({ onBack }: Props) { const containerRef = useRef(null); const termRef = useRef(null); const fitRef = useRef(null); - const wsRef = useRef(null); - const [status, setStatus] = useState('disconnected'); + const { status, send, subscribe } = useWs(); - // Initialize xterm on mount + // Keep a stable ref to `send` so the xterm onData closure never goes stale + const sendRef = useRef(send); + useEffect(() => { sendRef.current = send; }, [send]); + + // Initialize xterm once on mount useEffect(() => { const el = containerRef.current; if (!el) return; @@ -42,12 +44,9 @@ export default function SerialConsolePage({ onBack }: Props) { fitRef.current = fit; term.writeln('\x1b[2m── Meatloaf Serial Console ──\x1b[0m'); - term.writeln('\x1b[2mPress Connect to open a session.\x1b[0m'); term.writeln(''); - term.onData((data) => { - if (wsRef.current?.readyState === WebSocket.OPEN) wsRef.current.send(data); - }); + term.onData((data) => sendRef.current(data)); const onResize = () => fitRef.current?.fit(); window.addEventListener('resize', onResize); @@ -60,79 +59,20 @@ export default function SerialConsolePage({ onBack }: Props) { }; }, []); - // Close WebSocket on unmount + // Forward all incoming WS messages to the terminal useEffect(() => { - return () => { - if (wsRef.current) { - wsRef.current.onopen = wsRef.current.onmessage = wsRef.current.onerror = wsRef.current.onclose = null; - wsRef.current.close(); - wsRef.current = null; - } - }; - }, []); - - const writeln = (msg: string) => termRef.current?.writeln(msg); - - const connect = () => { - if (wsRef.current) { - wsRef.current.onopen = wsRef.current.onmessage = wsRef.current.onerror = wsRef.current.onclose = null; - wsRef.current.close(); - wsRef.current = null; - } - - const url = `ws://${window.location.hostname}/console`; - setStatus('connecting'); - writeln(`\x1b[2mConnecting to ${url}…\x1b[0m`); - - const ws = new WebSocket(url); - ws.binaryType = 'arraybuffer'; - wsRef.current = ws; - - ws.onopen = () => { - setStatus('connected'); - writeln('\x1b[32mConnected.\x1b[0m'); - }; - - ws.onmessage = (ev) => { - if (!termRef.current) return; - if (ev.data instanceof ArrayBuffer) termRef.current.write(new Uint8Array(ev.data)); - else termRef.current.write(String(ev.data)); - }; - - let hadError = false; - ws.onerror = () => { - hadError = true; - writeln('\x1b[31mConnection error.\x1b[0m'); - }; - - ws.onclose = (ev) => { - setStatus(hadError ? 'error' : 'disconnected'); - wsRef.current = null; - if (!hadError) writeln(`\x1b[2mSession ended${ev.reason ? `: ${ev.reason}` : ''}.\x1b[0m`); - }; - }; - - const disconnect = () => { - if (wsRef.current) { - wsRef.current.onopen = wsRef.current.onmessage = wsRef.current.onerror = wsRef.current.onclose = null; - wsRef.current.close(); - wsRef.current = null; - } - setStatus('disconnected'); - writeln('\x1b[2mDisconnected.\x1b[0m'); - }; - - const busy = status === 'connecting' || status === 'connected'; + return subscribe((msg) => { + termRef.current?.write(msg); + }); + }, [subscribe]); const statusColor = - status === 'connected' ? 'text-green-400' : - status === 'connecting' ? 'text-amber-400' : - status === 'error' ? 'text-red-400' : 'text-neutral-500'; + status === 'connected' ? 'text-green-400' : + status === 'connecting' ? 'text-amber-400' : 'text-neutral-500'; const statusLabel = status === 'connected' ? 'Connected' : - status === 'connecting' ? 'Connecting…' : - status === 'error' ? 'Error' : 'Disconnected'; + status === 'connecting' ? 'Connecting…' : 'Disconnected'; return (
@@ -143,7 +83,7 @@ export default function SerialConsolePage({ onBack }: Props) { style={{ paddingTop: 'max(0.5rem, env(safe-area-inset-top))' }} > - -
{/* Terminal */} diff --git a/webdav3.py b/webdav3.py index 65af666..46f033c 100644 --- a/webdav3.py +++ b/webdav3.py @@ -941,7 +941,7 @@ class DAVServer(ThreadingMixIn, HTTPServer): pass if __name__ == '__main__': - # WebDav TCP Port + # WebDav TCP Port srvport = 80 # Get local IP address myaddr = get_localip()