Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion clients/macos/vellum-assistant/App/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ public final class AppDelegate: NSObject, NSApplicationDelegate {
private var cachedSkills: [SkillInfo] = []
private var refreshSkillsTask: Task<Void, Never>?

@AppStorage("themePreference") private var themePreference: String = "system"

public func applicationDidFinishLaunching(_ notification: Notification) {
NSApp.appearance = NSAppearance(named: .darkAqua)
applyThemePreference()
registerBundledFonts()

#if DEBUG
Expand Down Expand Up @@ -147,6 +149,38 @@ public final class AppDelegate: NSObject, NSApplicationDelegate {
showMainWindow()
}

/// Applies the user's theme preference to the app appearance.
/// Called on launch and whenever the setting changes.
func applyThemePreference() {
let pref = UserDefaults.standard.string(forKey: "themePreference") ?? "system"
let appearance: NSAppearance?
switch pref {
case "light":
appearance = NSAppearance(named: .aqua)
case "dark":
appearance = NSAppearance(named: .darkAqua)
default:
appearance = nil // follow system
}
NSApp.appearance = appearance
// Propagate to all existing windows so the change takes effect immediately
for window in NSApp.windows {
window.appearance = appearance
window.invalidateShadow()
window.contentView?.needsDisplay = true
window.displayIfNeeded()
}
// Force SwiftUI to re-evaluate adaptive colors by toggling the appearance
DispatchQueue.main.async {
for window in NSApp.windows {
window.contentView?.effectiveAppearance.performAsCurrentDrawingAppearance {
window.contentView?.needsLayout = true
window.contentView?.needsDisplay = true
}
}
}
}

private func setupDaemonClient() {
// Show macOS notification when a reminder fires
daemonClient.onReminderFired = { msg in
Expand Down
14 changes: 12 additions & 2 deletions clients/macos/vellum-assistant/Features/Chat/ChatView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,16 @@ struct ChatView: View {
)
}

@Environment(\.colorScheme) private var colorScheme

@ViewBuilder
private var chatBackground: some View {
if let url = ResourceBundle.bundle.url(forResource: "background", withExtension: "png"),
let nsImage = NSImage(contentsOf: url) {
Image(nsImage: nsImage)
.resizable()
.scaledToFit()
.opacity(colorScheme == .light ? 0 : 1.0)
.allowsHitTesting(false)
}
}
Expand Down Expand Up @@ -311,7 +314,7 @@ struct ChatView: View {
}

if isThinking {
ThinkingIndicator()
ThinkingIndicator(label: messages.count <= 1 ? "Waking up..." : "Thinking")
.id("thinking-indicator")
.transition(.opacity.combined(with: .move(edge: .bottom)))
}
Expand Down Expand Up @@ -839,12 +842,19 @@ private struct ChatBubble: View {
// MARK: - Thinking Indicator

private struct ThinkingIndicator: View {
var label: String = "Thinking"
@State private var phase: Int = 0
@State private var timer: Timer?

var body: some View {
HStack(spacing: VSpacing.xs) {
Text("Thinking")
Image("OwlIcon")
.resizable()
.scaledToFit()
.frame(width: 12, height: 12)
.foregroundColor(VColor.textSecondary)

Text(label)
.font(VFont.caption)
.foregroundColor(VColor.textSecondary)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ final class MainWindow {
let hostingController = NSHostingController(rootView: MainWindowView(threadManager: threadManager, zoomManager: zoomManager, traceStore: traceStore, daemonClient: daemonClient, surfaceManager: surfaceManager, ambientAgent: ambientAgent, settingsStore: services.settingsStore, windowState: windowState, onMicrophoneToggle: onMicrophoneToggle ?? {}))

let screenFrame = NSScreen.main?.visibleFrame ?? NSScreen.screens.first?.visibleFrame ?? NSRect(x: 0, y: 0, width: 1440, height: 900)
let windowWidth = min(screenFrame.width * 0.8, 1200)
let windowHeight = min(screenFrame.height * 0.85, 900)
let windowWidth: CGFloat = 780
let windowHeight: CGFloat = 700
let windowRect = NSRect(
x: screenFrame.midX - windowWidth / 2,
y: screenFrame.midY - windowHeight / 2,
Expand All @@ -107,7 +107,7 @@ final class MainWindow {
window.titlebarAppearsTransparent = true
window.backgroundColor = NSColor(VColor.background)
window.isReleasedWhenClosed = false
window.contentMinSize = NSSize(width: 800, height: 600)
window.contentMinSize = NSSize(width: 500, height: 400)
Comment thread
AnitaKirkovska marked this conversation as resolved.
window.setFrame(windowRect, display: false)
window.setFrameAutosaveName("MainWindow")

Expand Down
Loading