From 066805ea35765ff2e7d32bee0f7cd536219488cf Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 7 Feb 2026 11:54:59 +0700 Subject: [PATCH 1/2] feat: add dock menu with welcome window and connections list Add right-click context menu to the dock icon with: - "Show Welcome Window" option to quickly reopen the welcome screen - "Open Connection" submenu listing all saved connections with database type icons for quick connect --- TablePro/AppDelegate.swift | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/TablePro/AppDelegate.swift b/TablePro/AppDelegate.swift index 9350f0642..8a16cf092 100644 --- a/TablePro/AppDelegate.swift +++ b/TablePro/AppDelegate.swift @@ -21,6 +21,75 @@ class AppDelegate: NSObject, NSApplicationDelegate { /// Track windows that have been configured to avoid re-applying styles (which causes flicker) private var configuredWindows = Set() + func applicationDockMenu(_ sender: NSApplication) -> NSMenu? { + let menu = NSMenu() + + let welcomeItem = NSMenuItem( + title: "Show Welcome Window", + action: #selector(showWelcomeFromDock), + keyEquivalent: "" + ) + welcomeItem.target = self + menu.addItem(welcomeItem) + + // Add connections submenu + let connections = ConnectionStorage.shared.loadConnections() + if !connections.isEmpty { + let connectionsItem = NSMenuItem(title: "Open Connection", action: nil, keyEquivalent: "") + let submenu = NSMenu() + + for connection in connections { + let item = NSMenuItem( + title: connection.name, + action: #selector(connectFromDock(_:)), + keyEquivalent: "" + ) + item.target = self + item.representedObject = connection.id + item.image = NSImage(named: connection.type.iconName) + item.image?.size = NSSize(width: 16, height: 16) + submenu.addItem(item) + } + + connectionsItem.submenu = submenu + menu.addItem(connectionsItem) + } + + return menu + } + + @objc + private func showWelcomeFromDock() { + openWelcomeWindow() + } + + @objc + private func connectFromDock(_ sender: NSMenuItem) { + guard let connectionId = sender.representedObject as? UUID else { return } + let connections = ConnectionStorage.shared.loadConnections() + guard let connection = connections.first(where: { $0.id == connectionId }) else { return } + + // Open main window and connect (same flow as auto-reconnect) + NotificationCenter.default.post(name: .openMainWindow, object: nil) + + Task { @MainActor in + do { + try await DatabaseManager.shared.connectToSession(connection) + + // Close welcome window on successful connection + for window in NSApp.windows where self.isWelcomeWindow(window) { + window.close() + } + } catch { + // Connection failed - close main window, reopen welcome + for window in NSApp.windows where self.isMainWindow(window) { + window.close() + } + self.openWelcomeWindow() + } + } + } + func applicationDidFinishLaunching(_ notification: Notification) { // Configure windows after app launch configureWelcomeWindow() From 210bfbdb5c4c7fb392c2f008001e117ef2c000fb Mon Sep 17 00:00:00 2001 From: Ngo Quoc Dat Date: Sat, 7 Feb 2026 11:57:38 +0700 Subject: [PATCH 2/2] fix: address review feedback for dock menu - Create resized copy of NSImage instead of mutating shared asset catalog image - Add error logging for dock connection failures consistent with auto-reconnect --- TablePro/AppDelegate.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/TablePro/AppDelegate.swift b/TablePro/AppDelegate.swift index 8a16cf092..e11dc58fe 100644 --- a/TablePro/AppDelegate.swift +++ b/TablePro/AppDelegate.swift @@ -46,8 +46,13 @@ class AppDelegate: NSObject, NSApplicationDelegate { ) item.target = self item.representedObject = connection.id - item.image = NSImage(named: connection.type.iconName) - item.image?.size = NSSize(width: 16, height: 16) + if let original = NSImage(named: connection.type.iconName) { + let resized = NSImage(size: NSSize(width: 16, height: 16), flipped: false) { rect in + original.draw(in: rect) + return true + } + item.image = resized + } submenu.addItem(item) } @@ -81,6 +86,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { window.close() } } catch { + print("[AppDelegate] Dock connection failed for '\(connection.name)': \(error.localizedDescription)") + // Connection failed - close main window, reopen welcome for window in NSApp.windows where self.isMainWindow(window) { window.close()