175 lines
4.7 KiB
Swift
175 lines
4.7 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 MoltbotChatTheme {
|
|
#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("MoltbotChatTheme.assistantBubble"),
|
|
dynamicProvider: resolvedAssistantBubbleColor(for:))
|
|
|
|
static let onboardingAssistantBubbleDynamicNSColor = NSColor(
|
|
name: NSColor.Name("MoltbotChatTheme.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
|
|
Color(uiColor: .systemBackground)
|
|
#endif
|
|
}
|
|
|
|
static var card: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: .textBackgroundColor)
|
|
#else
|
|
Color(uiColor: .secondarySystemBackground)
|
|
#endif
|
|
}
|
|
|
|
static var subtleCard: AnyShapeStyle {
|
|
#if os(macOS)
|
|
AnyShapeStyle(.ultraThinMaterial)
|
|
#else
|
|
AnyShapeStyle(Color(uiColor: .secondarySystemBackground).opacity(0.9))
|
|
#endif
|
|
}
|
|
|
|
static var userBubble: Color {
|
|
Color(red: 127 / 255.0, green: 184 / 255.0, blue: 212 / 255.0)
|
|
}
|
|
|
|
static var assistantBubble: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: self.assistantBubbleDynamicNSColor)
|
|
#else
|
|
Color(uiColor: .secondarySystemBackground)
|
|
#endif
|
|
}
|
|
|
|
static var onboardingAssistantBubble: Color {
|
|
#if os(macOS)
|
|
Color(nsColor: self.onboardingAssistantBubbleDynamicNSColor)
|
|
#else
|
|
Color(uiColor: .secondarySystemBackground)
|
|
#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(Color(uiColor: .systemBackground))
|
|
#endif
|
|
}
|
|
|
|
static var composerField: AnyShapeStyle {
|
|
#if os(macOS)
|
|
AnyShapeStyle(.thinMaterial)
|
|
#else
|
|
AnyShapeStyle(Color(uiColor: .secondarySystemBackground))
|
|
#endif
|
|
}
|
|
|
|
static var composerBorder: Color {
|
|
Color.white.opacity(0.12)
|
|
}
|
|
|
|
static var divider: Color {
|
|
Color.secondary.opacity(0.2)
|
|
}
|
|
}
|
|
|
|
enum MoltbotPlatformImageFactory {
|
|
static func image(_ image: MoltbotPlatformImage) -> Image {
|
|
#if os(macOS)
|
|
Image(nsImage: image)
|
|
#else
|
|
Image(uiImage: image)
|
|
#endif
|
|
}
|
|
}
|