mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-26 01:35:28 +03:00
Cordova framework integration, Android support, mobile UI & options tab
Cordova integration and android platform : - Added cordova directory with required config - Added cordova applications generation in gulpfile - Added cordova development instructions - Used cordova plugins to simulate missing chrome api plugins (chrome.serial and chrome.fileSystem) - Added cordova clipboard support - Added android operating system and Cordova gui mode - Fixed some css and js files to make them working on Android as well as on computers - Added --skipdep argument to accelerate cordova build (gulp task) - Added a webview helper to help people to update the webview app of their device New options tab : - Added options tab replacing the options dropdown - Added option to switch between phones UI and computers UI Mobile interface and global interface improvements : - Simplified the structure of the header with flex css - Made headerbar and tab container responsive (compact headerbar and side menu) - All tabs are adapted to mobile interface (except firmware flasher) - The servos and adjustments tabs are not fully adapted but are "usable" - Improved header bar animation - Improved log expandation animation - Added swipe gesture to toggle side menu Fixes during the development : - Logo position - Dark mode - Auto connection - Error messages (cordova_chromeapi.js) - Responsive grid - Testing - Disconnection - Width of boxes inside the OSD tab - Fixed cli tab - OSD tab - Motor stop switch - White spaces in boxes - Dialogs size - Connect button state - Prevent tablet with a height larger than 575px to switch to computers ui - Fixed logging tab - Fixed code smell - Fixed yarn cordova plugin install issue - Fixed content_wrapper - Fixed vibrations when scrolling - Fixed scrolling bar alignment - Fixed dialogReportProblem height - Fixed rates logo - Fixed auto connection default value (true) - Fixed D to D max - Fixed dialogs Added required messages in locales/en/messages.json file Requested changes
This commit is contained in:
parent
ea880840a8
commit
4f93e54ae6
99 changed files with 9095 additions and 3015 deletions
|
@ -36,7 +36,7 @@ Clipboard._configureClipboardAsNwJs = function(nwGui) {
|
|||
if (onSuccess) {
|
||||
onSuccess(text);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.readText = function(onSuccess, onError) {
|
||||
|
||||
|
@ -54,8 +54,8 @@ Clipboard._configureClipboardAsNwJs = function(nwGui) {
|
|||
if (onSuccess) {
|
||||
onSuccess(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
Clipboard._configureClipboardAsChrome = function() {
|
||||
|
||||
|
@ -69,15 +69,33 @@ Clipboard._configureClipboardAsChrome = function() {
|
|||
navigator.clipboard.writeText(text)
|
||||
.then(onSuccess)
|
||||
.catch(onError);
|
||||
}
|
||||
};
|
||||
|
||||
this.readText = function(onSuccess, onError) {
|
||||
navigator.clipboard.readText()
|
||||
.then(onSuccess)
|
||||
.catch(onError);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Clipboard._configureClipboardAsCordova = function() {
|
||||
|
||||
console.log('Cordova Clipboard available');
|
||||
|
||||
this.available = true;
|
||||
this.readAvailable = true;
|
||||
this.writeAvailable = true;
|
||||
|
||||
this.writeText = function(text, onSuccess, onError) {
|
||||
cordova.plugins.clipboard.copy(text, onSuccess, onError);
|
||||
};
|
||||
|
||||
this.readText = function(onSuccess, onError) {
|
||||
cordova.plugins.clipboard.paste(onSuccess, onError);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
Clipboard._configureClipboardAsOther = function() {
|
||||
|
||||
|
@ -89,12 +107,12 @@ Clipboard._configureClipboardAsOther = function() {
|
|||
|
||||
this.writeText = function(text, onSuccess, onError) {
|
||||
onError('Clipboard not available');
|
||||
}
|
||||
};
|
||||
|
||||
this.readText = function(onSuccess, onError) {
|
||||
onError('Clipboard not available');
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
switch (GUI.Mode) {
|
||||
|
@ -106,6 +124,10 @@ case GUI_Modes.ChromeApp:
|
|||
Clipboard._configureClipboardAsChrome();
|
||||
break;
|
||||
|
||||
case GUI_Modes.Cordova:
|
||||
Clipboard._configureClipboardAsCordova();
|
||||
break;
|
||||
|
||||
default:
|
||||
Clipboard._configureClipboardAsOther();
|
||||
}
|
||||
|
|
|
@ -172,9 +172,10 @@ Features.prototype.generateElements = function (featuresElements) {
|
|||
+ self._features[i].name
|
||||
+ '" title="'
|
||||
+ self._features[i].name
|
||||
+ '" type="checkbox"/></td>'
|
||||
+ '" type="checkbox"/></td><td><div>'
|
||||
+ featureName
|
||||
+ '<td><span i18n="feature' + self._features[i].name + '"></span>'
|
||||
+ '</div><span class="xs" i18n="feature' + self._features[i].name + '"></span></td>'
|
||||
+ '<td><span class="sm-min" i18n="feature' + self._features[i].name + '"></span>'
|
||||
+ feature_tip_html + '</td></tr>');
|
||||
|
||||
var feature_e = newElement.find('input.feature');
|
||||
|
|
|
@ -318,7 +318,8 @@ function configuration_restore(callback) {
|
|||
};
|
||||
|
||||
reader.onloadend = function (e) {
|
||||
if (e.total != 0 && e.total == e.loaded) {
|
||||
if ((e.total != 0 && e.total == e.loaded) || GUI.isCordova()) {
|
||||
// Cordova: Ignore verification : seem to have a bug with progressEvent returned
|
||||
console.log('Read SUCCESSFUL');
|
||||
|
||||
try { // check if string provided is a valid JSON
|
||||
|
|
418
src/js/cordova_chromeapi.js
vendored
Normal file
418
src/js/cordova_chromeapi.js
vendored
Normal file
|
@ -0,0 +1,418 @@
|
|||
'use strict';
|
||||
|
||||
const chromeCallbackWithError = function(message, callback) {
|
||||
let err;
|
||||
if (typeof message === 'string') {
|
||||
err = { 'message' : message };
|
||||
} else {
|
||||
err = message;
|
||||
}
|
||||
if (typeof callback !== 'function') {
|
||||
console.error(err.message);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (typeof chrome.runtime !== 'undefined') {
|
||||
chrome.runtime.lastError = err;
|
||||
} else {
|
||||
console.error(err.message);
|
||||
}
|
||||
callback.apply(null, Array.prototype.slice.call(arguments, 2));
|
||||
} finally {
|
||||
if (typeof chrome.runtime !== 'undefined') {
|
||||
delete chrome.runtime.lastError;
|
||||
}
|
||||
}
|
||||
};
|
||||
const chromeCallbackWithSuccess = function(argument, callback) {
|
||||
if (typeof callback === 'function') {
|
||||
if (typeof argument === 'undefined') {
|
||||
callback();
|
||||
} else {
|
||||
callback(argument);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const removeItemOfAnArray = async function (array, item) {
|
||||
for (let i = (array.length - 1); i >= 0; i--) {
|
||||
if (array[i] === item) {
|
||||
return array.splice(i, 1);
|
||||
}
|
||||
}
|
||||
return array;
|
||||
};
|
||||
|
||||
|
||||
const chromeapiSerial = {
|
||||
logHeader: 'SERIAL (adapted from Cordova): ',
|
||||
connection: {
|
||||
connectionId: 1, // Only one connection possible
|
||||
paused: false,
|
||||
persistent: false,
|
||||
name,
|
||||
bufferSize: 4096,
|
||||
receiveTimeout: 0,
|
||||
sendTimeout: 0,
|
||||
bitrate: 9600,
|
||||
dataBits: 'eight',
|
||||
parityBit: 'no',
|
||||
stopBits: 'one',
|
||||
ctsFlowControl: false,
|
||||
},
|
||||
setConnectionOptions: function(ConnectionOptions) {
|
||||
if (ConnectionOptions.persistent) {
|
||||
this.connection.persistent = ConnectionOptions.persistent;
|
||||
}
|
||||
if (ConnectionOptions.name) {
|
||||
this.connection.name = ConnectionOptions.name;
|
||||
}
|
||||
if (ConnectionOptions.bufferSize) {
|
||||
this.connection.bufferSize = ConnectionOptions.bufferSize;
|
||||
}
|
||||
if (ConnectionOptions.receiveTimeout) {
|
||||
this.connection.receiveTimeout = ConnectionOptions.receiveTimeout;
|
||||
}
|
||||
if (ConnectionOptions.sendTimeout) {
|
||||
this.connection.sendTimeout = ConnectionOptions.sendTimeout;
|
||||
}
|
||||
if (ConnectionOptions.bitrate) {
|
||||
this.connection.bitrate = ConnectionOptions.bitrate;
|
||||
}
|
||||
if (ConnectionOptions.dataBits) {
|
||||
this.connection.dataBits = ConnectionOptions.dataBits;
|
||||
}
|
||||
if (ConnectionOptions.parityBit) {
|
||||
this.connection.parityBit = ConnectionOptions.parityBit;
|
||||
}
|
||||
if (ConnectionOptions.stopBits) {
|
||||
this.connection.stopBits = ConnectionOptions.stopBits;
|
||||
}
|
||||
if (ConnectionOptions.ctsFlowControl) {
|
||||
this.connection.ctsFlowControl = ConnectionOptions.ctsFlowControl;
|
||||
}
|
||||
},
|
||||
getCordovaSerialConnectionOptions: function() {
|
||||
let dataBits, stopBits, parityBit;
|
||||
if (this.connection.dataBits === 'seven') {
|
||||
dataBits = 7;
|
||||
} else {
|
||||
dataBits = 8;
|
||||
}
|
||||
if (this.connection.stopBits === 'two') {
|
||||
stopBits = 2;
|
||||
} else {
|
||||
stopBits = 1;
|
||||
}
|
||||
if (this.connection.parityBit === 'odd') {
|
||||
parityBit = 0;
|
||||
} else if (this.connection.parityBit === 'even') {
|
||||
parityBit = 1;
|
||||
}
|
||||
return {
|
||||
baudRate: this.connection.bitrate,
|
||||
dataBits: dataBits,
|
||||
stopBits: stopBits,
|
||||
parity: parityBit,
|
||||
sleepOnPause: false,
|
||||
};
|
||||
},
|
||||
|
||||
// Chrome serial API methods
|
||||
getDevices: async function(callback) {
|
||||
const self = this;
|
||||
cordova.plugins.usbevent.listDevices(function(list) {
|
||||
const devices = [];
|
||||
if (list.devices !== undefined) {
|
||||
let count = 0;
|
||||
list.devices.forEach(device => {
|
||||
count++;
|
||||
devices.push({
|
||||
path: `${device.vendorId}/${device.productId}`,
|
||||
vendorId: device.vendorId,
|
||||
productId: device.productId,
|
||||
displayName: `${device.vendorId}/${device.productId}`,
|
||||
});
|
||||
if (count === list.devices.length) {
|
||||
if (callback) {
|
||||
callback(devices);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (callback) {
|
||||
callback(devices);
|
||||
}
|
||||
}
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
},
|
||||
connect: function(path, ConnectionOptions, callback) {
|
||||
const self = this;
|
||||
if (typeof ConnectionOptions !== 'undefined') {
|
||||
self.setConnectionOptions(ConnectionOptions);
|
||||
}
|
||||
const pathSplit = path.split('/');
|
||||
if (pathSplit.length === 2) {
|
||||
const vid = parseInt(pathSplit[0]);
|
||||
const pid = parseInt(pathSplit[1]);
|
||||
console.log(`${self.logHeader}request permission (vid=${vid} / pid=${pid})`);
|
||||
cordova_serial.requestPermission({vid: vid, pid: pid}, function() {
|
||||
const options = self.getCordovaSerialConnectionOptions();
|
||||
cordova_serial.open(options, function () {
|
||||
cordova_serial.registerReadCallback(function (data) {
|
||||
const info = {
|
||||
connectionId: self.connection.connectionId,
|
||||
data: data,
|
||||
};
|
||||
self.onReceive.receiveData(info);
|
||||
}, function () {
|
||||
console.warn(`${self.logHeader}failed to register read callback`);
|
||||
});
|
||||
chromeCallbackWithSuccess(self.connection, callback);
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
} else {
|
||||
chromeCallbackWithError(`${self.logHeader} invalid vendor id / product id`, callback);
|
||||
}
|
||||
},
|
||||
disconnect: function(connectionId, callback) {
|
||||
const self = this;
|
||||
cordova_serial.close(function () {
|
||||
chromeCallbackWithSuccess(true, callback);
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback(false));
|
||||
});
|
||||
},
|
||||
setPaused: function(connectionId, paused, callback) {
|
||||
this.connection.paused = paused; // Change connectionInfo but don't pause the connection
|
||||
chromeCallbackWithSuccess(undefined, callback);
|
||||
},
|
||||
getInfo: function(callback) {
|
||||
chromeCallbackWithSuccess(this.connection, callback);
|
||||
},
|
||||
send: function(connectionId, data, callback) {
|
||||
const string = Array.prototype.map.call(new Uint8Array(data), x => (`00${x.toString(16)}`).slice(-2)).join('');
|
||||
cordova_serial.writeHex(string, function () {
|
||||
chromeCallbackWithSuccess({
|
||||
bytesSent: string.length >> 1,
|
||||
}, callback);
|
||||
}, function(error) {
|
||||
const info = {
|
||||
bytesSent: 0,
|
||||
error: 'undefined',
|
||||
};
|
||||
chrome.serial.onReceiveError.receiveError(info);
|
||||
chromeCallbackWithError(`SERIAL (adapted from Cordova): ${error}`, callback(info));
|
||||
});
|
||||
},
|
||||
getControlSignals: function(connectionId, callback) {
|
||||
// Not supported yet
|
||||
console.warn('chrome.serial.getControlSignals not supported yet');
|
||||
chromeCallbackWithSuccess({}, callback);
|
||||
},
|
||||
setControlSignals: function(connectionId, signals, callback) {
|
||||
// Not supported yet
|
||||
console.warn('chrome.serial.setControlSignals not supported yet');
|
||||
chromeCallbackWithSuccess({
|
||||
result: false,
|
||||
}, callback);
|
||||
},
|
||||
// update: function() { },
|
||||
// getConnections: function() { },
|
||||
// flush: function() { },
|
||||
// setBreak: function() { },
|
||||
// clearBreak: function() { },
|
||||
|
||||
onReceive: {
|
||||
listeners: [],
|
||||
addListener: function(functionReference) {
|
||||
this.listeners.push(functionReference);
|
||||
},
|
||||
removeListener: async function(functionReference) {
|
||||
this.listeners = await removeItemOfAnArray(this.listeners, functionReference);
|
||||
},
|
||||
receiveData: function(data) {
|
||||
if (data.data.byteLength > 0) {
|
||||
for (let i = (this.listeners.length - 1); i >= 0; i--) {
|
||||
this.listeners[i](data);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
onReceiveError: {
|
||||
listeners: [],
|
||||
addListener: function(functionReference) {
|
||||
this.listeners.push(functionReference);
|
||||
},
|
||||
removeListener: async function(functionReference) {
|
||||
this.listeners = await removeItemOfAnArray(this.listeners, functionReference);
|
||||
},
|
||||
receiveError: function(error) {
|
||||
for (let i = (this.listeners.length - 1); i >= 0; i--) {
|
||||
this.listeners[i](error);
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const chromeapiFilesystem = {
|
||||
logHeader: 'FILESYSTEM (adapted from Cordova): ',
|
||||
savedEntries: [],
|
||||
getFileExtension: function(fileName) {
|
||||
const re = /(?:\.([^.]+))?$/;
|
||||
return re.exec(fileName)[1];
|
||||
},
|
||||
|
||||
// Chrome fileSystem API methods
|
||||
getDisplayPath: function(entry, callback) {
|
||||
chromeCallbackWithSuccess(entry.fullPath, callback);
|
||||
},
|
||||
getWritableEntry: function(entry, callback) {
|
||||
// Entry returned by chooseEntry method is writable on Android
|
||||
chromeCallbackWithSuccess(entry, callback);
|
||||
},
|
||||
isWritableEntry: function(entry, callback) {
|
||||
// Entry returned by chooseEntry method is writable on Android
|
||||
chromeCallbackWithSuccess(true, callback);
|
||||
},
|
||||
chooseEntryOpenFile: function(options, callback) {
|
||||
const self = this;
|
||||
fileChooser.open(function(uri) {
|
||||
window.resolveLocalFileSystemURL(uri, function(entry) {
|
||||
if (options.accepts && options.accepts[0].extensions && options.accepts[0].extensions && options.accepts[0].extensions.length > 0) {
|
||||
self.getDisplayPath(entry, function(fileName) {
|
||||
const extension = self.getFileExtension(fileName);
|
||||
if (options.accepts[0].extensions.indexOf(extension) > -1) {
|
||||
chromeCallbackWithSuccess(entry, callback);
|
||||
} else {
|
||||
navigator.notification.alert('Invalid file extension', function() {
|
||||
chromeCallbackWithError(`${self.logHeader}file opened has an incorrect extension`, callback);
|
||||
}, 'Choose a file', 'Ok');
|
||||
}
|
||||
});
|
||||
} else {
|
||||
console.log('no extensions : any type of file accepted');
|
||||
chromeCallbackWithSuccess(entry, callback);
|
||||
}
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
},
|
||||
chooseEntrySaveFile: function(options, callback) {
|
||||
const self = this;
|
||||
if (!options.suggestedName) {
|
||||
options.suggestedName = 'newfile';
|
||||
}
|
||||
const extension = self.getFileExtension(options.suggestedName);
|
||||
const folder = 'Betaflight configurator';
|
||||
navigator.notification.prompt(i18n.getMessage('dialogFileNameDescription', {
|
||||
folder: folder,
|
||||
}), function(res) {
|
||||
if (res.buttonIndex === 1) {
|
||||
const newExtension = self.getFileExtension(res.input1);
|
||||
let fileName = res.input1;
|
||||
if (newExtension === undefined) {
|
||||
fileName += `.${extension}`;
|
||||
}
|
||||
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory, function(rootEntry) {
|
||||
rootEntry.getDirectory(folder, { create: true }, function(directoryEntry) {
|
||||
directoryEntry.getFile(fileName, { create: false }, function(fileEntry) {
|
||||
console.log(fileEntry);
|
||||
navigator.notification.confirm(i18n.getMessage('dialogFileAlreadyExistsDescription'), function(resp) {
|
||||
if (resp === 1) {
|
||||
chromeCallbackWithSuccess(fileEntry, callback);
|
||||
} else {
|
||||
chromeCallbackWithError(`${self.logHeader}Canceled: file already exists`, callback);
|
||||
}
|
||||
}, i18n.getMessage('dialogFileAlreadyExistsTitle'), [i18n.getMessage('yes'), i18n.getMessage('cancel')]);
|
||||
}, function() {
|
||||
directoryEntry.getFile(fileName, { create: true }, function(fileEntry) {
|
||||
chromeCallbackWithSuccess(fileEntry, callback);
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
});
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
}, function(error) {
|
||||
chromeCallbackWithError(self.logHeader+error, callback);
|
||||
});
|
||||
} else {
|
||||
chromeCallbackWithError(`${self.logHeader}Canceled: no file name`, callback);
|
||||
}
|
||||
}, i18n.getMessage('dialogFileNameTitle'), [i18n.getMessage('initialSetupButtonSave'), i18n.getMessage('cancel')], options.suggestedName);
|
||||
},
|
||||
chooseEntry: function(options, callback) {
|
||||
const self = this;
|
||||
if (typeof options === 'undefined' || typeof options.type === 'undefined') {
|
||||
self.chooseEntryOpenFile(options, callback);
|
||||
} else if (options.type === 'openDirectory') {
|
||||
// not supported yet
|
||||
console.warn('chrome.fileSystem.chooseEntry: options.type = openDirectory not supported yet');
|
||||
chromeCallbackWithSuccess(undefined, callback);
|
||||
} else if (options.type === 'openWritableFile') {
|
||||
// Entry returned by chooseEntry method is writable on Android
|
||||
self.chooseEntryOpenFile(options, callback);
|
||||
} else if (options.type === 'saveFile') {
|
||||
self.chooseEntrySaveFile(options, callback);
|
||||
} else {
|
||||
self.chooseEntryOpenFile(options, callback);
|
||||
}
|
||||
},
|
||||
restoreEntry: function(id, callback) {
|
||||
this.isRestorable(id, function(isRestorable) {
|
||||
if (isRestorable) {
|
||||
chromeCallbackWithSuccess(this.savedEntries[id], callback);
|
||||
} else {
|
||||
chromeCallbackWithError(`${self.logHeader}This entry can't be restored`, callback);
|
||||
}
|
||||
});
|
||||
},
|
||||
isRestorable: function(id, callback) {
|
||||
if (typeof this.savedEntries[id] !== 'undefined') {
|
||||
chromeCallbackWithSuccess(true, callback);
|
||||
} else {
|
||||
chromeCallbackWithSuccess(false, callback);
|
||||
}
|
||||
},
|
||||
retainEntry: function(entry) {
|
||||
const id = this.savedEntries.length;
|
||||
if (id >= 500) {
|
||||
for (let i=0 ; i<500 ; i++) {
|
||||
if (i < 499) {
|
||||
this.savedEntries[i] = this.savedEntries[i+1];
|
||||
} else {
|
||||
this.savedEntries[i] = entry;
|
||||
}
|
||||
}
|
||||
return 499;
|
||||
} else {
|
||||
this.savedEntries[id] = entry;
|
||||
return id;
|
||||
}
|
||||
},
|
||||
/**requestFileSystem: function(options, callback) { },
|
||||
getVolumeList: function(callback) { },*/
|
||||
};
|
||||
|
||||
|
||||
const cordovaChromeapi = {
|
||||
init: function(callback) {
|
||||
chrome.serial = chromeapiSerial;
|
||||
chrome.fileSystem = chromeapiFilesystem;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
},
|
||||
};
|
67
src/js/cordova_startup.js
vendored
Normal file
67
src/js/cordova_startup.js
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
'use strict';
|
||||
|
||||
const cordovaUI = {
|
||||
uiZoom: 1,
|
||||
canChangeUI: true,
|
||||
init: async function() {
|
||||
const self = this;
|
||||
const screenWidth = $(window).width();
|
||||
const screenHeight = $(window).height();
|
||||
let length;
|
||||
let orientation;
|
||||
if (screenWidth > screenHeight) {
|
||||
length = screenWidth;
|
||||
orientation = 'landscape';
|
||||
} else {
|
||||
length = screenHeight;
|
||||
orientation = 'portrait';
|
||||
}
|
||||
if (length < 1024) {
|
||||
self.uiZoom = length/1024;
|
||||
}
|
||||
if (screenWidth > 575 && screenHeight > 575) {
|
||||
self.canChangeUI = false;
|
||||
}
|
||||
ConfigStorage.get('cordovaForceComputerUI', function (result) {
|
||||
if (result.cordovaForceComputerUI === undefined) {
|
||||
if ((orientation === 'landscape' && screenHeight <= 575)
|
||||
|| (orientation === 'portrait' && screenWidth <= 575)) {
|
||||
ConfigStorage.set({'cordovaForceComputerUI': false});
|
||||
} else {
|
||||
ConfigStorage.set({'cordovaForceComputerUI': true});
|
||||
}
|
||||
}
|
||||
});
|
||||
self.set();
|
||||
},
|
||||
set: function() {
|
||||
const self = this;
|
||||
ConfigStorage.get('cordovaForceComputerUI', function (result) {
|
||||
if (result.cordovaForceComputerUI) {
|
||||
window.screen.orientation.lock('landscape');
|
||||
$('body').css('zoom', self.uiZoom);
|
||||
} else {
|
||||
window.screen.orientation.lock('portrait');
|
||||
$('body').css('zoom', 1);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const cordovaApp = {
|
||||
initialize: function() {
|
||||
this.bindEvents();
|
||||
},
|
||||
bindEvents: function() {
|
||||
document.addEventListener('deviceready', this.onDeviceReady, false);
|
||||
},
|
||||
onDeviceReady: function() {
|
||||
$('.open_firmware_flasher, .tab_firmware_flasher').hide();
|
||||
cordovaUI.init();
|
||||
navigator.splashscreen.hide();
|
||||
cordovaChromeapi.init();
|
||||
appReady();
|
||||
},
|
||||
};
|
||||
|
||||
cordovaApp.initialize();
|
|
@ -19,6 +19,7 @@ var GUI_control = function () {
|
|||
'changelog',
|
||||
'firmware_flasher',
|
||||
'privacy_policy',
|
||||
'options',
|
||||
'help'
|
||||
];
|
||||
this.defaultAllowedFCTabsWhenConnected = [
|
||||
|
@ -48,33 +49,51 @@ var GUI_control = function () {
|
|||
this.allowedTabs = this.defaultAllowedTabsWhenDisconnected;
|
||||
|
||||
// check which operating system is user running
|
||||
if (navigator.appVersion.indexOf("Win") != -1) this.operating_system = "Windows";
|
||||
else if (navigator.appVersion.indexOf("Mac") != -1) this.operating_system = "MacOS";
|
||||
else if (navigator.appVersion.indexOf("CrOS") != -1) this.operating_system = "ChromeOS";
|
||||
else if (navigator.appVersion.indexOf("Linux") != -1) this.operating_system = "Linux";
|
||||
else if (navigator.appVersion.indexOf("X11") != -1) this.operating_system = "UNIX";
|
||||
else this.operating_system = "Unknown";
|
||||
this.operating_system = GUI_checkOperatingSystem();
|
||||
|
||||
// Check the method of execution
|
||||
this.nwGui = null;
|
||||
try {
|
||||
this.nwGui = require('nw.gui');
|
||||
this.Mode = GUI_Modes.NWJS;
|
||||
this.nwGui = require('nw.gui');
|
||||
this.Mode = GUI_Modes.NWJS;
|
||||
} catch (ex) {
|
||||
if (window.chrome && chrome.storage && chrome.storage.local) {
|
||||
this.Mode = GUI_Modes.ChromeApp;
|
||||
} else {
|
||||
this.Mode = GUI_Modes.Other;
|
||||
}
|
||||
if (typeof cordovaApp !== 'undefined') {
|
||||
this.Mode = GUI_Modes.Cordova;
|
||||
} else {
|
||||
if (window.chrome && chrome.storage && chrome.storage.local) {
|
||||
this.Mode = GUI_Modes.ChromeApp;
|
||||
} else {
|
||||
this.Mode = GUI_Modes.Other;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const GUI_Modes = {
|
||||
NWJS: "NW.js",
|
||||
ChromeApp: "Chrome",
|
||||
Cordova: "Cordova",
|
||||
Other: "Other"
|
||||
};
|
||||
|
||||
function GUI_checkOperatingSystem() {
|
||||
if (navigator.appVersion.indexOf("Win") !== -1) {
|
||||
return "Windows";
|
||||
} else if (navigator.appVersion.indexOf("Mac") !== -1) {
|
||||
return "MacOS";
|
||||
} else if (navigator.appVersion.indexOf("CrOS") !== -1) {
|
||||
return "ChromeOS";
|
||||
} else if (navigator.appVersion.indexOf("Android") !== -1) {
|
||||
return "Android";
|
||||
} else if (navigator.appVersion.indexOf("Linux") !== -1) {
|
||||
return "Linux";
|
||||
} else if (navigator.appVersion.indexOf("X11") !== -1) {
|
||||
return "UNIX";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
// Timer managing methods
|
||||
|
||||
// name = string
|
||||
|
@ -363,13 +382,16 @@ GUI_control.prototype.selectDefaultTabWhenConnected = function() {
|
|||
};
|
||||
|
||||
GUI_control.prototype.isChromeApp = function () {
|
||||
return this.Mode == GUI_Modes.ChromeApp;
|
||||
return this.Mode === GUI_Modes.ChromeApp;
|
||||
};
|
||||
GUI_control.prototype.isNWJS = function () {
|
||||
return this.Mode == GUI_Modes.NWJS;
|
||||
return this.Mode === GUI_Modes.NWJS;
|
||||
};
|
||||
GUI_control.prototype.isCordova = function () {
|
||||
return this.Mode === GUI_Modes.Cordova;
|
||||
};
|
||||
GUI_control.prototype.isOther = function () {
|
||||
return this.Mode == GUI_Modes.Other;
|
||||
return this.Mode === GUI_Modes.Other;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -51,10 +51,12 @@ i18n.init = function(cb) {
|
|||
};
|
||||
|
||||
i18n.changeLanguage = function(languageSelected) {
|
||||
ConfigStorage.set({'userLanguageSelect': languageSelected});
|
||||
i18next.changeLanguage(getValidLocale(languageSelected));
|
||||
i18n.selectedLanguage = languageSelected;
|
||||
GUI.log(i18n.getMessage('language_changed'));
|
||||
if (typeof ConfigStorage !== 'undefined') {
|
||||
ConfigStorage.set({'userLanguageSelect': languageSelected});
|
||||
}
|
||||
i18next.changeLanguage(getValidLocale(languageSelected));
|
||||
i18n.selectedLanguage = languageSelected;
|
||||
GUI.log(i18n.getMessage('language_changed'));
|
||||
};
|
||||
|
||||
i18n.getMessage = function(messageID, parameters) {
|
||||
|
@ -159,17 +161,22 @@ i18n.localizePage = function(forceReTranslate) {
|
|||
* returns the current locale to the callback
|
||||
*/
|
||||
function getStoredUserLocale(cb) {
|
||||
ConfigStorage.get('userLanguageSelect', function (result) {
|
||||
let userLanguage = 'DEFAULT';
|
||||
if (result.userLanguageSelect) {
|
||||
userLanguage = result.userLanguageSelect;
|
||||
}
|
||||
i18n.selectedLanguage = userLanguage;
|
||||
if (typeof ConfigStorage !== 'undefined') {
|
||||
ConfigStorage.get('userLanguageSelect', function (result) {
|
||||
let userLanguage = 'DEFAULT';
|
||||
if (result.userLanguageSelect) {
|
||||
userLanguage = result.userLanguageSelect;
|
||||
}
|
||||
i18n.selectedLanguage = userLanguage;
|
||||
|
||||
userLanguage = getValidLocale(userLanguage);
|
||||
userLanguage = getValidLocale(userLanguage);
|
||||
|
||||
cb(userLanguage);
|
||||
});
|
||||
} else {
|
||||
const userLanguage = getValidLocale('DEFAULT');
|
||||
cb(userLanguage);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function getValidLocale(userLocale) {
|
||||
|
|
158
src/js/main.js
158
src/js/main.js
|
@ -4,6 +4,12 @@ window.googleAnalytics = analytics;
|
|||
window.analytics = null;
|
||||
|
||||
$(document).ready(function () {
|
||||
if (typeof cordovaApp === 'undefined') {
|
||||
appReady();
|
||||
}
|
||||
});
|
||||
|
||||
function appReady() {
|
||||
$.getJSON('version.json', function(data) {
|
||||
CONFIGURATOR.version = data.version;
|
||||
CONFIGURATOR.gitChangesetId = data.gitChangesetId;
|
||||
|
@ -29,7 +35,7 @@ $(document).ready(function () {
|
|||
initializeSerialBackend();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkSetupAnalytics(callback) {
|
||||
if (!analytics) {
|
||||
|
@ -143,13 +149,17 @@ function closeSerial() {
|
|||
}
|
||||
|
||||
function closeHandler() {
|
||||
this.hide();
|
||||
if (!GUI.isCordova()) {
|
||||
this.hide();
|
||||
}
|
||||
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' });
|
||||
|
||||
closeSerial();
|
||||
|
||||
this.close(true);
|
||||
if (!GUI.isCordova()) {
|
||||
this.close(true);
|
||||
}
|
||||
}
|
||||
|
||||
//Process to execute to real start the app
|
||||
|
@ -171,14 +181,16 @@ function startProcess() {
|
|||
GUI.nwGui.Shell.openExternal(url);
|
||||
});
|
||||
nwWindow.on('close', closeHandler);
|
||||
} else if (!GUI.isOther()) {
|
||||
} else if (GUI.isChromeApp()) {
|
||||
chrome.app.window.onClosed.addListener(closeHandler);
|
||||
// This event does not actually get fired:
|
||||
chrome.runtime.onSuspend.addListener(closeHandler);
|
||||
} else if (GUI.isCordova()) {
|
||||
window.addEventListener('beforeunload', closeHandler);
|
||||
}
|
||||
|
||||
$('.connect_b a.connect').removeClass('disabled');
|
||||
$('#logo .version').text(CONFIGURATOR.version);
|
||||
$('#logo .version, #tab_logoversion .version').text(CONFIGURATOR.version);
|
||||
updateStatusBarVersion();
|
||||
updateTopBarVersion();
|
||||
|
||||
|
@ -202,6 +214,10 @@ function startProcess() {
|
|||
);
|
||||
});
|
||||
|
||||
if (GUI.isCordova()) {
|
||||
UI_PHONES.init();
|
||||
}
|
||||
|
||||
const ui_tabs = $('#tabs > ul');
|
||||
$('a', ui_tabs).click(function () {
|
||||
if ($(this).parent().hasClass('active') === false && !GUI.tab_switch_in_progress) { // only initialize when the tab isn't already active
|
||||
|
@ -274,6 +290,9 @@ function startProcess() {
|
|||
case 'privacy_policy':
|
||||
TABS.staticTab.initialize('privacy_policy', content_ready);
|
||||
break;
|
||||
case 'options':
|
||||
TABS.options.initialize(content_ready);
|
||||
break;
|
||||
case 'firmware_flasher':
|
||||
TABS.firmware_flasher.initialize(content_ready);
|
||||
break;
|
||||
|
@ -354,117 +373,6 @@ function startProcess() {
|
|||
|
||||
$('#tabs ul.mode-disconnected li a:first').click();
|
||||
|
||||
// options
|
||||
$('a#options').click(function () {
|
||||
const el = $(this);
|
||||
|
||||
if (!el.hasClass('active')) {
|
||||
el.addClass('active');
|
||||
el.after('<div id="options-window"></div>');
|
||||
|
||||
$('div#options-window').load('./tabs/options.html', function () {
|
||||
// translate to user-selected language
|
||||
i18n.localizePage();
|
||||
|
||||
ConfigStorage.get('permanentExpertMode', function (result) {
|
||||
if (result.permanentExpertMode) {
|
||||
$('div.permanentExpertMode input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.permanentExpertMode input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'permanentExpertMode': checked});
|
||||
|
||||
$('input[name="expertModeCheckbox"]').prop('checked', checked).change();
|
||||
}).change();
|
||||
});
|
||||
|
||||
ConfigStorage.get('rememberLastTab', function (result) {
|
||||
$('div.rememberLastTab input')
|
||||
.prop('checked', !!result.rememberLastTab)
|
||||
.change(function() { ConfigStorage.set({rememberLastTab: $(this).is(':checked')}); })
|
||||
.change();
|
||||
});
|
||||
|
||||
if (GUI.operating_system !== 'ChromeOS') {
|
||||
ConfigStorage.get('checkForConfiguratorUnstableVersions', function (result) {
|
||||
if (result.checkForConfiguratorUnstableVersions) {
|
||||
$('div.checkForConfiguratorUnstableVersions input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.checkForConfiguratorUnstableVersions input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'checkForConfiguratorUnstableVersions': checked});
|
||||
|
||||
checkForConfiguratorUpdates();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('div.checkForConfiguratorUnstableVersions').hide();
|
||||
}
|
||||
|
||||
ConfigStorage.get('analyticsOptOut', function (result) {
|
||||
if (result.analyticsOptOut) {
|
||||
$('div.analyticsOptOut input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.analyticsOptOut input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'analyticsOptOut': checked});
|
||||
|
||||
checkSetupAnalytics(function (analyticsService) {
|
||||
if (checked) {
|
||||
analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptOut');
|
||||
}
|
||||
|
||||
analyticsService.setOptOut(checked);
|
||||
|
||||
if (!checked) {
|
||||
analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptIn');
|
||||
}
|
||||
});
|
||||
}).change();
|
||||
});
|
||||
|
||||
$('div.cliAutoComplete input')
|
||||
.prop('checked', CliAutoComplete.configEnabled)
|
||||
.change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'cliAutoComplete': checked});
|
||||
CliAutoComplete.setEnabled(checked);
|
||||
}).change();
|
||||
|
||||
$('#darkThemeSelect')
|
||||
.val(DarkTheme.configEnabled)
|
||||
.change(function () {
|
||||
const value = parseInt($(this).val());
|
||||
|
||||
ConfigStorage.set({'darkTheme': value});
|
||||
setDarkTheme(value);
|
||||
}).change();
|
||||
|
||||
function close_and_cleanup(e) {
|
||||
if (e.type === 'click' && !$.contains($('div#options-window')[0], e.target) || e.type === 'keyup' && e.keyCode === 27) {
|
||||
$(document).unbind('click keyup', close_and_cleanup);
|
||||
|
||||
$('div#options-window').slideUp(250, function () {
|
||||
el.removeClass('active');
|
||||
$(this).empty().remove();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$(document).bind('click keyup', close_and_cleanup);
|
||||
|
||||
$(this).slideDown(250);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// listen to all input change events and adjust the value within limits if necessary
|
||||
$("#content").on('focus', 'input[type="number"]', function () {
|
||||
const element = $(this);
|
||||
|
@ -535,22 +443,19 @@ function startProcess() {
|
|||
$("#showlog").on('click', function () {
|
||||
let state = $(this).data('state');
|
||||
if (state) {
|
||||
$("#log").animate({height: 27}, 200, function () {
|
||||
setTimeout(function() {
|
||||
const command_log = $('div#log');
|
||||
command_log.scrollTop($('div.wrapper', command_log).height());
|
||||
});
|
||||
}, 200);
|
||||
$("#log").removeClass('active');
|
||||
$("#content").removeClass('logopen');
|
||||
$(".tab_container").removeClass('logopen');
|
||||
$("#tab-content-container").removeClass('logopen');
|
||||
$("#scrollicon").removeClass('active');
|
||||
ConfigStorage.set({'logopen': false});
|
||||
|
||||
state = false;
|
||||
} else {
|
||||
$("#log").animate({height: 111}, 200);
|
||||
$("#log").addClass('active');
|
||||
$("#content").addClass('logopen');
|
||||
$(".tab_container").addClass('logopen');
|
||||
$("#tab-content-container").addClass('logopen');
|
||||
$("#scrollicon").addClass('active');
|
||||
ConfigStorage.set({'logopen': true});
|
||||
|
||||
|
@ -567,11 +472,12 @@ function startProcess() {
|
|||
});
|
||||
|
||||
ConfigStorage.get('permanentExpertMode', function (result) {
|
||||
const experModeCheckbox = 'input[name="expertModeCheckbox"]';
|
||||
if (result.permanentExpertMode) {
|
||||
$('input[name="expertModeCheckbox"]').prop('checked', true);
|
||||
$(experModeCheckbox).prop('checked', true);
|
||||
}
|
||||
|
||||
$('input[name="expertModeCheckbox"]').change(function () {
|
||||
$(experModeCheckbox).change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
checkSetupAnalytics(function (analyticsService) {
|
||||
analyticsService.setDimension(analyticsService.DIMENSIONS.CONFIGURATOR_EXPERT_MODE, checked ? 'On' : 'Off');
|
||||
|
@ -819,7 +725,7 @@ function updateTopBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
|||
|
||||
const versionText = `${configuratorVersion}<br />${firmwareVersionAndId}<br />${targetVersion}`;
|
||||
|
||||
$('#logo .logo_text').html(versionText);
|
||||
$('#logo .logo_text, #tab_logoversion .version').html(versionText);
|
||||
}
|
||||
|
||||
function updateStatusBarVersion(firmwareVersion, firmwareId, hardwareId) {
|
||||
|
|
251
src/js/main_cordova.js
Normal file
251
src/js/main_cordova.js
Normal file
|
@ -0,0 +1,251 @@
|
|||
'use strict';
|
||||
|
||||
const REQUIRED_WEBVIEW_VERSION = 72;
|
||||
const WEBVIEW = {
|
||||
chromeVersion: '',
|
||||
majorChromeVersion: 0,
|
||||
appsId: {
|
||||
androidWebview: 'com.android.webview',
|
||||
googleWebview: 'com.google.android.webview',
|
||||
chrome: 'com.android.chrome',
|
||||
},
|
||||
apps: {
|
||||
'com.android.webview': { },
|
||||
'com.google.android.webview': {
|
||||
name: 'Android System WebView',
|
||||
displayName: 'Google Android Webview',
|
||||
},
|
||||
'com.android.chrome': {
|
||||
name: 'Google Chrome',
|
||||
displayName: 'Chrome',
|
||||
},
|
||||
},
|
||||
matchingVersion: 0,
|
||||
usedApp: null,
|
||||
uptodateApps: [],
|
||||
htmlElements: {
|
||||
webview_step_msg: '#webview_step_msg',
|
||||
webview_step_btn1: '#webview_step_btn1',
|
||||
webview_step_btn2: '#webview_step_btn2',
|
||||
},
|
||||
advices: {
|
||||
installGoogleAndroidWebview: function(callback) {
|
||||
$(WEBVIEW.htmlElements.webview_step_msg).html(i18n.getMessage('cordovaWebviewInstall', {
|
||||
app: WEBVIEW.apps[WEBVIEW.appsId.googleWebview].name,
|
||||
}));
|
||||
$('#webview_step_btn1').text(i18n.getMessage('cordovaWebviewInstallBtn'))
|
||||
.attr('app_id', WEBVIEW.appsId.googleWebview);
|
||||
callback();
|
||||
},
|
||||
updateGoogleAndroidWebview: function(callback) {
|
||||
$(WEBVIEW.htmlElements.webview_step_msg).html(i18n.getMessage('cordovaWebviewUpdate', {
|
||||
app: WEBVIEW.apps[WEBVIEW.appsId.googleWebview].name,
|
||||
}));
|
||||
$(WEBVIEW.htmlElements.webview_step_btn1).text(i18n.getMessage('cordovaWebviewUpdateBtn'))
|
||||
.attr('app_id', WEBVIEW.appsId.googleWebview);
|
||||
callback();
|
||||
},
|
||||
updateAndroidChrome: function(callback) {
|
||||
$(WEBVIEW.htmlElements.webview_step_msg).html(i18n.getMessage('cordovaWebviewUpdate', {
|
||||
app: WEBVIEW.apps[WEBVIEW.appsId.chrome].name,
|
||||
}));
|
||||
$(WEBVIEW.htmlElements.webview_step_btn1).text(i18n.getMessage('cordovaWebviewUpdateBtn'))
|
||||
.attr('app_id', WEBVIEW.appsId.chrome);
|
||||
callback();
|
||||
},
|
||||
uninstallGoogleAndroidWebview: function(callback) {
|
||||
$(WEBVIEW.htmlElements.webview_step_msg).html(i18n.getMessage('cordovaWebviewUninstall', {
|
||||
app: WEBVIEW.apps[WEBVIEW.appsId.googleWebview].name,
|
||||
}));
|
||||
$(WEBVIEW.htmlElements.webview_step_btn1).text(i18n.getMessage('cordovaWebviewUninstallBtn1'))
|
||||
.attr('app_id', WEBVIEW.appsId.googleWebview);
|
||||
$(WEBVIEW.htmlElements.webview_step_btn2).text(i18n.getMessage('cordovaWebviewUninstallBtn2'))
|
||||
.attr('app_id', WEBVIEW.appsId.googleWebview)
|
||||
.show();
|
||||
callback();
|
||||
},
|
||||
selectWebview: function(id, callback) {
|
||||
let app;
|
||||
if (id === WEBVIEW.appsId.googleWebview) {
|
||||
app = WEBVIEW.apps[WEBVIEW.appsId.googleWebview].displayName;
|
||||
} else if (id === WEBVIEW.appsId.chrome) {
|
||||
app = WEBVIEW.apps[WEBVIEW.appsId.chrome].displayName;
|
||||
}
|
||||
$(WEBVIEW.htmlElements.webview_step_msg).html(i18n.getMessage('cordovaWebviewEnable', {
|
||||
app: app,
|
||||
}));
|
||||
$(WEBVIEW.htmlElements.webview_step_btn1).hide();
|
||||
$(WEBVIEW.htmlElements.webview_step_btn2).text(i18n.getMessage('cordovaWebviewEnableBtn')).show();
|
||||
callback();
|
||||
},
|
||||
},
|
||||
getAdvice1: function(callback) {
|
||||
const self = this;
|
||||
if (self.usedApp === WEBVIEW.appsId.googleWebview) {
|
||||
self.advices.updateGoogleAndroidWebview(callback);
|
||||
} else if (self.usedApp === WEBVIEW.appsId.chrome) {
|
||||
self.advices.updateAndroidChrome(callback);
|
||||
}
|
||||
},
|
||||
getAdvice2: function(callback) {
|
||||
const self = this;
|
||||
if (self.uptodateApps.length > 0) {
|
||||
self.advices.selectWebview(callback);
|
||||
} else {
|
||||
if ((self.apps[WEBVIEW.appsId.googleWebview].installed && self.apps[WEBVIEW.appsId.googleWebview].enabled)
|
||||
&& (self.apps[WEBVIEW.appsId.chrome].installed && self.apps[WEBVIEW.appsId.chrome].enabled)) {
|
||||
self.advices.uninstallGoogleAndroidWebview(callback);
|
||||
} else if (!(self.apps[WEBVIEW.appsId.googleWebview].installed && self.apps[WEBVIEW.appsId.googleWebview].enabled)
|
||||
&& !(self.apps[WEBVIEW.appsId.chrome].installed && self.apps[WEBVIEW.appsId.chrome].enabled)) {
|
||||
self.advices.installGoogleAndroidWebview(callback);
|
||||
} else {
|
||||
self.getAdvice3(callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
getAdvice3: function(callback) {
|
||||
const self = this;
|
||||
if (self.apps[WEBVIEW.appsId.googleWebview].installed && self.apps[WEBVIEW.appsId.googleWebview].enabled
|
||||
&& !self.apps[WEBVIEW.appsId.googleWebview].uptodate) {
|
||||
self.advices.updateGoogleAndroidWebview(callback);
|
||||
} else if (self.apps[WEBVIEW.appsId.chrome].installed && self.apps[WEBVIEW.appsId.chrome].enabled
|
||||
&& !self.apps[WEBVIEW.appsId.chrome].uptodate) {
|
||||
self.advices.updateAndroidChrome(callback);
|
||||
}
|
||||
},
|
||||
getAdvice: function(callback) {
|
||||
const self = this;
|
||||
if (self.usedApp && self.usedApp !== WEBVIEW.appsId.androidWebview) {
|
||||
this.getAdvice1(callback);
|
||||
} else {
|
||||
this.getAdvice2(callback);
|
||||
}
|
||||
},
|
||||
tryToFindUsedApp: function(callback) {
|
||||
const self = this;
|
||||
const appsId = Object.keys(self.apps);
|
||||
for (let i=0; i<appsId.length; i++) {
|
||||
const id = appsId[i];
|
||||
if (self.matchingVersion === 1 && self.apps[id].used === 'could') {
|
||||
self.apps[id].used = 'yes';
|
||||
self.usedApp = id;
|
||||
$(`li[app_id='${id}']`).append(` (<span style="color: green">${i18n.getMessage('cordovaWebviewUsed')}</span>)`);
|
||||
}
|
||||
if (i === appsId.length-1) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
},
|
||||
checkInstalledApps: function(callback) {
|
||||
const self = this;
|
||||
const appsId = Object.keys(self.apps);
|
||||
let installedApps = 0;
|
||||
|
||||
function checkAvailability(id, i) {
|
||||
appAvailability.check(id, function(info) {
|
||||
appInstalled(info, id, i);
|
||||
}, function() {
|
||||
appNotInstalled(id, i);
|
||||
});
|
||||
}
|
||||
function end(i) {
|
||||
if (i === appsId.length-1) {
|
||||
if (installedApps === 0) {
|
||||
$('#webview_apps').append('<li i18n="cordovaNoWebview" style="color: red"></li>');
|
||||
}
|
||||
i18n.localizePage();
|
||||
console.log('callback');
|
||||
callback();
|
||||
}
|
||||
}
|
||||
function appInstalled(info, id, i) {
|
||||
installedApps++;
|
||||
self.apps[id].installed = true;
|
||||
self.apps[id].enabled = info.enabled;
|
||||
self.apps[id].version = info.version;
|
||||
self.apps[id].majorVersion = parseInt(info.version.split('.')[0]);
|
||||
if (self.chromeVersion === self.apps[id].version) {
|
||||
self.apps[id].used = 'could';
|
||||
self.matchingVersion++;
|
||||
} else {
|
||||
self.apps[id].used = 'no';
|
||||
}
|
||||
let color;
|
||||
if (self.apps[id].majorVersion >= REQUIRED_WEBVIEW_VERSION) {
|
||||
color = 'green';
|
||||
self.apps[id].uptodate = true;
|
||||
self.uptodateApps.push(id);
|
||||
} else {
|
||||
color = 'red';
|
||||
self.apps[id].uptodate = false;
|
||||
}
|
||||
let app = `<li app_id="${id}">${id} (<span style="color: ${color}">${self.apps[id].version}</span>)`;
|
||||
if (!self.apps[id].enabled) {
|
||||
app += ' (<span i18n="portsTelemetryDisabled"></span>)';
|
||||
}
|
||||
app += '</li>';
|
||||
$('#webview_apps').append(app);
|
||||
end(i);
|
||||
}
|
||||
function appNotInstalled(id, i) {
|
||||
self.apps[id].installed = false;
|
||||
end(i);
|
||||
}
|
||||
|
||||
for (let i=0; i<appsId.length; i++) {
|
||||
const id = appsId[i];
|
||||
checkAvailability(id, i);
|
||||
}
|
||||
},
|
||||
exec: function() {
|
||||
const self = this;
|
||||
$('#webview_troubleshooting').hide();
|
||||
$('#loading').show();
|
||||
self.chromeVersion = window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/, "$1");
|
||||
self.majorChromeVersion = self.chromeVersion.split('.')[0];
|
||||
if (self.majorChromeVersion >= REQUIRED_WEBVIEW_VERSION) {
|
||||
navigator.splashscreen.show();
|
||||
document.location.href = 'main.html';
|
||||
} else {
|
||||
navigator.splashscreen.hide();
|
||||
self.checkInstalledApps(function() {
|
||||
self.tryToFindUsedApp(function() {
|
||||
self.getAdvice(function() {
|
||||
$('#loading').hide();
|
||||
$('#webview_troubleshooting').show();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
const cordovaApp = {
|
||||
initialize: function() {
|
||||
this.bindEvents();
|
||||
},
|
||||
bindEvents: function() {
|
||||
document.addEventListener('deviceready', this.onDeviceReady, false);
|
||||
},
|
||||
onDeviceReady: function() {
|
||||
i18n.init(function() {
|
||||
i18n.localizePage();
|
||||
WEBVIEW.exec();
|
||||
});
|
||||
},
|
||||
};
|
||||
cordovaApp.initialize();
|
||||
|
||||
$(WEBVIEW.htmlElements.webview_step_btn1).on('click', function() {
|
||||
const appId = $(WEBVIEW.htmlElements.webview_step_btn1).attr('app_id');
|
||||
cordova.plugins.market.open(appId);
|
||||
});
|
||||
$(WEBVIEW.htmlElements.webview_step_btn2).on('click', function() {
|
||||
if ($(WEBVIEW.htmlElements.webview_step_btn2).attr('app_id') !== undefined) {
|
||||
const appId = $(WEBVIEW.htmlElements.webview_step_btn2).attr('app_id');
|
||||
window.cordova.plugins.settings.open(['application_details', false, appId]);
|
||||
} else {
|
||||
window.cordova.plugins.settings.open('settings');
|
||||
}
|
||||
});
|
|
@ -146,6 +146,8 @@ Model.prototype.resize = function () {
|
|||
};
|
||||
|
||||
Model.prototype.dispose = function () {
|
||||
this.renderer.forceContextLoss();
|
||||
this.renderer.dispose();
|
||||
if (this.canUseWebGLRenderer()) {
|
||||
this.renderer.forceContextLoss();
|
||||
this.renderer.dispose();
|
||||
}
|
||||
};
|
||||
|
|
87
src/js/phones_ui.js
Normal file
87
src/js/phones_ui.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
'use strict';
|
||||
|
||||
const UI_PHONES = {
|
||||
background: '#background',
|
||||
tabContainer: '.tab_container',
|
||||
tabContentContainer: '#tab-content-container',
|
||||
headerbar: '.headerbar',
|
||||
init: function() {
|
||||
const self = this;
|
||||
$('#menu_btn').click(function() {
|
||||
self.openSideMenu();
|
||||
});
|
||||
$(this.background).click(function() {
|
||||
self.closeSideMenu();
|
||||
});
|
||||
$('#tabs a').click(function() {
|
||||
if ($('.tab_container').hasClass('reveal')) {
|
||||
self.closeSideMenu();
|
||||
}
|
||||
});
|
||||
$('#reveal_btn').click(function() {
|
||||
self.expandHeader();
|
||||
});
|
||||
$(`${this.background}, ${this.tabContainer}`).swipe( {
|
||||
swipeLeft: function() {
|
||||
self.closeSideMenu();
|
||||
},
|
||||
});
|
||||
$('#side_menu_swipe').swipe( {
|
||||
swipeRight: function() {
|
||||
self.openSideMenu();
|
||||
},
|
||||
});
|
||||
},
|
||||
initToolbar: function() {
|
||||
$('.toolbar_expand_btn').click(this.expandToolbar);
|
||||
},
|
||||
openSideMenu: function() {
|
||||
$(this.background).fadeIn(300);
|
||||
$(this.tabContainer).addClass('reveal');
|
||||
},
|
||||
closeSideMenu: function() {
|
||||
$(this.background).fadeOut(300);
|
||||
$(this.tabContainer).removeClass('reveal');
|
||||
},
|
||||
expandHeader: function() {
|
||||
const self = this;
|
||||
let expand, headerExpanded, reveal;
|
||||
if (GUI.connected_to) {
|
||||
expand = 'expand2';
|
||||
headerExpanded = 'header_expanded2';
|
||||
reveal = '.header-wrapper';
|
||||
} else {
|
||||
expand = 'expand';
|
||||
headerExpanded = 'headerExpanded';
|
||||
reveal = '#port-picker';
|
||||
}
|
||||
if ($(self.headerbar).hasClass(expand)) {
|
||||
$(reveal).removeClass('reveal');
|
||||
setTimeout(function() {
|
||||
$(self.tabContentContainer).removeClass(headerExpanded);
|
||||
$(self.headerbar).removeClass(expand);
|
||||
}, 100);
|
||||
} else {
|
||||
$(self.tabContentContainer).addClass(headerExpanded);
|
||||
$(self.headerbar).addClass(expand);
|
||||
setTimeout(function() {
|
||||
$(reveal).addClass('reveal');
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
expandToolbar: function() {
|
||||
const toolbar = $('.content_toolbar.xs-compressed');
|
||||
if (toolbar.length > 0) {
|
||||
if ($('.content_toolbar.xs-compressed').hasClass('expanded')) {
|
||||
toolbar.removeClass('expanded');
|
||||
} else {
|
||||
toolbar.addClass('expanded');
|
||||
}
|
||||
}
|
||||
},
|
||||
reset: function() {
|
||||
$(this.tabContentContainer).removeClass('header_expanded2 header_expanded');
|
||||
$('#port-picker, .header-wrapper').removeClass('reveal');
|
||||
$(this.headerbar).removeClass('expand2 expand');
|
||||
},
|
||||
};
|
|
@ -40,7 +40,7 @@ PortHandler.check = function () {
|
|||
if (GUI.connected_to) {
|
||||
for (var i = 0; i < removed_ports.length; i++) {
|
||||
if (removed_ports[i] == GUI.connected_to) {
|
||||
$('div#port-picker a.connect').click();
|
||||
$('div#header_btns a.connect').click();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ PortHandler.check = function () {
|
|||
// we need firmware flasher protection over here
|
||||
if (GUI.active_tab != 'firmware_flasher') {
|
||||
GUI.timeout_add('auto-connect_timeout', function () {
|
||||
$('div#port-picker a.connect').click();
|
||||
$('div#header_btns a.connect').click();
|
||||
}, 100); // timeout so bus have time to initialize after being detected by the system
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +164,6 @@ PortHandler.check_usb_devices = function (callback) {
|
|||
}
|
||||
self.dfu_available = false;
|
||||
}
|
||||
|
||||
if(callback) callback(self.dfu_available);
|
||||
|
||||
if (!$('option:selected', portPickerElement).data().isDFU) {
|
||||
|
|
|
@ -68,7 +68,7 @@ function initializeSerialBackend() {
|
|||
|
||||
// lock port select & baud while we are connecting / connected
|
||||
$('div#port-picker #port, div#port-picker #baud, div#port-picker #delay').prop('disabled', true);
|
||||
$('div.connect_controls a.connect_state').text(i18n.getMessage('connecting'));
|
||||
$('div.connect_controls div.connect_state').text(i18n.getMessage('connecting'));
|
||||
|
||||
serial.connect(portName, {bitrate: selected_baud}, onOpen);
|
||||
|
||||
|
@ -107,7 +107,7 @@ function initializeSerialBackend() {
|
|||
|
||||
// auto-connect
|
||||
ConfigStorage.get('auto_connect', function (result) {
|
||||
if (result.auto_connect === 'undefined' || result.auto_connect) {
|
||||
if (result.auto_connect === undefined || result.auto_connect) {
|
||||
// default or enabled by user
|
||||
GUI.auto_connect = true;
|
||||
|
||||
|
@ -147,6 +147,10 @@ function initializeSerialBackend() {
|
|||
}
|
||||
|
||||
function finishClose(finishedCallback) {
|
||||
if (GUI.isCordova()) {
|
||||
UI_PHONES.reset();
|
||||
}
|
||||
|
||||
var wasConnected = CONFIGURATOR.connectionValid;
|
||||
|
||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.FLIGHT_CONTROLLER, 'Disconnected');
|
||||
|
@ -183,7 +187,7 @@ function finishClose(finishedCallback) {
|
|||
|
||||
// reset connect / disconnect button
|
||||
$('div.connect_controls a.connect').removeClass('active');
|
||||
$('div.connect_controls a.connect_state').text(i18n.getMessage('connect'));
|
||||
$('div.connect_controls div.connect_state').text(i18n.getMessage('connect'));
|
||||
|
||||
// reset active sensor indicators
|
||||
sensor_status(0);
|
||||
|
@ -309,7 +313,7 @@ function onOpen(openInfo) {
|
|||
}
|
||||
|
||||
function abortConnect() {
|
||||
$('div#connectbutton a.connect_state').text(i18n.getMessage('connect'));
|
||||
$('div#connectbutton div.connect_state').text(i18n.getMessage('connect'));
|
||||
$('div#connectbutton a.connect').removeClass('active');
|
||||
|
||||
// unlock port select & baud
|
||||
|
@ -409,6 +413,7 @@ function checkReportProblems() {
|
|||
});
|
||||
|
||||
problemDialog.showModal();
|
||||
$('#dialogReportProblems').scrollTop(0);
|
||||
}
|
||||
|
||||
processUid();
|
||||
|
@ -456,6 +461,10 @@ function finishOpen() {
|
|||
GUI.allowedTabs.splice(GUI.allowedTabs.indexOf('led_strip'), 1);
|
||||
}
|
||||
|
||||
if (GUI.isCordova()) {
|
||||
UI_PHONES.reset();
|
||||
}
|
||||
|
||||
onConnect();
|
||||
|
||||
GUI.selectDefaultTabWhenConnected();
|
||||
|
@ -474,7 +483,7 @@ function onConnect() {
|
|||
$('div#flashbutton a.flash').removeClass('active');
|
||||
}
|
||||
GUI.timeout_remove('connecting'); // kill connecting timer
|
||||
$('div#connectbutton a.connect_state').text(i18n.getMessage('disconnect')).addClass('active');
|
||||
$('div#connectbutton div.connect_state').text(i18n.getMessage('disconnect')).addClass('active');
|
||||
$('div#connectbutton a.connect').addClass('active');
|
||||
|
||||
$('#tabs ul.mode-disconnected').hide();
|
||||
|
|
|
@ -176,9 +176,13 @@ TABS.auxiliary.initialize = function (callback) {
|
|||
$(elementName + ' .channel-slider').Link('lower').to($(elementName + ' .lowerLimitValue'));
|
||||
$(elementName + ' .channel-slider').Link('upper').to($(elementName + ' .upperLimitValue'));
|
||||
|
||||
let sliderValues = [900, 1000, 1200, 1400, 1500, 1600, 1800, 2000, 2100];
|
||||
if ($(window).width() < 575) {
|
||||
sliderValues = [1000, 1200, 1400, 1600, 1800, 2000];
|
||||
}
|
||||
$(rangeElement).find(".pips-channel-range").noUiSlider_pips({
|
||||
mode: 'values',
|
||||
values: [900, 1000, 1200, 1400, 1500, 1600, 1800, 2000, 2100],
|
||||
values: sliderValues,
|
||||
density: 4,
|
||||
stepped: true
|
||||
});
|
||||
|
@ -250,7 +254,7 @@ TABS.auxiliary.initialize = function (callback) {
|
|||
configureRangeTemplate(auxChannelCount);
|
||||
configureLinkTemplate();
|
||||
|
||||
var modeTableBodyElement = $('.tab-auxiliary .modes tbody')
|
||||
const modeTableBodyElement = $('.tab-auxiliary .modes');
|
||||
for (var modeIndex = 0; modeIndex < AUX_CONFIG.length; modeIndex++) {
|
||||
|
||||
var modeId = AUX_CONFIG_IDS[modeIndex];
|
||||
|
|
|
@ -111,6 +111,8 @@ TABS.cli.initialize = function (callback) {
|
|||
// translate to user-selected language
|
||||
i18n.localizePage();
|
||||
|
||||
TABS.cli.adaptPhones();
|
||||
|
||||
CONFIGURATOR.cliActive = true;
|
||||
|
||||
var textarea = $('.tab-cli textarea[name="commands"]');
|
||||
|
@ -320,6 +322,17 @@ TABS.cli.initialize = function (callback) {
|
|||
});
|
||||
};
|
||||
|
||||
TABS.cli.adaptPhones = function() {
|
||||
if ($(window).width() < 575) {
|
||||
const backdropHeight = $('.note').height() + 22 + 38;
|
||||
$('.backdrop').css('height', `calc(100% - ${backdropHeight}px)`);
|
||||
}
|
||||
|
||||
if (GUI.isCordova()) {
|
||||
UI_PHONES.initToolbar();
|
||||
}
|
||||
};
|
||||
|
||||
TABS.cli.history = {
|
||||
history: [],
|
||||
index: 0
|
||||
|
|
|
@ -593,6 +593,11 @@ TABS.led_strip.initialize = function (callback, scrollPosition) {
|
|||
|
||||
updateBulkCmd();
|
||||
|
||||
if ($(window).width() < 575) {
|
||||
const gridZoom = $('.tab_title').width() / 496;
|
||||
$('.mainGrid, .gridSections').css('zoom', gridZoom);
|
||||
}
|
||||
|
||||
GUI.content_ready(callback);
|
||||
}
|
||||
|
||||
|
|
143
src/js/tabs/options.js
Normal file
143
src/js/tabs/options.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
'use strict';
|
||||
|
||||
TABS.options = {};
|
||||
TABS.options.initialize = function (callback) {
|
||||
if (GUI.active_tab !== 'options') {
|
||||
GUI.active_tab = 'options';
|
||||
}
|
||||
|
||||
$('#content').load("./tabs/options.html", function () {
|
||||
i18n.localizePage();
|
||||
|
||||
TABS.options.initPermanentExpertMode();
|
||||
TABS.options.initRememberLastTab();
|
||||
TABS.options.initCheckForConfiguratorUnstableVersions();
|
||||
TABS.options.initAnalyticsOptOut();
|
||||
TABS.options.initCliAutoComplete();
|
||||
TABS.options.initCordovaForceComputerUI();
|
||||
TABS.options.initDarkTheme();
|
||||
|
||||
GUI.content_ready(callback);
|
||||
});
|
||||
};
|
||||
|
||||
TABS.options.cleanup = function (callback) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
TABS.options.initPermanentExpertMode = function () {
|
||||
ConfigStorage.get('permanentExpertMode', function (result) {
|
||||
if (result.permanentExpertMode) {
|
||||
$('div.permanentExpertMode input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.permanentExpertMode input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'permanentExpertMode': checked});
|
||||
|
||||
$('input[name="expertModeCheckbox"]').prop('checked', checked).change();
|
||||
}).change();
|
||||
});
|
||||
};
|
||||
|
||||
TABS.options.initRememberLastTab = function () {
|
||||
ConfigStorage.get('rememberLastTab', function (result) {
|
||||
$('div.rememberLastTab input')
|
||||
.prop('checked', !!result.rememberLastTab)
|
||||
.change(function() { ConfigStorage.set({rememberLastTab: $(this).is(':checked')}); })
|
||||
.change();
|
||||
});
|
||||
};
|
||||
|
||||
TABS.options.initCheckForConfiguratorUnstableVersions = function () {
|
||||
if (GUI.operating_system !== 'ChromeOS') {
|
||||
ConfigStorage.get('checkForConfiguratorUnstableVersions', function (result) {
|
||||
if (result.checkForConfiguratorUnstableVersions) {
|
||||
$('div.checkForConfiguratorUnstableVersions input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.checkForConfiguratorUnstableVersions input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'checkForConfiguratorUnstableVersions': checked});
|
||||
|
||||
checkForConfiguratorUpdates();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('div.checkForConfiguratorUnstableVersions').hide();
|
||||
}
|
||||
};
|
||||
|
||||
TABS.options.initAnalyticsOptOut = function () {
|
||||
ConfigStorage.get('analyticsOptOut', function (result) {
|
||||
if (result.analyticsOptOut) {
|
||||
$('div.analyticsOptOut input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.analyticsOptOut input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'analyticsOptOut': checked});
|
||||
|
||||
checkSetupAnalytics(function (analyticsService) {
|
||||
if (checked) {
|
||||
analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptOut');
|
||||
}
|
||||
|
||||
analyticsService.setOptOut(checked);
|
||||
|
||||
if (!checked) {
|
||||
analyticsService.sendEvent(analyticsService.EVENT_CATEGORIES.APPLICATION, 'OptIn');
|
||||
}
|
||||
});
|
||||
}).change();
|
||||
});
|
||||
};
|
||||
|
||||
TABS.options.initCliAutoComplete = function () {
|
||||
$('div.cliAutoComplete input')
|
||||
.prop('checked', CliAutoComplete.configEnabled)
|
||||
.change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'cliAutoComplete': checked});
|
||||
CliAutoComplete.setEnabled(checked);
|
||||
}).change();
|
||||
};
|
||||
|
||||
TABS.options.initCordovaForceComputerUI = function () {
|
||||
if (GUI.isCordova() && cordovaUI.canChangeUI) {
|
||||
ConfigStorage.get('cordovaForceComputerUI', function (result) {
|
||||
if (result.cordovaForceComputerUI) {
|
||||
$('div.cordovaForceComputerUI input').prop('checked', true);
|
||||
}
|
||||
|
||||
$('div.cordovaForceComputerUI input').change(function () {
|
||||
const checked = $(this).is(':checked');
|
||||
|
||||
ConfigStorage.set({'cordovaForceComputerUI': checked});
|
||||
|
||||
if (typeof cordovaUI.set === 'function') {
|
||||
cordovaUI.set();
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
$('div.cordovaForceComputerUI').hide();
|
||||
}
|
||||
};
|
||||
|
||||
TABS.options.initDarkTheme = function () {
|
||||
$('#darkThemeSelect')
|
||||
.val(DarkTheme.configEnabled)
|
||||
.change(function () {
|
||||
const value = parseInt($(this).val());
|
||||
|
||||
ConfigStorage.set({'darkTheme': value});
|
||||
setDarkTheme(value);
|
||||
}).change();
|
||||
};
|
|
@ -2200,6 +2200,12 @@ TABS.osd.initialize = function (callback) {
|
|||
// translate to user-selected language
|
||||
i18n.localizePage();
|
||||
|
||||
if ($(window).width() < 390) {
|
||||
const previewZoom = ($(window).width() - 30) / 360;
|
||||
$('.display-layout .preview').css('zoom', previewZoom);
|
||||
}
|
||||
|
||||
|
||||
// Open modal window
|
||||
OSD.GUI.fontManager = new jBox('Modal', {
|
||||
width: 750,
|
||||
|
|
|
@ -2586,28 +2586,28 @@ TABS.pid_tuning.changeRatesTypeLogo = function() {
|
|||
|
||||
switch(self.currentRatesType) {
|
||||
case self.RATES_TYPE.RACEFLIGHT:
|
||||
ratesLogoElement.attr("src", "../images/rate_logos/raceflight.svg");
|
||||
ratesLogoElement.attr("src", "./images/rate_logos/raceflight.svg");
|
||||
|
||||
break;
|
||||
|
||||
case self.RATES_TYPE.KISS:
|
||||
ratesLogoElement.attr("src", "../images/rate_logos/kiss.svg");
|
||||
ratesLogoElement.attr("src", "./images/rate_logos/kiss.svg");
|
||||
|
||||
break;
|
||||
|
||||
case self.RATES_TYPE.ACTUAL:
|
||||
ratesLogoElement.attr("src", "../images/rate_logos/actual.svg");
|
||||
ratesLogoElement.attr("src", "./images/rate_logos/actual.svg");
|
||||
|
||||
break;
|
||||
|
||||
case self.RATES_TYPE.QUICKRATES:
|
||||
ratesLogoElement.attr("src", "../images/rate_logos/quickrates.svg");
|
||||
ratesLogoElement.attr("src", "./images/rate_logos/quickrates.svg");
|
||||
|
||||
break;
|
||||
|
||||
// add future rates types here
|
||||
default: // BetaFlight
|
||||
ratesLogoElement.attr("src", "../images/rate_logos/betaflight.svg");
|
||||
ratesLogoElement.attr("src", "./images/rate_logos/betaflight.svg");
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -184,9 +184,11 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
|
||||
let lastVtxControlSelected;
|
||||
var ports_e = $('.tab-ports .ports');
|
||||
const portIdentifierTemplateE = $('#tab-ports-templates .portIdentifier');
|
||||
var port_configuration_template_e = $('#tab-ports-templates .portConfiguration');
|
||||
|
||||
for (var portIndex = 0; portIndex < SERIAL_CONFIG.ports.length; portIndex++) {
|
||||
const portIdentifierE = portIdentifierTemplateE.clone();
|
||||
var port_configuration_e = port_configuration_template_e.clone();
|
||||
var serialPort = SERIAL_CONFIG.ports[portIndex];
|
||||
|
||||
|
@ -216,6 +218,7 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
var blackbox_baudrate_e = port_configuration_e.find('select.blackbox_baudrate');
|
||||
blackbox_baudrate_e.val(blackboxBaudrate);
|
||||
|
||||
portIdentifierE.find('.identifier').text(portIdentifierToNameMapping[serialPort.identifier]);
|
||||
port_configuration_e.find('.identifier').text(portIdentifierToNameMapping[serialPort.identifier]);
|
||||
|
||||
port_configuration_e.data('index', portIndex);
|
||||
|
@ -288,6 +291,7 @@ TABS.ports.initialize = function (callback, scrollPosition) {
|
|||
}
|
||||
}
|
||||
|
||||
ports_e.find('tbody').append(portIdentifierE);
|
||||
ports_e.find('tbody').append(port_configuration_e);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,10 @@ TABS.vtx.initialize = function (callback) {
|
|||
// translate to user-selected language
|
||||
i18n.localizePage();
|
||||
|
||||
if (GUI.isCordova()) {
|
||||
UI_PHONES.initToolbar();
|
||||
}
|
||||
|
||||
self.updating = false;
|
||||
GUI.content_ready(callback);
|
||||
}
|
||||
|
@ -112,8 +116,9 @@ TABS.vtx.initialize = function (callback) {
|
|||
// Load schema
|
||||
const urlVtxSchema = chrome.runtime.getURL(`resources/jsonschema/vtxconfig_schema-${vtxConfig.version}.json`);
|
||||
|
||||
if (GUI.Mode === GUI_Modes.ChromeApp) {
|
||||
if (GUI.Mode === GUI_Modes.ChromeApp || GUI.isCordova()) {
|
||||
// FIXME the ChromeOs don't let us use a Schema Validator because almost all of them use eval, and/or use require
|
||||
// On android : Fetch API cannot load : URL scheme "file" is not supported
|
||||
callback_valid();
|
||||
} else {
|
||||
fetch(urlVtxSchema)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue