Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/desktop-server-tabs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"aicodeman": patch
---

**Mac app: server tabs.** The Mac app now keeps several Codeman servers open in one window, one tab each in the title bar, and switches between them with a click or ⌘1 to ⌘8. Every tab shows whether its server needs you, is waiting, is working or is offline, and ⌘0 shows all servers at once with the ones that need you first. ⌘T opens another server, a tab can be renamed, coloured and dragged, ⇧⌘T reopens a closed one, and your tabs come back at the next launch. On macOS 14 and later every server keeps its own login and cookies; before macOS 14 a second tab on the same machine is refused. Behaviour change: only the server you used last keeps its per-device settings (font size, skin); every other server starts those fresh once.
1 change: 1 addition & 0 deletions config/test-suites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ export const BROWSER_TEST_GLOBS = [
'test/terminal-touch-swipe-axis.browser.test.ts',
'test/phone-press-feedback.browser.test.ts',
'test/desktop-connect-page.browser.test.ts', // no server: the page is served by request interception
'test/desktop-tabs-pages.browser.test.ts', // no server: the pages are served by request interception
'test/local-model-ui.browser.test.ts',
'test/home-breakpoint-swap.browser.test.ts',
'test/log-viewer-reconnect.browser.test.ts',
Expand Down
8 changes: 6 additions & 2 deletions packages/desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,21 @@ security-framework = "3"
# Ignoring signals in the logo blinker (src/logo.rs). Already in the tree
# through wry and tao, so no new crate is added.
libc = "0.2"
# JavaScript dialogs, HTTP Basic challenges, clearing cookies and the window's
# content size (src/macos.rs). The versions wry already pulls in, so no new
# JavaScript dialogs, HTTP Basic challenges, clearing one server's cookies and
# the window's content size (src/macos.rs). The versions wry already pulls in, so no new
# crate is added.
objc2 = { version = "0.6.5", default-features = false, features = ["std"] }
block2 = { version = "0.6.2", default-features = false, features = ["std"] }
objc2-foundation = { version = "0.3.2", default-features = false, features = [
"std",
"objc2-core-foundation",
"block2",
"NSArray",
"NSBundle",
"NSDate",
"NSDictionary",
"NSGeometry",
"NSHTTPCookie",
"NSObject",
"NSOperation",
"NSProcessInfo",
Expand All @@ -61,6 +63,7 @@ objc2-foundation = { version = "0.3.2", default-features = false, features = [
"NSURLRequest",
"NSURLResponse",
"NSURLSession",
"NSUUID",
"NSValue",
] }
objc2-app-kit = { version = "0.3.2", default-features = false, features = [
Expand All @@ -80,6 +83,7 @@ objc2-web-kit = { version = "0.3.2", default-features = false, features = [
"block2",
"objc2-app-kit",
"WKFrameInfo",
"WKHTTPCookieStore",
"WKNavigationDelegate",
"WKSecurityOrigin",
"WKUIDelegate",
Expand Down
47 changes: 38 additions & 9 deletions packages/desktop/README.md

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions packages/desktop/assets/connect.html
Original file line number Diff line number Diff line change
Expand Up @@ -1636,13 +1636,20 @@ <h1>Codeman</h1>
els.fullscreen.checked = !!msg.startFullscreen;
els.version.textContent = 'Codeman Desktop ' + (msg.version || '');
renderRecent();
if (state.servers[0]) choose(state.servers[0]);
// A server tab opened again at launch names its server (target), and
// connects to it by itself when connectNow says so; any other tab
// shows the server used last.
var target = typeof msg.target === 'string' && msg.target ? msg.target : '';
var targeted = target ? (state.servers.filter(function (s) { return s.url === target; })[0] || { url: target }) : null;
var shown = targeted || state.servers[0];
if (shown) choose(shown);
var auto = !!(msg.autoConnect && !manual && !tooOld && !msg.starting && !msg.notice && state.servers[0]);
// The tab of the server used last; This Mac on a first run. An
// automatic connect opens Codeman without looking at this Mac first:
// that look runs a few processes and asks the server once more, and
// it is only needed when the connect fails, which then asks for it.
selectTab(state.servers[0] && !isLocalUrl(state.servers[0].url) ? 'remote' : 'local', auto);
if (targeted) auto = !!(msg.connectNow && !tooOld && !msg.starting && !msg.notice);
// The tab of that server; This Mac on a first run. An automatic
// connect opens Codeman without looking at this Mac first: that look
// runs a few processes and asks the server once more, and it is only
// needed when the connect fails, which then asks for it.
selectTab(shown && !isLocalUrl(shown.url) ? 'remote' : 'local', auto);
if (msg.starting) {
setBusy(true, false);
setStatus('busy', 'Starting Codeman on this Mac…', msg.notice || '');
Expand Down
Loading
Loading