mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-13 02:21:14 +01:00
91b1464824
Replacing the top frame with a data-uri is forbidden since chromium-based-webview version 60. With this commit we swap the body with an iframe when needed. Old webviews work as usual also with this approach. No special treatment is needed for local storage as its usage is forbidden in data-uri iframes. Fixes #758
254 lines
8.1 KiB
JavaScript
254 lines
8.1 KiB
JavaScript
var reportedPositionFailures = 0;
|
|
navigator.geolocation.getCurrentPosition = function(success, failure, options) { //override because default implementation requires GPS permission
|
|
geoposition = JSON.parse(GBjs.getCurrentPosition());
|
|
|
|
if(options && options.maximumAge && (geoposition.timestamp < Date.now() - options.maximumAge) && reportedPositionFailures <= 10 ) {
|
|
reportedPositionFailures++;
|
|
failure({ code: 2, message: "POSITION_UNAVAILABLE"});
|
|
} else {
|
|
reportedPositionFailures = 0;
|
|
success(geoposition);
|
|
}
|
|
}
|
|
|
|
if (window.Storage){
|
|
var prefix = GBjs.getAppLocalstoragePrefix();
|
|
GBjs.gbLog("redefining local storage with prefix: " + prefix);
|
|
|
|
Storage.prototype.setItem = (function(key, value) {
|
|
this.call(localStorage,prefix + key, value);
|
|
}).bind(Storage.prototype.setItem);
|
|
|
|
Storage.prototype.getItem = (function(key) {
|
|
// console.log("I am about to return " + prefix + key);
|
|
var def = null;
|
|
if(key == 'clay-settings') {
|
|
def = '{}';
|
|
}
|
|
return this.call(localStorage,prefix + key) || def;
|
|
}).bind(Storage.prototype.getItem);
|
|
}
|
|
|
|
function loadScript(url, callback) {
|
|
// Adding the script tag to the head as suggested before
|
|
var head = document.getElementsByTagName('head')[0];
|
|
var script = document.createElement('script');
|
|
script.type = 'text/javascript';
|
|
script.src = url;
|
|
|
|
// Then bind the event to the callback function.
|
|
// There are several events for cross browser compatibility.
|
|
script.onreadystatechange = callback;
|
|
script.onload = callback;
|
|
|
|
// Fire the loading
|
|
head.appendChild(script);
|
|
}
|
|
|
|
function getURLVariable(variable, defaultValue) {
|
|
// Find all URL parameters
|
|
var query = location.search.substring(1);
|
|
var vars = query.split('&');
|
|
for (var i = 0; i < vars.length; i++) {
|
|
var pair = vars[i].split('=');
|
|
|
|
// If the query variable parameter is found, decode it to use and return it for use
|
|
if (pair[0] === variable) {
|
|
return decodeURIComponent(pair[1]);
|
|
}
|
|
}
|
|
return defaultValue || false;
|
|
}
|
|
|
|
function showStep(desiredStep) {
|
|
var steps = document.getElementsByClassName("step");
|
|
var testStep = null;
|
|
for (var i = 0; i < steps.length; i ++) {
|
|
if (steps[i].id == desiredStep)
|
|
testStep = steps[i].id;
|
|
}
|
|
if (testStep !== null) {
|
|
for (var i = 0; i < steps.length; i ++) {
|
|
steps[i].style.display = 'none';
|
|
}
|
|
document.getElementById(desiredStep).style.display="block";
|
|
}
|
|
}
|
|
|
|
function hideSteps() {
|
|
var steps = document.getElementsByClassName("step");
|
|
for (var i = 0; i < steps.length; i ++) {
|
|
steps[i].style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function gbPebble() {
|
|
this.configurationURL = null;
|
|
this.configurationValues = null;
|
|
var self = this;
|
|
self.events = {};
|
|
//events processing: see http://stackoverflow.com/questions/10978311/implementing-events-in-my-own-object
|
|
self.addEventListener = function(name, handler) {
|
|
if (self.events.hasOwnProperty(name))
|
|
self.events[name].push(handler);
|
|
else
|
|
self.events[name] = [handler];
|
|
}
|
|
|
|
self.removeEventListener = function(name, handler) {
|
|
if (!self.events.hasOwnProperty(name))
|
|
return;
|
|
|
|
var index = self.events[name].indexOf(handler);
|
|
if (index != -1)
|
|
self.events[name].splice(index, 1);
|
|
}
|
|
|
|
self.evaluate = function(name, args) {
|
|
if (!self.events.hasOwnProperty(name))
|
|
return;
|
|
|
|
if (!args || !args.length)
|
|
args = [];
|
|
|
|
var evs = self.events[name], l = evs.length;
|
|
for (var i = 0; i < l; i++) {
|
|
evs[i].apply(null, args);
|
|
}
|
|
}
|
|
|
|
this.actuallyOpenURL = function() {
|
|
showStep("step1compat");
|
|
window.open(self.configurationURL.toString(), "config");
|
|
}
|
|
|
|
this.actuallySendData = function() {
|
|
GBjs.sendAppMessage(self.configurationValues);
|
|
GBjs.closeActivity();
|
|
}
|
|
|
|
this.savePreset = function() {
|
|
GBjs.saveAppStoredPreset(self.configurationValues);
|
|
}
|
|
|
|
this.loadPreset = function() {
|
|
showStep("step2");
|
|
var presetElements = document.getElementsByClassName("store_presets");
|
|
for (var i = 0; i < presetElements.length; i ++) {
|
|
presetElements[i].style.display = 'none';
|
|
}
|
|
self.configurationValues = GBjs.getAppStoredPreset();
|
|
document.getElementById("jsondata").innerHTML=self.configurationValues;
|
|
}
|
|
|
|
//needs to be called like this because of original Pebble function name
|
|
this.openURL = function(url) {
|
|
if (url.lastIndexOf("http", 0) === 0) {
|
|
document.getElementById("config_url").innerHTML=url;
|
|
var UUID = GBjs.getAppUUID();
|
|
self.configurationURL = new Uri(url).addQueryParam("return_to", "gadgetbridge://"+UUID+"?config=true&json=");
|
|
} else {
|
|
//TODO: add custom return_to
|
|
var iframe = document.getElementsByTagName('iframe')[0];
|
|
var oldbody = document.getElementsByTagName("body")[0];
|
|
if (iframe === undefined && oldbody !== undefined) {
|
|
iframe = document.createElement("iframe");
|
|
oldbody.parentNode.replaceChild(iframe,oldbody);
|
|
} else {
|
|
hideSteps();
|
|
document.documentElement.appendChild(iframe);
|
|
}
|
|
|
|
iframe.src = url;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.getActiveWatchInfo = function() {
|
|
return JSON.parse(GBjs.getActiveWatchInfo());
|
|
}
|
|
|
|
this.sendAppMessage = function (dict, callbackAck, callbackNack){
|
|
try {
|
|
self.configurationValues = JSON.stringify(dict);
|
|
document.getElementById("jsondata").innerHTML=self.configurationValues;
|
|
if (callbackAck != undefined) {
|
|
callbackAck();
|
|
}
|
|
}
|
|
catch (e) {
|
|
GBjs.gbLog("sendAppMessage failed");
|
|
if (callbackNack != undefined) {
|
|
callbackNack();
|
|
}
|
|
}
|
|
}
|
|
|
|
this.getAccountToken = function() {
|
|
return '';
|
|
}
|
|
|
|
this.getWatchToken = function() {
|
|
return GBjs.getWatchToken();
|
|
}
|
|
|
|
this.getTimelineToken = function() {
|
|
return '';
|
|
}
|
|
|
|
this.showSimpleNotificationOnPebble = function(title, body) {
|
|
GBjs.gbLog("app wanted to show: " + title + " body: "+ body);
|
|
}
|
|
|
|
|
|
this.showConfiguration = function() {
|
|
console.error("This watchapp doesn't support configuration");
|
|
GBjs.closeActivity();
|
|
}
|
|
|
|
this.parseReturnedPebbleJS = function() {
|
|
var str = document.getElementById('pastereturn').value;
|
|
var needle = "pebblejs://close#";
|
|
|
|
if (str.split(needle)[1] !== undefined) {
|
|
var t = new Object();
|
|
t.response = decodeURIComponent(str.split(needle)[1]);
|
|
self.evaluate('webviewclosed',[t]);
|
|
showStep("step2");
|
|
} else {
|
|
console.error("No valid configuration found in the entered string.");
|
|
}
|
|
}
|
|
}
|
|
|
|
var Pebble = new gbPebble();
|
|
|
|
var jsConfigFile = GBjs.getAppConfigurationFile();
|
|
var storedPreset = GBjs.getAppStoredPreset();
|
|
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
if (jsConfigFile != null) {
|
|
loadScript(jsConfigFile, function() {
|
|
Pebble.evaluate('ready', [{'type': "ready"}]); //callback object apparently needed by some watchfaces
|
|
if (getURLVariable('config') == 'true') {
|
|
showStep("step2");
|
|
var json_string = getURLVariable('json');
|
|
var t = new Object();
|
|
t.response = json_string;
|
|
if (json_string != '') {
|
|
Pebble.evaluate('webviewclosed',[t]);
|
|
}
|
|
|
|
} else {
|
|
if (storedPreset === undefined) {
|
|
var presetElements = document.getElementsByClassName("load_presets");
|
|
for (var i = 0; i < presetElements.length; i ++) {
|
|
presetElements[i].style.display = 'none';
|
|
}
|
|
}
|
|
Pebble.evaluate('showConfiguration');
|
|
}
|
|
});
|
|
}
|
|
}, false); |