瀏覽代碼

Resets context keys when closing or hiding

main
Eric Amodio 2 年之前
父節點
當前提交
307c7b6082
共有 2 個檔案被更改,包括 70 行新增21 行删除
  1. +25
    -11
      src/webviews/webviewBase.ts
  2. +45
    -10
      src/webviews/webviewViewBase.ts

+ 25
- 11
src/webviews/webviewBase.ts 查看文件

@ -164,10 +164,18 @@ export abstract class WebviewBase implements Disposable {
this._panel.webview.html = html;
}
private resetContextKeys() {
void setContext(`${this.contextKeyPrefix}:active`, false);
void setContext(`${this.contextKeyPrefix}:focus`, false);
void setContext(`${this.contextKeyPrefix}:inputFocus`, false);
}
private onPanelDisposed() {
this.onVisibilityChanged?.(false);
this.resetContextKeys();
this.onActiveChanged?.(false);
this.onFocusChanged?.(false);
this.onVisibilityChanged?.(false);
this.isReady = false;
this._disposablePanel?.dispose();
@ -193,20 +201,26 @@ export abstract class WebviewBase implements Disposable {
})
protected onViewStateChanged(e: WebviewPanelOnDidChangeViewStateEvent): void {
const { active, visible } = e.webviewPanel;
// If we are becoming active, delay it a bit to give the UI time to update
if (active) {
setTimeout(() => void setContext(`${this.contextKeyPrefix}:active`, active), 250);
if (visible) {
// If we are becoming active, delay it a bit to give the UI time to update
if (active) {
setTimeout(() => void setContext(`${this.contextKeyPrefix}:active`, active), 250);
} else {
void setContext(`${this.contextKeyPrefix}:active`, active);
}
this.onActiveChanged?.(active);
if (!active) {
this.onFocusChanged?.(false);
}
} else {
void setContext(`${this.contextKeyPrefix}:active`, active);
this.resetContextKeys();
this.onActiveChanged?.(false);
this.onFocusChanged?.(false);
}
this.onVisibilityChanged?.(visible);
this.onActiveChanged?.(active);
if (!active) {
this.onFocusChanged?.(active);
}
}
@debug<WebviewBase<State>['onMessageReceivedCore']>({

+ 45
- 10
src/webviews/webviewViewBase.ts 查看文件

@ -122,7 +122,7 @@ export abstract class WebviewViewBase implements
this._disposableView = Disposable.from(
this._view.onDidDispose(this.onViewDisposed, this),
this._view.onDidChangeVisibility(this.onViewVisibilityChanged, this),
this._view.onDidChangeVisibility(() => this.onViewVisibilityChanged(this.visible), this),
this._view.webview.onDidReceiveMessage(this.onMessageReceivedCore, this),
window.onDidChangeWindowState(this.onWindowStateChanged, this),
...(this.onInitializing?.() ?? []),
@ -134,13 +134,38 @@ export abstract class WebviewViewBase implements
}
@debug()
protected async refresh(): Promise<void> {
protected async refresh(force?: boolean): Promise<void> {
if (this._view == null) return;
this._view.webview.html = await this.getHtml(this._view.webview);
// Mark the webview as not ready, until we know if we are changing the html
this.isReady = false;
const html = await this.getHtml(this._view.webview);
if (force) {
// Reset the html to get the webview to reload
this._view.webview.html = '';
}
// If we aren't changing the html, mark the webview as ready again
if (this._view.webview.html === html) {
this.isReady = true;
return;
}
this._view.webview.html = html;
}
private resetContextKeys() {
void setContext(`${this.contextKeyPrefix}:focus`, false);
void setContext(`${this.contextKeyPrefix}:inputFocus`, false);
}
private onViewDisposed() {
this.resetContextKeys();
this.onFocusChanged?.(false);
this.onVisibilityChanged?.(false);
this.isReady = false;
this._disposableView?.dispose();
this._disposableView = undefined;
this._view = undefined;
@ -155,13 +180,14 @@ export abstract class WebviewViewBase implements
this.onFocusChanged?.(e.focused);
}
private async onViewVisibilityChanged() {
const visible = this.visible;
Logger.debug(`WebviewView(${this.id}).onViewVisibilityChanged`, `visible=${visible}`);
@debug()
private async onViewVisibilityChanged(visible: boolean) {
if (visible) {
void this.container.usage.track(`${this.trackingFeature}:shown`);
await this.refresh();
} else {
this.resetContextKeys();
this.onFocusChanged?.(false);
}
this.onVisibilityChanged?.(visible);
}
@ -272,12 +298,21 @@ export abstract class WebviewViewBase implements
return html;
}
protected nextIpcId(): string {
return nextIpcId();
}
protected notify<T extends IpcNotificationType<any>>(
type: T,
params: IpcMessageParams<T>,
completionId?: string,
): Thenable<boolean> {
return this.postMessage({ id: nextIpcId(), method: type.method, params: params, completionId: completionId });
): Promise<boolean> {
return this.postMessage({
id: this.nextIpcId(),
method: type.method,
params: params,
completionId: completionId,
});
}
@serialize()
@ -285,7 +320,7 @@ export abstract class WebviewViewBase implements
args: { 0: m => `(id=${m.id}, method=${m.method}${m.completionId ? `, completionId=${m.completionId}` : ''})` },
})
protected postMessage(message: IpcMessage) {
if (this._view == null) return Promise.resolve(false);
if (this._view == null || !this.isReady) return Promise.resolve(false);
// It looks like there is a bug where `postMessage` can sometimes just hang infinitely. Not sure why, but ensure we don't hang
return Promise.race<boolean>([

Loading…
取消
儲存