Improve WorkerWaiter and OutputWaiter.
- Will run and display outputs in the output area as they're baked - Creates output tabs - Can change output tabs (only the first 4 at the moment)
This commit is contained in:
parent
2cb33bfec4
commit
e0c9aba25e
@ -90,7 +90,7 @@ class InputWaiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a loaderworker using inputNum
|
* Removes a loaderworker
|
||||||
*
|
*
|
||||||
* @param {Object} workerObj
|
* @param {Object} workerObj
|
||||||
*/
|
*/
|
||||||
@ -203,14 +203,6 @@ class InputWaiter {
|
|||||||
this.inputs.splice(i, 1);
|
this.inputs.splice(i, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (this.inputs.length === 0) {
|
|
||||||
// this.inputs.push({
|
|
||||||
// inputNum: inputNum,
|
|
||||||
// data: "",
|
|
||||||
// status: "loaded",
|
|
||||||
// progress: 100
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,15 +319,12 @@ class InputWaiter {
|
|||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (this.inputs[index].inputNum === inputNum) {
|
|
||||||
if (typeof this.inputs[index].data === "string") {
|
if (typeof this.inputs[index].data === "string") {
|
||||||
return this.inputs[index].data;
|
return this.inputs[index].data;
|
||||||
} else {
|
} else {
|
||||||
return this.inputs[index].data.fileBuffer;
|
return this.inputs[index].data.fileBuffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the index of the input in the inputs list
|
* Gets the index of the input in the inputs list
|
||||||
@ -359,7 +348,8 @@ class InputWaiter {
|
|||||||
const value = (textArea.value !== undefined) ? textArea.value : "";
|
const value = (textArea.value !== undefined) ? textArea.value : "";
|
||||||
const inputNum = this.getActiveTab();
|
const inputNum = this.getActiveTab();
|
||||||
|
|
||||||
if (this.getInput(inputNum) === null || typeof this.getInput(inputNum) === "string") {
|
const input = this.getInput(inputNum);
|
||||||
|
if (input === null || typeof input === "string") {
|
||||||
this.updateInputValue(inputNum, value);
|
this.updateInputValue(inputNum, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,6 +764,8 @@ class InputWaiter {
|
|||||||
progress: 100
|
progress: 100
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.manager.output.addOutput(inputNum, changeTab);
|
||||||
|
|
||||||
const tabsWrapper = document.getElementById("input-tabs");
|
const tabsWrapper = document.getElementById("input-tabs");
|
||||||
const numTabs = tabsWrapper.children.length;
|
const numTabs = tabsWrapper.children.length;
|
||||||
|
|
||||||
@ -831,6 +823,8 @@ class InputWaiter {
|
|||||||
}
|
}
|
||||||
this.refreshTabs(activeTab);
|
this.refreshTabs(activeTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.manager.output.removeTab(inputNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -883,6 +877,8 @@ class InputWaiter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.changeTab(activeTab);
|
this.changeTab(activeTab);
|
||||||
|
|
||||||
|
// MAKE THE OUTPUT REFRESH TOO
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -966,14 +962,8 @@ class InputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
changeTab(inputNum) {
|
changeTab(inputNum) {
|
||||||
const inputIdx = this.getInputIndex(inputNum);
|
const currentNum = this.getActiveTab();
|
||||||
let currentIdx = -1;
|
if (this.getInputIndex(inputNum) === -1) return;
|
||||||
try {
|
|
||||||
currentIdx = this.getActiveTab();
|
|
||||||
} catch (err) {}
|
|
||||||
if (inputIdx === -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const tabsWrapper = document.getElementById("input-tabs");
|
const tabsWrapper = document.getElementById("input-tabs");
|
||||||
const tabs = tabsWrapper.children;
|
const tabs = tabsWrapper.children;
|
||||||
@ -990,7 +980,7 @@ class InputWaiter {
|
|||||||
if (!found) {
|
if (!found) {
|
||||||
// Shift the tabs here
|
// Shift the tabs here
|
||||||
let direction = "right";
|
let direction = "right";
|
||||||
if (currentIdx > inputIdx) {
|
if (currentNum > inputNum) {
|
||||||
direction = "left";
|
direction = "left";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1122,9 +1112,8 @@ class InputWaiter {
|
|||||||
const activeTab = activeTabs.item(0);
|
const activeTab = activeTabs.item(0);
|
||||||
const tabNum = activeTab.getAttribute("inputNum");
|
const tabNum = activeTab.getAttribute("inputNum");
|
||||||
return parseInt(tabNum, 10);
|
return parseInt(tabNum, 10);
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,7 +84,7 @@ class Manager {
|
|||||||
setup() {
|
setup() {
|
||||||
this.input.addTab();
|
this.input.addTab();
|
||||||
this.input.setupLoaderWorker();
|
this.input.setupLoaderWorker();
|
||||||
this.worker.setupChefWorkers();
|
this.worker.setupChefWorker();
|
||||||
this.recipe.initialiseOperationDragNDrop();
|
this.recipe.initialiseOperationDragNDrop();
|
||||||
this.controls.initComponents();
|
this.controls.initComponents();
|
||||||
this.controls.autoBakeChange();
|
this.controls.autoBakeChange();
|
||||||
@ -165,24 +165,24 @@ class Manager {
|
|||||||
this.addDynamicListener("#input-tabs li .input-tab-content", "click", this.input.changeTabClick, this.input);
|
this.addDynamicListener("#input-tabs li .input-tab-content", "click", this.input.changeTabClick, this.input);
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
|
// document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
|
||||||
document.getElementById("copy-output").addEventListener("click", this.output.copyClick.bind(this.output));
|
// document.getElementById("copy-output").addEventListener("click", this.output.copyClick.bind(this.output));
|
||||||
document.getElementById("switch").addEventListener("click", this.output.switchClick.bind(this.output));
|
// document.getElementById("switch").addEventListener("click", this.output.switchClick.bind(this.output));
|
||||||
document.getElementById("undo-switch").addEventListener("click", this.output.undoSwitchClick.bind(this.output));
|
// document.getElementById("undo-switch").addEventListener("click", this.output.undoSwitchClick.bind(this.output));
|
||||||
document.getElementById("maximise-output").addEventListener("click", this.output.maximiseOutputClick.bind(this.output));
|
// document.getElementById("maximise-output").addEventListener("click", this.output.maximiseOutputClick.bind(this.output));
|
||||||
document.getElementById("magic").addEventListener("click", this.output.magicClick.bind(this.output));
|
// document.getElementById("magic").addEventListener("click", this.output.magicClick.bind(this.output));
|
||||||
document.getElementById("output-text").addEventListener("scroll", this.highlighter.outputScroll.bind(this.highlighter));
|
// document.getElementById("output-text").addEventListener("scroll", this.highlighter.outputScroll.bind(this.highlighter));
|
||||||
document.getElementById("output-text").addEventListener("mouseup", this.highlighter.outputMouseup.bind(this.highlighter));
|
// document.getElementById("output-text").addEventListener("mouseup", this.highlighter.outputMouseup.bind(this.highlighter));
|
||||||
document.getElementById("output-text").addEventListener("mousemove", this.highlighter.outputMousemove.bind(this.highlighter));
|
// document.getElementById("output-text").addEventListener("mousemove", this.highlighter.outputMousemove.bind(this.highlighter));
|
||||||
document.getElementById("output-html").addEventListener("mouseup", this.highlighter.outputHtmlMouseup.bind(this.highlighter));
|
// document.getElementById("output-html").addEventListener("mouseup", this.highlighter.outputHtmlMouseup.bind(this.highlighter));
|
||||||
document.getElementById("output-html").addEventListener("mousemove", this.highlighter.outputHtmlMousemove.bind(this.highlighter));
|
// document.getElementById("output-html").addEventListener("mousemove", this.highlighter.outputHtmlMousemove.bind(this.highlighter));
|
||||||
this.addMultiEventListener("#output-text", "mousedown dblclick select", this.highlighter.outputMousedown, this.highlighter);
|
// this.addMultiEventListener("#output-text", "mousedown dblclick select", this.highlighter.outputMousedown, this.highlighter);
|
||||||
this.addMultiEventListener("#output-html", "mousedown dblclick select", this.highlighter.outputHtmlMousedown, this.highlighter);
|
// this.addMultiEventListener("#output-html", "mousedown dblclick select", this.highlighter.outputHtmlMousedown, this.highlighter);
|
||||||
this.addDynamicListener("#output-file-download", "click", this.output.downloadFile, this.output);
|
// this.addDynamicListener("#output-file-download", "click", this.output.downloadFile, this.output);
|
||||||
this.addDynamicListener("#output-file-slice i", "click", this.output.displayFileSlice, this.output);
|
// this.addDynamicListener("#output-file-slice i", "click", this.output.displayFileSlice, this.output);
|
||||||
document.getElementById("show-file-overlay").addEventListener("click", this.output.showFileOverlayClick.bind(this.output));
|
// document.getElementById("show-file-overlay").addEventListener("click", this.output.showFileOverlayClick.bind(this.output));
|
||||||
this.addDynamicListener(".extract-file,.extract-file i", "click", this.output.extractFileClick, this.output);
|
// this.addDynamicListener(".extract-file,.extract-file i", "click", this.output.extractFileClick, this.output);
|
||||||
// this.addDynamicListener("#output-tabs ul li .output-tab-content", "click", this.output.changeTabClick, this.output);
|
this.addDynamicListener("#output-tabs-wrapper #output-tabs li .output-tab-content", "click", this.output.changeTabClick, this.output);
|
||||||
|
|
||||||
// Options
|
// Options
|
||||||
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));
|
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -8,35 +8,60 @@
|
|||||||
import ChefWorker from "worker-loader?inline&fallback=false!../core/ChefWorker";
|
import ChefWorker from "worker-loader?inline&fallback=false!../core/ChefWorker";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Waiter to handle conversations with the ChefWorker.
|
* Waiter to handle conversations with the ChefWorker
|
||||||
*/
|
*/
|
||||||
class WorkerWaiter {
|
class WorkerWaiter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WorkerWaiter constructor.
|
* WorkerWaiter constructor
|
||||||
*
|
*
|
||||||
* @param {App} app - The main view object for CyberChef
|
* @param {App} app - The main view object for CyberChef
|
||||||
* @param {Manager} manager - The CyberChef event manager.
|
* @param {Manager} manager - The CyberChef event manager
|
||||||
*/
|
*/
|
||||||
constructor(app, manager) {
|
constructor(app, manager) {
|
||||||
this.app = app;
|
this.app = app;
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
|
||||||
this.callbacks = {};
|
|
||||||
this.callbackID = 0;
|
|
||||||
this.pendingInputs = [];
|
|
||||||
this.runningWorkers = 0;
|
|
||||||
this.chefWorkers = [];
|
this.chefWorkers = [];
|
||||||
this.outputs = [];
|
this.maxWorkers = navigator.hardwareConcurrency || 4;
|
||||||
|
this.inputs = [];
|
||||||
|
this.totalOutputs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up a pool of ChefWorkers to be used for baking
|
* Terminates any existing ChefWorkers and sets up a new worker
|
||||||
*/
|
*/
|
||||||
setupChefWorkers() {
|
setupChefWorker() {
|
||||||
const threads = navigator.hardwareConcurrency || 4; // Default to 4
|
for (let i = 0; i < this.chefWorkers.length; i++) {
|
||||||
|
const worker = this.chefWorkers.pop();
|
||||||
|
worker.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < threads; i++) {
|
this.addChefWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new ChefWorker
|
||||||
|
*
|
||||||
|
* @returns {number} The index of the created worker
|
||||||
|
*/
|
||||||
|
addChefWorker() {
|
||||||
|
// First find if there are any inactive workers, as this will be
|
||||||
|
// more efficient than creating a new one
|
||||||
|
for (let i = 0; i < this.chefWorkers.length; i++) {
|
||||||
|
if (!this.chefWorkers[i].active) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.chefWorkers.length === this.maxWorkers) {
|
||||||
|
// Can't create any more workers
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("Adding new ChefWorker");
|
||||||
|
|
||||||
|
// Create a new ChefWorker and send it the docURL
|
||||||
const newWorker = new ChefWorker();
|
const newWorker = new ChefWorker();
|
||||||
newWorker.addEventListener("message", this.handleChefMessage.bind(this));
|
newWorker.addEventListener("message", this.handleChefMessage.bind(this));
|
||||||
let docURL = document.location.href.split(/[#?]/)[0];
|
let docURL = document.location.href.split(/[#?]/)[0];
|
||||||
@ -45,48 +70,108 @@ class WorkerWaiter {
|
|||||||
docURL = docURL.substring(0, index);
|
docURL = docURL.substring(0, index);
|
||||||
}
|
}
|
||||||
newWorker.postMessage({"action": "docURL", "data": docURL});
|
newWorker.postMessage({"action": "docURL", "data": docURL});
|
||||||
newWorker.postMessage({"action": "inputNum", "data": 0});
|
|
||||||
|
|
||||||
this.chefWorkers.push({
|
// Store the worker, whether or not it's active, and the inputNum as an object
|
||||||
|
const newWorkerObj = {
|
||||||
worker: newWorker,
|
worker: newWorker,
|
||||||
inputNum: 0
|
active: false,
|
||||||
});
|
inputNum: this.manager.input.getActiveTab()
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
|
this.chefWorkers.push(newWorkerObj);
|
||||||
|
return this.chefWorkers.indexOf(newWorkerObj);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for messages sent back by the ChefWorker.
|
* Removes a ChefWorker
|
||||||
|
*
|
||||||
|
* @param {Object} workerObj
|
||||||
|
*/
|
||||||
|
removeChefWorker(workerObj) {
|
||||||
|
const index = this.chefWorkers.indexOf(workerObj);
|
||||||
|
if (index === -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.chefWorkers[index].worker.terminate();
|
||||||
|
this.chefWorkers.splice(index, 1);
|
||||||
|
|
||||||
|
// There should always be a ChefWorker loaded
|
||||||
|
if (this.chefWorkers.length === 0) {
|
||||||
|
this.addChefWorker();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds and returns the object for the ChefWorker of a given inputNum
|
||||||
|
*
|
||||||
|
* @param {number} inputNum
|
||||||
|
*/
|
||||||
|
getChefWorker(inputNum) {
|
||||||
|
for (let i = 0; i < this.chefWorkers.length; i++) {
|
||||||
|
if (this.chefWorkers[i].inputNum === inputNum) {
|
||||||
|
return this.chefWorkers[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for messages sent back by the ChefWorkers
|
||||||
*
|
*
|
||||||
* @param {MessageEvent} e
|
* @param {MessageEvent} e
|
||||||
*/
|
*/
|
||||||
handleChefMessage(e) {
|
handleChefMessage(e) {
|
||||||
const r = e.data;
|
const r = e.data;
|
||||||
log.debug("Receiving '" + r.action + "' from ChefWorker");
|
let inputNum = 0;
|
||||||
|
log.debug(`Receiving ${r.action} from ChefWorker.`);
|
||||||
|
|
||||||
|
if (r.data.hasOwnProperty("inputNum")) {
|
||||||
|
inputNum = r.data.inputNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentWorker = this.getChefWorker(inputNum);
|
||||||
|
|
||||||
switch (r.action) {
|
switch (r.action) {
|
||||||
case "bakeComplete":
|
case "bakeComplete":
|
||||||
this.runningWorkers -= 1;
|
log.debug(`Bake ${inputNum} complete.`);
|
||||||
this.outputs.push({
|
this.updateOutput(r.data, r.data.inputNum);
|
||||||
data: r.data,
|
|
||||||
inputNum: r.data.inputNum
|
if (this.inputs.length > 0) {
|
||||||
|
const nextInput = this.inputs.pop();
|
||||||
|
log.debug(`Baking input ${nextInput.inputNum}.`);
|
||||||
|
this.manager.output.updateOutputStatus("baking", nextInput.inputNum);
|
||||||
|
this.manager.output.updateOutputMessage("Baking...", nextInput.inputNum);
|
||||||
|
currentWorker.inputNum = nextInput.inputNum;
|
||||||
|
currentWorker.active = true;
|
||||||
|
currentWorker.worker.postMessage({
|
||||||
|
action: "bake",
|
||||||
|
data: {
|
||||||
|
input: nextInput.input,
|
||||||
|
recipeConfig: nextInput.recipeConfig,
|
||||||
|
options: nextInput.options,
|
||||||
|
progress: nextInput.progress,
|
||||||
|
step: nextInput.step,
|
||||||
|
inputNum: nextInput.inputNum
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (this.pendingInputs.length > 0) {
|
this.displayProgress();
|
||||||
log.debug(`Bake ${r.data.inputNum} complete. Baking next input`);
|
} else {
|
||||||
this.bakeNextInput(r.data.inputNum);
|
// The ChefWorker is no longer needed
|
||||||
} else if (this.runningWorkers <= 0) {
|
log.debug("No more inputs to bake. Closing ChefWorker.");
|
||||||
this.runningWorkers = 0;
|
this.removeChefWorker(currentWorker);
|
||||||
this.recipeConfig = undefined;
|
|
||||||
this.options = undefined;
|
this.displayProgress();
|
||||||
this.progress = undefined;
|
|
||||||
this.step = undefined;
|
const progress = this.getBakeProgress();
|
||||||
|
if (progress.total === progress.baked) {
|
||||||
this.bakingComplete();
|
this.bakingComplete();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "bakeError":
|
case "BakeError":
|
||||||
this.runningWorkers -= 1;
|
this.manager.output.updateOutputError(r.data, inputNum);
|
||||||
this.app.handleError(r.data);
|
// do more here
|
||||||
this.setBakingStatus(false);
|
|
||||||
break;
|
break;
|
||||||
case "dishReturned":
|
case "dishReturned":
|
||||||
this.callbacks[r.data.id](r.data);
|
this.callbacks[r.data.id](r.data);
|
||||||
@ -95,17 +180,20 @@ class WorkerWaiter {
|
|||||||
break;
|
break;
|
||||||
case "workerLoaded":
|
case "workerLoaded":
|
||||||
this.app.workerLoaded = true;
|
this.app.workerLoaded = true;
|
||||||
log.debug("ChefWorker loaded");
|
log.debug("ChefWorker loaded.");
|
||||||
this.app.loaded();
|
this.app.loaded();
|
||||||
break;
|
break;
|
||||||
case "statusMessage":
|
case "statusMessage":
|
||||||
this.manager.output.setStatusMsg(r.data);
|
// Status message should be done per output
|
||||||
|
// log.error(r);
|
||||||
|
this.manager.output.updateOutputMessage(r.data.message, r.data.inputNum);
|
||||||
break;
|
break;
|
||||||
case "optionUpdate":
|
case "optionUpdate":
|
||||||
log.debug(`Setting ${r.data.option} to ${r.data.value}`);
|
log.debug(`Setting ${r.data.option} to ${r.data.value}`);
|
||||||
this.app.options[r.data.option] = r.data.value;
|
this.app.options[r.data.option] = r.data.value;
|
||||||
break;
|
break;
|
||||||
case "setRegisters":
|
case "setRegisters":
|
||||||
|
// Should this update with the tabs?
|
||||||
this.manager.recipe.setRegisters(r.data.opIndex, r.data.numPrevRegisters, r.data.registers);
|
this.manager.recipe.setRegisters(r.data.opIndex, r.data.numPrevRegisters, r.data.registers);
|
||||||
break;
|
break;
|
||||||
case "highlightsCalculated":
|
case "highlightsCalculated":
|
||||||
@ -117,78 +205,96 @@ class WorkerWaiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the value of an output
|
||||||
|
*
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {number} inputNum
|
||||||
|
*/
|
||||||
|
updateOutput(data, inputNum) {
|
||||||
|
|
||||||
|
this.manager.output.updateOutputValue(data, inputNum);
|
||||||
|
this.manager.output.updateOutputStatus("baked", inputNum);
|
||||||
|
|
||||||
|
this.manager.recipe.updateBreakpointIndicator(this.app.progress);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the UI to show if baking is in process or not.
|
* Updates the UI to show if baking is in process or not.
|
||||||
*
|
*
|
||||||
* @param {bakingStatus}
|
* @param {boolean} bakingStatus
|
||||||
*/
|
*/
|
||||||
setBakingStatus(bakingStatus) {
|
setBakingStatus(bakingStatus) {
|
||||||
this.app.baking = bakingStatus;
|
this.app.baking = bakingStatus;
|
||||||
|
this.manager.controls.toggleBakeButtonFunction(bakingStatus);
|
||||||
this.manager.output.toggleLoader(bakingStatus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the progress of the ChefWorkers
|
||||||
|
*/
|
||||||
|
getBakeProgress() {
|
||||||
|
const pendingInputs = this.inputs.length;
|
||||||
|
let bakingInputs = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.chefWorkers.length; i++) {
|
||||||
|
if (this.chefWorkers[i].active) {
|
||||||
|
bakingInputs++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const total = this.totalOutputs;
|
||||||
|
const bakedInputs = total - pendingInputs - bakingInputs;
|
||||||
|
|
||||||
|
return {
|
||||||
|
total: total,
|
||||||
|
pending: pendingInputs,
|
||||||
|
baking: bakingInputs,
|
||||||
|
baked: bakedInputs
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calcels the current bake by terminating and removing all ChefWorkers,
|
* Cancels the current bake by terminating and removing all ChefWorkers
|
||||||
* and creating a new one
|
|
||||||
*/
|
*/
|
||||||
cancelBake() {
|
cancelBake() {
|
||||||
for (let i = this.chefWorkers.length - 1; i >= 0; i--) {
|
for (let i = this.chefWorkers.length - 1; i >= 0; i--) {
|
||||||
this.chefWorkers[i].worker.terminate();
|
this.removeChefWorker(this.chefWorkers[i]);
|
||||||
this.chefWorkers.pop();
|
|
||||||
}
|
}
|
||||||
this.setupChefWorkers();
|
|
||||||
this.setBakingStatus(false);
|
this.setBakingStatus(false);
|
||||||
|
this.inputs = [];
|
||||||
|
this.totalOutputs = 0;
|
||||||
this.manager.controls.showStaleIndicator();
|
this.manager.controls.showStaleIndicator();
|
||||||
|
this.displayProgress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for completed bakes
|
* Handler for completed bakes
|
||||||
*/
|
*/
|
||||||
bakingComplete() {
|
bakingComplete() {
|
||||||
this.setBakingStatus(false);
|
this.setBakingStatus(false);
|
||||||
|
|
||||||
if (this.pendingInputs.length !== 0) return;
|
// look into changing this to something better
|
||||||
|
// for (let i = 0; i < this.outputs.length; i++) {
|
||||||
|
// if (this.outputs[i].data.error) {
|
||||||
|
// this.app.handleError(this.outputs[i].error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
// What are these for?
|
||||||
if (this.outputs[i].error) {
|
// Should be a value for each input, not just one
|
||||||
this.app.handleError(this.outputs[i].error);
|
// this.app.progress = this.outputs[0].data.progress;
|
||||||
}
|
// this.app.dish = this.outputs[0].data.dish;
|
||||||
}
|
|
||||||
|
|
||||||
this.app.progress = this.outputs[0].data.progress;
|
|
||||||
this.app.dish = this.outputs[0].data.dish;
|
|
||||||
this.manager.recipe.updateBreakpointIndicator(this.app.progress);
|
this.manager.recipe.updateBreakpointIndicator(this.app.progress);
|
||||||
this.manager.output.multiSet(this.outputs);
|
// Don't need to update the output here as updateOutput() will take care of that
|
||||||
|
document.getElementById("bake").style.background = "";
|
||||||
|
this.totalOutputs = 0; // Reset for next time
|
||||||
log.debug("--- Bake complete ---");
|
log.debug("--- Bake complete ---");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for completed bakes
|
* Bakes the current input using the current recipe.
|
||||||
*
|
* Either sends the input and recipe to a ChefWorker,
|
||||||
* @param {Object} response
|
* or, if there's already the max running, adds it to inputs
|
||||||
*/
|
|
||||||
bakingCompleteOld(response) {
|
|
||||||
this.setBakingStatus(false);
|
|
||||||
|
|
||||||
if (!response) return;
|
|
||||||
|
|
||||||
if (response.error) {
|
|
||||||
this.app.handleError(response.error);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.app.progress = response.progress;
|
|
||||||
this.app.dish = response.dish;
|
|
||||||
this.manager.recipe.updateBreakpointIndicator(response.progress);
|
|
||||||
this.manager.output.set(response.result, response.type, response.duration);
|
|
||||||
log.debug("--- Bake complete ---");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asks the ChefWorker to bake the current input using the current recipe.
|
|
||||||
*
|
*
|
||||||
* @param {string | Array} input
|
* @param {string | Array} input
|
||||||
* @param {Object[]} recipeConfig
|
* @param {Object[]} recipeConfig
|
||||||
@ -199,67 +305,55 @@ class WorkerWaiter {
|
|||||||
bake(input, recipeConfig, options, progress, step) {
|
bake(input, recipeConfig, options, progress, step) {
|
||||||
this.setBakingStatus(true);
|
this.setBakingStatus(true);
|
||||||
|
|
||||||
this.recipeConfig = recipeConfig;
|
|
||||||
this.options = options;
|
|
||||||
this.progress = progress;
|
|
||||||
this.step = step;
|
|
||||||
this.outputs = [];
|
|
||||||
|
|
||||||
if (typeof input === "string") {
|
if (typeof input === "string") {
|
||||||
input = [{
|
input = [{
|
||||||
input: input,
|
input: input,
|
||||||
inputNum: 0
|
inputNum: this.manager.input.getActiveTab()
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialInputs = input.slice(0, this.chefWorkers.length);
|
for (let i = 0; i < input.length; i++) {
|
||||||
this.pendingInputs = input.slice(this.chefWorkers.length, input.length);
|
this.totalOutputs++;
|
||||||
this.runningWorkers = 0;
|
this.manager.output.updateOutputStatus("pending", input[i].inputNum);
|
||||||
|
this.manager.output.updateOutputMessage(`Input ${input[i].inputNum} has not been baked yet.`, input[i].inputNum);
|
||||||
for (let i = 0; i < initialInputs.length; i++) {
|
// If an input exists for the current inputNum, remove it
|
||||||
this.runningWorkers += 1;
|
for (let x = 0; x < this.inputs.length; x++) {
|
||||||
this.chefWorkers[i].inputNum = initialInputs[i].inputNum;
|
if (this.inputs[x].inputNum === input[i].inputNum) {
|
||||||
this.chefWorkers[i].worker.postMessage({
|
this.inputs.splice(x, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const workerId = this.addChefWorker();
|
||||||
|
if (workerId !== -1) {
|
||||||
|
// Send the input to the ChefWorker
|
||||||
|
this.manager.output.updateOutputStatus("baking", input[i].inputNum);
|
||||||
|
this.manager.output.updateOutputMessage("Baking...", input[i].inputNum);
|
||||||
|
this.chefWorkers[workerId].active = true;
|
||||||
|
this.chefWorkers[workerId].inputNum = input[i].inputNum;
|
||||||
|
this.chefWorkers[workerId].worker.postMessage({
|
||||||
action: "bake",
|
action: "bake",
|
||||||
data: {
|
data: {
|
||||||
input: initialInputs[i].input,
|
input: input[i].input,
|
||||||
recipeConfig: recipeConfig,
|
recipeConfig: recipeConfig,
|
||||||
options: options,
|
options: options,
|
||||||
progress: progress,
|
progress: progress,
|
||||||
step: step,
|
step: step,
|
||||||
inputNum: initialInputs[i].inputNum
|
inputNum: input[i].inputNum
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
} else {
|
||||||
}
|
// Add the input to inputs so it can be processed when ready
|
||||||
|
this.inputs.push({
|
||||||
|
input: input[i].input,
|
||||||
/**
|
recipeConfig: recipeConfig,
|
||||||
*
|
options: options,
|
||||||
* @param inputNum
|
progress: progress,
|
||||||
*/
|
step: step,
|
||||||
bakeNextInput(inputNum) {
|
inputNum: input[i].inputNum
|
||||||
this.runningWorkers += 1;
|
|
||||||
const nextInput = this.pendingInputs.pop();
|
|
||||||
for (let i = 0; i < this.chefWorkers.length; i++) {
|
|
||||||
if (this.chefWorkers[i].inputNum === inputNum) {
|
|
||||||
this.chefWorkers[i].inputNum = nextInput.inputNum;
|
|
||||||
this.chefWorkers[i].worker.postMessage({
|
|
||||||
action: "bake",
|
|
||||||
data: {
|
|
||||||
input: nextInput.input,
|
|
||||||
recipeConfig: this.recipeConfig,
|
|
||||||
options: this.options,
|
|
||||||
progress: this.progress,
|
|
||||||
step: this.step,
|
|
||||||
inputNum: nextInput.inputNum
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant
|
* Asks the ChefWorker to run a silent bake, forcing the browser to load and cache all the relevant
|
||||||
* JavaScript code needed to do a real bake.
|
* JavaScript code needed to do a real bake.
|
||||||
@ -267,7 +361,11 @@ class WorkerWaiter {
|
|||||||
* @param {Object[]} [recipeConfig]
|
* @param {Object[]} [recipeConfig]
|
||||||
*/
|
*/
|
||||||
silentBake(recipeConfig) {
|
silentBake(recipeConfig) {
|
||||||
this.chefWorkers[0].worker.postMessage({
|
// If there aren't any active ChefWorkers, addChefWorker will
|
||||||
|
// return an inactive worker instead of creating a new one
|
||||||
|
const workerId = this.addChefWorker();
|
||||||
|
if (workerId === -1) return;
|
||||||
|
this.chefWorkers[workerId].worker.postMessage({
|
||||||
action: "silentBake",
|
action: "silentBake",
|
||||||
data: {
|
data: {
|
||||||
recipeConfig: recipeConfig
|
recipeConfig: recipeConfig
|
||||||
@ -275,28 +373,6 @@ class WorkerWaiter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Asks the ChefWorker to calculate highlight offsets if possible.
|
|
||||||
*
|
|
||||||
* @param {Object[]} recipeConfig
|
|
||||||
* @param {string} direction
|
|
||||||
* @param {Object} pos - The position object for the highlight.
|
|
||||||
* @param {number} pos.start - The start offset.
|
|
||||||
* @param {number} pos.end - The end offset.
|
|
||||||
*/
|
|
||||||
highlight(recipeConfig, direction, pos) {
|
|
||||||
this.chefWorkers[0].postMessage({
|
|
||||||
action: "highlight",
|
|
||||||
data: {
|
|
||||||
recipeConfig: recipeConfig,
|
|
||||||
direction: direction,
|
|
||||||
pos: pos
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Asks the ChefWorker to return the dish as the specified type
|
* Asks the ChefWorker to return the dish as the specified type
|
||||||
*
|
*
|
||||||
@ -306,8 +382,11 @@ class WorkerWaiter {
|
|||||||
*/
|
*/
|
||||||
getDishAs(dish, type, callback) {
|
getDishAs(dish, type, callback) {
|
||||||
const id = this.callbackID++;
|
const id = this.callbackID++;
|
||||||
|
const workerId = this.addChefWorker();
|
||||||
|
if (workerId === -1) return;
|
||||||
|
|
||||||
this.callbacks[id] = callback;
|
this.callbacks[id] = callback;
|
||||||
this.chefWorkers[0].worker.postMessage({
|
this.chefWorkers[workerId].worker.postMessage({
|
||||||
action: "getDishAs",
|
action: "getDishAs",
|
||||||
data: {
|
data: {
|
||||||
dish: dish,
|
dish: dish,
|
||||||
@ -317,15 +396,12 @@ class WorkerWaiter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the console log level in the worker.
|
* Sets the console log level in the workers.
|
||||||
*
|
*
|
||||||
* @param {string} level
|
* @param {string} level
|
||||||
*/
|
*/
|
||||||
setLogLevel(level) {
|
setLogLevel(level) {
|
||||||
if (!this.chefWorkers || !this.chefWorkers.length > 0) return;
|
|
||||||
|
|
||||||
for (let i = 0; i < this.chefWorkers.length; i++) {
|
for (let i = 0; i < this.chefWorkers.length; i++) {
|
||||||
this.chefWorkers[i].worker.postMessage({
|
this.chefWorkers[i].worker.postMessage({
|
||||||
action: "setLogLevel",
|
action: "setLogLevel",
|
||||||
@ -333,7 +409,46 @@ class WorkerWaiter {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the bake progress in the output bar and bake button
|
||||||
|
*/
|
||||||
|
displayProgress() {
|
||||||
|
const progress = this.getBakeProgress();
|
||||||
|
const percentComplete = ((progress.pending + progress.baking) / progress.total) * 100;
|
||||||
|
const bakeButton = document.getElementById("bake");
|
||||||
|
if (this.app.baking) {
|
||||||
|
if (percentComplete < 100) {
|
||||||
|
document.getElementById("bake").style.background = `linear-gradient(to left, #fea79a ${percentComplete}%, #f44336 ${percentComplete}%)`;
|
||||||
|
} else {
|
||||||
|
bakeButton.style.background = "";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not baking
|
||||||
|
bakeButton.style.background = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const bakeInfo = document.getElementById("bake-info");
|
||||||
|
let width = progress.total.toString().length;
|
||||||
|
width = width < 2 ? 2 : width;
|
||||||
|
|
||||||
|
const totalStr = progress.total.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
const bakedStr = progress.baked.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
const pendingStr = progress.pending.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
const bakingStr = progress.baking.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
|
||||||
|
let msg = "Total: " + totalStr;
|
||||||
|
msg += "<br>Baked: " + bakedStr;
|
||||||
|
|
||||||
|
if (progress.pending > 0) {
|
||||||
|
msg += "<br>Pending: " + pendingStr;
|
||||||
|
} else if (progress.baking > 0) {
|
||||||
|
msg += "<br>Baking: " + bakingStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bakeInfo.innerHTML = msg;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default WorkerWaiter;
|
export default WorkerWaiter;
|
||||||
|
@ -45,8 +45,8 @@
|
|||||||
-moz-padding-start: 1px; /* Fixes bug in Firefox */
|
-moz-padding-start: 1px; /* Fixes bug in Firefox */
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-tabs ul,
|
#input-tabs-wrapper #input-tabs,
|
||||||
#output-tabs ul {
|
#output-tabs-wrapper #output-tabs {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
background-color: var(--title-background-colour);
|
background-color: var(--title-background-colour);
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -59,8 +59,8 @@
|
|||||||
height: var(--tab-height);
|
height: var(--tab-height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-tabs ul li,
|
#input-tabs li,
|
||||||
#output-tabs ul li {
|
#output-tabs li {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -73,8 +73,8 @@
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
#input-tabs ul li:hover,
|
#input-tabs li:hover,
|
||||||
#output-tabs ul li:hover {
|
#output-tabs li:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: var(--primary-background-colour);
|
background-color: var(--primary-background-colour);
|
||||||
}
|
}
|
||||||
@ -85,6 +85,11 @@
|
|||||||
background-color: var(--primary-background-colour);
|
background-color: var(--primary-background-colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tab-buttons {
|
||||||
|
transition: 1s all ease;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.input-tab-content,
|
.input-tab-content,
|
||||||
.output-tab-content {
|
.output-tab-content {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -142,10 +147,10 @@
|
|||||||
|
|
||||||
#output-loader {
|
#output-loader {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: calc(100% - var(--title-height));
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: var(--primary-background-colour);
|
background-color: var(--primary-background-colour);
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user