Add carriage return detection for pasted and switched inputs.

Fix switching the output to input not working properly.
Add nicer confirmation boxes for zipping outputs.
This commit is contained in:
j433866 2019-08-22 11:53:41 +01:00
parent 9f2d1453ed
commit f43a868607
6 changed files with 399 additions and 246 deletions

View file

@ -222,8 +222,6 @@ class InputWaiter {
if (Object.prototype.hasOwnProperty.call(r, "progress") &&
Object.prototype.hasOwnProperty.call(r, "inputNum")) {
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;
@ -305,6 +303,9 @@ class InputWaiter {
case "removeChefWorker":
this.removeChefWorker();
break;
case "fileLoaded":
this.fileLoaded(r.data.inputNum);
break;
default:
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 {string} inputData.type - The MIME type 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) {
return new Promise(function(resolve, reject) {
@ -373,7 +374,7 @@ class InputWaiter {
if (!silent) window.dispatchEvent(this.manager.statechange);
} else {
this.setFile(inputData);
this.setFile(inputData, silent);
}
}.bind(this));
@ -389,8 +390,9 @@ class InputWaiter {
* @param {number} inputData.size - The size in bytes 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 {boolean} [silent=true] - If false, fires the manager statechange event
*/
setFile(inputData) {
setFile(inputData, silent=true) {
const activeTab = this.manager.tabs.getActiveInputTab();
if (inputData.inputNum !== activeTab) return;
@ -414,6 +416,30 @@ class InputWaiter {
this.setInputInfo(inputData.size, null);
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.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,13 +724,17 @@ class InputWaiter {
*
* @param {event} e
*/
inputPaste(e) {
async inputPaste(e) {
e.preventDefault();
e.stopPropagation();
const pastedData = e.clipboardData.getData("Text");
if (pastedData.length < (this.app.options.ioDisplayThreshold * 1024)) {
const preserve = await this.preserveCarriageReturns(pastedData);
if (pastedData.length < (this.app.options.ioDisplayThreshold * 1024) && !preserve) {
// 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;
@ -728,9 +745,6 @@ class InputWaiter {
inputText.setSelectionRange(selStart + pastedData.length, selStart + pastedData.length);
this.debounceInputChange(e);
} else {
e.preventDefault();
e.stopPropagation();
const file = new File([pastedData], "PastedData", {
type: "text/plain",
lastModified: Date.now()
@ -815,6 +829,45 @@ 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) {
const optionsStr = "This behaviour can be changed in the <a href='#' onclick='document.getElementById(\"options\").click()'>options</a>";
if (!this.app.options.userSetCR) {
let preserve = await new Promise(function(resolve, reject) {
this.app.confirm(
"Carriage Return Detected",
"A carriage return was detected in your input. As HTML textareas can't display carriage returns, 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, and can be toggled in the options.",
"Preserve Carriage Returns",
"Enable Editing", resolve, this);
}.bind(this));
if (preserve === undefined) {
this.app.alert(`Not preserving carriage returns. ${optionsStr}`, 4000);
preserve = false;
}
this.manager.options.updateOption("preserveCR", preserve);
this.manager.options.updateOption("userSetCR", true);
} else {
if (this.app.options.preserveCR) {
this.app.alert(`Carriage return(s) detected in input, so editing has been disabled to preserve them. ${optionsStr}`, 6000);
} else {
this.app.alert(`Carriage return(s) detected in input. Editing is remaining enabled, but any carriage returns will be removed. ${optionsStr}`, 6000);
}
}
return this.app.options.preserveCR;
} else {
return false;
}
}
/**
* Load files from the UI into the inputWorker
*