-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor: openVariablePanels command and split out a PanelController #120
Changes from 7 commits
d20523b
c7053f4
9e7fef5
d526f65
72cb4eb
9348831
dc6c48b
8b2eb04
fdee37f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import * as vscode from 'vscode'; | ||
import type { | ||
Disposable, | ||
IPanelService, | ||
IServerManager, | ||
VariableDefintion, | ||
} from '../types'; | ||
import { getEmbedWidgetUrl } from '../dh/dhc'; | ||
import { assertDefined, getDHThemeKey, getPanelHtml } from '../util'; | ||
import { DhcService } from '../services'; | ||
|
||
export class PanelController implements Disposable { | ||
constructor(serverManager: IServerManager, panelService: IPanelService) { | ||
this._panelService = panelService; | ||
this._serverManager = serverManager; | ||
} | ||
|
||
private readonly _panelService: IPanelService; | ||
private readonly _serverManager: IServerManager; | ||
|
||
dispose = async (): Promise<void> => {}; | ||
|
||
openPanels = async ( | ||
serverUrl: URL, | ||
variables: VariableDefintion[] | ||
): Promise<void> => { | ||
let lastPanel: vscode.WebviewPanel | null = null; | ||
|
||
for (const { id, title } of variables) { | ||
if (!this._panelService.hasPanel(serverUrl, id)) { | ||
const panel = vscode.window.createWebviewPanel( | ||
'dhPanel', // Identifies the type of the webview. Used internally | ||
title, | ||
{ viewColumn: vscode.ViewColumn.Two, preserveFocus: true }, | ||
{ | ||
enableScripts: true, | ||
retainContextWhenHidden: true, | ||
} | ||
); | ||
|
||
this._panelService.setPanel(serverUrl, id, panel); | ||
|
||
// If panel gets disposed, remove it from the caches | ||
panel.onDidDispose(() => { | ||
this._panelService.deletePanel(serverUrl, id); | ||
}); | ||
|
||
// See @deprecated comment in PanelFocusManager.onDidChangeViewState | ||
// Ensure focus is not stolen when panel is loaded | ||
// panel.onDidChangeViewState( | ||
// this.panelFocusManager.handleOnDidChangeViewState(panel) | ||
// ); | ||
} | ||
|
||
const panel = this._panelService.getPanelOrThrow(serverUrl, id); | ||
lastPanel = panel; | ||
|
||
// See @deprecated comment in PanelFocusManager.onDidChangeViewState | ||
// Ensure focus is not stolen when panel is loaded | ||
// this.panelFocusManager.initialize(panel); | ||
|
||
const connection = this._serverManager.getConnection(serverUrl); | ||
assertDefined(connection, 'connection'); | ||
|
||
const iframeUrl = getEmbedWidgetUrl( | ||
serverUrl, | ||
title, | ||
getDHThemeKey(), | ||
connection instanceof DhcService ? connection.getPsk() : undefined | ||
); | ||
|
||
panel.webview.html = getPanelHtml(iframeUrl, title); | ||
|
||
// TODO: The postMessage apis will be needed for auth in DHE (vscode-deephaven/issues/76). | ||
// Leaving this here commented out for reference, but it will need some | ||
// re-working. Namely this seems to subscribe multiple times. Should see | ||
// if can move it inside of the panel creation block or unsubscribe older | ||
// subscriptions whenever we subscribe. | ||
// panel.webview.onDidReceiveMessage(({ data }) => { | ||
// const postMessage = panel.webview.postMessage.bind(panel.webview); | ||
// this.handlePanelMessage(data, postMessage); | ||
// }); | ||
} | ||
Comment on lines
+64
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why isn't this in the creation block above? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I plan to move it as part of the TODO: since it needs some other work anyway. |
||
|
||
lastPanel?.reveal(); | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './ConnectionController'; | ||
export * from './ExtensionController'; | ||
export * from './PanelController'; | ||
export * from './PipServerController'; | ||
export * from './ServerConnectionTreeDragAndDropController'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,43 +5,31 @@ import type { | |
ConnectionAndSession, | ||
ConsoleType, | ||
IDhService, | ||
IPanelService, | ||
IToastService, | ||
VariableDefintion, | ||
} from '../types'; | ||
import { | ||
assertIsVariableID, | ||
formatTimestamp, | ||
getCombinedSelectedLinesText, | ||
isAggregateError, | ||
Logger, | ||
NoConsoleTypesError, | ||
parseServerError, | ||
} from '../util'; | ||
import { OPEN_VARIABLE_PANELS_CMD, VARIABLE_UNICODE_ICONS } from '../common'; | ||
|
||
const logger = new Logger('DhService'); | ||
|
||
/* eslint-disable @typescript-eslint/naming-convention */ | ||
const icons = { | ||
Figure: '📈', | ||
'deephaven.plot.express.DeephavenFigure': '📈', | ||
Table: '⬜', | ||
'deephaven.ui.Element': '✨', | ||
} as const; | ||
type IconType = keyof typeof icons; | ||
/* eslint-enable @typescript-eslint/naming-convention */ | ||
|
||
export abstract class DhService<TDH = unknown, TClient = unknown> | ||
implements IDhService<TDH, TClient> | ||
{ | ||
constructor( | ||
serverUrl: URL, | ||
panelService: IPanelService, | ||
diagnosticsCollection: vscode.DiagnosticCollection, | ||
outputChannel: vscode.OutputChannel, | ||
toaster: IToastService | ||
) { | ||
this.serverUrl = serverUrl; | ||
this.panelService = panelService; | ||
this.diagnosticsCollection = diagnosticsCollection; | ||
this.outputChannel = outputChannel; | ||
this.toaster = toaster; | ||
|
@@ -55,7 +43,6 @@ export abstract class DhService<TDH = unknown, TClient = unknown> | |
|
||
protected readonly outputChannel: vscode.OutputChannel; | ||
protected readonly toaster: IToastService; | ||
private readonly panelService: IPanelService; | ||
private readonly diagnosticsCollection: vscode.DiagnosticCollection; | ||
private cachedCreateClient: Promise<TClient> | null = null; | ||
private cachedCreateSession: Promise< | ||
|
@@ -74,14 +61,6 @@ export abstract class DhService<TDH = unknown, TClient = unknown> | |
dh: TDH, | ||
client: TClient | ||
): Promise<ConnectionAndSession<DhcType.IdeConnection, DhcType.IdeSession>>; | ||
protected abstract getPanelHtml(title: string): string; | ||
protected abstract handlePanelMessage( | ||
message: { | ||
id: string; | ||
message: string; | ||
}, | ||
postResponseMessage: (response: unknown) => void | ||
): Promise<void>; | ||
|
||
private clearCaches(): void { | ||
this.cachedCreateClient = null; | ||
|
@@ -103,6 +82,7 @@ export abstract class DhService<TDH = unknown, TClient = unknown> | |
|
||
public async dispose(): Promise<void> { | ||
this.clearCaches(); | ||
this._onDidDisconnect.dispose(); | ||
} | ||
|
||
protected getToastErrorMessage( | ||
|
@@ -303,69 +283,23 @@ export abstract class DhService<TDH = unknown, TClient = unknown> | |
return; | ||
} | ||
|
||
const changed = [...result!.changes.created, ...result!.changes.updated]; | ||
|
||
// Have to set this with type assertion since TypeScript can't figure out | ||
// assignments inside of the `forEach` and will treat `lastPanel` as `null`. | ||
let lastPanel = null as vscode.WebviewPanel | null; | ||
|
||
changed.forEach(({ id, title = 'Unknown', type }) => { | ||
assertIsVariableID(id, 'id'); | ||
const changed = [ | ||
...result!.changes.created, | ||
...result!.changes.updated, | ||
] as VariableDefintion[]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unfortunately no. It complains about the mismatch of the branded ids with string ids. I added a comment. |
||
|
||
const icon = icons[type as IconType] ?? type; | ||
changed.forEach(({ title = 'Unknown', type }) => { | ||
const icon = VARIABLE_UNICODE_ICONS[type] ?? type; | ||
this.outputChannel.appendLine(`${icon} ${title}`); | ||
|
||
// Don't show panels for variables starting with '_' | ||
if (title.startsWith('_')) { | ||
return; | ||
} | ||
|
||
if (!this.panelService.hasPanel(this.serverUrl, id)) { | ||
const panel = vscode.window.createWebviewPanel( | ||
'dhPanel', // Identifies the type of the webview. Used internally | ||
title, | ||
{ viewColumn: vscode.ViewColumn.Two, preserveFocus: true }, | ||
{ | ||
enableScripts: true, | ||
retainContextWhenHidden: true, | ||
} | ||
); | ||
|
||
this.panelService.setPanel(this.serverUrl, id, panel); | ||
|
||
// If panel gets disposed, remove it from the caches | ||
panel.onDidDispose(() => { | ||
this.panelService.deletePanel(this.serverUrl, id); | ||
}); | ||
|
||
// See @deprecated comment in PanelFocusManager.onDidChangeViewState | ||
// Ensure focus is not stolen when panel is loaded | ||
// panel.onDidChangeViewState( | ||
// this.panelFocusManager.handleOnDidChangeViewState(panel) | ||
// ); | ||
} | ||
|
||
const panel = this.panelService.getPanelOrThrow(this.serverUrl, id); | ||
lastPanel = panel; | ||
|
||
// See @deprecated comment in PanelFocusManager.onDidChangeViewState | ||
// Ensure focus is not stolen when panel is loaded | ||
// this.panelFocusManager.initialize(panel); | ||
|
||
panel.webview.html = this.getPanelHtml(title); | ||
|
||
// TODO: The postMessage apis will be needed for auth in DHE (vscode-deephaven/issues/76). | ||
// Leaving this here commented out for reference, but it will need some | ||
// re-working. Namely this seems to subscribe multiple times. Should see | ||
// if can move it inside of the panel creation block or unsubscribe older | ||
// subscriptions whenever we subscribe. | ||
// panel.webview.onDidReceiveMessage(({ data }) => { | ||
// const postMessage = panel.webview.postMessage.bind(panel.webview); | ||
// this.handlePanelMessage(data, postMessage); | ||
// }); | ||
}); | ||
|
||
lastPanel?.reveal(); | ||
const showVariables = changed.filter(v => !v.title.startsWith('_')); | ||
|
||
vscode.commands.executeCommand( | ||
OPEN_VARIABLE_PANELS_CMD, | ||
this.serverUrl, | ||
showVariables | ||
); | ||
} | ||
|
||
getConsoleTypes = async (): Promise<Set<ConsoleType>> => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have a TODO or be removed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Deleted