Make sure custom editors restore state inside webview on reload
This commit is contained in:
parent
335de3b713
commit
49bcd96469
2 changed files with 67 additions and 50 deletions
|
@ -5,13 +5,11 @@
|
||||||
|
|
||||||
import { Lazy } from 'vs/base/common/lazy';
|
import { Lazy } from 'vs/base/common/lazy';
|
||||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||||
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
import { CustomEditorInput } from 'vs/workbench/contrib/customEditor/browser/customEditorInput';
|
||||||
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
|
import { IWebviewService, WebviewExtensionDescription } from 'vs/workbench/contrib/webview/browser/webview';
|
||||||
import { WebviewEditorInputFactory, SerializedWebview } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory';
|
import { reviveWebviewExtensionDescription, SerializedWebview, WebviewEditorInputFactory, DeserializedWebview } from 'vs/workbench/contrib/webview/browser/webviewEditorInputFactory';
|
||||||
import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
import { IWebviewWorkbenchService, WebviewInputOptions } from 'vs/workbench/contrib/webview/browser/webviewWorkbenchService';
|
||||||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||||
|
|
||||||
|
@ -37,6 +35,10 @@ interface SerializedCustomEditor extends SerializedWebview {
|
||||||
readonly dirty?: boolean;
|
readonly dirty?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface DeserializedCustomEditor extends DeserializedWebview {
|
||||||
|
readonly editorResource: URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export class CustomEditorInputFactory extends WebviewEditorInputFactory {
|
export class CustomEditorInputFactory extends WebviewEditorInputFactory {
|
||||||
|
|
||||||
|
@ -64,36 +66,38 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fromJson(input: SerializedCustomEditor): DeserializedCustomEditor {
|
||||||
|
return {
|
||||||
|
editorResource: URI.from(input.editorResource),
|
||||||
|
...super.fromJson(input),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public deserialize(
|
public deserialize(
|
||||||
_instantiationService: IInstantiationService,
|
_instantiationService: IInstantiationService,
|
||||||
serializedEditorInput: string
|
serializedEditorInput: string
|
||||||
): CustomEditorInput {
|
): CustomEditorInput {
|
||||||
const data = this.fromJson(serializedEditorInput);
|
const data = this.fromJson(JSON.parse(serializedEditorInput));
|
||||||
const id = data.id || generateUuid();
|
const webview = CustomEditorInputFactory.reviveWebview(data, this._webviewService);
|
||||||
|
const customInput = this._instantiationService.createInstance(CustomEditorInput, data.editorResource, data.viewType, data.id, webview, { startsDirty: (data as any).dirty });
|
||||||
const webview = new Lazy(() => {
|
|
||||||
const webview = this._webviewService.createWebviewOverlay(id, {
|
|
||||||
enableFindWidget: data.options.enableFindWidget,
|
|
||||||
retainContextWhenHidden: data.options.retainContextWhenHidden
|
|
||||||
}, data.options);
|
|
||||||
|
|
||||||
if (data.extensionLocation && data.extensionId) {
|
|
||||||
webview.extension = {
|
|
||||||
location: data.extensionLocation,
|
|
||||||
id: data.extensionId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return webview;
|
|
||||||
});
|
|
||||||
|
|
||||||
const customInput = this._instantiationService.createInstance(CustomEditorInput, URI.from((data as any).editorResource), data.viewType, id, webview, { startsDirty: (data as any).dirty });
|
|
||||||
if (typeof data.group === 'number') {
|
if (typeof data.group === 'number') {
|
||||||
customInput.updateGroup(data.group);
|
customInput.updateGroup(data.group);
|
||||||
}
|
}
|
||||||
return customInput;
|
return customInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static reviveWebview(data: { id: string, state: any, options: WebviewInputOptions, extension?: WebviewExtensionDescription, }, webviewService: IWebviewService) {
|
||||||
|
return new Lazy(() => {
|
||||||
|
const webview = webviewService.createWebviewOverlay(data.id, {
|
||||||
|
enableFindWidget: data.options.enableFindWidget,
|
||||||
|
retainContextWhenHidden: data.options.retainContextWhenHidden
|
||||||
|
}, data.options);
|
||||||
|
webview.state = data.state;
|
||||||
|
webview.extension = data.extension;
|
||||||
|
return webview;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static createCustomEditorInput(resource: URI, instantiationService: IInstantiationService): Promise<IEditorInput> {
|
public static createCustomEditorInput(resource: URI, instantiationService: IInstantiationService): Promise<IEditorInput> {
|
||||||
return instantiationService.invokeFunction(async accessor => {
|
return instantiationService.invokeFunction(async accessor => {
|
||||||
const webviewService = accessor.get<IWebviewService>(IWebviewService);
|
const webviewService = accessor.get<IWebviewService>(IWebviewService);
|
||||||
|
@ -106,20 +110,8 @@ export class CustomEditorInputFactory extends WebviewEditorInputFactory {
|
||||||
|
|
||||||
const backupData = backup.meta;
|
const backupData = backup.meta;
|
||||||
const id = backupData.webview.id;
|
const id = backupData.webview.id;
|
||||||
|
const extension = reviveWebviewExtensionDescription(backupData.extension?.id, backupData.extension?.location);
|
||||||
const webview = new Lazy(() => {
|
const webview = CustomEditorInputFactory.reviveWebview({ id, options: backupData.webview.options, state: backupData.webview.state, extension, }, webviewService);
|
||||||
const webview = webviewService.createWebviewOverlay(id, {
|
|
||||||
enableFindWidget: backupData.webview.options.enableFindWidget,
|
|
||||||
retainContextWhenHidden: backupData.webview.options.retainContextWhenHidden
|
|
||||||
}, backupData.webview.options);
|
|
||||||
|
|
||||||
webview.extension = backupData.extension ? {
|
|
||||||
location: URI.revive(backupData.extension.location),
|
|
||||||
id: new ExtensionIdentifier(backupData.extension.id),
|
|
||||||
} : undefined;
|
|
||||||
|
|
||||||
return webview;
|
|
||||||
});
|
|
||||||
|
|
||||||
const editor = instantiationService.createInstance(CustomEditorInput, URI.revive(backupData.editorResource), backupData.viewType, id, webview, { startsDirty: true, backupId: backupData.backupId });
|
const editor = instantiationService.createInstance(CustomEditorInput, URI.revive(backupData.editorResource), backupData.viewType, id, webview, { startsDirty: true, backupId: backupData.backupId });
|
||||||
editor.updateGroup(0);
|
editor.updateGroup(0);
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
import { generateUuid } from 'vs/base/common/uuid';
|
|
||||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { IEditorInputFactory } from 'vs/workbench/common/editor';
|
import { IEditorInputFactory } from 'vs/workbench/common/editor';
|
||||||
|
import { WebviewExtensionDescription, WebviewIcons } from 'vs/workbench/contrib/webview/browser/webview';
|
||||||
import { WebviewInput } from './webviewEditorInput';
|
import { WebviewInput } from './webviewEditorInput';
|
||||||
import { IWebviewWorkbenchService, WebviewInputOptions } from './webviewWorkbenchService';
|
import { IWebviewWorkbenchService, WebviewInputOptions } from './webviewWorkbenchService';
|
||||||
|
|
||||||
|
@ -17,17 +17,28 @@ interface SerializedIconPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SerializedWebview {
|
export interface SerializedWebview {
|
||||||
readonly id?: string;
|
readonly id: string;
|
||||||
readonly viewType: string;
|
readonly viewType: string;
|
||||||
readonly title: string;
|
readonly title: string;
|
||||||
readonly options: WebviewInputOptions;
|
readonly options: WebviewInputOptions;
|
||||||
readonly extensionLocation: string | UriComponents | undefined;
|
readonly extensionLocation: UriComponents | undefined;
|
||||||
readonly extensionId: string | undefined;
|
readonly extensionId: string | undefined;
|
||||||
readonly state: any;
|
readonly state: any;
|
||||||
readonly iconPath: SerializedIconPath | undefined;
|
readonly iconPath: SerializedIconPath | undefined;
|
||||||
readonly group?: number;
|
readonly group?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DeserializedWebview {
|
||||||
|
readonly id: string;
|
||||||
|
readonly viewType: string;
|
||||||
|
readonly title: string;
|
||||||
|
readonly options: WebviewInputOptions;
|
||||||
|
readonly extension: WebviewExtensionDescription | undefined;
|
||||||
|
readonly state: any;
|
||||||
|
readonly iconPath: WebviewIcons | undefined;
|
||||||
|
readonly group?: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class WebviewEditorInputFactory implements IEditorInputFactory {
|
export class WebviewEditorInputFactory implements IEditorInputFactory {
|
||||||
|
|
||||||
public static readonly ID = WebviewInput.typeId;
|
public static readonly ID = WebviewInput.typeId;
|
||||||
|
@ -57,19 +68,14 @@ export class WebviewEditorInputFactory implements IEditorInputFactory {
|
||||||
_instantiationService: IInstantiationService,
|
_instantiationService: IInstantiationService,
|
||||||
serializedEditorInput: string
|
serializedEditorInput: string
|
||||||
): WebviewInput {
|
): WebviewInput {
|
||||||
const data = this.fromJson(serializedEditorInput);
|
const data = this.fromJson(JSON.parse(serializedEditorInput));
|
||||||
return this._webviewWorkbenchService.reviveWebview(data.id || generateUuid(), data.viewType, data.title, data.iconPath, data.state, data.options, data.extensionLocation && data.extensionId ? {
|
return this._webviewWorkbenchService.reviveWebview(data.id, data.viewType, data.title, data.iconPath, data.state, data.options, data.extension, data.group);
|
||||||
location: data.extensionLocation,
|
|
||||||
id: data.extensionId
|
|
||||||
} : undefined, data.group);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fromJson(serializedEditorInput: string) {
|
protected fromJson(data: SerializedWebview): DeserializedWebview {
|
||||||
const data: SerializedWebview = JSON.parse(serializedEditorInput);
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
extensionLocation: reviveUri(data.extensionLocation),
|
extension: reviveWebviewExtensionDescription(data.extensionId, data.extensionLocation),
|
||||||
extensionId: data.extensionId ? new ExtensionIdentifier(data.extensionId) : undefined,
|
|
||||||
iconPath: reviveIconPath(data.iconPath),
|
iconPath: reviveIconPath(data.iconPath),
|
||||||
state: reviveState(data.state),
|
state: reviveState(data.state),
|
||||||
};
|
};
|
||||||
|
@ -90,6 +96,25 @@ export class WebviewEditorInputFactory implements IEditorInputFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function reviveWebviewExtensionDescription(
|
||||||
|
extensionId: string | undefined,
|
||||||
|
extensionLocation: UriComponents | undefined,
|
||||||
|
): WebviewExtensionDescription | undefined {
|
||||||
|
if (!extensionId) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
const location = reviveUri(extensionLocation);
|
||||||
|
if (!location) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: new ExtensionIdentifier(extensionId),
|
||||||
|
location,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function reviveIconPath(data: SerializedIconPath | undefined) {
|
function reviveIconPath(data: SerializedIconPath | undefined) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
Loading…
Reference in a new issue