mirror of
https://github.com/gchq/CyberChef.git
synced 2025-04-21 15:26:16 -04:00
Merge branch 'j433866-carriage-returns'
This commit is contained in:
commit
9e1079027b
8 changed files with 445 additions and 266 deletions
|
@ -670,18 +670,22 @@ class App {
|
||||||
*
|
*
|
||||||
* @param {string} title - The title of the box
|
* @param {string} title - The title of the box
|
||||||
* @param {string} body - The question (HTML supported)
|
* @param {string} body - The question (HTML supported)
|
||||||
|
* @param {string} accept - The text of the accept button
|
||||||
|
* @param {string} reject - The text of the reject button
|
||||||
* @param {function} callback - A function accepting one boolean argument which handles the
|
* @param {function} callback - A function accepting one boolean argument which handles the
|
||||||
* response e.g. function(answer) {...}
|
* response e.g. function(answer) {...}
|
||||||
* @param {Object} [scope=this] - The object to bind to the callback function
|
* @param {Object} [scope=this] - The object to bind to the callback function
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* // Pops up a box asking if the user would like a cookie. Prints the answer to the console.
|
* // Pops up a box asking if the user would like a cookie. Prints the answer to the console.
|
||||||
* this.confirm("Question", "Would you like a cookie?", function(answer) {console.log(answer);});
|
* this.confirm("Question", "Would you like a cookie?", "Yes", "No", function(answer) {console.log(answer);});
|
||||||
*/
|
*/
|
||||||
confirm(title, body, callback, scope) {
|
confirm(title, body, accept, reject, callback, scope) {
|
||||||
scope = scope || this;
|
scope = scope || this;
|
||||||
document.getElementById("confirm-title").innerHTML = title;
|
document.getElementById("confirm-title").innerHTML = title;
|
||||||
document.getElementById("confirm-body").innerHTML = body;
|
document.getElementById("confirm-body").innerHTML = body;
|
||||||
|
document.getElementById("confirm-yes").innerText = accept;
|
||||||
|
document.getElementById("confirm-no").innerText = reject;
|
||||||
document.getElementById("confirm-modal").style.display = "block";
|
document.getElementById("confirm-modal").style.display = "block";
|
||||||
|
|
||||||
this.confirmClosed = false;
|
this.confirmClosed = false;
|
||||||
|
@ -694,9 +698,14 @@ class App {
|
||||||
callback.bind(scope)(true);
|
callback.bind(scope)(true);
|
||||||
$("#confirm-modal").modal("hide");
|
$("#confirm-modal").modal("hide");
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
.one("click", "#confirm-no", function() {
|
||||||
|
this.confirmClosed = true;
|
||||||
|
callback.bind(scope)(false);
|
||||||
|
}.bind(this))
|
||||||
.one("hide.bs.modal", function(e) {
|
.one("hide.bs.modal", function(e) {
|
||||||
if (!this.confirmClosed)
|
if (!this.confirmClosed) {
|
||||||
callback.bind(scope)(false);
|
callback.bind(scope)(undefined);
|
||||||
|
}
|
||||||
this.confirmClosed = true;
|
this.confirmClosed = true;
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,7 +224,7 @@ class Manager {
|
||||||
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));
|
document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));
|
||||||
document.getElementById("reset-options").addEventListener("click", this.options.resetOptionsClick.bind(this.options));
|
document.getElementById("reset-options").addEventListener("click", this.options.resetOptionsClick.bind(this.options));
|
||||||
this.addDynamicListener(".option-item input[type=checkbox]", "change", this.options.switchChange, this.options);
|
this.addDynamicListener(".option-item input[type=checkbox]", "change", this.options.switchChange, this.options);
|
||||||
this.addDynamicListener(".option-item input[type=checkbox]", "change", this.options.setWordWrap, this.options);
|
this.addDynamicListener(".option-item input[type=checkbox]#wordWrap", "change", this.options.setWordWrap, this.options);
|
||||||
this.addDynamicListener(".option-item input[type=checkbox]#useMetaKey", "change", this.bindings.updateKeybList, this.bindings);
|
this.addDynamicListener(".option-item input[type=checkbox]#useMetaKey", "change", this.bindings.updateKeybList, this.bindings);
|
||||||
this.addDynamicListener(".option-item input[type=number]", "keyup", this.options.numberChange, this.options);
|
this.addDynamicListener(".option-item input[type=number]", "keyup", this.options.numberChange, this.options);
|
||||||
this.addDynamicListener(".option-item input[type=number]", "change", this.options.numberChange, this.options);
|
this.addDynamicListener(".option-item input[type=number]", "change", this.options.numberChange, this.options);
|
||||||
|
|
|
@ -563,16 +563,23 @@
|
||||||
<div class="checkbox option-item">
|
<div class="checkbox option-item">
|
||||||
<label for="imagePreview">
|
<label for="imagePreview">
|
||||||
<input type="checkbox" option="imagePreview" id="imagePreview">
|
<input type="checkbox" option="imagePreview" id="imagePreview">
|
||||||
Render a preview of the input if it's detected to be an image.
|
Render a preview of the input if it's detected to be an image
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="checkbox option-item">
|
<div class="checkbox option-item">
|
||||||
<label for="syncTabs">
|
<label for="syncTabs">
|
||||||
<input type="checkbox" option="syncTabs" id="syncTabs">
|
<input type="checkbox" option="syncTabs" id="syncTabs">
|
||||||
Keep the current tab in sync between the input and output.
|
Keep the current tab in sync between the input and output
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="checkbox option-item">
|
||||||
|
<label for="preserveCR" data-toggle="tooltip" data-placement="right" data-html="true" title="As HTML textareas don't support carriage returns, editing input must be turned off to preserve them.<br><br>When this option is enabled, editing is disabled for pasted text that contains carriage returns. Otherwise, editing will remain enabled but carriage returns will not be preserved.">
|
||||||
|
<input type="checkbox" option="preserveCR" id="preserveCR">
|
||||||
|
Preserve carriage returns when pasting an input
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button type="button" class="btn btn-secondary" id="reset-options">Reset options to default</button>
|
<button type="button" class="btn btn-secondary" id="reset-options">Reset options to default</button>
|
||||||
|
|
|
@ -53,7 +53,9 @@ function main() {
|
||||||
logLevel: "info",
|
logLevel: "info",
|
||||||
autoMagic: true,
|
autoMagic: true,
|
||||||
imagePreview: true,
|
imagePreview: true,
|
||||||
syncTabs: true
|
syncTabs: true,
|
||||||
|
preserveCR: true,
|
||||||
|
userSetCR: false
|
||||||
};
|
};
|
||||||
|
|
||||||
document.removeEventListener("DOMContentLoaded", main, false);
|
document.removeEventListener("DOMContentLoaded", main, false);
|
||||||
|
|
|
@ -222,8 +222,6 @@ class InputWaiter {
|
||||||
if (Object.prototype.hasOwnProperty.call(r, "progress") &&
|
if (Object.prototype.hasOwnProperty.call(r, "progress") &&
|
||||||
Object.prototype.hasOwnProperty.call(r, "inputNum")) {
|
Object.prototype.hasOwnProperty.call(r, "inputNum")) {
|
||||||
this.manager.tabs.updateInputTabProgress(r.inputNum, r.progress, 100);
|
this.manager.tabs.updateInputTabProgress(r.inputNum, r.progress, 100);
|
||||||
} else if (Object.prototype.hasOwnProperty.call(r, "fileBuffer")) {
|
|
||||||
this.manager.tabs.updateInputTabProgress(r.inputNum, 100, 100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const transferable = Object.prototype.hasOwnProperty.call(r, "fileBuffer") ? [r.fileBuffer] : undefined;
|
const transferable = Object.prototype.hasOwnProperty.call(r, "fileBuffer") ? [r.fileBuffer] : undefined;
|
||||||
|
@ -305,6 +303,9 @@ class InputWaiter {
|
||||||
case "removeChefWorker":
|
case "removeChefWorker":
|
||||||
this.removeChefWorker();
|
this.removeChefWorker();
|
||||||
break;
|
break;
|
||||||
|
case "fileLoaded":
|
||||||
|
this.fileLoaded(r.data.inputNum);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
log.error(`Unknown action ${r.action}.`);
|
log.error(`Unknown action ${r.action}.`);
|
||||||
}
|
}
|
||||||
|
@ -331,7 +332,7 @@ class InputWaiter {
|
||||||
* @param {number} inputData.size - The size in bytes of the input file
|
* @param {number} inputData.size - The size in bytes of the input file
|
||||||
* @param {string} inputData.type - The MIME type of the input file
|
* @param {string} inputData.type - The MIME type of the input file
|
||||||
* @param {number} inputData.progress - The load progress of the input file
|
* @param {number} inputData.progress - The load progress of the input file
|
||||||
* @param {boolean} [silent=false] - If true, fires the manager statechange event
|
* @param {boolean} [silent=false] - If false, fires the manager statechange event
|
||||||
*/
|
*/
|
||||||
async set(inputData, silent=false) {
|
async set(inputData, silent=false) {
|
||||||
return new Promise(function(resolve, reject) {
|
return new Promise(function(resolve, reject) {
|
||||||
|
@ -373,7 +374,7 @@ class InputWaiter {
|
||||||
|
|
||||||
if (!silent) window.dispatchEvent(this.manager.statechange);
|
if (!silent) window.dispatchEvent(this.manager.statechange);
|
||||||
} else {
|
} else {
|
||||||
this.setFile(inputData);
|
this.setFile(inputData, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -389,8 +390,9 @@ class InputWaiter {
|
||||||
* @param {number} inputData.size - The size in bytes of the input file
|
* @param {number} inputData.size - The size in bytes of the input file
|
||||||
* @param {string} inputData.type - The MIME type of the input file
|
* @param {string} inputData.type - The MIME type of the input file
|
||||||
* @param {number} inputData.progress - The load progress of the input file
|
* @param {number} inputData.progress - The load progress of the input file
|
||||||
|
* @param {boolean} [silent=true] - If false, fires the manager statechange event
|
||||||
*/
|
*/
|
||||||
setFile(inputData) {
|
setFile(inputData, silent=true) {
|
||||||
const activeTab = this.manager.tabs.getActiveInputTab();
|
const activeTab = this.manager.tabs.getActiveInputTab();
|
||||||
if (inputData.inputNum !== activeTab) return;
|
if (inputData.inputNum !== activeTab) return;
|
||||||
|
|
||||||
|
@ -414,6 +416,30 @@ class InputWaiter {
|
||||||
|
|
||||||
this.setInputInfo(inputData.size, null);
|
this.setInputInfo(inputData.size, null);
|
||||||
this.displayFilePreview(inputData);
|
this.displayFilePreview(inputData);
|
||||||
|
|
||||||
|
if (!silent) window.dispatchEvent(this.manager.statechange);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update file details when a file completes loading
|
||||||
|
*
|
||||||
|
* @param {number} inputNum - The inputNum of the input which has finished loading
|
||||||
|
*/
|
||||||
|
fileLoaded(inputNum) {
|
||||||
|
this.manager.tabs.updateInputTabProgress(inputNum, 100, 100);
|
||||||
|
|
||||||
|
const activeTab = this.manager.tabs.getActiveInputTab();
|
||||||
|
if (activeTab !== inputNum) return;
|
||||||
|
|
||||||
|
this.inputWorker.postMessage({
|
||||||
|
action: "setInput",
|
||||||
|
data: {
|
||||||
|
inputNum: inputNum,
|
||||||
|
silent: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateFileProgress(inputNum, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -495,19 +521,6 @@ class InputWaiter {
|
||||||
fileLoaded.textContent = progress + "%";
|
fileLoaded.textContent = progress + "%";
|
||||||
fileLoaded.style.color = "";
|
fileLoaded.style.color = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress === 100 && progress !== oldProgress) {
|
|
||||||
// Don't set the input if the progress hasn't changed
|
|
||||||
this.inputWorker.postMessage({
|
|
||||||
action: "setInput",
|
|
||||||
data: {
|
|
||||||
inputNum: inputNum,
|
|
||||||
silent: false
|
|
||||||
}
|
|
||||||
});
|
|
||||||
window.dispatchEvent(this.manager.statechange);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -711,33 +724,50 @@ class InputWaiter {
|
||||||
*
|
*
|
||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
inputPaste(e) {
|
async inputPaste(e) {
|
||||||
const pastedData = e.clipboardData.getData("Text");
|
e.preventDefault();
|
||||||
if (pastedData.length < (this.app.options.ioDisplayThreshold * 1024)) {
|
e.stopPropagation();
|
||||||
// Pasting normally fires the inputChange() event before
|
|
||||||
// changing the value, so instead change it here ourselves
|
|
||||||
// and manually fire inputChange()
|
|
||||||
e.preventDefault();
|
|
||||||
const inputText = document.getElementById("input-text");
|
|
||||||
const selStart = inputText.selectionStart;
|
|
||||||
const selEnd = inputText.selectionEnd;
|
|
||||||
const startVal = inputText.value.slice(0, selStart);
|
|
||||||
const endVal = inputText.value.slice(selEnd);
|
|
||||||
|
|
||||||
inputText.value = startVal + pastedData + endVal;
|
|
||||||
inputText.setSelectionRange(selStart + pastedData.length, selStart + pastedData.length);
|
|
||||||
this.debounceInputChange(e);
|
|
||||||
} else {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
|
const self = this;
|
||||||
|
/**
|
||||||
|
* Triggers the input file/binary data overlay
|
||||||
|
*
|
||||||
|
* @param {string} pastedData
|
||||||
|
*/
|
||||||
|
function triggerOverlay(pastedData) {
|
||||||
const file = new File([pastedData], "PastedData", {
|
const file = new File([pastedData], "PastedData", {
|
||||||
type: "text/plain",
|
type: "text/plain",
|
||||||
lastModified: Date.now()
|
lastModified: Date.now()
|
||||||
});
|
});
|
||||||
|
|
||||||
this.loadUIFiles([file]);
|
self.loadUIFiles([file]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pastedData = e.clipboardData.getData("Text");
|
||||||
|
const inputText = document.getElementById("input-text");
|
||||||
|
const selStart = inputText.selectionStart;
|
||||||
|
const selEnd = inputText.selectionEnd;
|
||||||
|
const startVal = inputText.value.slice(0, selStart);
|
||||||
|
const endVal = inputText.value.slice(selEnd);
|
||||||
|
const val = startVal + pastedData + endVal;
|
||||||
|
|
||||||
|
if (val.length >= (this.app.options.ioDisplayThreshold * 1024)) {
|
||||||
|
// Data too large to display, use overlay
|
||||||
|
triggerOverlay(val);
|
||||||
return false;
|
return false;
|
||||||
|
} else if (await this.preserveCarriageReturns(val)) {
|
||||||
|
// Data contains a carriage return and the user doesn't wish to edit it, use overlay
|
||||||
|
// We check this in a separate condition to make sure it is not run unless absolutely
|
||||||
|
// necessary.
|
||||||
|
triggerOverlay(val);
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// Pasting normally fires the inputChange() event before
|
||||||
|
// changing the value, so instead change it here ourselves
|
||||||
|
// and manually fire inputChange()
|
||||||
|
inputText.value = val;
|
||||||
|
inputText.setSelectionRange(selStart + pastedData.length, selStart + pastedData.length);
|
||||||
|
this.debounceInputChange(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -815,6 +845,46 @@ class InputWaiter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an input contains carriage returns.
|
||||||
|
* If a CR is detected, checks if the preserve CR option has been set,
|
||||||
|
* and if not, asks the user for their preference.
|
||||||
|
*
|
||||||
|
* @param {string} input - The input to be checked
|
||||||
|
* @returns {boolean} - If true, the input contains a CR which should be
|
||||||
|
* preserved, so display an overlay so it can't be edited
|
||||||
|
*/
|
||||||
|
async preserveCarriageReturns(input) {
|
||||||
|
if (input.indexOf("\r") < 0) return false;
|
||||||
|
|
||||||
|
const optionsStr = "This behaviour can be changed in the <a href='#' onclick='document.getElementById(\"options\").click()'>Options pane</a>";
|
||||||
|
if (!this.app.options.userSetCR) {
|
||||||
|
// User has not set a CR preference yet
|
||||||
|
let preserve = await new Promise(function(resolve, reject) {
|
||||||
|
this.app.confirm(
|
||||||
|
"Carriage Return Detected",
|
||||||
|
"A <a href='https://wikipedia.org/wiki/Carriage_return'>carriage return</a> (<code>\\r</code>, <code>0x0d</code>) was detected in your input. As HTML textareas <a href='https://html.spec.whatwg.org/multipage/form-elements.html#the-textarea-element'>can't display carriage returns</a>, editing must be turned off to preserve them. <br>Alternatively, you can enable editing but your carriage returns will not be preserved.<br><br>This preference will be saved but can be toggled in the options pane.",
|
||||||
|
"Preserve Carriage Returns",
|
||||||
|
"Enable Editing", resolve, this);
|
||||||
|
}.bind(this));
|
||||||
|
if (preserve === undefined) {
|
||||||
|
// The confirm pane was closed without picking a specific choice
|
||||||
|
this.app.alert(`Not preserving carriage returns.\n${optionsStr}`, 5000);
|
||||||
|
preserve = false;
|
||||||
|
}
|
||||||
|
this.manager.options.updateOption("preserveCR", preserve);
|
||||||
|
this.manager.options.updateOption("userSetCR", true);
|
||||||
|
} else {
|
||||||
|
if (this.app.options.preserveCR) {
|
||||||
|
this.app.alert(`A carriage return (\\r, 0x0d) was detected in your input, so editing has been disabled to preserve it.<br>${optionsStr}`, 10000);
|
||||||
|
} else {
|
||||||
|
this.app.alert(`A carriage return (\\r, 0x0d) was detected in your input. Editing is remaining enabled, but carriage returns will not be preserved.<br>${optionsStr}`, 10000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.app.options.preserveCR;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load files from the UI into the inputWorker
|
* Load files from the UI into the inputWorker
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,174 +1,180 @@
|
||||||
/**
|
/**
|
||||||
* Waiter to handle events related to the CyberChef options.
|
|
||||||
*
|
|
||||||
* @author n1474335 [n1474335@gmail.com]
|
* @author n1474335 [n1474335@gmail.com]
|
||||||
* @copyright Crown Copyright 2016
|
* @copyright Crown Copyright 2016
|
||||||
* @license Apache-2.0
|
* @license Apache-2.0
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
* @param {App} app - The main view object for CyberChef.
|
|
||||||
*/
|
*/
|
||||||
const OptionsWaiter = function(app, manager) {
|
|
||||||
this.app = app;
|
|
||||||
this.manager = manager;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads options and sets values of switches and inputs to match them.
|
* Waiter to handle events related to the CyberChef options.
|
||||||
*
|
|
||||||
* @param {Object} options
|
|
||||||
*/
|
*/
|
||||||
OptionsWaiter.prototype.load = function(options) {
|
class OptionsWaiter {
|
||||||
for (const option in options) {
|
|
||||||
this.app.options[option] = options[option];
|
/**
|
||||||
|
* OptionsWaiter constructor.
|
||||||
|
*
|
||||||
|
* @param {App} app - The main view object for CyberChef.
|
||||||
|
* @param {Manager} manager - The CyberChef event manager.
|
||||||
|
*/
|
||||||
|
constructor(app, manager) {
|
||||||
|
this.app = app;
|
||||||
|
this.manager = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set options to match object
|
/**
|
||||||
const cboxes = document.querySelectorAll("#options-body input[type=checkbox]");
|
* Loads options and sets values of switches and inputs to match them.
|
||||||
let i;
|
*
|
||||||
for (i = 0; i < cboxes.length; i++) {
|
* @param {Object} options
|
||||||
cboxes[i].checked = this.app.options[cboxes[i].getAttribute("option")];
|
*/
|
||||||
}
|
load(options) {
|
||||||
|
for (const option in options) {
|
||||||
|
this.app.options[option] = options[option];
|
||||||
|
}
|
||||||
|
|
||||||
const nboxes = document.querySelectorAll("#options-body input[type=number]");
|
// Set options to match object
|
||||||
for (i = 0; i < nboxes.length; i++) {
|
const cboxes = document.querySelectorAll("#options-body input[type=checkbox]");
|
||||||
nboxes[i].value = this.app.options[nboxes[i].getAttribute("option")];
|
let i;
|
||||||
nboxes[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
|
for (i = 0; i < cboxes.length; i++) {
|
||||||
}
|
cboxes[i].checked = this.app.options[cboxes[i].getAttribute("option")];
|
||||||
|
}
|
||||||
|
|
||||||
const selects = document.querySelectorAll("#options-body select");
|
const nboxes = document.querySelectorAll("#options-body input[type=number]");
|
||||||
for (i = 0; i < selects.length; i++) {
|
for (i = 0; i < nboxes.length; i++) {
|
||||||
const val = this.app.options[selects[i].getAttribute("option")];
|
nboxes[i].value = this.app.options[nboxes[i].getAttribute("option")];
|
||||||
if (val) {
|
nboxes[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
|
||||||
selects[i].value = val;
|
}
|
||||||
selects[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
|
|
||||||
} else {
|
const selects = document.querySelectorAll("#options-body select");
|
||||||
selects[i].selectedIndex = 0;
|
for (i = 0; i < selects.length; i++) {
|
||||||
|
const val = this.app.options[selects[i].getAttribute("option")];
|
||||||
|
if (val) {
|
||||||
|
selects[i].value = val;
|
||||||
|
selects[i].dispatchEvent(new CustomEvent("change", {bubbles: true}));
|
||||||
|
} else {
|
||||||
|
selects[i].selectedIndex = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for options click events.
|
* Handler for options click events.
|
||||||
* Dispays the options pane.
|
* Dispays the options pane.
|
||||||
*
|
*
|
||||||
* @param {event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
OptionsWaiter.prototype.optionsClick = function(e) {
|
optionsClick(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
$("#options-modal").modal();
|
$("#options-modal").modal();
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for reset options click events.
|
|
||||||
* Resets options back to their default values.
|
|
||||||
*/
|
|
||||||
OptionsWaiter.prototype.resetOptionsClick = function() {
|
|
||||||
this.load(this.app.doptions);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for switch change events.
|
|
||||||
* Modifies the option state and saves it to local storage.
|
|
||||||
*
|
|
||||||
* @param {event} e
|
|
||||||
*/
|
|
||||||
OptionsWaiter.prototype.switchChange = function(e) {
|
|
||||||
const el = e.target;
|
|
||||||
const option = el.getAttribute("option");
|
|
||||||
const state = el.checked;
|
|
||||||
|
|
||||||
log.debug(`Setting ${option} to ${state}`);
|
|
||||||
this.app.options[option] = state;
|
|
||||||
|
|
||||||
if (this.app.isLocalStorageAvailable())
|
|
||||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for number change events.
|
|
||||||
* Modifies the option value and saves it to local storage.
|
|
||||||
*
|
|
||||||
* @param {event} e
|
|
||||||
*/
|
|
||||||
OptionsWaiter.prototype.numberChange = function(e) {
|
|
||||||
const el = e.target;
|
|
||||||
const option = el.getAttribute("option");
|
|
||||||
const val = parseInt(el.value, 10);
|
|
||||||
|
|
||||||
log.debug(`Setting ${option} to ${val}`);
|
|
||||||
this.app.options[option] = val;
|
|
||||||
|
|
||||||
if (this.app.isLocalStorageAvailable())
|
|
||||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for select change events.
|
|
||||||
* Modifies the option value and saves it to local storage.
|
|
||||||
*
|
|
||||||
* @param {event} e
|
|
||||||
*/
|
|
||||||
OptionsWaiter.prototype.selectChange = function(e) {
|
|
||||||
const el = e.target;
|
|
||||||
const option = el.getAttribute("option");
|
|
||||||
|
|
||||||
log.debug(`Setting ${option} to ${el.value}`);
|
|
||||||
this.app.options[option] = el.value;
|
|
||||||
|
|
||||||
if (this.app.isLocalStorageAvailable())
|
|
||||||
localStorage.setItem("options", JSON.stringify(this.app.options));
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets or unsets word wrap on the input and output depending on the wordWrap option value.
|
|
||||||
*/
|
|
||||||
OptionsWaiter.prototype.setWordWrap = function() {
|
|
||||||
document.getElementById("input-text").classList.remove("word-wrap");
|
|
||||||
document.getElementById("output-text").classList.remove("word-wrap");
|
|
||||||
document.getElementById("output-html").classList.remove("word-wrap");
|
|
||||||
document.getElementById("input-highlighter").classList.remove("word-wrap");
|
|
||||||
document.getElementById("output-highlighter").classList.remove("word-wrap");
|
|
||||||
|
|
||||||
if (!this.app.options.wordWrap) {
|
|
||||||
document.getElementById("input-text").classList.add("word-wrap");
|
|
||||||
document.getElementById("output-text").classList.add("word-wrap");
|
|
||||||
document.getElementById("output-html").classList.add("word-wrap");
|
|
||||||
document.getElementById("input-highlighter").classList.add("word-wrap");
|
|
||||||
document.getElementById("output-highlighter").classList.add("word-wrap");
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the theme by setting the class of the <html> element.
|
* Handler for reset options click events.
|
||||||
*
|
* Resets options back to their default values.
|
||||||
* @param {Event} e
|
*/
|
||||||
*/
|
resetOptionsClick() {
|
||||||
OptionsWaiter.prototype.themeChange = function (e) {
|
this.load(this.app.doptions);
|
||||||
const themeClass = e.target.value;
|
}
|
||||||
|
|
||||||
document.querySelector(":root").className = themeClass;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the console logging level.
|
* Handler for switch change events.
|
||||||
*
|
*
|
||||||
* @param {Event} e
|
* @param {event} e
|
||||||
*/
|
*/
|
||||||
OptionsWaiter.prototype.logLevelChange = function (e) {
|
switchChange(e) {
|
||||||
const level = e.target.value;
|
const el = e.target;
|
||||||
log.setLevel(level, false);
|
const option = el.getAttribute("option");
|
||||||
this.manager.worker.setLogLevel();
|
const state = el.checked;
|
||||||
this.manager.input.setLogLevel();
|
|
||||||
};
|
this.updateOption(option, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for number change events.
|
||||||
|
*
|
||||||
|
* @param {event} e
|
||||||
|
*/
|
||||||
|
numberChange(e) {
|
||||||
|
const el = e.target;
|
||||||
|
const option = el.getAttribute("option");
|
||||||
|
const val = parseInt(el.value, 10);
|
||||||
|
|
||||||
|
this.updateOption(option, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler for select change events.
|
||||||
|
*
|
||||||
|
* @param {event} e
|
||||||
|
*/
|
||||||
|
selectChange(e) {
|
||||||
|
const el = e.target;
|
||||||
|
const option = el.getAttribute("option");
|
||||||
|
|
||||||
|
this.updateOption(option, el.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies an option value and saves it to local storage.
|
||||||
|
*
|
||||||
|
* @param {string} option - The option to be updated
|
||||||
|
* @param {string|number|boolean} value - The new value of the option
|
||||||
|
*/
|
||||||
|
updateOption(option, value) {
|
||||||
|
log.debug(`Setting ${option} to ${value}`);
|
||||||
|
this.app.options[option] = value;
|
||||||
|
|
||||||
|
if (this.app.isLocalStorageAvailable())
|
||||||
|
localStorage.setItem("options", JSON.stringify(this.app.options));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets or unsets word wrap on the input and output depending on the wordWrap option value.
|
||||||
|
*/
|
||||||
|
setWordWrap() {
|
||||||
|
document.getElementById("input-text").classList.remove("word-wrap");
|
||||||
|
document.getElementById("output-text").classList.remove("word-wrap");
|
||||||
|
document.getElementById("output-html").classList.remove("word-wrap");
|
||||||
|
document.getElementById("input-highlighter").classList.remove("word-wrap");
|
||||||
|
document.getElementById("output-highlighter").classList.remove("word-wrap");
|
||||||
|
|
||||||
|
if (!this.app.options.wordWrap) {
|
||||||
|
document.getElementById("input-text").classList.add("word-wrap");
|
||||||
|
document.getElementById("output-text").classList.add("word-wrap");
|
||||||
|
document.getElementById("output-html").classList.add("word-wrap");
|
||||||
|
document.getElementById("input-highlighter").classList.add("word-wrap");
|
||||||
|
document.getElementById("output-highlighter").classList.add("word-wrap");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the theme by setting the class of the <html> element.
|
||||||
|
*
|
||||||
|
* @param {Event} e
|
||||||
|
*/
|
||||||
|
themeChange(e) {
|
||||||
|
const themeClass = e.target.value;
|
||||||
|
|
||||||
|
document.querySelector(":root").className = themeClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the console logging level.
|
||||||
|
*
|
||||||
|
* @param {Event} e
|
||||||
|
*/
|
||||||
|
logLevelChange(e) {
|
||||||
|
const level = e.target.value;
|
||||||
|
log.setLevel(level, false);
|
||||||
|
this.manager.worker.setLogLevel();
|
||||||
|
this.manager.input.setLogLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default OptionsWaiter;
|
export default OptionsWaiter;
|
||||||
|
|
|
@ -217,6 +217,9 @@ class OutputWaiter {
|
||||||
*/
|
*/
|
||||||
removeAllOutputs() {
|
removeAllOutputs() {
|
||||||
this.outputs = {};
|
this.outputs = {};
|
||||||
|
|
||||||
|
this.resetSwitch();
|
||||||
|
|
||||||
const tabsList = document.getElementById("output-tabs");
|
const tabsList = document.getElementById("output-tabs");
|
||||||
const tabsListChildren = tabsList.children;
|
const tabsListChildren = tabsList.children;
|
||||||
|
|
||||||
|
@ -516,9 +519,10 @@ class OutputWaiter {
|
||||||
this.app.alert("Could not find any output data to download. Has this output been baked?", 3000);
|
this.app.alert("Could not find any output data to download. Has this output been baked?", 3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let fileName = window.prompt("Please enter a filename: ", "download.dat");
|
const fileName = window.prompt("Please enter a filename: ", "download.dat");
|
||||||
|
|
||||||
if (fileName === null) fileName = "download.dat";
|
// Assume if the user clicks cancel they don't want to download
|
||||||
|
if (fileName === null) return;
|
||||||
|
|
||||||
const data = await dish.get(Dish.ARRAY_BUFFER),
|
const data = await dish.get(Dish.ARRAY_BUFFER),
|
||||||
file = new File([data], fileName);
|
file = new File([data], fileName);
|
||||||
|
@ -529,12 +533,22 @@ class OutputWaiter {
|
||||||
* Handler for save all click event
|
* Handler for save all click event
|
||||||
* Saves all outputs to a single archvie file
|
* Saves all outputs to a single archvie file
|
||||||
*/
|
*/
|
||||||
saveAllClick() {
|
async saveAllClick() {
|
||||||
const downloadButton = document.getElementById("save-all-to-file");
|
const downloadButton = document.getElementById("save-all-to-file");
|
||||||
if (downloadButton.firstElementChild.innerHTML === "archive") {
|
if (downloadButton.firstElementChild.innerHTML === "archive") {
|
||||||
this.downloadAllFiles();
|
this.downloadAllFiles();
|
||||||
} else if (window.confirm("Cancel zipping of outputs?")) {
|
} else {
|
||||||
this.terminateZipWorker();
|
const cancel = await new Promise(function(resolve, reject) {
|
||||||
|
this.app.confirm(
|
||||||
|
"Cancel zipping?",
|
||||||
|
"The outputs are currently being zipped for download.<br>Cancel zipping?",
|
||||||
|
"Continue zipping",
|
||||||
|
"Cancel zipping",
|
||||||
|
resolve, this);
|
||||||
|
}.bind(this));
|
||||||
|
if (!cancel) {
|
||||||
|
this.terminateZipWorker();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,57 +558,61 @@ class OutputWaiter {
|
||||||
* be zipped for download
|
* be zipped for download
|
||||||
*/
|
*/
|
||||||
async downloadAllFiles() {
|
async downloadAllFiles() {
|
||||||
return new Promise(resolve => {
|
const inputNums = Object.keys(this.outputs);
|
||||||
const inputNums = Object.keys(this.outputs);
|
for (let i = 0; i < inputNums.length; i++) {
|
||||||
for (let i = 0; i < inputNums.length; i++) {
|
const iNum = inputNums[i];
|
||||||
const iNum = inputNums[i];
|
if (this.outputs[iNum].status !== "baked" ||
|
||||||
if (this.outputs[iNum].status !== "baked" ||
|
this.outputs[iNum].bakeId !== this.manager.worker.bakeId) {
|
||||||
this.outputs[iNum].bakeId !== this.manager.worker.bakeId) {
|
const continueDownloading = await new Promise(function(resolve, reject) {
|
||||||
if (window.confirm("Not all outputs have been baked yet. Continue downloading outputs?")) {
|
this.app.confirm(
|
||||||
break;
|
"Incomplete outputs",
|
||||||
} else {
|
"Not all outputs have been baked yet. Continue downloading outputs?",
|
||||||
return;
|
"Download", "Cancel", resolve, this);
|
||||||
}
|
}.bind(this));
|
||||||
|
if (continueDownloading) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let fileName = window.prompt("Please enter a filename: ", "download.zip");
|
let fileName = window.prompt("Please enter a filename: ", "download.zip");
|
||||||
|
|
||||||
if (fileName === null || fileName === "") {
|
if (fileName === null || fileName === "") {
|
||||||
// Don't zip the files if there isn't a filename
|
// Don't zip the files if there isn't a filename
|
||||||
this.app.alert("No filename was specified.", 3000);
|
this.app.alert("No filename was specified.", 3000);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fileName.match(/.zip$/)) {
|
if (!fileName.match(/.zip$/)) {
|
||||||
fileName += ".zip";
|
fileName += ".zip";
|
||||||
}
|
}
|
||||||
|
|
||||||
let fileExt = window.prompt("Please enter a file extension for the files, or leave blank to detect automatically.", "");
|
let fileExt = window.prompt("Please enter a file extension for the files, or leave blank to detect automatically.", "");
|
||||||
|
|
||||||
if (fileExt === null) fileExt = "";
|
if (fileExt === null) fileExt = "";
|
||||||
|
|
||||||
if (this.zipWorker !== null) {
|
if (this.zipWorker !== null) {
|
||||||
this.terminateZipWorker();
|
this.terminateZipWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadButton = document.getElementById("save-all-to-file");
|
const downloadButton = document.getElementById("save-all-to-file");
|
||||||
|
|
||||||
downloadButton.classList.add("spin");
|
downloadButton.classList.add("spin");
|
||||||
downloadButton.title = `Zipping ${inputNums.length} files...`;
|
downloadButton.title = `Zipping ${inputNums.length} files...`;
|
||||||
downloadButton.setAttribute("data-original-title", `Zipping ${inputNums.length} files...`);
|
downloadButton.setAttribute("data-original-title", `Zipping ${inputNums.length} files...`);
|
||||||
|
|
||||||
downloadButton.firstElementChild.innerHTML = "autorenew";
|
downloadButton.firstElementChild.innerHTML = "autorenew";
|
||||||
|
|
||||||
log.debug("Creating ZipWorker");
|
log.debug("Creating ZipWorker");
|
||||||
this.zipWorker = new ZipWorker();
|
this.zipWorker = new ZipWorker();
|
||||||
this.zipWorker.postMessage({
|
this.zipWorker.postMessage({
|
||||||
outputs: this.outputs,
|
outputs: this.outputs,
|
||||||
filename: fileName,
|
filename: fileName,
|
||||||
fileExtension: fileExt
|
fileExtension: fileExt
|
||||||
});
|
|
||||||
this.zipWorker.addEventListener("message", this.handleZipWorkerMessage.bind(this));
|
|
||||||
});
|
});
|
||||||
|
this.zipWorker.addEventListener("message", this.handleZipWorkerMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1213,14 +1231,39 @@ class OutputWaiter {
|
||||||
* Moves the current output into the input textarea.
|
* Moves the current output into the input textarea.
|
||||||
*/
|
*/
|
||||||
async switchClick() {
|
async switchClick() {
|
||||||
const active = await this.getDishBuffer(this.getOutputDish(this.manager.tabs.getActiveOutputTab()));
|
const activeTab = this.manager.tabs.getActiveOutputTab();
|
||||||
|
const transferable = [];
|
||||||
|
|
||||||
|
const switchButton = document.getElementById("switch");
|
||||||
|
switchButton.classList.add("spin");
|
||||||
|
switchButton.disabled = true;
|
||||||
|
switchButton.firstElementChild.innerHTML = "autorenew";
|
||||||
|
$(switchButton).tooltip("hide");
|
||||||
|
|
||||||
|
let active = await this.getDishBuffer(this.getOutputDish(activeTab));
|
||||||
|
|
||||||
|
if (!this.outputExists(activeTab)) {
|
||||||
|
this.resetSwitchButton();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.outputs[activeTab].data.type === "string" &&
|
||||||
|
active.byteLength <= this.app.options.ioDisplayThreshold * 1024) {
|
||||||
|
const dishString = await this.getDishStr(this.getOutputDish(activeTab));
|
||||||
|
if (!await this.manager.input.preserveCarriageReturns(dishString)) {
|
||||||
|
active = dishString;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
transferable.push(active);
|
||||||
|
}
|
||||||
|
|
||||||
this.manager.input.inputWorker.postMessage({
|
this.manager.input.inputWorker.postMessage({
|
||||||
action: "inputSwitch",
|
action: "inputSwitch",
|
||||||
data: {
|
data: {
|
||||||
inputNum: this.manager.tabs.getActiveInputTab(),
|
inputNum: activeTab,
|
||||||
outputData: active
|
outputData: active
|
||||||
}
|
}
|
||||||
}, [active]);
|
}, transferable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1238,6 +1281,9 @@ class OutputWaiter {
|
||||||
inputSwitch(switchData) {
|
inputSwitch(switchData) {
|
||||||
this.switchOrigData = switchData;
|
this.switchOrigData = switchData;
|
||||||
document.getElementById("undo-switch").disabled = false;
|
document.getElementById("undo-switch").disabled = false;
|
||||||
|
|
||||||
|
this.resetSwitchButton();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1246,17 +1292,35 @@ class OutputWaiter {
|
||||||
*/
|
*/
|
||||||
undoSwitchClick() {
|
undoSwitchClick() {
|
||||||
this.manager.input.updateInputObj(this.switchOrigData.inputNum, this.switchOrigData.data);
|
this.manager.input.updateInputObj(this.switchOrigData.inputNum, this.switchOrigData.data);
|
||||||
|
|
||||||
|
this.manager.input.fileLoaded(this.switchOrigData.inputNum);
|
||||||
|
|
||||||
|
this.resetSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the switch data and resets the switch buttons
|
||||||
|
*/
|
||||||
|
resetSwitch() {
|
||||||
|
if (this.switchOrigData !== undefined) {
|
||||||
|
delete this.switchOrigData;
|
||||||
|
}
|
||||||
|
|
||||||
const undoSwitch = document.getElementById("undo-switch");
|
const undoSwitch = document.getElementById("undo-switch");
|
||||||
undoSwitch.disabled = true;
|
undoSwitch.disabled = true;
|
||||||
$(undoSwitch).tooltip("hide");
|
$(undoSwitch).tooltip("hide");
|
||||||
|
|
||||||
this.manager.input.inputWorker.postMessage({
|
this.resetSwitchButton();
|
||||||
action: "setInput",
|
}
|
||||||
data: {
|
|
||||||
inputNum: this.switchOrigData.inputNum,
|
/**
|
||||||
silent: false
|
* Resets the switch button to its usual state
|
||||||
}
|
*/
|
||||||
});
|
resetSwitchButton() {
|
||||||
|
const switchButton = document.getElementById("switch");
|
||||||
|
switchButton.classList.remove("spin");
|
||||||
|
switchButton.disabled = false;
|
||||||
|
switchButton.firstElementChild.innerHTML = "open_in_browser";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -202,6 +202,7 @@ self.bakeInput = function(inputNum, bakeId) {
|
||||||
if (inputObj === null ||
|
if (inputObj === null ||
|
||||||
inputObj === undefined ||
|
inputObj === undefined ||
|
||||||
inputObj.status !== "loaded") {
|
inputObj.status !== "loaded") {
|
||||||
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
action: "queueInputError",
|
action: "queueInputError",
|
||||||
data: {
|
data: {
|
||||||
|
@ -441,7 +442,7 @@ self.updateTabHeader = function(inputNum) {
|
||||||
*
|
*
|
||||||
* @param {object} inputData
|
* @param {object} inputData
|
||||||
* @param {number} inputData.inputNum - The input to get the data for
|
* @param {number} inputData.inputNum - The input to get the data for
|
||||||
* @param {boolean} inputData.silent - If false, the manager statechange event won't be fired
|
* @param {boolean} inputData.silent - If false, the manager statechange event will be fired
|
||||||
*/
|
*/
|
||||||
self.setInput = function(inputData) {
|
self.setInput = function(inputData) {
|
||||||
const inputNum = inputData.inputNum;
|
const inputNum = inputData.inputNum;
|
||||||
|
@ -590,7 +591,7 @@ self.updateInputObj = function(inputData) {
|
||||||
const inputNum = inputData.inputNum;
|
const inputNum = inputData.inputNum;
|
||||||
const data = inputData.data;
|
const data = inputData.data;
|
||||||
|
|
||||||
if (self.getInputObj(inputNum) === -1) return;
|
if (self.getInputObj(inputNum) === undefined) return;
|
||||||
|
|
||||||
self.inputs[inputNum].data = data;
|
self.inputs[inputNum].data = data;
|
||||||
};
|
};
|
||||||
|
@ -663,11 +664,19 @@ self.handleLoaderMessage = function(r) {
|
||||||
if ("fileBuffer" in r) {
|
if ("fileBuffer" in r) {
|
||||||
log.debug(`Input file ${inputNum} loaded.`);
|
log.debug(`Input file ${inputNum} loaded.`);
|
||||||
self.loadingInputs--;
|
self.loadingInputs--;
|
||||||
|
|
||||||
self.updateInputValue({
|
self.updateInputValue({
|
||||||
inputNum: inputNum,
|
inputNum: inputNum,
|
||||||
value: r.fileBuffer
|
value: r.fileBuffer
|
||||||
});
|
});
|
||||||
|
|
||||||
|
self.postMessage({
|
||||||
|
action: "fileLoaded",
|
||||||
|
data: {
|
||||||
|
inputNum: inputNum
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const idx = self.getLoaderWorkerIdx(r.id);
|
const idx = self.getLoaderWorkerIdx(r.id);
|
||||||
self.loadNextFile(idx);
|
self.loadNextFile(idx);
|
||||||
} else if ("progress" in r) {
|
} else if ("progress" in r) {
|
||||||
|
@ -782,7 +791,7 @@ self.loadFiles = function(filesData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.getLoadProgress();
|
self.getLoadProgress();
|
||||||
self.setInput({inputNum: activeTab, silent: false});
|
self.setInput({inputNum: activeTab, silent: true});
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1025,7 +1034,7 @@ self.inputSwitch = function(switchData) {
|
||||||
const currentData = currentInput.data;
|
const currentData = currentInput.data;
|
||||||
if (currentInput === undefined || currentInput === null) return;
|
if (currentInput === undefined || currentInput === null) return;
|
||||||
|
|
||||||
if (typeof switchData.outputData === "object") {
|
if (typeof switchData.outputData !== "string") {
|
||||||
const output = new Uint8Array(switchData.outputData),
|
const output = new Uint8Array(switchData.outputData),
|
||||||
types = detectFileType(output);
|
types = detectFileType(output);
|
||||||
let type = "unknown",
|
let type = "unknown",
|
||||||
|
@ -1036,15 +1045,22 @@ self.inputSwitch = function(switchData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArrayBuffer
|
// ArrayBuffer
|
||||||
currentInput.data = {
|
self.updateInputObj({
|
||||||
fileBuffer: switchData.outputData,
|
inputNum: switchData.inputNum,
|
||||||
name: `output.${ext}`,
|
data: {
|
||||||
size: switchData.outputData.byteLength.toLocaleString(),
|
fileBuffer: switchData.outputData,
|
||||||
type: type
|
name: `output.${ext}`,
|
||||||
};
|
size: switchData.outputData.byteLength.toLocaleString(),
|
||||||
|
type: type
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
// String
|
// String
|
||||||
currentInput.data = switchData.outputData;
|
self.updateInputValue({
|
||||||
|
inputNum: switchData.inputNum,
|
||||||
|
value: switchData.outputData,
|
||||||
|
force: true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
self.postMessage({
|
self.postMessage({
|
||||||
|
@ -1055,6 +1071,11 @@ self.inputSwitch = function(switchData) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
self.setInput({inputNum: switchData.inputNum, silent: false});
|
self.postMessage({
|
||||||
|
action: "fileLoaded",
|
||||||
|
data: {
|
||||||
|
inputNum: switchData.inputNum
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue