Skip to content

Commit 92786be

Browse files
committed
microsoft#100346 show view progress
1 parent 3e2f28f commit 92786be

2 files changed

Lines changed: 127 additions & 80 deletions

File tree

src/vs/workbench/contrib/userDataSync/browser/userDataManualSyncView.ts

Lines changed: 110 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { IUserDataSyncWorkbenchService, getSyncAreaLabel, CONTEXT_ENABLE_MANUAL_
2222
import { TreeView } from 'vs/workbench/contrib/views/browser/treeView';
2323
import { isEqual, basename } from 'vs/base/common/resources';
2424
import { IDecorationsProvider, IDecorationData, IDecorationsService } from 'vs/workbench/services/decorations/browser/decorations';
25+
import { IProgressService } from 'vs/platform/progress/common/progress';
2526

2627
const viewName = localize('manual sync', "Sync Manually");
2728

@@ -33,6 +34,9 @@ export class UserDataManualSyncView extends Disposable {
3334
constructor(
3435
container: ViewContainer,
3536
@IInstantiationService private readonly instantiationService: IInstantiationService,
37+
@IEditorService private readonly editorService: IEditorService,
38+
@IProgressService private readonly progressService: IProgressService,
39+
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
3640
@IUserDataSyncWorkbenchService userDataSyncWorkbenchService: IUserDataSyncWorkbenchService,
3741
@IDecorationsService decorationsService: IDecorationsService,
3842
) {
@@ -83,6 +87,7 @@ export class UserDataManualSyncView extends Disposable {
8387
const localActionOrder = 1;
8488
const remoteActionOrder = 1;
8589
const mergeActionOrder = 1;
90+
const that = this;
8691

8792
/* accept all local */
8893
registerAction2(class extends Action2 {
@@ -99,9 +104,8 @@ export class UserDataManualSyncView extends Disposable {
99104
},
100105
});
101106
}
102-
async run(accessor: ServicesAccessor): Promise<void> {
103-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
104-
await userDataSyncWorkbenchService.userDataSyncPreview.push();
107+
run(accessor: ServicesAccessor): Promise<void> {
108+
return that.push();
105109
}
106110
});
107111

@@ -121,8 +125,7 @@ export class UserDataManualSyncView extends Disposable {
121125
});
122126
}
123127
async run(accessor: ServicesAccessor): Promise<void> {
124-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
125-
await userDataSyncWorkbenchService.userDataSyncPreview.pull();
128+
return that.pull();
126129
}
127130
});
128131

@@ -142,8 +145,7 @@ export class UserDataManualSyncView extends Disposable {
142145
});
143146
}
144147
async run(accessor: ServicesAccessor): Promise<void> {
145-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
146-
await userDataSyncWorkbenchService.userDataSyncPreview.merge();
148+
return that.merge();
147149
}
148150
});
149151

@@ -163,13 +165,7 @@ export class UserDataManualSyncView extends Disposable {
163165
});
164166
}
165167
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
166-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
167-
const userDataSyncService = accessor.get(IUserDataSyncService);
168-
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
169-
const isConflict = userDataSyncWorkbenchService.userDataSyncPreview.conflicts.some(({ local }) => isEqual(local, previewResource.local));
170-
const localResource = isConflict ? previewResource.preview : previewResource.local;
171-
const content = await userDataSyncService.resolveContent(localResource);
172-
await userDataSyncWorkbenchService.userDataSyncPreview.accept(previewResource.syncResource, localResource, content || '');
168+
return that.acceptLocal(ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle));
173169
}
174170
});
175171

@@ -189,11 +185,7 @@ export class UserDataManualSyncView extends Disposable {
189185
});
190186
}
191187
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
192-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
193-
const userDataSyncService = accessor.get(IUserDataSyncService);
194-
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
195-
const content = await userDataSyncService.resolveContent(previewResource.remote);
196-
await userDataSyncWorkbenchService.userDataSyncPreview.accept(previewResource.syncResource, previewResource.remote, content || '');
188+
return that.acceptRemote(ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle));
197189
}
198190
});
199191

@@ -213,9 +205,7 @@ export class UserDataManualSyncView extends Disposable {
213205
});
214206
}
215207
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
216-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
217-
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
218-
await userDataSyncWorkbenchService.userDataSyncPreview.merge(previewResource.preview);
208+
return that.mergeResource(ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle));
219209
}
220210
});
221211

@@ -234,12 +224,7 @@ export class UserDataManualSyncView extends Disposable {
234224
});
235225
}
236226
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
237-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
238-
const userDataSyncService = accessor.get(IUserDataSyncService);
239-
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
240-
const resource = previewResource.remoteChange === Change.Deleted || previewResource.localChange === Change.Added ? previewResource.local : previewResource.remote;
241-
const content = await userDataSyncService.resolveContent(resource);
242-
await userDataSyncWorkbenchService.userDataSyncPreview.accept(previewResource.syncResource, resource, content || '');
227+
return that.deleteResource(ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle));
243228
}
244229
});
245230

@@ -258,12 +243,7 @@ export class UserDataManualSyncView extends Disposable {
258243
});
259244
}
260245
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
261-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
262-
const userDataSyncService = accessor.get(IUserDataSyncService);
263-
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
264-
const resource = previewResource.remoteChange === Change.Added || previewResource.localChange === Change.Deleted ? previewResource.local : previewResource.remote;
265-
const content = await userDataSyncService.resolveContent(resource);
266-
await userDataSyncWorkbenchService.userDataSyncPreview.accept(previewResource.syncResource, resource, content || '');
246+
return that.addResource(ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle));
267247
}
268248
});
269249

@@ -275,31 +255,85 @@ export class UserDataManualSyncView extends Disposable {
275255
});
276256
}
277257
async run(accessor: ServicesAccessor, handle: TreeViewItemHandleArg): Promise<void> {
278-
const editorService = accessor.get(IEditorService);
279-
const userDataSyncWorkbenchService = accessor.get(IUserDataSyncWorkbenchService);
280258
const previewResource: IUserDataSyncResourceGroup = ManualSyncViewDataProvider.toUserDataSyncResourceGroup(handle.$treeItemHandle);
281-
const isConflict = userDataSyncWorkbenchService.userDataSyncPreview.conflicts.some(({ local }) => isEqual(local, previewResource.local));
282-
if (previewResource.localChange === Change.Added || previewResource.remoteChange === Change.Deleted) {
283-
await editorService.openEditor({ resource: URI.revive(previewResource.remote), label: localize({ key: 'resourceLabel', comment: ['remote as in file in cloud'] }, "{0} (Remote)", basename(previewResource.remote)) });
284-
} else {
285-
const leftResource = URI.revive(previewResource.remote);
286-
const rightResource = isConflict ? URI.revive(previewResource.preview) : URI.revive(previewResource.local);
287-
const leftResourceName = localize({ key: 'leftResourceName', comment: ['remote as in file in cloud'] }, "{0} (Remote)", basename(leftResource));
288-
const rightResourceName = localize({ key: 'rightResourceName', comment: ['local as in file in disk'] }, "{0} (Local)", basename(rightResource));
289-
await editorService.openEditor({
290-
leftResource,
291-
rightResource,
292-
label: localize('sideBySideLabels', "{0} ↔ {1}", leftResourceName, rightResourceName),
293-
options: {
294-
preserveFocus: true,
295-
revealIfVisible: true,
296-
},
297-
});
298-
}
259+
return that.showChanges(previewResource);
299260
}
300261
});
301262
}
302263

264+
private async push(): Promise<void> {
265+
return this.withProgress(() => this.userDataSyncPreview.push());
266+
}
267+
268+
private async pull(): Promise<void> {
269+
return this.withProgress(() => this.userDataSyncPreview.pull());
270+
}
271+
272+
private async merge(): Promise<void> {
273+
return this.withProgress(() => this.userDataSyncPreview.merge());
274+
}
275+
276+
private async acceptLocal(previewResource: IUserDataSyncResourceGroup): Promise<void> {
277+
const isConflict = this.userDataSyncPreview.conflicts.some(({ local }) => isEqual(local, previewResource.local));
278+
const localResource = isConflict ? previewResource.preview : previewResource.local;
279+
return this.withProgress(async () => {
280+
const content = await this.userDataSyncService.resolveContent(localResource);
281+
await this.userDataSyncPreview.accept(previewResource.syncResource, localResource, content || '');
282+
});
283+
}
284+
285+
private async acceptRemote(previewResource: IUserDataSyncResourceGroup): Promise<void> {
286+
return this.withProgress(async () => {
287+
const content = await this.userDataSyncService.resolveContent(previewResource.remote);
288+
await this.userDataSyncPreview.accept(previewResource.syncResource, previewResource.remote, content || '');
289+
});
290+
}
291+
292+
private async mergeResource(previewResource: IUserDataSyncResourceGroup): Promise<void> {
293+
return this.withProgress(() => this.userDataSyncPreview.merge(previewResource.preview));
294+
}
295+
296+
private async deleteResource(previewResource: IUserDataSyncResourceGroup): Promise<void> {
297+
const resource = previewResource.remoteChange === Change.Deleted || previewResource.localChange === Change.Added ? previewResource.local : previewResource.remote;
298+
return this.withProgress(async () => {
299+
const content = await this.userDataSyncService.resolveContent(resource);
300+
await this.userDataSyncPreview.accept(previewResource.syncResource, resource, content || '');
301+
});
302+
}
303+
304+
private async addResource(previewResource: IUserDataSyncResourceGroup): Promise<void> {
305+
const resource = previewResource.remoteChange === Change.Added || previewResource.localChange === Change.Deleted ? previewResource.local : previewResource.remote;
306+
return this.withProgress(async () => {
307+
const content = await this.userDataSyncService.resolveContent(resource);
308+
await this.userDataSyncPreview.accept(previewResource.syncResource, resource, content || '');
309+
});
310+
}
311+
312+
private async showChanges(previewResource: IUserDataSyncResourceGroup): Promise<void> {
313+
const isConflict = this.userDataSyncPreview.conflicts.some(({ local }) => isEqual(local, previewResource.local));
314+
if (previewResource.localChange === Change.Added || previewResource.remoteChange === Change.Deleted) {
315+
await this.editorService.openEditor({ resource: URI.revive(previewResource.remote), label: localize({ key: 'resourceLabel', comment: ['remote as in file in cloud'] }, "{0} (Remote)", basename(previewResource.remote)) });
316+
} else {
317+
const leftResource = URI.revive(previewResource.remote);
318+
const rightResource = isConflict ? URI.revive(previewResource.preview) : URI.revive(previewResource.local);
319+
const leftResourceName = localize({ key: 'leftResourceName', comment: ['remote as in file in cloud'] }, "{0} (Remote)", basename(leftResource));
320+
const rightResourceName = localize({ key: 'rightResourceName', comment: ['local as in file in disk'] }, "{0} (Local)", basename(rightResource));
321+
await this.editorService.openEditor({
322+
leftResource,
323+
rightResource,
324+
label: localize('sideBySideLabels', "{0} ↔ {1}", leftResourceName, rightResourceName),
325+
options: {
326+
preserveFocus: true,
327+
revealIfVisible: true,
328+
},
329+
});
330+
}
331+
}
332+
333+
private withProgress(task: () => Promise<void>): Promise<void> {
334+
return this.progressService.withProgress({ location: MANUAL_SYNC_VIEW_ID, delay: 500 }, task);
335+
}
336+
303337
}
304338

305339
class ManualSyncViewDataProvider implements ITreeViewDataProvider {
@@ -344,27 +378,31 @@ class ManualSyncViewDataProvider implements ITreeViewDataProvider {
344378
}
345379

346380
private getChanges(): ITreeItem[] {
347-
return this.userDataSyncPreview.changes.map(change => ({
348-
handle: JSON.stringify(change),
349-
resourceUri: change.remote,
350-
themeIcon: FileThemeIcon,
351-
description: getSyncAreaLabel(change.syncResource),
352-
contextValue: `sync-resource-${change.localChange === Change.Added ? 'add-local' : change.localChange === Change.Deleted ? 'delete-local' : change.remoteChange === Change.Added ? 'add-remote' : change.remoteChange === Change.Deleted ? 'delete-remote' : 'modified'}-change`,
353-
collapsibleState: TreeItemCollapsibleState.None,
354-
command: { id: `workbench.actions.sync.showChanges`, title: '', arguments: [<TreeViewItemHandleArg>{ $treeViewId: '', $treeItemHandle: JSON.stringify(change) }] },
355-
}));
381+
return this.userDataSyncPreview.changes.map(change => {
382+
return {
383+
handle: JSON.stringify(change),
384+
resourceUri: change.remote,
385+
themeIcon: FileThemeIcon,
386+
description: getSyncAreaLabel(change.syncResource),
387+
contextValue: `sync-resource-${change.localChange === Change.Added ? 'add-local' : change.localChange === Change.Deleted ? 'delete-local' : change.remoteChange === Change.Added ? 'add-remote' : change.remoteChange === Change.Deleted ? 'delete-remote' : 'modified'}-change`,
388+
collapsibleState: TreeItemCollapsibleState.None,
389+
command: { id: `workbench.actions.sync.showChanges`, title: '', arguments: [<TreeViewItemHandleArg>{ $treeViewId: '', $treeItemHandle: JSON.stringify(change) }] },
390+
};
391+
});
356392
}
357393

358394
private getConflicts(): ITreeItem[] {
359-
return this.userDataSyncPreview.conflicts.map(conflict => ({
360-
handle: JSON.stringify(conflict),
361-
resourceUri: conflict.remote,
362-
themeIcon: FileThemeIcon,
363-
description: getSyncAreaLabel(conflict.syncResource),
364-
contextValue: `sync-resource-modified-conflict`,
365-
collapsibleState: TreeItemCollapsibleState.None,
366-
command: { id: `workbench.actions.sync.showChanges`, title: '', arguments: [<TreeViewItemHandleArg>{ $treeViewId: '', $treeItemHandle: JSON.stringify(conflict) }] },
367-
}));
395+
return this.userDataSyncPreview.conflicts.map(conflict => {
396+
return {
397+
handle: JSON.stringify(conflict),
398+
resourceUri: conflict.remote,
399+
themeIcon: FileThemeIcon,
400+
description: getSyncAreaLabel(conflict.syncResource),
401+
contextValue: `sync-resource-modified-conflict`,
402+
collapsibleState: TreeItemCollapsibleState.None,
403+
command: { id: `workbench.actions.sync.showChanges`, title: '', arguments: [<TreeViewItemHandleArg>{ $treeViewId: '', $treeItemHandle: JSON.stringify(conflict) }] },
404+
};
405+
});
368406
}
369407

370408
static toUserDataSyncResourceGroup(handle: string): IUserDataSyncResourceGroup {

src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
345345
/* Merge to sync globalState changes */
346346
await task.merge();
347347

348+
this.userDataSyncPreview.unsetManualSyncPreview();
349+
348350
this.manualSyncViewEnablementContext.set(false);
349351
if (visibleViewContainer) {
350352
this.viewsService.openViewContainer(visibleViewContainer.id);
@@ -558,19 +560,17 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat
558560

559561
class UserDataSyncPreview extends Disposable implements IUserDataSyncPreview {
560562

561-
private _onDidChangeChanges = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
562-
readonly onDidChangeChanges = this._onDidChangeChanges.event;
563-
564-
private _onDidChangeConflicts = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
565-
readonly onDidChangeConflicts = this._onDidChangeConflicts.event;
566-
567563
private _changes: ReadonlyArray<IUserDataSyncResourceGroup> = [];
568564
get changes() { return Object.freeze(this._changes); }
565+
private _onDidChangeChanges = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
566+
readonly onDidChangeChanges = this._onDidChangeChanges.event;
569567

570568
private _conflicts: ReadonlyArray<IUserDataSyncResourceGroup> = [];
571569
get conflicts() { return Object.freeze(this._conflicts); }
570+
private _onDidChangeConflicts = this._register(new Emitter<ReadonlyArray<IUserDataSyncResourceGroup>>());
571+
readonly onDidChangeConflicts = this._onDidChangeConflicts.event;
572572

573-
private manualSync: { preview: [SyncResource, ISyncResourcePreview][], task: IManualSyncTask } | undefined;
573+
private manualSync: { preview: [SyncResource, ISyncResourcePreview][], task: IManualSyncTask, disposables: DisposableStore } | undefined;
574574

575575
constructor(
576576
private readonly userDataSyncService: IUserDataSyncService
@@ -581,7 +581,16 @@ class UserDataSyncPreview extends Disposable implements IUserDataSyncPreview {
581581
}
582582

583583
setManualSyncPreview(task: IManualSyncTask, preview: [SyncResource, ISyncResourcePreview][]): void {
584-
this.manualSync = { task, preview };
584+
const disposables = new DisposableStore();
585+
this.manualSync = { task, preview, disposables };
586+
this.updateChanges();
587+
}
588+
589+
unsetManualSyncPreview(): void {
590+
if (this.manualSync) {
591+
this.manualSync.disposables.dispose();
592+
this.manualSync = undefined;
593+
}
585594
this.updateChanges();
586595
}
587596

0 commit comments

Comments
 (0)