Skip to content

Commit 8150253

Browse files
committed
Add chat menu
1 parent 348c8fa commit 8150253

File tree

3 files changed

+102
-2
lines changed

3 files changed

+102
-2
lines changed

Core/Sources/Service/GUI/ChatProvider+Service.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import ChatService
2+
import Combine
23
import Foundation
34
import OpenAIService
45
import SuggestionWidget
@@ -11,6 +12,7 @@ extension ChatProvider {
1112
onSwitchContext: @escaping () -> Void
1213
) {
1314
self.init()
15+
1416
let cancellable = service.objectWillChange.sink { [weak self] in
1517
guard let self else { return }
1618
Task { @MainActor in
@@ -22,6 +24,8 @@ extension ChatProvider {
2224
)
2325
}
2426
self.isReceivingMessage = await service.chatGPTService.isReceivingMessage
27+
self.systemPrompt = service.systemPrompt
28+
self.extraSystemPrompt = service.extraSystemPrompt
2529
}
2630
}
2731

@@ -75,5 +79,19 @@ extension ChatProvider {
7579
}
7680
}
7781
}
82+
83+
onResetPrompt = {
84+
Task {
85+
await service.resetPrompt()
86+
}
87+
}
88+
89+
onRunCustomCommand = { command in
90+
Task {
91+
let commandHandler = PseudoCommandHandler()
92+
await commandHandler.handleCustomCommand(command)
93+
}
94+
}
7895
}
7996
}
97+

Core/Sources/SuggestionWidget/ChatProvider.swift

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import Foundation
2+
import Preferences
23
import SwiftUI
34

45
public final class ChatProvider: ObservableObject {
56
let id = UUID()
67
@Published public var history: [ChatMessage] = []
78
@Published public var isReceivingMessage = false
9+
public var systemPrompt = ""
10+
public var extraSystemPrompt = ""
811
public var onMessageSend: (String) -> Void
912
public var onStop: () -> Void
1013
public var onClear: () -> Void
1114
public var onClose: () -> Void
1215
public var onSwitchContext: () -> Void
1316
public var onDeleteMessage: (String) -> Void
1417
public var onResendMessage: (String) -> Void
18+
public var onResetPrompt: () -> Void
19+
public var onRunCustomCommand: (CustomCommand) -> Void = { _ in }
1520

1621
public init(
1722
history: [ChatMessage] = [],
@@ -22,7 +27,9 @@ public final class ChatProvider: ObservableObject {
2227
onClose: @escaping () -> Void = {},
2328
onSwitchContext: @escaping () -> Void = {},
2429
onDeleteMessage: @escaping (String) -> Void = { _ in },
25-
onResendMessage: @escaping (String) -> Void = { _ in }
30+
onResendMessage: @escaping (String) -> Void = { _ in },
31+
onResetPrompt: @escaping () -> Void = {},
32+
onRunCustomCommand: @escaping (CustomCommand) -> Void = { _ in }
2633
) {
2734
self.history = history
2835
self.isReceivingMessage = isReceivingMessage
@@ -33,6 +40,8 @@ public final class ChatProvider: ObservableObject {
3340
self.onSwitchContext = onSwitchContext
3441
self.onDeleteMessage = onDeleteMessage
3542
self.onResendMessage = onResendMessage
43+
self.onResetPrompt = onResetPrompt
44+
self.onRunCustomCommand = onRunCustomCommand
3645
}
3746

3847
public func send(_ message: String) { onMessageSend(message) }
@@ -42,6 +51,10 @@ public final class ChatProvider: ObservableObject {
4251
public func switchContext() { onSwitchContext() }
4352
public func deleteMessage(id: String) { onDeleteMessage(id) }
4453
public func resendMessage(id: String) { onResendMessage(id) }
54+
public func resetPrompt() { onResetPrompt() }
55+
public func triggerCustomCommand(_ command: CustomCommand) {
56+
onRunCustomCommand(command)
57+
}
4558
}
4659

4760
public struct ChatMessage: Equatable {
@@ -55,3 +68,4 @@ public struct ChatMessage: Equatable {
5568
self.text = text
5669
}
5770
}
71+

Core/Sources/SuggestionWidget/SuggestionPanelContent/ChatPanel.swift

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ struct ChatPanelInputArea: View {
258258
}
259259
.padding(8)
260260
.background(.ultraThickMaterial)
261+
.contextMenu {
262+
ChatContextMenu(chat: chat)
263+
}
261264
}
262265

263266
var clearButton: some View {
@@ -342,6 +345,71 @@ struct ChatPanelInputArea: View {
342345
}
343346
}
344347

348+
struct ChatContextMenu: View {
349+
let chat: ChatProvider
350+
@AppStorage(\.customCommands) var customCommands
351+
352+
var body: some View {
353+
Group {
354+
currentSystemPrompt
355+
currentExtraSystemPrompt
356+
resetPrompt
357+
358+
Divider()
359+
360+
customCommandMenu
361+
}
362+
}
363+
364+
@ViewBuilder
365+
var currentSystemPrompt: some View {
366+
Text("System Prompt:")
367+
Text({
368+
var text = chat.systemPrompt
369+
if text.isEmpty { text = "N/A" }
370+
if text.count > 30 { text = String(text.prefix(30)) + "..." }
371+
return text
372+
}() as String)
373+
}
374+
375+
@ViewBuilder
376+
var currentExtraSystemPrompt: some View {
377+
Text("Extra Prompt:")
378+
Text({
379+
var text = chat.extraSystemPrompt
380+
if text.isEmpty { text = "N/A" }
381+
if text.count > 30 { text = String(text.prefix(30)) + "..." }
382+
return text
383+
}() as String)
384+
}
385+
386+
var resetPrompt: some View {
387+
Button("Reset System Prompt") {
388+
chat.resetPrompt()
389+
}
390+
}
391+
392+
var customCommandMenu: some View {
393+
Menu("Custom Commands") {
394+
ForEach(
395+
customCommands.filter {
396+
switch $0.feature {
397+
case .chatWithSelection, .customChat: return true
398+
case .promptToCode: return false
399+
}
400+
},
401+
id: \.name
402+
) { command in
403+
Button(action: {
404+
chat.triggerCustomCommand(command)
405+
}) {
406+
Text(command.name)
407+
}
408+
}
409+
}
410+
}
411+
}
412+
345413
struct RoundedCorners: Shape {
346414
var tl: CGFloat = 0.0
347415
var tr: CGFloat = 0.0
@@ -403,7 +471,7 @@ struct GlobalChatSwitchToggleStyle: ToggleStyle {
403471
HStack(spacing: 4) {
404472
Text(configuration.isOn ? "Shared Conversation" : "Local Conversation")
405473
.foregroundStyle(.tertiary)
406-
474+
407475
RoundedRectangle(cornerRadius: 10, style: .circular)
408476
.foregroundColor(configuration.isOn ? Color.indigo : .gray.opacity(0.5))
409477
.frame(width: 30, height: 20, alignment: .center)

0 commit comments

Comments
 (0)