Skip to content

Commit aac293e

Browse files
committed
Break ChatPanel.swift into multiple files
1 parent ba592c2 commit aac293e

File tree

6 files changed

+453
-320
lines changed

6 files changed

+453
-320
lines changed

Core/Sources/ChatGPTChatTab/ChatPanel.swift

Lines changed: 0 additions & 315 deletions
Original file line numberDiff line numberDiff line change
@@ -294,265 +294,6 @@ private struct StopRespondingButton: View {
294294
}
295295
}
296296

297-
private struct Instruction: View {
298-
let chat: StoreOf<Chat>
299-
300-
var body: some View {
301-
Group {
302-
Markdown(
303-
"""
304-
You can use plugins to perform various tasks.
305-
306-
| Plugin Name | Description |
307-
| --- | --- |
308-
| `/run` | Runs a command under the project root |
309-
| `/math` | Solves a math problem in natural language |
310-
| `/search` | Searches on Bing and summarizes the results |
311-
| `/shortcut(name)` | Runs a shortcut from the Shortcuts.app, with the previous message as input |
312-
| `/shortcutInput(name)` | Runs a shortcut and uses its result as a new message |
313-
314-
To use plugins, you can prefix a message with `/pluginName`.
315-
"""
316-
)
317-
.modifier(InstructionModifier())
318-
319-
Markdown(
320-
"""
321-
You can use scopes to give the bot extra abilities.
322-
323-
| Scope Name | Abilities |
324-
| --- | --- |
325-
| `@file` | Read the metadata of the editing file |
326-
| `@code` | Read the code and metadata in the editing file |
327-
| `@sense`| Experimental. Read the relevant code of the focused editor |
328-
| `@project` | Experimental. Access content of the project |
329-
| `@web` (beta) | Search on Bing or query from a web page |
330-
331-
To use scopes, you can prefix a message with `@code`.
332-
333-
You can use shorthand to represent a scope, such as `@c`, and enable multiple scopes with `@c+web`.
334-
"""
335-
)
336-
.modifier(InstructionModifier())
337-
338-
WithViewStore(chat, observe: \.chatMenu.defaultScopes) { viewStore in
339-
Markdown(
340-
"""
341-
Hello, I am your AI programming assistant. I can identify issues, explain and even improve code.
342-
343-
\({
344-
if viewStore.state.isEmpty {
345-
return "No scope is enabled by default"
346-
} else {
347-
let scopes = viewStore.state.map(\.rawValue).sorted()
348-
.joined(separator: ", ")
349-
return "Default scopes: `\(scopes)`"
350-
}
351-
}())
352-
"""
353-
)
354-
.modifier(InstructionModifier())
355-
}
356-
}
357-
}
358-
359-
struct InstructionModifier: ViewModifier {
360-
@AppStorage(\.chatFontSize) var chatFontSize
361-
362-
func body(content: Content) -> some View {
363-
content
364-
.textSelection(.enabled)
365-
.markdownTheme(.custom(fontSize: chatFontSize))
366-
.opacity(0.8)
367-
.frame(maxWidth: .infinity, alignment: .leading)
368-
.padding()
369-
.overlay {
370-
RoundedRectangle(cornerRadius: 8)
371-
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
372-
}
373-
}
374-
}
375-
}
376-
377-
private struct UserMessage: View {
378-
let id: String
379-
let text: String
380-
let chat: StoreOf<Chat>
381-
@Environment(\.colorScheme) var colorScheme
382-
@AppStorage(\.chatFontSize) var chatFontSize
383-
@AppStorage(\.chatCodeFontSize) var chatCodeFontSize
384-
385-
var body: some View {
386-
Markdown(text)
387-
.textSelection(.enabled)
388-
.markdownTheme(.custom(fontSize: chatFontSize))
389-
.markdownCodeSyntaxHighlighter(
390-
ChatCodeSyntaxHighlighter(
391-
brightMode: colorScheme != .dark,
392-
fontSize: chatCodeFontSize
393-
)
394-
)
395-
.frame(alignment: .leading)
396-
.padding()
397-
.background {
398-
RoundedCorners(tl: r, tr: r, bl: r, br: 0)
399-
.fill(Color.userChatContentBackground)
400-
}
401-
.overlay {
402-
RoundedCorners(tl: r, tr: r, bl: r, br: 0)
403-
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
404-
}
405-
.padding(.leading)
406-
.padding(.trailing, 8)
407-
.shadow(color: .black.opacity(0.1), radius: 2)
408-
.frame(maxWidth: .infinity, alignment: .trailing)
409-
.contextMenu {
410-
Button("Copy") {
411-
NSPasteboard.general.clearContents()
412-
NSPasteboard.general.setString(text, forType: .string)
413-
}
414-
415-
Button("Send Again") {
416-
chat.send(.resendMessageButtonTapped(id))
417-
}
418-
419-
Button("Set as Extra System Prompt") {
420-
chat.send(.setAsExtraPromptButtonTapped(id))
421-
}
422-
423-
Divider()
424-
425-
Button("Delete") {
426-
chat.send(.deleteMessageButtonTapped(id))
427-
}
428-
}
429-
}
430-
}
431-
432-
private struct BotMessage: View {
433-
let id: String
434-
let text: String
435-
let references: [DisplayedChatMessage.Reference]
436-
let chat: StoreOf<Chat>
437-
@Environment(\.colorScheme) var colorScheme
438-
@AppStorage(\.chatFontSize) var chatFontSize
439-
@AppStorage(\.chatCodeFontSize) var chatCodeFontSize
440-
441-
@State var isReferencesPresented = false
442-
@State var isReferencesHovered = false
443-
444-
var body: some View {
445-
HStack(alignment: .bottom, spacing: 2) {
446-
VStack(alignment: .leading, spacing: 16) {
447-
if !references.isEmpty {
448-
Button(action: {
449-
isReferencesPresented.toggle()
450-
}, label: {
451-
HStack(spacing: 4) {
452-
Image(systemName: "plus.circle")
453-
Text("Used \(references.count) references")
454-
}
455-
.padding(8)
456-
.background {
457-
RoundedRectangle(cornerRadius: r - 4)
458-
.foregroundStyle(Color(isReferencesHovered ? .black : .clear))
459-
460-
}
461-
.overlay {
462-
RoundedRectangle(cornerRadius: r - 4)
463-
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
464-
}
465-
.foregroundStyle(.secondary)
466-
})
467-
.buttonStyle(.plain)
468-
.popover(isPresented: $isReferencesPresented, arrowEdge: .trailing) {
469-
ReferenceList(references: references)
470-
}
471-
}
472-
473-
Markdown(text)
474-
.textSelection(.enabled)
475-
.markdownTheme(.custom(fontSize: chatFontSize))
476-
.markdownCodeSyntaxHighlighter(
477-
ChatCodeSyntaxHighlighter(
478-
brightMode: colorScheme != .dark,
479-
fontSize: chatCodeFontSize
480-
)
481-
)
482-
}
483-
.frame(alignment: .trailing)
484-
.padding()
485-
.background {
486-
RoundedCorners(tl: r, tr: r, bl: 0, br: r)
487-
.fill(Color.contentBackground)
488-
}
489-
.overlay {
490-
RoundedCorners(tl: r, tr: r, bl: 0, br: r)
491-
.stroke(Color(nsColor: .separatorColor), lineWidth: 1)
492-
}
493-
.padding(.leading, 8)
494-
.shadow(color: .black.opacity(0.1), radius: 2)
495-
.contextMenu {
496-
Button("Copy") {
497-
NSPasteboard.general.clearContents()
498-
NSPasteboard.general.setString(text, forType: .string)
499-
}
500-
501-
Button("Set as Extra System Prompt") {
502-
chat.send(.setAsExtraPromptButtonTapped(id))
503-
}
504-
505-
Divider()
506-
507-
Button("Delete") {
508-
chat.send(.deleteMessageButtonTapped(id))
509-
}
510-
}
511-
512-
CopyButton {
513-
NSPasteboard.general.clearContents()
514-
NSPasteboard.general.setString(text, forType: .string)
515-
}
516-
}
517-
.frame(maxWidth: .infinity, alignment: .leading)
518-
.padding(.trailing, 2)
519-
}
520-
}
521-
522-
struct ReferenceList: View {
523-
let references: [DisplayedChatMessage.Reference]
524-
var body: some View {
525-
ScrollView {
526-
VStack {
527-
ForEach(0..<references.endIndex, id: \.self) { index in
528-
let reference = references[index]
529-
HStack(spacing: 8) {
530-
Text(reference.title)
531-
Text(reference.subtitle)
532-
.foregroundStyle(.secondary)
533-
}
534-
}
535-
}
536-
.padding()
537-
.frame(maxHeight: 500)
538-
}
539-
}
540-
}
541-
542-
struct FunctionMessage: View {
543-
let id: String
544-
let text: String
545-
@AppStorage(\.chatFontSize) var chatFontSize
546-
547-
var body: some View {
548-
Markdown(text)
549-
.textSelection(.enabled)
550-
.markdownTheme(.functionCall(fontSize: chatFontSize))
551-
.padding(.vertical, 2)
552-
.padding(.trailing, 2)
553-
}
554-
}
555-
556297
struct ChatPanelInputArea: View {
557298
let chat: StoreOf<Chat>
558299
@FocusState var focusedField: Chat.State.Field?
@@ -675,62 +416,6 @@ struct ChatPanelInputArea: View {
675416
}
676417
}
677418

678-
struct RoundedCorners: Shape {
679-
var tl: CGFloat = 0.0
680-
var tr: CGFloat = 0.0
681-
var bl: CGFloat = 0.0
682-
var br: CGFloat = 0.0
683-
684-
func path(in rect: CGRect) -> Path {
685-
Path { path in
686-
687-
let w = rect.size.width
688-
let h = rect.size.height
689-
690-
// Make sure we do not exceed the size of the rectangle
691-
let tr = min(min(self.tr, h / 2), w / 2)
692-
let tl = min(min(self.tl, h / 2), w / 2)
693-
let bl = min(min(self.bl, h / 2), w / 2)
694-
let br = min(min(self.br, h / 2), w / 2)
695-
696-
path.move(to: CGPoint(x: w / 2.0, y: 0))
697-
path.addLine(to: CGPoint(x: w - tr, y: 0))
698-
path.addArc(
699-
center: CGPoint(x: w - tr, y: tr),
700-
radius: tr,
701-
startAngle: Angle(degrees: -90),
702-
endAngle: Angle(degrees: 0),
703-
clockwise: false
704-
)
705-
path.addLine(to: CGPoint(x: w, y: h - br))
706-
path.addArc(
707-
center: CGPoint(x: w - br, y: h - br),
708-
radius: br,
709-
startAngle: Angle(degrees: 0),
710-
endAngle: Angle(degrees: 90),
711-
clockwise: false
712-
)
713-
path.addLine(to: CGPoint(x: bl, y: h))
714-
path.addArc(
715-
center: CGPoint(x: bl, y: h - bl),
716-
radius: bl,
717-
startAngle: Angle(degrees: 90),
718-
endAngle: Angle(degrees: 180),
719-
clockwise: false
720-
)
721-
path.addLine(to: CGPoint(x: 0, y: tl))
722-
path.addArc(
723-
center: CGPoint(x: tl, y: tl),
724-
radius: tl,
725-
startAngle: Angle(degrees: 180),
726-
endAngle: Angle(degrees: 270),
727-
clockwise: false
728-
)
729-
path.closeSubpath()
730-
}
731-
}
732-
}
733-
734419
// MARK: - Previews
735420

736421
struct ChatPanel_Preview: PreviewProvider {

0 commit comments

Comments
 (0)