Files
openclaw/apps/macos/Sources/OpenClaw/DashboardWindow.swift
Peter Steinberger 477b2860d5 feat(macos): add tabs to the dashboard link browser sidebar (#103438)
Each inline link opens in its own tab (exact-URL dedupe); sidebar
target=_blank links open new tabs. Tab strip on top with click to
activate, close buttons, middle-click close, pointer-drag reorder, and
a per-tab context menu (Open in Default Browser, Copy Link, Reload,
Close Tab, Close Other Tabs). Navigation controls sit below the tabs
and follow the active tab. Closing the last tab collapses the sidebar
with no lingering webviews or history.
2026-07-10 06:51:49 +01:00

60 lines
1.8 KiB
Swift

import AppKit
import Foundation
import OSLog
let dashboardWindowLogger = Logger(subsystem: "ai.openclaw", category: "DashboardWindow")
enum DashboardWindowLayout {
static let windowSize = NSSize(width: 1240, height: 860)
static let windowMinSize = NSSize(width: 900, height: 620)
static let mainBrowserMinWidth: CGFloat = 520
static let linkBrowserMinWidth: CGFloat = 320
static let linkBrowserMaxWidth: CGFloat = 760
static let linkBrowserPreferredFraction: CGFloat = 0.4
static let linkBrowserTabBarHeight: CGFloat = 30
static let linkBrowserSplitAutosaveName = "OpenClawDashboardLinkBrowserSplit"
}
enum DashboardLinkTarget: String, Equatable {
case inline
case external
}
enum DashboardTargetlessNavigationAction: Equatable {
case allow
case openExternal
case cancel
}
enum DashboardNewWindowAction: Equatable {
case openTab(URL)
case openExternal(URL)
case ignore
}
struct DashboardLinkRequest: Equatable {
let url: URL
let target: DashboardLinkTarget
}
struct DashboardWindowAuth: Equatable {
var gatewayUrl: String?
var token: String?
var password: String?
var hasCredential: Bool {
self.token?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false ||
self.password?.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty == false
}
}
/// Dashboard URLs carry the auth token in the `#token=...` fragment; strip the
/// fragment before logging so credentials never land in unified logs.
func dashboardLogString(for url: URL) -> String {
guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
return "<unparseable-url>"
}
components.fragment = nil
return components.url?.absoluteString ?? "<unparseable-url>"
}