-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
107 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,7 @@ | ||
# exercode-viewer | ||
:100: A viewer for scoring learner's submissions on Exercode. | ||
|
||
## Requirements | ||
|
||
- Node.js | ||
- Yarn |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
const child_process = require('node:child_process'); | ||
const fs = require('node:fs'); | ||
const os = require('node:os'); | ||
const path = require('node:path'); | ||
|
||
const { app, BrowserWindow, ipcMain } = require('electron'); | ||
const fflate = require('fflate'); | ||
|
||
const createWindow = () => { | ||
const { screen } = require('electron'); | ||
const { width, height } = screen.getPrimaryDisplay().workAreaSize; | ||
const mainWindow = new BrowserWindow({ | ||
width: width, | ||
height: height, | ||
webPreferences: { | ||
preload: path.join(__dirname, 'preload.cjs'), | ||
devTools: false, | ||
}, | ||
}); | ||
void mainWindow.loadURL('https://exercode.willbooster.com/'); | ||
mainWindow.webContents.openDevTools(); | ||
|
||
mainWindow.webContents.on('did-finish-load', () => { | ||
void mainWindow.webContents.executeJavaScript(` | ||
setInterval(function() { | ||
const chakraStackElem = document.querySelector('.chakra-stack'); | ||
if (chakraStackElem && !document.querySelector('#back')) { | ||
const backButton = document.createElement('button'); | ||
backButton.textContent = 'Back'; | ||
backButton.id = 'back'; | ||
backButton.onclick = () => window.history.back(); | ||
const firstChild = chakraStackElem.firstChild; | ||
chakraStackElem.insertBefore(backButton, firstChild); | ||
const forwardButton = document.createElement('button'); | ||
forwardButton.textContent = 'Forward'; | ||
forwardButton.onclick = () => window.history.forward(); | ||
chakraStackElem.insertBefore(forwardButton, firstChild); | ||
} | ||
const downloadElem = document.querySelector('#download'); | ||
const executionCommandElem = document.querySelector('#execution'); | ||
if (downloadElem && executionCommandElem) { | ||
const zipUrl = downloadElem.href; | ||
downloadElem.onclick = async () => { | ||
const response = await fetch(zipUrl); | ||
const buffer = await response.arrayBuffer(); | ||
window.electron.execute(zipUrl, buffer, executionCommandElem.textContent); | ||
}; | ||
downloadElem.removeAttribute('href'); | ||
downloadElem.id = 'execute'; | ||
downloadElem.textContent = 'Execute on Your PC'; | ||
} | ||
}, 100); | ||
`); | ||
}); | ||
}; | ||
|
||
app.whenReady().then(() => { | ||
ipcMain.on('execute', async (_, zipUrl, buffer, executionCommand) => { | ||
const tempDir = path.join(os.tmpdir(), 'exercode'); | ||
fs.rmSync(tempDir, { force: true, recursive: true }); | ||
|
||
const uint8Array = new Uint8Array(buffer); | ||
const files = fflate.unzipSync(uint8Array); | ||
for (const [filename, fileData] of Object.entries(files)) { | ||
const filePath = path.join(tempDir, filename); | ||
fs.mkdirSync(path.dirname(filePath), { recursive: true }); | ||
fs.writeFileSync(filePath, fileData); | ||
} | ||
|
||
const dirName = new URL(zipUrl).pathname.split('/').at(-1); | ||
const dirPath = path.join(tempDir, dirName); | ||
|
||
let command; | ||
let args; | ||
executionCommand = executionCommand.split(' && ').slice(2).join(' && '); | ||
switch (os.platform()) { | ||
case 'win32': // Windows | ||
command = 'start'; | ||
args = ['cmd.exe', '/K', `cd ${dirPath} && ${executionCommand}`]; | ||
break; | ||
case 'darwin': // macOS | ||
command = 'osascript'; | ||
args = ['-e', `tell app "Terminal" to do script "cd ${dirPath} && ${executionCommand.replaceAll('"', '\'')}"`, '-e', 'tell app "Terminal" to activate']; | ||
break; | ||
default: // Linux | ||
command = 'gnome-terminal'; | ||
args = ['--', 'bash', '-c', `cd ${dirPath} && ${executionCommand}`]; | ||
break; | ||
} | ||
child_process.spawn(command, args, { shell: false }); | ||
}); | ||
createWindow(); | ||
}); | ||
|
||
app.on('window-all-closed', () => { | ||
app.quit(); | ||
}); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
const { contextBridge, ipcRenderer } = require('electron'); | ||
|
||
contextBridge.exposeInMainWorld('electron', { | ||
execute: (url) => ipcRenderer.send('execute', url), | ||
execute: (zipUrl, buffer, executionCommand) => ipcRenderer.send('execute', zipUrl, buffer, executionCommand), | ||
}); |