mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-20 23:05:15 +03:00
Merge pull request #1982 from mikeller/fix_link_opening
This commit is contained in:
commit
90e198dd1f
6 changed files with 118 additions and 125 deletions
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
"app": {
|
"app": {
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["js/eventPage.js"],
|
"scripts": ["js/chromeAppEventPage.js"],
|
||||||
"persistent": false
|
"persistent": false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
10
package.json
10
package.json
|
@ -2,8 +2,8 @@
|
||||||
"name": "betaflight-configurator",
|
"name": "betaflight-configurator",
|
||||||
"description": "Crossplatform configuration tool for Betaflight flight control system.",
|
"description": "Crossplatform configuration tool for Betaflight flight control system.",
|
||||||
"version": "10.7.0",
|
"version": "10.7.0",
|
||||||
"main": "main_nwjs.html",
|
"main": "main.html",
|
||||||
"bg-script": "js/eventPage.js",
|
"chromium-args" : "--disable-features=nw2",
|
||||||
"default_locale": "en",
|
"default_locale": "en",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "gulp debug",
|
"start": "gulp debug",
|
||||||
|
@ -12,8 +12,10 @@
|
||||||
"test": "karma start test/karma.conf.js"
|
"test": "karma start test/karma.conf.js"
|
||||||
},
|
},
|
||||||
"window": {
|
"window": {
|
||||||
"show": false,
|
"icon": "images/bf_icon_128.png",
|
||||||
"icon": "images/bf_icon_128.png"
|
"id": "main-window",
|
||||||
|
"min_width": 1024,
|
||||||
|
"min_height": 550
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
27
src/js/chromeAppEventPage.js
Normal file
27
src/js/chromeAppEventPage.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
If an id is also specified and a window with a matching id has been shown before, the remembered bounds of the window will be used instead.
|
||||||
|
*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function startApplication() {
|
||||||
|
chrome.app.window.create('main.html', {
|
||||||
|
id: 'main-window',
|
||||||
|
frame: 'chrome',
|
||||||
|
innerBounds: {
|
||||||
|
minWidth: 1024,
|
||||||
|
minHeight: 550,
|
||||||
|
},
|
||||||
|
}, function (createdWindow) {
|
||||||
|
if (getChromeVersion() >= 54) {
|
||||||
|
createdWindow.icon = 'images/bf_icon_128.png';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.app.runtime.onLaunched.addListener(startApplication);
|
||||||
|
|
||||||
|
function getChromeVersion () {
|
||||||
|
const raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||||
|
|
||||||
|
return raw ? parseInt(raw[2], 10) : false;
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
/*
|
|
||||||
If an id is also specified and a window with a matching id has been shown before, the remembered bounds of the window will be used instead.
|
|
||||||
|
|
||||||
In this JS we cannot use the i18n wrapper used in the rest of the application (it is not available). We must remain with the chrome one.
|
|
||||||
*/
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
function startApplication() {
|
|
||||||
var applicationStartTime = new Date().getTime();
|
|
||||||
|
|
||||||
chrome.app.window.create('main.html', {
|
|
||||||
id: 'main-window',
|
|
||||||
frame: 'chrome',
|
|
||||||
innerBounds: {
|
|
||||||
minWidth: 1024,
|
|
||||||
minHeight: 550
|
|
||||||
}
|
|
||||||
}, function (createdWindow) {
|
|
||||||
if (getChromeVersion() >= 54) {
|
|
||||||
createdWindow.icon = 'images/bf_icon_128.png';
|
|
||||||
}
|
|
||||||
createdWindow.onClosed.addListener(function () {
|
|
||||||
// automatically close the port when application closes
|
|
||||||
// save connectionId in separate variable before createdWindow.contentWindow is destroyed
|
|
||||||
var connectionId = createdWindow.contentWindow.serial.connectionId,
|
|
||||||
valid_connection = createdWindow.contentWindow.CONFIGURATOR.connectionValid,
|
|
||||||
mincommand = createdWindow.contentWindow.MOTOR_CONFIG.mincommand;
|
|
||||||
|
|
||||||
if (connectionId && valid_connection) {
|
|
||||||
// code below is handmade MSP message (without pretty JS wrapper), it behaves exactly like MSP.send_message
|
|
||||||
// sending exit command just in case the cli tab was open.
|
|
||||||
// reset motors to default (mincommand)
|
|
||||||
|
|
||||||
var bufferOut = new ArrayBuffer(5),
|
|
||||||
bufView = new Uint8Array(bufferOut);
|
|
||||||
|
|
||||||
bufView[0] = 0x65; // e
|
|
||||||
bufView[1] = 0x78; // x
|
|
||||||
bufView[2] = 0x69; // i
|
|
||||||
bufView[3] = 0x74; // t
|
|
||||||
bufView[4] = 0x0D; // enter
|
|
||||||
|
|
||||||
chrome.serial.send(connectionId, bufferOut, function () { console.log('Send exit') });
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
bufferOut = new ArrayBuffer(22);
|
|
||||||
bufView = new Uint8Array(bufferOut);
|
|
||||||
var checksum = 0;
|
|
||||||
|
|
||||||
bufView[0] = 36; // $
|
|
||||||
bufView[1] = 77; // M
|
|
||||||
bufView[2] = 60; // <
|
|
||||||
bufView[3] = 16; // data length
|
|
||||||
bufView[4] = 214; // MSP_SET_MOTOR
|
|
||||||
|
|
||||||
checksum = bufView[3] ^ bufView[4];
|
|
||||||
|
|
||||||
for (var i = 0; i < 16; i += 2) {
|
|
||||||
bufView[i + 5] = mincommand & 0x00FF;
|
|
||||||
bufView[i + 6] = mincommand >> 8;
|
|
||||||
|
|
||||||
checksum ^= bufView[i + 5];
|
|
||||||
checksum ^= bufView[i + 6];
|
|
||||||
}
|
|
||||||
|
|
||||||
bufView[5 + 16] = checksum;
|
|
||||||
|
|
||||||
chrome.serial.send(connectionId, bufferOut, function (sendInfo) {
|
|
||||||
chrome.serial.disconnect(connectionId, function (result) {
|
|
||||||
console.log('SERIAL: Connection closed - ' + result);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
} else if (connectionId) {
|
|
||||||
chrome.serial.disconnect(connectionId, function (result) {
|
|
||||||
console.log('SERIAL: Connection closed - ' + result);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.app.runtime.onLaunched.addListener(startApplication);
|
|
||||||
|
|
||||||
function getChromeVersion () {
|
|
||||||
var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
|
||||||
|
|
||||||
return raw ? parseInt(raw[2], 10) : false;
|
|
||||||
}
|
|
109
src/js/main.js
109
src/js/main.js
|
@ -80,35 +80,78 @@ function setupAnalytics(result) {
|
||||||
|
|
||||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppStart', { sessionControl: 'start' });
|
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppStart', { sessionControl: 'start' });
|
||||||
|
|
||||||
function sendCloseEvent() {
|
|
||||||
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUI.isNWJS()) {
|
|
||||||
GUI.nwGui.Window.getAll(function (windows) {
|
|
||||||
windows.forEach(function (win) {
|
|
||||||
win.on('close', function () {
|
|
||||||
sendCloseEvent();
|
|
||||||
|
|
||||||
this.close(true);
|
|
||||||
});
|
|
||||||
win.on('new-win-policy', function(frame, url, policy) {
|
|
||||||
// do not open the window
|
|
||||||
policy.ignore();
|
|
||||||
// and open it in external browser
|
|
||||||
GUI.nwGui.Shell.openExternal(url);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else if (!GUI.isOther()) {
|
|
||||||
// Looks like we're in Chrome - but the event does not actually get fired
|
|
||||||
chrome.runtime.onSuspend.addListener(sendCloseEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
$('.connect_b a.connect').removeClass('disabled');
|
$('.connect_b a.connect').removeClass('disabled');
|
||||||
$('.firmware_b a.flash').removeClass('disabled');
|
$('.firmware_b a.flash').removeClass('disabled');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function closeSerial() {
|
||||||
|
// automatically close the port when application closes
|
||||||
|
const connectionId = serial.connectionId;
|
||||||
|
|
||||||
|
if (connectionId && CONFIGURATOR.connectionValid) {
|
||||||
|
// code below is handmade MSP message (without pretty JS wrapper), it behaves exactly like MSP.send_message
|
||||||
|
// sending exit command just in case the cli tab was open.
|
||||||
|
// reset motors to default (mincommand)
|
||||||
|
|
||||||
|
let bufferOut = new ArrayBuffer(5),
|
||||||
|
bufView = new Uint8Array(bufferOut);
|
||||||
|
|
||||||
|
bufView[0] = 0x65; // e
|
||||||
|
bufView[1] = 0x78; // x
|
||||||
|
bufView[2] = 0x69; // i
|
||||||
|
bufView[3] = 0x74; // t
|
||||||
|
bufView[4] = 0x0D; // enter
|
||||||
|
|
||||||
|
chrome.serial.send(connectionId, bufferOut, function () {
|
||||||
|
console.log('Send exit');
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
bufferOut = new ArrayBuffer(22);
|
||||||
|
bufView = new Uint8Array(bufferOut);
|
||||||
|
let checksum = 0;
|
||||||
|
|
||||||
|
bufView[0] = 36; // $
|
||||||
|
bufView[1] = 77; // M
|
||||||
|
bufView[2] = 60; // <
|
||||||
|
bufView[3] = 16; // data length
|
||||||
|
bufView[4] = 214; // MSP_SET_MOTOR
|
||||||
|
|
||||||
|
checksum = bufView[3] ^ bufView[4];
|
||||||
|
|
||||||
|
for (let i = 0; i < 16; i += 2) {
|
||||||
|
bufView[i + 5] = MOTOR_CONFIG.mincommand & 0x00FF;
|
||||||
|
bufView[i + 6] = MOTOR_CONFIG.mincommand >> 8;
|
||||||
|
|
||||||
|
checksum ^= bufView[i + 5];
|
||||||
|
checksum ^= bufView[i + 6];
|
||||||
|
}
|
||||||
|
|
||||||
|
bufView[5 + 16] = checksum;
|
||||||
|
|
||||||
|
chrome.serial.send(connectionId, bufferOut, function () {
|
||||||
|
chrome.serial.disconnect(connectionId, function (result) {
|
||||||
|
console.log(`SERIAL: Connection closed - ${result}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 100);
|
||||||
|
} else if (connectionId) {
|
||||||
|
chrome.serial.disconnect(connectionId, function (result) {
|
||||||
|
console.log(`SERIAL: Connection closed - ${result}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeHandler() {
|
||||||
|
this.hide();
|
||||||
|
|
||||||
|
analytics.sendEvent(analytics.EVENT_CATEGORIES.APPLICATION, 'AppClose', { sessionControl: 'end' });
|
||||||
|
|
||||||
|
closeSerial();
|
||||||
|
|
||||||
|
this.close(true);
|
||||||
|
}
|
||||||
|
|
||||||
//Process to execute to real start the app
|
//Process to execute to real start the app
|
||||||
function startProcess() {
|
function startProcess() {
|
||||||
// translate to user-selected language
|
// translate to user-selected language
|
||||||
|
@ -119,6 +162,22 @@ function startProcess() {
|
||||||
chromeVersion: window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/, "$1"),
|
chromeVersion: window.navigator.appVersion.replace(/.*Chrome\/([0-9.]*).*/, "$1"),
|
||||||
configuratorVersion: CONFIGURATOR.version }));
|
configuratorVersion: CONFIGURATOR.version }));
|
||||||
|
|
||||||
|
if (GUI.isNWJS()) {
|
||||||
|
let nwWindow = GUI.nwGui.Window.get();
|
||||||
|
nwWindow.on('new-win-policy', function(frame, url, policy) {
|
||||||
|
// do not open the window
|
||||||
|
policy.ignore();
|
||||||
|
// and open it in external browser
|
||||||
|
GUI.nwGui.Shell.openExternal(url);
|
||||||
|
});
|
||||||
|
nwWindow.on('close', closeHandler);
|
||||||
|
} else if (!GUI.isOther()) {
|
||||||
|
chrome.app.window.onClosed.addListener(closeHandler);
|
||||||
|
// This event does not actually get fired:
|
||||||
|
chrome.runtime.onSuspend.addListener(closeHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.connect_b a.connect').removeClass('disabled');
|
||||||
$('#logo .version').text(CONFIGURATOR.version);
|
$('#logo .version').text(CONFIGURATOR.version);
|
||||||
updateStatusBarVersion();
|
updateStatusBarVersion();
|
||||||
updateTopBarVersion();
|
updateTopBarVersion();
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
<script>
|
|
||||||
// Closing empty default nw.js window; we use the chrome window created in eventPage.js.
|
|
||||||
// The window created in eventPage.js also has some hocks to cleanup stuff when closing.
|
|
||||||
// Restoring window size, position and state also works out-of-the-box.
|
|
||||||
window.close();
|
|
||||||
</script>
|
|
Loading…
Add table
Add a link
Reference in a new issue