Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/core/src/applicationcomposer/activation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { openTemplateInComposerCommand } from './commands/openTemplateInComposer
import { openInComposerDialogCommand } from './commands/openInComposerDialog'

export async function activate(extensionContext: vscode.ExtensionContext): Promise<void> {
const visualizationManager = new ApplicationComposerManager(extensionContext)
const visualizationManager = await ApplicationComposerManager.create(extensionContext)

extensionContext.subscriptions.push(
openTemplateInComposerCommand.register(visualizationManager),
Expand Down
34 changes: 20 additions & 14 deletions packages/core/src/applicationcomposer/composerWebview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,43 @@

import { join } from 'path'
import * as nls from 'vscode-nls'
const localize = nls.loadMessageBundle()
import * as path from 'path'
import * as vscode from 'vscode'
import { handleMessage } from './handleMessage'
import { FileWatchInfo } from './types'

const localize = nls.loadMessageBundle()

export class ApplicationComposer {
public readonly documentUri: vscode.Uri
public webviewPanel: vscode.WebviewPanel
public webviewPanel: vscode.WebviewPanel = {} as vscode.WebviewPanel
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there any reason this can't be public webviewPanel: vscode.WebviewPanel | undefined? If the webview panel is an empty object does that make some assumptions down the line that it might be defined, even though it isn't?

Copy link
Contributor Author

@Hweinstock Hweinstock Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I wasn't sure if there was a better way to handle this. Since the constructor is private, the only way to instantiate ApplicationComposer is through the create method. Thus, this field will always be initiated. Perhaps there is a better way to enforce this invariant?

The advantage of an empty object is that I don't have to do an undefined check on each usage, but maybe if we can't enforce create being the sole entry point then this is necessary?

protected readonly disposables: vscode.Disposable[] = []
protected isPanelDisposed = false
private readonly onVisualizationDisposeEmitter = new vscode.EventEmitter<void>()
public workSpacePath: string
public defaultTemplatePath: string
public defaultTemplateName: string
// fileWatches is used to monitor template file changes and achieve bi-direction sync
public fileWatches: Record<string, FileWatchInfo>
private getWebviewContent: () => string

public constructor(
private constructor(
textDocument: vscode.TextDocument,
context: vscode.ExtensionContext,
getWebviewContent: () => string
private getWebviewContent: () => Promise<string>,
public fileWatches: Record<string, FileWatchInfo> = {} // fileWatches is used to monitor template file changes and achieve bi-direction sync
) {
this.getWebviewContent = getWebviewContent
this.documentUri = textDocument.uri
this.webviewPanel = this.setupWebviewPanel(textDocument, context)
this.workSpacePath = path.dirname(textDocument.uri.fsPath)
this.defaultTemplatePath = textDocument.uri.fsPath
this.defaultTemplateName = path.basename(this.defaultTemplatePath)
this.fileWatches = {}
}

public static async create(
textDocument: vscode.TextDocument,
context: vscode.ExtensionContext,
getWebviewContent: () => Promise<string>
) {
const obj = new ApplicationComposer(textDocument, getWebviewContent)
obj.webviewPanel = await obj.setupWebviewPanel(textDocument, context)
return obj
}

public get onVisualizationDisposeEvent(): vscode.Event<void> {
Expand All @@ -56,25 +62,25 @@ export class ApplicationComposer {
if (!this.isPanelDisposed) {
this.webviewPanel.dispose()
const document = await vscode.workspace.openTextDocument(this.documentUri)
this.webviewPanel = this.setupWebviewPanel(document, context)
this.webviewPanel = await this.setupWebviewPanel(document, context)
}
}

protected getText(textDocument: vscode.TextDocument): string {
return textDocument.getText()
}

private setupWebviewPanel(
private async setupWebviewPanel(
textDocument: vscode.TextDocument,
context: vscode.ExtensionContext
): vscode.WebviewPanel {
): Promise<vscode.WebviewPanel> {
const documentUri = textDocument.uri

// Create and show panel
const panel = this.createVisualizationWebviewPanel(documentUri, context)

// Set the initial html for the webpage
panel.webview.html = this.getWebviewContent()
panel.webview.html = await this.getWebviewContent()

// Handle messages from the webview
this.disposables.push(
Expand Down
24 changes: 17 additions & 7 deletions packages/core/src/applicationcomposer/webviewManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ export class ApplicationComposerManager {
protected readonly name: string = 'ApplicationComposerManager'

protected readonly managedVisualizations = new Map<string, ApplicationComposer>()
protected extensionContext: vscode.ExtensionContext
protected webviewHtml?: string
protected readonly logger = getLogger()

public constructor(extensionContext: vscode.ExtensionContext) {
this.extensionContext = extensionContext
void this.fetchWebviewHtml()
private constructor(protected extensionContext: vscode.ExtensionContext) {}

public static async create(extensionContext: vscode.ExtensionContext): Promise<ApplicationComposerManager> {
const obj = new ApplicationComposerManager(extensionContext)
await obj.fetchWebviewHtml()
return obj
}

private async fetchWebviewHtml() {
Expand All @@ -41,7 +43,7 @@ export class ApplicationComposerManager {
}
}

private getWebviewContent = () => {
private getWebviewContent = async () => {
if (!this.webviewHtml) {
void this.fetchWebviewHtml()
return ''
Expand Down Expand Up @@ -76,7 +78,11 @@ export class ApplicationComposerManager {

// Existing visualization does not exist, construct new visualization
try {
const newVisualization = new ApplicationComposer(document, this.extensionContext, this.getWebviewContent)
const newVisualization = await ApplicationComposer.create(
document,
this.extensionContext,
this.getWebviewContent
)
this.handleNewVisualization(document.uri.fsPath, newVisualization)

if (vscode.version === '1.91.0') {
Expand All @@ -99,7 +105,11 @@ export class ApplicationComposerManager {
const document = await vscode.workspace.openTextDocument({
language: 'yaml',
})
const newVisualization = new ApplicationComposer(document, this.extensionContext, this.getWebviewContent)
const newVisualization = await ApplicationComposer.create(
document,
this.extensionContext,
this.getWebviewContent
)
this.handleNewVisualization(document.uri.fsPath, newVisualization)

return newVisualization.getPanel()
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/test/applicationcomposer/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { WebviewContext } from '../../applicationcomposer/types'
import { MockDocument } from '../fake/fakeDocument'

export async function createTemplate() {
const manager = new ApplicationComposerManager(globals.context)
const manager = await ApplicationComposerManager.create(globals.context)
const panel = await manager.createTemplate()
assert.ok(panel)
return panel
Expand Down
Loading