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

107 lines
2.8 KiB
TypeScript
Raw Normal View History

2024-10-21 13:57:45 -06:00
"use client"
2024-07-23 17:30:35 -04:00
2024-10-21 13:57:45 -06:00
import { useSocket } from "@/context/SocketContext"
import {
closeTerminal as closeTerminalHelper,
createTerminal as createTerminalHelper,
} from "@/lib/terminal"
import { Terminal } from "@xterm/xterm"
import React, { createContext, useContext, useState } from "react"
2024-07-23 17:30:35 -04:00
interface TerminalContextType {
2024-10-21 13:57:45 -06:00
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>
closeTerminal: (id: string) => void
deploy: (callback: () => void) => void
2024-07-23 17:30:35 -04:00
}
2024-10-21 13:57:45 -06:00
const TerminalContext = createContext<TerminalContextType | undefined>(
undefined
)
2024-07-23 17:30:35 -04:00
2024-10-21 13:57:45 -06:00
export const TerminalProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const { socket } = useSocket()
const [terminals, setTerminals] = useState<
{ id: string; terminal: Terminal | null }[]
>([])
const [activeTerminalId, setActiveTerminalId] = useState<string>("")
const [creatingTerminal, setCreatingTerminal] = useState<boolean>(false)
2024-07-23 17:30:35 -04:00
const createNewTerminal = async (command?: string): Promise<void> => {
2024-10-21 13:57:45 -06:00
if (!socket) return
setCreatingTerminal(true)
2024-07-23 17:30:35 -04:00
try {
createTerminalHelper({
setTerminals,
setActiveTerminalId,
setCreatingTerminal,
command,
2024-07-23 17:30:35 -04:00
socket,
2024-10-21 13:57:45 -06:00
})
2024-07-23 17:30:35 -04:00
} catch (error) {
2024-10-21 13:57:45 -06:00
console.error("Error creating terminal:", error)
2024-07-23 17:30:35 -04:00
} finally {
2024-10-21 13:57:45 -06:00
setCreatingTerminal(false)
2024-07-23 17:30:35 -04:00
}
2024-10-21 13:57:45 -06:00
}
2024-07-23 17:30:35 -04:00
const closeTerminal = (id: string) => {
2024-10-21 13:57:45 -06:00
if (!socket) return
const terminalToClose = terminals.find((term) => term.id === id)
2024-07-23 17:30:35 -04:00
if (terminalToClose) {
closeTerminalHelper({
term: terminalToClose,
terminals,
setTerminals,
setActiveTerminalId,
2024-10-21 13:57:45 -06:00
setClosingTerminal: () => {},
2024-07-23 17:30:35 -04:00
socket,
activeTerminalId,
2024-10-21 13:57:45 -06:00
})
2024-07-23 17:30:35 -04:00
}
2024-10-21 13:57:45 -06:00
}
2024-07-23 17:30:35 -04:00
const deploy = (callback: () => void) => {
2024-10-21 13:57:45 -06:00
if (!socket) console.error("Couldn't deploy: No socket")
console.log("Deploying...")
socket?.emit("deploy", () => {
2024-10-21 13:57:45 -06:00
callback()
})
}
2024-07-23 17:30:35 -04:00
const value = {
terminals,
setTerminals,
activeTerminalId,
setActiveTerminalId,
creatingTerminal,
setCreatingTerminal,
createNewTerminal,
closeTerminal,
2024-10-21 13:57:45 -06:00
deploy,
}
2024-07-23 17:30:35 -04:00
return (
<TerminalContext.Provider value={value}>
{children}
</TerminalContext.Provider>
2024-10-21 13:57:45 -06:00
)
}
2024-07-23 17:30:35 -04:00
export const useTerminal = (): TerminalContextType => {
2024-10-21 13:57:45 -06:00
const context = useContext(TerminalContext)
2024-07-23 17:30:35 -04:00
if (!context) {
2024-10-21 13:57:45 -06:00
throw new Error("useTerminal must be used within a TerminalProvider")
2024-07-23 17:30:35 -04:00
}
2024-10-21 13:57:45 -06:00
return context
}