Timstyle for Fitbit OS5

This month I have released a new version of Timestyle for Fitbit OS5, the new OS for its Versa 3 and Sense devices

Broken

This was a bit more tricky than a usual app port as I don’t own one of these devices, I have an older Versa model and Fitbit have not, and will not release OS5 for these devices. So I am reliant on the emulator, which is at best an approximation of the real device. I’ve blogged in the past that sometimes the render does not match and sometimes api calls work differntly.

Most of the changes were pretty straightforward and similar to the port I did with wrist-list. However when I was happy and submitted the app to Fitbit it was rejected as the screen did not update properly when returning from the settings screen on the device.

Due to the fact that your CLOCK has functionality issues, we regretfully inform you that we have declined your submission. Please find the issues uncovered during testing below:

unfortunately the issue is still present, the digits aren’t visible for like a minute after I set a time offset. Please consult the following link for more information:  https://dev.fitbit.com/legal/app-gallery-guidelines/

Of course it rendered perfectly in the emulator, so I was down to guessing what the problem was, luckily I was able to re-submit and then the reviewer would let me know when I had got it right. I would not have been able to fix this issue without the help and support of the Fitbit app reviewers - so a bit thank you to them.

Clockface screen updates in Fitbit OS5

The mail SVG layout of the clockface looks a bit like this

1
2
3
4
<svg>
  <link rel="import" href="watchface.view" />
  <link rel="import" href="settings.view" />
</svg>

watchface.view starts like this

1
2
3
<svg id="watchface-screen">
  <svg id="watch" class="watch">
    <rect id="background" />

and settings.view starts like this

1
2
<svg id="settings-screen" display="none">
  <defs>

Then I show and hide the relevant screens when the user navigates between them.

1
2
3
4
5
6
7
8
9
10
11
12
let settingsScreen = document.getElementById("settings-screen");
let watchFaceScreen = document.getElementById("watchface-screen");

function showSettingsScreen() {
  settingsScreen.style.display = "inline";
  watchFaceScreen.style.display = "none";
}

function showWatchFace() {
  watchFaceScreen.style.display = "inline";
  settingsScreen.style.display = "none";
}

When the user moves from the settings screen to the clockface, having made changes to the settings, then this is the sort of code that is executed

1
2
3
4
5
btnSettingsBack.onclick = function(evt) {
  handleOverrideIndicator(deviceSettings.isDeviceSettingsBeingUsed());
  simpleClock.setOffset(deviceSettings.isOverrideTime(), deviceSettings.getOverrideMins(), true);
  showWatchFace();
}

I had a thought that maybe the device had extra optimisations for battery performance such that the updates to the display in watchface.view did not occur while it had its display set to be none

I reordered the code, moving the showWatchFace() call to before the calls to update the display and re-submitted the app

1
2
3
4
5
btnSettingsBack.onclick = function(evt) {
  showWatchFace();
  handleOverrideIndicator(deviceSettings.isDeviceSettingsBeingUsed());
  simpleClock.setOffset(deviceSettings.isOverrideTime(), deviceSettings.getOverrideMins(), true);
}

And it was accepted. As I said the emulator does not have this optimisation and works in either order so some care is needed when working with clockfaces, I have not seen this behaviour in apps that are not clockfaces.