Change baking to send all inputs individually.

Re-enable go to tab button.
Active tab is now autobaked on load completion.
Handle (ish) loaderWorker errors.
Improve load performance.
This commit is contained in:
j433866 2019-04-26 15:15:44 +01:00
parent f638bd4ded
commit 1cf83c2485
6 changed files with 206 additions and 154 deletions

View file

@ -120,7 +120,6 @@ class App {
*
* @param {boolean} [step] - Set to true if we should only execute one operation instead of the
* whole recipe.
* @param input - The inputs to bake
*/
bake(step=false, input) {
// if (this.baking) return;
@ -132,7 +131,6 @@ class App {
this.manager.recipe.updateBreakpointIndicator(false);
this.manager.worker.bake(
input, // The user's input
this.getRecipeConfig(), // The configuration of the recipe
this.options, // Options set by the user
this.progress, // The current position in the recipe

View file

@ -215,9 +215,6 @@ class InputWaiter {
case "terminateLoaderWorker":
this.removeLoaderWorker(this.getLoaderWorker(r.data));
break;
case "allInputs":
this.app.bake(false, r.data);
break;
case "refreshTabs":
this.refreshTabs(r.data.nums, r.data.activeTab);
break;
@ -234,7 +231,7 @@ class InputWaiter {
this.showLoadingInfo(r.data);
break;
case "setInput":
this.set(r.data, true);
this.set(r.data.inputObj, r.data.silent);
break;
case "inputAdded":
this.inputAdded(r.data.changeTab, r.data.inputNum);
@ -242,6 +239,12 @@ class InputWaiter {
case "addInputs":
this.addInputs(r.data);
break;
case "queueInput":
this.manager.worker.queueInput(r.data);
break;
case "bake":
this.app.bake(false);
break;
default:
log.error(`Unknown action ${r.action}.`);
}
@ -281,10 +284,11 @@ class InputWaiter {
* @param {boolean} [silent=false]
*/
set(inputData, silent=false) {
const inputText = document.getElementById("input-text");
const activeTab = this.getActiveTab();
if (inputData.inputNum !== activeTab) return;
const inputText = document.getElementById("input-text");
if (typeof inputData.input === "string") {
inputText.value = inputData.input;
// close file
@ -370,16 +374,19 @@ class InputWaiter {
fileLoaded.textContent = progress + "%";
if (progress < 100) {
// setTimeout(function() {
// this.inputWorker.postMessage({
// action: "getInputProgress",
// data: activeTab
// });
// }.bind(this), 100);
setTimeout(function() {
this.inputWorker.postMessage({
action: "getInputProgress",
data: activeTab
});
}.bind(this), 100);
} else {
this.inputWorker.postMessage({
action: "setInput",
data: inputNum
data: {
inputNum: inputNum,
silent: true
}
});
}
}
@ -531,21 +538,35 @@ class InputWaiter {
}
/**
* Load files from the UI into the inputWorker, creating tabs if needed
* Load files from the UI into the inputWorker
*
* @param files
*/
loadUIFiles(files) {
const numFiles = files.length;
const activeTab = this.getActiveTab();
log.debug(`Loading ${numFiles} files.`);
// Show something in the UI to make it clear we're loading files
this.inputWorker.postMessage({
action: "loadUIFiles",
data: files
this.hideLoadingMessage();
this.showLoadingInfo({
pending: numFiles,
loading: 0,
loaded: 0,
total: numFiles,
activeProgress: {
inputNum: activeTab,
progress: 0
}
});
this.hideLoadingMessage();
this.inputWorker.postMessage({
action: "loadUIFiles",
data: {
files: files,
activeTab: activeTab
}
});
}
/**
@ -601,7 +622,14 @@ class InputWaiter {
// setinputInfo
/**
* Display the loaded files information in the input header
* @param loadedData
* @param {object} loadedData
* @param {number} loadedData.pending
* @param {number} loadedData.loading
* @param {number} loadedData.loaded
* @param {number} loadedData.total
* @param {object} loadedData.activeProgress
* @param {number} loadedData.activeProgress.inputNum
* @param {number} loadedData.activeProgress.progress
*/
showLoadingInfo(loadedData) {
const pending = loadedData.pending;
@ -629,6 +657,15 @@ class InputWaiter {
document.getElementById("input-files-info").innerHTML = msg;
this.updateFileProgress(loadedData.activeProgress.inputNum, loadedData.activeProgress.progress);
if (loaded < total) {
setTimeout(function() {
this.inputWorker.postMessage({
action: "getLoadProgress",
data: this.getActiveTab()
});
}.bind(this), 100);
}
}
// displayTabInfo
// simple getInput for each tab
@ -754,7 +791,10 @@ class InputWaiter {
} else {
this.inputWorker.postMessage({
action: "setInput",
data: inputNum
data: {
inputNum: inputNum,
silent: true
}
});
}
@ -890,10 +930,19 @@ class InputWaiter {
* @param {array} inputNums
*/
addInputs(inputNums) {
const activeTab = this.getActiveTab();
for (let i = 0; i < inputNums.length; i++) {
if (inputNums[i] === activeTab) continue;
this.manager.output.addOutput(inputNums[i], false);
}
this.changeTab(inputNums[inputNums.length - 1], this.app.options.syncTabs);
// this.changeTab(inputNums[inputNums.length - 1], this.app.options.syncTabs);
this.inputWorker.postMessage({
action: "refreshTabs",
data: {
inputNum: this.getActiveTab(),
direction: "left"
}
});
}
/**
@ -959,6 +1008,14 @@ class InputWaiter {
}
});
}
/**
* Handler for go to tab button clicked
*/
goToTab() {
const tabNum = parseInt(window.prompt("Enter tab number:", this.getActiveTab().toString()), 10);
this.changeTab(tabNum, this.app.options.syncTabs);
}
}
export default InputWaiter;

View file

@ -13,6 +13,9 @@ self.pendingFiles = [];
self.inputs = {};
self.loaderWorkerPorts = [];
self.currentInputNum = 1;
self.numInputs = 0;
self.pendingInputs = 0;
self.loadingInputs = 0;
/**
* Respond to message from parent thread.
@ -82,21 +85,10 @@ self.addEventListener("message", function(e) {
});
self.getLoadProgress = function(inputNum) {
const inputNums = Object.keys(self.inputs);
const total = inputNums.length;
const total = self.numInputs;
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++;
}
}
const loading = self.loadingInputs;
const loaded = total - pending - loading;
self.postMessage({
action: "loadingInfo",
@ -111,12 +103,6 @@ self.getLoadProgress = function(inputNum) {
}
}
});
if (loaded < total) {
setTimeout(function(inputNum) {
self.getLoadProgress(inputNum);
}, 100);
}
};
self.autoBake = function(inputNum) {
@ -127,17 +113,19 @@ self.autoBake = function(inputNum) {
inputData = inputData.fileBuffer;
}
self.postMessage({
action: "allInputs",
data: [{
action: "queueInput",
data: {
input: inputData,
inputNum: parseInt(inputNum, 10)
}]
}
});
self.postMessage({
action: "bake"
});
}
};
self.getAllInputs = function() {
const inputs = [];
const inputNums = Object.keys(self.inputs);
for (let i = 0; i < inputNums.length; i++) {
@ -146,16 +134,17 @@ self.getAllInputs = function() {
if (typeof inputData !== "string") {
inputData = inputData.fileBuffer;
}
inputs.push({
self.postMessage({
action: "queueInput",
data: {
input: inputData,
inputNum: inputNums[i]
}
});
}
}
self.postMessage({
action: "allInputs",
data: inputs
action: "bake"
});
};
@ -165,15 +154,11 @@ self.getInputObj = function(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;
}
if (self.inputs[inputNum]) {
if (typeof self.inputs[inputNum].data === "string") {
return self.inputs[inputNum].data;
} else {
return self.inputs[inputNum].fileBuffer;
}
}
return "";
@ -308,7 +293,9 @@ self.updateTabHeader = function(inputNum) {
});
};
self.setInput = function(inputNum) {
self.setInput = function(inputData) {
const inputNum = inputData.inputNum;
const silent = inputData.silent;
const input = self.getInputObj(inputNum);
if (input === undefined || input === null) return;
@ -327,7 +314,10 @@ self.setInput = function(inputNum) {
self.postMessage({
action: "setInput",
data: inputObj
data: {
inputObj: inputObj,
silent: silent
}
});
self.getInputProgress(inputNum);
};
@ -426,12 +416,29 @@ self.handleLoaderMessage = function(e) {
inputNum = r.inputNum;
}
if (r.hasOwnProperty("error")) {
self.updateInputStatus(r.inputNum, "error");
self.updateInputProgress(r.inputNum, 0);
log.error(r.error);
self.loadingInputs--;
self.terminateLoaderWorker(r.id);
self.activateLoaderWorker();
return;
}
if (r.hasOwnProperty("fileBuffer")) {
log.debug(`Input file ${inputNum} loaded.`);
self.loadingInputs--;
self.updateInputValue({
inputNum: inputNum,
value: r.fileBuffer
});
self.setInput({inputNum: inputNum, silent: false});
const idx = self.getLoaderWorkerIdx(r.id);
self.loadNextFile(idx);
} else if (r.hasOwnProperty("progress")) {
@ -450,6 +457,7 @@ self.loadNextFile = function(workerIdx) {
const nextFile = self.pendingFiles.splice(0, 1)[0];
self.loaderWorkerPorts[workerIdx].inputNum = nextFile.inputNum;
self.loadingInputs++;
port.postMessage({
action: "loadInput",
data: {
@ -484,16 +492,31 @@ self.terminateLoaderWorker = function(id) {
/**
* Loads files using LoaderWorkers
*
* @param {object} filesData
* @param filesData.files
* @param {number} filesData.activeTab
*/
self.loadFiles = function(files) {
self.loadFiles = function(filesData) {
const files = filesData.files;
const activeTab = filesData.activeTab;
let lastInputNum = -1;
const inputNums = [];
for (let i = 0; i < files.length; i++) {
if (i === 0 && self.getInputValue(activeTab) === "") {
self.removeInput(activeTab);
lastInputNum = self.addInput(false, "file", {
name: files[i].name,
size: files[i].size.toLocaleString(),
type: files[i].type || "unknown"
}, activeTab);
} else {
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({
@ -526,9 +549,10 @@ self.loadFiles = function(files) {
* @param {string} fileData.name
* @param {string} fileData.size
* @param {string} fileData.type
* @param {number} inputNum
*/
self.addInput = function(changeTab=false, type, fileData={name: "unknown", size: "unknown", type: "unknown"}) {
const inputNum = self.currentInputNum++;
self.addInput = function(changeTab=false, type, fileData={name: "unknown", size: "unknown", type: "unknown"}, inputNum = self.currentInputNum++) {
self.numInputs++;
const newInputObj = {
inputNum: inputNum
};
@ -571,15 +595,24 @@ self.addInput = function(changeTab=false, type, fileData={name: "unknown", size:
self.removeInput = function(removeInputData) {
const inputNum = removeInputData.inputNum;
const refreshTabs = removeInputData.refreshTabs;
self.numInputs--;
delete self.inputs[inputNum];
for (let i = 0; i < self.loaderWorkerPorts.length; i++) {
if (self.loaderWorkerPorts[i].inputNum === inputNum) {
self.loadingInputs--;
self.terminateLoaderWorker(self.loaderWorkerPorts[i].id);
}
}
for (let i = 0; i < self.pendingFiles.length; i++) {
if (self.pendingFiles[i].inputNum === inputNum) {
self.pendingFiles.splice(i, 1);
break;
}
}
if (refreshTabs) {
self.refreshTabs(inputNum, "left");
}

View file

@ -160,7 +160,7 @@ class Manager {
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-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 .input-tab-content", "click", this.input.changeTabClick, this.input);

View file

@ -27,6 +27,7 @@ class OutputWaiter {
this.manager = manager;
this.outputs = {};
this.activeTab = -1;
this.maxTabs = 4; // Calculate this
}
@ -466,6 +467,7 @@ class OutputWaiter {
for (let i = 0; i < tabs.length; i++) {
if (tabs.item(i).getAttribute("inputNum") === inputNum.toString()) {
tabs.item(i).classList.add("active-output-tab");
this.activeTab = inputNum;
found = true;
} else {
tabs.item(i).classList.remove("active-output-tab");
@ -482,6 +484,7 @@ class OutputWaiter {
tabs.item(i).setAttribute("inputNum", newOutputs[i].toString());
this.displayTabInfo(newOutputs[i]);
if (newOutputs[i] === inputNum) {
this.activeTab = inputNum;
tabs.item(i).classList.add("active-output-tab");
}
}
@ -740,13 +743,7 @@ class OutputWaiter {
* @returns {number}
*/
getActiveTab() {
const activeTabs = document.getElementsByClassName("active-output-tab");
if (activeTabs.length > 0) {
const activeTab = activeTabs.item(0);
const tabNum = activeTab.getAttribute("inputNum");
return parseInt(tabNum, 10);
}
return -1;
return this.activeTab;
}
/**

View file

@ -310,10 +310,12 @@ class WorkerWaiter {
this.chefWorkers[workerIdx].inputNum = nextInput.inputNum;
this.chefWorkers[workerIdx].active = true;
const input = nextInput.input;
if (typeof input === "string") {
this.chefWorkers[workerIdx].worker.postMessage({
action: "bake",
data: {
input: nextInput.input,
input: input,
recipeConfig: this.recipeConfig,
options: this.options,
progress: this.progress,
@ -321,42 +323,33 @@ class WorkerWaiter {
inputNum: nextInput.inputNum
}
});
} else {
this.chefWorkers[workerIdx].worker.postMessage({
action: "bake",
data: {
input: input,
recipeConfig: this.recipeConfig,
options: this.options,
progress: this.progress,
step: this.step,
inputNum: nextInput.inputNum
}
}, [nextInput.input]);
}
}
/**
* Bakes the current input using the current recipe.
*
* @param {string | Array} input
* @param {Object[]} recipeConfig
* @param {Object} options
* @param {number} progress
* @param {boolean} step
*/
bake(input, recipeConfig, options, progress, step) {
bake(recipeConfig, options, progress, step) {
this.setBakingStatus(true);
this.bakeStartTime = new Date().getTime();
if (typeof input === "string") {
input = [{
input: input,
inputNum: this.manager.input.getActiveTab()
}];
}
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;
@ -368,49 +361,20 @@ class WorkerWaiter {
this.bakeNextInput(workerIdx);
}
this.displayProgress();
return;
}
/**
* Queues an input ready to be baked
*
* @param {object} inputData
* @param {string | ArrayBuffer} inputData.input
* @param {number} inputData.inputNum
*/
queueInput(inputData) {
this.manager.output.updateOutputStatus("pending", inputData.inputNum);
for (let i = 0; i < input.length; i++) {
this.totalOutputs++;
this.manager.output.updateOutputStatus("pending", input[i].inputNum);
this.manager.output.updateOutputMessage(`Input ${input[i].inputNum} has not been baked yet.`, input[i].inputNum);
// If an input exists for the current inputNum, remove it
for (let x = 0; x < this.inputs.length; x++) {
if (this.inputs[x].inputNum === input[i].inputNum) {
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",
data: {
input: input[i].input,
recipeConfig: recipeConfig,
options: options,
progress: progress,
step: step,
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,
progress: progress,
step: step,
inputNum: input[i].inputNum
});
}
}
this.inputs.push(inputData);
}
/**
@ -474,6 +438,9 @@ class WorkerWaiter {
*/
displayProgress() {
const progress = this.getBakeProgress();
if (progress.total === progress.baked) return;
const percentComplete = ((progress.pending + progress.baking) / progress.total) * 100;
const bakeButton = document.getElementById("bake");
if (this.app.baking) {