Skip to content

Commit

Permalink
Fix explorer edit item. Fixes microsoft#78153
Browse files Browse the repository at this point in the history
  • Loading branch information
jeanp413 committed Aug 11, 2019
1 parent 52ecb5b commit 46f6387
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 36 deletions.
7 changes: 5 additions & 2 deletions src/vs/workbench/contrib/files/browser/fileActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole

folder.addChild(newStat);

const onSuccess = async (value: string) => {
const onSuccess = (value: string): Promise<void> => {
const createPromise = isFolder ? fileService.createFolder(resources.joinPath(folder.resource, value)) : textFileService.create(resources.joinPath(folder.resource, value));
return createPromise.then(created => {
refreshIfSeparator(value, explorerService);
Expand All @@ -877,7 +877,10 @@ async function openExplorerAndCreate(accessor: ServicesAccessor, isFolder: boole
if (success) {
onSuccess(value);
} else {
explorerService.select(folder.resource).then(undefined, onUnexpectedError);
// Fixes #78153
setTimeout(() => {
explorerService.select(folder.resource).then(undefined, onUnexpectedError);
}, 0);
}
}
});
Expand Down
35 changes: 25 additions & 10 deletions src/vs/workbench/contrib/files/browser/views/explorerView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import * as nls from 'vs/nls';
import { URI } from 'vs/base/common/uri';
import * as perf from 'vs/base/common/performance';
import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
import { IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification } from 'vs/base/common/actions';
import { memoize } from 'vs/base/common/decorators';
import { IFilesConfiguration, ExplorerFolderContext, FilesExplorerFocusedContext, ExplorerFocusedContext, ExplorerRootContext, ExplorerResourceReadonlyContext, IExplorerService, ExplorerResourceCut, ExplorerResourceMoveableToTrash } from 'vs/workbench/contrib/files/common/files';
import { NewFolderAction, NewFileAction, FileCopiedContext, RefreshExplorerView, CollapseExplorerView } from 'vs/workbench/contrib/files/browser/fileActions';
Expand Down Expand Up @@ -68,6 +68,7 @@ export class ExplorerView extends ViewletPanel {
private shouldRefresh = true;
private dragHandler!: DelayedDragHandler;
private autoReveal = false;
private actions: IAction[] | undefined;

constructor(
options: IViewletPanelOptions,
Expand Down Expand Up @@ -170,7 +171,12 @@ export class ExplorerView extends ViewletPanel {
}));

this._register(this.explorerService.onDidChangeRoots(() => this.setTreeInput()));
this._register(this.explorerService.onDidChangeItem(e => this.refresh(e.recursive, e.item)));
this._register(this.explorerService.onDidChangeItem(e => {
if (this.explorerService.isEditable(undefined)) {
this.tree.domFocus();
}
this.refresh(e.recursive, e.item);
}));
this._register(this.explorerService.onDidChangeEditable(async e => {
const isEditing = !!this.explorerService.getEditableData(e);

Expand Down Expand Up @@ -218,14 +224,16 @@ export class ExplorerView extends ViewletPanel {
}

getActions(): IAction[] {
const actions: Action[] = [];

actions.push(this.instantiationService.createInstance(NewFileAction));
actions.push(this.instantiationService.createInstance(NewFolderAction));
actions.push(this.instantiationService.createInstance(RefreshExplorerView, RefreshExplorerView.ID, RefreshExplorerView.LABEL));
actions.push(this.instantiationService.createInstance(CollapseExplorerView, CollapseExplorerView.ID, CollapseExplorerView.LABEL));

return actions;
if (!this.actions) {
this.actions = [
this.instantiationService.createInstance(NewFileAction),
this.instantiationService.createInstance(NewFolderAction),
this.instantiationService.createInstance(RefreshExplorerView, RefreshExplorerView.ID, RefreshExplorerView.LABEL),
this.instantiationService.createInstance(CollapseExplorerView, CollapseExplorerView.ID, CollapseExplorerView.LABEL)
];
this.actions.forEach(a => this._register(a));
}
return this.actions;
}

focus(): void {
Expand Down Expand Up @@ -334,6 +342,13 @@ export class ExplorerView extends ViewletPanel {

this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));

this._register(this.tree.onDidScroll(e => {
let editable = this.explorerService.getEditable();
if (editable && this.tree.getRelativeTop(editable.stat) === null) {
editable.data.onFinish('', false);
}
}));

// save view state on shutdown
this._register(this.storageService.onWillSaveState(() => {
this.storageService.store(ExplorerView.TREE_VIEW_STATE_STORAGE_KEY, JSON.stringify(this.tree.getViewState()), StorageScope.WORKSPACE);
Expand Down
35 changes: 11 additions & 24 deletions src/vs/workbench/contrib/files/browser/views/explorerViewer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,40 +218,32 @@ export class FilesRenderer implements ITreeRenderer<ExplorerItem, FuzzyScore, IF
const lastDot = value.lastIndexOf('.');

inputBox.value = value;
inputBox.focus();
inputBox.select({ start: 0, end: lastDot > 0 && !stat.isDirectory ? lastDot : value.length });

let isFinishableDisposeEvent = false;
setTimeout(() => {
// Check if disposed
if (!inputBox.inputElement) {
return;
}
inputBox.focus();
inputBox.select({ start: 0, end: lastDot > 0 && !stat.isDirectory ? lastDot : value.length });
isFinishableDisposeEvent = true;
}, 0);

const done = once(async (success: boolean) => {
const done = once((success: boolean, finishEditing: boolean) => {
label.element.style.display = 'none';
const value = inputBox.value;
dispose(toDispose);
label.element.remove();
// Timeout: once done rendering only then re-render #70902
setTimeout(() => editableData.onFinish(value, success), 0);
if (finishEditing) {
editableData.onFinish(value, success);
}
});

const blurDisposable = DOM.addDisposableListener(inputBox.inputElement, DOM.EventType.BLUR, () => {
done(inputBox.isInputValid());
done(inputBox.isInputValid(), true);
});

const toDispose = [
inputBox,
DOM.addStandardDisposableListener(inputBox.inputElement, DOM.EventType.KEY_DOWN, (e: IKeyboardEvent) => {
if (e.equals(KeyCode.Enter)) {
if (inputBox.validate()) {
done(true);
done(true, true);
}
} else if (e.equals(KeyCode.Escape)) {
done(false);
done(false, true);
}
}),
blurDisposable,
Expand All @@ -260,13 +252,8 @@ export class FilesRenderer implements ITreeRenderer<ExplorerItem, FuzzyScore, IF
];

return toDisposable(() => {
if (isFinishableDisposeEvent) {
done(false);
}
else {
dispose(toDispose);
label.element.remove();
}
blurDisposable.dispose();
done(false, false);
});
}

Expand Down
4 changes: 4 additions & 0 deletions src/vs/workbench/contrib/files/common/explorerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ export class ExplorerService implements IExplorerService {
return !!this.cutItems && this.cutItems.indexOf(item) >= 0;
}

getEditable(): { stat: ExplorerItem, data: IEditableData } | undefined {
return this.editable;
}

getEditableData(stat: ExplorerItem): IEditableData | undefined {
return this.editable && this.editable.stat === stat ? this.editable.data : undefined;
}
Expand Down
1 change: 1 addition & 0 deletions src/vs/workbench/contrib/files/common/files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface IExplorerService {
readonly onDidCopyItems: Event<{ items: ExplorerItem[], cut: boolean, previouslyCutItems: ExplorerItem[] | undefined }>;

setEditable(stat: ExplorerItem, data: IEditableData | null): void;
getEditable(): { stat: ExplorerItem, data: IEditableData } | undefined;
getEditableData(stat: ExplorerItem): IEditableData | undefined;
// If undefined is passed checks if any element is currently being edited.
isEditable(stat: ExplorerItem | undefined): boolean;
Expand Down

0 comments on commit 46f6387

Please sign in to comment.