mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-28 06:31:58 +00:00
try to clear transient editors on EditorViewStateManager restore (#206380)
* try to clear transient editors on EditorViewStateManager restore * add onWillHide to quickpick * adopt onwillhide * Update src/vs/workbench/contrib/terminalContrib/links/browser/terminalLinkQuickpick.ts Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com> * Update src/vs/workbench/contrib/terminalContrib/links/browser/terminalLinkQuickpick.ts Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com> * refactoring for pr feedback * rename to PickerEditorState and ensure dispose will clean up * add openTransientEditor * Update src/vs/workbench/browser/quickaccess.ts Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com> * Update src/vs/workbench/browser/quickaccess.ts Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com> * use editorService.closeEditors * don't close current file * delete pickerEditorState onClose and check for dirty editors before closing * editors - do not turn non-transient already opened editors transient * let pinning clear transient * 💄 * 💄 * improve closing of editors --------- Co-authored-by: Benjamin Pasero <benjamin.pasero@microsoft.com>
This commit is contained in:
parent
fc62e2a62f
commit
ab77280f55
@ -296,6 +296,9 @@ export interface IEditorOptions {
|
||||
* This option is meant to be used only when the editor is used for a short
|
||||
* period of time, for example when opening a preview of the editor from a
|
||||
* picker control in the background while navigating through results of the picker.
|
||||
*
|
||||
* Note: an editor that is already opened in a group that is not transient, will
|
||||
* not turn transient.
|
||||
*/
|
||||
transient?: boolean;
|
||||
}
|
||||
|
||||
@ -799,7 +799,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// that the transient state is not staying around when
|
||||
// the user interacts with the editor.
|
||||
|
||||
this.setTransient(this.activeEditor, false);
|
||||
this.model.setTransient(this.activeEditor, false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1034,13 +1034,6 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
}
|
||||
|
||||
setTransient(candidate: EditorInput | undefined, transient: boolean): void {
|
||||
const editor = candidate ?? this.activeEditor;
|
||||
if (editor) {
|
||||
this.model.setTransient(editor, transient);
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region openEditor()
|
||||
|
||||
@ -8,12 +8,14 @@ import { ContextKeyExpr, RawContextKey } from 'vs/platform/contextkey/common/con
|
||||
import { ICommandHandler } from 'vs/platform/commands/common/commands';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { getIEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { ICodeEditorViewState, IDiffEditorViewState } from 'vs/editor/common/editorCommon';
|
||||
import { IResourceEditorInput, ITextResourceEditorInput } from 'vs/platform/editor/common/editor';
|
||||
import { EditorInput } from 'vs/workbench/common/editor/editorInput';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ACTIVE_GROUP_TYPE, AUX_WINDOW_GROUP_TYPE, IEditorService, SIDE_GROUP_TYPE } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { IUntitledTextResourceEditorInput, IUntypedEditorInput, GroupIdentifier, IEditorPane } from 'vs/workbench/common/editor';
|
||||
|
||||
export const inQuickPickContextKeyValue = 'inQuickOpen';
|
||||
export const InQuickPickContextKey = new RawContextKey<boolean>(inQuickPickContextKeyValue, false, localize('inQuickOpen', "Whether keyboard focus is inside the quick open control"));
|
||||
@ -51,14 +53,21 @@ export function getQuickNavigateHandler(id: string, next?: boolean): ICommandHan
|
||||
quickInputService.navigate(!!next, quickNavigate);
|
||||
};
|
||||
}
|
||||
export class EditorViewState {
|
||||
export class PickerEditorState extends Disposable {
|
||||
private _editorViewState: {
|
||||
editor: EditorInput;
|
||||
group: IEditorGroup;
|
||||
state: ICodeEditorViewState | IDiffEditorViewState | undefined;
|
||||
} | undefined = undefined;
|
||||
|
||||
constructor(private readonly editorService: IEditorService) { }
|
||||
private readonly openedTransientEditors = new Set<EditorInput>(); // editors that were opened between set and restore
|
||||
|
||||
constructor(
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@IEditorGroupsService private readonly editorGroupsService: IEditorGroupsService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
set(): void {
|
||||
if (this._editorViewState) {
|
||||
@ -73,27 +82,55 @@ export class EditorViewState {
|
||||
state: getIEditor(activeEditorPane.getControl())?.saveViewState() ?? undefined,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async restore(shouldCloseCurrEditor = false): Promise<void> {
|
||||
/**
|
||||
* Open a transient editor such that it may be closed when the state is restored.
|
||||
* Note that, when the state is restored, if the editor is no longer transient, it will not be closed.
|
||||
*/
|
||||
async openTransientEditor(editor: IResourceEditorInput | ITextResourceEditorInput | IUntitledTextResourceEditorInput | IUntypedEditorInput, group?: IEditorGroup | GroupIdentifier | SIDE_GROUP_TYPE | ACTIVE_GROUP_TYPE | AUX_WINDOW_GROUP_TYPE): Promise<IEditorPane | undefined> {
|
||||
editor.options = { ...editor.options, transient: true };
|
||||
|
||||
const editorPane = await this.editorService.openEditor(editor, group);
|
||||
if (editorPane?.input && editorPane.input !== this._editorViewState?.editor && editorPane.group.isTransient(editorPane.input)) {
|
||||
this.openedTransientEditors.add(editorPane.input);
|
||||
}
|
||||
|
||||
return editorPane;
|
||||
}
|
||||
|
||||
async restore(): Promise<void> {
|
||||
if (this._editorViewState) {
|
||||
const options: IEditorOptions = {
|
||||
viewState: this._editorViewState.state,
|
||||
preserveFocus: true /* import to not close the picker as a result */
|
||||
};
|
||||
if (shouldCloseCurrEditor) {
|
||||
const activeEditorPane = this.editorService.activeEditorPane;
|
||||
const currEditor = activeEditorPane?.input;
|
||||
if (currEditor && currEditor !== this._editorViewState.editor && activeEditorPane?.group.isPinned(currEditor) !== true) {
|
||||
await activeEditorPane.group.closeEditor(currEditor);
|
||||
for (const editor of this.openedTransientEditors) {
|
||||
if (editor.isDirty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const group of this.editorGroupsService.groups) {
|
||||
if (group.isTransient(editor)) {
|
||||
await group.closeEditor(editor, { preserveFocus: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await this._editorViewState.group.openEditor(this._editorViewState.editor, options);
|
||||
await this._editorViewState.group.openEditor(this._editorViewState.editor, {
|
||||
viewState: this._editorViewState.state,
|
||||
preserveFocus: true // important to not close the picker as a result
|
||||
});
|
||||
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._editorViewState = undefined;
|
||||
this.openedTransientEditors.clear();
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,6 +369,11 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
this.splice(targetIndex, false, newEditor);
|
||||
}
|
||||
|
||||
// Handle transient
|
||||
if (makeTransient) {
|
||||
this.doSetTransient(newEditor, targetIndex, true);
|
||||
}
|
||||
|
||||
// Handle preview
|
||||
if (!makePinned) {
|
||||
|
||||
@ -385,11 +390,6 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
this.preview = newEditor;
|
||||
}
|
||||
|
||||
// Handle transient
|
||||
if (makeTransient) {
|
||||
this.doSetTransient(newEditor, targetIndex, true);
|
||||
}
|
||||
|
||||
// Listeners
|
||||
this.registerEditorListeners(newEditor);
|
||||
|
||||
@ -416,14 +416,14 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
else {
|
||||
const [existingEditor, existingEditorIndex] = existingEditorAndIndex;
|
||||
|
||||
// Update transient (existing editors do not turn transient if they were not before)
|
||||
this.doSetTransient(existingEditor, existingEditorIndex, makeTransient === false ? false : this.isTransient(existingEditor));
|
||||
|
||||
// Pin it
|
||||
if (makePinned) {
|
||||
this.doPin(existingEditor, existingEditorIndex);
|
||||
}
|
||||
|
||||
// Update transient
|
||||
this.doSetTransient(existingEditor, existingEditorIndex, makeTransient);
|
||||
|
||||
// Activate it
|
||||
if (makeActive) {
|
||||
this.doSetActive(existingEditor, existingEditorIndex);
|
||||
@ -726,6 +726,9 @@ export class EditorGroupModel extends Disposable implements IEditorGroupModel {
|
||||
return; // can only pin a preview editor
|
||||
}
|
||||
|
||||
// Clear Transient
|
||||
this.setTransient(editor, false);
|
||||
|
||||
// Convert the preview editor to be a pinned editor
|
||||
this.preview = null;
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ import { IFilesConfigurationService } from 'vs/workbench/services/filesConfigura
|
||||
import { ResourceMap } from 'vs/base/common/map';
|
||||
import { SymbolsQuickAccessProvider } from 'vs/workbench/contrib/search/browser/symbolsQuickAccess';
|
||||
import { AnythingQuickAccessProviderRunOptions, DefaultQuickAccessFilterValue, Extensions, IQuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { EditorViewState, IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess';
|
||||
import { PickerEditorState, IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess';
|
||||
import { GotoSymbolQuickAccessProvider } from 'vs/workbench/contrib/codeEditor/browser/quickaccess/gotoSymbolQuickAccess';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { ScrollType, IEditor } from 'vs/editor/common/editorCommon';
|
||||
@ -83,11 +83,11 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
|
||||
private static SYMBOL_PICKS_MERGE_DELAY = 200; // allow some time to merge fast and slow picks to reduce flickering
|
||||
|
||||
private readonly pickState = new class {
|
||||
private readonly pickState = this._register(new class extends Disposable {
|
||||
|
||||
picker: IQuickPick<IAnythingQuickPickItem> | undefined = undefined;
|
||||
|
||||
editorViewState: EditorViewState;
|
||||
editorViewState = this._register(this.instantiationService.createInstance(PickerEditorState));
|
||||
|
||||
scorerCache: FuzzyScorerCache = Object.create(null);
|
||||
fileQueryCache: FileQueryCacheState | undefined = undefined;
|
||||
@ -100,8 +100,11 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
|
||||
isQuickNavigating: boolean | undefined = undefined;
|
||||
|
||||
constructor(private readonly provider: AnythingQuickAccessProvider, editorService: IEditorService) {
|
||||
this.editorViewState = new EditorViewState(editorService);
|
||||
constructor(
|
||||
private readonly provider: AnythingQuickAccessProvider,
|
||||
private readonly instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
set(picker: IQuickPick<IAnythingQuickPickItem>): void {
|
||||
@ -129,7 +132,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
this.lastGlobalPicks = undefined;
|
||||
this.editorViewState.reset();
|
||||
}
|
||||
}(this, this.editorService);
|
||||
}(this, this.instantiationService));
|
||||
|
||||
get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined {
|
||||
if (this.configuration.preserveInput) {
|
||||
@ -844,7 +847,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
this.pickState.editorViewState.set();
|
||||
|
||||
// open it
|
||||
await this.editorService.openEditor({
|
||||
await this.pickState.editorViewState.openTransientEditor({
|
||||
resource: activeGlobalResource,
|
||||
options: { preserveFocus: true, revealIfOpened: true, ignoreError: true }
|
||||
});
|
||||
|
||||
@ -28,7 +28,7 @@ import { ACTIVE_GROUP, IEditorService, SIDE_GROUP } from 'vs/workbench/services/
|
||||
import { ITextQueryBuilderOptions, QueryBuilder } from 'vs/workbench/services/search/common/queryBuilder';
|
||||
import { IPatternInfo, ISearchComplete, ITextQuery, VIEW_ID } from 'vs/workbench/services/search/common/search';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { EditorViewState } from 'vs/workbench/browser/quickaccess';
|
||||
import { PickerEditorState } from 'vs/workbench/browser/quickaccess';
|
||||
import { IViewsService } from 'vs/workbench/services/views/common/viewsService';
|
||||
import { Sequencer } from 'vs/base/common/async';
|
||||
|
||||
@ -57,9 +57,7 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<ITextSearch
|
||||
results: [],
|
||||
messages: []
|
||||
});
|
||||
private readonly editorViewState = new EditorViewState(
|
||||
this._editorService
|
||||
);
|
||||
private readonly editorViewState: PickerEditorState;
|
||||
|
||||
private _getTextQueryBuilderOptions(charsPerLine: number): ITextQueryBuilderOptions {
|
||||
return {
|
||||
@ -88,7 +86,8 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<ITextSearch
|
||||
super(TEXT_SEARCH_QUICK_ACCESS_PREFIX, { canAcceptInBackground: true, shouldSkipTrimPickFilter: true });
|
||||
|
||||
this.queryBuilder = this._instantiationService.createInstance(QueryBuilder);
|
||||
this.searchModel = this._instantiationService.createInstance(SearchModel);
|
||||
this.searchModel = this._register(this._instantiationService.createInstance(SearchModel));
|
||||
this.editorViewState = this._register(this._instantiationService.createInstance(PickerEditorState));
|
||||
this.searchModel.location = SearchModelLocation.QUICK_ACCESS;
|
||||
this.editorSequencer = new Sequencer();
|
||||
}
|
||||
@ -122,22 +121,24 @@ export class TextSearchQuickAccess extends PickerQuickAccessProvider<ITextSearch
|
||||
this.editorViewState.set();
|
||||
const itemMatch = item.match;
|
||||
this.editorSequencer.queue(async () => {
|
||||
await this._editorService.openEditor({
|
||||
await this.editorViewState.openTransientEditor({
|
||||
resource: itemMatch.parent().resource,
|
||||
options: { transient: true, preserveFocus: true, revealIfOpened: true, ignoreError: true, selection: itemMatch.range() }
|
||||
options: { preserveFocus: true, revealIfOpened: true, ignoreError: true, selection: itemMatch.range() }
|
||||
});
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.add(Event.once(picker.onDidHide)(({ reason }) => {
|
||||
disposables.add(Event.once(picker.onWillHide)(({ reason }) => {
|
||||
// Restore view state upon cancellation if we changed it
|
||||
// but only when the picker was closed via explicit user
|
||||
// gesture and not e.g. when focus was lost because that
|
||||
// could mean the user clicked into the editor directly.
|
||||
if (reason === QuickInputHideReason.Gesture) {
|
||||
this.editorViewState.restore(true);
|
||||
this.editorViewState.restore();
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.add(Event.once(picker.onDidHide)(({ reason }) => {
|
||||
this.searchModel.searchResult.toggleHighlights(false);
|
||||
}));
|
||||
|
||||
|
||||
@ -15,17 +15,17 @@ import { IAccessibleViewService } from 'vs/workbench/contrib/accessibility/brows
|
||||
import { AccessibleViewProviderId } from 'vs/workbench/contrib/accessibility/browser/accessibilityConfiguration';
|
||||
import type { TerminalLink } from 'vs/workbench/contrib/terminalContrib/links/browser/terminalLink';
|
||||
import { Sequencer, timeout } from 'vs/base/common/async';
|
||||
import { EditorViewState } from 'vs/workbench/browser/quickaccess';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { PickerEditorState } from 'vs/workbench/browser/quickaccess';
|
||||
import { getLinkSuffix } from 'vs/workbench/contrib/terminalContrib/links/browser/terminalLinkParsing';
|
||||
import { TerminalBuiltinLinkType } from 'vs/workbench/contrib/terminalContrib/links/browser/links';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { basenameOrAuthority, dirname } from 'vs/base/common/resources';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
||||
export class TerminalLinkQuickpick extends DisposableStore {
|
||||
|
||||
private readonly _editorSequencer = new Sequencer();
|
||||
private readonly _editorViewState: EditorViewState;
|
||||
private readonly _editorViewState: PickerEditorState;
|
||||
|
||||
private _instance: ITerminalInstance | IDetachedTerminalInstance | undefined;
|
||||
|
||||
@ -33,13 +33,13 @@ export class TerminalLinkQuickpick extends DisposableStore {
|
||||
readonly onDidRequestMoreLinks = this._onDidRequestMoreLinks.event;
|
||||
|
||||
constructor(
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@ILabelService private readonly _labelService: ILabelService,
|
||||
@IQuickInputService private readonly _quickInputService: IQuickInputService,
|
||||
@IAccessibleViewService private readonly _accessibleViewService: IAccessibleViewService
|
||||
@IAccessibleViewService private readonly _accessibleViewService: IAccessibleViewService,
|
||||
@IInstantiationService instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this._editorViewState = new EditorViewState(_editorService);
|
||||
this._editorViewState = this.add(instantiationService.createInstance(PickerEditorState));
|
||||
}
|
||||
|
||||
async show(instance: ITerminalInstance | IDetachedTerminalInstance, links: { viewport: IDetectedLinks; all: Promise<IDetectedLinks> }): Promise<void> {
|
||||
@ -145,7 +145,7 @@ export class TerminalLinkQuickpick extends DisposableStore {
|
||||
// gesture and not e.g. when focus was lost because that
|
||||
// could mean the user clicked into the editor directly.
|
||||
if (reason === QuickInputHideReason.Gesture) {
|
||||
this._editorViewState.restore(true);
|
||||
this._editorViewState.restore();
|
||||
}
|
||||
disposables.dispose();
|
||||
if (pick.selectedItems.length === 0) {
|
||||
@ -266,9 +266,9 @@ export class TerminalLinkQuickpick extends DisposableStore {
|
||||
|
||||
this._editorViewState.set();
|
||||
this._editorSequencer.queue(async () => {
|
||||
await this._editorService.openEditor({
|
||||
await this._editorViewState.openTransientEditor({
|
||||
resource: link.uri,
|
||||
options: { transient: true, preserveFocus: true, revealIfOpened: true, ignoreError: true, selection, }
|
||||
options: { preserveFocus: true, revealIfOpened: true, ignoreError: true, selection, }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -837,19 +837,6 @@ export interface IEditorGroup {
|
||||
*/
|
||||
unstickEditor(editor?: EditorInput): void;
|
||||
|
||||
/**
|
||||
* A transient editor will attempt to appear as preview and certain components
|
||||
* (such as history tracking) may decide to ignore the editor when it becomes
|
||||
* active.
|
||||
* This option is meant to be used only when the editor is used for a short
|
||||
* period of time, for example when opening a preview of the editor from a
|
||||
* picker control in the background while navigating through results of the picker.
|
||||
*
|
||||
* @param editor the editor to update transient state, or the currently active editor
|
||||
* if unspecified.
|
||||
*/
|
||||
setTransient(editor: EditorInput | undefined, transient: boolean): void;
|
||||
|
||||
/**
|
||||
* Whether this editor group should be locked or not.
|
||||
*
|
||||
|
||||
@ -477,7 +477,6 @@ suite('EditorGroupsService', () => {
|
||||
const editorCloseEvents: IGroupModelChangeEvent[] = [];
|
||||
let editorPinCounter = 0;
|
||||
let editorStickyCounter = 0;
|
||||
let editorTransientCounter = 0;
|
||||
let editorCapabilitiesCounter = 0;
|
||||
const editorGroupModelChangeListener = group.onDidModelChange(e => {
|
||||
if (e.kind === GroupModelChangeKind.EDITOR_OPEN) {
|
||||
@ -490,9 +489,6 @@ suite('EditorGroupsService', () => {
|
||||
} else if (e.kind === GroupModelChangeKind.EDITOR_STICKY) {
|
||||
assert.ok(e.editor);
|
||||
editorStickyCounter++;
|
||||
} else if (e.kind === GroupModelChangeKind.EDITOR_TRANSIENT) {
|
||||
assert.ok(e.editor);
|
||||
editorTransientCounter++;
|
||||
} else if (e.kind === GroupModelChangeKind.EDITOR_CAPABILITIES) {
|
||||
assert.ok(e.editor);
|
||||
editorCapabilitiesCounter++;
|
||||
@ -597,15 +593,6 @@ suite('EditorGroupsService', () => {
|
||||
group.unstickEditor(input);
|
||||
assert.strictEqual(editorStickyCounter, 2);
|
||||
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(editorTransientCounter, 0);
|
||||
group.setTransient(input, true);
|
||||
assert.strictEqual(group.isTransient(input), true);
|
||||
assert.strictEqual(editorTransientCounter, 1);
|
||||
group.setTransient(input, false);
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(editorTransientCounter, 2);
|
||||
|
||||
editorCloseListener.dispose();
|
||||
editorWillCloseListener.dispose();
|
||||
editorDidCloseListener.dispose();
|
||||
@ -1835,30 +1822,42 @@ suite('EditorGroupsService', () => {
|
||||
const group = part.activeGroup;
|
||||
|
||||
const input = createTestFileEditorInput(URI.file('foo/bar'), TEST_EDITOR_INPUT_ID);
|
||||
const inputInactive = createTestFileEditorInput(URI.file('foo/bar/inactive'), TEST_EDITOR_INPUT_ID);
|
||||
const inputTransient = createTestFileEditorInput(URI.file('foo/bar/inactive'), TEST_EDITOR_INPUT_ID);
|
||||
|
||||
await group.openEditor(input, { pinned: true });
|
||||
await group.openEditor(inputInactive, { inactive: true });
|
||||
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(group.isTransient(inputInactive), false);
|
||||
|
||||
group.setTransient(input, true);
|
||||
|
||||
assert.strictEqual(group.isTransient(input), true);
|
||||
assert.strictEqual(group.isTransient(inputInactive), false);
|
||||
|
||||
group.setTransient(input, false);
|
||||
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(group.isTransient(inputInactive), false);
|
||||
|
||||
const inputTransient = createTestFileEditorInput(URI.file('foo/bar/transient'), TEST_EDITOR_INPUT_ID);
|
||||
|
||||
await group.openEditor(inputTransient, { transient: true });
|
||||
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(group.isTransient(inputTransient), true);
|
||||
|
||||
await group.openEditor(inputTransient, {});
|
||||
await group.openEditor(input, { pinned: true });
|
||||
await group.openEditor(inputTransient, { transient: true });
|
||||
|
||||
assert.strictEqual(group.isTransient(inputTransient), true);
|
||||
|
||||
await group.openEditor(inputTransient, { transient: false });
|
||||
assert.strictEqual(group.isTransient(inputTransient), false);
|
||||
|
||||
await group.openEditor(inputTransient, { transient: true });
|
||||
assert.strictEqual(group.isTransient(inputTransient), false); // cannot make a non-transient editor transient when already opened
|
||||
});
|
||||
|
||||
test('transient editors - pinning clears transient', async () => {
|
||||
const [part] = await createPart();
|
||||
const group = part.activeGroup;
|
||||
|
||||
const input = createTestFileEditorInput(URI.file('foo/bar'), TEST_EDITOR_INPUT_ID);
|
||||
const inputTransient = createTestFileEditorInput(URI.file('foo/bar/inactive'), TEST_EDITOR_INPUT_ID);
|
||||
|
||||
await group.openEditor(input, { pinned: true });
|
||||
await group.openEditor(inputTransient, { transient: true });
|
||||
|
||||
assert.strictEqual(group.isTransient(input), false);
|
||||
assert.strictEqual(group.isTransient(inputTransient), true);
|
||||
|
||||
await group.openEditor(input, { pinned: true });
|
||||
await group.openEditor(inputTransient, { pinned: true, transient: true });
|
||||
|
||||
assert.strictEqual(group.isTransient(inputTransient), false);
|
||||
});
|
||||
|
||||
@ -1882,7 +1881,7 @@ suite('EditorGroupsService', () => {
|
||||
await group.openEditor(input2, { transient: true });
|
||||
assert.strictEqual(group.isPinned(input2), false);
|
||||
|
||||
group.setTransient(input2, false);
|
||||
group.focus();
|
||||
assert.strictEqual(group.isPinned(input2), true);
|
||||
});
|
||||
|
||||
|
||||
@ -8,16 +8,23 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IQuickAccessRegistry, Extensions, IQuickAccessProvider, QuickAccessRegistry } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { IQuickPick, IQuickPickItem, IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TestServiceAccessor, workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { TestServiceAccessor, workbenchInstantiationService, createEditorPart } from 'vs/workbench/test/browser/workbenchTestServices';
|
||||
import { DisposableStore, toDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { PickerQuickAccessProvider, FastAndSlowPicks } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorService } from 'vs/workbench/services/editor/browser/editorService';
|
||||
import { PickerEditorState } from 'vs/workbench/browser/quickaccess';
|
||||
import { EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
|
||||
suite('QuickAccess', () => {
|
||||
|
||||
let disposables: DisposableStore;
|
||||
let instantiationService: IInstantiationService;
|
||||
let instantiationService: TestInstantiationService;
|
||||
let accessor: TestServiceAccessor;
|
||||
|
||||
let providerDefaultCalled = false;
|
||||
@ -334,4 +341,51 @@ suite('QuickAccess', () => {
|
||||
|
||||
restore();
|
||||
});
|
||||
|
||||
test('PickerEditorState can properly restore editors', async () => {
|
||||
|
||||
const part = await createEditorPart(instantiationService, disposables);
|
||||
instantiationService.stub(IEditorGroupsService, part);
|
||||
|
||||
const editorService = disposables.add(instantiationService.createInstance(EditorService, undefined));
|
||||
instantiationService.stub(IEditorService, editorService);
|
||||
|
||||
const editorViewState = disposables.add(instantiationService.createInstance(PickerEditorState));
|
||||
disposables.add(part);
|
||||
disposables.add(editorService);
|
||||
|
||||
const input1 = {
|
||||
resource: URI.parse('foo://bar1'),
|
||||
options: {
|
||||
pinned: true, preserveFocus: true, selection: new Range(1, 0, 1, 3)
|
||||
}
|
||||
};
|
||||
const input2 = {
|
||||
resource: URI.parse('foo://bar2'),
|
||||
options: {
|
||||
pinned: true, selection: new Range(1, 0, 1, 3)
|
||||
}
|
||||
};
|
||||
const input3 = {
|
||||
resource: URI.parse('foo://bar3')
|
||||
};
|
||||
const input4 = {
|
||||
resource: URI.parse('foo://bar4')
|
||||
};
|
||||
|
||||
const editor = await editorService.openEditor(input1);
|
||||
assert.strictEqual(editor, editorService.activeEditorPane);
|
||||
editorViewState.set();
|
||||
await editorService.openEditor(input2);
|
||||
await editorViewState.openTransientEditor(input3);
|
||||
await editorViewState.openTransientEditor(input4);
|
||||
await editorViewState.restore();
|
||||
|
||||
assert.strictEqual(part.activeGroup.activeEditor?.resource, input1.resource);
|
||||
assert.deepStrictEqual(part.activeGroup.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE).map(e => e.resource), [input1.resource, input2.resource]);
|
||||
if (part.activeGroup.activeEditorPane?.getSelection) {
|
||||
assert.deepStrictEqual(part.activeGroup.activeEditorPane?.getSelection(), input1.options.selection);
|
||||
}
|
||||
await part.activeGroup.closeAllEditors();
|
||||
});
|
||||
});
|
||||
|
||||
@ -918,7 +918,6 @@ export class TestEditorGroupView implements IEditorGroupView {
|
||||
pinEditor(_editor?: EditorInput): void { }
|
||||
stickEditor(editor?: EditorInput | undefined): void { }
|
||||
unstickEditor(editor?: EditorInput | undefined): void { }
|
||||
setTransient(editor: EditorInput | undefined, transient: boolean): void { }
|
||||
lock(locked: boolean): void { }
|
||||
focus(): void { }
|
||||
get scopedContextKeyService(): IContextKeyService { throw new Error('not implemented'); }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user