forked from intitni/CopilotForXcode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathChatTab.swift
More file actions
100 lines (84 loc) · 2.4 KB
/
ChatTab.swift
File metadata and controls
100 lines (84 loc) · 2.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import ComposableArchitecture
import Foundation
import SwiftUI
public struct ChatTabInfo: Identifiable, Equatable {
public var id: String
public var title: String
public init(id: String, title: String) {
self.id = id
self.title = title
}
}
public struct ChatTabInfoPreferenceKey: PreferenceKey {
public static var defaultValue: [ChatTabInfo] = []
public static func reduce(value: inout [ChatTabInfo], nextValue: () -> [ChatTabInfo]) {
value.append(contentsOf: nextValue())
}
}
/// Every chat tab should conform to this type.
public typealias ChatTab = BaseChatTab & ChatTabType
open class BaseChatTab: Equatable {
final class InfoObservable: ObservableObject {
@Published var id: String
@Published var title: String
init(id: String, title: String) {
self.title = title
self.id = id
}
}
struct ContentView: View {
@ObservedObject var info: InfoObservable
var buildView: () -> any View
var body: some View {
AnyView(buildView())
.preference(
key: ChatTabInfoPreferenceKey.self,
value: [ChatTabInfo(
id: info.id,
title: info.title
)]
)
}
}
public let id: String
public var title: String {
didSet { info.title = title }
}
let info: InfoObservable
public init(id: String, title: String) {
self.id = id
self.title = title
info = InfoObservable(id: id, title: title)
}
@ViewBuilder
public var body: some View {
let id = "BaseChatTab\(info.id)"
if let tab = self as? ChatTabType {
ContentView(info: info, buildView: tab.buildView).id(id)
} else {
EmptyView().id(id)
}
}
@ViewBuilder
public var menu: some View {
EmptyView()
}
public static func == (lhs: BaseChatTab, rhs: BaseChatTab) -> Bool {
lhs.id == rhs.id
}
}
public protocol ChatTabType {
@ViewBuilder
func buildView() -> any View
}
public class EmptyChatTab: ChatTab {
public func buildView() -> any View {
VStack {
Text("Empty-\(id)")
}
.background(Color.blue)
}
public init(id: String = UUID().uuidString) {
super.init(id: id, title: "Empty")
}
}