diff --git a/README.md b/README.md index d337457..955b89a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![](https://img.shields.io/badge/Fitbit%20App%20Gallery-%2300B0B9?style=flat&logo=fitbit&logoColor=white)](https://gallery.fitbit.com/details/ae441b73-2660-407f-b796-a98d1d0583a0) ![languages](https://img.shields.io/badge/languages-JavaScript%20|%20CSS-blue) ![platform](https://img.shields.io/badge/platforms-Ionic%20|%20Versa%20|%20Versa%202%20|%20Versa%20Lite-silver) -![version](https://img.shields.io/badge/version-%201.4.1-green) +![version](https://img.shields.io/badge/version-%201.5.0-green) [![](https://img.shields.io/github/license/smirko-dev/fitbit-clockface.svg)](https://github.com/smirko-dev/fitbit-clockface/blob/master/LICENSE) [![FitbitBuild Actions Status](https://github.com/smirko-dev/fitbit-clockface/workflows/FitbitBuild/badge.svg)](https://github.com/smirko-dev/fitbit-clockface/actions) [![CodeQL Actions Status](https://github.com/smirko-dev/fitbit-clockface/workflows/CodeQL/badge.svg)](https://github.com/smirko-dev/fitbit-clockface/actions) @@ -17,6 +17,7 @@ It comes with - battery icon (Ionic: and status in percentage) - next calendar event of the current day - user activity in case of no events (selectable in settings menu) +- six color schemes (selectable in settings menu) - touch to hide calendar event temporarily Find the latest published version in the [Fitbit gallery](https://gallery.fitbit.com/details/ae441b73-2660-407f-b796-a98d1d0583a0). @@ -37,7 +38,7 @@ Icons are from https://materialdesignicons.com/ ([Apache license version 2.0](ht ### Settings -![Settings](screenshots/settings.png) +![Settings](screenshots/settings.png) ![Activities](screenshots/activities.png) ## How to build diff --git a/app/index.js b/app/index.js index 1360ac0..27644cb 100644 --- a/app/index.js +++ b/app/index.js @@ -1,12 +1,15 @@ +import { me } from "appbit"; import document from "document"; import { battery } from "power"; import { display } from "display"; import { today } from 'user-activity'; import { me as device } from "device"; +import * as fs from "fs"; import * as appointment from "./appointment"; import * as clock from "./clock"; import * as messaging from "messaging"; import { fromEpochSec, timeString } from "../common/utils"; +import { settingsType, settingsFile } from "../common/constants"; // Get a handle on the and elements const hourLabel = document.getElementById("hourLabel"); @@ -19,14 +22,6 @@ const batteryLabel = document.getElementById("batteryLabel"); const activityIcon = document.getElementById("activityIcon"); const activityLabel = document.getElementById("activityLabel"); -const ActivitySelection = { - DIST: 'distance', - FLOORS: 'floors', - CAL: 'calories', - STEPS: 'steps' -} - -let activitySelection = ActivitySelection.STEPS; //TODO: let activityIntervalID = 0; const INVISIBLE = 0.0; @@ -40,19 +35,52 @@ else { batteryLabel.style.opacity = VISIBLE; } -// Update app settings -messaging.peerSocket.onmessage = (evt) => { - if (evt.data === "distance") { - activitySelection = ActivitySelection.DIST; +// Register for the unload event +me.onunload = saveSettings; + +// Load settings at startup +let settings = loadSettings(); +applySettings(settings.activity, settings.color); + +// Apply and store settings +function applySettings(activity, color) { + if (typeof activity !== 'undefined') { + activityIcon.image = `${activity}.png`; + settings.activity = activity; } - else if (evt.data === "floors") { - activitySelection = ActivitySelection.FLOORS; + if (typeof color !== 'undefined') { + hourLabel.style.fill = color; + activityIcon.style.fill = color; + settings.color = color; } - else if (evt.data === "calories") { - activitySelection = ActivitySelection.CAL; +} + +// Load settings +function loadSettings() { + try { + return fs.readFileSync(settingsFile, settingsType); } - else { - activitySelection = ActivitySelection.STEPS; + catch (ex) { + // Default values + return { + activity: "steps", + color: "#2490DD" + }; + } +} + +// Save settings +function saveSettings() { + fs.writeFileSync(settingsFile, settings, settingsType); +} + +// Update settings +messaging.peerSocket.onmessage = (evt) => { + if (evt.data.key === "activity") { + applySettings(evt.data.value, settings.color); + } + else if (evt.data.key === "color") { + applySettings(settings.activity, evt.data.value); } renderAppointment(); } @@ -122,23 +150,17 @@ function showActivity() { } function updateActivity() { - switch (activitySelection) { - case ActivitySelection.DIST: - activityIcon.image = "distance.png"; - activityLabel.text = today.adjusted.distance; - break; - case ActivitySelection.FLOORS: - activityIcon.image = "floors.png"; - activityLabel.text = today.adjusted.elevationGain; - break; - case ActivitySelection.CAL: - activityIcon.image = "calories.png"; - activityLabel.text = today.adjusted.calories; - break; - default: - activityIcon.image = "steps.png"; - activityLabel.text = today.adjusted.steps; - break; + if (settings.activity === 'distance') { + activityLabel.text = today.adjusted.distance; + } + else if (settings.activity === 'floors') { + activityLabel.text = today.adjusted.elevationGain; + } + else if (settings.activity === 'calories') { + activityLabel.text = today.adjusted.calories; + } + else { + activityLabel.text = today.adjusted.steps; } } diff --git a/common/constants.js b/common/constants.js index be3ea13..bef9528 100644 --- a/common/constants.js +++ b/common/constants.js @@ -1,3 +1,5 @@ export const dataType = "cbor"; export const dataFile = "appointments.cbor"; +export const settingsType = "cbor"; +export const settingsFile = "settings.cbor"; export const millisecondsPerMinute = 1000 * 60; diff --git a/companion/index.js b/companion/index.js index 1e7abdc..3167783 100644 --- a/companion/index.js +++ b/companion/index.js @@ -14,7 +14,16 @@ settingsStorage.onchange = function(evt) { if (messaging.peerSocket.readyState === messaging.peerSocket.OPEN) { if (evt.key === "activity") { let data = JSON.parse(evt.newValue); - messaging.peerSocket.send(data["values"][0].value); + messaging.peerSocket.send({ + key: evt.key, + value: data["values"][0].value + }); + } + else { + messaging.peerSocket.send({ + key: evt.key, + value: JSON.parse(evt.newValue) + }); } } } diff --git a/package.json b/package.json index c2b5390..dfeaee3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "compactclock", - "version": "1.4.1", + "version": "1.5.0", "license": "MIT", "devDependencies": { "@fitbit/sdk": "~4.2.0", diff --git a/screenshots/activities.png b/screenshots/activities.png new file mode 100644 index 0000000..781768e --- /dev/null +++ b/screenshots/activities.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ae45b7a05f7b5817ce3df4331bd6ac197149b5eb4c4a6a04473ec34dd23f68ee +size 6659 diff --git a/screenshots/settings.png b/screenshots/settings.png index 781768e..c5bf8f1 100644 --- a/screenshots/settings.png +++ b/screenshots/settings.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ae45b7a05f7b5817ce3df4331bd6ac197149b5eb4c4a6a04473ec34dd23f68ee -size 6659 +oid sha256:105335cbc60698e56f8f45da480369ecb809c08b062d2b0eb8979299c7851634 +size 10335 diff --git a/settings/index.jsx b/settings/index.jsx index df876b2..691e4f5 100644 --- a/settings/index.jsx +++ b/settings/index.jsx @@ -14,11 +14,24 @@ function settingsFunc(props) { label={`${title}`} settingsKey="activity" options={[ - { name: `${steps}`, value: "steps" }, - { name: `${dist}`, value: "distance" }, - { name: `${floors}`, value: "floors" }, - { name: `${cal}`, value: "calories" } + { name: `${steps}`, value: 'steps' }, + { name: `${dist}`, value: 'distance' }, + { name: `${floors}`, value: 'floors' }, + { name: `${cal}`, value: 'calories' } ]} + onSelection={(value) => console.log(value)} + /> + console.log(color)} />