Skip to content

Commit a40c74d

Browse files
committed
Implement workspace folder selection for tasks in the panel
- update_task_in_tree, add_subtask_to_tree should accept params variable, dont destructure in body - move handlers from `apps/editor/src/views/panel/frontend/hooks/use-tasks.ts` to `apps/editor/src/views/panel/frontend/Home/hooks/use-tasks.ts` - current behavior: in multi-root folder workspace, user can change tasks-related folder in a dropdown. expected behavior: They should be shown a quick pick through backend instead. - task-folder selecting quick pick should highlight currently piced folder - task-folder selecting quick pick should have title 'Workspace Folders', and close button on the right side. - the task's folder selector should not grow longer than necessary - the task's folder selector should have hover highlight
1 parent 4daa9db commit a40c74d

9 files changed

Lines changed: 239 additions & 115 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as vscode from 'vscode'
2+
import { PanelProvider } from '../panel-provider'
3+
import { PickTasksWorkspaceMessage } from '../../types/messages'
4+
5+
export const handle_pick_tasks_workspace = async (
6+
panel_provider: PanelProvider,
7+
message: PickTasksWorkspaceMessage
8+
) => {
9+
const items: vscode.QuickPickItem[] = message.roots.map((root) => ({
10+
label: root.split(/[\\/]/).pop() || root,
11+
description: root
12+
}))
13+
14+
const quick_pick = vscode.window.createQuickPick()
15+
quick_pick.items = items
16+
quick_pick.placeholder = 'Select workspace folder for tasks'
17+
quick_pick.matchOnDescription = true
18+
quick_pick.title = 'Workspace Folders'
19+
quick_pick.buttons = [
20+
{ iconPath: new vscode.ThemeIcon('close'), tooltip: 'Close' }
21+
]
22+
23+
if (message.active_root) {
24+
const active_item = items.find(
25+
(item) => item.description === message.active_root
26+
)
27+
if (active_item) {
28+
quick_pick.activeItems = [active_item]
29+
}
30+
}
31+
32+
const selected = await new Promise<vscode.QuickPickItem | undefined>(
33+
(resolve) => {
34+
let is_accepted = false
35+
quick_pick.onDidTriggerButton(() => {
36+
quick_pick.hide()
37+
})
38+
quick_pick.onDidAccept(() => {
39+
is_accepted = true
40+
resolve(quick_pick.selectedItems[0])
41+
quick_pick.hide()
42+
})
43+
quick_pick.onDidHide(() => {
44+
if (!is_accepted) {
45+
resolve(undefined)
46+
}
47+
quick_pick.dispose()
48+
})
49+
quick_pick.show()
50+
}
51+
)
52+
53+
if (selected && selected.description) {
54+
panel_provider.send_message({
55+
command: 'TASKS_WORKSPACE_PICKED',
56+
root: selected.description
57+
})
58+
}
59+
}

‎apps/editor/src/views/panel/backend/message-handlers/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,4 @@ export * from './handle-save-find-relevant-files-shrink-source-code'
7171
export * from './handle-update-last-used-web-configuration-or-group'
7272
export * from './handle-return-home-and-switch-to-edit-files'
7373
export * from './checkpoints/handlers'
74+
export * from './handle-pick-tasks-workspace'

‎apps/editor/src/views/panel/backend/panel-provider.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ import {
9292
handle_toggle_checkpoint_star,
9393
handle_restore_checkpoint,
9494
handle_restore_temp_checkpoint,
95-
handle_update_checkpoint_description
95+
handle_update_checkpoint_description,
96+
handle_pick_tasks_workspace
9697
} from './message-handlers'
9798
import { handle_update_api_configuration } from './message-handlers/handle-update-api-configuration'
9899
import { handle_pick_model_provider } from './message-handlers/handle-pick-model-provider'
@@ -987,6 +988,8 @@ export class PanelProvider implements vscode.WebviewViewProvider {
987988
)
988989
} else if (message.command == 'GET_VOICE_INPUT_PUSH_TO_TALK') {
989990
this._send_voice_input_push_to_talk()
991+
} else if (message.command == 'PICK_TASKS_WORKSPACE') {
992+
await handle_pick_tasks_workspace(this, message)
990993
}
991994
} catch (error: any) {
992995
Logger.error({

‎apps/editor/src/views/panel/frontend/Home/Home.module.scss‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,28 @@
119119

120120
&__workspace-dropdown {
121121
position: relative;
122+
display: flex;
123+
align-items: center;
122124
height: 24px;
123-
flex: 1;
124-
margin-right: 6px;
125+
min-width: 0;
126+
margin-right: 2px;
127+
128+
&-button {
129+
cursor: pointer;
130+
display: flex;
131+
align-items: center;
132+
gap: 4px;
133+
color: var(--vscode-descriptionForeground);
134+
font-size: 11px;
135+
min-width: 0;
136+
padding: 2px 4px;
137+
border-radius: 5px;
138+
139+
&:hover {
140+
background-color: var(--vscode-toolbar-hoverBackground);
141+
color: var(--vscode-icon-foreground);
142+
}
143+
}
125144
}
126145

127146
&__tasks {

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

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@ import { Checkpoints as UiCheckpoints } from '@ui/components/editor/panel/Checkp
55
import { ModeButton as UiModeButton } from '@ui/components/editor/panel/ModeButton'
66
import cn from 'classnames'
77
import { post_message } from '../utils/post-message'
8-
import { Checkpoint, FrontendMessage } from '@/views/panel/types/messages'
8+
import {
9+
Checkpoint,
10+
FrontendMessage,
11+
BackendMessage
12+
} from '@/views/panel/types/messages'
913
import { Responses as UiResponses } from '@ui/components/editor/panel/Responses'
1014
import { ResponseHistoryItem } from '@shared/types/response-history-item'
1115
import { Separator as UiSeparator } from '@ui/components/editor/panel/Separator'
1216
import { Tabs as UiTabs } from '@ui/components/editor/panel/Tabs'
1317
import { Translation, use_translation } from '../i18n/use-translation'
1418
import { IconButton as UiIconButton } from '@ui/components/editor/common/IconButton'
1519
import { Tasks as UiTasks } from '@ui/components/editor/panel/Tasks'
16-
import { Task } from '@shared/types/task'
1720
import { use_tasks } from './hooks/use-tasks'
1821
import { use_sticky_mode } from './hooks/use-sticky-mode'
1922
import { SettingsButton as UiSettingsButton } from '@ui/components/editor/panel/SettingsButton'
20-
import { InlineDropdown as UiInlineDropdown } from '@ui/components/editor/panel/InlineDropdown'
2123

2224
type Props = {
2325
vscode: any
@@ -38,9 +40,6 @@ type Props = {
3840
on_response_history_item_remove: (created_at: number) => void
3941
on_edit_checkpoint_description: (timestamp: number) => void
4042
on_delete_checkpoint: (timestamp: number) => void
41-
tasks: Record<string, Task[]>
42-
on_tasks_change: (root: string, tasks: Task[]) => void
43-
on_task_delete: (root: string, timestamp: number) => void
4443
on_task_forward: (text: string) => void
4544
is_setup_complete: boolean
4645
is_connected: boolean
@@ -61,12 +60,32 @@ export const Home: React.FC<Props> = (props) => {
6160
handle_scroll
6261
} = use_sticky_mode(props.is_active)
6362

64-
const roots = Object.keys(props.tasks)
63+
const {
64+
tasks,
65+
handle_reorder,
66+
handle_change,
67+
handle_add,
68+
handle_add_subtask,
69+
handle_delete
70+
} = use_tasks(props.vscode)
71+
72+
const roots = Object.keys(tasks)
6573
const active_root =
6674
active_workspace_root && roots.includes(active_workspace_root)
6775
? active_workspace_root
6876
: roots[0]
6977

78+
useEffect(() => {
79+
const handle_message = (event: MessageEvent<BackendMessage>) => {
80+
const message = event.data
81+
if (message.command == 'TASKS_WORKSPACE_PICKED') {
82+
set_active_workspace_root(message.root)
83+
}
84+
}
85+
window.addEventListener('message', handle_message)
86+
return () => window.removeEventListener('message', handle_message)
87+
}, [])
88+
7089
useEffect(() => {
7190
const handle_mouse_up = (event: MouseEvent) => {
7291
if (props.is_active && event.button == 4) {
@@ -78,14 +97,6 @@ export const Home: React.FC<Props> = (props) => {
7897
return () => window.removeEventListener('mouseup', handle_mouse_up)
7998
}, [props.is_active, props.on_go_forward])
8099

81-
const {
82-
handle_reorder,
83-
handle_change,
84-
handle_add,
85-
handle_add_subtask,
86-
handle_delete
87-
} = use_tasks(props.on_tasks_change, props.on_task_delete)
88-
89100
const handle_settings_click = () => {
90101
post_message(props.vscode, {
91102
command: 'EXECUTE_COMMAND',
@@ -186,15 +197,32 @@ export const Home: React.FC<Props> = (props) => {
186197
<>
187198
{roots.length > 1 && (
188199
<div className={styles['inner__workspace-dropdown']}>
189-
<UiInlineDropdown
190-
options={roots.map((root) => ({
191-
value: root,
192-
label: root.split(/[\\/]/).pop() || root
193-
}))}
194-
selected_value={active_root!}
195-
on_change={(val) => set_active_workspace_root(val)}
196-
info={t('home.folder')}
197-
/>
200+
<div
201+
className={styles['inner__workspace-dropdown-button']}
202+
onClick={(e) => {
203+
e.stopPropagation()
204+
post_message(props.vscode, {
205+
command: 'PICK_TASKS_WORKSPACE',
206+
roots,
207+
active_root
208+
} as FrontendMessage)
209+
}}
210+
title={t('home.folder')}
211+
>
212+
<span
213+
style={{
214+
overflow: 'hidden',
215+
textOverflow: 'ellipsis',
216+
whiteSpace: 'nowrap'
217+
}}
218+
>
219+
{active_root?.split(/[\\/]/).pop() || active_root}
220+
</span>
221+
<span
222+
className="codicon codicon-unfold"
223+
style={{ fontSize: '12px', flexShrink: 0 }}
224+
/>
225+
</div>
198226
</div>
199227
)}
200228
{roots.length > 0 && (
@@ -204,11 +232,7 @@ export const Home: React.FC<Props> = (props) => {
204232
on_click={(e) => {
205233
e.stopPropagation()
206234
if (active_root) {
207-
handle_add(
208-
active_root,
209-
props.tasks[active_root],
210-
'top'
211-
)
235+
handle_add(active_root, tasks[active_root], 'top')
212236
}
213237
}}
214238
/>
@@ -258,30 +282,30 @@ export const Home: React.FC<Props> = (props) => {
258282
)}
259283
{active_root && (
260284
<div className={styles.inner__tasks}>
261-
{props.tasks[active_root].length == 0 ? (
285+
{tasks[active_root].length == 0 ? (
262286
<div className={styles.inner__empty}>
263287
{t('home.tasks.empty')}
264288
</div>
265289
) : (
266290
<UiTasks
267-
tasks={props.tasks[active_root]}
291+
tasks={tasks[active_root]}
268292
on_reorder={(new_tasks) =>
269293
handle_reorder(active_root, new_tasks)
270294
}
271295
on_change={(updated_task) => {
272296
handle_change(
273297
active_root,
274-
props.tasks[active_root],
298+
tasks[active_root],
275299
updated_task
276300
)
277301
}}
278302
on_add={() => {
279-
handle_add(active_root, props.tasks[active_root])
303+
handle_add(active_root, tasks[active_root])
280304
}}
281305
on_add_subtask={(parent_task) => {
282306
handle_add_subtask(
283307
active_root,
284-
props.tasks[active_root],
308+
tasks[active_root],
285309
parent_task
286310
)
287311
}}

0 commit comments

Comments
 (0)