By default, open html file in preview

When the editor opens, I want to display the source html in the left panel for editing and on the right I want to display a preview of that rendered html. I understand that I should do this in the initializeLayout method of my FrontEndApplicationContribution, but what do I call to actually open the editor and preview windows? This is what I have at the moment:

    initializeLayout(app: FrontendApplication): MaybePromise<void> {
        // Open the file browser in the left pane.
        this.navigator.openView({
            activate: true
        })

        // Open index.html in a preview browser.
        const uriStr = this.workspaceService.tryGetRoots()[0];
        console.log(uriStr);
        const uri = new URI(uriStr + "index.html");
        debugger;
        open(this.openerService, uri, { preview: true });
    }

@akosyakov: Do you have any thoughts here? (Also, if this is already obvious in the docs, please point me to them. Thanks!)

Update: I’m now trying to do this with the MarkdownPreviewHandler:

const filesystemPath = "/path/to/home/projectpath/browser-app/index.html"
const uri = FileUri.create(filesystemPath);
this.previewHandler.renderContent({'content': 'foo', 'originUri': uri});

cc @akosyakov

No, you should not. Try this.

Amazing! Thanks so much. I’ll let you know how it goes.

My initial example was the other way around. I have fixed and simplified it. Please check the diff.

@kittaakos: This worked perfectly. Thanks so much! Really appreciate it.

Can you tell me how to a) find the index.html in the root directory (the directory that’s open in the file browser) and then b) open that index.html in the editor. In other words, instead of needing to click on the index.html file to trigger the preview, I want to have the editor and the preview opened when the user first views Theia.

@briandant I had a similar issue and solved it that way:

  • Inject a Workspace Service
  • in initialize(), add a WorkspaceService#onWorkspaceChanged listener (so you’re notified if the workspace changes)
  • this listener can just check whether a file called ‘index.html’ is included in the FileStat[]
  • and if it’s included, open it just the same way as in @kittaakos example (the URI is the resource property of the FileStat)

@alex0711: Thanks! I am using the onWorkspaceChanged listener, which seems to accomplish the first aspect of the task—I am listening for the right event. (Though I wonder: does onWorkspaceChanged actually watch for too much? Will index.html be opened every time any change is made, rather than merely being opened when Theia first loads?)

But how do I access the FileStat[]?

Could you post some code to show me precisely what you’re doing?

@briandant that’s what’s working for me, a little bit adapted to look for a index.html file directly at the root:
AFAIK the onWorkspaceChanged is only triggered if the workspace location changes (opening or closing the workspace, no file changes). It’s important to add this code in the initialize method of the FrontendApplicationContribution (else the listener may be registered after the workspace is opened) and also the widget can only be opened once Theia has transitioned to ‘ready state’, therefore the openHandler is used in a onStateChanged callback.

        this.workspaceService.onWorkspaceChanged((files: FileStat[]) => {
        console.log("Workspace changed");
        // the files array may be empty if the workspace got closed, so there should actually be a check...
        const indexHtml = files[0].children?.find(a => a.name === 'index.html');
        if (indexHtml) {
            const uri = indexHtml.resource;
            if (uri && uri.scheme === 'file' && (uri.path.ext === '.html')) {
                this.stateService.onStateChanged((state) => {
                    if (state === 'ready') {
                        this.openHandler.open(uri, { widgetOptions: { area: 'main' } });
                    }
                })
            }
        }
    });