Skip to content

Commit 6b5ac69

Browse files
committed
Migrate ChatGPTChatTab to latest TCA
1 parent 50171ac commit 6b5ac69

7 files changed

Lines changed: 402 additions & 374 deletions

File tree

Core/Sources/ChatGPTChatTab/Chat.swift

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,18 @@ private var isPreview: Bool {
5454
ProcessInfo.processInfo.environment["XCODE_RUNNING_FOR_PREVIEWS"] == "1"
5555
}
5656

57-
struct Chat: ReducerProtocol {
57+
@Reducer
58+
struct Chat {
5859
public typealias MessageID = String
5960

61+
@ObservableState
6062
struct State: Equatable {
6163
var title: String = "Chat"
62-
@BindingState var typedMessage = ""
64+
var typedMessage = ""
6365
var history: [DisplayedChatMessage] = []
64-
@BindingState var isReceivingMessage = false
66+
var isReceivingMessage = false
6567
var chatMenu = ChatMenu.State()
66-
@BindingState var focusedField: Field?
68+
var focusedField: Field?
6769

6870
enum Field: String, Hashable {
6971
case textField
@@ -115,7 +117,7 @@ struct Chat: ReducerProtocol {
115117

116118
@Dependency(\.openURL) var openURL
117119

118-
var body: some ReducerProtocol<State, Action> {
120+
var body: some ReducerOf<Self> {
119121
BindingReducer()
120122

121123
Scope(state: \.chatMenu, action: /Action.chatMenu) {
@@ -387,7 +389,9 @@ struct Chat: ReducerProtocol {
387389
}
388390
}
389391

390-
struct ChatMenu: ReducerProtocol {
392+
@Reducer
393+
struct ChatMenu {
394+
@ObservableState
391395
struct State: Equatable {
392396
var systemPrompt: String = ""
393397
var extraSystemPrompt: String = ""
@@ -409,7 +413,7 @@ struct ChatMenu: ReducerProtocol {
409413

410414
let service: ChatService
411415

412-
var body: some ReducerProtocol<State, Action> {
416+
var body: some ReducerOf<Self> {
413417
Reduce { state, action in
414418
switch action {
415419
case .appear:

Core/Sources/ChatGPTChatTab/ChatContextMenu.swift

Lines changed: 77 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ struct ChatTabItemView: View {
88
let chat: StoreOf<Chat>
99

1010
var body: some View {
11-
WithViewStore(chat, observe: \.title) { viewStore in
12-
Text(viewStore.state)
11+
WithPerceptionTracking {
12+
Text(chat.title)
1313
}
1414
}
1515
}
@@ -22,46 +22,44 @@ struct ChatContextMenu: View {
2222
@AppStorage(\.chatGPTTemperature) var defaultTemperature
2323

2424
var body: some View {
25-
currentSystemPrompt
26-
.onAppear { store.send(.appear) }
27-
currentExtraSystemPrompt
28-
resetPrompt
25+
WithPerceptionTracking {
26+
currentSystemPrompt
27+
.onAppear { store.send(.appear) }
28+
currentExtraSystemPrompt
29+
resetPrompt
2930

30-
Divider()
31+
Divider()
3132

32-
chatModel
33-
temperature
34-
defaultScopes
33+
chatModel
34+
temperature
35+
defaultScopes
3536

36-
Divider()
37+
Divider()
3738

38-
customCommandMenu
39+
customCommandMenu
40+
}
3941
}
4042

4143
@ViewBuilder
4244
var currentSystemPrompt: some View {
4345
Text("System Prompt:")
44-
WithViewStore(store, observe: \.systemPrompt) { viewStore in
45-
Text({
46-
var text = viewStore.state
47-
if text.isEmpty { text = "N/A" }
48-
if text.count > 30 { text = String(text.prefix(30)) + "..." }
49-
return text
50-
}() as String)
51-
}
46+
Text({
47+
var text = store.systemPrompt
48+
if text.isEmpty { text = "N/A" }
49+
if text.count > 30 { text = String(text.prefix(30)) + "..." }
50+
return text
51+
}() as String)
5252
}
5353

5454
@ViewBuilder
5555
var currentExtraSystemPrompt: some View {
5656
Text("Extra Prompt:")
57-
WithViewStore(store, observe: \.extraSystemPrompt) { viewStore in
58-
Text({
59-
var text = viewStore.state
60-
if text.isEmpty { text = "N/A" }
61-
if text.count > 30 { text = String(text.prefix(30)) + "..." }
62-
return text
63-
}() as String)
64-
}
57+
Text({
58+
var text = store.extraSystemPrompt
59+
if text.isEmpty { text = "N/A" }
60+
if text.count > 30 { text = String(text.prefix(30)) + "..." }
61+
return text
62+
}() as String)
6563
}
6664

6765
var resetPrompt: some View {
@@ -73,46 +71,44 @@ struct ChatContextMenu: View {
7371
@ViewBuilder
7472
var chatModel: some View {
7573
Menu("Chat Model") {
76-
WithViewStore(store, observe: \.chatModelIdOverride) { viewStore in
77-
Button(action: {
78-
viewStore.send(.chatModelIdOverrideSelected(nil))
79-
}) {
80-
HStack {
81-
if let defaultModel = chatModels
82-
.first(where: { $0.id == defaultChatModelId })
83-
{
84-
Text("Default (\(defaultModel.name))")
85-
if viewStore.state == nil {
86-
Image(systemName: "checkmark")
87-
}
88-
} else {
89-
Text("No Model Available")
74+
Button(action: {
75+
store.send(.chatModelIdOverrideSelected(nil))
76+
}) {
77+
HStack {
78+
if let defaultModel = chatModels
79+
.first(where: { $0.id == defaultChatModelId })
80+
{
81+
Text("Default (\(defaultModel.name))")
82+
if store.chatModelIdOverride == nil {
83+
Image(systemName: "checkmark")
9084
}
85+
} else {
86+
Text("No Model Available")
9187
}
9288
}
89+
}
9390

94-
if let id = viewStore.state, !chatModels.map(\.id).contains(id) {
95-
Button(action: {
96-
viewStore.send(.chatModelIdOverrideSelected(nil))
97-
}) {
98-
HStack {
99-
Text("Default (Selected Model Not Found)")
100-
Image(systemName: "checkmark")
101-
}
91+
if let id = store.chatModelIdOverride, !chatModels.map(\.id).contains(id) {
92+
Button(action: {
93+
store.send(.chatModelIdOverrideSelected(nil))
94+
}) {
95+
HStack {
96+
Text("Default (Selected Model Not Found)")
97+
Image(systemName: "checkmark")
10298
}
10399
}
100+
}
104101

105-
Divider()
102+
Divider()
106103

107-
ForEach(chatModels, id: \.id) { model in
108-
Button(action: {
109-
viewStore.send(.chatModelIdOverrideSelected(model.id))
110-
}) {
111-
HStack {
112-
Text(model.name)
113-
if model.id == viewStore.state {
114-
Image(systemName: "checkmark")
115-
}
104+
ForEach(chatModels, id: \.id) { model in
105+
Button(action: {
106+
store.send(.chatModelIdOverrideSelected(model.id))
107+
}) {
108+
HStack {
109+
Text(model.name)
110+
if model.id == store.chatModelIdOverride {
111+
Image(systemName: "checkmark")
116112
}
117113
}
118114
}
@@ -123,31 +119,29 @@ struct ChatContextMenu: View {
123119
@ViewBuilder
124120
var temperature: some View {
125121
Menu("Temperature") {
126-
WithViewStore(store, observe: \.temperatureOverride) { viewStore in
127-
Button(action: {
128-
viewStore.send(.temperatureOverrideSelected(nil))
129-
}) {
130-
HStack {
131-
Text(
132-
"Default (\(defaultTemperature.formatted(.number.precision(.fractionLength(1)))))"
133-
)
134-
if viewStore.state == nil {
135-
Image(systemName: "checkmark")
136-
}
122+
Button(action: {
123+
store.send(.temperatureOverrideSelected(nil))
124+
}) {
125+
HStack {
126+
Text(
127+
"Default (\(defaultTemperature.formatted(.number.precision(.fractionLength(1)))))"
128+
)
129+
if store.temperatureOverride == nil {
130+
Image(systemName: "checkmark")
137131
}
138132
}
133+
}
139134

140-
Divider()
135+
Divider()
141136

142-
ForEach(Array(stride(from: 0.0, through: 2.0, by: 0.1)), id: \.self) { value in
143-
Button(action: {
144-
viewStore.send(.temperatureOverrideSelected(value))
145-
}) {
146-
HStack {
147-
Text("\(value.formatted(.number.precision(.fractionLength(1))))")
148-
if value == viewStore.state {
149-
Image(systemName: "checkmark")
150-
}
137+
ForEach(Array(stride(from: 0.0, through: 2.0, by: 0.1)), id: \.self) { value in
138+
Button(action: {
139+
store.send(.temperatureOverrideSelected(value))
140+
}) {
141+
HStack {
142+
Text("\(value.formatted(.number.precision(.fractionLength(1))))")
143+
if value == store.temperatureOverride {
144+
Image(systemName: "checkmark")
151145
}
152146
}
153147
}
@@ -158,7 +152,6 @@ struct ChatContextMenu: View {
158152
@ViewBuilder
159153
var defaultScopes: some View {
160154
Menu("Default Scopes") {
161-
WithViewStore(store, observe: \.defaultScopes) { viewStore in
162155
Button(action: {
163156
store.send(.resetDefaultScopesButtonTapped)
164157
}) {
@@ -169,17 +162,16 @@ struct ChatContextMenu: View {
169162

170163
ForEach(ChatService.Scope.allCases, id: \.rawValue) { value in
171164
Button(action: {
172-
viewStore.send(.toggleScope(value))
165+
store.send(.toggleScope(value))
173166
}) {
174167
HStack {
175168
Text("@" + value.rawValue)
176-
if viewStore.state.contains(value) {
169+
if store.defaultScopes.contains(value) {
177170
Image(systemName: "checkmark")
178171
}
179172
}
180173
}
181174
}
182-
}
183175
}
184176
}
185177

0 commit comments

Comments
 (0)