diff options
-rwxr-xr-x | _locales/en/messages.json | 18 | ||||
-rw-r--r-- | src/css/tabs/cli.css | 17 | ||||
-rw-r--r-- | tabs/cli.html | 15 | ||||
-rw-r--r-- | tabs/cli.js | 181 |
4 files changed, 210 insertions, 21 deletions
diff --git a/_locales/en/messages.json b/_locales/en/messages.json index ce67a801..c0a52e3e 100755 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1480,6 +1480,24 @@ "cliClearOutputHistoryBtn": { "message": "Clear output history" }, + "cliCopyToClipboardBtn": { + "message": "Copy to clipboard" + }, + "cliCopySuccessful": { + "message": "Copied!" + }, + "cliLoadFromFileBtn": { + "message": "Load from file" + }, + "cliConfirmSnippetDialogTitle": { + "message": "Review loaded commands" + }, + "cliConfirmSnippetNote": { + "message": "<strong>Note</strong>: You can review and edit commands before execution." + }, + "cliConfirmSnippetBtn": { + "message": "Execute" + }, "loggingNote": { "message": "Data will be logged in this tab <span style=\"color: red\">only</span>, leaving the tab will <span style=\"color: red\">cancel</span> logging and application will return to its normal <strong>\"configurator\"</strong> state.<br /> You are free to select the global update period, data will be written into the log file every <strong>1</strong> second for performance reasons." diff --git a/src/css/tabs/cli.css b/src/css/tabs/cli.css index d7f1643d..d73ff43f 100644 --- a/src/css/tabs/cli.css +++ b/src/css/tabs/cli.css @@ -50,6 +50,18 @@ resize: none; } +.jBox-container textarea#preview { + background-color: rgba(0, 0, 0, 0.75); + width: 100%; + resize: none; + overflow-y: scroll; + overflow-x: hidden; + font-family: monospace; + color: white; + padding: 5px; + margin-bottom: 5px; +} + .tab-cli #content-watermark { z-index: 0; } @@ -58,6 +70,11 @@ white-space: pre-wrap; } +.tab-cli .window .error_message { + color: red; + font-weight: bold; +} + .tab-cli .save { color: white; } diff --git a/tabs/cli.html b/tabs/cli.html index 9a533704..5c7430c3 100644 --- a/tabs/cli.html +++ b/tabs/cli.html @@ -16,7 +16,22 @@ <div class="content_toolbar"> <div class="btn save_btn pull-right"> <a class="save" href="#" i18n="cliSaveToFileBtn"></a> + <a class="load" href="#" i18n="cliLoadFromFileBtn"></a> <a class="clear" href="#" i18n="cliClearOutputHistoryBtn"></a> + <a class="copy" href="#" i18n="cliCopyToClipboardBtn"></a> + </div> + </div> + + <!-- Snippet preview dialog --> + <div id="snippetpreviewcontent" style="display: none"> + <div class="note"> + <div class="note_spacer"> + <p i18n="cliConfirmSnippetNote"></p> + </div> + </div> + <textarea id="preview" cols="120" rows="20"></textarea> + <div class="default_btn"> + <a class="confirm" href="#" i18n="cliConfirmSnippetBtn"></a> </div> </div> </div>
\ No newline at end of file diff --git a/tabs/cli.js b/tabs/cli.js index 11772c36..b8552a06 100644 --- a/tabs/cli.js +++ b/tabs/cli.js @@ -4,7 +4,10 @@ TABS.cli = { lineDelayMs: 50, profileSwitchDelayMs: 100, outputHistory: "", - cliBuffer: "" + cliBuffer: "", + GUI: { + snippetPreviewWindow: null, + }, }; function removePromptHash(promptText) { @@ -41,6 +44,74 @@ function getCliCommand(command, cliBuffer) { return commandWithBackSpaces(command, buffer, noOfCharsToDelete); } +function copyToClipboard(text) { + function onCopySuccessful() { + const button = $('.tab-cli .copy'); + const origText = button.text(); + const origWidth = button.css("width"); + button.text(chrome.i18n.getMessage("cliCopySuccessful")); + button.css({ + width: origWidth, + textAlign: "center", + }); + setTimeout(() => { + button.text(origText); + button.css({ + width: "", + textAlign: "", + }); + }, 1500); + } + + function onCopyFailed(ex) { + console.warn(ex); + } + + function nwCopy(text) { + try { + let clipboard = require('nw.gui').Clipboard.get(); + clipboard.set(text, "text"); + onCopySuccessful(); + } catch (ex) { + onCopyFailed(ex); + } + } + + function webCopy(text) { + navigator.clipboard.writeText(text) + .then(onCopySuccessful, onCopyFailed); + } + + let copyFunc; + try { + let nwGui = require('nw.gui'); + copyFunc = nwCopy; + } catch (e) { + copyFunc = webCopy; + } + copyFunc(text); +} + +function sendLinesWithDelay(outputArray) { + return (delay, line, index) => { + return new Promise((resolve) => { + helper.timeout.add('CLI_send_slowly', () => { + var processingDelay = self.lineDelayMs; + if (line.toLowerCase().startsWith('profile')) { + processingDelay = self.profileSwitchDelayMs; + } + const isLastCommand = outputArray.length === index + 1; + if (isLastCommand && self.cliBuffer) { + line = getCliCommand(line, self.cliBuffer); + } + TABS.cli.sendLine(line, () => { + resolve(processingDelay); + }); + }, delay); + }); + }; +} + TABS.cli.initialize = function (callback) { var self = this; @@ -56,13 +127,28 @@ TABS.cli.initialize = function (callback) { self.outputHistory = ""; self.cliBuffer = ""; + const clipboardCopySupport = (() => { + let nwGui = null; + try { + nwGui = require('nw.gui'); + } catch (e) {} + return !(nwGui == null && !navigator.clipboard) + })(); + + function executeCommands(out_string) { + self.history.add(out_string.trim()); + + var outputArray = out_string.split("\n"); + Promise.reduce(outputArray, sendLinesWithDelay(outputArray), 0); + } + $('#content').load("./tabs/cli.html", function () { // translate to user-selected language localize(); CONFIGURATOR.cliActive = true; - var textarea = $('.tab-cli textarea'); + var textarea = $('.tab-cli textarea[name="commands"]'); $('.tab-cli .save').click(function() { var prefix = 'cli'; @@ -111,11 +197,76 @@ TABS.cli.initialize = function (callback) { }); }); -$('.tab-cli .clear').click(function() { + $('.tab-cli .clear').click(function() { self.outputHistory = ""; $('.tab-cli .window .wrapper').empty(); }); + if (clipboardCopySupport) { + $('.tab-cli .copy').click(function() { + copyToClipboard(self.outputHistory); + }); + } else { + $('.tab-cli .copy').hide(); + } + + $('.tab-cli .load').click(function() { + var accepts = [ + { + description: 'Config files', extensions: ["txt", "config"], + }, + { + description: 'All files', + }, + ]; + + chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(entry) { + if (chrome.runtime.lastError) { + console.error(chrome.runtime.lastError.message); + return; + } + + if (!entry) { + console.log('No file selected'); + return; + } + + let previewArea = $("#snippetpreviewcontent textarea#preview"); + + function executeSnippet() { + const commands = previewArea.val(); + executeCommands(commands); + self.GUI.snippetPreviewWindow.close(); + } + + function previewCommands(result) { + if (!self.GUI.snippetPreviewWindow) { + self.GUI.snippetPreviewWindow = new jBox("Modal", { + id: "snippetPreviewWindow", + width: 'auto', + height: 'auto', + closeButton: 'title', + animation: false, + isolateScroll: false, + title: chrome.i18n.getMessage("cliConfirmSnippetDialogTitle"), + content: $('#snippetpreviewcontent'), + onCreated: () => $("#snippetpreviewcontent a.confirm").click(() => executeSnippet()), + }); + } + previewArea.val(result); + self.GUI.snippetPreviewWindow.open(); + } + + entry.file((file) => { + let reader = new FileReader(); + reader.onload = + () => previewCommands(reader.result); + reader.onerror = () => console.error(reader.error); + reader.readAsText(file); + }); + }); + }); + // Tab key detection must be on keydown, // `keypress`/`keyup` happens too late, as `textarea` will have already lost focus. textarea.keydown(function (event) { @@ -142,23 +293,7 @@ $('.tab-cli .clear').click(function() { self.history.add(out_string.trim()); var outputArray = out_string.split("\n"); - Promise.reduce(outputArray, function(delay, line, index) { - return new Promise(function (resolve) { - helper.timeout.add('CLI_send_slowly', function () { - var processingDelay = self.lineDelayMs; - if (line.toLowerCase().startsWith('profile')) { - processingDelay = self.profileSwitchDelayMs; - } - const isLastCommand = outputArray.length === index + 1; - if (isLastCommand && self.cliBuffer) { - line = getCliCommand(line, self.cliBuffer); - } - self.sendLine(line, function () { - resolve(processingDelay); - }); - }, delay) - }) - }, 0); + Promise.reduce(outputArray, sendLinesWithDelay(outputArray), 0); textarea.val(''); } @@ -224,7 +359,11 @@ function writeToOutput(text) { } function writeLineToOutput(text) { - writeToOutput(text + "<br>"); + if (text.startsWith("### ERROR: ")) { + writeToOutput('<span class="error_message">' + text + '</span><br>'); + } else { + writeToOutput(text + "<br>"); + } } function setPrompt(text) { |