From 3898a1c3e22bc29de7db23940b48d69b2fb507f4 Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Tue, 17 Mar 2026 07:04:49 -0400 Subject: [PATCH] feat: host key dialog and double-click connection flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add HostKeyDialog modal with two modes: new host (informational with blue accent) and changed key (warning with red accent). Shows hostname, key type, and fingerprint in monospace. ConnectionTree now has @dblclick handler that calls sessionStore.connect(). Session store gains a connect() method that looks up the connection, checks for existing sessions, and creates a mock session tab. Pre-loaded mock sessions removed — sessions start empty and are created on double-click. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../src/components/common/HostKeyDialog.vue | 105 ++++++++++++++++++ .../src/components/sidebar/ConnectionTree.vue | 10 +- frontend/src/stores/session.store.ts | 35 +++++- 3 files changed, 143 insertions(+), 7 deletions(-) create mode 100644 frontend/src/components/common/HostKeyDialog.vue diff --git a/frontend/src/components/common/HostKeyDialog.vue b/frontend/src/components/common/HostKeyDialog.vue new file mode 100644 index 0000000..862d7b8 --- /dev/null +++ b/frontend/src/components/common/HostKeyDialog.vue @@ -0,0 +1,105 @@ + + + diff --git a/frontend/src/components/sidebar/ConnectionTree.vue b/frontend/src/components/sidebar/ConnectionTree.vue index 734ca11..ba925f8 100644 --- a/frontend/src/components/sidebar/ConnectionTree.vue +++ b/frontend/src/components/sidebar/ConnectionTree.vue @@ -41,6 +41,7 @@ v-for="conn in connectionStore.connectionsByGroup(group.id)" :key="conn.id" class="w-full flex items-center gap-2 pl-8 pr-3 py-1.5 text-xs hover:bg-[var(--wraith-bg-tertiary)] transition-colors cursor-pointer" + @dblclick="handleConnect(conn)" > import { ref } from "vue"; -import { useConnectionStore } from "@/stores/connection.store"; +import { useConnectionStore, type Connection } from "@/stores/connection.store"; +import { useSessionStore } from "@/stores/session.store"; const connectionStore = useConnectionStore(); +const sessionStore = useSessionStore(); // All groups expanded by default const expandedGroups = ref>( @@ -80,4 +83,9 @@ function toggleGroup(groupId: number): void { expandedGroups.value.add(groupId); } } + +/** Double-click a connection to open a new session. */ +function handleConnect(conn: Connection): void { + sessionStore.connect(conn.id); +} diff --git a/frontend/src/stores/session.store.ts b/frontend/src/stores/session.store.ts index 2390e18..6c64b2d 100644 --- a/frontend/src/stores/session.store.ts +++ b/frontend/src/stores/session.store.ts @@ -1,5 +1,6 @@ import { defineStore } from "pinia"; import { ref, computed } from "vue"; +import { useConnectionStore } from "@/stores/connection.store"; export interface Session { id: string; @@ -17,13 +18,9 @@ export interface Session { * For now, mock sessions are used to render the tab bar. */ export const useSessionStore = defineStore("session", () => { - const sessions = ref([ - { id: "s1", connectionId: 1, name: "Asgard", protocol: "ssh", active: true }, - { id: "s2", connectionId: 2, name: "Docker", protocol: "ssh", active: false }, - { id: "s3", connectionId: 4, name: "CLT-VMHOST01", protocol: "rdp", active: false }, - ]); + const sessions = ref([]); - const activeSessionId = ref("s1"); + const activeSessionId = ref(null); const activeSession = computed(() => sessions.value.find((s) => s.id === activeSessionId.value) ?? null, @@ -61,6 +58,31 @@ export const useSessionStore = defineStore("session", () => { activeSessionId.value = id; } + /** + * Connect to a server by connection ID. + * Creates a new session tab and sets it active. + * + * TODO: Replace with Wails binding call — SSHService.Connect(hostname, port, ...) + * For now, creates a mock session using the connection's name. + */ + function connect(connectionId: number): void { + const connectionStore = useConnectionStore(); + const conn = connectionStore.connections.find((c) => c.id === connectionId); + if (!conn) return; + + // Check if there's already an active session for this connection + const existing = sessions.value.find((s) => s.connectionId === connectionId); + if (existing) { + activeSessionId.value = existing.id; + return; + } + + // TODO: Replace with Wails binding call: + // const sessionId = await SSHService.Connect(conn.hostname, conn.port, username, authMethods, cols, rows) + // For now, create a mock session + addSession(connectionId, conn.name, conn.protocol); + } + return { sessions, activeSessionId, @@ -69,5 +91,6 @@ export const useSessionStore = defineStore("session", () => { activateSession, closeSession, addSession, + connect, }; });