68 lines
2.5 KiB
JavaScript
68 lines
2.5 KiB
JavaScript
'use strict';
|
|
/**
|
|
* GPS Navigator — Qt WebChannel bridge.
|
|
*
|
|
* qwebchannel.js is injected by PyQt5 at DocumentCreation time (before any
|
|
* page script runs), so QWebChannel is always available here.
|
|
*
|
|
* Exposes:
|
|
* window._py(method, arg1, ...) → Promise that resolves with the return value
|
|
* window.py → the registered bridge object (set after init)
|
|
*/
|
|
(function () {
|
|
|
|
// _py('method', arg1, arg2, ...) → Promise<result>
|
|
// Works for both void slots (resolves undefined) and value-returning slots.
|
|
window._py = function (method) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
return new Promise(function (resolve) {
|
|
window.py[method].apply(window.py, args.concat([resolve]));
|
|
});
|
|
};
|
|
|
|
function _initChannel() {
|
|
if (typeof QWebChannel === 'undefined' || typeof qt === 'undefined') {
|
|
// Running in a plain browser (dev mode) — no bridge available.
|
|
console.warn('[bridge] QWebChannel not available — dev mode, no GPS bridge');
|
|
window.py = null;
|
|
// Let the app start anyway (it will show "no GPS" state)
|
|
if (typeof window.bootApp === 'function') window.bootApp();
|
|
return;
|
|
}
|
|
|
|
new QWebChannel(qt.webChannelTransport, function (channel) {
|
|
window.py = channel.objects.py;
|
|
|
|
// ── GPS messages: Python signal → JS handler ────────────────────────
|
|
// Qt queues this signal delivery from the NMEA reader thread to the
|
|
// main thread, so it always arrives in the JS event loop safely.
|
|
window.py.gpsMessage.connect(function (json_str) {
|
|
try {
|
|
var msg = JSON.parse(json_str);
|
|
if (typeof window.handleGPSMsg === 'function') {
|
|
window.handleGPSMsg(msg);
|
|
}
|
|
} catch (e) {
|
|
console.error('[bridge] gpsMessage parse error:', e, json_str);
|
|
}
|
|
});
|
|
|
|
// ── Start GPS autodetect (signal handler is now connected) ───────────
|
|
window.py.autodetect_and_start();
|
|
|
|
// ── Boot the application ─────────────────────────────────────────────
|
|
if (typeof window.bootApp === 'function') {
|
|
window.bootApp();
|
|
}
|
|
});
|
|
}
|
|
|
|
// Run after DOM + all other scripts are loaded
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', _initChannel);
|
|
} else {
|
|
_initChannel();
|
|
}
|
|
|
|
})();
|