@opensumi/ide-webview 2.21.7-rc-1670229502.0 → 2.21.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/abstract-webview.js +3 -3
- package/lib/browser/abstract-webview.js.map +1 -1
- package/lib/browser/contribution.js.map +1 -1
- package/lib/browser/electron-webview-webview.js.map +1 -1
- package/lib/browser/iframe-webview.js.map +1 -1
- package/lib/browser/index.js.map +1 -1
- package/lib/browser/plain-webview.js +3 -3
- package/lib/browser/plain-webview.js.map +1 -1
- package/lib/browser/webview-window.js.map +1 -1
- package/lib/browser/webview.service.d.ts +1 -1
- package/lib/browser/webview.service.d.ts.map +1 -1
- package/lib/browser/webview.service.js +38 -38
- package/lib/browser/webview.service.js.map +1 -1
- package/lib/electron-main/index.js.map +1 -1
- package/package.json +11 -11
- package/src/browser/abstract-webview.ts +0 -231
- package/src/browser/contribution.ts +0 -80
- package/src/browser/editor-webview.tsx +0 -207
- package/src/browser/electron-webview-webview.ts +0 -156
- package/src/browser/iframe-webview.ts +0 -140
- package/src/browser/index.ts +0 -19
- package/src/browser/plain-webview.ts +0 -284
- package/src/browser/types.ts +0 -274
- package/src/browser/webview-window.ts +0 -130
- package/src/browser/webview.service.ts +0 -483
- package/src/common/index.ts +0 -1
- package/src/electron-main/index.ts +0 -31
- package/src/electron-webview/host-channel.ts +0 -64
- package/src/electron-webview/host-preload.js +0 -2
- package/src/electron-webview/plain-preload.js +0 -55
- package/src/index.ts +0 -1
- package/src/webview-host/common.ts +0 -108
- package/src/webview-host/web-preload.ts +0 -78
- package/src/webview-host/webview-manager.ts +0 -368
- package/src/webview-host/webview.html +0 -11
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/* istanbul ignore file */
|
|
2
|
-
import { Autowired } from '@opensumi/di';
|
|
3
|
-
import { Domain, URI, CommandContribution, CommandRegistry, AppConfig } from '@opensumi/ide-core-browser';
|
|
4
|
-
import { localize } from '@opensumi/ide-core-common';
|
|
5
|
-
import { ResourceService, IResource } from '@opensumi/ide-editor';
|
|
6
|
-
import { BrowserEditorContribution, EditorComponentRegistry } from '@opensumi/ide-editor/lib/browser';
|
|
7
|
-
|
|
8
|
-
import { EDITOR_WEBVIEW_SCHEME, IWebviewService, IEditorWebviewMetaData, isWebview } from './types';
|
|
9
|
-
import { WebviewServiceImpl } from './webview.service';
|
|
10
|
-
|
|
11
|
-
const WEBVIEW_DEVTOOLS_COMMAND = {
|
|
12
|
-
id: 'workbench.action.webview.openDeveloperTools',
|
|
13
|
-
label: localize('openToolsLabel', 'Open Webview Developer Tools'),
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
@Domain(BrowserEditorContribution, CommandContribution)
|
|
17
|
-
export class WebviewModuleContribution implements BrowserEditorContribution, CommandContribution {
|
|
18
|
-
@Autowired(IWebviewService)
|
|
19
|
-
webviewService: WebviewServiceImpl;
|
|
20
|
-
|
|
21
|
-
@Autowired(EditorComponentRegistry)
|
|
22
|
-
editorComponentRegistry: EditorComponentRegistry;
|
|
23
|
-
|
|
24
|
-
@Autowired(AppConfig)
|
|
25
|
-
private readonly appConfig: AppConfig;
|
|
26
|
-
|
|
27
|
-
registerResource(resourceService: ResourceService) {
|
|
28
|
-
resourceService.registerResourceProvider({
|
|
29
|
-
scheme: EDITOR_WEBVIEW_SCHEME,
|
|
30
|
-
provideResource: async (uri: URI): Promise<IResource<IEditorWebviewMetaData>> => {
|
|
31
|
-
const existingComponent = this.webviewService.editorWebviewComponents.get(uri.path.toString());
|
|
32
|
-
if (existingComponent) {
|
|
33
|
-
return existingComponent.resource;
|
|
34
|
-
} else {
|
|
35
|
-
// try revive, 如果无法恢复,会抛错
|
|
36
|
-
await this.webviewService.tryRestoredWebviewComponent(uri.path.toString());
|
|
37
|
-
return this.webviewService.editorWebviewComponents.get(uri.path.toString())!.resource;
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
shouldCloseResource: (resource: IResource<IEditorWebviewMetaData>, openedResources: IResource[][]) => {
|
|
41
|
-
let count = 0;
|
|
42
|
-
for (const resources of openedResources) {
|
|
43
|
-
for (const r of resources) {
|
|
44
|
-
if (r.uri.scheme === EDITOR_WEBVIEW_SCHEME && r.uri.toString() === resource.uri.toString()) {
|
|
45
|
-
count++;
|
|
46
|
-
}
|
|
47
|
-
if (count > 1) {
|
|
48
|
-
return true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
const component = this.webviewService.editorWebviewComponents.get(resource.uri.path.toString());
|
|
53
|
-
if (component?.webview && isWebview(component.webview)) {
|
|
54
|
-
// 只对类 vscode webview 进行 dispose,
|
|
55
|
-
// loadUrl 的 plainWebview 必须手动 dispose
|
|
56
|
-
this.webviewService.editorWebviewComponents.get(resource.uri.path.toString())!.clear();
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return true;
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
registerCommands(commandRegistry: CommandRegistry) {
|
|
65
|
-
commandRegistry.registerCommand(WEBVIEW_DEVTOOLS_COMMAND, {
|
|
66
|
-
execute: () => {
|
|
67
|
-
const elements = document.querySelectorAll<Electron.WebviewTag>('webview');
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
|
69
|
-
for (let i = 0; i < elements.length; i += 1) {
|
|
70
|
-
try {
|
|
71
|
-
elements[i].openDevTools();
|
|
72
|
-
} catch (e) {
|
|
73
|
-
// noop
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
isEnabled: () => this.appConfig.isElectronRenderer,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
|
|
3
|
-
import { Disposable, DomListener, useInjectable } from '@opensumi/ide-core-browser';
|
|
4
|
-
import { ReactEditorComponent } from '@opensumi/ide-editor/lib/browser';
|
|
5
|
-
|
|
6
|
-
import { IWebview, IPlainWebview, IEditorWebviewMetaData, IWebviewService, isWebview } from './types';
|
|
7
|
-
import { WebviewServiceImpl } from './webview.service';
|
|
8
|
-
|
|
9
|
-
declare const ResizeObserver: any;
|
|
10
|
-
declare const MutationObserver: any;
|
|
11
|
-
|
|
12
|
-
export const EditorWebviewComponentView: ReactEditorComponent<IEditorWebviewMetaData> = ({ resource }) => {
|
|
13
|
-
const webviewService = useInjectable(IWebviewService) as WebviewServiceImpl;
|
|
14
|
-
const webview = webviewService.editorWebviewComponents.get(resource.metadata!.id)?.webview;
|
|
15
|
-
let container: HTMLDivElement | null = null;
|
|
16
|
-
|
|
17
|
-
React.useEffect(() => {
|
|
18
|
-
if (webview && container) {
|
|
19
|
-
const mounter = new WebviewMounter(
|
|
20
|
-
webview,
|
|
21
|
-
container,
|
|
22
|
-
document.getElementById('workbench-editor')!,
|
|
23
|
-
document.getElementById('workbench-editor')!,
|
|
24
|
-
);
|
|
25
|
-
webview.onRemove(() => {
|
|
26
|
-
mounter.dispose();
|
|
27
|
-
});
|
|
28
|
-
return () => {
|
|
29
|
-
webview.remove();
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<div
|
|
36
|
-
style={{ height: '100%', width: '100%', position: 'relative' }}
|
|
37
|
-
className='editor-webview-webview-component'
|
|
38
|
-
ref={(el) => (container = el)}
|
|
39
|
-
></div>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* 同一个ID创建的webview会保存在内存以便重复使用,不要使用这个组件进行大量不同webview的创建
|
|
45
|
-
*/
|
|
46
|
-
export const PlainWebview: React.ComponentType<{ id: string; renderRoot?: HTMLElement; appendToChild?: boolean }> = ({
|
|
47
|
-
id,
|
|
48
|
-
renderRoot = document.body,
|
|
49
|
-
appendToChild,
|
|
50
|
-
}) => {
|
|
51
|
-
let container: HTMLDivElement | null = null;
|
|
52
|
-
const webviewService = useInjectable(IWebviewService) as IWebviewService;
|
|
53
|
-
|
|
54
|
-
React.useEffect(() => {
|
|
55
|
-
const component = webviewService.getOrCreatePlainWebviewComponent(id);
|
|
56
|
-
if (component && container) {
|
|
57
|
-
if (appendToChild) {
|
|
58
|
-
component.webview.appendTo(container);
|
|
59
|
-
} else {
|
|
60
|
-
const mounter = new WebviewMounter(
|
|
61
|
-
component.webview,
|
|
62
|
-
container,
|
|
63
|
-
document.getElementById('workbench-editor')!,
|
|
64
|
-
renderRoot,
|
|
65
|
-
);
|
|
66
|
-
component.webview.onRemove(() => {
|
|
67
|
-
mounter.dispose();
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return () => {
|
|
72
|
-
component.webview.remove();
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
}, []);
|
|
76
|
-
|
|
77
|
-
return <div style={{ height: '100%', width: '100%', position: 'relative' }} ref={(el) => (container = el)}></div>;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// 将iframe挂载在一个固定的位置,以overlay的形式覆盖在container中,
|
|
81
|
-
// 防止它在DOM树改变时被重载
|
|
82
|
-
export class WebviewMounter extends Disposable {
|
|
83
|
-
private mounting: number;
|
|
84
|
-
|
|
85
|
-
private _container: HTMLElement | null;
|
|
86
|
-
|
|
87
|
-
constructor(
|
|
88
|
-
private webview: IWebview | IPlainWebview,
|
|
89
|
-
private container: HTMLElement,
|
|
90
|
-
mutationRoot: HTMLElement,
|
|
91
|
-
private renderRoot: HTMLElement = document.body,
|
|
92
|
-
) {
|
|
93
|
-
super();
|
|
94
|
-
if (!this.webview.getDomNode()) {
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
this.webview.appendTo(this.getWebviewRealContainer());
|
|
98
|
-
if (isWebview(this.webview)) {
|
|
99
|
-
this.webview.setKeybindingDomTarget(container);
|
|
100
|
-
}
|
|
101
|
-
const resizeObserver = new ResizeObserver(this.doMount.bind(this));
|
|
102
|
-
const mutationObserver = new MutationObserver((mutations) => {
|
|
103
|
-
const ancestors: Set<HTMLElement> = new Set();
|
|
104
|
-
let ancestor: HTMLElement | null = this.container;
|
|
105
|
-
while (ancestor && ancestor !== mutationRoot) {
|
|
106
|
-
ancestors.add(ancestor);
|
|
107
|
-
ancestor = ancestor.parentElement;
|
|
108
|
-
}
|
|
109
|
-
for (const { addedNodes, removedNodes } of mutations) {
|
|
110
|
-
for (const node of addedNodes) {
|
|
111
|
-
if (ancestors.has(node)) {
|
|
112
|
-
this.doMount();
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
for (const node of removedNodes) {
|
|
117
|
-
if (ancestors.has(node)) {
|
|
118
|
-
this.doMount();
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
resizeObserver.observe(container);
|
|
125
|
-
mutationObserver.observe(mutationRoot, { childList: true, subtree: true });
|
|
126
|
-
|
|
127
|
-
this.doMount();
|
|
128
|
-
|
|
129
|
-
this.addDispose({
|
|
130
|
-
dispose: () => {
|
|
131
|
-
if (this._container) {
|
|
132
|
-
this._container.remove();
|
|
133
|
-
this._container = null;
|
|
134
|
-
this.webview = null as any;
|
|
135
|
-
this.container = null as any;
|
|
136
|
-
}
|
|
137
|
-
resizeObserver.disconnect();
|
|
138
|
-
mutationObserver.disconnect();
|
|
139
|
-
},
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
this.addDispose(
|
|
143
|
-
new DomListener(window, 'resize', () => {
|
|
144
|
-
this.doMount();
|
|
145
|
-
}),
|
|
146
|
-
);
|
|
147
|
-
|
|
148
|
-
// 监听滚动
|
|
149
|
-
let parent = container.parentElement;
|
|
150
|
-
while (parent) {
|
|
151
|
-
this.addDispose(
|
|
152
|
-
new DomListener(parent, 'scroll', () => {
|
|
153
|
-
this.doMount();
|
|
154
|
-
}),
|
|
155
|
-
);
|
|
156
|
-
parent = parent.parentElement;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
doMount() {
|
|
161
|
-
if (this.mounting) {
|
|
162
|
-
window.cancelAnimationFrame(this.mounting);
|
|
163
|
-
}
|
|
164
|
-
this.mounting = window.requestAnimationFrame(() => {
|
|
165
|
-
if (!this.webview.getDomNode()) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const rect = this.container.getBoundingClientRect();
|
|
169
|
-
if (rect.height === 0 || rect.width === 0) {
|
|
170
|
-
this.webview.getDomNode()!.style.display = 'none';
|
|
171
|
-
if (isWebview(this.webview) && !this.webview.options.longLive) {
|
|
172
|
-
this.webview.setListenMessages(false);
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
this.webview.getDomNode()!.style.display = '';
|
|
176
|
-
if (isWebview(this.webview)) {
|
|
177
|
-
this.webview.setListenMessages(true);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
const renderRootRects = this.renderRoot.getBoundingClientRect();
|
|
181
|
-
this.webview.getDomNode()!.style.top = rect.top - renderRootRects.top + 'px';
|
|
182
|
-
this.webview.getDomNode()!.style.left = rect.left - renderRootRects.left + 'px';
|
|
183
|
-
this.webview.getDomNode()!.style.height = rect.height + 'px';
|
|
184
|
-
this.webview.getDomNode()!.style.width = rect.width + 'px';
|
|
185
|
-
this.mounting = 0;
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
getWebviewRealContainer() {
|
|
190
|
-
if (this._container) {
|
|
191
|
-
return this._container;
|
|
192
|
-
}
|
|
193
|
-
let mountContainer = this.renderRoot.querySelector(':scope > div[data-webview-container=true]');
|
|
194
|
-
if (!mountContainer) {
|
|
195
|
-
const container = document.createElement('div');
|
|
196
|
-
container.style.zIndex = '2';
|
|
197
|
-
container.style.position = 'absolute';
|
|
198
|
-
container.setAttribute('data-webview-container', 'true');
|
|
199
|
-
container.style.top = '0';
|
|
200
|
-
this.renderRoot.appendChild(container);
|
|
201
|
-
mountContainer = container;
|
|
202
|
-
}
|
|
203
|
-
this._container = document.createElement('div');
|
|
204
|
-
mountContainer!.appendChild(this._container);
|
|
205
|
-
return this._container!;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import {
|
|
3
|
-
Disposable,
|
|
4
|
-
DomListener,
|
|
5
|
-
getDebugLogger,
|
|
6
|
-
IDisposable,
|
|
7
|
-
AppConfig,
|
|
8
|
-
electronEnv,
|
|
9
|
-
} from '@opensumi/ide-core-browser';
|
|
10
|
-
|
|
11
|
-
import { WebviewScheme } from '../common';
|
|
12
|
-
|
|
13
|
-
import { AbstractWebviewPanel } from './abstract-webview';
|
|
14
|
-
import { IWebview, IWebviewContentOptions } from './types';
|
|
15
|
-
|
|
16
|
-
@Injectable({ multiple: true })
|
|
17
|
-
export class ElectronWebviewWebviewPanel extends AbstractWebviewPanel implements IWebview {
|
|
18
|
-
private webview: Electron.WebviewTag;
|
|
19
|
-
|
|
20
|
-
private _needReload = false;
|
|
21
|
-
|
|
22
|
-
private _iframeDisposer: Disposable | null = new Disposable();
|
|
23
|
-
|
|
24
|
-
private _isReady: boolean;
|
|
25
|
-
|
|
26
|
-
@Autowired(AppConfig)
|
|
27
|
-
config: AppConfig;
|
|
28
|
-
|
|
29
|
-
constructor(public readonly id: string, options: IWebviewContentOptions = {}) {
|
|
30
|
-
super(id, options);
|
|
31
|
-
|
|
32
|
-
this.webview = document.createElement('webview');
|
|
33
|
-
this.webview.src = `${WebviewScheme}://index.html`;
|
|
34
|
-
this.webview.preload = electronEnv.webviewPreload;
|
|
35
|
-
this.webview.style.border = 'none';
|
|
36
|
-
this.webview.style.width = '100%';
|
|
37
|
-
this.webview.style.position = 'absolute';
|
|
38
|
-
this.webview.style.height = '100%';
|
|
39
|
-
this.webview.style.zIndex = '2';
|
|
40
|
-
super.init();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
prepareContainer() {
|
|
44
|
-
this.clear();
|
|
45
|
-
this._iframeDisposer = new Disposable();
|
|
46
|
-
this._ready = new Promise<void>((resolve) => {
|
|
47
|
-
// tslint:disable-next-line: no-unused-variable
|
|
48
|
-
const disposer = this._onWebviewMessage('webview-ready', () => {
|
|
49
|
-
if (this._isReady) {
|
|
50
|
-
// 这种情况一般是由于iframe在dom中的位置变动导致了重载。
|
|
51
|
-
// 此时我们需要重新初始化
|
|
52
|
-
// electronWebview不需要重新监听事件
|
|
53
|
-
this.updateStyle();
|
|
54
|
-
this.doUpdateContent();
|
|
55
|
-
}
|
|
56
|
-
this._isReady = true;
|
|
57
|
-
resolve();
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
this._needReload = false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
getDomNode() {
|
|
64
|
-
return this.webview;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected _sendToWebview(channel: string, data: any) {
|
|
68
|
-
if (!this._isListening) {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
this._ready
|
|
72
|
-
.then(() => {
|
|
73
|
-
if (!this.webview) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
this.webview.send(channel, data);
|
|
77
|
-
})
|
|
78
|
-
.catch((err) => {
|
|
79
|
-
getDebugLogger().error(err);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
protected _onWebviewMessage(channel: string, listener: (data: any) => any): IDisposable {
|
|
84
|
-
return this._iframeDisposer!.addDispose(
|
|
85
|
-
new DomListener(this.webview, 'ipc-message', (e) => {
|
|
86
|
-
if (!this.webview) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
if (e.channel === channel) {
|
|
90
|
-
if (!this._isListening) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
listener(e.args[0]);
|
|
94
|
-
}
|
|
95
|
-
}),
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
appendTo(container: HTMLElement) {
|
|
100
|
-
if (this.webview) {
|
|
101
|
-
if (container.style.position === 'static' || !container.style.position) {
|
|
102
|
-
container.style.position = 'relative';
|
|
103
|
-
}
|
|
104
|
-
container.innerHTML = '';
|
|
105
|
-
container.appendChild(this.webview);
|
|
106
|
-
if (this._needReload) {
|
|
107
|
-
this.init();
|
|
108
|
-
this.doUpdateContent();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
remove() {
|
|
114
|
-
if (this.webview) {
|
|
115
|
-
this.webview.remove();
|
|
116
|
-
this._onRemove.fire();
|
|
117
|
-
// remove 只是视图被销毁,但是html,state等内容保留,因此这里之前是改坏了
|
|
118
|
-
// this.dispose();
|
|
119
|
-
this.clear();
|
|
120
|
-
this._needReload = true;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
clear() {
|
|
125
|
-
if (this._iframeDisposer) {
|
|
126
|
-
this._iframeDisposer.dispose();
|
|
127
|
-
this._iframeDisposer = null;
|
|
128
|
-
}
|
|
129
|
-
this._isReady = false;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
dispose() {
|
|
133
|
-
super.dispose();
|
|
134
|
-
if (this._iframeDisposer) {
|
|
135
|
-
this._iframeDisposer.dispose();
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
// tslint:disable-next-line: no-unused-variable
|
|
140
|
-
const WebviewHTMLStr = `<!DOCTYPE html>
|
|
141
|
-
<html lang="en" style="width: 100%; height: 100%;">
|
|
142
|
-
|
|
143
|
-
<head>
|
|
144
|
-
<meta charset="UTF-8">
|
|
145
|
-
<meta http-equiv="Content-Security-Policy"
|
|
146
|
-
content="default-src 'self'; script-src 'self'; frame-src 'self'; style-src 'unsafe-inline'; worker-src 'self'; img-src * data: ; " />
|
|
147
|
-
|
|
148
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
149
|
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
150
|
-
<title>Webview Panel Container</title>
|
|
151
|
-
</head>
|
|
152
|
-
|
|
153
|
-
<body style="margin: 0; overflow: hidden; width: 100%; height: 100%">
|
|
154
|
-
</body>
|
|
155
|
-
|
|
156
|
-
</html>`;
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { Injectable, Autowired } from '@opensumi/di';
|
|
2
|
-
import { Disposable, DomListener, getDebugLogger, IDisposable, AppConfig } from '@opensumi/ide-core-browser';
|
|
3
|
-
|
|
4
|
-
import { AbstractWebviewPanel } from './abstract-webview';
|
|
5
|
-
import { IWebview, IWebviewContentOptions } from './types';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@Injectable({ multiple: true })
|
|
9
|
-
export class IFrameWebviewPanel extends AbstractWebviewPanel implements IWebview {
|
|
10
|
-
private iframe: HTMLIFrameElement;
|
|
11
|
-
|
|
12
|
-
private _needReload = false;
|
|
13
|
-
|
|
14
|
-
private _iframeDisposer: Disposable | null = new Disposable();
|
|
15
|
-
|
|
16
|
-
private _isReady: boolean;
|
|
17
|
-
|
|
18
|
-
@Autowired(AppConfig)
|
|
19
|
-
config: AppConfig;
|
|
20
|
-
|
|
21
|
-
constructor(public readonly id: string, options: IWebviewContentOptions = {}) {
|
|
22
|
-
super(id, options);
|
|
23
|
-
|
|
24
|
-
this.iframe = document.createElement('iframe');
|
|
25
|
-
this.iframe.setAttribute('allow', 'autoplay');
|
|
26
|
-
|
|
27
|
-
const sandboxRules = new Set(['allow-same-origin', 'allow-scripts']);
|
|
28
|
-
|
|
29
|
-
if (options.allowForms) {
|
|
30
|
-
sandboxRules.add('allow-forms');
|
|
31
|
-
}
|
|
32
|
-
this.iframe.setAttribute('sandbox', Array.from(sandboxRules).join(' '));
|
|
33
|
-
this.iframe.setAttribute('src', `${this.config.webviewEndpoint}/index.html?id=${this.id}`);
|
|
34
|
-
this.iframe.style.border = 'none';
|
|
35
|
-
this.iframe.style.width = '100%';
|
|
36
|
-
this.iframe.style.position = 'absolute';
|
|
37
|
-
this.iframe.style.height = '100%';
|
|
38
|
-
this.iframe.style.zIndex = '2';
|
|
39
|
-
|
|
40
|
-
super.init();
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
prepareContainer() {
|
|
44
|
-
this.clear();
|
|
45
|
-
this._iframeDisposer = new Disposable();
|
|
46
|
-
this._ready = new Promise<void>((resolve) => {
|
|
47
|
-
// tslint:disable-next-line: no-unused-variable
|
|
48
|
-
const disposer = this._onWebviewMessage('webview-ready', () => {
|
|
49
|
-
if (this._isReady) {
|
|
50
|
-
// 这种情况一般是由于iframe在dom中的位置变动导致了重载。
|
|
51
|
-
// 此时我们需要重新初始化
|
|
52
|
-
this.initEvents();
|
|
53
|
-
this.doUpdateContent();
|
|
54
|
-
}
|
|
55
|
-
this._isReady = true;
|
|
56
|
-
resolve();
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
this._needReload = false;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
getDomNode() {
|
|
63
|
-
return this.iframe;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
protected _sendToWebview(channel: string, data: any) {
|
|
67
|
-
if (!this._isListening) {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
this._ready
|
|
71
|
-
.then(() => {
|
|
72
|
-
if (!this.iframe) {
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
this.iframe.contentWindow!.postMessage(
|
|
76
|
-
{
|
|
77
|
-
channel,
|
|
78
|
-
data,
|
|
79
|
-
},
|
|
80
|
-
'*',
|
|
81
|
-
);
|
|
82
|
-
})
|
|
83
|
-
.catch((err) => {
|
|
84
|
-
getDebugLogger().error(err);
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
protected _onWebviewMessage(channel: string, listener: (data: any) => any): IDisposable {
|
|
89
|
-
return this._iframeDisposer!.addDispose(
|
|
90
|
-
new DomListener(window, 'message', (e) => {
|
|
91
|
-
if (e.data && e.data.target === this.id && e.data.channel === channel) {
|
|
92
|
-
if (!this._isListening) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
listener(e.data.data);
|
|
96
|
-
}
|
|
97
|
-
}),
|
|
98
|
-
);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
appendTo(container: HTMLElement) {
|
|
102
|
-
if (this.iframe) {
|
|
103
|
-
if (container.style.position === 'static' || !container.style.position) {
|
|
104
|
-
container.style.position = 'relative';
|
|
105
|
-
}
|
|
106
|
-
container.innerHTML = '';
|
|
107
|
-
container.appendChild(this.iframe);
|
|
108
|
-
if (this._needReload) {
|
|
109
|
-
this.init();
|
|
110
|
-
this.doUpdateContent();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
remove() {
|
|
116
|
-
if (this.iframe) {
|
|
117
|
-
this.iframe.remove();
|
|
118
|
-
this._onRemove.fire();
|
|
119
|
-
// remove 只是视图被销毁,但是html,state等内容保留,因此这里之前是改坏了
|
|
120
|
-
// this.dispose();
|
|
121
|
-
this.clear();
|
|
122
|
-
this._needReload = true;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
clear() {
|
|
127
|
-
if (this._iframeDisposer) {
|
|
128
|
-
this._iframeDisposer.dispose();
|
|
129
|
-
this._iframeDisposer = null;
|
|
130
|
-
}
|
|
131
|
-
this._isReady = false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
dispose() {
|
|
135
|
-
super.dispose();
|
|
136
|
-
if (this._iframeDisposer) {
|
|
137
|
-
this._iframeDisposer.dispose();
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
}
|
package/src/browser/index.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Provider, Injectable } from '@opensumi/di';
|
|
2
|
-
import { BrowserModule } from '@opensumi/ide-core-browser';
|
|
3
|
-
|
|
4
|
-
import { WebviewModuleContribution } from './contribution';
|
|
5
|
-
import { IWebviewService } from './types';
|
|
6
|
-
import { WebviewServiceImpl } from './webview.service';
|
|
7
|
-
export * from './types';
|
|
8
|
-
export { PlainWebview } from './editor-webview';
|
|
9
|
-
|
|
10
|
-
@Injectable()
|
|
11
|
-
export class WebviewModule extends BrowserModule {
|
|
12
|
-
providers: Provider[] = [
|
|
13
|
-
{
|
|
14
|
-
token: IWebviewService,
|
|
15
|
-
useClass: WebviewServiceImpl,
|
|
16
|
-
},
|
|
17
|
-
WebviewModuleContribution,
|
|
18
|
-
];
|
|
19
|
-
}
|