Skip to content

Commit 5e63ea2

Browse files
committed
feat(integrations): move activity log and connected clients to dedicated window per macOS HIG
1 parent aba76aa commit 5e63ea2

11 files changed

Lines changed: 912 additions & 567 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Window menu: "Integrations Activity" opens a dedicated, resizable window for the MCP activity log and connected clients. The window has a sidebar (Activity Log / Connected Clients) and a unified toolbar with native search, filter menu, refresh, and export. Window size is remembered across launches.
1213
- Sample database (Chinook) bundled — open from welcome screen with one click; reset via File menu
1314
- Connection string detection — paste a `postgres://`, `mysql://`, `redis://`, or `mongodb://` URL, then click Use to auto-fill the connection form
1415
- Activation telemetry: the daily heartbeat now reports three write-once timestamps per device (first connection attempt, first successful connection, first executed query), so we can see where new users drop off during activation. The values are stored locally in UserDefaults, set once and never overwritten, and the server also refuses to overwrite them once received. Both Mac and iOS send the same fields.
@@ -31,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3132

3233
### Changed
3334

35+
- Settings > Integrations is now a flat preferences pane per macOS HIG. The activity log, the connected-clients list, and the setup instructions have moved out of Settings: activity and connections live in the new Integrations Activity window (Window menu), and setup instructions open in a "Connect a Client…" sheet from the Settings pane. Settings keeps only configuration: server toggle, status, port, row limits, query timeout, authentication tokens, and network options.
3436
- MCP: idle session timeout raised from 5 to 15 minutes.
3537
- MCP: complete internal rewrite of the server, stdio bridge, and protocol dispatcher for spec compliance. Public API of `MCPServerManager` and the on-disk handshake format are unchanged; clients do not need to re-pair.
3638
- Internal: introduce `TabSession` as the foundation type for the editor tab/window subsystem rewrite. Currently a parallel structure mirroring `QueryTab`; subsequent PRs migrate state ownership and lifecycle hooks per `docs/architecture/tab-subsystem-rewrite.md`. No user-visible behavior change in this PR.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// IntegrationsActivityWindowFactory.swift
3+
// TablePro
4+
//
5+
6+
import AppKit
7+
import SwiftUI
8+
9+
@MainActor
10+
internal enum IntegrationsActivityWindowFactory {
11+
private static let identifier = NSUserInterfaceItemIdentifier("integrations-activity")
12+
private static let autosaveName: NSWindow.FrameAutosaveName = "IntegrationsActivityWindow"
13+
private static let defaultSize = NSSize(width: 960, height: 600)
14+
private static let minimumSize = NSSize(width: 720, height: 420)
15+
16+
internal static func openOrFront() {
17+
if let existing = existingWindow() {
18+
existing.makeKeyAndOrderFront(nil)
19+
NSApp.activate(ignoringOtherApps: true)
20+
return
21+
}
22+
let window = makeWindow()
23+
window.makeKeyAndOrderFront(nil)
24+
NSApp.activate(ignoringOtherApps: true)
25+
}
26+
27+
private static func existingWindow() -> NSWindow? {
28+
NSApp.windows.first { $0.identifier == identifier }
29+
}
30+
31+
private static func makeWindow() -> NSWindow {
32+
let hostingController = NSHostingController(rootView: IntegrationsActivityView())
33+
let window = NSWindow(contentViewController: hostingController)
34+
window.identifier = identifier
35+
window.title = String(localized: "Integrations Activity")
36+
window.styleMask = [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView]
37+
window.toolbarStyle = .unified
38+
window.titlebarSeparatorStyle = .automatic
39+
window.collectionBehavior.insert(.fullScreenPrimary)
40+
window.isReleasedWhenClosed = false
41+
window.setContentSize(defaultSize)
42+
window.minSize = minimumSize
43+
window.applyAutosaveName(autosaveName)
44+
return window
45+
}
46+
}

TablePro/Resources/Localizable.xcstrings

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,9 @@
14801480
},
14811481
"%1$@, %2$@" : {
14821482
"shouldTranslate" : false
1483+
},
1484+
"%d connected" : {
1485+
14831486
},
14841487
"%d connections found" : {
14851488
"localizations" : {
@@ -3853,6 +3856,9 @@
38533856
}
38543857
}
38553858
}
3859+
},
3860+
"Active %@" : {
3861+
38563862
},
38573863
"Active Connections" : {
38583864
"localizations" : {
@@ -3985,8 +3991,15 @@
39853991
}
39863992
}
39873993
}
3994+
},
3995+
"Activity" : {
3996+
3997+
},
3998+
"Activity is retained for 90 days" : {
3999+
39884000
},
39894001
"Activity is retained for 90 days." : {
4002+
"extractionState" : "stale",
39904003
"localizations" : {
39914004
"tr" : {
39924005
"stringUnit" : {
@@ -7836,9 +7849,6 @@
78367849
}
78377850
}
78387851
}
7839-
},
7840-
"Bundled sample database" : {
7841-
78427852
},
78437853
"Bytes Received" : {
78447854
"localizations" : {
@@ -8845,6 +8855,12 @@
88458855
}
88468856
}
88478857
}
8858+
},
8859+
"Choose a section from the sidebar." : {
8860+
8861+
},
8862+
"Choose your client and follow the steps to connect it to TablePro." : {
8863+
88488864
},
88498865
"Claude Code" : {
88508866
"localizations" : {
@@ -9044,6 +9060,9 @@
90449060
}
90459061
}
90469062
}
9063+
},
9064+
"Clear Filters" : {
9065+
90479066
},
90489067
"Clear History..." : {
90499068
"localizations" : {
@@ -9135,6 +9154,7 @@
91359154
}
91369155
},
91379156
"Clear search" : {
9157+
"extractionState" : "stale",
91389158
"localizations" : {
91399159
"tr" : {
91409160
"stringUnit" : {
@@ -9557,6 +9577,9 @@
95579577
}
95589578
}
95599579
}
9580+
},
9581+
"Clients will appear here while they have an active MCP session." : {
9582+
95609583
},
95619584
"Clipboard is empty or contains no text data." : {
95629585
"localizations" : {
@@ -10706,6 +10729,9 @@
1070610729
}
1070710730
}
1070810731
}
10732+
},
10733+
"Connect a Client…" : {
10734+
1070910735
},
1071010736
"Connect Anyway" : {
1071110737
"localizations" : {
@@ -15730,6 +15756,9 @@
1573015756
},
1573115757
"Disconnect from a database" : {
1573215758

15759+
},
15760+
"Disconnect the selected client" : {
15761+
1573315762
},
1573415763
"Disconnected" : {
1573515764
"localizations" : {
@@ -18839,6 +18868,7 @@
1883918868
}
1884018869
},
1884118870
"Export activity to CSV" : {
18871+
"extractionState" : "stale",
1884218872
"localizations" : {
1884318873
"tr" : {
1884418874
"stringUnit" : {
@@ -19374,6 +19404,7 @@
1937419404
}
1937519405
},
1937619406
"Export…" : {
19407+
"extractionState" : "stale",
1937719408
"localizations" : {
1937819409
"tr" : {
1937919410
"stringUnit" : {
@@ -21035,6 +21066,9 @@
2103521066
}
2103621067
}
2103721068
}
21069+
},
21070+
"Filter activity" : {
21071+
2103821072
},
2103921073
"Filter column" : {
2104021074
"localizations" : {
@@ -24619,6 +24653,9 @@
2461924653
}
2462024654
}
2462124655
}
24656+
},
24657+
"Integrations Activity" : {
24658+
2462224659
},
2462324660
"Integrations: Failed" : {
2462424661
"localizations" : {
@@ -27009,6 +27046,7 @@
2700927046
}
2701027047
},
2701127048
"Local only - not synced to iCloud" : {
27049+
"extractionState" : "stale",
2701227050
"localizations" : {
2701327051
"tr" : {
2701427052
"stringUnit" : {
@@ -27029,6 +27067,9 @@
2702927067
}
2703027068
}
2703127069
}
27070+
},
27071+
"Local only, not synced to iCloud" : {
27072+
2703227073
},
2703327074
"localhost" : {
2703427075
"localizations" : {
@@ -29462,6 +29503,9 @@
2946229503
}
2946329504
}
2946429505
}
29506+
},
29507+
"No activity matches the current filters." : {
29508+
2946529509
},
2946629510
"No activity yet" : {
2946729511
"localizations" : {
@@ -30043,6 +30087,9 @@
3004330087
}
3004430088
}
3004530089
}
30090+
},
30091+
"No matching activity" : {
30092+
3004630093
},
3004730094
"No matching connections" : {
3004830095
"extractionState" : "stale",
@@ -41089,6 +41136,7 @@
4108941136
}
4109041137
},
4109141138
"Settings" : {
41139+
"extractionState" : "stale",
4109241140
"localizations" : {
4109341141
"tr" : {
4109441142
"stringUnit" : {
@@ -50334,6 +50382,9 @@
5033450382
}
5033550383
}
5033650384
}
50385+
},
50386+
"via %@" : {
50387+
5033750388
},
5033850389
"View" : {
5033950390
"localizations" : {
@@ -50356,6 +50407,9 @@
5035650407
}
5035750408
}
5035850409
}
50410+
},
50411+
"View Activity…" : {
50412+
5035950413
},
5036050414
"View ER Diagram" : {
5036150415
"localizations" : {

TablePro/TableProApp.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,12 @@ struct AppMenuCommands: Commands {
580580

581581
Divider()
582582

583+
Button(String(localized: "Integrations Activity")) {
584+
IntegrationsActivityWindowFactory.openOrFront()
585+
}
586+
587+
Divider()
588+
583589
Button("Bring All to Front") {
584590
NSApp.arrangeInFront(nil)
585591
}

0 commit comments

Comments
 (0)