[extension] More cleanup
This commit is contained in:
parent
88be84bb62
commit
6fb6f57ece
@ -4,6 +4,20 @@ import { cloneAndOpenRepo } from './extension';
|
|||||||
import { BWPanel } from './problemPanel';
|
import { BWPanel } from './problemPanel';
|
||||||
import urlJoin from 'url-join';
|
import urlJoin from 'url-join';
|
||||||
|
|
||||||
|
export type TeamData = {
|
||||||
|
teamId: number;
|
||||||
|
contestId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WebviewMessageType = { msg: 'onLogin'; data: TeamData } | { msg: 'onLogout' };
|
||||||
|
|
||||||
|
export type MessageType =
|
||||||
|
| { msg: 'onTestAndSubmit' }
|
||||||
|
| { msg: 'onStartup' }
|
||||||
|
| { msg: 'onClone'; data: { contestId: number; teamId: number } }
|
||||||
|
| { msg: 'onLogin'; data: { teamName: string; password: string } }
|
||||||
|
| { msg: 'onLogout' };
|
||||||
|
|
||||||
export class SidebarProvider implements vscode.WebviewViewProvider {
|
export class SidebarProvider implements vscode.WebviewViewProvider {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly extensionUri: vscode.Uri,
|
private readonly extensionUri: vscode.Uri,
|
||||||
@ -19,43 +33,40 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
|||||||
};
|
};
|
||||||
webview.html = this.getHtmlForWebview(webview);
|
webview.html = this.getHtmlForWebview(webview);
|
||||||
|
|
||||||
webview.onDidReceiveMessage(async (data: { type: string; value: any }) => {
|
const webviewPostMessage = (m: WebviewMessageType) => {
|
||||||
switch (data.type) {
|
webview.postMessage(m);
|
||||||
|
};
|
||||||
|
|
||||||
|
webview.onDidReceiveMessage(async (m: MessageType) => {
|
||||||
|
switch (m.msg) {
|
||||||
case 'onTestAndSubmit': {
|
case 'onTestAndSubmit': {
|
||||||
if (this.context) {
|
if (this.context) {
|
||||||
BWPanel.createOrShow(this.context, this.webUrl);
|
BWPanel.show(this.context, this.webUrl);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'onStartup': {
|
case 'onStartup': {
|
||||||
const token: string | undefined = this.context.globalState.get('token');
|
const token: string | undefined = this.context.globalState.get('token');
|
||||||
const teamData = this.context.globalState.get('teamData');
|
const teamData = this.context.globalState.get('teamData') as TeamData | undefined;
|
||||||
if (token && teamData !== undefined) {
|
if (token && teamData !== undefined) {
|
||||||
webview.postMessage({
|
webviewPostMessage({
|
||||||
type: 'onLogin',
|
msg: 'onLogin',
|
||||||
value: teamData
|
data: teamData
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
webview.postMessage({
|
|
||||||
type: 'onWebUrl',
|
|
||||||
value: this.webUrl
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'onClone': {
|
case 'onClone': {
|
||||||
if (!data.value || !data.value.contestId || !data.value.teamId) {
|
await cloneAndOpenRepo(m.data.contestId, m.data.teamId);
|
||||||
return;
|
|
||||||
}
|
|
||||||
await cloneAndOpenRepo(parseInt(data.value.contestId), parseInt(data.value.teamId));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'requestLogin': {
|
case 'onLogin': {
|
||||||
const res = await fetch(urlJoin(this.webUrl, '/api/team/login'), {
|
const res = await fetch(urlJoin(this.webUrl, '/api/team/login'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
teamname: data.value.teamname,
|
teamname: m.data.teamName,
|
||||||
password: data.value.password
|
password: m.data.password
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
const thing = await res.json();
|
const thing = await res.json();
|
||||||
@ -72,13 +83,13 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.context.globalState.update('teamData', data2.data);
|
this.context.globalState.update('teamData', data2.data);
|
||||||
webview.postMessage({ type: 'onLogin', value: data2.data });
|
webviewPostMessage({ msg: 'onLogout' });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'requestLogout': {
|
case 'onLogout': {
|
||||||
const sessionToken = this.context.globalState.get<string>('token');
|
const sessionToken = this.context.globalState.get<string>('token');
|
||||||
if (sessionToken === undefined) {
|
if (sessionToken === undefined) {
|
||||||
webview.postMessage({ type: 'onLogout' });
|
webviewPostMessage({ msg: 'onLogout' });
|
||||||
}
|
}
|
||||||
const res = await fetch(urlJoin(this.webUrl, '/api/team/logout'), {
|
const res = await fetch(urlJoin(this.webUrl, '/api/team/logout'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
@ -92,29 +103,29 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
|||||||
}
|
}
|
||||||
const data2 = await res.json();
|
const data2 = await res.json();
|
||||||
if (data2.success === true) {
|
if (data2.success === true) {
|
||||||
webview.postMessage({ type: 'onLogout' });
|
webviewPostMessage({ msg: 'onLogout' });
|
||||||
this.context.globalState.update('token', undefined);
|
this.context.globalState.update('token', undefined);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'onLogout': {
|
// case 'onLogout': {
|
||||||
this.context.globalState.update('token', null);
|
// this.context.globalState.update('token', null);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case 'onInfo': {
|
// case 'onInfo': {
|
||||||
if (!data.value) {
|
// if (!data.value) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
vscode.window.showInformationMessage(data.value);
|
// vscode.window.showInformationMessage(data.value);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case 'onError': {
|
// case 'onError': {
|
||||||
if (!data.value) {
|
// if (!data.value) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
vscode.window.showErrorMessage(data.value);
|
// vscode.window.showErrorMessage(data.value);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,56 @@ import { runJava } from './run/java';
|
|||||||
import { extensionSettings } from './extension';
|
import { extensionSettings } from './extension';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { submitProblem } from './submit';
|
import { submitProblem } from './submit';
|
||||||
|
import urlJoin from 'url-join';
|
||||||
|
|
||||||
export class BWPanel {
|
export type ProblemData = {
|
||||||
/**
|
id: number;
|
||||||
* Track the currently panel. Only allow a single panel to exist at a time.
|
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
|
||||||
*/
|
*/
|
||||||
|
export class BWPanel {
|
||||||
public static currentPanel: BWPanel | undefined;
|
public static currentPanel: BWPanel | undefined;
|
||||||
|
|
||||||
public static readonly viewType = 'bwpanel';
|
private running: boolean = false;
|
||||||
|
private kill: Function | null = null;
|
||||||
|
|
||||||
private readonly _panel: vscode.WebviewPanel;
|
private constructor(
|
||||||
private readonly _extensionUri: vscode.Uri;
|
private readonly context: vscode.ExtensionContext,
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private readonly panel: vscode.WebviewPanel,
|
||||||
private static _context?: vscode.ExtensionContext;
|
private readonly extensionUri: vscode.Uri,
|
||||||
private static _running: boolean;
|
private readonly webUrl: string
|
||||||
private static _kill: Function | null;
|
) {
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
public static createOrShow(context: vscode.ExtensionContext, webUrl: string) {
|
public static show(context: vscode.ExtensionContext, webUrl: string) {
|
||||||
this._context = context;
|
|
||||||
const column = vscode.window.activeTextEditor
|
const column = vscode.window.activeTextEditor
|
||||||
? vscode.window.activeTextEditor.viewColumn
|
? vscode.window.activeTextEditor.viewColumn
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
// If we already have a panel, show it.
|
// Show panel if exists
|
||||||
if (BWPanel.currentPanel) {
|
if (BWPanel.currentPanel) {
|
||||||
BWPanel.currentPanel._panel.reveal(column);
|
BWPanel.currentPanel.panel.reveal(column);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, create a new panel.
|
// Otherwise create new panel
|
||||||
const panel = vscode.window.createWebviewPanel(
|
const panel = vscode.window.createWebviewPanel(
|
||||||
BWPanel.viewType,
|
'bwpanel',
|
||||||
'BWContest',
|
'BWContest',
|
||||||
column || vscode.ViewColumn.One,
|
column || vscode.ViewColumn.One,
|
||||||
{
|
{
|
||||||
// Enable javascript in the webview
|
|
||||||
enableScripts: true,
|
enableScripts: true,
|
||||||
|
|
||||||
retainContextWhenHidden: true,
|
retainContextWhenHidden: true,
|
||||||
|
|
||||||
// And restrict the webview to only loading content from our extension's `media` directory.
|
|
||||||
localResourceRoots: [
|
localResourceRoots: [
|
||||||
vscode.Uri.joinPath(context.extensionUri, 'media'),
|
vscode.Uri.joinPath(context.extensionUri, 'media'),
|
||||||
vscode.Uri.joinPath(context.extensionUri, 'out/compiled')
|
vscode.Uri.joinPath(context.extensionUri, 'out/compiled')
|
||||||
@ -51,7 +61,7 @@ export class BWPanel {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
BWPanel.currentPanel = new BWPanel(panel, context.extensionUri, webUrl);
|
BWPanel.currentPanel = new BWPanel(context, panel, context.extensionUri, webUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static kill() {
|
public static kill() {
|
||||||
@ -59,149 +69,134 @@ export class BWPanel {
|
|||||||
BWPanel.currentPanel = undefined;
|
BWPanel.currentPanel = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static revive(panel: vscode.WebviewPanel, extensionUri: vscode.Uri, webUrl: string) {
|
|
||||||
BWPanel.currentPanel = new BWPanel(panel, extensionUri, webUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri, webUrl: string) {
|
|
||||||
this._panel = panel;
|
|
||||||
this._extensionUri = extensionUri;
|
|
||||||
this._update();
|
|
||||||
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose() {
|
public dispose() {
|
||||||
|
this.panel.dispose();
|
||||||
BWPanel.currentPanel = undefined;
|
BWPanel.currentPanel = undefined;
|
||||||
this._panel.dispose();
|
|
||||||
while (this._disposables.length) {
|
|
||||||
const x = this._disposables.pop();
|
|
||||||
if (x) {
|
|
||||||
x.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _update() {
|
private webviewPostMessage(m: WebviewMessageType) {
|
||||||
const webview = this._panel.webview;
|
this.panel.webview.postMessage(m);
|
||||||
|
}
|
||||||
|
|
||||||
this._panel.webview.html = this._getHtmlForWebview(webview);
|
private async update() {
|
||||||
webview.onDidReceiveMessage(async (data) => {
|
const webview = this.panel.webview;
|
||||||
switch (data.type) {
|
|
||||||
case 'onKill': {
|
|
||||||
if (!BWPanel._running || !BWPanel._kill) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
BWPanel._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 (BWPanel._running === true) {
|
|
||||||
vscode.window.showErrorMessage('Already running');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await vscode.workspace.saveAll();
|
|
||||||
if (!data.value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const repoDir = extensionSettings().repoClonePath;
|
|
||||||
BWPanel._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 });
|
|
||||||
BWPanel._running = false;
|
|
||||||
BWPanel._kill = null;
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this._panel.webview.postMessage({
|
|
||||||
type: 'onOutput',
|
|
||||||
value: '[An error occurred while running]'
|
|
||||||
});
|
|
||||||
BWPanel._running = false;
|
|
||||||
BWPanel._kill = null;
|
|
||||||
});
|
|
||||||
BWPanel._kill = process.kill;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'onStartup': {
|
|
||||||
const token: string | undefined = BWPanel._context?.globalState.get('token');
|
|
||||||
|
|
||||||
if (token) {
|
this.panel.webview.html = this._getHtmlForWebview(webview);
|
||||||
this._panel.webview.postMessage({
|
webview.onDidReceiveMessage(async (m: MessageType) => {
|
||||||
type: 'onSession',
|
switch (m.msg) {
|
||||||
value: token
|
// 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
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'onInfo': {
|
// case 'onInfo': {
|
||||||
if (!data.value) {
|
// if (!data.value) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
vscode.window.showInformationMessage(data.value);
|
// vscode.window.showInformationMessage(data.value);
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case 'onError': {
|
// case 'onError': {
|
||||||
if (!data.value) {
|
// if (!data.value) {
|
||||||
return;
|
// return;
|
||||||
}
|
// }
|
||||||
vscode.window.showErrorMessage(data.value);
|
// vscode.window.showErrorMessage(data.value);
|
||||||
break;
|
|
||||||
}
|
|
||||||
// case "tokens": {
|
|
||||||
// await Util.globalState.update(accessTokenKey, data.accessToken);
|
|
||||||
// await Util.globalState.update(refreshTokenKey, data.refreshToken);
|
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@ -209,23 +204,20 @@ export class BWPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getHtmlForWebview(webview: vscode.Webview) {
|
private _getHtmlForWebview(webview: vscode.Webview) {
|
||||||
// // And the uri we use to load this script in the webview
|
|
||||||
const scriptUri = webview.asWebviewUri(
|
const scriptUri = webview.asWebviewUri(
|
||||||
vscode.Uri.joinPath(this._extensionUri, 'out/compiled', 'problemPanel.js')
|
vscode.Uri.joinPath(this.extensionUri, 'out/compiled', 'problemPanel.js')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Uri to load styles into webview
|
|
||||||
const stylesResetUri = webview.asWebviewUri(
|
const stylesResetUri = webview.asWebviewUri(
|
||||||
vscode.Uri.joinPath(this._extensionUri, 'media', 'reset.css')
|
vscode.Uri.joinPath(this.extensionUri, 'media', 'reset.css')
|
||||||
);
|
);
|
||||||
const stylesMainUri = webview.asWebviewUri(
|
const stylesMainUri = webview.asWebviewUri(
|
||||||
vscode.Uri.joinPath(this._extensionUri, 'media', 'vscode.css')
|
vscode.Uri.joinPath(this.extensionUri, 'media', 'vscode.css')
|
||||||
);
|
);
|
||||||
const cssUri = webview.asWebviewUri(
|
const cssUri = webview.asWebviewUri(
|
||||||
vscode.Uri.joinPath(this._extensionUri, 'out/compiled', 'problemPanel.css')
|
vscode.Uri.joinPath(this.extensionUri, 'out/compiled', 'problemPanel.css')
|
||||||
);
|
);
|
||||||
|
|
||||||
// // Use a nonce to only allow specific scripts to be run
|
|
||||||
const nonce = getNonce();
|
const nonce = getNonce();
|
||||||
|
|
||||||
return `<!DOCTYPE html>
|
return `<!DOCTYPE html>
|
||||||
|
@ -1,120 +1,89 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import urlJoin from 'url-join';
|
import type { WebviewMessageType, MessageType, ProblemData } from '../../src/problemPanel';
|
||||||
|
|
||||||
function postMessage(message: any) {
|
function postMessage(message: MessageType) {
|
||||||
vscode.postMessage(message);
|
vscode.postMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
type ProblemData = {
|
// let savedInputs: Map<number, { input: string; output: string }> = new Map();
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
pascalName: string;
|
|
||||||
sampleInput: string;
|
|
||||||
sampleOutput: string;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
let savedInputs: Map<number, { input: string; output: string }> = new Map();
|
let activeProblemIndex = 0;
|
||||||
|
|
||||||
let activeProblem: ProblemData[0];
|
|
||||||
let sessionToken: string | undefined;
|
|
||||||
let problemData: ProblemData | undefined;
|
let problemData: ProblemData | undefined;
|
||||||
|
|
||||||
let sampleInputText: HTMLTextAreaElement;
|
let sampleInputValue: string;
|
||||||
let outputText: HTMLTextAreaElement;
|
let outputValue: string;
|
||||||
|
|
||||||
let running = false;
|
let running = false;
|
||||||
|
|
||||||
let webUrl: string | undefined;
|
|
||||||
|
|
||||||
$: if (problemData && problemData.length !== 0) {
|
$: if (problemData && problemData.length !== 0) {
|
||||||
let first = problemData.at(0);
|
activeProblemIndex = 0;
|
||||||
if (first) {
|
|
||||||
activeProblem = first;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetInput() {
|
function resetInput() {
|
||||||
sampleInputText.value = activeProblem.sampleInput;
|
if (problemData) {
|
||||||
|
sampleInputValue = problemData[activeProblemIndex].sampleInput;
|
||||||
|
} else {
|
||||||
|
sampleInputValue = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let contestId: number | undefined;
|
|
||||||
let teamId: number | undefined;
|
|
||||||
|
|
||||||
function onRun() {
|
function onRun() {
|
||||||
if (!running && contestId && teamId) {
|
// if (problemData !== undefined && running === false) {
|
||||||
postMessage({
|
// postMessage({
|
||||||
type: 'onRun',
|
// type: 'requestRun',
|
||||||
value: {
|
// value: {
|
||||||
problemPascalName: activeProblem.pascalName,
|
// problemId: problemData[activeProblemIndex].id,
|
||||||
contestId: contestId,
|
// input: sampleInputValue
|
||||||
teamId: teamId,
|
// }
|
||||||
input: sampleInputText.value
|
// });
|
||||||
}
|
// }
|
||||||
});
|
|
||||||
running = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateTextBoxes() {
|
function updateTextBoxes() {
|
||||||
if (savedInputs.has(activeProblem.id)) {
|
// if (savedInputs.has(activeProblem.id)) {
|
||||||
sampleInputText.value = savedInputs.get(activeProblem.id)!.input;
|
// sampleInputText.value = savedInputs.get(activeProblem.id)!.input;
|
||||||
outputText.value = savedInputs.get(activeProblem.id)!.output;
|
// outputText.value = savedInputs.get(activeProblem.id)!.output;
|
||||||
} else {
|
// } else {
|
||||||
sampleInputText.value = activeProblem.sampleInput;
|
if (problemData !== undefined) {
|
||||||
outputText.value = '[Run to get output]';
|
sampleInputValue = problemData[activeProblemIndex].sampleInput;
|
||||||
}
|
}
|
||||||
|
outputValue = '[Run to get output]';
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function onSubmit() {
|
function onSubmit() {
|
||||||
if (teamId && contestId && sessionToken) {
|
// if (teamId && contestId && sessionToken) {
|
||||||
postMessage({
|
// postMessage({
|
||||||
type: 'onSubmit',
|
// type: 'onSubmit',
|
||||||
value: {
|
// value: {
|
||||||
sessionToken: sessionToken,
|
// sessionToken: sessionToken,
|
||||||
contestId: contestId,
|
// contestId: contestId,
|
||||||
teamId: teamId,
|
// teamId: teamId,
|
||||||
problemId: activeProblem.id,
|
// problemId: activeProblem.id,
|
||||||
problemName: activeProblem.pascalName
|
// problemName: activeProblem.pascalName
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
function onKill() {
|
function onKill() {
|
||||||
postMessage({ type: 'onKill' });
|
// postMessage({ type: 'onKill' });
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchProblemData() {
|
|
||||||
if (sessionToken && webUrl) {
|
|
||||||
const res = await fetch(urlJoin(webUrl, `/api/contest/${sessionToken}`));
|
|
||||||
const data = await res.json();
|
|
||||||
if (data.success === true) {
|
|
||||||
problemData = data.problems as ProblemData;
|
|
||||||
contestId = data.contestId;
|
|
||||||
teamId = data.teamId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('message', async (event) => {
|
|
||||||
const message = (event as MessageEvent).data;
|
|
||||||
if (message.type === 'onSession') {
|
|
||||||
if (message.value !== '') {
|
|
||||||
sessionToken = message.value;
|
|
||||||
await fetchProblemData();
|
|
||||||
updateTextBoxes();
|
|
||||||
}
|
|
||||||
} else if (message.type === 'onOutput') {
|
|
||||||
outputText.value = message.value;
|
|
||||||
running = false;
|
|
||||||
} else if (message.type === 'onWebUrl') {
|
|
||||||
webUrl = message.value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
postMessage({ type: 'onStartup' });
|
postMessage({ msg: 'onRequestProblemData' });
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('message', async (event) => {
|
||||||
|
const m = (event as MessageEvent).data as WebviewMessageType;
|
||||||
|
// if (message.msg === 'onOutput') {
|
||||||
|
// outputValue = message.value;
|
||||||
|
// running = false;
|
||||||
|
if (m.msg === 'onProblemData') {
|
||||||
|
problemData = m.data;
|
||||||
|
updateTextBoxes();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -122,32 +91,32 @@
|
|||||||
|
|
||||||
{#if problemData}
|
{#if problemData}
|
||||||
<div class="tab-container">
|
<div class="tab-container">
|
||||||
{#each problemData as problem}
|
{#each problemData as problem, i}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
if (!running) {
|
if (!running) {
|
||||||
savedInputs.set(activeProblem.id, {
|
// savedInputs.set(activeProblem.id, {
|
||||||
input: sampleInputText.value,
|
// input: sampleInputText.value,
|
||||||
output: outputText.value
|
// output: outputText.value
|
||||||
});
|
// });
|
||||||
activeProblem = problem;
|
activeProblemIndex = i;
|
||||||
updateTextBoxes();
|
updateTextBoxes();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
id={`problem_${problem.id}`}
|
id={`problem_${problem.id}`}
|
||||||
type="button"
|
type="button"
|
||||||
class={'tab ' + (activeProblem.id == problem.id ? 'active' : '')}>{problem.name}</button
|
class={'tab ' + (activeProblemIndex === i ? 'active' : '')}>{problem.name}</button
|
||||||
>
|
>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if activeProblem}
|
{#if problemData !== undefined}
|
||||||
<h2>{activeProblem.name}</h2>
|
<h2>{problemData[activeProblemIndex].name}</h2>
|
||||||
<div style="display:flex">
|
<div style="display:flex">
|
||||||
<div style="flex:1; margin-right:20px">
|
<div style="flex:1; margin-right:20px">
|
||||||
<h3>Sample Input (You can edit this!)</h3>
|
<h3>Sample Input (You can edit this!)</h3>
|
||||||
<textarea bind:this={sampleInputText} />
|
<textarea bind:value={sampleInputValue} />
|
||||||
<button style="margin-top:5px" on:click={resetInput} type="button">Reset Input</button>
|
<button style="margin-top:5px" on:click={resetInput} type="button">Reset Input</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="flex:1">
|
<div style="flex:1">
|
||||||
@ -157,7 +126,7 @@
|
|||||||
<span class="loader"></span>
|
<span class="loader"></span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<textarea bind:this={outputText} disabled />
|
<textarea bind:value={outputValue} readonly />
|
||||||
{#if !running}
|
{#if !running}
|
||||||
<button style="margin-top:5px" on:click={onRun} type="button">Run</button>
|
<button style="margin-top:5px" on:click={onRun} type="button">Run</button>
|
||||||
{:else}
|
{:else}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import type { WebviewMessageType, MessageType, TeamData } from '../../src/SidebarProvider';
|
||||||
|
|
||||||
function postMessage(message: any) {
|
function postMessage(message: MessageType) {
|
||||||
vscode.postMessage(message);
|
vscode.postMessage(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10,49 +11,44 @@
|
|||||||
|
|
||||||
let loggedIn = false;
|
let loggedIn = false;
|
||||||
|
|
||||||
interface TeamData {
|
|
||||||
teamId: number;
|
|
||||||
contestId: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
let teamData: TeamData | undefined;
|
let teamData: TeamData | undefined;
|
||||||
|
|
||||||
function onClone() {
|
function onClone() {
|
||||||
if (teamData) {
|
if (teamData) {
|
||||||
postMessage({
|
postMessage({
|
||||||
type: 'onClone',
|
msg: 'onClone',
|
||||||
value: { contestId: teamData.contestId, teamId: teamData.teamId }
|
data: { contestId: teamData.contestId, teamId: teamData.teamId }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLogin() {
|
function onLogin() {
|
||||||
postMessage({
|
postMessage({
|
||||||
type: 'requestLogin',
|
msg: 'onLogin',
|
||||||
value: { teamname: teamname, password: password }
|
data: { teamName: teamname, password: password }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onLogout() {
|
function onLogout() {
|
||||||
postMessage({
|
postMessage({
|
||||||
type: 'requestLogout'
|
msg: 'onLogout'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function onTestAndSubmit() {
|
function onTestAndSubmit() {
|
||||||
postMessage({ type: 'onTestAndSubmit' });
|
postMessage({ msg: 'onTestAndSubmit' });
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
postMessage({ type: 'onStartup' });
|
postMessage({ msg: 'onStartup' });
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('message', (event) => {
|
window.addEventListener('message', (event) => {
|
||||||
const message = (event as MessageEvent).data;
|
const m = (event as MessageEvent).data as WebviewMessageType;
|
||||||
if (message.type === 'onLogin') {
|
if (m.msg === 'onLogin') {
|
||||||
loggedIn = true;
|
loggedIn = true;
|
||||||
teamData = message.value;
|
teamData = m.data;
|
||||||
} else if (message.type === 'onLogout') {
|
} else if (m.msg === 'onLogout') {
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
teamData = undefined;
|
teamData = undefined;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user