merge: MEM-1/2/3 event listener leak cleanup (resolved session.store.ts conflict)
This commit is contained in:
commit
625a4500bc
@ -88,7 +88,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from "vue";
|
||||
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { useSessionStore, type Session } from "@/stores/session.store";
|
||||
import { useConnectionStore } from "@/stores/connection.store";
|
||||
@ -151,16 +151,10 @@ function closeMenuTab(): void {
|
||||
if (session) sessionStore.closeSession(session.id);
|
||||
}
|
||||
|
||||
// Listen for reattach events from detached windows
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
listen<{ sessionId: string; name: string; protocol: string }>("session:reattach", (event) => {
|
||||
const { sessionId } = event.payload;
|
||||
const session = sessionStore.sessions.find(s => s.id === sessionId);
|
||||
if (session) {
|
||||
session.active = true;
|
||||
sessionStore.activateSession(sessionId);
|
||||
}
|
||||
});
|
||||
import type { UnlistenFn } from "@tauri-apps/api/event";
|
||||
|
||||
let unlistenReattach: UnlistenFn | null = null;
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
@ -168,6 +162,19 @@ onMounted(async () => {
|
||||
} catch {
|
||||
availableShells.value = [];
|
||||
}
|
||||
|
||||
unlistenReattach = await listen<{ sessionId: string; name: string; protocol: string }>("session:reattach", (event) => {
|
||||
const { sessionId } = event.payload;
|
||||
const session = sessionStore.sessions.find(s => s.id === sessionId);
|
||||
if (session) {
|
||||
session.active = true;
|
||||
sessionStore.activateSession(sessionId);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
unlistenReattach?.();
|
||||
});
|
||||
|
||||
// Drag-and-drop tab reordering
|
||||
|
||||
@ -195,6 +195,7 @@ export function useRdp(): UseRdpReturn {
|
||||
const clipboardSync = ref(false);
|
||||
|
||||
let animFrameId: number | null = null;
|
||||
let unlistenFrame: (() => void) | null = null;
|
||||
|
||||
/**
|
||||
* Fetch the current frame from the Rust RDP backend.
|
||||
@ -315,8 +316,7 @@ export function useRdp(): UseRdpReturn {
|
||||
listen(`rdp:frame:${sessionId}`, () => {
|
||||
onFrameReady();
|
||||
}).then((unlisten) => {
|
||||
// Store unlisten so we can clean up
|
||||
(canvas as any).__wraith_unlisten = unlisten;
|
||||
unlistenFrame = unlisten;
|
||||
});
|
||||
});
|
||||
|
||||
@ -332,6 +332,10 @@ export function useRdp(): UseRdpReturn {
|
||||
cancelAnimationFrame(animFrameId);
|
||||
animFrameId = null;
|
||||
}
|
||||
if (unlistenFrame !== null) {
|
||||
unlistenFrame();
|
||||
unlistenFrame = null;
|
||||
}
|
||||
connected.value = false;
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@ import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
import { listen } from "@tauri-apps/api/event";
|
||||
import type { UnlistenFn } from "@tauri-apps/api/event";
|
||||
import { useConnectionStore } from "@/stores/connection.store";
|
||||
import type { ThemeDefinition } from "@/components/common/ThemePicker.vue";
|
||||
|
||||
@ -39,10 +40,14 @@ export const useSessionStore = defineStore("session", () => {
|
||||
|
||||
const sessionCount = computed(() => sessions.value.length);
|
||||
|
||||
const sessionUnlisteners = new Map<string, Array<UnlistenFn>>();
|
||||
|
||||
// Listen for backend close/exit events to update session status
|
||||
function setupStatusListeners(sessionId: string): void {
|
||||
listen(`ssh:close:${sessionId}`, () => markDisconnected(sessionId));
|
||||
listen(`ssh:exit:${sessionId}`, () => markDisconnected(sessionId));
|
||||
async function setupStatusListeners(sessionId: string): Promise<void> {
|
||||
const unlisteners: UnlistenFn[] = [];
|
||||
unlisteners.push(await listen(`ssh:close:${sessionId}`, () => markDisconnected(sessionId)));
|
||||
unlisteners.push(await listen(`ssh:exit:${sessionId}`, () => markDisconnected(sessionId)));
|
||||
sessionUnlisteners.set(sessionId, unlisteners);
|
||||
}
|
||||
|
||||
function markDisconnected(sessionId: string): void {
|
||||
@ -92,6 +97,12 @@ export const useSessionStore = defineStore("session", () => {
|
||||
console.error("Failed to disconnect session:", err);
|
||||
}
|
||||
|
||||
const unlisteners = sessionUnlisteners.get(id);
|
||||
if (unlisteners) {
|
||||
unlisteners.forEach((fn) => fn());
|
||||
sessionUnlisteners.delete(id);
|
||||
}
|
||||
|
||||
sessions.value.splice(idx, 1);
|
||||
|
||||
if (activeSessionId.value === id) {
|
||||
@ -325,7 +336,8 @@ export const useSessionStore = defineStore("session", () => {
|
||||
});
|
||||
|
||||
// Listen for PTY close
|
||||
listen(`pty:close:${sessionId}`, () => markDisconnected(sessionId));
|
||||
const unlistenPty = await listen(`pty:close:${sessionId}`, () => markDisconnected(sessionId));
|
||||
sessionUnlisteners.set(sessionId, [unlistenPty]);
|
||||
|
||||
activeSessionId.value = sessionId;
|
||||
} catch (err: unknown) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user