forked from op7418/CodePilot
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuseTerminal.ts
More file actions
106 lines (91 loc) · 2.86 KB
/
useTerminal.ts
File metadata and controls
106 lines (91 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
"use client";
import { useEffect, useRef, useCallback, useState } from "react";
import { usePanel } from "./usePanel";
export function useTerminal() {
const { workingDirectory, sessionId, terminalOpen } = usePanel();
const [isElectron] = useState(
() => typeof window !== "undefined" && !!window.electronAPI?.terminal
);
const [connected, setConnected] = useState(false);
const [exited, setExited] = useState(false);
const terminalIdRef = useRef<string>("");
const unsubDataRef = useRef<(() => void) | null>(null);
const unsubExitRef = useRef<(() => void) | null>(null);
const onDataCallbackRef = useRef<((data: string) => void) | null>(null);
const create = useCallback(async (cols: number, rows: number) => {
const api = window.electronAPI?.terminal;
if (!api || !workingDirectory) return;
// Kill previous terminal for this session
if (terminalIdRef.current) {
try {
await api.kill(terminalIdRef.current);
} catch {
// ignore
}
}
const id = `term-${sessionId || 'default'}-${Date.now()}`;
terminalIdRef.current = id;
setExited(false);
// Subscribe to events
unsubDataRef.current?.();
unsubExitRef.current?.();
unsubDataRef.current = api.onData((data) => {
if (data.id === id) {
onDataCallbackRef.current?.(data.data);
}
});
unsubExitRef.current = api.onExit((data) => {
if (data.id === id) {
setConnected(false);
setExited(true);
}
});
await api.create({ id, cwd: workingDirectory, cols, rows });
setConnected(true);
}, [workingDirectory, sessionId]);
const write = useCallback((data: string) => {
const api = window.electronAPI?.terminal;
if (!api || !terminalIdRef.current) return;
api.write(terminalIdRef.current, data);
}, []);
const resize = useCallback(async (cols: number, rows: number) => {
const api = window.electronAPI?.terminal;
if (!api || !terminalIdRef.current) return;
await api.resize(terminalIdRef.current, cols, rows);
}, []);
const kill = useCallback(async () => {
const api = window.electronAPI?.terminal;
if (!api || !terminalIdRef.current) return;
try {
await api.kill(terminalIdRef.current);
} catch {
// ignore
}
terminalIdRef.current = "";
setConnected(false);
}, []);
const setOnData = useCallback((callback: (data: string) => void) => {
onDataCallbackRef.current = callback;
}, []);
// Clean up on unmount
useEffect(() => {
return () => {
unsubDataRef.current?.();
unsubExitRef.current?.();
if (terminalIdRef.current && window.electronAPI?.terminal) {
window.electronAPI.terminal.kill(terminalIdRef.current).catch(() => {});
}
};
}, []);
return {
isElectron,
connected,
exited,
terminalOpen,
create,
write,
resize,
kill,
setOnData,
};
}