@@ -70,6 +70,8 @@ const api_mode_labels: Record<ApiMode, string> = {
7070
7171export const HomeView : React . FC < Props > = ( props ) => {
7272 const [ estimated_input_tokens , set_estimated_input_tokens ] = useState ( 0 )
73+ // We need this because we can't use overflow: hidden
74+ // due to absolutely positioned dropdown menu
7375 const [ dropdown_max_width , set_dropdown_max_width ] = useState <
7476 number | undefined
7577 > ( undefined )
@@ -182,189 +184,189 @@ export const HomeView: React.FC<Props> = (props) => {
182184 < div ref = { container_ref } className = { styles . container } >
183185 < Scrollable >
184186 < div className = { styles . inner } >
185- < div className = { styles . top } >
186- < div className = { styles . top__left } >
187- < IconButton
188- codicon_icon = "chevron-left"
189- on_click = { props . on_show_intro }
190- title = "Return to intro screen"
187+ < div className = { styles . top } >
188+ < div className = { styles . top__left } >
189+ < IconButton
190+ codicon_icon = "chevron-left"
191+ on_click = { props . on_show_intro }
192+ title = "Return to intro screen"
193+ />
194+ < div ref = { switch_container_ref } >
195+ < UiSwitch
196+ value = { props . home_view_type }
197+ on_change = { props . on_home_view_type_change }
198+ options = { Object . values ( HOME_VIEW_TYPES ) }
191199 />
192- < div ref = { switch_container_ref } >
193- < UiSwitch
194- value = { props . home_view_type }
195- on_change = { props . on_home_view_type_change }
196- options = { Object . values ( HOME_VIEW_TYPES ) }
197- />
198- </ div >
199- </ div >
200-
201- < div className = { styles . top__right } ref = { dropdown_container_ref } >
202- { props . home_view_type == HOME_VIEW_TYPES . WEB && (
203- < UiDropdown
204- options = { Object . entries ( web_mode_labels ) . map (
205- ( [ value , label ] ) => ( { value : value as WebMode , label } )
206- ) }
207- selected_value = { props . web_mode }
208- on_change = { props . on_web_mode_change }
209- title = { `Current mode: ${ web_mode_labels [ props . web_mode ] } ` }
210- max_width = { dropdown_max_width }
211- />
212- ) }
213- { props . home_view_type == HOME_VIEW_TYPES . API && (
214- < UiDropdown
215- options = { Object . entries ( api_mode_labels ) . map (
216- ( [ value , label ] ) => ( { value : value as ApiMode , label } )
217- ) }
218- selected_value = { props . api_mode }
219- on_change = { props . on_api_mode_change }
220- title = { `Current mode: ${ api_mode_labels [ props . api_mode ] } ` }
221- max_width = { dropdown_max_width }
222- />
223- ) }
224200 </ div >
225201 </ div >
226202
227- < UiSeparator height = { 8 } />
228-
229- { ! props . is_connected &&
230- props . home_view_type == HOME_VIEW_TYPES . WEB && (
231- < >
232- < div className = { styles [ 'browser-extension-message' ] } >
233- < span >
234- Get the Connector browser extension for hands-free chat
235- inititalizations
236- </ span >
237- < a href = "https://chromewebstore.google.com/detail/code-web-chat-connector/ljookipcanaglfaocjbgdicfbdhhjffp" >
238- Chrome Web Store ↗
239- </ a >
240- < a href = "https://addons.mozilla.org/en-US/firefox/addon/gemini-coder-connector/" >
241- Firefox Add-ons ↗
242- </ a >
243- </ div >
244-
245- < UiSeparator height = { 8 } />
246- </ >
203+ < div className = { styles . top__right } ref = { dropdown_container_ref } >
204+ { props . home_view_type == HOME_VIEW_TYPES . WEB && (
205+ < UiDropdown
206+ options = { Object . entries ( web_mode_labels ) . map (
207+ ( [ value , label ] ) => ( { value : value as WebMode , label } )
208+ ) }
209+ selected_value = { props . web_mode }
210+ on_change = { props . on_web_mode_change }
211+ title = { `Current mode: ${ web_mode_labels [ props . web_mode ] } ` }
212+ max_width = { dropdown_max_width }
213+ />
214+ ) }
215+ { props . home_view_type == HOME_VIEW_TYPES . API && (
216+ < UiDropdown
217+ options = { Object . entries ( api_mode_labels ) . map (
218+ ( [ value , label ] ) => ( { value : value as ApiMode , label } )
219+ ) }
220+ selected_value = { props . api_mode }
221+ on_change = { props . on_api_mode_change }
222+ title = { `Current mode: ${ api_mode_labels [ props . api_mode ] } ` }
223+ max_width = { dropdown_max_width }
224+ />
247225 ) }
248-
249- < div className = { styles [ 'chat-input' ] } >
250- < UiChatInput
251- value = { current_prompt }
252- chat_history = { props . chat_history }
253- on_change = { handle_input_change }
254- on_submit = { handle_submit }
255- on_submit_with_control = { handle_submit_with_control }
256- on_copy = {
257- props . home_view_type == HOME_VIEW_TYPES . WEB &&
258- props . web_mode != 'no-context'
259- ? handle_copy
260- : undefined
261- }
262- on_search_click = { props . on_search_click }
263- on_at_sign_click = { props . on_at_sign_click }
264- is_web_mode = { props . home_view_type == HOME_VIEW_TYPES . WEB }
265- is_connected = { props . is_connected }
266- token_count = { estimated_input_tokens }
267- submit_disabled_title = {
268- ! props . is_connected
269- ? 'WebSocket connection not established. Please install the browser extension.'
270- : 'Type something'
271- }
272- is_in_code_completions_mode = { is_in_code_completions_mode }
273- has_active_selection = { props . has_active_selection }
274- has_active_editor = { props . has_active_editor }
275- on_caret_position_change = { props . on_caret_position_change }
276- translations = { {
277- type_something : 'Type something' ,
278- completion_instructions : 'Completion instructions' ,
279- send_request : 'Send request' ,
280- initialize_chat : 'Initialize chat' ,
281- select_preset : 'Select preset' ,
282- select_config : 'Select config' ,
283- code_completions_mode_unavailable_with_text_selection :
284- 'Unable to work with text selection' ,
285- code_completions_mode_unavailable_without_active_editor :
286- 'This mode requires active editor' ,
287- search : 'Search history'
288- } }
289- />
290226 </ div >
227+ </ div >
228+
229+ < UiSeparator height = { 8 } />
291230
292- { ( ( props . home_view_type == HOME_VIEW_TYPES . WEB &&
293- props . web_mode == 'edit' ) ||
294- ( props . home_view_type == HOME_VIEW_TYPES . API &&
295- props . api_mode == 'edit' ) ) && (
231+ { ! props . is_connected &&
232+ props . home_view_type == HOME_VIEW_TYPES . WEB && (
296233 < >
297- < div className = { styles [ 'edit-format ' ] } >
234+ < div className = { styles [ 'browser-extension-message ' ] } >
298235 < span >
299- + < i title = "Style of generated code blocks" > edit format </ i > { ' ' }
300- instructions:
236+ Get the Connector browser extension for hands-free chat
237+ inititalizations
301238 </ span >
302- < UiHorizontalSelector
303- options = { [
304- {
305- value : 'whole' ,
306- label : 'whole' ,
307- title :
308- 'The model will output modified files in full. The best quality, especially from smaller models.'
309- } ,
310- {
311- value : 'truncated' ,
312- label : 'truncated' ,
313- title :
314- 'The model will skip unchanged fragments in modified files. Readable but requires Intelligent Update API tool to apply.'
315- } ,
316- {
317- value : 'diff' ,
318- label : 'diff' ,
319- title :
320- 'The model will output patches. Less readable but fast to apply. Smaller models may struggle with diff correctness.'
321- }
322- ] }
323- selected_value = {
324- props . home_view_type == HOME_VIEW_TYPES . WEB
325- ? props . chat_edit_format
326- : props . api_edit_format
327- }
328- on_select = { ( value ) =>
329- props . home_view_type == HOME_VIEW_TYPES . WEB
330- ? props . on_chat_edit_format_change ( value as EditFormat )
331- : props . on_api_edit_format_change ( value as EditFormat )
332- }
333- />
239+ < a href = "https://chromewebstore.google.com/detail/code-web-chat-connector/ljookipcanaglfaocjbgdicfbdhhjffp" >
240+ Chrome Web Store ↗
241+ </ a >
242+ < a href = "https://addons.mozilla.org/en-US/firefox/addon/gemini-coder-connector/" >
243+ Firefox Add-ons ↗
244+ </ a >
334245 </ div >
246+
247+ < UiSeparator height = { 8 } />
335248 </ >
336249 ) }
337250
338- { props . home_view_type == HOME_VIEW_TYPES . WEB && (
339- < >
340- < UiSeparator height = { 16 } />
341- < UiPresets
342- presets = { props . presets . map ( ( preset ) => {
343- return {
344- ...preset ,
345- has_affixes : ! ! (
346- preset . prompt_prefix || preset . prompt_suffix
347- )
251+ < div className = { styles [ 'chat-input' ] } >
252+ < UiChatInput
253+ value = { current_prompt }
254+ chat_history = { props . chat_history }
255+ on_change = { handle_input_change }
256+ on_submit = { handle_submit }
257+ on_submit_with_control = { handle_submit_with_control }
258+ on_copy = {
259+ props . home_view_type == HOME_VIEW_TYPES . WEB &&
260+ props . web_mode != 'no-context'
261+ ? handle_copy
262+ : undefined
263+ }
264+ on_search_click = { props . on_search_click }
265+ on_at_sign_click = { props . on_at_sign_click }
266+ is_web_mode = { props . home_view_type == HOME_VIEW_TYPES . WEB }
267+ is_connected = { props . is_connected }
268+ token_count = { estimated_input_tokens }
269+ submit_disabled_title = {
270+ ! props . is_connected
271+ ? 'WebSocket connection not established. Please install the browser extension.'
272+ : 'Type something'
273+ }
274+ is_in_code_completions_mode = { is_in_code_completions_mode }
275+ has_active_selection = { props . has_active_selection }
276+ has_active_editor = { props . has_active_editor }
277+ on_caret_position_change = { props . on_caret_position_change }
278+ translations = { {
279+ type_something : 'Type something' ,
280+ completion_instructions : 'Completion instructions' ,
281+ send_request : 'Send request' ,
282+ initialize_chat : 'Initialize chat' ,
283+ select_preset : 'Select preset' ,
284+ select_config : 'Select config' ,
285+ code_completions_mode_unavailable_with_text_selection :
286+ 'Unable to work with text selection' ,
287+ code_completions_mode_unavailable_without_active_editor :
288+ 'This mode requires active editor' ,
289+ search : 'Search history'
290+ } }
291+ />
292+ </ div >
293+
294+ { ( ( props . home_view_type == HOME_VIEW_TYPES . WEB &&
295+ props . web_mode == 'edit' ) ||
296+ ( props . home_view_type == HOME_VIEW_TYPES . API &&
297+ props . api_mode == 'edit' ) ) && (
298+ < >
299+ < div className = { styles [ 'edit-format' ] } >
300+ < span >
301+ + < i title = "Style of generated code blocks" > edit format</ i > { ' ' }
302+ instructions:
303+ </ span >
304+ < UiHorizontalSelector
305+ options = { [
306+ {
307+ value : 'whole' ,
308+ label : 'whole' ,
309+ title :
310+ 'The model will output modified files in full. The best quality, especially from smaller models.'
311+ } ,
312+ {
313+ value : 'truncated' ,
314+ label : 'truncated' ,
315+ title :
316+ 'The model will skip unchanged fragments in modified files. Readable but requires Intelligent Update API tool to apply.'
317+ } ,
318+ {
319+ value : 'diff' ,
320+ label : 'diff' ,
321+ title :
322+ 'The model will output patches. Less readable but fast to apply. Smaller models may struggle with diff correctness.'
348323 }
349- } ) }
350- is_disabled = { ! props . is_connected }
351- selected_presets = { props . selected_presets }
352- on_create_preset = { props . on_create_preset }
353- on_preset_click = { ( name ) => {
354- props . initialize_chats ( {
355- prompt : current_prompt ,
356- preset_names : [ name ]
357- } )
358- } }
359- on_preset_copy = { handle_preset_copy }
360- on_preset_edit = { props . on_preset_edit }
361- on_presets_reorder = { props . on_presets_reorder }
362- on_preset_duplicate = { props . on_preset_duplicate }
363- on_preset_delete = { props . on_preset_delete }
364- on_set_default_presets = { props . on_set_default_presets }
324+ ] }
325+ selected_value = {
326+ props . home_view_type == HOME_VIEW_TYPES . WEB
327+ ? props . chat_edit_format
328+ : props . api_edit_format
329+ }
330+ on_select = { ( value ) =>
331+ props . home_view_type == HOME_VIEW_TYPES . WEB
332+ ? props . on_chat_edit_format_change ( value as EditFormat )
333+ : props . on_api_edit_format_change ( value as EditFormat )
334+ }
365335 />
366- </ >
367- ) }
336+ </ div >
337+ </ >
338+ ) }
339+
340+ { props . home_view_type == HOME_VIEW_TYPES . WEB && (
341+ < >
342+ < UiSeparator height = { 16 } />
343+ < UiPresets
344+ presets = { props . presets . map ( ( preset ) => {
345+ return {
346+ ...preset ,
347+ has_affixes : ! ! (
348+ preset . prompt_prefix || preset . prompt_suffix
349+ )
350+ }
351+ } ) }
352+ is_disabled = { ! props . is_connected }
353+ selected_presets = { props . selected_presets }
354+ on_create_preset = { props . on_create_preset }
355+ on_preset_click = { ( name ) => {
356+ props . initialize_chats ( {
357+ prompt : current_prompt ,
358+ preset_names : [ name ]
359+ } )
360+ } }
361+ on_preset_copy = { handle_preset_copy }
362+ on_preset_edit = { props . on_preset_edit }
363+ on_presets_reorder = { props . on_presets_reorder }
364+ on_preset_duplicate = { props . on_preset_duplicate }
365+ on_preset_delete = { props . on_preset_delete }
366+ on_set_default_presets = { props . on_set_default_presets }
367+ />
368+ </ >
369+ ) }
368370 </ div >
369371 </ Scrollable >
370372 < div
0 commit comments