Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/iNavFlight/inav-configurator.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x_locales/en/messages.json18
-rw-r--r--src/css/tabs/cli.css17
-rw-r--r--tabs/cli.html15
-rw-r--r--tabs/cli.js181
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) {