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:
parent
41747c65b6
commit
e63a5fe642
39 changed files with 3375 additions and 19 deletions
|
@ -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) {
|
||||
|
|
|
@ -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',
|
||||
|
|
163
src/js/gui.js
163
src/js/gui.js
|
@ -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, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
};
|
||||
|
||||
// initialize object into GUI variable
|
||||
window.GUI = new GuiControl();
|
||||
|
|
|
@ -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}`);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue