@@ -5,6 +5,7 @@ import Preferences
55import SwiftUI
66
77final class OpenAIViewSettings : ObservableObject {
8+ static let availableLocalizedLocales = Locale . availableLocalizedLocales
89 @AppStorage ( \. openAIAPIKey) var openAIAPIKey : String
910 @AppStorage ( \. chatGPTModel) var chatGPTModel : String
1011 @AppStorage ( \. chatGPTEndpoint) var chatGPTEndpoint : String
@@ -30,68 +31,124 @@ struct OpenAIView: View {
3031
3132 Form {
3233 HStack {
33- Text ( " OpenAI API Key " )
3434 TextField ( text: $settings. openAIAPIKey, prompt: Text ( " sk-* " ) ) {
35- EmptyView ( )
36- } . textFieldStyle ( . copilot )
35+ Text ( " OpenAI API Key " )
36+ } . textFieldStyle ( . roundedBorder )
3737 Button ( action: {
3838 openURL ( apiKeyURL)
3939 } ) {
4040 Image ( systemName: " questionmark.circle.fill " )
41- }
42- . buttonStyle ( . plain)
41+ } . buttonStyle ( . plain)
4342 }
4443
4544 HStack {
46- Text ( " ChatGPT Model " )
47- TextField ( text: $settings. chatGPTModel, prompt: Text ( " gpt-3.5-turbo " ) ) {
48- EmptyView ( )
49- } . textFieldStyle ( . copilot)
50-
45+ Picker ( selection: $settings. chatGPTModel) {
46+ if !settings. chatGPTModel. isEmpty,
47+ ChatGPTModel ( rawValue: settings. chatGPTModel) == nil
48+ {
49+ Text ( settings. chatGPTModel) . tag ( settings. chatGPTModel)
50+ }
51+ ForEach ( ChatGPTModel . allCases, id: \. self) { model in
52+ Text ( model. rawValue) . tag ( model. rawValue)
53+ }
54+ } label: {
55+ Text ( " ChatGPT Model " )
56+ } . pickerStyle ( . menu)
5157 Button ( action: {
5258 openURL ( modelURL)
5359 } ) {
5460 Image ( systemName: " questionmark.circle.fill " )
61+ } . buttonStyle ( . plain)
62+ }
63+ . onChange ( of: settings. chatGPTModel) { newValue in
64+ if let model = ChatGPTModel ( rawValue: newValue) {
65+ settings. chatGPTEndpoint = model. endpoint
5566 }
56- . buttonStyle ( . plain)
5767 }
5868
59- HStack {
60- Text ( " ChatGPT Endpoint " )
61- TextField (
62- text: $settings. chatGPTEndpoint,
63- prompt: Text ( " https://api.openai.com/v1/chat/completions " )
64- ) {
65- EmptyView ( )
66- } . textFieldStyle ( . copilot)
67- }
68-
69- HStack {
70- Text ( " Reply in Language " )
71- TextField (
72- text: $settings. chatGPTLanguage,
73- prompt: Text ( " e.g. English. Leave it blank to let the bot decide. " )
74- ) {
75- EmptyView ( )
76- } . textFieldStyle ( . copilot)
69+ TextField (
70+ text: $settings. chatGPTEndpoint,
71+ prompt: Text ( " https://api.openai.com/v1/chat/completions " )
72+ ) {
73+ Text ( " ChatGPT Server " )
74+ } . textFieldStyle ( . roundedBorder)
75+
76+ if #available( macOS 13 . 0 , * ) {
77+ LabeledContent ( " Reply in Language " ) {
78+ languagePicker
79+ }
80+ } else {
81+ HStack {
82+ Text ( " Reply in Language " )
83+ languagePicker
84+ }
7785 }
78-
79- HStack {
80- Text ( " Max Token " )
81- TextField (
82- text: . init( get: {
83- String ( settings. chatGPTMaxToken)
84- } , set: { newValue in
85- settings. chatGPTMaxToken = Int ( newValue) ?? 0
86- } )
87- ) {
88- EmptyView ( )
89- } . textFieldStyle ( . copilot)
86+
87+ if let model = ChatGPTModel ( rawValue: settings. chatGPTModel) {
88+ let binding = Binding (
89+ get: { String ( settings. chatGPTMaxToken) } ,
90+ set: {
91+ if let selectionMaxToken = Int ( $0) {
92+ settings. chatGPTMaxToken = model
93+ . maxToken < selectionMaxToken ? model
94+ . maxToken : selectionMaxToken
95+ } else {
96+ settings. chatGPTMaxToken = 0
97+ }
98+ }
99+ )
100+ HStack {
101+ Stepper (
102+ value: $settings. chatGPTMaxToken,
103+ in: 0 ... model. maxToken,
104+ step: 1
105+ ) {
106+ Text ( " Max Token " )
107+ }
108+ TextField ( text: binding) {
109+ EmptyView ( )
110+ }
111+ . labelsHidden ( )
112+ . textFieldStyle ( . roundedBorder)
113+ }
90114 }
91115 }
92116 }
93117 }
94118 }
119+
120+ var languagePicker : some View {
121+ Menu {
122+ if !settings. chatGPTLanguage. isEmpty,
123+ !OpenAIViewSettings. availableLocalizedLocales
124+ . contains ( settings. chatGPTLanguage)
125+ {
126+ Button (
127+ settings. chatGPTLanguage,
128+ action: { self . settings. chatGPTLanguage = settings. chatGPTLanguage }
129+ )
130+ }
131+ Button (
132+ " Auto-detected by ChatGPT " ,
133+ action: { self . settings. chatGPTLanguage = " " }
134+ )
135+ ForEach (
136+ OpenAIViewSettings . availableLocalizedLocales,
137+ id: \. self
138+ ) { localizedLocales in
139+ Button (
140+ localizedLocales,
141+ action: { self . settings. chatGPTLanguage = localizedLocales }
142+ )
143+ }
144+ } label: {
145+ Text (
146+ settings. chatGPTLanguage. isEmpty
147+ ? " Auto-detected by ChatGPT "
148+ : settings. chatGPTLanguage
149+ )
150+ }
151+ }
95152}
96153
97154struct OpenAIView_Previews : PreviewProvider {
0 commit comments