@workbench-kit/shell-react 0.0.2-prototype.0.2.25 → 0.0.2-prototype.0.2.27

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.
@@ -1,6 +1,5 @@
1
1
  import { useCallback, useEffect, useMemo, useReducer, useState, type ReactNode } from 'react';
2
2
  import { Modal } from '@workbench-kit/react/modal';
3
- import { TilepaperAppIcon } from '@workbench-kit/react';
4
3
  import { Badge, Button, IconButton } from '@workbench-kit/react/primitives';
5
4
  import {
6
5
  WorkbenchSettingsModal,
@@ -89,6 +88,8 @@ export type { WorkbenchLocaleOption, WorkbenchThemeOption } from './settings.js'
89
88
  export interface WorkbenchShellProps {
90
89
  accountManagement?: WorkbenchAccountManagementInput | undefined;
91
90
  additionalSettingsCategories?: readonly WorkbenchSettingsCategory[] | undefined;
91
+ /** Host-owned product mark shown by the default title bar. */
92
+ appIcon?: ReactNode;
92
93
  catalogTrustPolicy?: ExtensionCatalogTrustPolicy | undefined;
93
94
  catalogUrl?: string | undefined;
94
95
  commandHost?: false | Omit<WorkbenchCommandHostProps, 'onOpenSettings'>;
@@ -147,6 +148,7 @@ const OPEN_SETTINGS_COMMAND_ID = 'workbench-kit.builtin.settings.open';
147
148
  export function WorkbenchShell({
148
149
  accountManagement,
149
150
  additionalSettingsCategories,
151
+ appIcon,
150
152
  catalogTrustPolicy,
151
153
  catalogUrl = '/extension-catalog.json',
152
154
  commandHost,
@@ -383,6 +385,7 @@ export function WorkbenchShell({
383
385
  const resolvedTitleBar =
384
386
  titleBar === undefined ? (
385
387
  <WorkbenchShellTitleBar
388
+ appIcon={appIcon}
386
389
  helpContent={helpContent}
387
390
  isAuxiliarySidebarVisible={layout.auxiliaryBar.visible}
388
391
  isPanelVisible={layout.panel.visible}
@@ -725,6 +728,7 @@ export function WorkbenchShell({
725
728
  }
726
729
 
727
730
  function WorkbenchShellTitleBar({
731
+ appIcon,
728
732
  helpContent,
729
733
  isAuxiliarySidebarVisible,
730
734
  isPanelVisible,
@@ -739,6 +743,7 @@ function WorkbenchShellTitleBar({
739
743
  onTogglePanel,
740
744
  onTogglePrimarySidebar,
741
745
  }: {
746
+ appIcon: ReactNode | undefined;
742
747
  helpContent: ReactNode | undefined;
743
748
  isAuxiliarySidebarVisible: boolean;
744
749
  isPanelVisible: boolean;
@@ -756,9 +761,11 @@ function WorkbenchShellTitleBar({
756
761
  return (
757
762
  <>
758
763
  <div className="workbench-shell-titlebar__identity">
759
- <span aria-hidden className="workbench-shell-titlebar__app-icon">
760
- <TilepaperAppIcon compact />
761
- </span>
764
+ {appIcon ? (
765
+ <span aria-hidden className="workbench-shell-titlebar__app-icon">
766
+ {appIcon}
767
+ </span>
768
+ ) : null}
762
769
  <span className="workbench-shell-titlebar__title">{title}</span>
763
770
  {titleMeta ? <span className="workbench-shell-titlebar__meta">{titleMeta}</span> : null}
764
771
  </div>
@@ -18,6 +18,7 @@ import {
18
18
  } from '@workbench-kit/react/workbench';
19
19
  import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
20
20
 
21
+ import { useContextKeyRevision } from '../commands/use-context-key-revision.js';
21
22
  import { useWorkbench } from '../shell/provider.js';
22
23
  import { registerWorkbenchShellCommandHandlers } from './shell-command-registration.js';
23
24
  import {
@@ -98,6 +99,7 @@ export function WorkbenchCommandHost({
98
99
  quickOpenTitle = 'Quick Open',
99
100
  }: WorkbenchCommandHostProps) {
100
101
  const {
102
+ contextKeyService,
101
103
  executeCommand,
102
104
  extensionRegistry,
103
105
  keybindingOverrides,
@@ -110,6 +112,11 @@ export function WorkbenchCommandHost({
110
112
  const [quickOpenQuery, setQuickOpenQuery] = useState('');
111
113
  const [layout, setLayout] = useState(() => layoutService.getState());
112
114
  const shellContextRef = useRef<WorkbenchShellCommandContext | undefined>(undefined);
115
+ const contextKeyRevision = useContextKeyRevision(contextKeyService);
116
+ const contextKeySnapshot = useMemo(
117
+ () => contextKeyService.createSnapshot(),
118
+ [contextKeyRevision, contextKeyService],
119
+ );
113
120
 
114
121
  const workspaceService = isWorkspaceResourceService(workspaceHostPort?.service)
115
122
  ? workspaceHostPort.service
@@ -126,19 +133,41 @@ export function WorkbenchCommandHost({
126
133
  };
127
134
  }, [layoutService]);
128
135
 
129
- const shellActivities = useMemo(
136
+ const managedShellActivities = useMemo(
130
137
  () => resolveShellCommandActivities(extensionRegistry),
131
138
  [extensionRegistry],
132
139
  );
140
+ const visibleShellActivities = useMemo(
141
+ () => resolveShellCommandActivities(extensionRegistry, contextKeySnapshot),
142
+ [contextKeySnapshot, extensionRegistry],
143
+ );
144
+ const visibleShellActivityIdSet = new Set(visibleShellActivities.map((activity) => activity.id));
145
+ const visibleShellActivitySignature = managedShellActivities
146
+ .map((activity) => (visibleShellActivityIdSet.has(activity.id) ? '1' : '0'))
147
+ .join('');
133
148
 
134
149
  const shellCommandDefinitions = useMemo(
135
150
  () =>
136
151
  createWorkbenchShellCommands({
137
- activities: shellActivities,
152
+ activities: managedShellActivities.filter(
153
+ (_activity, index) => visibleShellActivitySignature[index] === '1',
154
+ ),
138
155
  includeSettings: true,
139
156
  includeSidebarToggle: true,
140
157
  }),
141
- [shellActivities],
158
+ [managedShellActivities, visibleShellActivitySignature],
159
+ );
160
+
161
+ const managedShellCommandIds = useMemo(
162
+ () =>
163
+ new Set(
164
+ createWorkbenchShellCommands({
165
+ activities: managedShellActivities,
166
+ includeSettings: true,
167
+ includeSidebarToggle: true,
168
+ }).map((command) => command.id),
169
+ ),
170
+ [managedShellActivities],
142
171
  );
143
172
 
144
173
  const shellCommandRegistry = useMemo(
@@ -151,12 +180,16 @@ export function WorkbenchCommandHost({
151
180
 
152
181
  const shellContext = useMemo<WorkbenchShellCommandContext>(
153
182
  () => ({
183
+ isFocusModeActive: layoutService.isFocusModeActive(),
154
184
  isPrimarySidebarVisible: layout.sideBar.visible,
155
185
  openSettings: onOpenSettings,
156
186
  showActivity: (activityId) => {
157
187
  layoutService.setActiveViewContainer(activityId);
158
188
  layoutService.setSideBarVisible(true);
159
189
  },
190
+ toggleFocusMode: () => {
191
+ layoutService.setFocusModeActive(!layoutService.isFocusModeActive());
192
+ },
160
193
  togglePrimarySidebar: () => {
161
194
  layoutService.setSideBarVisible(!layout.sideBar.visible);
162
195
  },
@@ -190,11 +223,19 @@ export function WorkbenchCommandHost({
190
223
  buildWorkbenchPaletteCommands({
191
224
  additionalCommands,
192
225
  extensionCommandFeaturesById: collectExtensionCommandFeaturesById(extensionRegistry),
193
- extensionCommands: extensionRegistry.commands.getCommands(),
226
+ extensionCommands: extensionRegistry.commands
227
+ .getCommands()
228
+ .filter((command) => !managedShellCommandIds.has(command.id)),
194
229
  shellCommands: shellCommandDefinitions,
195
230
  shellContext,
196
231
  }),
197
- [additionalCommands, extensionRegistry, shellContext, shellCommandDefinitions],
232
+ [
233
+ additionalCommands,
234
+ extensionRegistry,
235
+ managedShellCommandIds,
236
+ shellContext,
237
+ shellCommandDefinitions,
238
+ ],
198
239
  );
199
240
 
200
241
  const resolvedQuickOpenProviders = useMemo(() => {
@@ -4,7 +4,11 @@ import type {
4
4
  WorkbenchShellCommandActivity,
5
5
  WorkbenchShellCommandContext,
6
6
  } from '@workbench-kit/react/workbench';
7
- import type { ExtensionCommandFeatureSpec, ExtensionRegistry } from '@workbench-kit/workbench-core';
7
+ import {
8
+ filterActivitiesByWhenClause,
9
+ type ExtensionCommandFeatureSpec,
10
+ type ExtensionRegistry,
11
+ } from '@workbench-kit/workbench-core';
8
12
 
9
13
  export const WORKBENCH_COMMAND_PALETTE_SHORTCUT = 'Ctrl+Shift+P';
10
14
  export const WORKBENCH_QUICK_ACCESS_SHORTCUT = 'Ctrl+P';
@@ -44,10 +48,16 @@ export function resolveExtensionCommandIcon(icon: ExtensionCommand['icon']): str
44
48
 
45
49
  export function resolveShellCommandActivities(
46
50
  extensionRegistry: ExtensionRegistry,
51
+ contextKeys?: object | undefined,
47
52
  ): WorkbenchShellCommandActivity[] {
48
53
  const activities = extensionRegistry.activities.getActivities();
49
54
  if (activities.length > 0) {
50
- return activities
55
+ const visibleActivities =
56
+ contextKeys === undefined
57
+ ? activities
58
+ : filterActivitiesByWhenClause(activities, contextKeys);
59
+
60
+ return visibleActivities
51
61
  .map((activity) => ({
52
62
  icon: formatWorkbenchCommandIcon(activity.icon),
53
63
  id: activity.viewContainerId,
@@ -1,10 +1,12 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
2
  import type {
3
3
  VirtualWorkspaceState,
4
4
  WorkspaceChangeEvent,
5
5
  WorkspaceResourceService,
6
6
  } from '@workbench-kit/workspace';
7
7
 
8
+ const EMPTY_WORKSPACE_FILES: VirtualWorkspaceState['files'] = [];
9
+
8
10
  export function isWorkspaceResourceService(value: unknown): value is WorkspaceResourceService {
9
11
  return (
10
12
  typeof value === 'object' &&
@@ -33,3 +35,18 @@ export function useWorkspaceResourceState(
33
35
 
34
36
  return state;
35
37
  }
38
+
39
+ export function useWorkspaceTextDocuments(workspaceService: WorkspaceResourceService | undefined) {
40
+ const workspaceState = useWorkspaceResourceState(workspaceService);
41
+ const files =
42
+ workspaceState?.files ?? workspaceService?.getState().files ?? EMPTY_WORKSPACE_FILES;
43
+ const documentsByPath = useMemo(
44
+ () => new Map(files.map((file) => [file.path.replace(/\\/g, '/'), file.content])),
45
+ [files],
46
+ );
47
+ const loadDocument = useCallback(
48
+ (documentPath: string) => documentsByPath.get(documentPath.replace(/\\/g, '/')) ?? null,
49
+ [documentsByPath],
50
+ );
51
+ return { files, loadDocument };
52
+ }