sandbox-web-ide/frontend/context/TerminalContext.tsx

129 lines
3.8 KiB
TypeScript
Raw Permalink Normal View History

2024-07-23 17:30:35 -04:00
"use client";
import React, { createContext, useContext, useState, useEffect } from 'react';
import { io, Socket } from 'socket.io-client';
import { Terminal } from '@xterm/xterm';
2024-07-23 20:17:50 -04:00
import { createTerminal as createTerminalHelper, closeTerminal as closeTerminalHelper } from '@/lib/terminal';
2024-07-23 17:30:35 -04:00
interface TerminalContextType {
socket: Socket | null;
terminals: { id: string; terminal: Terminal | null }[];
setTerminals: React.Dispatch<React.SetStateAction<{ id: string; terminal: Terminal | null }[]>>;
activeTerminalId: string;
setActiveTerminalId: React.Dispatch<React.SetStateAction<string>>;
creatingTerminal: boolean;
setCreatingTerminal: React.Dispatch<React.SetStateAction<boolean>>;
createNewTerminal: (command?: string) => Promise<void>;
2024-07-23 17:30:35 -04:00
closeTerminal: (id: string) => void;
setUserAndSandboxId: (userId: string, sandboxId: string) => void;
deploy: (callback: () => void) => void;
2024-07-23 17:30:35 -04:00
}
const TerminalContext = createContext<TerminalContextType | undefined>(undefined);
export const TerminalProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [socket, setSocket] = useState<Socket | null>(null);
const [terminals, setTerminals] = useState<{ id: string; terminal: Terminal | null }[]>([]);
const [activeTerminalId, setActiveTerminalId] = useState<string>('');
const [creatingTerminal, setCreatingTerminal] = useState<boolean>(false);
const [userId, setUserId] = useState<string | null>(null);
const [sandboxId, setSandboxId] = useState<string | null>(null);
useEffect(() => {
if (userId && sandboxId) {
console.log("Initializing socket connection...");
2024-07-31 18:35:28 -07:00
const newSocket = io(`${process.env.NEXT_PUBLIC_SERVER_URL}?userId=${userId}&sandboxId=${sandboxId}`);
2024-07-23 17:30:35 -04:00
console.log("Socket instance:", newSocket);
setSocket(newSocket);
newSocket.on('connect', () => {
console.log("Socket connected:", newSocket.id);
});
newSocket.on('disconnect', () => {
console.log("Socket disconnected");
});
return () => {
console.log("Disconnecting socket...");
newSocket.disconnect();
};
}
}, [userId, sandboxId]);
const createNewTerminal = async (command?: string): Promise<void> => {
2024-07-23 17:30:35 -04:00
if (!socket) return;
setCreatingTerminal(true);
try {
createTerminalHelper({
setTerminals,
setActiveTerminalId,
setCreatingTerminal,
command,
2024-07-23 17:30:35 -04:00
socket,
});
} catch (error) {
console.error("Error creating terminal:", error);
} finally {
setCreatingTerminal(false);
}
};
const closeTerminal = (id: string) => {
if (!socket) return;
const terminalToClose = terminals.find(term => term.id === id);
if (terminalToClose) {
closeTerminalHelper({
term: terminalToClose,
terminals,
setTerminals,
setActiveTerminalId,
setClosingTerminal: () => {},
socket,
activeTerminalId,
});
}
};
const setUserAndSandboxId = (newUserId: string, newSandboxId: string) => {
setUserId(newUserId);
setSandboxId(newSandboxId);
};
const deploy = (callback: () => void) => {
if (!socket) console.error("Couldn't deploy: No socket");
console.log("Deploying...")
socket?.emit("deploy", () => {
callback();
});
}
2024-07-23 17:30:35 -04:00
const value = {
socket,
terminals,
setTerminals,
activeTerminalId,
setActiveTerminalId,
creatingTerminal,
setCreatingTerminal,
createNewTerminal,
closeTerminal,
setUserAndSandboxId,
deploy
2024-07-23 17:30:35 -04:00
};
return (
<TerminalContext.Provider value={value}>
{children}
</TerminalContext.Provider>
);
};
export const useTerminal = (): TerminalContextType => {
const context = useContext(TerminalContext);
if (!context) {
throw new Error('useTerminal must be used within a TerminalProvider');
}
return context;
};