11import AppKit
2- import OpenAIService
32import Client
3+ import OpenAIService
44import Preferences
55import SuggestionModel
66import SwiftUI
77
8- final class OpenAIViewSettings : ObservableObject {
9- static let availableLocalizedLocales = Locale . availableLocalizedLocales
10- @AppStorage ( \. openAIAPIKey) var openAIAPIKey : String
11- @AppStorage ( \. chatGPTModel) var chatGPTModel : String
12- @AppStorage ( \. openAIBaseURL) var openAIBaseURL : String
13- @AppStorage ( \. chatGPTLanguage) var chatGPTLanguage : String
14- @AppStorage ( \. chatGPTMaxToken) var chatGPTMaxToken : Int
15- @AppStorage ( \. chatGPTTemperature) var chatGPTTemperature : Double
16- @AppStorage ( \. chatGPTMaxMessageCount) var chatGPTMaxMessageCount : Int
17- init ( ) { }
18- }
19-
208struct OpenAIView : View {
9+ final class Settings : ObservableObject {
10+ @AppStorage ( \. openAIAPIKey) var openAIAPIKey : String
11+ @AppStorage ( \. chatGPTModel) var chatGPTModel : String
12+ @AppStorage ( \. openAIBaseURL) var openAIBaseURL : String
13+ init ( ) { }
14+ }
15+
2116 let apiKeyURL = URL ( string: " https://platform.openai.com/account/api-keys " ) !
2217 let modelURL = URL (
2318 string: " https://platform.openai.com/docs/models/model-endpoint-compatibility "
2419 ) !
2520 @Environment ( \. openURL) var openURL
2621 @Environment ( \. toast) var toast
27- @StateObject var settings = OpenAIViewSettings ( )
28- @State var maxTokenOverLimit = false
22+ @State var isTesting = false
23+ @StateObject var settings = Settings ( )
2924
3025 var body : some View {
3126 Form {
@@ -50,7 +45,9 @@ struct OpenAIView: View {
5045 } . textFieldStyle ( . roundedBorder)
5146
5247 Button ( " Test " ) {
53- Task {
48+ Task { @MainActor in
49+ isTesting = true
50+ defer { isTesting = false }
5451 do {
5552 let reply = try await ChatGPTService ( designatedProvider: . openAI)
5653 . sendAndWait ( content: " Hello " , summary: nil )
@@ -59,7 +56,7 @@ struct OpenAIView: View {
5956 toast ( Text ( error. localizedDescription) , . error)
6057 }
6158 }
62- }
59+ } . disabled ( isTesting )
6360 }
6461
6562 HStack {
@@ -81,119 +78,6 @@ struct OpenAIView: View {
8178 Image ( systemName: " questionmark.circle.fill " )
8279 } . buttonStyle ( . plain)
8380 }
84-
85- if #available( macOS 13 . 0 , * ) {
86- LabeledContent ( " Reply in Language " ) {
87- languagePicker
88- }
89- } else {
90- HStack {
91- Text ( " Reply in Language " )
92- languagePicker
93- }
94- }
95-
96- let binding = Binding (
97- get: { String ( settings. chatGPTMaxToken) } ,
98- set: {
99- if let selectionMaxToken = Int ( $0) {
100- if let model = ChatGPTModel ( rawValue: settings. chatGPTModel) {
101- maxTokenOverLimit = model. maxToken < selectionMaxToken
102- } else {
103- maxTokenOverLimit = false
104- }
105- settings. chatGPTMaxToken = selectionMaxToken
106- } else {
107- settings. chatGPTMaxToken = 0
108- }
109- }
110- )
111- HStack {
112- Stepper (
113- value: $settings. chatGPTMaxToken,
114- in: 0 ... Int . max,
115- step: 1
116- ) {
117- Text ( " Max Token (Including Reply) " )
118- . multilineTextAlignment ( . trailing)
119- }
120- TextField ( text: binding) {
121- EmptyView ( )
122- }
123- . labelsHidden ( )
124- . textFieldStyle ( . roundedBorder)
125- . foregroundColor ( maxTokenOverLimit ? . red : . primary)
126-
127- if let model = ChatGPTModel ( rawValue: settings. chatGPTModel) {
128- Text ( " Max: \( model. maxToken) " )
129- }
130- }
131-
132- HStack {
133- Slider ( value: $settings. chatGPTTemperature, in: 0 ... 2 , step: 0.1 ) {
134- Text ( " Temperature " )
135- }
136-
137- Text (
138- " \( settings. chatGPTTemperature. formatted ( . number. precision ( . fractionLength( 1 ) ) ) ) "
139- )
140- . font ( . body)
141- . monospacedDigit ( )
142- . padding ( . vertical, 2 )
143- . padding ( . horizontal, 6 )
144- . background (
145- RoundedRectangle ( cornerRadius: 4 , style: . continuous)
146- . fill ( Color . primary. opacity ( 0.1 ) )
147- )
148- }
149-
150- Picker (
151- " Memory " ,
152- selection: $settings. chatGPTMaxMessageCount
153- ) {
154- Text ( " No Limit " ) . tag ( 0 )
155- Text ( " 3 Messages " ) . tag ( 3 )
156- Text ( " 5 Messages " ) . tag ( 5 )
157- Text ( " 7 Messages " ) . tag ( 7 )
158- }
159- }
160- . onAppear {
161- if let model = ChatGPTModel ( rawValue: settings. chatGPTModel) {
162- maxTokenOverLimit = model. maxToken < settings. chatGPTMaxToken
163- }
164- }
165- }
166-
167- var languagePicker : some View {
168- Menu {
169- if !settings. chatGPTLanguage. isEmpty,
170- !OpenAIViewSettings. availableLocalizedLocales
171- . contains ( settings. chatGPTLanguage)
172- {
173- Button (
174- settings. chatGPTLanguage,
175- action: { self . settings. chatGPTLanguage = settings. chatGPTLanguage }
176- )
177- }
178- Button (
179- " Auto-detected by ChatGPT " ,
180- action: { self . settings. chatGPTLanguage = " " }
181- )
182- ForEach (
183- OpenAIViewSettings . availableLocalizedLocales,
184- id: \. self
185- ) { localizedLocales in
186- Button (
187- localizedLocales,
188- action: { self . settings. chatGPTLanguage = localizedLocales }
189- )
190- }
191- } label: {
192- Text (
193- settings. chatGPTLanguage. isEmpty
194- ? " Auto-detected by ChatGPT "
195- : settings. chatGPTLanguage
196- )
19781 }
19882 }
19983}
0 commit comments