1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-26 01:35:28 +03:00

Presets TAB

This commit is contained in:
Ivan Efimov 2021-11-23 19:38:48 -06:00
parent 41747c65b6
commit e63a5fe642
39 changed files with 3375 additions and 19 deletions

View file

@ -5,30 +5,31 @@
const ConfigStorage = {
// key can be one string, or array of strings
get: function(key, callback) {
let result = {};
if (Array.isArray(key)) {
let obj = {};
key.forEach(function (element) {
try {
obj = {...obj, ...JSON.parse(window.localStorage.getItem(element))};
result = {...result, ...JSON.parse(window.localStorage.getItem(element))};
} catch (e) {
// is okay
}
});
callback(obj);
callback?.(result);
} else {
const keyValue = window.localStorage.getItem(key);
if (keyValue) {
let obj = {};
try {
obj = JSON.parse(keyValue);
result = JSON.parse(keyValue);
} catch (e) {
// It's fine if we fail that parse
}
callback(obj);
callback?.(result);
} else {
callback({});
callback?.(result);
}
}
return result;
},
// set takes an object like {'userLanguageSelect':'DEFAULT'}
set: function(input) {

View file

@ -30,6 +30,9 @@ const CONFIGURATOR = {
cliActive: false,
cliValid: false,
productName: 'Betaflight Configurator',
cliEngineActive: false,
cliEngineValid: false,
gitChangesetId: 'unknown',
version: '0.0.1',
gitRevision: 'norevision',
latestVersion: '0.0.1',

View file

@ -19,6 +19,7 @@ const GuiControl = function () {
this.operating_system = null;
this.interval_array = [];
this.timeout_array = [];
this.buttonDisabledClass = "disabled";
this.defaultAllowedTabsWhenDisconnected = [
'landing',
@ -36,6 +37,7 @@ const GuiControl = function () {
'power',
'adjustments',
'auxiliary',
'presets',
'cli',
'configuration',
'gps',
@ -407,5 +409,166 @@ GuiControl.prototype.isOther = function () {
return this.Mode === GUI_MODES.Other;
};
GuiControl.prototype.showYesNoDialog = function(yesNoDialogSettings) {
// yesNoDialogSettings:
// title, text, buttonYesText, buttonNoText, buttonYesCallback, buttonNoCallback
const dialog = $(".dialogYesNo");
const title = dialog.find(".dialogYesNoTitle");
const content = dialog.find(".dialogYesNoContent");
const buttonYes = dialog.find(".dialogYesNo-yesButton");
const buttonNo = dialog.find(".dialogYesNo-noButton");
title.html(yesNoDialogSettings.title);
content.html(yesNoDialogSettings.text);
buttonYes.html(yesNoDialogSettings.buttonYesText);
buttonNo.html(yesNoDialogSettings.buttonNoText);
buttonYes.off("click");
buttonNo.off("click");
buttonYes.on("click", () => {
dialog[0].close();
yesNoDialogSettings.buttonYesCallback?.();
});
buttonNo.on("click", () => {
dialog[0].close();
yesNoDialogSettings.buttonNoCallback?.();
});
dialog[0].showModal();
};
GuiControl.prototype.showWaitDialog = function(waitDialogSettings) {
// waitDialogSettings:
// title, buttonCancelCallback
const dialog = $(".dialogWait")[0];
const title = $(".dialogWaitTitle");
const buttonCancel = $(".dialogWait-cancelButton");
title.html(waitDialogSettings.title);
buttonCancel.toggle(!!waitDialogSettings.buttonCancelCallback);
buttonCancel.off("click");
buttonCancel.on("click", () => {
dialog.close();
waitDialogSettings.buttonCancelCallback?.();
});
dialog.showModal();
return dialog;
};
GuiControl.prototype.showInformationDialog = function(informationDialogSettings) {
// informationDialogSettings:
// title, text, buttonConfirmText
return new Promise(resolve => {
const dialog = $(".dialogInformation");
const title = dialog.find(".dialogInformationTitle");
const content = dialog.find(".dialogInformationContent");
const buttonConfirm = dialog.find(".dialogInformation-confirmButton");
title.html(informationDialogSettings.title);
content.html(informationDialogSettings.text);
buttonConfirm.html(informationDialogSettings.buttonConfirmText);
buttonConfirm.off("click");
buttonConfirm.on("click", () => {
dialog[0].close();
resolve();
});
dialog[0].showModal();
});
};
GuiControl.prototype.saveToTextFileDialog = function(textToSave, suggestedFileName, extension) {
return new Promise((resolve, reject) => {
const accepts = [{ description: extension.toUpperCase() + ' files', extensions: [extension] }];
chrome.fileSystem.chooseEntry(
{
type: 'saveFile',
suggestedName: suggestedFileName,
accepts: accepts,
},
entry => this._saveToTextFileDialogFileSelected(entry, textToSave, resolve, reject),
);
});
};
GuiControl.prototype._saveToTextFileDialogFileSelected = function(entry, textToSave, resolve, reject) {
checkChromeRuntimeError();
if (!entry) {
console.log('No file selected for saving');
resolve(false);
return;
}
entry.createWriter(writer => {
writer.onerror = () => {
reject();
console.error('Failed to write file');
};
writer.onwriteend = () => {
if (textToSave.length > 0 && writer.length === 0) {
writer.write(new Blob([textToSave], {type: 'text/plain'}));
} else {
resolve(true);
console.log('File write complete');
}
};
writer.truncate(0);
},
() => {
reject();
console.error('Failed to get file writer');
});
};
GuiControl.prototype.readTextFileDialog = function(extension) {
const accepts = [{ description: extension.toUpperCase() + ' files', extensions: [extension] }];
return new Promise(resolve => {
chrome.fileSystem.chooseEntry({type: 'openFile', accepts: accepts}, function(entry) {
checkChromeRuntimeError();
if (!entry) {
console.log('No file selected for loading');
resolve(false);
return;
}
entry.file((file) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => {
console.error(reader.error);
reject();
};
reader.readAsText(file);
});
});
});
};
GuiControl.prototype.escapeHtml = function(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
};
// initialize object into GUI variable
window.GUI = new GuiControl();

View file

@ -401,6 +401,9 @@ function startProcess() {
case 'cli':
TABS.cli.initialize(content_ready, GUI.nwGui);
break;
case 'presets':
TABS.presets.initialize(content_ready, GUI.nwGui);
break;
default:
console.log(`Tab not found: ${tab}`);

View file

@ -583,13 +583,17 @@ function onClosed(result) {
CONFIGURATOR.connectionValid = false;
CONFIGURATOR.cliValid = false;
CONFIGURATOR.cliActive = false;
CONFIGURATOR.cliEngineValid = false;
CONFIGURATOR.cliEngineActive = false;
}
function read_serial(info) {
if (!CONFIGURATOR.cliActive) {
MSP.read(info);
} else if (CONFIGURATOR.cliActive) {
if (CONFIGURATOR.cliActive) {
TABS.cli.read(info);
} else if (CONFIGURATOR.cliEngineActive) {
TABS.presets.read(info);
} else {
MSP.read(info);
}
}
@ -694,7 +698,8 @@ function update_live_status() {
display: 'inline-block'
});
if (GUI.active_tab != 'cli') {
if (GUI.active_tab !== 'cli' && GUI.active_tab !== 'presets') {
MSP.send_message(MSPCodes.MSP_BOXNAMES, false, false);
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_32)) {
MSP.send_message(MSPCodes.MSP_STATUS_EX, false, false);
} else {

View file

@ -18,6 +18,8 @@ options.initialize = function (callback) {
TABS.options.initCordovaForceComputerUI();
TABS.options.initDarkTheme();
TABS.options.initShowWarnings();
GUI.content_ready(callback);
});
};
@ -28,6 +30,19 @@ options.cleanup = function (callback) {
}
};
options.initShowWarnings = function () {
ConfigStorage.get('showPresetsWarningBackup', function (result) {
if (result.showPresetsWarningBackup) {
$('div.presetsWarningBackup input').prop('checked', true);
}
$('div.presetsWarningBackup input').change(function () {
const checked = $(this).is(':checked');
ConfigStorage.set({'showPresetsWarningBackup': checked});
}).change();
});
};
options.initPermanentExpertMode = function () {
ConfigStorage.get('permanentExpertMode', function (result) {
if (result.permanentExpertMode) {