mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-03 22:01:40 +00:00
* feat(mobile): session dashboard screens on iOS and Android via authenticated Control UI webview * fix(android): keep configured Control UI base path in session dashboard URL * docs(android): note system-trust boundary of the shared Control UI webview * fix(android): origin-only document-start rule for Control UI auth script * chore(i18n): refresh native inventory on rebased head * fix(ios): swiftlint closure form in session dashboard toolbar * fix(i18n): tolerate workflow-owned pending native rows in PR alignment checks * fix(android): KTX toUri per lint and refresh native inventory * fix(android): ktlint import order incl. main-inherited fleet test, refresh inventory
69 lines
2.6 KiB
Swift
69 lines
2.6 KiB
Swift
import OpenClawKit
|
|
import SwiftUI
|
|
|
|
/// Session-scoped dashboard rendered by the gateway Control UI.
|
|
struct SessionDashboardScreen: View {
|
|
@Environment(NodeAppModel.self) private var appModel
|
|
@Environment(\.dismiss) private var dismiss
|
|
let sessionKey: String
|
|
|
|
var body: some View {
|
|
let config = self.appModel.activeGatewayConnectConfig
|
|
let storedOperatorToken = AuthenticatedControlUI.storedOperatorToken(config: config)
|
|
ZStack {
|
|
OpenClawProBackground()
|
|
if let url = Self.dashboardURL(config: config, sessionKey: self.sessionKey) {
|
|
AuthenticatedControlUIWebView(
|
|
url: url,
|
|
authScript: AuthenticatedControlUI.authUserScript(
|
|
config: config,
|
|
pageURL: url,
|
|
storedOperatorToken: storedOperatorToken))
|
|
.id(AuthenticatedControlUI.webContentIdentity(
|
|
config: config,
|
|
storedOperatorToken: storedOperatorToken))
|
|
.ignoresSafeArea(.container, edges: .bottom)
|
|
} else {
|
|
self.unavailableCard
|
|
}
|
|
}
|
|
.navigationTitle("Dashboard")
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Button {
|
|
self.dismiss()
|
|
} label: {
|
|
Text("Done")
|
|
.font(OpenClawType.subheadSemiBold)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private var unavailableCard: some View {
|
|
VStack(spacing: 12) {
|
|
ProIconBadge(systemName: "rectangle.grid.2x2", color: OpenClawBrand.accent)
|
|
Text("Dashboard needs a connected gateway")
|
|
.font(OpenClawType.subheadSemiBold)
|
|
Text("Connect to your gateway to open this session dashboard.")
|
|
.font(OpenClawType.caption)
|
|
.foregroundStyle(.secondary)
|
|
.multilineTextAlignment(.center)
|
|
}
|
|
.padding(24)
|
|
}
|
|
|
|
/// Converts the active gateway WebSocket endpoint into the one-shot
|
|
/// authenticated Control UI route. Credentials stay in the startup script.
|
|
static func dashboardURL(config: GatewayConnectConfig?, sessionKey: String) -> URL? {
|
|
AuthenticatedControlUI.pageURL(
|
|
config: config,
|
|
path: "/chat",
|
|
queryItems: [
|
|
URLQueryItem(name: "session", value: sessionKey),
|
|
URLQueryItem(name: "face", value: "dashboard"),
|
|
])
|
|
}
|
|
}
|