@workbench-kit/shell-react 0.0.2-prototype.0.2.13 → 0.0.2-prototype.0.2.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -0
- package/package.json +11 -8
- package/src/chat/command-error-message.ts +7 -0
- package/src/chat/command-surface.tsx +1 -8
- package/src/chat/use-chat-command-proposals.ts +1 -8
- package/src/editor/state-storage.ts +10 -21
- package/src/field-remap/convert-note-editor.tsx +11 -16
- package/src/field-remap/convert-palette.tsx +4 -5
- package/src/field-remap/flow-sync-key.ts +149 -0
- package/src/field-remap/flow.tsx +35 -19
- package/src/field-remap/samples.ts +1 -14
- package/src/field-remap/view.css +12 -1
- package/src/index.ts +8 -0
- package/src/management/keybinding-overrides-storage.ts +9 -23
- package/src/management/preference-settings-storage.ts +9 -23
- package/src/shell/chrome-labels.ts +98 -0
- package/src/shell/model.tsx +63 -1
- package/src/shell/secondary-actions.tsx +10 -3
- package/src/shell/shell.tsx +106 -12
- package/src/shell/view-host.tsx +73 -0
- package/src/storage/local-json-storage.ts +66 -0
- package/src/workbench/appearance-storage.ts +14 -27
- package/src/workbench/command-host.tsx +145 -8
- package/src/workbench/layout-storage.ts +22 -24
|
@@ -4,8 +4,14 @@ import {
|
|
|
4
4
|
} from '@workbench-kit/platform';
|
|
5
5
|
import {
|
|
6
6
|
WorkbenchCommandPalette,
|
|
7
|
+
WorkbenchQuickOpen,
|
|
7
8
|
WorkbenchShortcutCommandBridge,
|
|
8
9
|
createWorkbenchShellCommands,
|
|
10
|
+
createWorkspaceFilesQuickOpenProvider,
|
|
11
|
+
resolveQuickOpenItemPath,
|
|
12
|
+
type QuickOpenItem,
|
|
13
|
+
type QuickOpenProvider,
|
|
14
|
+
type QuickOpenSelectContext,
|
|
9
15
|
type WorkbenchCommandDescriptor,
|
|
10
16
|
type WorkbenchCommandRunContext,
|
|
11
17
|
type WorkbenchShellCommandContext,
|
|
@@ -22,33 +28,94 @@ import {
|
|
|
22
28
|
resolveShellCommandActivities,
|
|
23
29
|
} from './command-palette.js';
|
|
24
30
|
import { resolveExtensionKeybindingCommand } from './keybinding-bridge.js';
|
|
31
|
+
import { isWorkspaceResourceService, useWorkspaceResourceState } from './workspace-view-state.js';
|
|
32
|
+
|
|
33
|
+
const WORKSPACE_OPEN_COMMAND_ID = 'workspace.open' as const;
|
|
25
34
|
|
|
26
35
|
export interface WorkbenchCommandHostProps {
|
|
27
36
|
additionalCommands?: readonly WorkbenchCommandDescriptor[];
|
|
37
|
+
/** Override command palette close control label (default English). */
|
|
38
|
+
commandPaletteCloseLabel?: string | undefined;
|
|
39
|
+
/** Override command palette empty-state copy (default English). */
|
|
40
|
+
commandPaletteEmptyLabel?: string | undefined;
|
|
41
|
+
/** Override command palette search placeholder (default English). */
|
|
42
|
+
commandPalettePlaceholder?: string | undefined;
|
|
43
|
+
/** Override command palette dialog title (default English). */
|
|
44
|
+
commandPaletteTitle?: string | undefined;
|
|
28
45
|
enableCommandPalette?: boolean;
|
|
29
46
|
enableExtensionKeybindings?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* When true (default), Ctrl/Cmd+P opens Quick Open instead of the command palette.
|
|
49
|
+
* Ctrl/Cmd+Shift+P still opens the command palette.
|
|
50
|
+
*/
|
|
51
|
+
enableQuickOpen?: boolean;
|
|
30
52
|
enableShortcutBridge?: boolean;
|
|
31
53
|
onOpenSettings: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Called when a Quick Open item is selected. Return `true` to skip the default
|
|
56
|
+
* `workspace.open` path for file items.
|
|
57
|
+
*/
|
|
58
|
+
onOpenQuickOpenItem?: (item: QuickOpenItem, context: QuickOpenSelectContext) => boolean | void;
|
|
32
59
|
onRunCommand?: (
|
|
33
60
|
command: WorkbenchCommandDescriptor,
|
|
34
61
|
context: WorkbenchCommandRunContext,
|
|
35
62
|
) => boolean | void;
|
|
63
|
+
/** Override Quick Open close control label (default English). */
|
|
64
|
+
quickOpenCloseLabel?: string | undefined;
|
|
65
|
+
/** Override Quick Open empty-state copy (default English). */
|
|
66
|
+
quickOpenEmptyLabel?: string | undefined;
|
|
67
|
+
/** Override Quick Open search placeholder (default English). */
|
|
68
|
+
quickOpenPlaceholder?: string | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* Extra / replacement Quick Open providers. When omitted, the host wires a
|
|
71
|
+
* workspace-files provider from the registered workspace host port.
|
|
72
|
+
*/
|
|
73
|
+
quickOpenProviders?: readonly QuickOpenProvider[];
|
|
74
|
+
/** Override Quick Open dialog title (default English). */
|
|
75
|
+
quickOpenTitle?: string | undefined;
|
|
76
|
+
/** Optional recent paths elevated when the Quick Open query is empty. */
|
|
77
|
+
quickOpenRecentPaths?: readonly string[] | undefined;
|
|
36
78
|
}
|
|
37
79
|
|
|
38
80
|
export function WorkbenchCommandHost({
|
|
39
81
|
additionalCommands = [],
|
|
82
|
+
commandPaletteCloseLabel = 'Close command palette',
|
|
83
|
+
commandPaletteEmptyLabel = 'No commands match your search',
|
|
84
|
+
commandPalettePlaceholder = 'Search commands',
|
|
85
|
+
commandPaletteTitle = 'Command Palette',
|
|
40
86
|
enableCommandPalette = true,
|
|
41
87
|
enableExtensionKeybindings = true,
|
|
88
|
+
enableQuickOpen = true,
|
|
42
89
|
enableShortcutBridge = true,
|
|
43
90
|
onOpenSettings,
|
|
91
|
+
onOpenQuickOpenItem,
|
|
44
92
|
onRunCommand,
|
|
93
|
+
quickOpenCloseLabel = 'Close Quick Open',
|
|
94
|
+
quickOpenEmptyLabel = 'No matching files',
|
|
95
|
+
quickOpenPlaceholder = 'Search files by name',
|
|
96
|
+
quickOpenProviders,
|
|
97
|
+
quickOpenRecentPaths,
|
|
98
|
+
quickOpenTitle = 'Quick Open',
|
|
45
99
|
}: WorkbenchCommandHostProps) {
|
|
46
|
-
const {
|
|
100
|
+
const {
|
|
101
|
+
executeCommand,
|
|
102
|
+
extensionRegistry,
|
|
103
|
+
keybindingOverrides,
|
|
104
|
+
layoutService,
|
|
105
|
+
workspaceHostPort,
|
|
106
|
+
} = useWorkbench();
|
|
47
107
|
const [paletteOpen, setPaletteOpen] = useState(false);
|
|
48
108
|
const [paletteQuery, setPaletteQuery] = useState('');
|
|
109
|
+
const [quickOpenOpen, setQuickOpenOpen] = useState(false);
|
|
110
|
+
const [quickOpenQuery, setQuickOpenQuery] = useState('');
|
|
49
111
|
const [layout, setLayout] = useState(() => layoutService.getState());
|
|
50
112
|
const shellContextRef = useRef<WorkbenchShellCommandContext | undefined>(undefined);
|
|
51
113
|
|
|
114
|
+
const workspaceService = isWorkspaceResourceService(workspaceHostPort?.service)
|
|
115
|
+
? workspaceHostPort.service
|
|
116
|
+
: undefined;
|
|
117
|
+
const workspaceState = useWorkspaceResourceState(workspaceService);
|
|
118
|
+
|
|
52
119
|
useEffect(() => {
|
|
53
120
|
const disposable = layoutService.onDidChangeLayout(({ state }) => {
|
|
54
121
|
setLayout(state);
|
|
@@ -127,18 +194,43 @@ export function WorkbenchCommandHost({
|
|
|
127
194
|
shellCommands: shellCommandDefinitions,
|
|
128
195
|
shellContext,
|
|
129
196
|
}),
|
|
130
|
-
[additionalCommands, extensionRegistry, shellContext],
|
|
197
|
+
[additionalCommands, extensionRegistry, shellContext, shellCommandDefinitions],
|
|
131
198
|
);
|
|
132
199
|
|
|
200
|
+
const resolvedQuickOpenProviders = useMemo(() => {
|
|
201
|
+
if (quickOpenProviders) {
|
|
202
|
+
return quickOpenProviders;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const files = workspaceState?.files ?? workspaceService?.getState().files ?? [];
|
|
206
|
+
return [
|
|
207
|
+
createWorkspaceFilesQuickOpenProvider({
|
|
208
|
+
files: () => workspaceService?.getState().files ?? files,
|
|
209
|
+
recentPaths: quickOpenRecentPaths,
|
|
210
|
+
}),
|
|
211
|
+
];
|
|
212
|
+
}, [quickOpenProviders, quickOpenRecentPaths, workspaceService, workspaceState?.files]);
|
|
213
|
+
|
|
133
214
|
const closePalette = useCallback(() => {
|
|
134
215
|
setPaletteOpen(false);
|
|
135
216
|
}, []);
|
|
136
217
|
|
|
137
218
|
const openPalette = useCallback((query = '') => {
|
|
219
|
+
setQuickOpenOpen(false);
|
|
138
220
|
setPaletteQuery(query);
|
|
139
221
|
setPaletteOpen(true);
|
|
140
222
|
}, []);
|
|
141
223
|
|
|
224
|
+
const closeQuickOpen = useCallback(() => {
|
|
225
|
+
setQuickOpenOpen(false);
|
|
226
|
+
}, []);
|
|
227
|
+
|
|
228
|
+
const openQuickOpen = useCallback((query = '') => {
|
|
229
|
+
setPaletteOpen(false);
|
|
230
|
+
setQuickOpenQuery(query);
|
|
231
|
+
setQuickOpenOpen(true);
|
|
232
|
+
}, []);
|
|
233
|
+
|
|
142
234
|
const runPaletteCommand = useCallback(
|
|
143
235
|
(command: WorkbenchCommandDescriptor, context: WorkbenchCommandRunContext) => {
|
|
144
236
|
const finish = () => {
|
|
@@ -155,13 +247,35 @@ export function WorkbenchCommandHost({
|
|
|
155
247
|
[closePalette, executeCommand, onRunCommand],
|
|
156
248
|
);
|
|
157
249
|
|
|
250
|
+
const runQuickOpenItem = useCallback(
|
|
251
|
+
(item: QuickOpenItem, context: QuickOpenSelectContext) => {
|
|
252
|
+
const finish = () => {
|
|
253
|
+
closeQuickOpen();
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
if (onOpenQuickOpenItem?.(item, context)) {
|
|
257
|
+
finish();
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
const path = resolveQuickOpenItemPath(item);
|
|
262
|
+
if (!path) {
|
|
263
|
+
finish();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
void executeCommand(WORKSPACE_OPEN_COMMAND_ID, { path }).finally(finish);
|
|
268
|
+
},
|
|
269
|
+
[closeQuickOpen, executeCommand, onOpenQuickOpenItem],
|
|
270
|
+
);
|
|
271
|
+
|
|
158
272
|
useEffect(() => {
|
|
159
|
-
if (!enableCommandPalette) {
|
|
273
|
+
if (!enableCommandPalette && !enableQuickOpen) {
|
|
160
274
|
return undefined;
|
|
161
275
|
}
|
|
162
276
|
|
|
163
277
|
const onKeyDown = (event: KeyboardEvent) => {
|
|
164
|
-
if (matchesWorkbenchCommandPaletteShortcut(event)) {
|
|
278
|
+
if (enableCommandPalette && matchesWorkbenchCommandPaletteShortcut(event)) {
|
|
165
279
|
event.preventDefault();
|
|
166
280
|
openPalette('>');
|
|
167
281
|
return;
|
|
@@ -169,7 +283,14 @@ export function WorkbenchCommandHost({
|
|
|
169
283
|
|
|
170
284
|
if (matchesWorkbenchQuickAccessShortcut(event)) {
|
|
171
285
|
event.preventDefault();
|
|
172
|
-
|
|
286
|
+
if (enableQuickOpen) {
|
|
287
|
+
openQuickOpen();
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (enableCommandPalette) {
|
|
292
|
+
openPalette();
|
|
293
|
+
}
|
|
173
294
|
}
|
|
174
295
|
};
|
|
175
296
|
|
|
@@ -177,7 +298,7 @@ export function WorkbenchCommandHost({
|
|
|
177
298
|
return () => {
|
|
178
299
|
window.removeEventListener('keydown', onKeyDown);
|
|
179
300
|
};
|
|
180
|
-
}, [enableCommandPalette, openPalette]);
|
|
301
|
+
}, [enableCommandPalette, enableQuickOpen, openPalette, openQuickOpen]);
|
|
181
302
|
|
|
182
303
|
useEffect(() => {
|
|
183
304
|
if (!enableExtensionKeybindings) {
|
|
@@ -228,16 +349,32 @@ export function WorkbenchCommandHost({
|
|
|
228
349
|
) : null}
|
|
229
350
|
{enableCommandPalette ? (
|
|
230
351
|
<WorkbenchCommandPalette
|
|
352
|
+
closeLabel={commandPaletteCloseLabel}
|
|
231
353
|
commands={paletteCommands}
|
|
354
|
+
emptyLabel={commandPaletteEmptyLabel}
|
|
232
355
|
open={paletteOpen}
|
|
233
|
-
placeholder=
|
|
356
|
+
placeholder={commandPalettePlaceholder}
|
|
234
357
|
query={paletteQuery}
|
|
235
|
-
title=
|
|
358
|
+
title={commandPaletteTitle}
|
|
236
359
|
onClose={closePalette}
|
|
237
360
|
onQueryChange={setPaletteQuery}
|
|
238
361
|
onRunCommand={runPaletteCommand}
|
|
239
362
|
/>
|
|
240
363
|
) : null}
|
|
364
|
+
{enableQuickOpen ? (
|
|
365
|
+
<WorkbenchQuickOpen
|
|
366
|
+
closeLabel={quickOpenCloseLabel}
|
|
367
|
+
emptyLabel={quickOpenEmptyLabel}
|
|
368
|
+
open={quickOpenOpen}
|
|
369
|
+
placeholder={quickOpenPlaceholder}
|
|
370
|
+
providers={resolvedQuickOpenProviders}
|
|
371
|
+
query={quickOpenQuery}
|
|
372
|
+
title={quickOpenTitle}
|
|
373
|
+
onClose={closeQuickOpen}
|
|
374
|
+
onQueryChange={setQuickOpenQuery}
|
|
375
|
+
onSelectItem={runQuickOpenItem}
|
|
376
|
+
/>
|
|
377
|
+
) : null}
|
|
241
378
|
</>
|
|
242
379
|
);
|
|
243
380
|
}
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
type WorkbenchLayoutConfig,
|
|
4
4
|
} from '@workbench-kit/workbench-config';
|
|
5
5
|
import {
|
|
6
|
-
createBrowserWorkbenchStorage,
|
|
7
6
|
createWorkbenchLayoutState,
|
|
8
7
|
type WorkbenchStorageReader,
|
|
9
8
|
type WorkbenchStorageWriter,
|
|
@@ -11,10 +10,16 @@ import {
|
|
|
11
10
|
type WorkbenchLayoutStateInput,
|
|
12
11
|
} from '@workbench-kit/workbench-core';
|
|
13
12
|
|
|
13
|
+
import {
|
|
14
|
+
readLocalJsonStorage,
|
|
15
|
+
resolveLocalWorkbenchStorage,
|
|
16
|
+
writeLocalJsonStorage,
|
|
17
|
+
} from '../storage/local-json-storage.js';
|
|
18
|
+
|
|
14
19
|
export const DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY = 'workbench-kit/.workbench/layout';
|
|
15
20
|
|
|
16
21
|
export function isWorkbenchLayoutPersistenceAvailable(): boolean {
|
|
17
|
-
return
|
|
22
|
+
return resolveLocalWorkbenchStorage() !== undefined;
|
|
18
23
|
}
|
|
19
24
|
|
|
20
25
|
export function workbenchLayoutConfigToInput(
|
|
@@ -30,6 +35,8 @@ export function workbenchLayoutConfigToInput(
|
|
|
30
35
|
visible: config.auxiliaryBar.visible,
|
|
31
36
|
},
|
|
32
37
|
panel: {
|
|
38
|
+
activeViewContainer: config.panel.activeViewContainer,
|
|
39
|
+
sizePercent: config.panel.sizePercent,
|
|
33
40
|
visible: config.panel.visible,
|
|
34
41
|
},
|
|
35
42
|
sideBar: {
|
|
@@ -58,6 +65,10 @@ export function workbenchLayoutStateToStorageValue(
|
|
|
58
65
|
},
|
|
59
66
|
panel: {
|
|
60
67
|
visible: state.panel.visible,
|
|
68
|
+
...(state.panel.activeViewContainer
|
|
69
|
+
? { activeViewContainer: state.panel.activeViewContainer }
|
|
70
|
+
: {}),
|
|
71
|
+
...(state.panel.sizePercent !== undefined ? { sizePercent: state.panel.sizePercent } : {}),
|
|
61
72
|
},
|
|
62
73
|
sideBar: {
|
|
63
74
|
visible: state.sideBar.visible,
|
|
@@ -75,17 +86,12 @@ export function readPersistedWorkbenchLayout(
|
|
|
75
86
|
storageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
|
|
76
87
|
storage?: WorkbenchStorageReader,
|
|
77
88
|
): WorkbenchLayoutStateInput | undefined {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return workbenchLayoutConfigToInput(parseWorkbenchLayoutConfig(JSON.parse(raw) as unknown));
|
|
86
|
-
} catch {
|
|
87
|
-
return undefined;
|
|
88
|
-
}
|
|
89
|
+
return readLocalJsonStorage(
|
|
90
|
+
storageKey,
|
|
91
|
+
(value) => workbenchLayoutConfigToInput(parseWorkbenchLayoutConfig(value)),
|
|
92
|
+
() => undefined,
|
|
93
|
+
storage,
|
|
94
|
+
);
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
export function writePersistedWorkbenchLayout(
|
|
@@ -93,17 +99,9 @@ export function writePersistedWorkbenchLayout(
|
|
|
93
99
|
storageKey = DEFAULT_WORKBENCH_LAYOUT_STORAGE_KEY,
|
|
94
100
|
storage?: WorkbenchStorageWriter,
|
|
95
101
|
): void {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
try {
|
|
100
|
-
resolvedStorage.setItem(
|
|
101
|
-
storageKey,
|
|
102
|
-
JSON.stringify(workbenchLayoutStateToStorageValue(state), null, 2),
|
|
103
|
-
);
|
|
104
|
-
} catch {
|
|
105
|
-
// Ignore quota and security errors so the shell keeps working offline.
|
|
106
|
-
}
|
|
102
|
+
writeLocalJsonStorage(storageKey, state, storage, {
|
|
103
|
+
toStorageValue: workbenchLayoutStateToStorageValue,
|
|
104
|
+
});
|
|
107
105
|
}
|
|
108
106
|
|
|
109
107
|
export function resolvePersistedWorkbenchLayout(
|