feat(multimonitor): header button to open Codeman spanned across all displays

Replace the header notification bell (now hidden by default; still reachable
via Settings → Notifications and the drawer) with a multi-monitor button.
Clicking it POSTs /api/system/span-displays, which spawns the bundled
scripts/span-codeman.sh — a fresh, maximized browser --app window sized to the
union of all displays — so in-page floating session panels can be dragged
across the physical monitor seam. macOS only; needs the one-time "Displays
have separate Spaces" OFF prerequisite (documented in the script). The route
pins the spanned window to localhost with a digits-only port from the Host
header so nothing attacker-controllable reaches the launched browser.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ark0N
2026-06-08 04:53:33 +02:00
co-authored by Claude Opus 4.8
parent 59145c48fc
commit 95b00357b6
4 changed files with 121 additions and 2 deletions
+17
View File
@@ -3129,6 +3129,23 @@ Object.assign(CodemanApp.prototype, {
this.notificationManager?.toggleDrawer();
},
// Open a Codeman window stretched across all displays (multi-monitor mode).
// The server spawns scripts/span-codeman.sh, which launches a fresh, spanning
// browser --app window so in-page floating panels can cross the monitor seam.
async launchMultiMonitor() {
try {
const res = await fetch('/api/system/span-displays', { method: 'POST' });
const data = await res.json().catch(() => ({}));
if (res.ok && data.success) {
this.showToast('Opening Codeman across all displays…', 'success');
} else {
this.showToast(data.error || 'Could not open spanning window', 'error');
}
} catch (err) {
this.showToast('Could not open spanning window: ' + (err?.message || err), 'error');
}
},
// Alias for showToast
toast(message, type = 'info') {
return this.showToast(message, type);