From e2d237fe0976b7b066752099ed5a55c37ca60c31 Mon Sep 17 00:00:00 2001 From: Hamzat Victor Date: Wed, 23 Oct 2024 11:55:38 +0100 Subject: [PATCH] feat: add theme to terminal --- backend/server/src/index.ts | 9 +- .../components/editor/terminals/terminal.tsx | 106 ++++++++++++------ frontend/components/ui/tab.tsx | 2 +- 3 files changed, 81 insertions(+), 36 deletions(-) diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts index 293f802..788c329 100644 --- a/backend/server/src/index.ts +++ b/backend/server/src/index.ts @@ -224,10 +224,11 @@ io.on("connection", async (socket) => { containers[data.sandboxId], sendLoadedEvent ) - await fileManagers[data.sandboxId].initialize() terminalManagers[data.sandboxId] = new TerminalManager( containers[data.sandboxId] ) + console.log(`terminal manager set up for ${data.sandboxId}`) + await fileManagers[data.sandboxId].initialize() } const fileManager = fileManagers[data.sandboxId] @@ -415,6 +416,12 @@ io.on("connection", async (socket) => { socket.on("createTerminal", async (id: string, callback) => { try { await lockManager.acquireLock(data.sandboxId, async () => { + let terminalManager = terminalManagers[data.sandboxId] + if (!terminalManager) { + terminalManager = terminalManagers[data.sandboxId] = + new TerminalManager(containers[data.sandboxId]) + } + await terminalManager.createTerminal(id, (responseString: string) => { socket.emit("terminalResponse", { id, data: responseString }) const port = extractPortNumber(responseString) diff --git a/frontend/components/editor/terminals/terminal.tsx b/frontend/components/editor/terminals/terminal.tsx index 47ce47a..4790a44 100644 --- a/frontend/components/editor/terminals/terminal.tsx +++ b/frontend/components/editor/terminals/terminal.tsx @@ -6,9 +6,9 @@ import "./xterm.css" import { debounce } from "@/lib/utils" import { Loader2 } from "lucide-react" +import { useTheme } from "next-themes" import { ElementRef, useEffect, useRef } from "react" import { Socket } from "socket.io-client" - export default function EditorTerminal({ socket, id, @@ -22,38 +22,17 @@ export default function EditorTerminal({ setTerm: (term: Terminal) => void visible: boolean }) { - const terminalRef = useRef>(null) + const { theme } = useTheme() + const terminalContainerRef = useRef>(null) const fitAddonRef = useRef(null) useEffect(() => { - if (!terminalRef.current) return + if (!terminalContainerRef.current) return // console.log("new terminal", id, term ? "reusing" : "creating"); const terminal = new Terminal({ cursorBlink: true, - theme: { - foreground: "#2e3436", - background: "#ffffff", - black: "#2e3436", - brightBlack: "#555753", - red: "#cc0000", - brightRed: "#ef2929", - green: "#4e9a06", - brightGreen: "#8ae234", - yellow: "#c4a000", - brightYellow: "#fce94f", - blue: "#3465a4", - brightBlue: "#729fcf", - magenta: "#75507b", - brightMagenta: "#ad7fa8", - cyan: "#06989a", - brightCyan: "#34e2e2", - white: "#d3d7cf", - brightWhite: "#eeeeec", - cursor: "#2e3436", - cursorAccent: "#ffffff", - selection: "rgba(52, 101, 164, 0.3)", - }, + theme: theme === "light" ? lightTheme : darkTheme, fontFamily: "var(--font-geist-mono)", fontSize: 14, lineHeight: 1.5, @@ -67,14 +46,20 @@ export default function EditorTerminal({ return dispose }, []) + useEffect(() => { + if (term) { + term.options.theme = theme === "light" ? lightTheme : darkTheme + } + }, [theme]) + useEffect(() => { if (!term) return - if (!terminalRef.current) return + if (!terminalContainerRef.current) return if (!fitAddonRef.current) { const fitAddon = new FitAddon() term.loadAddon(fitAddon) - term.open(terminalRef.current) + term.open(terminalContainerRef.current) fitAddon.fit() fitAddonRef.current = fitAddon } @@ -89,7 +74,7 @@ export default function EditorTerminal({ }) const resizeObserver = new ResizeObserver( debounce((entries) => { - if (!fitAddonRef.current || !terminalRef.current) return + if (!fitAddonRef.current || !terminalContainerRef.current) return const entry = entries[0] if (!entry) return @@ -98,8 +83,8 @@ export default function EditorTerminal({ // Only call fit if the size has actually changed if ( - width !== terminalRef.current.offsetWidth || - height !== terminalRef.current.offsetHeight + width !== terminalContainerRef.current.offsetWidth || + height !== terminalContainerRef.current.offsetHeight ) { try { fitAddonRef.current.fit() @@ -111,13 +96,13 @@ export default function EditorTerminal({ ) // start observing for resize - resizeObserver.observe(terminalRef.current) + resizeObserver.observe(terminalContainerRef.current) return () => { disposableOnData.dispose() disposableOnResize.dispose() resizeObserver.disconnect() } - }, [term, terminalRef.current]) + }, [term, terminalContainerRef.current]) useEffect(() => { if (!term) return @@ -136,7 +121,7 @@ export default function EditorTerminal({ return ( <>
@@ -150,3 +135,56 @@ export default function EditorTerminal({ ) } + +const lightTheme = { + foreground: "#2e3436", + background: "#ffffff", + black: "#2e3436", + brightBlack: "#555753", + red: "#cc0000", + brightRed: "#ef2929", + green: "#4e9a06", + brightGreen: "#8ae234", + yellow: "#c4a000", + brightYellow: "#fce94f", + blue: "#3465a4", + brightBlue: "#729fcf", + magenta: "#75507b", + brightMagenta: "#ad7fa8", + cyan: "#06989a", + brightCyan: "#34e2e2", + white: "#d3d7cf", + brightWhite: "#eeeeec", + cursor: "#2e3436", + cursorAccent: "#ffffff", + selectionBackground: "#3465a4", + selectionForeground: "#ffffff", + selectionInactiveBackground: "#264973", +} + +// Dark Theme +const darkTheme = { + foreground: "#f8f8f2", + background: "#0a0a0a", + black: "#21222c", + brightBlack: "#6272a4", + red: "#ff5555", + brightRed: "#ff6e6e", + green: "#50fa7b", + brightGreen: "#69ff94", + yellow: "#f1fa8c", + brightYellow: "#ffffa5", + blue: "#bd93f9", + brightBlue: "#d6acff", + magenta: "#ff79c6", + brightMagenta: "#ff92df", + cyan: "#8be9fd", + brightCyan: "#a4ffff", + white: "#f8f8f2", + brightWhite: "#ffffff", + cursor: "#f8f8f2", + cursorAccent: "#0a0a0a", + selectionBackground: "#264973", + selectionForeground: "#ffffff", + selectionInactiveBackground: "#1a3151", +} diff --git a/frontend/components/ui/tab.tsx b/frontend/components/ui/tab.tsx index 0ef38e0..f5bac5c 100644 --- a/frontend/components/ui/tab.tsx +++ b/frontend/components/ui/tab.tsx @@ -28,7 +28,7 @@ export default function Tab({ variant={"secondary"} className={`font-normal select-none ${ selected - ? "bg-neutral-700 hover:bg-neutral-600 text-foreground" + ? "bg-muted-foreground/50 hover:bg-muted-foreground/40 text-foreground" : "text-muted-foreground" }`} >