Small feature changes and bug fixes

This commit is contained in:
2026-02-16 13:17:08 +01:00
parent 04c9b8da1e
commit 25bcca213e
20 changed files with 2193 additions and 125 deletions

View File

@@ -32,7 +32,7 @@ struct ChatView: View {
ScrollView {
LazyVStack(alignment: .leading, spacing: 12) {
ForEach(viewModel.messages) { message in
MessageRow(message: message)
MessageRow(message: message, viewModel: viewModel)
.id(message.id)
}

View File

@@ -60,7 +60,7 @@ struct ContentView: View {
.sheet(isPresented: $vm.showSettings, onDismiss: {
chatViewModel.syncFromSettings()
}) {
SettingsView()
SettingsView(chatViewModel: chatViewModel)
}
.sheet(isPresented: $vm.showStats) {
StatsView(

View File

@@ -84,6 +84,7 @@ struct FooterItem: View {
struct SyncStatusFooter: View {
private let gitSync = GitSyncService.shared
private let settings = SettingsService.shared
private let guiSize = SettingsService.shared.guiTextSize
@State private var syncText = "Not Synced"
@State private var syncColor: Color = .secondary
@@ -104,17 +105,23 @@ struct SyncStatusFooter: View {
.onChange(of: gitSync.syncStatus.lastSyncTime) {
updateSyncStatus()
}
.onChange(of: gitSync.syncStatus.isCloned) {
updateSyncStatus()
}
.onChange(of: gitSync.lastSyncError) {
updateSyncStatus()
}
.onChange(of: gitSync.isSyncing) {
updateSyncStatus()
}
.onChange(of: settings.syncConfigured) {
updateSyncStatus()
}
}
private func updateSyncStatus() {
if let error = gitSync.lastSyncError {
syncText = "Error With Sync"
syncText = "Sync Error"
syncColor = .red
} else if gitSync.isSyncing {
syncText = "Syncing..."
@@ -123,10 +130,13 @@ struct SyncStatusFooter: View {
syncText = "Last Sync: \(timeAgo(lastSync))"
syncColor = .green
} else if gitSync.syncStatus.isCloned {
syncText = "Not Synced"
syncText = "Sync: Ready"
syncColor = .secondary
} else if settings.syncConfigured {
syncText = "Sync: Not Initialized"
syncColor = .orange
} else {
syncText = "Not Configured"
syncText = "Sync: Off"
syncColor = .secondary
}
}

View File

@@ -12,13 +12,20 @@ import AppKit
struct MessageRow: View {
let message: Message
let viewModel: ChatViewModel?
private let settings = SettingsService.shared
#if os(macOS)
@State private var isHovering = false
@State private var showCopied = false
@State private var isStarred = false
#endif
init(message: Message, viewModel: ChatViewModel? = nil) {
self.message = message
self.viewModel = viewModel
}
var body: some View {
// Compact layout for system messages (tool calls)
if message.role == .system && !isErrorMessage {
@@ -45,6 +52,18 @@ struct MessageRow: View {
Spacer()
#if os(macOS)
// Star button (user/assistant messages only, visible on hover)
if (message.role == .user || message.role == .assistant) && isHovering {
Button(action: toggleStar) {
Image(systemName: isStarred ? "star.fill" : "star")
.font(.system(size: 11))
.foregroundColor(isStarred ? .yellow : .oaiSecondary)
}
.buttonStyle(.plain)
.transition(.opacity)
.help("Star this message to always include it in context")
}
// Copy button (assistant messages only, visible on hover)
if message.role == .assistant && isHovering && !message.content.isEmpty {
Button(action: copyContent) {
@@ -138,6 +157,9 @@ struct MessageRow: View {
isHovering = hovering
}
}
.onAppear {
loadStarredState()
}
#endif
}
@@ -235,6 +257,17 @@ struct MessageRow: View {
}
}
}
private func loadStarredState() {
if let metadata = try? DatabaseService.shared.getMessageMetadata(messageId: message.id) {
isStarred = metadata.user_starred == 1
}
}
private func toggleStar() {
viewModel?.toggleMessageStar(messageId: message.id)
isStarred.toggle()
}
#endif
private var roleIcon: some View {