Move input logic into a new worker (InputWorker)
Change OutputWaiter to use dict of outputs instead of list LoaderWorker communicates with InputWorker using a messagechannel
This commit is contained in:
parent
6d8daac5ca
commit
406cbb0f41
@ -120,9 +120,10 @@ class App {
|
|||||||
*
|
*
|
||||||
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
|
||||||
* whole recipe.
|
* whole recipe.
|
||||||
|
* @param input - The inputs to bake
|
||||||
*/
|
*/
|
||||||
bake(step=false) {
|
bake(step=false, input) {
|
||||||
if (this.baking) return;
|
// if (this.baking) return;
|
||||||
|
|
||||||
// Reset attemptHighlight flag
|
// Reset attemptHighlight flag
|
||||||
this.options.attemptHighlight = true;
|
this.options.attemptHighlight = true;
|
||||||
@ -131,7 +132,7 @@ class App {
|
|||||||
this.manager.recipe.updateBreakpointIndicator(false);
|
this.manager.recipe.updateBreakpointIndicator(false);
|
||||||
|
|
||||||
this.manager.worker.bake(
|
this.manager.worker.bake(
|
||||||
this.getAllInput(), // The user's input
|
input, // The user's input
|
||||||
this.getRecipeConfig(), // The configuration of the recipe
|
this.getRecipeConfig(), // The configuration of the recipe
|
||||||
this.options, // Options set by the user
|
this.options, // Options set by the user
|
||||||
this.progress, // The current position in the recipe
|
this.progress, // The current position in the recipe
|
||||||
@ -151,7 +152,10 @@ class App {
|
|||||||
|
|
||||||
if (this.autoBake_ && !this.baking) {
|
if (this.autoBake_ && !this.baking) {
|
||||||
log.debug("Auto-baking");
|
log.debug("Auto-baking");
|
||||||
this.bake();
|
this.manager.input.inputWorker.postMessage({
|
||||||
|
action: "autobake",
|
||||||
|
data: this.manager.input.getActiveTab()
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
this.manager.controls.showStaleIndicator();
|
this.manager.controls.showStaleIndicator();
|
||||||
}
|
}
|
||||||
@ -177,23 +181,13 @@ class App {
|
|||||||
this.manager.worker.silentBake(recipeConfig);
|
this.manager.worker.silentBake(recipeConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the user's input data.
|
|
||||||
*
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getInput() {
|
|
||||||
return this.manager.input.getActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the user's input data for all tabs.
|
* Gets the user's input data for all tabs.
|
||||||
*
|
*
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
getAllInput() {
|
getAllInput() {
|
||||||
return this.manager.input.getAll();
|
this.manager.input.getAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -686,8 +680,8 @@ class App {
|
|||||||
|
|
||||||
// Update the current history state (not creating a new one)
|
// Update the current history state (not creating a new one)
|
||||||
if (this.options.updateUrl) {
|
if (this.options.updateUrl) {
|
||||||
this.lastStateUrl = this.manager.controls.generateStateUrl(true, true, recipeConfig);
|
// this.lastStateUrl = this.manager.controls.generateStateUrl(true, true, recipeConfig);
|
||||||
window.history.replaceState({}, title, this.lastStateUrl);
|
// window.history.replaceState({}, title, this.lastStateUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
610
src/web/InputWorker.mjs
Normal file
610
src/web/InputWorker.mjs
Normal file
@ -0,0 +1,610 @@
|
|||||||
|
/**
|
||||||
|
* Web Worker to handle loading data
|
||||||
|
*
|
||||||
|
* @author j433866 [j433866@gmail.com]
|
||||||
|
* @copyright Crown Copyright 2019
|
||||||
|
* @license Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
self.maxWorkers = 4;
|
||||||
|
self.maxTabs = 1;
|
||||||
|
self.pendingFiles = [];
|
||||||
|
self.inputs = {};
|
||||||
|
self.loaderWorkerPorts = [];
|
||||||
|
self.currentInputNum = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Respond to message from parent thread.
|
||||||
|
*/
|
||||||
|
self.addEventListener("message", function(e) {
|
||||||
|
const r = e.data;
|
||||||
|
if (!r.hasOwnProperty("action")) {
|
||||||
|
log.error("No action");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (r.action) {
|
||||||
|
case "loadUIFiles":
|
||||||
|
self.loadFiles(r.data);
|
||||||
|
break;
|
||||||
|
case "loaderWorkerReady":
|
||||||
|
self.loaderWorkerReady(r.data);
|
||||||
|
break;
|
||||||
|
case "updateMaxWorkers":
|
||||||
|
self.maxWorkers = r.data;
|
||||||
|
break;
|
||||||
|
case "updateMaxTabs":
|
||||||
|
self.maxTabs = r.data;
|
||||||
|
break;
|
||||||
|
case "updateInputValue":
|
||||||
|
self.updateInputValue(r.data);
|
||||||
|
break;
|
||||||
|
case "getInputProgress":
|
||||||
|
self.getInputProgress(r.data);
|
||||||
|
break;
|
||||||
|
case "updateInputProgress":
|
||||||
|
self.updateInputProgress(r.data);
|
||||||
|
break;
|
||||||
|
case "getAll":
|
||||||
|
self.getAllInputs();
|
||||||
|
break;
|
||||||
|
case "getLoadProgress":
|
||||||
|
self.getLoadProgress(r.data);
|
||||||
|
break;
|
||||||
|
case "setInput":
|
||||||
|
self.setInput(r.data);
|
||||||
|
break;
|
||||||
|
case "setLogLevel":
|
||||||
|
log.setLevel(r.data, false);
|
||||||
|
break;
|
||||||
|
case "addInput":
|
||||||
|
self.addInput(true, "string");
|
||||||
|
break;
|
||||||
|
case "refreshTabs":
|
||||||
|
self.refreshTabs(r.data.inputNum, r.data.direction);
|
||||||
|
break;
|
||||||
|
case "removeInput":
|
||||||
|
self.removeInput(r.data);
|
||||||
|
break;
|
||||||
|
case "changeTabRight":
|
||||||
|
self.changeTabRight(r.data.activeTab, r.data.nums);
|
||||||
|
break;
|
||||||
|
case "changeTabLeft":
|
||||||
|
self.changeTabLeft(r.data.activeTab, r.data.nums);
|
||||||
|
break;
|
||||||
|
case "autobake":
|
||||||
|
self.autoBake(r.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.error(`Unknown action '${r.action}'.`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.getLoadProgress = function(inputNum) {
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
const total = inputNums.length;
|
||||||
|
const pending = self.pendingFiles.length;
|
||||||
|
let loaded = 0;
|
||||||
|
let loading = 0;
|
||||||
|
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
switch (self.inputs[inputNums[i]].status) {
|
||||||
|
case "loading":
|
||||||
|
loading++;
|
||||||
|
break;
|
||||||
|
case "loaded":
|
||||||
|
loaded++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "loadingInfo",
|
||||||
|
data: {
|
||||||
|
pending: pending,
|
||||||
|
loading: loading,
|
||||||
|
loaded: loaded,
|
||||||
|
total: total,
|
||||||
|
activeProgress: {
|
||||||
|
inputNum: inputNum,
|
||||||
|
progress: self.getInputProgress(inputNum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loaded < total) {
|
||||||
|
setTimeout(function(inputNum) {
|
||||||
|
self.getLoadProgress(inputNum);
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.autoBake = function(inputNum) {
|
||||||
|
const input = self.getInputObj(inputNum);
|
||||||
|
if (input) {
|
||||||
|
let inputData = input.data;
|
||||||
|
if (typeof inputData !== "string") {
|
||||||
|
inputData = inputData.fileBuffer;
|
||||||
|
}
|
||||||
|
self.postMessage({
|
||||||
|
action: "allInputs",
|
||||||
|
data: [{
|
||||||
|
input: inputData,
|
||||||
|
inputNum: parseInt(inputNum, 10)
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getAllInputs = function() {
|
||||||
|
const inputs = [];
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
if (self.inputs[inputNums[i]].status === "loaded") {
|
||||||
|
let inputData = self.inputs[inputNums[i]].data;
|
||||||
|
if (typeof inputData !== "string") {
|
||||||
|
inputData = inputData.fileBuffer;
|
||||||
|
}
|
||||||
|
inputs.push({
|
||||||
|
input: inputData,
|
||||||
|
inputNum: inputNums[i]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "allInputs",
|
||||||
|
data: inputs
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getInputObj = function(inputNum) {
|
||||||
|
return self.inputs[inputNum];
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getInputValue = function(inputNum) {
|
||||||
|
for (let i = 0; i < self.inputs.length; i++) {
|
||||||
|
if (self.inputs[i].inputNum === inputNum) {
|
||||||
|
if (self.inputs[i].status === "loaded") {
|
||||||
|
let inputData = self.inputs[i].data;
|
||||||
|
if (typeof inputData !== "string") {
|
||||||
|
inputData = inputData.fileBuffer;
|
||||||
|
}
|
||||||
|
return inputData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getInputProgress = function(inputNum) {
|
||||||
|
const inputObj = self.getInputObj(inputNum);
|
||||||
|
if (inputObj === undefined || inputObj === null) return;
|
||||||
|
return inputObj.progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the largest inputNum
|
||||||
|
*
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
self.getLargestInputNum = function() {
|
||||||
|
let largest = 0;
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
const num = parseInt(inputNums[i], 10);
|
||||||
|
if (num > largest) {
|
||||||
|
largest = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return largest;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the smallest inputNum
|
||||||
|
*
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
self.getSmallestInputNum = function() {
|
||||||
|
let smallest = self.getLargestInputNum();
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
const num = parseInt(inputNums[i], 10);
|
||||||
|
if (num < smallest) {
|
||||||
|
smallest = num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return smallest;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the previous inputNum
|
||||||
|
*
|
||||||
|
* @param {number} inputNum - The current input number
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
self.getPreviousInputNum = function(inputNum) {
|
||||||
|
let num = -1;
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
|
if (iNum < inputNum) {
|
||||||
|
if (iNum > num) {
|
||||||
|
num = iNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the next inputNum
|
||||||
|
*
|
||||||
|
* @param {number} inputNum - The current input number
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
self.getNextInputNum = function(inputNum) {
|
||||||
|
let num = self.getLargestInputNum();
|
||||||
|
const inputNums = Object.keys(self.inputs);
|
||||||
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
|
if (iNum > inputNum) {
|
||||||
|
if (iNum < num) {
|
||||||
|
num = iNum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getNearbyNums = function(inputNum, direction) {
|
||||||
|
const nums = [];
|
||||||
|
for (let i = 0; i < self.maxTabs; i++) {
|
||||||
|
let newNum;
|
||||||
|
if (i === 0 && self.inputs[inputNum] !== undefined) {
|
||||||
|
newNum = inputNum;
|
||||||
|
} else {
|
||||||
|
switch (direction) {
|
||||||
|
case "left":
|
||||||
|
newNum = self.getNextInputNum(nums[i - 1]);
|
||||||
|
if (newNum === nums[i - 1]) {
|
||||||
|
direction = "right";
|
||||||
|
newNum = self.getPreviousInputNum(nums[i - 1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "right":
|
||||||
|
newNum = self.getPreviousInputNum(nums[i - 1]);
|
||||||
|
if (newNum === nums[i - 1]) {
|
||||||
|
direction = "left";
|
||||||
|
newNum = self.getNextInputNum(nums[i - 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!nums.includes(newNum) && (newNum > 0)) {
|
||||||
|
nums.push(newNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nums.sort(function(a, b) {
|
||||||
|
return a - b;
|
||||||
|
});
|
||||||
|
return nums;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateTabHeader = function(inputNum) {
|
||||||
|
const input = self.getInputObj(inputNum);
|
||||||
|
if (input === null || input === undefined) return;
|
||||||
|
let inputData = input.data;
|
||||||
|
if (typeof inputData !== "string") {
|
||||||
|
inputData = input.data.name;
|
||||||
|
}
|
||||||
|
self.postMessage({
|
||||||
|
action: "updateTabHeader",
|
||||||
|
data: {
|
||||||
|
inputNum: inputNum,
|
||||||
|
input: inputData.slice(0, 100)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.setInput = function(inputNum) {
|
||||||
|
const input = self.getInputObj(inputNum);
|
||||||
|
if (input === undefined || input === null) return;
|
||||||
|
|
||||||
|
const inputVal = input.data;
|
||||||
|
const inputObj = {
|
||||||
|
inputNum: inputNum,
|
||||||
|
input: inputVal
|
||||||
|
};
|
||||||
|
if (typeof inputVal !== "string") {
|
||||||
|
inputObj.input = inputVal.fileBuffer.slice(0, 4096);
|
||||||
|
inputObj.name = inputVal.name;
|
||||||
|
inputObj.size = inputVal.size;
|
||||||
|
inputObj.type = inputVal.type;
|
||||||
|
inputObj.progress = input.progress;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "setInput",
|
||||||
|
data: inputObj
|
||||||
|
});
|
||||||
|
self.getInputProgress(inputNum);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.refreshTabs = function(inputNum, direction) {
|
||||||
|
const nums = self.getNearbyNums(inputNum, direction);
|
||||||
|
self.postMessage({
|
||||||
|
action: "refreshTabs",
|
||||||
|
data: {
|
||||||
|
nums: nums,
|
||||||
|
activeTab: (nums.includes(inputNum)) ? inputNum : self.getNextInputNum(inputNum)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i < nums.length; i++) {
|
||||||
|
self.updateTabHeader(nums[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// self.setInput(inputNum);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateInputStatus = function(inputNum, status) {
|
||||||
|
for (let i = 0; i < self.inputs.length; i++) {
|
||||||
|
if (self.inputs[i].inputNum === inputNum) {
|
||||||
|
self.inputs[i].status = status;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateInputProgress = function(inputData) {
|
||||||
|
const inputNum = inputData.inputNum;
|
||||||
|
const progress = inputData.progress;
|
||||||
|
|
||||||
|
if (self.inputs[inputNum] !== undefined) {
|
||||||
|
self.inputs[inputNum].progress = progress;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.updateInputValue = function(inputData) {
|
||||||
|
const inputNum = inputData.inputNum;
|
||||||
|
if (inputNum < 1) return;
|
||||||
|
const value = inputData.value;
|
||||||
|
if (self.inputs[inputNum] !== undefined) {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
self.inputs[inputNum].data = value;
|
||||||
|
} else {
|
||||||
|
self.inputs[inputNum].data.fileBuffer = value;
|
||||||
|
}
|
||||||
|
self.inputs[inputNum].status = "loaded";
|
||||||
|
self.inputs[inputNum].progress = 100;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get to here, an input for inputNum could not be found
|
||||||
|
// Only do this if the value is a string, as loadFiles will create
|
||||||
|
// the input object for files
|
||||||
|
if (typeof value === "string") {
|
||||||
|
self.inputs.push({
|
||||||
|
inputNum: inputNum,
|
||||||
|
data: value,
|
||||||
|
status: "loaded",
|
||||||
|
progress: 100
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.getLoaderWorkerIdx = function(workerId) {
|
||||||
|
for (let i = 0; i < self.loaderWorkerPorts.length; i++) {
|
||||||
|
if (self.loaderWorkerPorts[i].id === workerId) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.loaderWorkerReady = function(workerData) {
|
||||||
|
const newWorkerObj = {
|
||||||
|
id: workerData.id,
|
||||||
|
port: workerData.port,
|
||||||
|
inputNum: -1,
|
||||||
|
active: true
|
||||||
|
};
|
||||||
|
newWorkerObj.port.onmessage = function (e) {
|
||||||
|
self.handleLoaderMessage(e);
|
||||||
|
};
|
||||||
|
self.loaderWorkerPorts.push(newWorkerObj);
|
||||||
|
self.loadNextFile(self.loaderWorkerPorts.indexOf(newWorkerObj));
|
||||||
|
};
|
||||||
|
|
||||||
|
self.handleLoaderMessage = function(e) {
|
||||||
|
const r = e.data;
|
||||||
|
let inputNum = 0;
|
||||||
|
|
||||||
|
if (r.hasOwnProperty("inputNum")) {
|
||||||
|
inputNum = r.inputNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r.hasOwnProperty("fileBuffer")) {
|
||||||
|
log.debug(`Input file ${inputNum} loaded.`);
|
||||||
|
self.updateInputValue({
|
||||||
|
inputNum: inputNum,
|
||||||
|
value: r.fileBuffer
|
||||||
|
});
|
||||||
|
const idx = self.getLoaderWorkerIdx(r.id);
|
||||||
|
self.loadNextFile(idx);
|
||||||
|
} else if (r.hasOwnProperty("progress")) {
|
||||||
|
self.updateInputProgress(r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.loadNextFile = function(workerIdx) {
|
||||||
|
if (workerIdx === -1) return; // No more workers can be created
|
||||||
|
const port = self.loaderWorkerPorts[workerIdx].port;
|
||||||
|
if (self.pendingFiles.length === 0) {
|
||||||
|
const workerObj = self.loaderWorkerPorts.splice(workerIdx, 1)[0];
|
||||||
|
self.terminateLoaderWorker(workerObj.id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nextFile = self.pendingFiles.splice(0, 1)[0];
|
||||||
|
self.loaderWorkerPorts[workerIdx].inputNum = nextFile.inputNum;
|
||||||
|
port.postMessage({
|
||||||
|
action: "loadInput",
|
||||||
|
data: {
|
||||||
|
file: nextFile.file,
|
||||||
|
inputNum: nextFile.inputNum
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.activateLoaderWorker = function() {
|
||||||
|
for (let i = 0; i < self.loaderWorkerPorts.length; i++) {
|
||||||
|
if (!self.loaderWorkerPorts[i].active) {
|
||||||
|
self.loaderWorkerPorts[i].active = true;
|
||||||
|
self.loadNextFile(i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.postMessage({
|
||||||
|
action: "activateLoaderWorker"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
self.terminateLoaderWorker = function(id) {
|
||||||
|
self.postMessage({
|
||||||
|
action: "terminateLoaderWorker",
|
||||||
|
data: id
|
||||||
|
});
|
||||||
|
if (self.pendingFiles.length > 0) {
|
||||||
|
self.activateLoaderWorker();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads files using LoaderWorkers
|
||||||
|
*/
|
||||||
|
self.loadFiles = function(files) {
|
||||||
|
let lastInputNum = -1;
|
||||||
|
const inputNums = [];
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
lastInputNum = self.addInput(false, "file", {
|
||||||
|
name: files[i].name,
|
||||||
|
size: files[i].size.toLocaleString(),
|
||||||
|
type: files[i].type || "unknown"
|
||||||
|
});
|
||||||
|
inputNums.push(lastInputNum);
|
||||||
|
|
||||||
|
self.pendingFiles.push({
|
||||||
|
file: files[i],
|
||||||
|
inputNum: lastInputNum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let max = self.maxWorkers;
|
||||||
|
if (self.pendingFiles.length < self.maxWorkers) max = self.pendingFiles.length;
|
||||||
|
|
||||||
|
for (let i = 0; i < max; i++) {
|
||||||
|
self.activateLoaderWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
// self.refreshTabs(lastInputNum, "right");
|
||||||
|
self.getLoadProgress();
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "addInputs",
|
||||||
|
data: inputNums
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an input to the input array
|
||||||
|
*
|
||||||
|
* @param {boolean} [changetab=false] - Whether or not to send a message to the main thread that the input has been created
|
||||||
|
* @param {string} type - Either "string" or "file"
|
||||||
|
* @param {Object} fileData - Contains information about the file to be added to the input
|
||||||
|
* @param {string} fileData.name
|
||||||
|
* @param {string} fileData.size
|
||||||
|
* @param {string} fileData.type
|
||||||
|
*/
|
||||||
|
self.addInput = function(changeTab=false, type, fileData={name: "unknown", size: "unknown", type: "unknown"}) {
|
||||||
|
const inputNum = self.currentInputNum++;
|
||||||
|
const newInputObj = {
|
||||||
|
inputNum: inputNum
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case "string":
|
||||||
|
newInputObj.data = "";
|
||||||
|
newInputObj.status = "loaded";
|
||||||
|
newInputObj.progress = 100;
|
||||||
|
break;
|
||||||
|
case "file":
|
||||||
|
newInputObj.data = {
|
||||||
|
fileBuffer: new ArrayBuffer(),
|
||||||
|
name: fileData.name,
|
||||||
|
size: fileData.size,
|
||||||
|
type: fileData.type
|
||||||
|
};
|
||||||
|
newInputObj.status = "pending";
|
||||||
|
newInputObj.progress = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
log.error(`Invalid type '${type}'.`);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
self.inputs[inputNum] = newInputObj;
|
||||||
|
|
||||||
|
if (changeTab) {
|
||||||
|
self.postMessage({
|
||||||
|
action: "inputAdded",
|
||||||
|
data: {
|
||||||
|
changeTab: changeTab,
|
||||||
|
inputNum: inputNum
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return inputNum;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.removeInput = function(removeInputData) {
|
||||||
|
const inputNum = removeInputData.inputNum;
|
||||||
|
const refreshTabs = removeInputData.refreshTabs;
|
||||||
|
|
||||||
|
delete self.inputs[inputNum];
|
||||||
|
|
||||||
|
for (let i = 0; i < self.loaderWorkerPorts.length; i++) {
|
||||||
|
if (self.loaderWorkerPorts[i].inputNum === inputNum) {
|
||||||
|
self.terminateLoaderWorker(self.loaderWorkerPorts[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshTabs) {
|
||||||
|
self.refreshTabs(inputNum, "left");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.changeTabRight = function(inputNum, tabNums) {
|
||||||
|
const newInput = self.getNextInputNum(inputNum);
|
||||||
|
if (tabNums.includes(newInput)) {
|
||||||
|
self.postMessage({
|
||||||
|
action: "changeTab",
|
||||||
|
data: newInput
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.refreshTabs(newInput, "right");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.changeTabLeft = function(inputNum, tabNums) {
|
||||||
|
const newInput = self.getPreviousInputNum(inputNum);
|
||||||
|
if (tabNums.includes(newInput)) {
|
||||||
|
self.postMessage({
|
||||||
|
action: "changeTab",
|
||||||
|
data: newInput
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.refreshTabs(newInput, "left");
|
||||||
|
}
|
||||||
|
};
|
@ -6,6 +6,21 @@
|
|||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
self.port = null;
|
||||||
|
self.id = null;
|
||||||
|
|
||||||
|
|
||||||
|
self.handlePortMessage = function(e) {
|
||||||
|
const r = e.data;
|
||||||
|
log.debug(`LoaderWorker receiving command '${r.action}'`);
|
||||||
|
|
||||||
|
switch (r.action) {
|
||||||
|
case "loadInput":
|
||||||
|
self.loadFile(r.data.file, r.data.inputNum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Respond to message from parent thread.
|
* Respond to message from parent thread.
|
||||||
@ -16,6 +31,12 @@ self.addEventListener("message", function(e) {
|
|||||||
self.loadFile(r.file, r.inputNum);
|
self.loadFile(r.file, r.inputNum);
|
||||||
} else if (r.hasOwnProperty("file")) {
|
} else if (r.hasOwnProperty("file")) {
|
||||||
self.loadFile(r.file, "");
|
self.loadFile(r.file, "");
|
||||||
|
} else if (r.hasOwnProperty("port")) {
|
||||||
|
self.port = r.port;
|
||||||
|
self.id = r.id;
|
||||||
|
self.port.onmessage = function(e) {
|
||||||
|
self.handlePortMessage(e);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -28,17 +49,21 @@ self.addEventListener("message", function(e) {
|
|||||||
*/
|
*/
|
||||||
self.loadFile = function(file, inputNum) {
|
self.loadFile = function(file, inputNum) {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
const data = new Uint8Array(file.size);
|
let data;
|
||||||
|
try {
|
||||||
|
data = new Uint8Array(file.size);
|
||||||
|
} catch (err) {
|
||||||
|
self.port.postMessage({"error": err, "inputNum": inputNum});
|
||||||
|
}
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
const CHUNK_SIZE = 10485760; // 10MiB
|
const CHUNK_SIZE = 10485760; // 10MiB
|
||||||
|
|
||||||
const seek = function() {
|
const seek = function() {
|
||||||
if (offset >= file.size) {
|
if (offset >= file.size) {
|
||||||
self.postMessage({"progress": 100, "inputNum": inputNum});
|
self.port.postMessage({"fileBuffer": data.buffer, "inputNum": inputNum, "id": self.id}, [data.buffer]);
|
||||||
self.postMessage({"fileBuffer": data.buffer, "inputNum": inputNum}, [data.buffer]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.postMessage({"progress": Math.round(offset / file.size * 100), "inputNum": inputNum});
|
// self.port.postMessage({"progress": Math.round(offset / file.size * 100), "inputNum": inputNum});
|
||||||
const slice = file.slice(offset, offset + CHUNK_SIZE);
|
const slice = file.slice(offset, offset + CHUNK_SIZE);
|
||||||
reader.readAsArrayBuffer(slice);
|
reader.readAsArrayBuffer(slice);
|
||||||
};
|
};
|
||||||
@ -50,7 +75,7 @@ self.loadFile = function(file, inputNum) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
reader.onerror = function(e) {
|
reader.onerror = function(e) {
|
||||||
self.postMessage({"error": reader.error.message});
|
self.port.postMessage({"error": reader.error.message, "inputNum": inputNum});
|
||||||
};
|
};
|
||||||
|
|
||||||
seek();
|
seek();
|
||||||
|
@ -82,8 +82,8 @@ class Manager {
|
|||||||
* Sets up the various components and listeners.
|
* Sets up the various components and listeners.
|
||||||
*/
|
*/
|
||||||
setup() {
|
setup() {
|
||||||
this.input.addTab(true);
|
this.input.setupInputWorker();
|
||||||
this.input.setupLoaderWorker();
|
this.input.addInput();
|
||||||
this.worker.setupChefWorker();
|
this.worker.setupChefWorker();
|
||||||
this.recipe.initialiseOperationDragNDrop();
|
this.recipe.initialiseOperationDragNDrop();
|
||||||
this.controls.initComponents();
|
this.controls.initComponents();
|
||||||
@ -145,10 +145,10 @@ class Manager {
|
|||||||
|
|
||||||
// Input
|
// Input
|
||||||
this.addMultiEventListener("#input-text", "keyup", this.input.inputChange, this.input);
|
this.addMultiEventListener("#input-text", "keyup", this.input.inputChange, this.input);
|
||||||
this.addMultiEventListener("#input-text", "paste", this.input.inputPaste, this.input);
|
// this.addMultiEventListener("#input-text", "paste", this.input.inputPaste, this.input);
|
||||||
document.getElementById("reset-layout").addEventListener("click", this.app.resetLayout.bind(this.app));
|
document.getElementById("reset-layout").addEventListener("click", this.app.resetLayout.bind(this.app));
|
||||||
document.getElementById("clr-io").addEventListener("click", this.input.clearAllIoClick.bind(this.input));
|
// document.getElementById("clr-io").addEventListener("click", this.input.clearAllIoClick.bind(this.input));
|
||||||
this.addListeners("#open-file", "change", this.input.inputOpen, this.input);
|
this.addListeners("#open-file,#open-folder", "change", this.input.inputOpen, this.input);
|
||||||
this.addListeners("#input-text,#input-file", "dragover", this.input.inputDragover, this.input);
|
this.addListeners("#input-text,#input-file", "dragover", this.input.inputDragover, this.input);
|
||||||
this.addListeners("#input-text,#input-file", "dragleave", this.input.inputDragleave, this.input);
|
this.addListeners("#input-text,#input-file", "dragleave", this.input.inputDragleave, this.input);
|
||||||
this.addListeners("#input-text,#input-file", "drop", this.input.inputDrop, this.input);
|
this.addListeners("#input-text,#input-file", "drop", this.input.inputDrop, this.input);
|
||||||
@ -156,22 +156,37 @@ class Manager {
|
|||||||
// document.getElementById("input-text").addEventListener("mouseup", this.highlighter.inputMouseup.bind(this.highlighter));
|
// document.getElementById("input-text").addEventListener("mouseup", this.highlighter.inputMouseup.bind(this.highlighter));
|
||||||
// document.getElementById("input-text").addEventListener("mousemove", this.highlighter.inputMousemove.bind(this.highlighter));
|
// document.getElementById("input-text").addEventListener("mousemove", this.highlighter.inputMousemove.bind(this.highlighter));
|
||||||
// this.addMultiEventListener("#input-text", "mousedown dblclick select", this.highlighter.inputMousedown, this.highlighter);
|
// this.addMultiEventListener("#input-text", "mousedown dblclick select", this.highlighter.inputMousedown, this.highlighter);
|
||||||
document.querySelector("#input-file .close").addEventListener("click", this.input.clearIoClick.bind(this.input));
|
// document.querySelector("#input-file .close").addEventListener("click", this.input.clearIoClick.bind(this.input));
|
||||||
document.getElementById("btn-new-tab").addEventListener("click", this.input.addTab.bind(this.input));
|
document.getElementById("btn-new-tab").addEventListener("click", this.input.addInput.bind(this.input));
|
||||||
document.getElementById("btn-previous-input-tab").addEventListener("click", this.input.changeTabLeft.bind(this.input));
|
document.getElementById("btn-previous-input-tab").addEventListener("click", this.input.changeTabLeft.bind(this.input));
|
||||||
document.getElementById("btn-next-input-tab").addEventListener("click", this.input.changeTabRight.bind(this.input));
|
document.getElementById("btn-next-input-tab").addEventListener("click", this.input.changeTabRight.bind(this.input));
|
||||||
document.getElementById("btn-go-to-input-tab").addEventListener("click", this.input.goToTab.bind(this.input));
|
// document.getElementById("btn-go-to-input-tab").addEventListener("click", this.input.goToTab.bind(this.input));
|
||||||
|
// document.getElementById("btn-find-input-tab").addEventListener("click", this.input.findTab.bind(this.input));
|
||||||
this.addDynamicListener("#input-tabs li .btn-close-tab i", "click", this.input.removeTabClick, this.input);
|
this.addDynamicListener("#input-tabs li .btn-close-tab i", "click", this.input.removeTabClick, this.input);
|
||||||
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);
|
||||||
|
// document.getElementById("input-show-pending").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-show-loading").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-show-loaded").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-filename-filter").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-filename-filter").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-content-filter").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-content-filter").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-num-results").addEventListener("change", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-num-results").addEventListener("keyup", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// document.getElementById("input-filter-refresh").addEventListener("click", this.input.filterTabSearch.bind(this.input));
|
||||||
|
// this.addDynamicListener(".input-filter-result", "click", this.input.filterItemClick, this.input);
|
||||||
|
document.getElementById("btn-open-file").addEventListener("click", this.input.inputOpenClick.bind(this.input));
|
||||||
|
document.getElementById("btn-open-folder").addEventListener("click", this.input.folderOpenClick.bind(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("save-all-to-file").addEventListener("click", this.output.saveAllClick.bind(this.output));
|
document.getElementById("save-all-to-file").addEventListener("click", this.output.saveAllClick.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));
|
||||||
@ -179,8 +194,8 @@ class Manager {
|
|||||||
// 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-wrapper #output-tabs 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);
|
||||||
|
@ -168,6 +168,7 @@ OptionsWaiter.prototype.logLevelChange = function (e) {
|
|||||||
const level = e.target.value;
|
const level = e.target.value;
|
||||||
log.setLevel(level, false);
|
log.setLevel(level, false);
|
||||||
this.manager.worker.setLogLevel();
|
this.manager.worker.setLogLevel();
|
||||||
|
this.manager.input.setLogLevel();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default OptionsWaiter;
|
export default OptionsWaiter;
|
||||||
|
@ -26,7 +26,7 @@ class OutputWaiter {
|
|||||||
this.app = app;
|
this.app = app;
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
|
|
||||||
this.outputs = [];
|
this.outputs = {};
|
||||||
|
|
||||||
this.maxTabs = 4; // Calculate this
|
this.maxTabs = 4; // Calculate this
|
||||||
}
|
}
|
||||||
@ -46,31 +46,17 @@ class OutputWaiter {
|
|||||||
* @returns {string | ArrayBuffer}
|
* @returns {string | ArrayBuffer}
|
||||||
*/
|
*/
|
||||||
getOutput(inputNum) {
|
getOutput(inputNum) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
if (this.outputs[inputNum] === undefined || this.outputs[inputNum] === null) return -1;
|
||||||
if (index === -1) return -1;
|
|
||||||
|
|
||||||
if (typeof this.outputs[index].data.dish.value === "string") {
|
if (this.outputs[inputNum].data === null) return "";
|
||||||
return this.outputs[index].data.dish.value;
|
|
||||||
|
if (typeof this.outputs[inputNum].data.dish.value === "string") {
|
||||||
|
return this.outputs[inputNum].data.dish.value;
|
||||||
} else {
|
} else {
|
||||||
return this.outputs[index].data.dish.value || "";
|
return this.outputs[inputNum].data.dish.value || "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the index of the output for the specified input number
|
|
||||||
*
|
|
||||||
* @param {number} inputNum
|
|
||||||
* @returns {number}
|
|
||||||
*/
|
|
||||||
getOutputIndex(inputNum) {
|
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
|
||||||
if (this.outputs[i].inputNum === inputNum) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the output string or FileBuffer for the active input
|
* Gets the output string or FileBuffer for the active input
|
||||||
*
|
*
|
||||||
@ -88,10 +74,10 @@ class OutputWaiter {
|
|||||||
* @param {boolean} [changeTab=true]
|
* @param {boolean} [changeTab=true]
|
||||||
*/
|
*/
|
||||||
addOutput(inputNum, changeTab = true) {
|
addOutput(inputNum, changeTab = true) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
const output = this.getOutput(inputNum);
|
||||||
if (index !== -1) {
|
if (output !== -1) {
|
||||||
// Remove the output if it already exists
|
// Remove the output if it already exists
|
||||||
this.outputs.splice(index, 1);
|
delete this.outputs[inputNum];
|
||||||
}
|
}
|
||||||
const newOutput = {
|
const newOutput = {
|
||||||
data: null,
|
data: null,
|
||||||
@ -102,11 +88,10 @@ class OutputWaiter {
|
|||||||
status: "inactive"
|
status: "inactive"
|
||||||
};
|
};
|
||||||
|
|
||||||
this.outputs.push(newOutput);
|
this.outputs[inputNum] = newOutput;
|
||||||
|
|
||||||
// add new tab
|
// add new tab
|
||||||
this.addTab(inputNum, changeTab);
|
this.addTab(inputNum, changeTab);
|
||||||
return this.outputs.indexOf(newOutput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,13 +102,11 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
updateOutputValue(data, inputNum) {
|
updateOutputValue(data, inputNum) {
|
||||||
let index = this.getOutputIndex(inputNum);
|
if (this.getOutput(inputNum) === -1) {
|
||||||
if (index === -1) {
|
this.addOutput(inputNum);
|
||||||
index = this.addOutput(inputNum);
|
|
||||||
this.addTab(inputNum, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.outputs[index].data = data;
|
this.outputs[inputNum].data = data;
|
||||||
|
|
||||||
// set output here
|
// set output here
|
||||||
this.set(inputNum);
|
this.set(inputNum);
|
||||||
@ -137,10 +120,8 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
updateOutputMessage(statusMessage, inputNum) {
|
updateOutputMessage(statusMessage, inputNum) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
if (index === -1) return;
|
this.outputs[inputNum].statusMessage = statusMessage;
|
||||||
|
|
||||||
this.outputs[index].statusMessage = statusMessage;
|
|
||||||
this.set(inputNum);
|
this.set(inputNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,10 +134,9 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
updateOutputError(error, inputNum) {
|
updateOutputError(error, inputNum) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
if (index === -1) return;
|
|
||||||
|
|
||||||
this.outputs[index].error = error;
|
this.outputs[inputNum].error = error;
|
||||||
|
|
||||||
// call handle error here
|
// call handle error here
|
||||||
// or make the error handling part of set()
|
// or make the error handling part of set()
|
||||||
@ -170,10 +150,8 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
updateOutputStatus(status, inputNum) {
|
updateOutputStatus(status, inputNum) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
if (index === -1) return;
|
this.outputs[inputNum].status = status;
|
||||||
|
|
||||||
this.outputs[index].status = status;
|
|
||||||
|
|
||||||
this.set(inputNum);
|
this.set(inputNum);
|
||||||
}
|
}
|
||||||
@ -184,10 +162,9 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
removeOutput(inputNum) {
|
removeOutput(inputNum) {
|
||||||
const index = this.getOutputIndex(inputNum);
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
if (index === -1) return;
|
|
||||||
|
|
||||||
this.outputs.splice(index, 1);
|
delete (this.outputs[inputNum]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,9 +173,11 @@ class OutputWaiter {
|
|||||||
* @param {number} inputNum
|
* @param {number} inputNum
|
||||||
*/
|
*/
|
||||||
set(inputNum) {
|
set(inputNum) {
|
||||||
const outputIndex = this.getOutputIndex(inputNum);
|
const output = this.outputs[inputNum];
|
||||||
if (outputIndex === -1) return;
|
if (output === undefined || output === null) return;
|
||||||
const output = this.outputs[outputIndex];
|
|
||||||
|
if (typeof inputNum !== "number") inputNum = parseInt(inputNum, 10);
|
||||||
|
|
||||||
const outputText = document.getElementById("output-text");
|
const outputText = document.getElementById("output-text");
|
||||||
const outputHtml = document.getElementById("output-html");
|
const outputHtml = document.getElementById("output-html");
|
||||||
const outputFile = document.getElementById("output-file");
|
const outputFile = document.getElementById("output-file");
|
||||||
@ -208,6 +187,11 @@ class OutputWaiter {
|
|||||||
// If pending or baking, show loader and status message
|
// If pending or baking, show loader and status message
|
||||||
// If error, style the tab and handle the error
|
// If error, style the tab and handle the error
|
||||||
// If done, display the output if it's the active tab
|
// If done, display the output if it's the active tab
|
||||||
|
if (output.status === "inactive" || output.status === "stale") {
|
||||||
|
this.manager.controls.showStaleIndicator();
|
||||||
|
} else {
|
||||||
|
this.manager.controls.hideStaleIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
if (output.status === "inactive") {
|
if (output.status === "inactive") {
|
||||||
// An output is inactive when it has been created but has not been baked at all
|
// An output is inactive when it has been created but has not been baked at all
|
||||||
@ -229,7 +213,6 @@ class OutputWaiter {
|
|||||||
// otherwise don't do anything
|
// otherwise don't do anything
|
||||||
if (inputNum === this.getActiveTab()) {
|
if (inputNum === this.getActiveTab()) {
|
||||||
this.toggleLoader(true);
|
this.toggleLoader(true);
|
||||||
|
|
||||||
document.querySelector("#output-loader .loading-msg").textContent = output.statusMessage;
|
document.querySelector("#output-loader .loading-msg").textContent = output.statusMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,6 +229,7 @@ class OutputWaiter {
|
|||||||
this.toggleLoader(false);
|
this.toggleLoader(false);
|
||||||
this.closeFile();
|
this.closeFile();
|
||||||
let scriptElements, lines, length;
|
let scriptElements, lines, length;
|
||||||
|
const duration = output.data.duration;
|
||||||
|
|
||||||
switch (output.data.type) {
|
switch (output.data.type) {
|
||||||
case "html":
|
case "html":
|
||||||
@ -267,6 +251,7 @@ class OutputWaiter {
|
|||||||
log.error(err);
|
log.error(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
length = output.data.dish.value.length;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "ArrayBuffer":
|
case "ArrayBuffer":
|
||||||
@ -277,8 +262,8 @@ class OutputWaiter {
|
|||||||
|
|
||||||
outputText.value = "";
|
outputText.value = "";
|
||||||
outputHtml.innerHTML = "";
|
outputHtml.innerHTML = "";
|
||||||
length = output.data.result.byteLength;
|
|
||||||
|
|
||||||
|
length = output.data.result.length;
|
||||||
this.setFile(output.data.result);
|
this.setFile(output.data.result);
|
||||||
break;
|
break;
|
||||||
case "string":
|
case "string":
|
||||||
@ -296,6 +281,8 @@ class OutputWaiter {
|
|||||||
length = output.data.result.length;
|
length = output.data.result.length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
this.setOutputInfo(length, lines, duration);
|
||||||
|
this.backgroundMagic();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -368,7 +355,7 @@ class OutputWaiter {
|
|||||||
outputElement.disabled = true;
|
outputElement.disabled = true;
|
||||||
outputLoader.style.visibility = "visible";
|
outputLoader.style.visibility = "visible";
|
||||||
outputLoader.style.opacity = 1;
|
outputLoader.style.opacity = 1;
|
||||||
}.bind(this), 200);
|
}, 200);
|
||||||
} else {
|
} else {
|
||||||
// Remove the Bombe from the DOM to save resources
|
// Remove the Bombe from the DOM to save resources
|
||||||
this.outputLoaderTimeout = setTimeout(function () {
|
this.outputLoaderTimeout = setTimeout(function () {
|
||||||
@ -388,7 +375,7 @@ class OutputWaiter {
|
|||||||
* Saves the current output to a file.
|
* Saves the current output to a file.
|
||||||
*/
|
*/
|
||||||
saveClick() {
|
saveClick() {
|
||||||
this.downloadFile(this.getActiveTab());
|
this.downloadFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -452,6 +439,8 @@ class OutputWaiter {
|
|||||||
document.getElementById("output-highlighter").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
document.getElementById("output-highlighter").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
||||||
document.getElementById("output-file").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
document.getElementById("output-file").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
||||||
document.getElementById("output-loader").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
document.getElementById("output-loader").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
||||||
|
|
||||||
|
document.getElementById("save-all-to-file").style.display = "inline-block";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,7 +457,7 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
changeTab(inputNum, changeInput = false) {
|
changeTab(inputNum, changeInput = false) {
|
||||||
const currentNum = this.getActiveTab();
|
const currentNum = this.getActiveTab();
|
||||||
if (this.getOutputIndex(inputNum) === -1) return;
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
|
|
||||||
const tabsWrapper = document.getElementById("output-tabs");
|
const tabsWrapper = document.getElementById("output-tabs");
|
||||||
const tabs = tabsWrapper.children;
|
const tabs = tabsWrapper.children;
|
||||||
@ -523,12 +512,7 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
changeTabLeft() {
|
changeTabLeft() {
|
||||||
const currentTab = this.getActiveTab();
|
const currentTab = this.getActiveTab();
|
||||||
const currentOutput = this.getOutputIndex(currentTab);
|
this.changeTab(this.getPreviousInputNum(currentTab), this.app.options.syncTabs);
|
||||||
if (currentOutput > 0) {
|
|
||||||
this.changeTab(this.getPreviousInputNum(currentTab), this.app.options.syncTabs);
|
|
||||||
} else {
|
|
||||||
this.changeTab(this.getSmallestInputNum(), this.app.options.syncTabs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -594,9 +578,11 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
getLargestInputNum() {
|
getLargestInputNum() {
|
||||||
let largest = 0;
|
let largest = 0;
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
const inputNums = Object.keys(this.outputs);
|
||||||
if (this.outputs[i].inputNum > largest) {
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
largest = this.outputs[i].inputNum;
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
|
if (iNum > largest) {
|
||||||
|
largest = iNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return largest;
|
return largest;
|
||||||
@ -609,9 +595,11 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
getSmallestInputNum() {
|
getSmallestInputNum() {
|
||||||
let smallest = this.getLargestInputNum();
|
let smallest = this.getLargestInputNum();
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
const inputNums = Object.keys(this.outputs);
|
||||||
if (this.outputs[i].inputNum < smallest) {
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
smallest = this.outputs[i].inputNum;
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
|
if (iNum < smallest) {
|
||||||
|
smallest = iNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return smallest;
|
return smallest;
|
||||||
@ -625,10 +613,12 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
getPreviousInputNum(inputNum) {
|
getPreviousInputNum(inputNum) {
|
||||||
let num = this.getSmallestInputNum();
|
let num = this.getSmallestInputNum();
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
const inputNums = Object.keys(this.outputs);
|
||||||
if (this.outputs[i].inputNum < inputNum) {
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
if (this.outputs[i].inputNum > num) {
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
num = this.outputs[i].inputNum;
|
if (iNum < inputNum) {
|
||||||
|
if (iNum > num) {
|
||||||
|
num = iNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -643,10 +633,12 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
getNextInputNum(inputNum) {
|
getNextInputNum(inputNum) {
|
||||||
let num = this.getLargestInputNum();
|
let num = this.getLargestInputNum();
|
||||||
for (let i = 0; i < this.outputs.length; i++) {
|
const inputNums = Object.keys(this.outputs);
|
||||||
if (this.outputs[i].inputNum > inputNum) {
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
if (this.outputs[i].inputNum < num) {
|
const iNum = parseInt(inputNums[i], 10);
|
||||||
num = this.outputs[i].inputNum;
|
if (iNum > inputNum) {
|
||||||
|
if (iNum < num) {
|
||||||
|
num = iNum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -660,7 +652,7 @@ class OutputWaiter {
|
|||||||
*/
|
*/
|
||||||
removeTab(inputNum) {
|
removeTab(inputNum) {
|
||||||
let activeTab = this.getActiveTab();
|
let activeTab = this.getActiveTab();
|
||||||
if (this.getOutputIndex(inputNum) === -1) return;
|
if (this.getOutput(inputNum) === -1) return;
|
||||||
|
|
||||||
const tabElement = this.getTabItem(inputNum);
|
const tabElement = this.getTabItem(inputNum);
|
||||||
|
|
||||||
@ -706,6 +698,8 @@ class OutputWaiter {
|
|||||||
document.getElementById("output-file").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
document.getElementById("output-file").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
||||||
document.getElementById("output-loader").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
document.getElementById("output-loader").style.height = "calc(100% - var(--tab-height) - var(--title-height))";
|
||||||
|
|
||||||
|
document.getElementById("save-all-to-file").style.display = "inline-block";
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
tabsList.parentElement.style.display = "none";
|
tabsList.parentElement.style.display = "none";
|
||||||
|
|
||||||
@ -713,6 +707,8 @@ class OutputWaiter {
|
|||||||
document.getElementById("output-highlighter").style.height = "calc(100% - var(--title-height))";
|
document.getElementById("output-highlighter").style.height = "calc(100% - var(--title-height))";
|
||||||
document.getElementById("output-file").style.height = "calc(100% - var(--title-height))";
|
document.getElementById("output-file").style.height = "calc(100% - var(--title-height))";
|
||||||
document.getElementById("output-loader").style.height = "calc(100% - var(--title-height))";
|
document.getElementById("output-loader").style.height = "calc(100% - var(--title-height))";
|
||||||
|
|
||||||
|
document.getElementById("save-all-to-file").style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.changeTab(activeTab);
|
this.changeTab(activeTab);
|
||||||
@ -782,6 +778,159 @@ class OutputWaiter {
|
|||||||
tabContent.innerText = `Tab ${inputNum}`;
|
tabContent.innerText = `Tab ${inputNum}`;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays information about the output.
|
||||||
|
*
|
||||||
|
* @param {number} length - The length of the current output string
|
||||||
|
* @param {number} lines - The number of the lines in the current output string
|
||||||
|
* @param {number} duration - The length of time (ms) it took to generate the output
|
||||||
|
*/
|
||||||
|
setOutputInfo(length, lines, duration) {
|
||||||
|
if (!length) return;
|
||||||
|
let width = length.toString().length;
|
||||||
|
width = width < 4 ? 4 : width;
|
||||||
|
|
||||||
|
const lengthStr = length.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
const timeStr = (duration.toString() + "ms").padStart(width, " ").replace(/ /g, " ");
|
||||||
|
|
||||||
|
let msg = "time: " + timeStr + "<br>length: " + lengthStr;
|
||||||
|
|
||||||
|
if (typeof lines === "number") {
|
||||||
|
const linesStr = lines.toString().padStart(width, " ").replace(/ /g, " ");
|
||||||
|
msg += "<br>lines: " + linesStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("output-info").innerHTML = msg;
|
||||||
|
document.getElementById("input-selection-info").innerHTML = "";
|
||||||
|
document.getElementById("output-selection-info").innerHTML = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the BackgroundWorker to attempt Magic on the current output.
|
||||||
|
*/
|
||||||
|
backgroundMagic() {
|
||||||
|
this.hideMagicButton();
|
||||||
|
if (!this.app.options.autoMagic || this.getActive()) return;
|
||||||
|
const sample = this.getActive().slice(0, 1000) || "";
|
||||||
|
|
||||||
|
if (sample.length) {
|
||||||
|
this.manager.background.magic(sample);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the results of a background Magic call.
|
||||||
|
*
|
||||||
|
* @param {Object[]} options
|
||||||
|
*/
|
||||||
|
backgroundMagicResult(options) {
|
||||||
|
if (!options.length ||
|
||||||
|
!options[0].recipe.length)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const currentRecipeConfig = this.app.getRecipeConfig();
|
||||||
|
const newRecipeConfig = currentRecipeConfig.concat(options[0].recipe);
|
||||||
|
const opSequence = options[0].recipe.map(o => o.op).join(", ");
|
||||||
|
|
||||||
|
this.showMagicButton(opSequence, options[0].data, newRecipeConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for Magic click events.
|
||||||
|
*
|
||||||
|
* Loads the Magic recipe.
|
||||||
|
*
|
||||||
|
* @fires Manager#statechange
|
||||||
|
*/
|
||||||
|
magicClick() {
|
||||||
|
const magicButton = document.getElementById("magic");
|
||||||
|
this.app.setRecipeConfig(JSON.parse(magicButton.getAttribute("data-recipe")));
|
||||||
|
window.dispatchEvent(this.manager.statechange);
|
||||||
|
this.hideMagicButton();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the Magic button with a title and adds a link to a complete recipe.
|
||||||
|
*
|
||||||
|
* @param {string} opSequence
|
||||||
|
* @param {string} result
|
||||||
|
* @param {Object[]} recipeConfig
|
||||||
|
*/
|
||||||
|
showMagicButton(opSequence, result, recipeConfig) {
|
||||||
|
const magicButton = document.getElementById("magic");
|
||||||
|
magicButton.setAttribute("data-original-title", `<i>${opSequence}</i> will produce <span class="data-text">"${Utils.escapeHtml(Utils.truncate(result), 30)}"</span>`);
|
||||||
|
magicButton.setAttribute("data-recipe", JSON.stringify(recipeConfig), null, "");
|
||||||
|
magicButton.classList.remove("hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides the Magic button and resets its values.
|
||||||
|
*/
|
||||||
|
hideMagicButton() {
|
||||||
|
const magicButton = document.getElementById("magic");
|
||||||
|
magicButton.classList.add("hidden");
|
||||||
|
magicButton.setAttribute("data-recipe", "");
|
||||||
|
magicButton.setAttribute("data-original-title", "Magic!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for file slice display events.
|
||||||
|
*/
|
||||||
|
displayFileSlice() {
|
||||||
|
const startTime = new Date().getTime(),
|
||||||
|
showFileOverlay = document.getElementById("show-file-overlay"),
|
||||||
|
sliceFromEl = document.getElementById("output-file-slice-from"),
|
||||||
|
sliceToEl = document.getElementById("output-file-slice-to"),
|
||||||
|
sliceFrom = parseInt(sliceFromEl.value, 10),
|
||||||
|
sliceTo = parseInt(sliceToEl.value, 10),
|
||||||
|
str = Utils.arrayBufferToStr(this.getActive().slice(sliceFrom, sliceTo));
|
||||||
|
|
||||||
|
document.getElementById("output-text").classList.remove("blur");
|
||||||
|
showFileOverlay.style.display = "block";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for copy click events.
|
||||||
|
* Copies the output to the clipboard
|
||||||
|
*/
|
||||||
|
copyClick() {
|
||||||
|
const output = this.getActive();
|
||||||
|
|
||||||
|
// Create invisible textarea to populate with the raw dish string (not the printable version that
|
||||||
|
// contains dots instead of the actual bytes)
|
||||||
|
const textarea = document.createElement("textarea");
|
||||||
|
textarea.style.position = "fixed";
|
||||||
|
textarea.style.top = 0;
|
||||||
|
textarea.style.left = 0;
|
||||||
|
textarea.style.width = 0;
|
||||||
|
textarea.style.height = 0;
|
||||||
|
textarea.style.border = "none";
|
||||||
|
|
||||||
|
textarea.value = output;
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
|
||||||
|
let success = false;
|
||||||
|
try {
|
||||||
|
textarea.select();
|
||||||
|
success = output && document.execCommand("copy");
|
||||||
|
} catch (err) {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
this.app.alert("Copied raw output successfully.", 2000);
|
||||||
|
} else {
|
||||||
|
this.app.alert("Sorry, the output could not be copied.", 3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default OutputWaiter;
|
export default OutputWaiter;
|
||||||
|
@ -139,33 +139,13 @@ class WorkerWaiter {
|
|||||||
this.updateOutput(r.data, r.data.inputNum);
|
this.updateOutput(r.data, r.data.inputNum);
|
||||||
|
|
||||||
if (this.inputs.length > 0) {
|
if (this.inputs.length > 0) {
|
||||||
const nextInput = this.inputs[0];
|
this.bakeNextInput(this.chefWorkers.indexOf(currentWorker));
|
||||||
this.inputs.splice(0, 1);
|
|
||||||
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
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.displayProgress();
|
|
||||||
} else {
|
} else {
|
||||||
// The ChefWorker is no longer needed
|
// The ChefWorker is no longer needed
|
||||||
log.debug("No more inputs to bake. Closing ChefWorker.");
|
log.debug("No more inputs to bake. Closing ChefWorker.");
|
||||||
currentWorker.active = false;
|
currentWorker.active = false;
|
||||||
this.removeChefWorker(currentWorker);
|
this.removeChefWorker(currentWorker);
|
||||||
|
|
||||||
this.displayProgress();
|
|
||||||
|
|
||||||
const progress = this.getBakeProgress();
|
const progress = this.getBakeProgress();
|
||||||
if (progress.total === progress.baked) {
|
if (progress.total === progress.baked) {
|
||||||
this.bakingComplete();
|
this.bakingComplete();
|
||||||
@ -209,6 +189,7 @@ class WorkerWaiter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the value of an output
|
* Update the value of an output
|
||||||
*
|
*
|
||||||
@ -268,7 +249,6 @@ class WorkerWaiter {
|
|||||||
this.inputs = [];
|
this.inputs = [];
|
||||||
this.totalOutputs = 0;
|
this.totalOutputs = 0;
|
||||||
this.manager.controls.showStaleIndicator();
|
this.manager.controls.showStaleIndicator();
|
||||||
this.displayProgress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -311,10 +291,40 @@ class WorkerWaiter {
|
|||||||
log.debug("--- Bake complete ---");
|
log.debug("--- Bake complete ---");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bakes the next input
|
||||||
|
*
|
||||||
|
* @param {number} workerIdx
|
||||||
|
*/
|
||||||
|
bakeNextInput(workerIdx) {
|
||||||
|
if (this.inputs.length === 0) return;
|
||||||
|
if (workerIdx === -1) return;
|
||||||
|
if (!this.chefWorkers[workerIdx]) return;
|
||||||
|
|
||||||
|
const nextInput = this.inputs.splice(0, 1)[0];
|
||||||
|
|
||||||
|
log.debug(`Baking input ${nextInput.inputNum}.`);
|
||||||
|
this.manager.output.updateOutputStatus("baking", nextInput.inputNum);
|
||||||
|
this.manager.output.updateOutputMessage("Baking...", nextInput.inputNum);
|
||||||
|
|
||||||
|
|
||||||
|
this.chefWorkers[workerIdx].inputNum = nextInput.inputNum;
|
||||||
|
this.chefWorkers[workerIdx].active = true;
|
||||||
|
this.chefWorkers[workerIdx].worker.postMessage({
|
||||||
|
action: "bake",
|
||||||
|
data: {
|
||||||
|
input: nextInput.input,
|
||||||
|
recipeConfig: this.recipeConfig,
|
||||||
|
options: this.options,
|
||||||
|
progress: this.progress,
|
||||||
|
step: this.step,
|
||||||
|
inputNum: nextInput.inputNum
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bakes the current input using the current recipe.
|
* Bakes the current input using the current recipe.
|
||||||
* Either sends the input and recipe to a ChefWorker,
|
|
||||||
* or, if there's already the max running, adds it to inputs
|
|
||||||
*
|
*
|
||||||
* @param {string | Array} input
|
* @param {string | Array} input
|
||||||
* @param {Object[]} recipeConfig
|
* @param {Object[]} recipeConfig
|
||||||
@ -333,6 +343,34 @@ class WorkerWaiter {
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
this.manager.output.updateOutputStatus("pending", input[i].inputNum);
|
||||||
|
|
||||||
|
for (let x = 0; x < this.inputs.length; x++) {
|
||||||
|
if (this.inputs[x].inputNum === input[i].inputNum) {
|
||||||
|
this.inputs.splice(x, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.totalOutputs += input.length;
|
||||||
|
this.inputs = input;
|
||||||
|
|
||||||
|
this.recipeConfig = recipeConfig;
|
||||||
|
this.options = options;
|
||||||
|
this.progress = progress;
|
||||||
|
this.step = step;
|
||||||
|
|
||||||
|
for (let i = 0; i < this.maxWorkers; i++) {
|
||||||
|
const workerIdx = this.addChefWorker();
|
||||||
|
if (workerIdx === -1) break;
|
||||||
|
this.bakeNextInput(workerIdx);
|
||||||
|
}
|
||||||
|
this.displayProgress();
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
for (let i = 0; i < input.length; i++) {
|
||||||
this.totalOutputs++;
|
this.totalOutputs++;
|
||||||
this.manager.output.updateOutputStatus("pending", input[i].inputNum);
|
this.manager.output.updateOutputStatus("pending", input[i].inputNum);
|
||||||
@ -469,6 +507,12 @@ class WorkerWaiter {
|
|||||||
|
|
||||||
bakeInfo.innerHTML = msg;
|
bakeInfo.innerHTML = msg;
|
||||||
|
|
||||||
|
if (progress.total !== progress.baked) {
|
||||||
|
setTimeout(function() {
|
||||||
|
this.displayProgress();
|
||||||
|
}.bind(this), 100);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user