Skip to content

Commit 6f2e27b

Browse files
committed
Update target selection keyboard shortcuts to use number keys across views
- instead of alt W/A/C, use alt 1/2/3 - the issue is that from home, for alt 1/2/3 shortcuts to work they have to be pressed twice - remove keyboard shortcuts from home - remove keyboard shortcuts from home, including keycaps on target button - to home, add keyboard shortcuts alt 1/2/3 to set the target - prompt field should ignore keyboard shortcuts when main view does ├── apps │ └── editor │ └── src │ └── views │ └── prompt │ └── frontend │ ├── Home │ │ ├── Home.module.scss │ │ ├── Home.tsx │ │ └── hooks │ │ └── use-keyboard-shortcuts.ts │ ├── Main │ │ ├── Main.tsx │ │ └── MainView │ │ ├── MainView.tsx │ │ └── hooks │ │ └── use-keyboard-shortcuts.ts │ ├── Prompt.tsx │ └── hooks │ └── use-prompt │ └── use-prompt.ts └── packages └── ui └── src └── components └── editor ├── common │ └── prompts │ └── PromptField │ ├── PromptField.tsx │ └── hooks │ └── use-keyboard-shortcuts.ts └── prompt └── TargetButton ├── TargetButton.stories.tsx ├── TargetButton.tsx └── index.ts
1 parent d9eba2d commit 6f2e27b

6 files changed

Lines changed: 88 additions & 103 deletions

File tree

‎apps/editor/src/views/prompt/frontend/Home/Home.tsx‎

Lines changed: 14 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ import { CompactableActionButton } from '@ui/components/editor/prompt/Compactabl
1212
import { Tasks as UiTasks } from '@ui/components/editor/prompt/Tasks'
1313
import { use_tasks } from './hooks/use-tasks'
1414
import { use_has_scrolled_past_target_button } from './hooks/use-has-scrolled-past-mode-button'
15+
import { use_keyboard_shortcuts } from './hooks/use-keyboard-shortcuts'
1516
import { use_compacting } from '@shared/hooks'
1617
import {
1718
ApiPromptType,
1819
WebPromptType,
1920
CliPromptType
2021
} from '@shared/types/prompt-types'
21-
import { use_keyboard_shortcuts } from './hooks/use-keyboard-shortcuts'
2222
import { use_is_landscape } from '../hooks/use-is-landscape'
2323

2424
type Props = {
2525
vscode: any
2626
is_active: boolean
27-
on_go_forward: () => void
2827
on_chatbots_click: () => void
2928
on_api_calls_click: () => void
3029
on_cli_calls_click: () => void
@@ -44,6 +43,13 @@ export const Home: React.FC<Props> = (props) => {
4443
const { has_scrolled_past_target_button, target_ref, handle_scroll } =
4544
use_has_scrolled_past_target_button(props.is_active)
4645

46+
const { is_alt_pressed } = use_keyboard_shortcuts({
47+
is_active: props.is_active,
48+
on_chatbots_click: props.on_chatbots_click,
49+
on_api_calls_click: props.on_api_calls_click,
50+
on_cli_calls_click: props.on_cli_calls_click
51+
})
52+
4753
const {
4854
tasks,
4955
handle_reorder,
@@ -65,9 +71,6 @@ export const Home: React.FC<Props> = (props) => {
6571

6672
const header_targets_ref = useRef<HTMLDivElement>(null)
6773

68-
const [is_alt_pressed, set_is_alt_pressed] = useState(false)
69-
const alt_interrupted_ref = useRef(false)
70-
7174
const discord_label = 'Discord'
7275
const coffee_label = t('header.buy-me-a-coffee')
7376

@@ -82,64 +85,6 @@ export const Home: React.FC<Props> = (props) => {
8285
return () => window.removeEventListener('message', handle_message)
8386
}, [])
8487

85-
useEffect(() => {
86-
const handle_key_down = (event: KeyboardEvent) => {
87-
if (
88-
event.key == 'Alt' &&
89-
!event.shiftKey &&
90-
!event.ctrlKey &&
91-
!event.metaKey
92-
) {
93-
if (!alt_interrupted_ref.current) {
94-
set_is_alt_pressed(true)
95-
}
96-
} else {
97-
if (event.altKey) {
98-
alt_interrupted_ref.current = true
99-
}
100-
set_is_alt_pressed(false)
101-
}
102-
}
103-
104-
const handle_key_up = (event: KeyboardEvent) => {
105-
if (!event.altKey) {
106-
alt_interrupted_ref.current = false
107-
} else if (event.key != 'Alt') {
108-
alt_interrupted_ref.current = true
109-
}
110-
set_is_alt_pressed(
111-
event.altKey &&
112-
!alt_interrupted_ref.current &&
113-
!event.shiftKey &&
114-
!event.ctrlKey &&
115-
!event.metaKey
116-
)
117-
}
118-
119-
const handle_blur = () => {
120-
set_is_alt_pressed(false)
121-
alt_interrupted_ref.current = false
122-
}
123-
124-
window.addEventListener('keydown', handle_key_down)
125-
window.addEventListener('keyup', handle_key_up)
126-
window.addEventListener('blur', handle_blur)
127-
128-
return () => {
129-
window.removeEventListener('keydown', handle_key_down)
130-
window.removeEventListener('keyup', handle_key_up)
131-
window.removeEventListener('blur', handle_blur)
132-
}
133-
}, [])
134-
135-
use_keyboard_shortcuts({
136-
is_active: props.is_active,
137-
on_go_forward: props.on_go_forward,
138-
on_chatbots_click: props.on_chatbots_click,
139-
on_api_calls_click: props.on_api_calls_click,
140-
on_cli_calls_click: props.on_cli_calls_click
141-
})
142-
14388
const header = (
14489
<div className={styles.header}>
14590
<div
@@ -192,7 +137,7 @@ export const Home: React.FC<Props> = (props) => {
192137
hover_color={
193138
props.web_prompt_type == 'edit-files' ? 'blue' : 'purple'
194139
}
195-
keycap_char={is_alt_pressed ? 'W' : undefined}
140+
keycap_char={is_alt_pressed ? '1' : undefined}
196141
/>
197142
<UiTargetButton
198143
label="API"
@@ -201,7 +146,7 @@ export const Home: React.FC<Props> = (props) => {
201146
hover_color={
202147
props.api_prompt_type == 'edit-files' ? 'blue' : 'purple'
203148
}
204-
keycap_char={is_alt_pressed ? 'A' : undefined}
149+
keycap_char={is_alt_pressed ? '2' : undefined}
205150
/>
206151
<UiTargetButton
207152
label="CLI"
@@ -210,7 +155,7 @@ export const Home: React.FC<Props> = (props) => {
210155
hover_color={
211156
props.cli_prompt_type == 'edit-files' ? 'blue' : 'purple'
212157
}
213-
keycap_char={is_alt_pressed ? 'C' : undefined}
158+
keycap_char={is_alt_pressed ? '3' : undefined}
214159
/>
215160
</div>
216161
</div>
@@ -227,21 +172,21 @@ export const Home: React.FC<Props> = (props) => {
227172
}
228173
on_click={props.on_chatbots_click}
229174
hover_color={props.web_prompt_type == 'edit-files' ? 'blue' : 'purple'}
230-
keycap_char={is_alt_pressed ? 'W' : undefined}
175+
keycap_char={is_alt_pressed ? '1' : undefined}
231176
/>
232177
<UiTargetButton
233178
label="API"
234179
description={t('home.target.api.description')}
235180
on_click={props.on_api_calls_click}
236181
hover_color={props.api_prompt_type == 'edit-files' ? 'blue' : 'purple'}
237-
keycap_char={is_alt_pressed ? 'A' : undefined}
182+
keycap_char={is_alt_pressed ? '2' : undefined}
238183
/>
239184
<UiTargetButton
240185
label="CLI"
241186
description={t('home.target.cli.description')}
242187
on_click={props.on_cli_calls_click}
243188
hover_color={props.cli_prompt_type == 'edit-files' ? 'blue' : 'purple'}
244-
keycap_char={is_alt_pressed ? 'C' : undefined}
189+
keycap_char={is_alt_pressed ? '3' : undefined}
245190
/>
246191
</div>
247192
)
Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,46 @@
1-
import { useEffect, useRef } from 'react'
1+
import { useEffect, useState, useRef } from 'react'
22

3-
type Params = {
3+
export const use_keyboard_shortcuts = (params: {
44
is_active: boolean
5-
on_go_forward: () => void
65
on_chatbots_click: () => void
76
on_api_calls_click: () => void
87
on_cli_calls_click: () => void
9-
}
10-
11-
export const use_keyboard_shortcuts = (params: Params) => {
8+
}) => {
9+
const [is_alt_pressed, set_is_alt_pressed] = useState(false)
10+
const alt_interrupted_ref = useRef(false)
1211
const left_alt_pressed_ref = useRef(false)
1312

13+
const update_alt_pressed = (val: boolean) => {
14+
set_is_alt_pressed(val)
15+
}
16+
1417
useEffect(() => {
15-
const handle_mouse_up = (event: MouseEvent) => {
16-
if (params.is_active && event.button == 4) {
17-
params.on_go_forward()
18-
}
18+
if (!params.is_active) {
19+
update_alt_pressed(false)
20+
return
1921
}
2022

2123
const handle_key_down = (event: KeyboardEvent) => {
2224
if (event.code == 'AltLeft') {
2325
left_alt_pressed_ref.current = true
2426
}
2527

26-
if (!params.is_active) return
28+
if (
29+
event.code == 'AltLeft' &&
30+
!event.shiftKey &&
31+
!event.ctrlKey &&
32+
!event.metaKey
33+
) {
34+
if (!alt_interrupted_ref.current) {
35+
update_alt_pressed(true)
36+
}
37+
} else {
38+
if (event.altKey) {
39+
alt_interrupted_ref.current = true
40+
}
41+
42+
update_alt_pressed(false)
43+
}
2744

2845
if (
2946
event.altKey &&
@@ -32,13 +49,13 @@ export const use_keyboard_shortcuts = (params: Params) => {
3249
!event.metaKey &&
3350
!event.ctrlKey
3451
) {
35-
if (event.code == 'KeyW') {
52+
if (event.code == 'Digit1' || event.code == 'Numpad1') {
3653
event.preventDefault()
3754
params.on_chatbots_click()
38-
} else if (event.code == 'KeyA') {
55+
} else if (event.code == 'Digit2' || event.code == 'Numpad2') {
3956
event.preventDefault()
4057
params.on_api_calls_click()
41-
} else if (event.code == 'KeyC') {
58+
} else if (event.code == 'Digit3' || event.code == 'Numpad3') {
4259
event.preventDefault()
4360
params.on_cli_calls_click()
4461
}
@@ -49,26 +66,43 @@ export const use_keyboard_shortcuts = (params: Params) => {
4966
if (event.code == 'AltLeft') {
5067
left_alt_pressed_ref.current = false
5168
}
69+
70+
if (!event.altKey) {
71+
alt_interrupted_ref.current = false
72+
} else if (event.code != 'AltLeft') {
73+
alt_interrupted_ref.current = true
74+
}
75+
update_alt_pressed(
76+
event.altKey &&
77+
left_alt_pressed_ref.current &&
78+
!alt_interrupted_ref.current &&
79+
!event.shiftKey &&
80+
!event.ctrlKey &&
81+
!event.metaKey
82+
)
5283
}
5384

5485
const handle_blur = () => {
5586
left_alt_pressed_ref.current = false
87+
update_alt_pressed(false)
88+
alt_interrupted_ref.current = false
5689
}
5790

58-
window.addEventListener('mouseup', handle_mouse_up)
5991
window.addEventListener('keydown', handle_key_down)
6092
window.addEventListener('keyup', handle_key_up)
6193
window.addEventListener('blur', handle_blur)
94+
6295
return () => {
63-
window.removeEventListener('mouseup', handle_mouse_up)
6496
window.removeEventListener('keydown', handle_key_down)
6597
window.removeEventListener('keyup', handle_key_up)
6698
window.removeEventListener('blur', handle_blur)
6799
}
68100
}, [
69101
params.is_active,
70-
params.on_go_forward,
71102
params.on_chatbots_click,
72-
params.on_api_calls_click
103+
params.on_api_calls_click,
104+
params.on_cli_calls_click
73105
])
106+
107+
return { is_alt_pressed }
74108
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@ export const MainView: React.FC<Props> = (props) => {
513513
on_tabs_reorder={props.on_tabs_reorder}
514514
voice_input_push_to_talk={props.voice_input_push_to_talk}
515515
currently_open_file_path={props.currently_open_file_path}
516+
are_keyboard_shortcuts_disabled={
517+
props.are_keyboard_shortcuts_disabled
518+
}
516519
translations={{
517520
voice_input: t('prompt-field.voice-input'),
518521
stop_recording: t('prompt-field.stop-recording'),
@@ -540,6 +543,7 @@ export const MainView: React.FC<Props> = (props) => {
540543
attach_selected_files: t('prompt-field.attach-selected-files'),
541544
more: t('prompt-field.more')
542545
}}
546+
543547
/>
544548
</div>
545549

‎apps/editor/src/views/prompt/frontend/Prompt.tsx‎

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -265,12 +265,6 @@ export const Prompt = () => {
265265
}
266266

267267
const current_state = get_current_instructions_state()
268-
const are_keyboard_shortcuts_disabled =
269-
!!updating_web_configuration ||
270-
!!updating_api_configuration ||
271-
!!updating_cli_configuration ||
272-
!!items_in_preview ||
273-
active_view != 'main'
274268

275269
const is_main_slot_hidden =
276270
!!updating_web_configuration ||
@@ -298,7 +292,11 @@ export const Prompt = () => {
298292
set_api_configurations={set_api_configurations}
299293
scroll_reset_key={main_view_scroll_reset_key}
300294
are_keyboard_shortcuts_disabled={
301-
are_keyboard_shortcuts_disabled
295+
!!updating_web_configuration ||
296+
!!updating_api_configuration ||
297+
!!updating_cli_configuration ||
298+
!!items_in_preview ||
299+
active_view == 'home'
302300
}
303301
vscode={vscode}
304302
on_web_configuration_edit={(web_configuration) => {
@@ -412,7 +410,6 @@ export const Prompt = () => {
412410
web_prompt_type={web_prompt_type}
413411
api_prompt_type={api_prompt_type}
414412
cli_prompt_type={cli_prompt_type}
415-
on_go_forward={() => set_active_view('main')}
416413
on_chatbots_click={() => {
417414
set_active_view('main')
418415
set_main_view_scroll_reset_key((k) => k + 1)
@@ -544,13 +541,13 @@ export const Prompt = () => {
544541
}
545542
title="Edit Agent"
546543
>
547-
<EditCliConfigurationForm
548-
cli_configuration={updating_cli_configuration}
549-
on_update={set_updated_cli_configuration}
550-
pick_agent={(agent_id) => {
551-
post_message(vscode, { command: 'PICK_AGENT', agent_id })
552-
}}
553-
/>
544+
<EditCliConfigurationForm
545+
cli_configuration={updating_cli_configuration}
546+
on_update={set_updated_cli_configuration}
547+
pick_agent={(agent_id) => {
548+
post_message(vscode, { command: 'PICK_AGENT', agent_id })
549+
}}
550+
/>
554551
</UiPage>
555552
</div>
556553
)}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export type PromptFieldProps = {
9191
target: Target
9292
on_target_change: (target: Target) => void
9393
active_border_color?: 'blue' | 'purple' | 'yellow'
94+
are_keyboard_shortcuts_disabled?: boolean
9495
translations: {
9596
voice_input: string
9697
stop_recording: string
@@ -114,6 +115,7 @@ export type PromptFieldProps = {
114115
attach_selected_files: string
115116
more: string
116117
}
118+
117119
}
118120

119121
export const PromptField: React.FC<PromptFieldProps> = (props) => {

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export const use_keyboard_shortcuts = (props: PromptFieldProps) => {
2727

2828
useEffect(() => {
2929
const handle_key_down = (e: KeyboardEvent) => {
30+
if (props.are_keyboard_shortcuts_disabled) return
3031
if (e.code == 'AltLeft') {
3132
left_alt_pressed_ref.current = true
3233
}
@@ -130,12 +131,14 @@ export const use_keyboard_shortcuts = (props: PromptFieldProps) => {
130131
}, [
131132
props.show_edit_format_selector,
132133
props.on_edit_format_change,
133-
props.edit_format
134+
props.edit_format,
135+
props.are_keyboard_shortcuts_disabled
134136
])
135137

136138
const handle_container_key_down = (
137139
e: React.KeyboardEvent<HTMLDivElement>
138140
) => {
141+
if (props.are_keyboard_shortcuts_disabled) return
139142
if (e.key == 'Escape' && !e.ctrlKey && !e.metaKey && !e.altKey) {
140143
if (props.is_recording) {
141144
props.on_recording_finished()

0 commit comments

Comments
 (0)