Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
242 lines
7.8 KiB
Swift
242 lines
7.8 KiB
Swift
import SwiftUI
|
|
|
|
#if os(macOS)
|
|
import AppKit
|
|
#else
|
|
import UIKit
|
|
#endif
|
|
|
|
#if os(macOS)
|
|
extension NSAppearance {
|
|
fileprivate var isDarkAqua: Bool {
|
|
self.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua
|
|
}
|
|
}
|
|
#endif
|
|
|
|
enum OpenClawChatTheme {
|
|
#if !os(macOS)
|
|
private enum IOSPalette {
|
|
static let lightCanvasTop = UIColor(red: 246 / 255.0, green: 247 / 255.0, blue: 249 / 255.0, alpha: 1)
|
|
static let lightCanvasMiddle = UIColor(red: 250 / 255.0, green: 251 / 255.0, blue: 252 / 255.0, alpha: 1)
|
|
static let lightCanvasBottom = UIColor.white
|
|
static let lightAccent = UIColor(red: 220 / 255.0, green: 38 / 255.0, blue: 38 / 255.0, alpha: 1)
|
|
static let lightAccentHot = UIColor(red: 239 / 255.0, green: 68 / 255.0, blue: 68 / 255.0, alpha: 1)
|
|
static let darkCanvasTop = UIColor(red: 12 / 255.0, green: 13 / 255.0, blue: 15 / 255.0, alpha: 1)
|
|
static let darkCanvasMiddle = UIColor(red: 7 / 255.0, green: 8 / 255.0, blue: 10 / 255.0, alpha: 1)
|
|
static let darkCanvasBottom = UIColor(red: 4 / 255.0, green: 5 / 255.0, blue: 6 / 255.0, alpha: 1)
|
|
static let darkPanel = UIColor(red: 10 / 255.0, green: 12 / 255.0, blue: 14 / 255.0, alpha: 1)
|
|
static let darkPanelRaised = UIColor(red: 17 / 255.0, green: 18 / 255.0, blue: 21 / 255.0, alpha: 1)
|
|
static let darkComposer = UIColor(red: 24 / 255.0, green: 25 / 255.0, blue: 28 / 255.0, alpha: 1)
|
|
static let darkAccent = UIColor(red: 198 / 255.0, green: 49 / 255.0, blue: 42 / 255.0, alpha: 1)
|
|
static let darkAccentHot = UIColor(red: 239 / 255.0, green: 62 / 255.0, blue: 82 / 255.0, alpha: 1)
|
|
}
|
|
|
|
private static func adaptiveColor(
|
|
light: UIColor,
|
|
dark: UIColor) -> Color
|
|
{
|
|
Color(uiColor: UIColor { traits in
|
|
traits.userInterfaceStyle == .dark ? dark : light
|
|
})
|
|
}
|
|
#endif
|
|
|
|
#if os(macOS)
|
|
static func resolvedAssistantBubbleColor(for appearance: NSAppearance) -> NSColor {
|
|
// NSColor semantic colors don't reliably resolve for arbitrary NSAppearance in SwiftPM.
|
|
// Use explicit light/dark values so the bubble updates when the system appearance flips.
|
|
appearance.isDarkAqua
|
|
? NSColor(calibratedWhite: 0.18, alpha: 0.88)
|
|
: NSColor(calibratedWhite: 0.94, alpha: 0.92)
|
|
}
|
|
|
|
static func resolvedOnboardingAssistantBubbleColor(for appearance: NSAppearance) -> NSColor {
|
|
appearance.isDarkAqua
|
|
? NSColor(calibratedWhite: 0.20, alpha: 0.94)
|
|
: NSColor(calibratedWhite: 0.97, alpha: 0.98)
|
|
}
|
|
|
|
static let assistantBubbleDynamicNSColor = NSColor(
|
|
name: NSColor.Name("OpenClawChatTheme.assistantBubble"),
|
|
dynamicProvider: resolvedAssistantBubbleColor(for:))
|
|
|
|
static let onboardingAssistantBubbleDynamicNSColor = NSColor(
|
|
name: NSColor.Name("OpenClawChatTheme.onboardingAssistantBubble"),
|
|
dynamicProvider: resolvedOnboardingAssistantBubbleColor(for:))
|
|
#endif
|
|
|
|
static var surface: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: .windowBackgroundColor)
|
|
#else
|
|
Color(uiColor: .systemBackground)
|
|
#endif
|
|
}
|
|
|
|
@ViewBuilder
|
|
static var background: some View {
|
|
#if os(macOS)
|
|
ZStack {
|
|
Rectangle()
|
|
.fill(.ultraThinMaterial)
|
|
LinearGradient(
|
|
colors: [
|
|
Color.white.opacity(0.12),
|
|
Color(nsColor: .windowBackgroundColor).opacity(0.35),
|
|
Color.black.opacity(0.35),
|
|
],
|
|
startPoint: .topLeading,
|
|
endPoint: .bottomTrailing)
|
|
RadialGradient(
|
|
colors: [
|
|
Color(nsColor: .systemOrange).opacity(0.14),
|
|
.clear,
|
|
],
|
|
center: .topLeading,
|
|
startRadius: 40,
|
|
endRadius: 320)
|
|
RadialGradient(
|
|
colors: [
|
|
Color(nsColor: .systemTeal).opacity(0.12),
|
|
.clear,
|
|
],
|
|
center: .topTrailing,
|
|
startRadius: 40,
|
|
endRadius: 280)
|
|
Color.black.opacity(0.08)
|
|
}
|
|
#else
|
|
ZStack {
|
|
LinearGradient(
|
|
colors: [
|
|
self.adaptiveColor(
|
|
light: IOSPalette.lightCanvasTop,
|
|
dark: IOSPalette.darkCanvasTop),
|
|
self.adaptiveColor(
|
|
light: IOSPalette.lightCanvasMiddle,
|
|
dark: IOSPalette.darkCanvasMiddle),
|
|
self.adaptiveColor(
|
|
light: IOSPalette.lightCanvasBottom,
|
|
dark: IOSPalette.darkCanvasBottom),
|
|
],
|
|
startPoint: .topLeading,
|
|
endPoint: .bottomTrailing)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
static var card: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: .textBackgroundColor)
|
|
#else
|
|
self.adaptiveColor(light: .secondarySystemBackground, dark: IOSPalette.darkPanel)
|
|
#endif
|
|
}
|
|
|
|
static var subtleCard: AnyShapeStyle {
|
|
#if os(macOS)
|
|
AnyShapeStyle(.ultraThinMaterial)
|
|
#else
|
|
AnyShapeStyle(self.adaptiveColor(light: .tertiarySystemBackground, dark: IOSPalette.darkPanelRaised))
|
|
#endif
|
|
}
|
|
|
|
static var userBubble: Color {
|
|
#if os(macOS)
|
|
Color(red: 127 / 255.0, green: 184 / 255.0, blue: 212 / 255.0)
|
|
#else
|
|
self.adaptiveColor(
|
|
light: IOSPalette.lightAccent,
|
|
dark: IOSPalette.darkAccent)
|
|
#endif
|
|
}
|
|
|
|
static var accent: Color {
|
|
self.userBubble
|
|
}
|
|
|
|
static var danger: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: .systemRed)
|
|
#else
|
|
Color(uiColor: .systemRed)
|
|
#endif
|
|
}
|
|
|
|
static var assistantBubble: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: self.assistantBubbleDynamicNSColor)
|
|
#else
|
|
// iMessage-style grey receiver bubble: clearly visible on the white chat surface.
|
|
self.adaptiveColor(light: .systemGray5, dark: IOSPalette.darkPanelRaised)
|
|
#endif
|
|
}
|
|
|
|
static var onboardingAssistantBubble: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: self.onboardingAssistantBubbleDynamicNSColor)
|
|
#else
|
|
self.adaptiveColor(light: .secondarySystemBackground, dark: IOSPalette.darkPanelRaised)
|
|
#endif
|
|
}
|
|
|
|
static var onboardingAssistantBorder: Color {
|
|
#if os(macOS)
|
|
Color.white.opacity(0.12)
|
|
#else
|
|
Color.white.opacity(0.12)
|
|
#endif
|
|
}
|
|
|
|
static var userText: Color {
|
|
.white
|
|
}
|
|
|
|
static var assistantText: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: .labelColor)
|
|
#else
|
|
Color(uiColor: .label)
|
|
#endif
|
|
}
|
|
|
|
static var composerBackground: AnyShapeStyle {
|
|
#if os(macOS)
|
|
AnyShapeStyle(.ultraThinMaterial)
|
|
#else
|
|
AnyShapeStyle(self.adaptiveColor(light: .secondarySystemGroupedBackground, dark: IOSPalette.darkPanel))
|
|
#endif
|
|
}
|
|
|
|
static var composerField: AnyShapeStyle {
|
|
#if os(macOS)
|
|
AnyShapeStyle(.thinMaterial)
|
|
#else
|
|
AnyShapeStyle(self.adaptiveColor(light: .secondarySystemBackground, dark: IOSPalette.darkComposer))
|
|
#endif
|
|
}
|
|
|
|
static var composerBorder: Color {
|
|
#if os(macOS)
|
|
Color.white.opacity(0.12)
|
|
#else
|
|
self.adaptiveColor(light: .separator, dark: UIColor.white.withAlphaComponent(0.14))
|
|
#endif
|
|
}
|
|
|
|
static var divider: Color {
|
|
Color.secondary.opacity(0.2)
|
|
}
|
|
}
|
|
|
|
enum OpenClawPlatformImageFactory {
|
|
static func image(_ image: OpenClawPlatformImage) -> Image {
|
|
#if os(macOS)
|
|
Image(nsImage: image)
|
|
#else
|
|
Image(uiImage: image)
|
|
#endif
|
|
}
|
|
}
|