bw-hspc-contest-env/extension/bwcontest/src/problemPanel.ts

247 lines
6.9 KiB
TypeScript
Raw Normal View History

2023-05-06 00:01:27 -04:00
import * as vscode from 'vscode';
import { getNonce } from './getNonce';
2023-05-07 16:30:42 -04:00
import { runJava } from './run/java';
import { extensionSettings } from './extension';
import { join } from 'path';
2023-05-08 14:37:52 -04:00
import { submitProblem } from './submit';
2023-10-16 13:11:54 -04:00
import urlJoin from 'url-join';
export type ProblemData = {
id: number;
name: string;
pascalName: string;
sampleInput: string;
sampleOutput: string;
}[];
export type MessageType = { msg: 'onRequestProblemData' };
export type WebviewMessageType = { msg: 'onProblemData'; data: ProblemData };
/**
* Singleton class for problem panel
*/
2023-05-06 00:01:27 -04:00
export class BWPanel {
public static currentPanel: BWPanel | undefined;
2023-10-16 13:11:54 -04:00
private running: boolean = false;
private kill: Function | null = null;
2023-05-06 00:01:27 -04:00
2023-10-16 13:11:54 -04:00
private constructor(
private readonly context: vscode.ExtensionContext,
private readonly panel: vscode.WebviewPanel,
private readonly extensionUri: vscode.Uri,
private readonly webUrl: string
) {
this.update();
}
2023-05-06 00:01:27 -04:00
2023-10-16 13:11:54 -04:00
public static show(context: vscode.ExtensionContext, webUrl: string) {
2023-05-06 00:01:27 -04:00
const column = vscode.window.activeTextEditor
? vscode.window.activeTextEditor.viewColumn
: undefined;
2023-10-16 13:11:54 -04:00
// Show panel if exists
2023-05-06 00:01:27 -04:00
if (BWPanel.currentPanel) {
2023-10-16 13:11:54 -04:00
BWPanel.currentPanel.panel.reveal(column);
2023-05-06 00:01:27 -04:00
return;
}
2023-10-16 13:11:54 -04:00
// Otherwise create new panel
2023-05-06 00:01:27 -04:00
const panel = vscode.window.createWebviewPanel(
2023-10-16 13:11:54 -04:00
'bwpanel',
'BWContest',
2023-05-06 00:01:27 -04:00
column || vscode.ViewColumn.One,
{
enableScripts: true,
2023-05-07 16:30:42 -04:00
retainContextWhenHidden: true,
2023-05-06 00:01:27 -04:00
localResourceRoots: [
2023-05-08 14:37:52 -04:00
vscode.Uri.joinPath(context.extensionUri, 'media'),
vscode.Uri.joinPath(context.extensionUri, 'out/compiled')
2023-05-06 00:01:27 -04:00
]
}
);
2023-10-16 13:11:54 -04:00
BWPanel.currentPanel = new BWPanel(context, panel, context.extensionUri, webUrl);
2023-05-06 00:01:27 -04:00
}
public static kill() {
BWPanel.currentPanel?.dispose();
BWPanel.currentPanel = undefined;
}
public dispose() {
2023-10-16 13:11:54 -04:00
this.panel.dispose();
2023-05-06 00:01:27 -04:00
BWPanel.currentPanel = undefined;
}
2023-10-16 13:11:54 -04:00
private webviewPostMessage(m: WebviewMessageType) {
this.panel.webview.postMessage(m);
}
2023-05-06 00:01:27 -04:00
2023-10-16 13:11:54 -04:00
private async update() {
const webview = this.panel.webview;
this.panel.webview.html = this._getHtmlForWebview(webview);
webview.onDidReceiveMessage(async (m: MessageType) => {
switch (m.msg) {
// case 'onKill': {
// if (!this.running || !this.kill) {
// break;
// }
// this.kill();
// }
// case 'onSubmit': {
// await vscode.workspace.saveAll();
// if (!data.value) {
// return;
// }
// const ans = await vscode.window.showInformationMessage(
// `Are you sure you want to submit ${data.value.problemName}?`,
// 'Yes',
// 'No'
// );
// if (ans !== 'Yes') {
// break;
// }
// try {
// await submitProblem(
// data.value.sessionToken,
// data.value.contestId,
// data.value.teamId,
// data.value.problemId
// );
// } catch (err: any) {
// vscode.window.showErrorMessage(err.message ?? 'Submission unsuccessful');
// break;
// }
// vscode.window.showInformationMessage('Submitted!');
// break;
// }
// case 'onRun': {
// if (this.running === true) {
// vscode.window.showErrorMessage('Already running');
// break;
// }
// await vscode.workspace.saveAll();
// if (!data.value) {
// break;
// }
// const repoDir = extensionSettings().repoClonePath;
// this.running = true;
// const process = await runJava(
// join(
// repoDir,
// 'BWContest',
// data.value.contestId.toString(),
// data.value.teamId.toString(),
// data.value.problemPascalName.toString()
// ),
// join(
// repoDir,
// 'BWContest',
// data.value.contestId.toString(),
// data.value.teamId.toString(),
// data.value.problemPascalName.toString(),
// `${data.value.problemPascalName}.java`
// ),
// data.value.problemPascalName,
// data.value.input
// );
// if (!process) {
// this.panel.webview.postMessage({
// type: 'onOutput',
// value: '[An error occurred while running]'
// });
// break;
// }
// process.output
// .then((output) => {
// this.panel.webview.postMessage({ type: 'onOutput', value: output });
// this.running = false;
// this.kill = null;
// })
// .catch(() => {
// this.panel.webview.postMessage({
// type: 'onOutput',
// value: '[An error occurred while running]'
// });
// this.running = false;
// this.kill = null;
// });
// this.kill = process.kill;
// break;
// }
case 'onRequestProblemData': {
const token: string | undefined = this.context.globalState.get('token');
if (token !== undefined) {
const res = await fetch(urlJoin(this.webUrl, `/api/contest/${token}`));
const data = await res.json();
if (data.success === true) {
this.webviewPostMessage({
msg: 'onProblemData',
data: data.problems
});
2023-10-16 13:11:54 -04:00
}
2023-05-06 00:01:27 -04:00
}
break;
}
2023-10-16 13:11:54 -04:00
// case 'onInfo': {
// if (!data.value) {
// return;
// }
// vscode.window.showInformationMessage(data.value);
// break;
// }
// case 'onError': {
// if (!data.value) {
// return;
// }
// vscode.window.showErrorMessage(data.value);
// break;
2023-05-06 00:01:27 -04:00
// }
}
});
}
private _getHtmlForWebview(webview: vscode.Webview) {
const scriptUri = webview.asWebviewUri(
2023-10-16 13:11:54 -04:00
vscode.Uri.joinPath(this.extensionUri, 'out/compiled', 'problemPanel.js')
2023-05-06 00:01:27 -04:00
);
const stylesResetUri = webview.asWebviewUri(
2023-10-16 13:11:54 -04:00
vscode.Uri.joinPath(this.extensionUri, 'media', 'reset.css')
2023-05-06 00:01:27 -04:00
);
const stylesMainUri = webview.asWebviewUri(
2023-10-16 13:11:54 -04:00
vscode.Uri.joinPath(this.extensionUri, 'media', 'vscode.css')
2023-05-06 00:01:27 -04:00
);
2023-05-07 11:01:27 -04:00
const cssUri = webview.asWebviewUri(
2023-10-16 13:11:54 -04:00
vscode.Uri.joinPath(this.extensionUri, 'out/compiled', 'problemPanel.css')
2023-05-07 11:01:27 -04:00
);
2023-05-06 00:01:27 -04:00
const nonce = getNonce();
return `<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--
Use a content security policy to only allow loading images from https or from our extension directory,
and only allow scripts that have a specific nonce.
-->
<meta http-equiv="Content-Security-Policy" content="img-src https: data:; style-src 'unsafe-inline' ${webview.cspSource}; script-src 'nonce-${nonce}';">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="${stylesResetUri}" rel="stylesheet">
<link href="${stylesMainUri}" rel="stylesheet">
2023-05-07 11:01:27 -04:00
<link href="${cssUri}" rel="stylesheet">
<script nonce="${nonce}">
const vscode = acquireVsCodeApi();
</script>
2023-05-06 00:01:27 -04:00
</head>
<body>
</body>
<script src=${scriptUri} nonce="${nonce}">
</script>
</html>`;
}
}