@@ -9,27 +9,29 @@ import {
99 FaSyncAlt ,
1010 FaCoins ,
1111 FaCode ,
12+ FaServer ,
1213} from "react-icons/fa" ;
1314import Dialog from "./Dialog" ;
1415import Input from "./Input" ;
1516import { GPT_MODEL_NAMES , GPT_4 } from "../utils/constants" ;
1617import Accordion from "./Accordion" ;
17- import type { ModelSettings } from "../utils/types" ;
18+ import type { ModelSettings , SettingModel } from "../utils/types" ;
1819import { useGuestMode } from "../hooks/useGuestMode" ;
20+ import clsx from "clsx" ;
1921
2022export const SettingsDialog : React . FC < {
2123 show : boolean ;
2224 close : ( ) => void ;
23- customSettings : [ ModelSettings , ( settings : ModelSettings ) => void ] ;
24- } > = ( { show, close, customSettings : [ customSettings , setCustomSettings ] } ) => {
25+ customSettings : SettingModel ;
26+ } > = ( { show, close, customSettings } ) => {
2527 const [ settings , setSettings ] = React . useState < ModelSettings > ( {
26- ...customSettings ,
28+ ...customSettings . settings ,
2729 } ) ;
28- const { isGuestMode } = useGuestMode ( settings . guestKey ) ;
30+ const { isGuestMode } = useGuestMode ( settings . customGuestKey ) ;
2931 const { t } = useTranslation ( [ "settings" , "common" ] ) ;
3032
3133 useEffect ( ( ) => {
32- setSettings ( customSettings ) ;
34+ setSettings ( customSettings . settings ) ;
3335 } , [ customSettings , close ] ) ;
3436
3537 const updateSettings = < Key extends keyof ModelSettings > (
@@ -41,15 +43,53 @@ export const SettingsDialog: React.FC<{
4143 } ) ;
4244 } ;
4345
46+ function urlIsValid ( url : string | undefined ) {
47+ if ( url ) {
48+ const pattern = / ^ ( h t t p s ? : \/ \/ ) ? [ \w . - ] + \. [ a - z A - Z ] { 2 , } ( \/ \S * ) ? $ / ;
49+ return pattern . test ( url ) ;
50+ }
51+ return true ;
52+ }
53+
4454 const handleSave = ( ) => {
45- setCustomSettings ( settings ) ;
55+ if ( ! urlIsValid ( settings . customEndPoint ) ) {
56+ alert (
57+ t (
58+ "Endpoint URL is invalid. Please ensure that you have set a correct URL."
59+ )
60+ ) ;
61+ return ;
62+ }
63+
64+ if ( ! settings . customApiKey ) {
65+ customSettings . resetSettings ( ) ;
66+ } else {
67+ customSettings . saveSettings ( settings ) ;
68+ }
4669 close ( ) ;
4770 return ;
4871 } ;
4972
73+ const handleReset = ( ) => {
74+ customSettings . resetSettings ( ) ;
75+ updateSettings ( "customApiKey" , "" ) ;
76+ close ( ) ;
77+ } ;
78+
5079 const disabled = ! settings . customApiKey ;
5180 const advancedSettings = (
52- < >
81+ < div className = "flex flex-col gap-2" >
82+ < Input
83+ left = {
84+ < >
85+ < FaServer />
86+ < span className = "ml-2" > { t ( "endPoint" ) } </ span >
87+ </ >
88+ }
89+ disabled = { disabled }
90+ value = { settings . customEndPoint }
91+ onChange = { ( e ) => updateSettings ( "customEndPoint" , e . target . value ) }
92+ />
5393 < Input
5494 left = {
5595 < >
@@ -72,7 +112,6 @@ export const SettingsDialog: React.FC<{
72112 step : 0.01 ,
73113 } }
74114 />
75- < br />
76115 < Input
77116 left = {
78117 < >
@@ -96,18 +135,17 @@ export const SettingsDialog: React.FC<{
96135 step : 1 ,
97136 } }
98137 />
99- < br />
100138 < Input
101139 left = {
102140 < >
103141 < FaCoins />
104142 < span className = "ml-2" > { t ( "tokens" ) } </ span >
105143 </ >
106144 }
107- value = { settings . maxTokens ?? 400 }
145+ value = { settings . customMaxTokens ?? 400 }
108146 disabled = { disabled }
109147 onChange = { ( e ) =>
110- updateSettings ( "maxTokens " , parseFloat ( e . target . value ) )
148+ updateSettings ( "customMaxTokens " , parseFloat ( e . target . value ) )
111149 }
112150 type = "range"
113151 toolTipProperties = { {
@@ -120,24 +158,31 @@ export const SettingsDialog: React.FC<{
120158 step : 100 ,
121159 } }
122160 />
123- </ >
161+ </ div >
124162 ) ;
125163
126164 return (
127165 < Dialog
128166 header = { `${ t ( "settings" ) } ⚙` }
129167 isShown = { show }
130168 close = { close }
131- footerButton = { < Button onClick = { handleSave } > { t ( "common:save" ) } </ Button > }
169+ footerButton = {
170+ < >
171+ < Button className = "bg-red-400 hover:bg-red-500" onClick = { handleReset } >
172+ { t ( "common:reset" ) }
173+ </ Button >
174+ < Button onClick = { handleSave } > { t ( "common:save" ) } </ Button >
175+ </ >
176+ }
177+ contentClassName = "text-md relative flex flex-col gap-2 p-2 leading-relaxed"
132178 >
133179 < p > { t ( "usage" ) } </ p >
134- < br />
135180 < p
136- className = {
137- settings . customModelName === GPT_4
138- ? "rounded-md border-[2px] border-white/10 bg-yellow-300 text-black"
139- : " "
140- }
181+ className = { clsx (
182+ "my-2" ,
183+ settings . customModelName === GPT_4 &&
184+ "rounded-md border-[2px] border-white/10 bg-yellow-300 text-black "
185+ ) }
141186 >
142187 < FaExclamationCircle className = "inline-block" />
143188
@@ -155,67 +200,60 @@ export const SettingsDialog: React.FC<{
155200 </ b >
156201 </ Trans >
157202 </ p >
158- < br />
159- < div className = "text-md relative flex-auto p-2 leading-relaxed" >
160- < Input
161- left = {
162- < >
163- < FaKey />
164- < span className = "ml-2" > { t ( "key" ) } </ span >
165- </ >
166- }
167- placeholder = { "sk-..." }
168- value = { settings . customApiKey }
169- onChange = { ( e ) => updateSettings ( "customApiKey" , e . target . value ) }
170- />
171- < br className = "md:inline" />
203+ < Input
204+ left = {
205+ < >
206+ < FaKey />
207+ < span className = "ml-2" > { t ( "key" ) } </ span >
208+ </ >
209+ }
210+ placeholder = { "sk-..." }
211+ value = { settings . customApiKey }
212+ onChange = { ( e ) => updateSettings ( "customApiKey" , e . target . value ) }
213+ />
214+ < Input
215+ left = {
216+ < >
217+ < FaMicrochip />
218+ < span className = "ml-2" > { t ( "model" ) } </ span >
219+ </ >
220+ }
221+ type = "combobox"
222+ value = { settings . customModelName }
223+ onChange = { ( ) => null }
224+ setValue = { ( e ) => updateSettings ( "customModelName" , e ) }
225+ attributes = { { options : GPT_MODEL_NAMES } }
226+ disabled = { disabled }
227+ />
228+ { isGuestMode && (
172229 < Input
173230 left = {
174231 < >
175- < FaMicrochip />
176- < span className = "ml-2" > { t ( "model " ) } </ span >
232+ < FaCode />
233+ < span className = "ml-2" > { t ( "guest-key " ) } </ span >
177234 </ >
178235 }
179- type = "combobox"
180- value = { settings . customModelName }
181- onChange = { ( ) => null }
182- setValue = { ( e ) => updateSettings ( "customModelName" , e ) }
183- attributes = { { options : GPT_MODEL_NAMES } }
184- disabled = { disabled }
236+ value = { settings . customGuestKey }
237+ onChange = { ( e ) => updateSettings ( "customGuestKey" , e . target . value ) }
185238 />
186- < br className = "md:inline" />
187- { isGuestMode && (
188- < Input
189- left = {
190- < >
191- < FaCode />
192- < span className = "ml-2" > { t ( "guest-key" ) } </ span >
193- </ >
194- }
195- value = { settings . guestKey }
196- onChange = { ( e ) => updateSettings ( "guestKey" , e . target . value ) }
197- />
198- ) }
199- < br className = "hidden md:inline" />
200- < Accordion
201- child = { advancedSettings }
202- name = { t ( "advanced-settings" ) }
203- > </ Accordion >
204- < br />
205- < Trans i18nKey = "api-key-notice" ns = "settings" >
206- < strong className = "mt-10" >
207- NOTE: To get a key, sign up for an OpenAI account and visit the
208- following
209- < a
210- href = "https://platform.openai.com/account/api-keys"
211- className = "text-blue-500"
212- >
213- link.
214- </ a >
215- This key is only used in the current browser session
216- </ strong >
217- </ Trans >
218- </ div >
239+ ) }
240+ < Accordion
241+ child = { advancedSettings }
242+ name = { t ( "advanced-settings" ) }
243+ > </ Accordion >
244+ < Trans i18nKey = "api-key-notice" ns = "settings" >
245+ < strong className = "mt-10" >
246+ NOTE: To get a key, sign up for an OpenAI account and visit the
247+ following
248+ < a
249+ href = "https://platform.openai.com/account/api-keys"
250+ className = "text-blue-500"
251+ >
252+ link.
253+ </ a >
254+ This key is only used in the current browser session
255+ </ strong >
256+ </ Trans >
219257 </ Dialog >
220258 ) ;
221259} ;
0 commit comments