Skip to content

Commit 7f52031

Browse files
wolfibDevtools-frontend LUCI CQ
authored and
Devtools-frontend LUCI CQ
committed
[Patch agent] Handle automatic workspaces in select workspace dialog
Show automatic workspace folder in SelectWorkspaceDialog and enable connecting to it. Screencast: https://i.imgur.com/GNBp3oY.mp4 Bug: 399560823 Change-Id: If81564dd1b294b89b04f8c505f3e271117ed909a Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6382152 Commit-Queue: Wolfgang Beyer <wolfi@chromium.org> Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Ergün Erdoğmuş <ergunsh@chromium.org>
1 parent 5985fec commit 7f52031

File tree

8 files changed

+178
-54
lines changed

8 files changed

+178
-54
lines changed

front_end/models/workspace/WorkspaceImpl.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ export class WorkspaceImpl extends Common.ObjectWrapper.ObjectWrapper<EventTypes
293293
return this.projectsInternal.get(projectId) || null;
294294
}
295295

296+
projectForFileSystemRoot(root: Platform.DevToolsPath.RawPathString): Project|null {
297+
const projectId = Common.ParsedURL.ParsedURL.rawPathToUrlString(root);
298+
return this.project(projectId);
299+
}
300+
296301
projects(): Project[] {
297302
return [...this.projectsInternal.values()];
298303
}

front_end/panels/ai_assistance/PatchWidget.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
MockAidaAbortError,
1818
mockAidaClient,
1919
MockAidaFetchError,
20+
setupAutomaticFileSystem,
2021
} from '../../testing/AiAssistanceHelpers.js';
2122
import {updateHostConfig} from '../../testing/EnvironmentHelpers.js';
2223
import {describeWithMockConnection} from '../../testing/MockConnection.js';
@@ -30,6 +31,7 @@ describeWithMockConnection('PatchWidget', () => {
3031
showFreDialogStub = sinon.stub(PanelCommon.FreDialog, 'show');
3132

3233
initializePersistenceImplForTests();
34+
setupAutomaticFileSystem();
3335
});
3436

3537
afterEach(() => {
@@ -265,6 +267,7 @@ Files:
265267

266268
// Simulate clicking the "Change" button
267269
assert.isTrue(showSelectWorkspaceDialogStub.notCalled);
270+
assert.isDefined(view.input.onChangeWorkspaceClick);
268271
view.input.onChangeWorkspaceClick();
269272
assert.isTrue(showSelectWorkspaceDialogStub.calledOnce);
270273

front_end/panels/ai_assistance/PatchWidget.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import * as i18n from '../../core/i18n/i18n.js';
1414
import * as Platform from '../../core/platform/platform.js';
1515
import * as Root from '../../core/root/root.js';
1616
import * as AiAssistanceModel from '../../models/ai_assistance/ai_assistance.js';
17+
import * as Persistence from '../../models/persistence/persistence.js';
1718
import * as Workspace from '../../models/workspace/workspace.js';
1819
import * as WorkspaceDiff from '../../models/workspace_diff/workspace_diff.js';
1920
import * as Buttons from '../../ui/components/buttons/buttons.js';
@@ -159,7 +160,7 @@ export interface ViewInput {
159160
onCancel: () => void;
160161
onDiscard: () => void;
161162
onSaveAll: () => void;
162-
onChangeWorkspaceClick: () => void;
163+
onChangeWorkspaceClick?: () => void;
163164
}
164165

165166
export interface ViewOutput {
@@ -188,6 +189,8 @@ export class PatchWidget extends UI.Widget.Widget {
188189
#patchSuggestionState = PatchSuggestionState.INITIAL;
189190
#workspaceDiff = WorkspaceDiff.WorkspaceDiff.workspaceDiff();
190191
#workspace = Workspace.Workspace.WorkspaceImpl.instance();
192+
#automaticFileSystem =
193+
Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.instance().automaticFileSystem;
191194

192195
constructor(element?: HTMLElement, view?: View, opts?: {
193196
aidaClient: Host.AidaClient.AidaClient,
@@ -324,13 +327,15 @@ export class PatchWidget extends UI.Widget.Widget {
324327
<div class="selected-folder">
325328
<devtools-icon .name=${'folder'}></devtools-icon> <span class="folder-name" title=${input.projectPath}>${input.projectName}</span>
326329
</div>
327-
<devtools-button
328-
@click=${input.onChangeWorkspaceClick}
329-
.jslogContext=${'change-workspace'}
330-
.variant=${Buttons.Button.Variant.TEXT}
331-
.title=${lockedString(UIStringsNotTranslate.changeRootFolder)}
332-
${Directives.ref(output.changeRef)}
333-
>${lockedString(UIStringsNotTranslate.change)}</devtools-button>
330+
${input.onChangeWorkspaceClick ? html`
331+
<devtools-button
332+
@click=${input.onChangeWorkspaceClick}
333+
.jslogContext=${'change-workspace'}
334+
.variant=${Buttons.Button.Variant.TEXT}
335+
.title=${lockedString(UIStringsNotTranslate.changeRootFolder)}
336+
${Directives.ref(output.changeRef)}
337+
>${lockedString(UIStringsNotTranslate.change)}</devtools-button>
338+
` : nothing}
334339
</div>
335340
` : nothing}
336341
<div class="apply-to-workspace-container">
@@ -412,6 +417,15 @@ export class PatchWidget extends UI.Widget.Widget {
412417
Common.ParsedURL.ParsedURL.urlToRawPathString(
413418
this.#project.id() as Platform.DevToolsPath.UrlString, Host.Platform.isWin()) :
414419
Platform.DevToolsPath.EmptyRawPathString;
420+
const automaticFileSystemProject =
421+
this.#automaticFileSystem ? this.#workspace.projectForFileSystemRoot(this.#automaticFileSystem.root) : null;
422+
const projects = this.#workspace.projectsForType(Workspace.Workspace.projectTypes.FileSystem)
423+
.filter(
424+
project => project instanceof Persistence.FileSystemWorkspaceBinding.FileSystem &&
425+
project.fileSystem().type() ===
426+
Persistence.PlatformFileSystem.PlatformFileSystemType.WORKSPACE_PROJECT);
427+
const showChangeButton = projects.length > 1 || this.#project !== automaticFileSystemProject;
428+
415429
this.#view(
416430
{
417431
workspaceDiff: this.#workspaceDiff,
@@ -431,7 +445,8 @@ export class PatchWidget extends UI.Widget.Widget {
431445
},
432446
onDiscard: this.#onDiscard.bind(this),
433447
onSaveAll: this.#onSaveAll.bind(this),
434-
onChangeWorkspaceClick: this.#showSelectWorkspaceDialog.bind(this, {applyPatch: false}),
448+
onChangeWorkspaceClick: showChangeButton ? this.#showSelectWorkspaceDialog.bind(this, {applyPatch: false}) :
449+
undefined,
435450
},
436451
this.#viewOutput, this.contentElement);
437452
}
@@ -499,7 +514,9 @@ export class PatchWidget extends UI.Widget.Widget {
499514
}
500515

501516
#selectDefaultProject(): void {
502-
const project = this.#workspace.project(this.#projectIdSetting.get());
517+
const automaticFileSystemProject =
518+
this.#automaticFileSystem ? this.#workspace.projectForFileSystemRoot(this.#automaticFileSystem.root) : null;
519+
const project = automaticFileSystemProject || this.#workspace.project(this.#projectIdSetting.get());
503520
if (project) {
504521
this.#project = project;
505522
} else {

front_end/panels/ai_assistance/SelectWorkspaceDialog.test.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import * as Persistence from '../../models/persistence/persistence.js';
66
import * as Workspace from '../../models/workspace/workspace.js';
7-
import {createTestFilesystem} from '../../testing/AiAssistanceHelpers.js';
7+
import {createTestFilesystem, setupAutomaticFileSystem} from '../../testing/AiAssistanceHelpers.js';
88
import {dispatchKeyDownEvent, renderElementIntoDOM} from '../../testing/DOMHelpers.js';
99
import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';
1010
import {createViewFunctionStub, type ViewFunctionStub} from '../../testing/ViewFunctionHelpers.js';
@@ -13,11 +13,18 @@ import * as UI from '../../ui/legacy/legacy.js';
1313
import * as AiAssistance from './ai_assistance.js';
1414

1515
describeWithEnvironment('SelectWorkspaceDialog', () => {
16+
const root = '/path/to/my-automatic-file-system';
17+
18+
beforeEach(() => {
19+
setupAutomaticFileSystem();
20+
});
21+
1622
afterEach(() => {
1723
const workspace = Workspace.Workspace.WorkspaceImpl.instance();
1824
for (const project of workspace.projects()) {
1925
workspace.removeProject(project);
2026
}
27+
Persistence.AutomaticFileSystemManager.AutomaticFileSystemManager.removeInstance();
2128
});
2229

2330
function createComponent(): {
@@ -87,7 +94,7 @@ describeWithEnvironment('SelectWorkspaceDialog', () => {
8794
sinon.spy(Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.instance(), 'addFileSystem');
8895
const {view} = createComponent();
8996
assert.strictEqual(view.callCount, 1);
90-
assert.lengthOf(view.input.projects, 2);
97+
assert.lengthOf(view.input.folders, 2);
9198
assert.strictEqual(view.input.selectedIndex, 0);
9299

93100
view.input.onAddFolderButtonClick();
@@ -96,8 +103,8 @@ describeWithEnvironment('SelectWorkspaceDialog', () => {
96103
createTestFilesystem('file://test3');
97104
const input = await view.nextInput;
98105
assert.strictEqual(view.callCount, 2);
99-
assert.lengthOf(input.projects, 3);
100-
assert.strictEqual(input.projects[2].name, 'test3');
106+
assert.lengthOf(input.folders, 3);
107+
assert.strictEqual(input.folders[2].name, 'test3');
101108
assert.strictEqual(input.selectedIndex, 2);
102109
});
103110

@@ -109,15 +116,32 @@ describeWithEnvironment('SelectWorkspaceDialog', () => {
109116
view.input.onProjectSelected(1);
110117
let input = await view.nextInput;
111118
assert.strictEqual(view.callCount, 2);
112-
assert.lengthOf(input.projects, 2);
119+
assert.lengthOf(input.folders, 2);
113120
assert.strictEqual(input.selectedIndex, 1);
114121

115122
input.onAddFolderButtonClick();
116123
assert.isTrue(addProjectSpy.calledOnce);
117124

118125
Workspace.Workspace.WorkspaceImpl.instance().removeProject(project);
119126
input = await view.nextInput;
120-
assert.lengthOf(input.projects, 1);
127+
assert.lengthOf(input.folders, 1);
121128
assert.strictEqual(input.selectedIndex, 0);
122129
});
130+
131+
it('allows selecting an automatic workspace', async () => {
132+
setupAutomaticFileSystem({hasFileSystem: true});
133+
const {view, onProjectSelected, hideDialogSpy} = createComponent();
134+
135+
assert.strictEqual(view.callCount, 1);
136+
assert.lengthOf(view.input.folders, 3);
137+
assert.strictEqual(view.input.selectedIndex, 0);
138+
assert.strictEqual(view.input.folders[0].name, 'my-automatic-file-system');
139+
140+
view.input.onSelectButtonClick();
141+
await new Promise(resolve => setTimeout(resolve, 0));
142+
const {project: automaticFileSystemProject} = createTestFilesystem(`file://${root}`);
143+
144+
assert.isTrue(onProjectSelected.calledOnceWith(automaticFileSystemProject));
145+
assert.isTrue(hideDialogSpy.calledOnce);
146+
});
123147
});

0 commit comments

Comments
 (0)