Skip to content

Commit 0cc2fc5

Browse files
committed
Extract selected files display and controls from prompt field into a dedicated standalone component
- create a new ui component in `packages/ui/src/components/editor/prompt` "SelectedFiles", should accept props: 'selected files token count': number, on_toggle_include_selected_files, translations: 'Attach selected files'. How it should look: checbox, translations, token count. - place 'selected files' under prompt field without any separator - to `packages/ui/src/components/editor/prompt/SelectedFiles/SelectedFiles.tsx` add 'on preview' (translation: Preview), don't handle the callback just yet, button on the right side. - we like how it looks like: [Fragment], we want `packages/ui/src/components/editor/prompt/SelectedFiles/SelectedFiles.tsx` to look alike - render token count to the left of 'preview' - as we have only one button, it should be called 'preview' in css - seet the ponter correctly on either checbox on label, make label 100% height - strike through tokens in `packages/ui/src/components/editor/prompt/SelectedFiles/SelectedFiles.tsx` as well when appropriate - remove tokens of selected files from prompt field (`packages/ui/src/components/editor/prompt/SelectedFiles/SelectedFiles.tsx` is enough) (including shortcut alt X) - fix `packages/ui/src/components/editor/common/prompts/PromptField/PromptField.stories.tsx` - in `packages/ui/src/components/editor/prompt/SelectedFiles/SelectedFiles.tsx`, ellipsis truncation of 'attach selected files' doesn't work ├── apps │ └── editor │ └── src │ ├── commands │ │ └── apply-response-command │ │ └── utils │ │ └── response-parser │ │ └── parsers │ │ └── diff-parser │ │ └── test │ │ └── diff-parser.spec.ts │ ├── constants │ │ └── edit-format-instructions.ts │ ├── i18n │ │ └── translations │ │ └── views │ │ └── prompt │ │ └── handlers │ │ └── select-edit-format-instructions.ts │ └── views │ ├── prompt │ │ └── frontend │ │ ├── Home │ │ │ └── Home.module.scss │ │ ├── Main │ │ │ └── MainView │ │ │ └── MainView.tsx │ │ └── i18n │ │ └── translations │ │ ├── index.ts │ │ ├── main.ts │ │ └── prompt-field.ts │ └── settings │ └── frontend │ └── Home │ └── sections │ ├── ApiConfigurationsSection.tsx │ ├── ModelProvidersSection.tsx │ └── WebConfigurationsSection.tsx ├── docs │ └── chatbot-initialization.mdx └── packages ├── shared │ └── src │ └── utils │ └── display-token-count.ts └── ui └── src └── components └── editor ├── chats │ └── Progress │ └── Progress.module.scss ├── common │ ├── Checkbox │ │ ├── Checkbox.module.scss │ │ ├── Checkbox.stories.tsx │ │ ├── Checkbox.tsx │ │ └── index.ts │ ├── DropdownMenu │ │ └── DropdownMenu.module.scss │ └── prompts │ ├── PromptField │ │ ├── PromptField.module.scss │ │ ├── PromptField.stories.tsx │ │ ├── PromptField.tsx │ │ ├── components │ │ │ ├── Tooltip.module.scss │ │ │ ├── Tooltip.tsx │ │ │ └── index.ts │ │ ├── hooks │ │ │ ├── use-drag-drop.ts │ │ │ ├── use-dropdown.ts │ │ │ ├── use-ghost-text.ts │ │ │ ├── use-handlers │ │ │ │ ├── handle-copy.ts │ │ │ │ ├── handle-cut.ts │ │ │ │ ├── handle-input-change.ts │ │ │ │ ├── handle-input-click.ts │ │ │ │ ├── handle-key-down.ts │ │ │ │ ├── handle-paste.ts │ │ │ │ ├── handle-submit.ts │ │ │ │ ├── index.ts │ │ │ │ ├── types.ts │ │ │ │ ├── use-handlers.ts │ │ │ │ └── utils.ts │ │ │ └── use-keyboard-shortcuts.ts │ │ └── index.ts │ ├── Template │ │ ├── Template.module.scss │ │ ├── Template.tsx │ │ └── index.ts │ └── shared │ └── symbols │ ├── caret.ts │ ├── get-highlighted-text.tsx │ ├── index.ts │ ├── position-mapping.ts │ ├── prompt-symbols.module.scss │ ├── reconstruct-raw-value.ts │ └── use-symbol-deletion.ts ├── prompt │ ├── AsciiArtEffect │ │ ├── AsciiArtEffect.module.scss │ │ ├── AsciiArtEffect.tsx │ │ └── index.ts │ ├── BrowserExtensionMessage │ │ └── BrowserExtensionMessage.module.scss │ ├── Configurations │ │ ├── Configurations.module.scss │ │ ├── Configurations.stories.tsx │ │ ├── Configurations.tsx │ │ └── index.ts │ ├── HomeLinkButton │ │ └── HomeLinkButton.module.scss │ ├── IconAccentButton │ │ └── IconAccentButton.module.scss │ ├── RecentDonations │ │ └── RecentDonations.module.scss │ ├── ResponsePreview │ │ ├── ResponsePreview.module.scss │ │ └── components │ │ └── FileItem │ │ ├── FileItem.module.scss │ │ ├── FileItem.tsx │ │ └── index.ts │ ├── Responses │ │ ├── Responses.module.scss │ │ └── Responses.stories.tsx │ ├── SelectedFiles │ │ ├── SelectedFiles.module.scss │ │ ├── SelectedFiles.stories.tsx │ │ ├── SelectedFiles.tsx │ │ └── index.ts │ └── modals │ └── OngoingApiCallsModal │ └── OngoingApiCallsModal.module.scss └── settings ├── DefaultConfigurationSelector │ └── DefaultConfigurationSelector.module.scss ├── Layout │ └── Layout.module.scss ├── NavigationItemGroup │ └── NavigationItemGroup.module.scss ├── NavigationItemSection │ └── NavigationItemSection.module.scss ├── Section │ └── Section.module.scss ├── SortableList │ └── SortableList.stories.tsx └── Templates └── Templates.module.scss
1 parent 5a82a80 commit 0cc2fc5

12 files changed

Lines changed: 228 additions & 142 deletions

File tree

‎apps/editor/src/views/prompt/frontend/Main/MainView/MainView.tsx‎

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import styles from './MainView.module.scss'
22
import { Configurations as UiConfigurations } from '@ui/components/editor/prompt/Configurations'
33
import { PromptField as UiPromptField } from '@ui/components/editor/common/prompts/PromptField'
4+
import { SelectedFiles as UiSelectedFiles } from '@ui/components/editor/prompt/SelectedFiles'
45
import { Separator as UiSeparator } from '@ui/components/editor/prompt/Separator'
56
import { WebConfiguration } from '@shared/types/web-configuration'
67
import { Responses as UiResponses } from '@ui/components/editor/prompt/Responses'
@@ -340,13 +341,6 @@ export const MainView: React.FC<Props> = (props) => {
340341
on_tabs_reorder={props.on_tabs_reorder}
341342
warning={warning}
342343
voice_input_push_to_talk={props.voice_input_push_to_talk}
343-
selected_files_token_count={props.selected_files_token_count}
344-
include_selected_files={props.include_selected_files}
345-
on_toggle_include_selected_files={() =>
346-
props.on_toggle_include_selected_files(
347-
!props.include_selected_files
348-
)
349-
}
350344
currently_open_file_path={props.currently_open_file_path}
351345
translations={{
352346
voice_input: t('prompt-field.voice-input'),
@@ -378,6 +372,18 @@ export const MainView: React.FC<Props> = (props) => {
378372
/>
379373
</div>
380374

375+
<UiSelectedFiles
376+
selected_files_token_count={props.selected_files_token_count}
377+
include_selected_files={props.include_selected_files}
378+
on_toggle_include_selected_files={
379+
props.on_toggle_include_selected_files
380+
}
381+
translations={{
382+
attach_selected_files: t('main.attach-selected-files'),
383+
preview: t('main.preview' as any)
384+
}}
385+
/>
386+
381387
<UiSeparator height={10} />
382388

383389
{props.mode == MODE.WEB && (

‎apps/editor/src/views/prompt/frontend/i18n/translations/main.ts‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,5 +88,41 @@ export const main = {
8888
cs: ' tokenů',
8989
hu: ' token',
9090
bg: ' токена'
91+
},
92+
'main.attach-selected-files': {
93+
en: 'Attach selected files',
94+
pl: 'Dołącz wybrane pliki',
95+
'zh-cn': '附加所选文件',
96+
ja: '選択したファイルを添付',
97+
'zh-tw': '附加選取的檔案',
98+
de: 'Ausgewählte Dateien anhängen',
99+
es: 'Adjuntar archivos seleccionados',
100+
fr: 'Joindre les fichiers sélectionnés',
101+
'pt-br': 'Anexar arquivos selecionados',
102+
ru: 'Прикрепить выбранные файлы',
103+
ko: '선택한 파일 첨부',
104+
it: 'Allega file selezionati',
105+
tr: 'Seçili dosyaları ekle',
106+
cs: 'Připojit vybrané soubory',
107+
hu: 'Kiválasztott fájlok csatolása',
108+
bg: 'Прикачване на избраните файлове'
109+
},
110+
'main.preview': {
111+
en: 'Preview',
112+
pl: 'Podgląd',
113+
'zh-cn': '预览',
114+
ja: 'プレビュー',
115+
'zh-tw': '預覽',
116+
de: 'Vorschau',
117+
es: 'Vista previa',
118+
fr: 'Aperçu',
119+
'pt-br': 'Pré-visualização',
120+
ru: 'Предпросмотр',
121+
ko: '미리보기',
122+
it: 'Anteprima',
123+
tr: 'Önizleme',
124+
cs: 'Náhled',
125+
hu: 'Előnézet',
126+
bg: 'Преглед'
91127
}
92128
} as const

‎packages/ui/src/components/editor/common/prompts/PromptField/PromptField.module.scss‎

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -235,44 +235,6 @@
235235
min-width: 0;
236236
}
237237

238-
&__token-count-wrapper {
239-
position: relative;
240-
241-
&--clickable {
242-
cursor: pointer;
243-
244-
.footer__right__details__token-count {
245-
cursor: pointer;
246-
}
247-
248-
&:hover {
249-
.footer__right__details__token-count {
250-
color: var(--vscode-foreground);
251-
}
252-
}
253-
}
254-
}
255-
256-
&__token-count {
257-
display: flex;
258-
align-items: center;
259-
gap: 1px;
260-
color: var(--cwc-text-color-dimmed);
261-
cursor: default;
262-
263-
&__icon::before {
264-
font-size: 13px;
265-
}
266-
267-
&__count {
268-
font-variant-numeric: tabular-nums;
269-
270-
&--excluded {
271-
text-decoration: line-through;
272-
}
273-
}
274-
}
275-
276238
&__button {
277239
pointer-events: all;
278240
color: var(--vscode-foreground);

‎packages/ui/src/components/editor/common/prompts/PromptField/PromptField.stories.tsx‎

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,7 @@ export const Empty = () => (
4545
on_tab_change={() => {}}
4646
on_new_tab={() => {}}
4747
on_tab_delete={() => {}}
48-
selected_files_token_count={0}
4948
prompt_token_count={0}
50-
include_selected_files={true}
51-
on_toggle_include_selected_files={() => {}}
5249
translations={{
5350
voice_input: 'Voice input',
5451
stop_recording: 'Stop recording',
@@ -114,10 +111,7 @@ export const WithText = () => (
114111
on_tab_change={() => {}}
115112
on_new_tab={() => {}}
116113
on_tab_delete={() => {}}
117-
selected_files_token_count={0}
118114
prompt_token_count={0}
119-
include_selected_files={true}
120-
on_toggle_include_selected_files={() => {}}
121115
translations={{
122116
voice_input: 'Voice input',
123117
stop_recording: 'Stop recording',
@@ -184,9 +178,6 @@ export const LongText = () => (
184178
on_tab_change={() => {}}
185179
on_new_tab={() => {}}
186180
on_tab_delete={() => {}}
187-
selected_files_token_count={0}
188-
include_selected_files={true}
189-
on_toggle_include_selected_files={() => {}}
190181
translations={{
191182
voice_input: 'Voice input',
192183
stop_recording: 'Stop recording',
@@ -252,10 +243,7 @@ export const WithPlaceholderSavedContext = () => (
252243
on_tab_change={() => {}}
253244
on_new_tab={() => {}}
254245
on_tab_delete={() => {}}
255-
selected_files_token_count={0}
256246
prompt_token_count={0}
257-
include_selected_files={true}
258-
on_toggle_include_selected_files={() => {}}
259247
translations={{
260248
voice_input: 'Voice input',
261249
stop_recording: 'Stop recording',
@@ -327,10 +315,7 @@ export const WithPlaceholderSelection = () => (
327315
on_tab_change={() => {}}
328316
on_new_tab={() => {}}
329317
on_tab_delete={() => {}}
330-
selected_files_token_count={0}
331318
prompt_token_count={0}
332-
include_selected_files={true}
333-
on_toggle_include_selected_files={() => {}}
334319
translations={{
335320
voice_input: 'Voice input',
336321
stop_recording: 'Stop recording',
@@ -396,10 +381,7 @@ export const WithCommit = () => (
396381
on_tab_change={() => {}}
397382
on_new_tab={() => {}}
398383
on_tab_delete={() => {}}
399-
selected_files_token_count={0}
400384
prompt_token_count={0}
401-
include_selected_files={true}
402-
on_toggle_include_selected_files={() => {}}
403385
translations={{
404386
voice_input: 'Voice input',
405387
stop_recording: 'Stop recording',
@@ -464,10 +446,7 @@ export const WithCommitWithQuotes = () => (
464446
on_tab_change={() => {}}
465447
on_new_tab={() => {}}
466448
on_tab_delete={() => {}}
467-
selected_files_token_count={0}
468449
prompt_token_count={0}
469-
include_selected_files={true}
470-
on_toggle_include_selected_files={() => {}}
471450
translations={{
472451
voice_input: 'Voice input',
473452
stop_recording: 'Stop recording',
@@ -540,10 +519,7 @@ export const WithEditFormatSelector = () => {
540519
on_tab_change={() => {}}
541520
on_new_tab={() => {}}
542521
on_tab_delete={() => {}}
543-
selected_files_token_count={0}
544522
prompt_token_count={0}
545-
include_selected_files={true}
546-
on_toggle_include_selected_files={() => {}}
547523
translations={{
548524
voice_input: 'Voice input',
549525
stop_recording: 'Stop recording',
@@ -610,10 +586,7 @@ export const WithFilePaths = () => (
610586
on_tab_change={() => {}}
611587
on_new_tab={() => {}}
612588
on_tab_delete={() => {}}
613-
selected_files_token_count={0}
614589
prompt_token_count={0}
615-
include_selected_files={true}
616-
on_toggle_include_selected_files={() => {}}
617590
translations={{
618591
voice_input: 'Voice input',
619592
stop_recording: 'Stop recording',
@@ -707,10 +680,7 @@ export const WithTabs = () => {
707680
on_tab_change={set_active_index}
708681
on_new_tab={handle_new_tab}
709682
on_tab_delete={handle_tab_delete}
710-
selected_files_token_count={0}
711683
prompt_token_count={0}
712-
include_selected_files={true}
713-
on_toggle_include_selected_files={() => {}}
714684
translations={{
715685
voice_input: 'Voice input',
716686
stop_recording: 'Stop recording',
@@ -775,10 +745,7 @@ export const WithWarning = () => (
775745
on_tab_change={() => {}}
776746
on_new_tab={() => {}}
777747
on_tab_delete={() => {}}
778-
selected_files_token_count={0}
779748
prompt_token_count={0}
780-
include_selected_files={true}
781-
on_toggle_include_selected_files={() => {}}
782749
translations={{
783750
voice_input: 'Voice input',
784751
stop_recording: 'Stop recording',

‎packages/ui/src/components/editor/common/prompts/PromptField/PromptField.tsx‎

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ export type PromptFieldProps = {
7979
on_tabs_reorder?: (new_order: number[]) => void
8080
warning?: string
8181
voice_input_push_to_talk?: boolean
82-
selected_files_token_count: number
8382
prompt_token_count: number
84-
include_selected_files: boolean
85-
on_toggle_include_selected_files: () => void
8683
is_copy_only?: boolean
8784
mode: Mode
8885
on_mode_change: (mode: Mode) => void
@@ -121,7 +118,6 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
121118
const [is_focused, set_is_focused] = useState(false)
122119
const [is_recording_hovered, set_is_recording_hovered] = useState(false)
123120
const [is_edit_format_hovered, set_is_edit_format_hovered] = useState(false)
124-
const [is_token_count_hovered, set_is_token_count_hovered] = useState(false)
125121
const [is_mode_switch_hovered, set_is_mode_switch_hovered] = useState(false)
126122
const [hovered_left_action, set_hovered_left_action] = useState<
127123
'at' | 'hash' | 'slash' | null
@@ -444,8 +440,7 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
444440
<div
445441
className={cn(styles['footer__right__details'], {
446442
[styles['footer__right__details--visible']]:
447-
props.show_edit_format_selector ||
448-
props.selected_files_token_count > 0
443+
props.show_edit_format_selector
449444
})}
450445
>
451446
{props.show_edit_format_selector && props.edit_format && (
@@ -565,53 +560,6 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
565560
</button>
566561
</div>
567562
)}
568-
<div
569-
className={cn(
570-
styles['footer__right__details__token-count-wrapper'],
571-
{
572-
[styles[
573-
'footer__right__details__token-count-wrapper--clickable'
574-
]]: true
575-
}
576-
)}
577-
onMouseEnter={() => set_is_token_count_hovered(true)}
578-
onMouseLeave={() => set_is_token_count_hovered(false)}
579-
onClick={(e) => {
580-
e.stopPropagation()
581-
props.on_toggle_include_selected_files()
582-
}}
583-
>
584-
{is_token_count_hovered && (
585-
<Tooltip
586-
message={props.translations.attach_selected_files}
587-
details={is_mac ? '⌥X' : 'Alt+X'}
588-
align="center"
589-
/>
590-
)}
591-
<KeycapWrapper char={is_alt_pressed ? 'X' : undefined}>
592-
<div className={styles['footer__right__details__token-count']}>
593-
<div
594-
className={cn(
595-
styles['footer__right__details__token-count__icon'],
596-
'codicon',
597-
'codicon-attach'
598-
)}
599-
/>
600-
<div
601-
className={cn(
602-
styles['footer__right__details__token-count__count'],
603-
{
604-
[styles[
605-
'footer__right__details__token-count__count--excluded'
606-
]]: props.include_selected_files === false
607-
}
608-
)}
609-
>
610-
{display_token_count(props.selected_files_token_count)}
611-
</div>
612-
</div>
613-
</KeycapWrapper>
614-
</div>
615563
</div>
616564

617565
<div className={styles['footer__right__submit']} ref={dropdown_ref}>

‎packages/ui/src/components/editor/common/prompts/PromptField/hooks/use-keyboard-shortcuts.ts‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ export const use_keyboard_shortcuts = (props: PromptFieldProps) => {
3737
return
3838
}
3939

40-
if (e.code == 'KeyX') {
41-
e.preventDefault()
42-
if (props.on_toggle_include_selected_files) {
43-
props.on_toggle_include_selected_files()
44-
}
45-
return
46-
}
47-
4840
if (props.show_edit_format_selector && props.on_edit_format_change) {
4941
switch (e.code) {
5042
case 'KeyW':

‎packages/ui/src/components/editor/prompt/AsciiArtEffect/AsciiArtEffect.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { useEffect, useRef } from 'react'
22
import styles from './AsciiArtEffect.module.scss'
33

4-
export type AsciiArtEffectProps = {
4+
export type Props = {
55
density?: number
66
}
77

8-
export const AsciiArtEffect = ({ density = 1 }: AsciiArtEffectProps) => {
8+
export const AsciiArtEffect = ({ density = 1 }: Props) => {
99
const ref = useRef<HTMLDivElement>(null)
1010

1111
useEffect(() => {

‎packages/ui/src/components/editor/prompt/ResponsePreview/components/FileItem/FileItem.module.scss‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,18 @@
120120
}
121121

122122
.message {
123-
margin: 0 20px;
123+
margin: 0 22px;
124124
display: flex;
125125
justify-content: space-between;
126126
gap: 4px;
127127
border-bottom-left-radius: 6px;
128128
border-bottom-right-radius: 6px;
129129
overflow: hidden;
130130

131+
:global([data-modern-ui='true']) & {
132+
margin: 0 20px;
133+
}
134+
131135
&--error {
132136
color: var(--cwc-text-color-red);
133137
background-color: var(--cwc-bg-red);

0 commit comments

Comments
 (0)