Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Analytics } from "@vercel/analytics/react"
interface Terminal {
id: string;
position: { x: number; y: number };
zIndex: number;
}

function AppContent() {
Expand All @@ -29,10 +30,13 @@ function AppContent() {
};

// Hold all terminals directly in state so changes trigger re-renders
const [highestZIndex, setHighestZIndex] = useState(1);

const [terminals, setTerminals] = useState<Terminal[]>(() => [
{
id: 'terminal-0',
position: generateRandomPosition(),
zIndex: 1,
},
]);

Expand All @@ -41,20 +45,24 @@ function AppContent() {
const handleTerminalCountChange = (count: number) => {
setTerminals((prev) => {
let updated = [...prev];
let newZ = highestZIndex;

// Add new terminals if needed
if (count > prev.length) {
for (let i = prev.length; i < count; i++) {
newZ += 1;
updated.push({
id: `terminal-${i}`,
position: generateRandomPosition(),
zIndex: newZ,
});
}
} else if (count < prev.length) {
// Remove terminals from the end
updated = updated.slice(0, count);
}

setHighestZIndex(newZ);
return updated;
});
};
Expand All @@ -64,15 +72,25 @@ function AppContent() {
};

const handlePositionChange = (terminalId: string, position: { x: number; y: number }) => {
setTerminals((prev) =>
prev.map((terminal) =>
terminal.id === terminalId
setTerminals((prev) =>
prev.map((terminal) =>
terminal.id === terminalId
? { ...terminal, position }
: terminal
)
);
};

const handleFocus = (terminalId: string) => {
const newZ = highestZIndex + 1;
setHighestZIndex(newZ);
setTerminals((prev) =>
prev.map((terminal) =>
terminal.id === terminalId ? { ...terminal, zIndex: newZ } : terminal
)
);
};

const handleArrangeTerminals = () => {
setTerminals((prev) => {
const terminalWidth = 320; // Default terminal width + some padding
Expand Down Expand Up @@ -154,6 +172,8 @@ function AppContent() {
id={terminal.id}
title={`Terminal ${index + 1}`}
initialPosition={terminal.position}
zIndex={terminal.zIndex}
onFocus={handleFocus}
onClose={() => handleTerminalClose(terminal.id)}
onPositionChange={handlePositionChange}
/>
Expand Down
16 changes: 12 additions & 4 deletions src/components/TerminalWindow/TerminalWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,28 @@ import { useTheme } from '../../contexts/ThemeContext';
import { generateMultiLineAsciiArt } from '../../utils/asciiArt';

interface TerminalWindowProps {
id: string;
id: string;
initialPosition?: { x: number; y: number };
initialSize?: { width?: number; height?: number };
title?: string;
onClose?: () => void;
onPositionChange?: (id: string, position: { x: number; y: number }) => void;
zIndex?: number;
onFocus?: (id: string) => void;
}

const DEFAULT_WIDTH = 650;
const DEFAULT_HEIGHT = 450;

export function TerminalWindow({
export function TerminalWindow({
id,
initialPosition = { x: 0, y: 0 },
initialSize = {},
title = 'Terminal',
onClose,
onPositionChange
onPositionChange,
zIndex = 10,
onFocus
}: TerminalWindowProps) {
const { currentTheme, getColorForRole } = useTheme();
const nodeRef = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -89,7 +93,11 @@ export function TerminalWindow({
}
}}
>
<div ref={nodeRef} style={{ position: 'absolute', zIndex: 10 }}>
<div
ref={nodeRef}
style={{ position: 'absolute', zIndex }}
onMouseDown={() => onFocus && onFocus(id)}
>
<ResizableBox
width={size.width}
height={size.height}
Expand Down