fix: lazy-connect terminal and cap reconnect attempts (#521)
TerminalPanel was connecting on mount even when the drawer was closed and the terminal tab was inactive. Combined with reconnectAttempts resetting on every ws.onopen, this caused infinite reconnection loops that spawned PTY processes until system limits were hit. - Pass `visible` prop to TerminalPanel, only connect when terminal tab is actually shown - Move reconnectAttempts reset from ws.onopen to "created" handler so only successful PTY creation resets the counter - Remove unused onMounted import Fixes #509 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,7 @@ function handleClose() {
|
||||
<FilesPanel />
|
||||
</div>
|
||||
<div v-show="activeTab === 'terminal'" class="drawer-pane">
|
||||
<TerminalPanel />
|
||||
<TerminalPanel :visible="activeTab === 'terminal' && show" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onUnmounted, computed } from "vue";
|
||||
import { ref, onUnmounted, computed, watch } from "vue";
|
||||
import { Terminal } from "@xterm/xterm";
|
||||
import { FitAddon } from "@xterm/addon-fit";
|
||||
import { WebLinksAddon } from "@xterm/addon-web-links";
|
||||
@@ -12,6 +12,8 @@ import type { ITheme } from "@xterm/xterm";
|
||||
const { t } = useI18n();
|
||||
const message = useMessage();
|
||||
|
||||
const props = defineProps<{ visible?: boolean }>();
|
||||
|
||||
// ─── Terminal themes ────────────────────────────────────────────
|
||||
|
||||
const TERMINAL_THEMES: Record<string, { label: string; theme: ITheme }> = {
|
||||
@@ -164,10 +166,8 @@ function connect() {
|
||||
ws = new WebSocket(url);
|
||||
|
||||
ws.onopen = () => {
|
||||
reconnectAttempts = 0;
|
||||
isConnecting.value = false;
|
||||
connectionError.value = null;
|
||||
// Server auto-creates the first session
|
||||
};
|
||||
|
||||
ws.onmessage = (event) => {
|
||||
@@ -210,6 +210,7 @@ function send(data: object | string) {
|
||||
function handleControl(msg: any) {
|
||||
switch (msg.type) {
|
||||
case "created":
|
||||
reconnectAttempts = 0;
|
||||
sessions.value.push({
|
||||
id: msg.id,
|
||||
shell: msg.shell,
|
||||
@@ -376,9 +377,14 @@ function formatTime(ts: number) {
|
||||
|
||||
// ─── Lifecycle ──────────────────────────────────────────────────
|
||||
|
||||
onMounted(() => {
|
||||
connect();
|
||||
});
|
||||
let hasConnected = false;
|
||||
|
||||
watch(() => props.visible, (visible) => {
|
||||
if (visible && !hasConnected && !ws) {
|
||||
hasConnected = true;
|
||||
connect();
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
onUnmounted(() => {
|
||||
unmountActiveTerminal();
|
||||
|
||||
Reference in New Issue
Block a user