2019-04-25 17:32:48 +02:00
|
|
|
/**
|
2019-07-03 11:34:15 +02:00
|
|
|
* Web worker to handle the inputs.
|
|
|
|
* Handles storage, modification and retrieval of the inputs.
|
2019-04-25 17:32:48 +02:00
|
|
|
*
|
|
|
|
* @author j433866 [j433866@gmail.com]
|
2022-09-02 13:56:04 +02:00
|
|
|
* @author n1474335 [n1474335@gmail.com]
|
2019-04-25 17:32:48 +02:00
|
|
|
* @copyright Crown Copyright 2019
|
|
|
|
* @license Apache-2.0
|
|
|
|
*/
|
|
|
|
|
2019-07-09 13:23:59 +02:00
|
|
|
import Utils from "../../core/Utils.mjs";
|
2019-04-25 17:32:48 +02:00
|
|
|
|
2019-07-03 12:53:38 +02:00
|
|
|
// Default max values
|
|
|
|
// These will be correctly calculated automatically
|
2019-04-25 17:32:48 +02:00
|
|
|
self.maxWorkers = 4;
|
|
|
|
self.maxTabs = 1;
|
2019-07-03 12:53:38 +02:00
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
self.pendingFiles = [];
|
2022-09-02 13:56:04 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Dictionary of inputs keyed on the inputNum
|
|
|
|
* Each entry is an object with the following type:
|
|
|
|
* @typedef {Object} Input
|
|
|
|
* @property {string} type
|
|
|
|
* @property {ArrayBuffer} buffer
|
|
|
|
* @property {string} stringSample
|
|
|
|
* @property {Object} file
|
|
|
|
* @property {string} file.name
|
|
|
|
* @property {number} file.size
|
|
|
|
* @property {string} file.type
|
|
|
|
* @property {string} status
|
|
|
|
* @property {number} progress
|
2022-10-21 19:29:52 +02:00
|
|
|
* @property {number} encoding
|
2022-10-28 13:24:16 +02:00
|
|
|
* @property {string} eolSequence
|
2022-09-02 13:56:04 +02:00
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.inputs = {};
|
2019-05-01 15:12:36 +02:00
|
|
|
self.loaderWorkers = [];
|
2019-04-25 17:32:48 +02:00
|
|
|
self.currentInputNum = 1;
|
2019-04-26 16:15:44 +02:00
|
|
|
self.numInputs = 0;
|
|
|
|
self.pendingInputs = 0;
|
|
|
|
self.loadingInputs = 0;
|
2019-04-25 17:32:48 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to message from parent thread.
|
2019-05-14 17:13:36 +02:00
|
|
|
*
|
|
|
|
* @param {MessageEvent} e
|
2019-04-25 17:32:48 +02:00
|
|
|
*/
|
|
|
|
self.addEventListener("message", function(e) {
|
|
|
|
const r = e.data;
|
2019-07-05 13:36:15 +02:00
|
|
|
if (!("action" in r)) {
|
2019-04-25 17:32:48 +02:00
|
|
|
log.error("No action");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-05-02 12:29:54 +02:00
|
|
|
log.debug(`Receiving ${r.action} from InputWaiter.`);
|
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
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":
|
2019-05-29 14:25:12 +02:00
|
|
|
self.updateMaxTabs(r.data.maxTabs, r.data.activeTab);
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
|
|
|
case "updateInputValue":
|
|
|
|
self.updateInputValue(r.data);
|
|
|
|
break;
|
|
|
|
case "updateInputProgress":
|
|
|
|
self.updateInputProgress(r.data);
|
|
|
|
break;
|
2019-05-14 17:13:36 +02:00
|
|
|
case "bakeAll":
|
|
|
|
self.bakeAllInputs();
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
2019-05-20 17:53:56 +02:00
|
|
|
case "bakeNext":
|
|
|
|
self.bakeInput(r.data.inputNum, r.data.bakeId);
|
|
|
|
break;
|
2019-04-25 17:32:48 +02:00
|
|
|
case "getLoadProgress":
|
|
|
|
self.getLoadProgress(r.data);
|
|
|
|
break;
|
|
|
|
case "setInput":
|
|
|
|
self.setInput(r.data);
|
|
|
|
break;
|
|
|
|
case "setLogLevel":
|
|
|
|
log.setLevel(r.data, false);
|
|
|
|
break;
|
|
|
|
case "addInput":
|
2022-09-02 13:56:04 +02:00
|
|
|
self.addInput(r.data, "userinput");
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
|
|
|
case "refreshTabs":
|
|
|
|
self.refreshTabs(r.data.inputNum, r.data.direction);
|
|
|
|
break;
|
|
|
|
case "removeInput":
|
|
|
|
self.removeInput(r.data);
|
|
|
|
break;
|
|
|
|
case "changeTabRight":
|
2019-06-06 17:33:35 +02:00
|
|
|
self.changeTabRight(r.data.activeTab);
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
|
|
|
case "changeTabLeft":
|
2019-06-06 17:33:35 +02:00
|
|
|
self.changeTabLeft(r.data.activeTab);
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
|
|
|
case "autobake":
|
2019-06-04 15:02:45 +02:00
|
|
|
self.autoBake(r.data.activeTab, 0, false);
|
2019-04-25 17:32:48 +02:00
|
|
|
break;
|
2019-04-30 15:15:05 +02:00
|
|
|
case "filterTabs":
|
|
|
|
self.filterTabs(r.data);
|
|
|
|
break;
|
2019-05-01 15:12:36 +02:00
|
|
|
case "loaderWorkerMessage":
|
|
|
|
self.handleLoaderMessage(r.data);
|
|
|
|
break;
|
2019-05-08 17:44:11 +02:00
|
|
|
case "updateTabHeader":
|
|
|
|
self.updateTabHeader(r.data);
|
|
|
|
break;
|
2019-05-16 11:42:07 +02:00
|
|
|
case "step":
|
2019-06-04 15:02:45 +02:00
|
|
|
self.autoBake(r.data.activeTab, r.data.progress, true);
|
2019-05-16 11:42:07 +02:00
|
|
|
break;
|
2019-05-28 12:59:57 +02:00
|
|
|
case "getInput":
|
|
|
|
self.getInput(r.data);
|
|
|
|
break;
|
2019-06-04 10:36:50 +02:00
|
|
|
case "getInputNums":
|
|
|
|
self.getInputNums(r.data);
|
|
|
|
break;
|
2019-04-25 17:32:48 +02:00
|
|
|
default:
|
|
|
|
log.error(`Unknown action '${r.action}'.`);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the load progress of the input files, and the
|
|
|
|
* load progress for the input given in inputNum
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The input to get the file loading progress for
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.getLoadProgress = function(inputNum) {
|
2019-04-26 16:15:44 +02:00
|
|
|
const total = self.numInputs;
|
2019-04-25 17:32:48 +02:00
|
|
|
const pending = self.pendingFiles.length;
|
2019-04-26 16:15:44 +02:00
|
|
|
const loading = self.loadingInputs;
|
|
|
|
const loaded = total - pending - loading;
|
2019-04-25 17:32:48 +02:00
|
|
|
|
|
|
|
self.postMessage({
|
|
|
|
action: "loadingInfo",
|
|
|
|
data: {
|
|
|
|
pending: pending,
|
|
|
|
loading: loading,
|
|
|
|
loaded: loaded,
|
|
|
|
total: total,
|
|
|
|
activeProgress: {
|
|
|
|
inputNum: inputNum,
|
|
|
|
progress: self.getInputProgress(inputNum)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Fired when an autobake is initiated.
|
|
|
|
* Queues the active input and sends a bake command.
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The input to be baked
|
2019-06-04 15:02:45 +02:00
|
|
|
* @param {number} progress - The current progress of the bake through the recipe
|
2019-05-16 11:42:07 +02:00
|
|
|
* @param {boolean} [step=false] - Set to true if we should only execute one operation instead of the
|
|
|
|
* whole recipe
|
2019-05-14 17:13:36 +02:00
|
|
|
*/
|
2019-06-04 15:02:45 +02:00
|
|
|
self.autoBake = function(inputNum, progress, step=false) {
|
2019-04-25 17:32:48 +02:00
|
|
|
const input = self.getInputObj(inputNum);
|
|
|
|
if (input) {
|
|
|
|
self.postMessage({
|
2019-05-20 17:53:56 +02:00
|
|
|
action: "bakeAllInputs",
|
2019-04-26 16:15:44 +02:00
|
|
|
data: {
|
2019-05-20 17:53:56 +02:00
|
|
|
nums: [parseInt(inputNum, 10)],
|
2019-06-04 15:02:45 +02:00
|
|
|
step: step,
|
|
|
|
progress: progress
|
2019-04-26 16:15:44 +02:00
|
|
|
}
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Fired when we want to bake all inputs (bake button clicked)
|
2019-05-20 17:53:56 +02:00
|
|
|
* Sends a list of inputNums to the workerwaiter
|
2019-05-14 17:13:36 +02:00
|
|
|
*/
|
|
|
|
self.bakeAllInputs = function() {
|
2019-05-20 17:53:56 +02:00
|
|
|
const inputNums = Object.keys(self.inputs),
|
|
|
|
nums = [];
|
2019-04-25 17:32:48 +02:00
|
|
|
|
|
|
|
for (let i = 0; i < inputNums.length; i++) {
|
|
|
|
if (self.inputs[inputNums[i]].status === "loaded") {
|
2019-05-20 17:53:56 +02:00
|
|
|
nums.push(parseInt(inputNums[i], 10));
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
self.postMessage({
|
2019-05-20 17:53:56 +02:00
|
|
|
action: "bakeAllInputs",
|
|
|
|
data: {
|
|
|
|
nums: nums,
|
2019-06-04 15:02:45 +02:00
|
|
|
step: false,
|
|
|
|
progress: 0
|
2019-05-20 17:53:56 +02:00
|
|
|
}
|
2019-04-25 17:32:48 +02:00
|
|
|
});
|
2019-05-20 17:53:56 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets the data for the provided inputNum and sends it to the WorkerWaiter
|
|
|
|
*
|
|
|
|
* @param {number} inputNum
|
|
|
|
* @param {number} bakeId
|
|
|
|
*/
|
|
|
|
self.bakeInput = function(inputNum, bakeId) {
|
|
|
|
const inputObj = self.getInputObj(inputNum);
|
2019-05-29 15:08:37 +02:00
|
|
|
if (inputObj === null ||
|
|
|
|
inputObj === undefined ||
|
|
|
|
inputObj.status !== "loaded") {
|
2019-08-22 12:53:41 +02:00
|
|
|
|
2019-05-29 15:08:37 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "queueInputError",
|
|
|
|
data: {
|
|
|
|
inputNum: inputNum,
|
|
|
|
bakeId: bakeId
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2019-05-20 17:53:56 +02:00
|
|
|
|
|
|
|
self.postMessage({
|
|
|
|
action: "queueInput",
|
|
|
|
data: {
|
2022-09-02 13:56:04 +02:00
|
|
|
input: inputObj.buffer,
|
2019-05-20 17:53:56 +02:00
|
|
|
inputNum: inputNum,
|
|
|
|
bakeId: bakeId
|
|
|
|
}
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the stored object for a specific inputNum
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The input we want to get the object for
|
|
|
|
* @returns {object}
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.getInputObj = function(inputNum) {
|
|
|
|
return self.inputs[inputNum];
|
|
|
|
};
|
|
|
|
|
2019-05-28 12:59:57 +02:00
|
|
|
/**
|
2019-07-03 12:53:38 +02:00
|
|
|
* Gets the stored value or object for a specific inputNum and sends it to the inputWaiter.
|
2019-05-28 12:59:57 +02:00
|
|
|
*
|
|
|
|
* @param {object} inputData - Object containing data about the input to retrieve
|
|
|
|
* @param {number} inputData.inputNum - The inputNum of the input to get
|
|
|
|
* @param {boolean} inputData.getObj - If true, returns the entire input object instead of just the value
|
|
|
|
* @param {number} inputData.id - The callback ID for the callback to run when returned to the inputWaiter
|
|
|
|
*/
|
|
|
|
self.getInput = function(inputData) {
|
2019-06-04 10:36:50 +02:00
|
|
|
const inputNum = inputData.inputNum,
|
2022-09-02 13:56:04 +02:00
|
|
|
data = (inputData.getObj) ? self.getInputObj(inputNum) : self.inputs[inputNum].buffer;
|
2019-06-04 10:36:50 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "getInput",
|
|
|
|
data: {
|
|
|
|
data: data,
|
|
|
|
id: inputData.id
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a list of the stored inputNums, along with the minimum and maximum
|
|
|
|
*
|
|
|
|
* @param {number} id - The callback ID to be executed when returned to the inputWaiter
|
|
|
|
*/
|
|
|
|
self.getInputNums = function(id) {
|
|
|
|
const inputNums = Object.keys(self.inputs),
|
|
|
|
min = self.getSmallestInputNum(inputNums),
|
|
|
|
max = self.getLargestInputNum(inputNums);
|
|
|
|
|
|
|
|
self.postMessage({
|
|
|
|
action: "getInputNums",
|
|
|
|
data: {
|
|
|
|
inputNums: inputNums,
|
|
|
|
min: min,
|
|
|
|
max: max,
|
|
|
|
id: id
|
|
|
|
}
|
|
|
|
});
|
2019-05-28 12:59:57 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the load progress for a specific inputNum
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The input we want to get the progress of
|
|
|
|
* @returns {number | string} - Returns "error" if there was a load error
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.getInputProgress = function(inputNum) {
|
|
|
|
const inputObj = self.getInputObj(inputNum);
|
|
|
|
if (inputObj === undefined || inputObj === null) return;
|
2019-05-08 17:44:11 +02:00
|
|
|
if (inputObj.status === "error") {
|
|
|
|
return "error";
|
|
|
|
}
|
2019-04-25 17:32:48 +02:00
|
|
|
return inputObj.progress;
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the largest inputNum of all the inputs
|
|
|
|
*
|
2019-06-03 14:48:49 +02:00
|
|
|
* @param {string[]} inputNums - The numbers to find the largest of
|
2019-05-14 17:13:36 +02:00
|
|
|
* @returns {number}
|
|
|
|
*/
|
2019-06-03 14:48:49 +02:00
|
|
|
self.getLargestInputNum = function(inputNums) {
|
2019-07-03 17:05:20 +02:00
|
|
|
return inputNums.reduce((acc, val) => {
|
|
|
|
val = parseInt(val, 10);
|
|
|
|
return val > acc ? val : acc;
|
|
|
|
}, -1);
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the smallest inputNum of all the inputs
|
|
|
|
*
|
2019-06-03 14:48:49 +02:00
|
|
|
* @param {string[]} inputNums - The numbers to find the smallest of
|
2019-05-14 17:13:36 +02:00
|
|
|
* @returns {number}
|
|
|
|
*/
|
2019-06-03 14:48:49 +02:00
|
|
|
self.getSmallestInputNum = function(inputNums) {
|
2019-07-03 17:05:20 +02:00
|
|
|
const min = inputNums.reduce((acc, val) => {
|
|
|
|
val = parseInt(val, 10);
|
|
|
|
return val < acc ? val : acc;
|
|
|
|
}, Number.MAX_SAFE_INTEGER);
|
2019-06-03 14:48:49 +02:00
|
|
|
|
|
|
|
// Assume we don't have this many tabs!
|
|
|
|
if (min === Number.MAX_SAFE_INTEGER) return -1;
|
|
|
|
|
|
|
|
return min;
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2019-05-14 17:13:36 +02:00
|
|
|
* Gets the next smallest inputNum
|
2019-04-25 17:32:48 +02:00
|
|
|
*
|
|
|
|
* @param {number} inputNum - The current input number
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
self.getPreviousInputNum = function(inputNum) {
|
|
|
|
const inputNums = Object.keys(self.inputs);
|
2019-05-29 14:25:12 +02:00
|
|
|
if (inputNums.length === 0) return -1;
|
2019-07-03 17:09:48 +02:00
|
|
|
|
|
|
|
return inputNums.reduce((acc, val) => {
|
|
|
|
val = parseInt(val, 10);
|
|
|
|
return (val < inputNum && val > acc) ? val : acc;
|
|
|
|
}, self.getSmallestInputNum(inputNums));
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2019-05-14 17:13:36 +02:00
|
|
|
* Gets the next largest inputNum
|
2019-04-25 17:32:48 +02:00
|
|
|
*
|
|
|
|
* @param {number} inputNum - The current input number
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
|
|
|
self.getNextInputNum = function(inputNum) {
|
|
|
|
const inputNums = Object.keys(self.inputs);
|
2019-07-03 17:09:48 +02:00
|
|
|
|
|
|
|
return inputNums.reduce((acc, val) => {
|
|
|
|
val = parseInt(val, 10);
|
|
|
|
return (val > inputNum && val < acc) ? val : acc;
|
|
|
|
}, self.getLargestInputNum(inputNums));
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets a list of inputNums starting from the provided inputNum.
|
|
|
|
* If direction is "left", gets the inputNums higher than the provided number.
|
|
|
|
* If direction is "right", gets the inputNums lower than the provided number.
|
|
|
|
* @param {number} inputNum - The inputNum we want to get the neighbours of
|
|
|
|
* @param {string} direction - Either "left" or "right". Determines which direction we search for nearby numbers in
|
|
|
|
* @returns {number[]}
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
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";
|
2019-05-14 17:13:36 +02:00
|
|
|
newNum = self.getPreviousInputNum(nums[0]);
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "right":
|
|
|
|
newNum = self.getPreviousInputNum(nums[i - 1]);
|
|
|
|
if (newNum === nums[i - 1]) {
|
|
|
|
direction = "left";
|
2019-05-14 17:13:36 +02:00
|
|
|
newNum = self.getNextInputNum(nums[0]);
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!nums.includes(newNum) && (newNum > 0)) {
|
|
|
|
nums.push(newNum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nums.sort(function(a, b) {
|
|
|
|
return a - b;
|
|
|
|
});
|
|
|
|
return nums;
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the data to display in the tab header for an input, and
|
|
|
|
* posts it back to the inputWaiter
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The inputNum of the tab header
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateTabHeader = function(inputNum) {
|
|
|
|
const input = self.getInputObj(inputNum);
|
|
|
|
if (input === null || input === undefined) return;
|
2022-09-02 13:56:04 +02:00
|
|
|
|
|
|
|
let header = input.type === "file" ? input.file.name : input.stringSample;
|
|
|
|
header = header.slice(0, 100).replace(/[\n\r]/g, "");
|
2019-06-10 14:08:03 +02:00
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "updateTabHeader",
|
|
|
|
data: {
|
|
|
|
inputNum: inputNum,
|
2022-09-02 13:56:04 +02:00
|
|
|
input: header
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the input for a specific inputNum, and posts it to the inputWaiter
|
|
|
|
* so that it can be displayed in the input area
|
|
|
|
*
|
|
|
|
* @param {object} inputData
|
|
|
|
* @param {number} inputData.inputNum - The input to get the data for
|
2019-08-22 12:53:41 +02:00
|
|
|
* @param {boolean} inputData.silent - If false, the manager statechange event will be fired
|
2019-05-14 17:13:36 +02:00
|
|
|
*/
|
2019-04-26 16:15:44 +02:00
|
|
|
self.setInput = function(inputData) {
|
2023-01-13 14:51:16 +01:00
|
|
|
const {inputNum, silent} = inputData;
|
2019-04-25 17:32:48 +02:00
|
|
|
const input = self.getInputObj(inputNum);
|
|
|
|
if (input === undefined || input === null) return;
|
|
|
|
|
2022-09-02 13:56:04 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "setInput",
|
|
|
|
data: {
|
|
|
|
inputNum: inputNum,
|
|
|
|
inputObj: input,
|
|
|
|
silent: silent
|
|
|
|
}
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
|
2019-05-08 17:44:11 +02:00
|
|
|
self.updateTabHeader(inputNum);
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Gets the nearby inputNums to the provided number, and posts them
|
|
|
|
* to the inputWaiter to be displayed on the page.
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The inputNum to find the nearby numbers for
|
|
|
|
* @param {string} direction - The direction to search for inputNums in. Either "left" or "right"
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.refreshTabs = function(inputNum, direction) {
|
2019-06-03 14:48:49 +02:00
|
|
|
const nums = self.getNearbyNums(inputNum, direction),
|
|
|
|
inputNums = Object.keys(self.inputs),
|
2019-07-24 15:22:56 +02:00
|
|
|
tabsLeft = (self.getSmallestInputNum(inputNums) !== nums[0] && nums.length > 0),
|
|
|
|
tabsRight = (self.getLargestInputNum(inputNums) !== nums[nums.length - 1] && nums.length > 0);
|
2019-06-03 14:48:49 +02:00
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "refreshTabs",
|
|
|
|
data: {
|
|
|
|
nums: nums,
|
2019-05-29 17:29:34 +02:00
|
|
|
activeTab: (nums.includes(inputNum)) ? inputNum : self.getNextInputNum(inputNum),
|
|
|
|
tabsLeft: tabsLeft,
|
|
|
|
tabsRight: tabsRight
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
// Update the tab headers for the new tabs
|
2019-04-25 17:32:48 +02:00
|
|
|
for (let i = 0; i < nums.length; i++) {
|
|
|
|
self.updateTabHeader(nums[i]);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Update the stored status for an input
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The input that's having its status changed
|
|
|
|
* @param {string} status - The status of the input
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateInputStatus = function(inputNum, status) {
|
2019-05-08 17:44:11 +02:00
|
|
|
if (self.inputs[inputNum] !== undefined) {
|
|
|
|
self.inputs[inputNum].status = status;
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Update the stored load progress of an input
|
|
|
|
*
|
|
|
|
* @param {object} inputData
|
|
|
|
* @param {number} inputData.inputNum - The input that's having its progress updated
|
|
|
|
* @param {number} inputData.progress - The load progress of the input
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateInputProgress = function(inputData) {
|
|
|
|
const inputNum = inputData.inputNum;
|
|
|
|
const progress = inputData.progress;
|
|
|
|
|
|
|
|
if (self.inputs[inputNum] !== undefined) {
|
|
|
|
self.inputs[inputNum].progress = progress;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Update the stored value of an input.
|
|
|
|
*
|
|
|
|
* @param {object} inputData
|
|
|
|
* @param {number} inputData.inputNum - The input that's having its value updated
|
2022-09-02 13:56:04 +02:00
|
|
|
* @param {ArrayBuffer} inputData.buffer - The new value of the input as a buffer
|
2022-10-21 19:29:52 +02:00
|
|
|
* @param {number} [inputData.encoding] - The character encoding of the input data
|
2022-10-28 13:24:16 +02:00
|
|
|
* @param {string} [inputData.eolSequence] - The end of line sequence of the input data
|
2022-09-02 13:56:04 +02:00
|
|
|
* @param {string} [inputData.stringSample] - A sample of the value as a string (truncated to 4096 chars)
|
2019-05-14 17:13:36 +02:00
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateInputValue = function(inputData) {
|
2022-09-02 13:56:04 +02:00
|
|
|
const inputNum = parseInt(inputData.inputNum, 10);
|
2019-04-25 17:32:48 +02:00
|
|
|
if (inputNum < 1) return;
|
|
|
|
|
2022-09-02 13:56:04 +02:00
|
|
|
if (!Object.prototype.hasOwnProperty.call(self.inputs, inputNum))
|
|
|
|
throw new Error(`No input with ID ${inputNum} exists`);
|
2019-05-07 16:34:36 +02:00
|
|
|
|
2022-09-02 13:56:04 +02:00
|
|
|
self.inputs[inputNum].buffer = inputData.buffer;
|
2022-10-21 19:29:52 +02:00
|
|
|
if ("encoding" in inputData) {
|
|
|
|
self.inputs[inputNum].encoding = inputData.encoding;
|
|
|
|
}
|
2022-10-28 13:24:16 +02:00
|
|
|
if ("eolSequence" in inputData) {
|
|
|
|
self.inputs[inputNum].eolSequence = inputData.eolSequence;
|
|
|
|
}
|
2022-09-02 13:56:04 +02:00
|
|
|
if (!("stringSample" in inputData)) {
|
|
|
|
inputData.stringSample = Utils.arrayBufferToStr(inputData.buffer.slice(0, 4096));
|
|
|
|
}
|
|
|
|
self.inputs[inputNum].stringSample = inputData.stringSample;
|
|
|
|
self.inputs[inputNum].status = "loaded";
|
|
|
|
self.inputs[inputNum].progress = 100;
|
2019-05-07 16:34:36 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Get the index of a loader worker object.
|
|
|
|
* Returns -1 if the worker could not be found
|
|
|
|
*
|
|
|
|
* @param {number} workerId - The ID of the worker we're searching for
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.getLoaderWorkerIdx = function(workerId) {
|
2019-05-01 15:12:36 +02:00
|
|
|
for (let i = 0; i < self.loaderWorkers.length; i++) {
|
|
|
|
if (self.loaderWorkers[i].id === workerId) {
|
2019-04-25 17:32:48 +02:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Fires when a loaderWorker is ready to load files.
|
|
|
|
* Stores data about the new loaderWorker in the loaderWorkers array,
|
|
|
|
* and sends the next file to the loaderWorker to be loaded.
|
|
|
|
*
|
|
|
|
* @param {object} workerData
|
|
|
|
* @param {number} workerData.id - The ID of the new loaderWorker
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.loaderWorkerReady = function(workerData) {
|
|
|
|
const newWorkerObj = {
|
|
|
|
id: workerData.id,
|
|
|
|
inputNum: -1,
|
|
|
|
active: true
|
|
|
|
};
|
2019-05-01 15:12:36 +02:00
|
|
|
self.loaderWorkers.push(newWorkerObj);
|
|
|
|
self.loadNextFile(self.loaderWorkers.indexOf(newWorkerObj));
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Handler for messages sent by loaderWorkers.
|
2022-09-02 13:56:04 +02:00
|
|
|
* (Messages are sent between the inputWorker and loaderWorkers via the main thread)
|
2019-05-14 17:13:36 +02:00
|
|
|
*
|
|
|
|
* @param {object} r - The data sent by the loaderWorker
|
|
|
|
* @param {number} r.inputNum - The inputNum which the message corresponds to
|
|
|
|
* @param {string} r.error - Present if an error is fired by the loaderWorker. Contains the error message string.
|
|
|
|
* @param {ArrayBuffer} r.fileBuffer - Present if a file has finished loading. Contains the loaded file buffer.
|
|
|
|
*/
|
2019-05-01 15:12:36 +02:00
|
|
|
self.handleLoaderMessage = function(r) {
|
2019-04-25 17:32:48 +02:00
|
|
|
let inputNum = 0;
|
|
|
|
|
2019-07-05 13:36:15 +02:00
|
|
|
if ("inputNum" in r) {
|
2019-04-25 17:32:48 +02:00
|
|
|
inputNum = r.inputNum;
|
|
|
|
}
|
|
|
|
|
2019-07-05 13:36:15 +02:00
|
|
|
if ("error" in r) {
|
2019-04-26 16:15:44 +02:00
|
|
|
self.updateInputProgress(r.inputNum, 0);
|
2019-05-08 17:44:11 +02:00
|
|
|
self.updateInputStatus(r.inputNum, "error");
|
2019-04-26 16:15:44 +02:00
|
|
|
|
|
|
|
log.error(r.error);
|
|
|
|
self.loadingInputs--;
|
|
|
|
|
|
|
|
self.terminateLoaderWorker(r.id);
|
|
|
|
self.activateLoaderWorker();
|
|
|
|
|
2019-05-08 17:44:11 +02:00
|
|
|
self.setInput({inputNum: inputNum, silent: true});
|
2019-04-26 16:15:44 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-07-05 13:36:15 +02:00
|
|
|
if ("fileBuffer" in r) {
|
2019-04-25 17:32:48 +02:00
|
|
|
log.debug(`Input file ${inputNum} loaded.`);
|
2019-04-26 16:15:44 +02:00
|
|
|
self.loadingInputs--;
|
2019-08-22 12:53:41 +02:00
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateInputValue({
|
|
|
|
inputNum: inputNum,
|
2022-09-02 13:56:04 +02:00
|
|
|
buffer: r.fileBuffer
|
2019-04-25 17:32:48 +02:00
|
|
|
});
|
2019-04-26 16:15:44 +02:00
|
|
|
|
2019-08-22 12:53:41 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "fileLoaded",
|
|
|
|
data: {
|
|
|
|
inputNum: inputNum
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
const idx = self.getLoaderWorkerIdx(r.id);
|
|
|
|
self.loadNextFile(idx);
|
2019-07-05 13:36:15 +02:00
|
|
|
} else if ("progress" in r) {
|
2019-04-25 17:32:48 +02:00
|
|
|
self.updateInputProgress(r);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Loads the next file using a loaderWorker
|
|
|
|
*
|
|
|
|
* @param {number} - The loaderWorker which will load the file
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.loadNextFile = function(workerIdx) {
|
2019-05-01 15:12:36 +02:00
|
|
|
if (workerIdx === -1) return;
|
|
|
|
const id = self.loaderWorkers[workerIdx].id;
|
2019-04-25 17:32:48 +02:00
|
|
|
if (self.pendingFiles.length === 0) {
|
2019-05-01 15:12:36 +02:00
|
|
|
const workerObj = self.loaderWorkers.splice(workerIdx, 1)[0];
|
2019-04-25 17:32:48 +02:00
|
|
|
self.terminateLoaderWorker(workerObj.id);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const nextFile = self.pendingFiles.splice(0, 1)[0];
|
2019-05-01 15:12:36 +02:00
|
|
|
self.loaderWorkers[workerIdx].inputNum = nextFile.inputNum;
|
2019-04-26 16:15:44 +02:00
|
|
|
self.loadingInputs++;
|
2019-05-01 15:12:36 +02:00
|
|
|
self.postMessage({
|
2019-04-25 17:32:48 +02:00
|
|
|
action: "loadInput",
|
|
|
|
data: {
|
|
|
|
file: nextFile.file,
|
2019-05-01 15:12:36 +02:00
|
|
|
inputNum: nextFile.inputNum,
|
|
|
|
workerId: id
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Sends a message to the inputWaiter to create a new loaderWorker.
|
|
|
|
* If there's an inactive loaderWorker that already exists, use that instead.
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.activateLoaderWorker = function() {
|
2019-05-01 15:12:36 +02:00
|
|
|
for (let i = 0; i < self.loaderWorkers.length; i++) {
|
|
|
|
if (!self.loaderWorkers[i].active) {
|
|
|
|
self.loaderWorkers[i].active = true;
|
2019-04-25 17:32:48 +02:00
|
|
|
self.loadNextFile(i);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
self.postMessage({
|
|
|
|
action: "activateLoaderWorker"
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Sends a message to the inputWaiter to terminate a loaderWorker.
|
|
|
|
*
|
|
|
|
* @param {number} id - The ID of the worker to be terminated
|
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.terminateLoaderWorker = function(id) {
|
|
|
|
self.postMessage({
|
|
|
|
action: "terminateLoaderWorker",
|
|
|
|
data: id
|
|
|
|
});
|
2019-05-14 17:13:36 +02:00
|
|
|
// If we still have pending files, spawn a worker
|
2019-04-25 17:32:48 +02:00
|
|
|
if (self.pendingFiles.length > 0) {
|
|
|
|
self.activateLoaderWorker();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Loads files using LoaderWorkers
|
2019-04-26 16:15:44 +02:00
|
|
|
*
|
|
|
|
* @param {object} filesData
|
2019-05-14 17:13:36 +02:00
|
|
|
* @param {FileList} filesData.files - The list of files to be loaded
|
|
|
|
* @param {number} filesData.activeTab - The active tab in the UI
|
2019-04-25 17:32:48 +02:00
|
|
|
*/
|
2019-04-26 16:15:44 +02:00
|
|
|
self.loadFiles = function(filesData) {
|
2023-01-13 14:51:16 +01:00
|
|
|
const {files, activeTab} = filesData;
|
2019-04-25 17:32:48 +02:00
|
|
|
let lastInputNum = -1;
|
|
|
|
const inputNums = [];
|
|
|
|
for (let i = 0; i < files.length; i++) {
|
2022-09-02 13:56:04 +02:00
|
|
|
// If the first input is empty, replace it rather than adding a new one
|
|
|
|
if (i === 0 && (!self.inputs[activeTab].buffer || self.inputs[activeTab].buffer.byteLength === 0)) {
|
2019-05-28 15:11:05 +02:00
|
|
|
self.removeInput({
|
|
|
|
inputNum: activeTab,
|
|
|
|
refreshTabs: false,
|
|
|
|
removeChefWorker: false
|
|
|
|
});
|
2019-04-26 16:15:44 +02:00
|
|
|
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"
|
|
|
|
});
|
|
|
|
}
|
2019-04-25 17:32:48 +02:00
|
|
|
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;
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
// Create loaderWorkers to load the new files
|
2019-04-25 17:32:48 +02:00
|
|
|
for (let i = 0; i < max; i++) {
|
|
|
|
self.activateLoaderWorker();
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getLoadProgress();
|
2023-01-13 14:51:16 +01:00
|
|
|
self.setInput({inputNum: lastInputNum, silent: true});
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2019-05-14 17:13:36 +02:00
|
|
|
* Adds an input to the input dictionary
|
2019-04-25 17:32:48 +02:00
|
|
|
*
|
2019-05-10 14:47:48 +02:00
|
|
|
* @param {boolean} [changetab=false] - Whether or not to change to the new input
|
2022-09-02 13:56:04 +02:00
|
|
|
* @param {string} type - Either "userinput" or "file"
|
2019-05-14 17:13:36 +02:00
|
|
|
* @param {Object} fileData - Contains information about the file to be added to the input (only used when type is "file")
|
|
|
|
* @param {string} fileData.name - The filename of the input being added
|
|
|
|
* @param {number} fileData.size - The file size (in bytes) of the input being added
|
|
|
|
* @param {string} fileData.type - The MIME type of the input being added
|
2019-05-10 14:47:48 +02:00
|
|
|
* @param {number} inputNum - Defaults to auto-incrementing self.currentInputNum
|
2019-04-25 17:32:48 +02:00
|
|
|
*/
|
2019-07-03 17:15:14 +02:00
|
|
|
self.addInput = function(
|
|
|
|
changeTab = false,
|
|
|
|
type,
|
|
|
|
fileData = {
|
|
|
|
name: "unknown",
|
2022-09-02 13:56:04 +02:00
|
|
|
size: 0,
|
2019-07-03 17:15:14 +02:00
|
|
|
type: "unknown"
|
|
|
|
},
|
|
|
|
inputNum = self.currentInputNum++
|
|
|
|
) {
|
2019-04-26 16:15:44 +02:00
|
|
|
self.numInputs++;
|
2019-04-25 17:32:48 +02:00
|
|
|
const newInputObj = {
|
2022-09-02 13:56:04 +02:00
|
|
|
type: null,
|
|
|
|
buffer: new ArrayBuffer(),
|
|
|
|
stringSample: "",
|
|
|
|
file: null,
|
|
|
|
status: "pending",
|
2022-10-21 19:29:52 +02:00
|
|
|
progress: 0,
|
2022-10-28 13:24:16 +02:00
|
|
|
encoding: 0,
|
|
|
|
eolSequence: "\u000a"
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
switch (type) {
|
2022-09-02 13:56:04 +02:00
|
|
|
case "userinput":
|
|
|
|
newInputObj.type = "userinput";
|
2019-04-25 17:32:48 +02:00
|
|
|
newInputObj.status = "loaded";
|
|
|
|
newInputObj.progress = 100;
|
|
|
|
break;
|
|
|
|
case "file":
|
2022-09-02 13:56:04 +02:00
|
|
|
newInputObj.type = "file";
|
|
|
|
newInputObj.file = {
|
2019-04-25 17:32:48 +02:00
|
|
|
name: fileData.name,
|
|
|
|
size: fileData.size,
|
|
|
|
type: fileData.type
|
|
|
|
};
|
|
|
|
newInputObj.status = "pending";
|
|
|
|
newInputObj.progress = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2022-09-02 13:56:04 +02:00
|
|
|
log.error(`Invalid input type '${type}'.`);
|
2019-04-25 17:32:48 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
self.inputs[inputNum] = newInputObj;
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
// Tell the inputWaiter we've added an input, so it can create a tab to display it
|
2019-05-08 15:47:05 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "inputAdded",
|
|
|
|
data: {
|
|
|
|
changeTab: changeTab,
|
|
|
|
inputNum: inputNum
|
|
|
|
}
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
|
|
|
|
return inputNum;
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Remove an input from the inputs dictionary
|
|
|
|
*
|
|
|
|
* @param {object} removeInputData
|
|
|
|
* @param {number} removeInputData.inputNum - The number of the input to be removed
|
|
|
|
* @param {boolean} removeInputData.refreshTabs - If true, refresh the tabs after removing the input
|
2019-05-28 15:11:05 +02:00
|
|
|
* @param {boolean} removeInputData.removeChefWorker - If true, remove a chefWorker from the WorkerWaiter
|
2019-05-14 17:13:36 +02:00
|
|
|
*/
|
2019-04-25 17:32:48 +02:00
|
|
|
self.removeInput = function(removeInputData) {
|
|
|
|
const inputNum = removeInputData.inputNum;
|
|
|
|
const refreshTabs = removeInputData.refreshTabs;
|
2019-04-26 16:15:44 +02:00
|
|
|
self.numInputs--;
|
2019-04-25 17:32:48 +02:00
|
|
|
|
2019-05-01 15:12:36 +02:00
|
|
|
for (let i = 0; i < self.loaderWorkers.length; i++) {
|
|
|
|
if (self.loaderWorkers[i].inputNum === inputNum) {
|
2019-05-14 17:13:36 +02:00
|
|
|
// Terminate any loaderWorker that's loading the removed input
|
2019-04-26 16:15:44 +02:00
|
|
|
self.loadingInputs--;
|
2019-05-01 15:12:36 +02:00
|
|
|
self.terminateLoaderWorker(self.loaderWorkers[i].id);
|
2019-05-14 17:13:36 +02:00
|
|
|
break;
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-26 16:15:44 +02:00
|
|
|
for (let i = 0; i < self.pendingFiles.length; i++) {
|
2019-05-14 17:13:36 +02:00
|
|
|
// Remove the input from the pending files list
|
2019-04-26 16:15:44 +02:00
|
|
|
if (self.pendingFiles[i].inputNum === inputNum) {
|
|
|
|
self.pendingFiles.splice(i, 1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
delete self.inputs[inputNum];
|
|
|
|
|
2019-04-25 17:32:48 +02:00
|
|
|
if (refreshTabs) {
|
2019-06-07 14:52:04 +02:00
|
|
|
self.refreshTabs(self.getPreviousInputNum(inputNum), "left");
|
2019-04-25 17:32:48 +02:00
|
|
|
}
|
2019-05-28 15:11:05 +02:00
|
|
|
|
|
|
|
if (self.numInputs < self.maxWorkers && removeInputData.removeChefWorker) {
|
|
|
|
self.postMessage({
|
|
|
|
action: "removeChefWorker"
|
|
|
|
});
|
|
|
|
}
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Change to the next tab.
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The inputNum of the tab to change to
|
|
|
|
*/
|
2019-06-06 17:33:35 +02:00
|
|
|
self.changeTabRight = function(inputNum) {
|
2019-04-25 17:32:48 +02:00
|
|
|
const newInput = self.getNextInputNum(inputNum);
|
2019-06-06 17:33:35 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "changeTab",
|
|
|
|
data: newInput
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Change to the previous tab.
|
|
|
|
*
|
|
|
|
* @param {number} inputNum - The inputNum of the tab to change to
|
|
|
|
*/
|
2019-06-06 17:33:35 +02:00
|
|
|
self.changeTabLeft = function(inputNum) {
|
2019-04-25 17:32:48 +02:00
|
|
|
const newInput = self.getPreviousInputNum(inputNum);
|
2019-06-06 17:33:35 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "changeTab",
|
|
|
|
data: newInput
|
|
|
|
});
|
2019-04-25 17:32:48 +02:00
|
|
|
};
|
2019-04-30 15:15:05 +02:00
|
|
|
|
2019-05-29 14:25:12 +02:00
|
|
|
/**
|
|
|
|
* Updates the maximum number of tabs, and refreshes them if it changes
|
|
|
|
*
|
|
|
|
* @param {number} maxTabs - The new max number of tabs
|
|
|
|
* @param {number} activeTab - The currently selected tab
|
|
|
|
*/
|
|
|
|
self.updateMaxTabs = function(maxTabs, activeTab) {
|
|
|
|
if (self.maxTabs !== maxTabs) {
|
|
|
|
self.maxTabs = maxTabs;
|
|
|
|
self.refreshTabs(activeTab, "right");
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
/**
|
|
|
|
* Search the inputs for any that match the filters provided,
|
|
|
|
* posting the results back to the inputWaiter
|
|
|
|
*
|
|
|
|
* @param {object} searchData - Object containing the search filters
|
|
|
|
* @param {boolean} searchData.showPending - If true, include pending inputs in the results
|
|
|
|
* @param {boolean} searchData.showLoading - If true, include loading inputs in the results
|
|
|
|
* @param {boolean} searchData.showLoaded - If true, include loaded inputs in the results
|
2019-05-30 14:28:45 +02:00
|
|
|
* @param {string} searchData.filter - A regular expression to match the inputs on
|
2019-10-16 16:38:20 +02:00
|
|
|
* @param {string} searchData.filterType - Either "CONTENT" or "FILENAME". Determines what should be matched with filter
|
2019-05-14 17:13:36 +02:00
|
|
|
* @param {number} searchData.numResults - The maximum number of results to be returned
|
|
|
|
*/
|
2019-04-30 15:15:05 +02:00
|
|
|
self.filterTabs = function(searchData) {
|
2019-05-30 14:28:45 +02:00
|
|
|
const showPending = searchData.showPending,
|
|
|
|
showLoading = searchData.showLoading,
|
|
|
|
showLoaded = searchData.showLoaded,
|
|
|
|
filterType = searchData.filterType;
|
|
|
|
|
|
|
|
let filterExp;
|
|
|
|
try {
|
|
|
|
filterExp = new RegExp(searchData.filter, "i");
|
|
|
|
} catch (error) {
|
|
|
|
self.postMessage({
|
|
|
|
action: "filterTabError",
|
|
|
|
data: error.message
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
2019-04-30 15:15:05 +02:00
|
|
|
const numResults = searchData.numResults;
|
|
|
|
|
|
|
|
const inputs = [];
|
|
|
|
const inputNums = Object.keys(self.inputs);
|
|
|
|
for (let i = 0; i < inputNums.length; i++) {
|
|
|
|
const iNum = inputNums[i];
|
|
|
|
let textDisplay = "";
|
|
|
|
let addInput = false;
|
|
|
|
if (self.inputs[iNum].status === "pending" && showPending ||
|
|
|
|
self.inputs[iNum].status === "loading" && showLoading ||
|
|
|
|
self.inputs[iNum].status === "loaded" && showLoaded) {
|
2019-05-30 14:28:45 +02:00
|
|
|
try {
|
2022-09-02 13:56:04 +02:00
|
|
|
if (self.inputs[iNum].type === "userinput") {
|
2019-05-30 14:28:45 +02:00
|
|
|
if (filterType.toLowerCase() === "content" &&
|
2022-09-02 13:56:04 +02:00
|
|
|
filterExp.test(self.inputs[iNum].stringSample)) {
|
|
|
|
textDisplay = self.inputs[iNum].stringSample;
|
2019-05-30 14:28:45 +02:00
|
|
|
addInput = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if ((filterType.toLowerCase() === "filename" &&
|
2022-09-02 13:56:04 +02:00
|
|
|
filterExp.test(self.inputs[iNum].file.name)) ||
|
|
|
|
(filterType.toLowerCase() === "content" &&
|
|
|
|
filterExp.test(self.inputs[iNum].stringSample))) {
|
|
|
|
textDisplay = self.inputs[iNum].file.name;
|
2019-05-30 14:28:45 +02:00
|
|
|
addInput = true;
|
|
|
|
}
|
2019-04-30 15:15:05 +02:00
|
|
|
}
|
2019-05-30 14:28:45 +02:00
|
|
|
} catch (error) {
|
|
|
|
self.postMessage({
|
|
|
|
action: "filterTabError",
|
|
|
|
data: error.message
|
|
|
|
});
|
|
|
|
return;
|
2019-04-30 15:15:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (addInput) {
|
|
|
|
if (textDisplay === "" || textDisplay === undefined) {
|
|
|
|
textDisplay = "New Tab";
|
|
|
|
}
|
|
|
|
const inputItem = {
|
|
|
|
inputNum: iNum,
|
|
|
|
textDisplay: textDisplay
|
|
|
|
};
|
|
|
|
inputs.push(inputItem);
|
|
|
|
}
|
|
|
|
if (inputs.length >= numResults) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-14 17:13:36 +02:00
|
|
|
// Send the results back to the inputWaiter
|
2019-04-30 15:15:05 +02:00
|
|
|
self.postMessage({
|
|
|
|
action: "displayTabSearchResults",
|
|
|
|
data: inputs
|
|
|
|
});
|
2019-04-30 15:45:34 +02:00
|
|
|
};
|