From 966c3d4811bd6fcea8de1e190024c0dc49f0b223 Mon Sep 17 00:00:00 2001 From: Daniele Gobbetti Date: Sat, 18 Jun 2016 18:40:57 +0200 Subject: [PATCH] Various improvements to the configuration page: - localstorage is now cleared at every launch: this prevents some clay configuration pages to send back to the watch a number of keys that were set by other configuration pages - only execute JS on document ready: this prevents some race conditions - added dummy getTimelineToken function to Pebble JS object - corrected (hopefully!) a few logic errors in the JS code (this referenced where it wasn't) - refactored the steps visualization in JS - lifecycle changes to the java activity: now the configuration page gets closed as soon as the settings have been sent, and there is only one instance of it --- app/src/main/AndroidManifest.xml | 1 + app/src/main/assets/app_config/configure.html | 18 ++++-- .../app_config/js/gadgetbridge_boilerplate.js | 64 ++++++++++++------- .../activities/ExternalPebbleJSActivity.java | 54 +++++++++++----- 4 files changed, 91 insertions(+), 46 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c72495ef..68536ab3 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -261,6 +261,7 @@ diff --git a/app/src/main/assets/app_config/configure.html b/app/src/main/assets/app_config/configure.html index 87188f12..68edb92d 100644 --- a/app/src/main/assets/app_config/configure.html +++ b/app/src/main/assets/app_config/configure.html @@ -1,6 +1,6 @@ - + @@ -52,14 +52,16 @@ - -
+ +

Url of the configuration:

- +
-
+

In case of "network error" after saving settings in the wathchapp, copy the "network error" URL and paste it here:


@@ -67,9 +69,11 @@ configuration
-
+

Incoming configuration data:

- +
diff --git a/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js b/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js index a40bf2d7..7738e6f5 100644 --- a/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js +++ b/app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js @@ -1,3 +1,6 @@ +//clay stores the values in the localStorage +localStorage.clear(); + function loadScript(url, callback) { // Adding the script tag to the head as suggested before var head = document.getElementsByTagName('head')[0]; @@ -29,46 +32,63 @@ function getURLVariable(variable, defaultValue) { 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 gbPebble() { this.configurationURL = null; this.configurationValues = null; + var self = this; this.addEventListener = function(e, f) { if(e == 'ready') { - this.ready = f; + self.ready = f; } if(e == 'showConfiguration') { - this.showConfiguration = f; + self.showConfiguration = f; } if(e == 'webviewclosed') { - this.parseconfig = f; + self.parseconfig = f; } if(e == 'appmessage') { - this.appmessage = f; + self.appmessage = f; } } this.removeEventListener = function(e, f) { if(e == 'ready') { - this.ready = null; + self.ready = null; } if(e == 'showConfiguration') { - this.showConfiguration = null; + self.showConfiguration = null; } if(e == 'webviewclosed') { - this.parseconfig = null; + self.parseconfig = null; } if(e == 'appmessage') { - this.appmessage = null; + self.appmessage = null; } } this.actuallyOpenURL = function() { - document.getElementById('step1compat').style.display="block"; - window.open(this.configurationURL.toString(), "config"); + showStep("step1compat"); + window.open(self.configurationURL.toString(), "config"); } this.actuallySendData = function() { - GBjs.sendAppMessage(this.configurationValues); + GBjs.sendAppMessage(self.configurationValues); + GBjs.closeActivity(); } //needs to be called like this because of original Pebble function name @@ -76,7 +96,7 @@ function gbPebble() { if (url.lastIndexOf("http", 0) === 0) { document.getElementById("config_url").innerHTML=url; var UUID = GBjs.getAppUUID(); - this.configurationURL = new Uri(url).addQueryParam("return_to", "gadgetbridge://"+UUID+"?config=true&json="); + self.configurationURL = new Uri(url).addQueryParam("return_to", "gadgetbridge://"+UUID+"?config=true&json="); } else { //TODO: add custom return_to location.href = url; @@ -90,7 +110,7 @@ function gbPebble() { this.sendAppMessage = function (dict, callbackAck, callbackNack){ try { - this.configurationValues = JSON.stringify(dict); + self.configurationValues = JSON.stringify(dict); document.getElementById("jsondata").innerHTML=this.configurationValues; return callbackAck; } @@ -108,6 +128,10 @@ function gbPebble() { return GBjs.getWatchToken(); } + this.getTimelineToken = function() { + return ''; + } + this.showSimpleNotificationOnPebble = function(title, body) { GBjs.gbLog("app wanted to show: " + title + " body: "+ body); } @@ -116,17 +140,14 @@ function gbPebble() { } 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 = unescape(str.split(needle)[1]); - this.parseconfig(t); - document.getElementById('step1').style.display="none"; - document.getElementById('step1compat').style.display="none"; - document.getElementById('step2').style.display="block"; + self.parseconfig(t); + showStep("step2"); } else { console.error("No valid configuration found in the entered string."); } @@ -136,13 +157,11 @@ function gbPebble() { var Pebble = new gbPebble(); var jsConfigFile = GBjs.getAppConfigurationFile(); +document.addEventListener('DOMContentLoaded', function(){ if (jsConfigFile != null) { loadScript(jsConfigFile, function() { if (getURLVariable('config') == 'true') { - document.getElementById('step1').style.display="none"; - document.getElementById('step1compat').style.display="none"; - document.getElementById('step2').style.display="block"; - + showStep("step2"); var json_string = unescape(getURLVariable('json')); var t = new Object(); t.response = json_string; @@ -154,3 +173,4 @@ if (jsConfigFile != null) { } }); } +}, false); \ No newline at end of file diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java index f2d30264..f756ecb5 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/ExternalPebbleJSActivity.java @@ -28,6 +28,7 @@ import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.PebbleUtils; @@ -37,7 +38,9 @@ public class ExternalPebbleJSActivity extends GBActivity { private static final Logger LOG = LoggerFactory.getLogger(ExternalPebbleJSActivity.class); private UUID appUuid; + private Uri confUri; private GBDevice mGBDevice = null; + private WebView myWebView; @Override protected void onCreate(Bundle savedInstanceState) { @@ -46,27 +49,15 @@ public class ExternalPebbleJSActivity extends GBActivity { Bundle extras = getIntent().getExtras(); if (extras != null) { mGBDevice = extras.getParcelable(GBDevice.EXTRA_DEVICE); + appUuid = (UUID) extras.getSerializable(DeviceService.EXTRA_APP_UUID); } else { throw new IllegalArgumentException("Must provide a device when invoking this activity"); } - String queryString = ""; - Uri uri = getIntent().getData(); - if (uri != null) { - //getting back with configuration data - try { - appUuid = UUID.fromString(uri.getHost()); - queryString = uri.getEncodedQuery(); - } catch (IllegalArgumentException e) { - Log.d("returned uri: ", uri.toString()); - } - } else { - appUuid = (UUID) getIntent().getSerializableExtra("app_uuid"); - } setContentView(R.layout.activity_external_pebble_js); - WebView myWebView = (WebView) findViewById(R.id.configureWebview); + myWebView = (WebView) findViewById(R.id.configureWebview); myWebView.clearCache(true); myWebView.setWebViewClient(new GBWebClient()); myWebView.setWebChromeClient(new GBChromeClient()); @@ -78,7 +69,32 @@ public class ExternalPebbleJSActivity extends GBActivity { JSInterface gbJSInterface = new JSInterface(); myWebView.addJavascriptInterface(gbJSInterface, "GBjs"); - myWebView.loadUrl("file:///android_asset/app_config/configure.html?" + queryString); + myWebView.loadUrl("file:///android_asset/app_config/configure.html"); + + } + + @Override + protected void onNewIntent(Intent incoming) { + super.onNewIntent(incoming); + confUri = incoming.getData(); + } + + @Override + protected void onResume() { + super.onResume(); + String queryString = ""; + + if (confUri != null) { + //getting back with configuration data + try { + appUuid = UUID.fromString(confUri.getHost()); + queryString = confUri.getEncodedQuery(); + } catch (IllegalArgumentException e) { + GB.toast("returned uri: " + confUri.toString(), Toast.LENGTH_LONG, GB.ERROR); + } + myWebView.loadUrl("file:///android_asset/app_config/configure.html?" + queryString); + } + } private JSONObject getAppConfigurationKeys() { @@ -112,8 +128,7 @@ public class ExternalPebbleJSActivity extends GBActivity { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("http://") || url.startsWith("https://")) { - Intent i = new Intent(Intent.ACTION_VIEW, - Uri.parse(url)); + Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); startActivity(i); } else { url = url.replaceFirst("^pebblejs://close#", "file:///android_asset/app_config/configure.html?config=true&json="); @@ -222,6 +237,11 @@ public class ExternalPebbleJSActivity extends GBActivity { //specification says: A string that is is guaranteed to be identical for each Pebble device for the same app across different mobile devices. The token is unique to your app and cannot be used to track Pebble devices across applications. see https://developer.pebble.com/docs/js/Pebble/ return "gb" + appUuid.toString(); } + + @JavascriptInterface + public void closeActivity() { + finish(); + } } @Override