Merge pull request #272375 from mjbvz/dev/mjbvz/convinced-armadillo

Allow custom editors to change title
This commit is contained in:
Matt Bierner
2025-10-20 19:36:03 -07:00
committed by GitHub
4 changed files with 54 additions and 17 deletions

View File

@@ -670,6 +670,7 @@ class MainThreadCustomEditorModel extends ResourceWorkingCopy implements ICustom
const backupMeta: CustomDocumentBackupData = {
viewType: this.viewType,
editorResource: this._editorResource,
customTitle: primaryEditor.getCustomTitle(),
backupId: '',
extension: primaryEditor.extension ? {
id: primaryEditor.extension.id.value,

View File

@@ -36,29 +36,29 @@ import { IUntitledTextEditorService } from '../../../services/untitled/common/un
interface CustomEditorInputInitInfo {
readonly resource: URI;
readonly viewType: string;
readonly customTitle: string | undefined;
}
export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
static create(
instantiationService: IInstantiationService,
resource: URI,
viewType: string,
init: CustomEditorInputInitInfo,
group: GroupIdentifier | undefined,
options?: { readonly customClasses?: string; readonly oldResource?: URI },
): EditorInput {
return instantiationService.invokeFunction(accessor => {
// If it's an untitled file we must populate the untitledDocumentData
const untitledString = accessor.get(IUntitledTextEditorService).getValue(resource);
const untitledString = accessor.get(IUntitledTextEditorService).getValue(init.resource);
const untitledDocumentData = untitledString ? VSBuffer.fromString(untitledString) : undefined;
const webview = accessor.get(IWebviewService).createWebviewOverlay({
providedViewType: viewType,
title: undefined,
providedViewType: init.viewType,
title: init.customTitle,
options: { customClasses: options?.customClasses },
contentOptions: {},
extension: undefined,
});
const input = instantiationService.createInstance(CustomEditorInput, { resource, viewType }, webview, { untitledDocumentData: untitledDocumentData, oldResource: options?.oldResource });
const input = instantiationService.createInstance(CustomEditorInput, init, webview, { untitledDocumentData: untitledDocumentData, oldResource: options?.oldResource });
if (typeof group !== 'undefined') {
input.updateGroup(group);
}
@@ -72,6 +72,9 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
public readonly oldResource?: URI;
private _defaultDirtyState: boolean | undefined;
private _editorName: string | undefined = undefined;
private _customTitle: string | undefined = undefined;
private readonly _backupId: string | undefined;
private readonly _untitledDocumentData: VSBuffer | undefined;
@@ -103,6 +106,8 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
this._backupId = options.backupId;
this._untitledDocumentData = options.untitledDocumentData;
this._customTitle = init.customTitle;
this.registerListeners();
}
@@ -171,8 +176,11 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
return capabilities;
}
private _editorName: string | undefined = undefined;
override getName(): string {
if (this._customTitle) {
return this._customTitle;
}
if (typeof this._editorName !== 'string') {
this._editorName = this.customEditorLabelService.getName(this.resource) ?? basename(this.labelService.getUriLabel(this.resource));
}
@@ -180,6 +188,15 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
return this._editorName;
}
override setName(value: string): void {
this._customTitle = value;
super.setName(value);
}
getCustomTitle(): string | undefined {
return this._customTitle;
}
override getDescription(verbosity = Verbosity.MEDIUM): string | undefined {
switch (verbosity) {
case Verbosity.SHORT:
@@ -247,6 +264,10 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
}
override getTitle(verbosity?: Verbosity): string {
if (this._customTitle) {
return this._customTitle;
}
switch (verbosity) {
case Verbosity.SHORT:
return this.shortTitle;
@@ -268,7 +289,10 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
}
public override copy(): EditorInput {
return CustomEditorInput.create(this.instantiationService, this.resource, this.viewType, this.group, this.webview.options);
return CustomEditorInput.create(this.instantiationService,
{ resource: this.resource, viewType: this.viewType, customTitle: this._customTitle },
this.group,
this.webview.options);
}
public override isReadonly(): boolean | IMarkdownString {

View File

@@ -23,6 +23,9 @@ import { IWorkingCopyEditorHandler, IWorkingCopyEditorService } from '../../../s
export interface CustomDocumentBackupData extends IWorkingCopyBackupMeta {
readonly viewType: string;
readonly editorResource: UriComponents;
readonly customTitle: string | undefined;
backupId: string;
readonly extension: undefined | {
@@ -92,7 +95,11 @@ export class CustomEditorInputSerializer extends WebviewEditorInputSerializer {
const data = this.fromJson(JSON.parse(serializedEditorInput));
const webview = reviveWebview(this._webviewService, data);
const customInput = this._instantiationService.createInstance(CustomEditorInput, { resource: data.editorResource, viewType: data.viewType }, webview, { startsDirty: data.dirty, backupId: data.backupId });
const customInput = this._instantiationService.createInstance(CustomEditorInput, {
resource: data.editorResource,
viewType: data.viewType,
customTitle: data.title,
}, webview, { startsDirty: data.dirty, backupId: data.backupId });
if (typeof data.group === 'number') {
customInput.updateGroup(data.group);
}
@@ -100,11 +107,11 @@ export class CustomEditorInputSerializer extends WebviewEditorInputSerializer {
}
}
function reviveWebview(webviewService: IWebviewService, data: { origin: string | undefined; viewType: string; state: any; webviewOptions: WebviewOptions; contentOptions: WebviewContentOptions; extension?: WebviewExtensionDescription }) {
function reviveWebview(webviewService: IWebviewService, data: { origin: string | undefined; viewType: string; state: any; webviewOptions: WebviewOptions; contentOptions: WebviewContentOptions; extension?: WebviewExtensionDescription; title: string | undefined }) {
const webview = webviewService.createWebviewOverlay({
providedViewType: data.viewType,
origin: data.origin,
title: undefined,
title: data.title,
options: {
purpose: WebviewContentPurpose.CustomEditor,
enableFindWidget: data.webviewOptions.enableFindWidget,
@@ -185,9 +192,14 @@ export class ComplexCustomWorkingCopyEditorHandler extends Disposable implements
contentOptions: restoreWebviewContentOptions(backupData.webview.options),
state: backupData.webview.state,
extension,
title: backupData.customTitle,
});
const editor = this._instantiationService.createInstance(CustomEditorInput, { resource: URI.revive(backupData.editorResource), viewType: backupData.viewType }, webview, { backupId: backupData.backupId });
const editor = this._instantiationService.createInstance(CustomEditorInput, {
resource: URI.revive(backupData.editorResource),
viewType: backupData.viewType,
customTitle: backupData.customTitle,
}, webview, { backupId: backupData.backupId });
editor.updateGroup(0);
return editor;
}

View File

@@ -138,10 +138,10 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
},
{
createEditorInput: ({ resource }, group) => {
return { editor: CustomEditorInput.create(this.instantiationService, resource, contributedEditor.id, group.id) };
return { editor: CustomEditorInput.create(this.instantiationService, { resource, viewType: contributedEditor.id, customTitle: undefined }, group.id) };
},
createUntitledEditorInput: ({ resource }, group) => {
return { editor: CustomEditorInput.create(this.instantiationService, resource ?? URI.from({ scheme: Schemas.untitled, authority: `Untitled-${this._untitledCounter++}` }), contributedEditor.id, group.id) };
return { editor: CustomEditorInput.create(this.instantiationService, { resource: resource ?? URI.from({ scheme: Schemas.untitled, authority: `Untitled-${this._untitledCounter++}` }), viewType: contributedEditor.id, customTitle: undefined }, group.id) };
},
createDiffEditorInput: (diffEditorInput, group) => {
return { editor: this.createDiffEditorInput(diffEditorInput, contributedEditor.id, group) };
@@ -157,8 +157,8 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
editorID: string,
group: IEditorGroup
): DiffEditorInput {
const modifiedOverride = CustomEditorInput.create(this.instantiationService, assertReturnsDefined(editor.modified.resource), editorID, group.id, { customClasses: 'modified' });
const originalOverride = CustomEditorInput.create(this.instantiationService, assertReturnsDefined(editor.original.resource), editorID, group.id, { customClasses: 'original' });
const modifiedOverride = CustomEditorInput.create(this.instantiationService, { resource: assertReturnsDefined(editor.modified.resource), viewType: editorID, customTitle: undefined }, group.id, { customClasses: 'modified' });
const originalOverride = CustomEditorInput.create(this.instantiationService, { resource: assertReturnsDefined(editor.original.resource), viewType: editorID, customTitle: undefined }, group.id, { customClasses: 'original' });
return this.instantiationService.createInstance(DiffEditorInput, editor.label, editor.description, originalOverride, modifiedOverride, true);
}
@@ -259,7 +259,7 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
let replacement: EditorInput | IResourceEditorInput;
if (possibleEditors.defaultEditor) {
const viewType = possibleEditors.defaultEditor.id;
replacement = CustomEditorInput.create(this.instantiationService, newResource, viewType, group);
replacement = CustomEditorInput.create(this.instantiationService, { resource: newResource, viewType, customTitle: undefined }, group);
} else {
replacement = { resource: newResource, options: { override: DEFAULT_EDITOR_ASSOCIATION.id } };
}