Implement WebSocket support for terminal connections and enhance terminal UI

This commit is contained in:
2025-03-30 00:13:32 +05:30
parent 305650925e
commit 3a75000e12
9 changed files with 590 additions and 225 deletions

View File

@@ -1,5 +1,4 @@
import React from "react";
import { useState, useEffect } from "react";
import React, { useState, useEffect, useRef } from "react";
import { X } from "lucide-react";
const Panel = ({
@@ -21,9 +20,67 @@ const Panel = ({
setActiveTab(initialTab);
}, [initialTab]);
// Update the renderTerminal function to create an interactive terminal
const renderTerminal = () => {
const terminalRef = useRef(null);
const [inputBuffer, setInputBuffer] = useState("");
// Auto-scroll terminal to bottom when content changes
useEffect(() => {
if (terminalRef.current) {
terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
}
}, [terminalOutput]);
// Set up keyboard event listeners when terminal is focused
useEffect(() => {
const handleKeyDown = (e) => {
if (!isRunning) return;
if (e.key === 'Enter') {
// Send current input buffer through WebSocket
if (inputBuffer.trim() && onInputSubmit) {
e.preventDefault(); // Prevent default Enter behavior
// Important: Set user input and THEN call submit in a sequence
onUserInputChange(inputBuffer);
// Add a small delay before submitting to ensure state update
setTimeout(() => {
onInputSubmit();
// Clear buffer after submission is processed
setInputBuffer("");
}, 10);
}
} else if (e.key === 'Backspace') {
// Handle backspace to remove characters
setInputBuffer(prev => prev.slice(0, -1));
} else if (e.key.length === 1) {
// Add regular characters to input buffer
setInputBuffer(prev => prev + e.key);
}
};
// Add event listener
if (terminalRef.current) {
terminalRef.current.addEventListener('keydown', handleKeyDown);
}
// Clean up
return () => {
if (terminalRef.current) {
terminalRef.current.removeEventListener('keydown', handleKeyDown);
}
};
}, [isRunning, inputBuffer, onInputSubmit, onUserInputChange]);
return (
<div className="panel-terminal">
<div
className="panel-terminal"
ref={terminalRef}
tabIndex={0} // Make div focusable
onClick={() => terminalRef.current?.focus()} // Focus when clicked
>
{terminalOutput.length > 0 ? (
// Render output from EditorArea when available
<>
@@ -32,36 +89,18 @@ const Panel = ({
{line.type === 'command' ? <span className="terminal-prompt">$</span> : ''} {line.content}
</div>
))}
{waitingForInput && (
<div className="terminal-line">
<span className="terminal-prompt">Input:</span>
<input
type="text"
className="terminal-input"
value={userInput}
onChange={(e) => onUserInputChange && onUserInputChange(e.target.value)}
placeholder="Enter input for your program here..."
onKeyDown={(e) => {
if (e.key === 'Enter' && onInputSubmit) {
onInputSubmit();
}
}}
autoFocus
/>
{/* Show current input with blinking cursor only when connection is active */}
{isRunning && (
<div className="terminal-line terminal-input-line">
<span className="terminal-prompt">$</span> {inputBuffer}
<span className="terminal-cursor"></span>
</div>
)}
</>
) : (
// Default terminal content when no output
// Default terminal content
<>
<div className="terminal-line">
<span className="terminal-prompt">$</span> npm start
</div>
<div className="terminal-line terminal-output">Starting the development server...</div>
<div className="terminal-line terminal-output">Compiled successfully!</div>
<div className="terminal-line terminal-output">You can now view vscode-clone in the browser.</div>
<div className="terminal-line terminal-output">Local: http://localhost:3000</div>
<div className="terminal-line terminal-output">On Your Network: http://192.168.1.5:3000</div>
<div className="terminal-line">
<span className="terminal-prompt">$</span>
</div>