Skip to content
This repository has been archived by the owner on Nov 7, 2024. It is now read-only.

Persist webview preview through vscode restarts #300

Merged
merged 6 commits into from
Jun 23, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions addons/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<style id="preview-theme-styles"></style>
<!-- before all of code to avoid rerender by style replacement -->
<script>
// The right side of the equation will be string-replaced later and set in the main.js
window.vscode_state = VSCODE_STATE;
Enter-tainer marked this conversation as resolved.
Show resolved Hide resolved

/// https://stackoverflow.com/questions/13586999/color-difference-similarity-between-two-values-with-js
function deltaE(rgbA, rgbB) {
let labA = rgb2lab(rgbA);
Expand Down
4 changes: 4 additions & 0 deletions addons/frontend/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ function setupVscodeChannel(nextWs) {
if (vscodeAPI?.postMessage) {
vscodeAPI.postMessage({ type: 'started' });
}
if (vscodeAPI?.setState && window.vscode_state) {
vscodeAPI.setState(window.vscode_state);
}


// Handle messages sent from the extension to the webview
window.addEventListener('message', event => {
Expand Down
4 changes: 3 additions & 1 deletion addons/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"categories": [
"Other"
],
"activationEvents": [],
"activationEvents": [
"onWebviewPanel:typst-preview"
],
"main": "./out/src/extension.js",
"contributes": {
"icons": {
Expand Down
40 changes: 37 additions & 3 deletions addons/vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ interface LaunchTask {
activeEditor: vscode.TextEditor,
bindDocument: vscode.TextDocument,
mode: 'doc' | 'slide',
webviewPanel?: vscode.WebviewPanel
}

interface LaunchInBrowserTask extends LaunchTask {
Expand All @@ -357,6 +358,7 @@ const launchPreview = async (task: LaunchInBrowserTask | LaunchInWebViewTask) =>
outputChannel,
activeEditor,
bindDocument,
webviewPanel
} = task;
const filePath = bindDocument.uri.fsPath;

Expand Down Expand Up @@ -462,7 +464,7 @@ const launchPreview = async (task: LaunchInBrowserTask | LaunchInWebViewTask) =>
async function launchPreviewInWebView() {
const basename = path.basename(activeEditor.document.fileName);
// Create and show a new WebView
const panel = vscode.window.createWebviewPanel(
const panel = webviewPanel !== undefined ? webviewPanel : vscode.window.createWebviewPanel(
'typst-preview', // 标识符
`${basename} (Preview)`, // 面板标题
getTargetViewColumn(activeEditor.viewColumn),
Expand Down Expand Up @@ -493,7 +495,7 @@ const launchPreview = async (task: LaunchInBrowserTask | LaunchInWebViewTask) =>
html = html.replace(
"preview-arg:previewMode:Doc",
`preview-arg:previewMode:${previewMode}`
);
).replace("VSCODE_STATE", JSON.stringify({ mode: task.mode, fsPath: bindDocument.uri.fsPath }));
Enter-tainer marked this conversation as resolved.
Show resolved Hide resolved
panel.webview.html = html.replace("ws://127.0.0.1:23625", `ws://127.0.0.1:${dataPlanePort}`);
// 虽然配置的是 http,但是如果是桌面客户端,任何 tcp 连接都支持,这也就包括了 ws
// https://code.visualstudio.com/api/advanced-topics/remote-extensions#forwarding-localhost
Expand Down Expand Up @@ -761,6 +763,37 @@ export class OutlineItem extends vscode.TreeItem {
contextValue = 'outline-item';
}

class TypstPreviewSerializer implements vscode.WebviewPanelSerializer {
context: vscode.ExtensionContext;
outputChannel: vscode.OutputChannel;

constructor(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel) {
this.context = context;
this.outputChannel = outputChannel;
}

async deserializeWebviewPanel(webviewPanel: vscode.WebviewPanel, state: any) {
const activeEditor = vscode.window.visibleTextEditors.find(editor => editor.document.uri.fsPath === state.fsPath);

if (!activeEditor) {
return;
}

const bindDocument = activeEditor.document;
const mode = state.mode;

launchPreview({
kind: "webview",
context: this.context,
outputChannel: this.outputChannel,
activeEditor,
bindDocument,
mode,
webviewPanel
});
}
}

let statusBarItem: vscode.StatusBarItem;
// This method is called when your extension is activated
// Your extension is activated the very first time the command is executed
Expand Down Expand Up @@ -854,8 +887,9 @@ export function activate(context: vscode.ExtensionContext) {
let showLogDisposable = vscode.commands.registerCommand('typst-preview.showLog', async () => {
outputChannel.show();
});
let serializerDisposable = vscode.window.registerWebviewPanelSerializer('typst-preview', new TypstPreviewSerializer(context, outputChannel));

context.subscriptions.push(webviewDisposable, browserDisposable, webviewSlideDisposable, browserSlideDisposable, syncDisposable, showLogDisposable, statusBarItem, revealDocumentDisposable, awaitTreeDisposable);
context.subscriptions.push(webviewDisposable, browserDisposable, webviewSlideDisposable, browserSlideDisposable, syncDisposable, showLogDisposable, statusBarItem, revealDocumentDisposable, awaitTreeDisposable, serializerDisposable);
process.on('SIGINT', () => {
for (const serverProcess of serverProcesses) {
serverProcess.kill();
Expand Down
Loading