initial commit
|
@ -0,0 +1,133 @@
|
||||||
|
import document from "document";
|
||||||
|
import { today } from "user-activity";
|
||||||
|
import { goals } from "user-activity";
|
||||||
|
|
||||||
|
const placeholderText = '···';
|
||||||
|
|
||||||
|
const healthLabels = {
|
||||||
|
steps: document.getElementById('stepsText').getElementById('healthTextLabel'),
|
||||||
|
cal: document.getElementById('calText').getElementById('healthTextLabel'),
|
||||||
|
dist: document.getElementById('distText').getElementById('healthTextLabel'),
|
||||||
|
elev: document.getElementById('elevText').getElementById('healthTextLabel'),
|
||||||
|
actmin: document.getElementById('actminText').getElementById('healthTextLabel')
|
||||||
|
}
|
||||||
|
|
||||||
|
const touchArea = document.getElementById("touchArea");
|
||||||
|
const overlay = document.getElementById('overlay');
|
||||||
|
const overlayShadeInstance = document.getElementById("overlayShadeInstance");
|
||||||
|
const healthTextInstances = document.getElementsByClassName("healthTextInstance");
|
||||||
|
|
||||||
|
let hasOverlay = false;
|
||||||
|
let overlayTimer;
|
||||||
|
|
||||||
|
function getActivityNumber(activity) {
|
||||||
|
let values = {raw: 0, display: placeholderText};
|
||||||
|
|
||||||
|
switch (activity) {
|
||||||
|
case 'steps':
|
||||||
|
values.raw = (today.adjusted.steps || 0);
|
||||||
|
values.display = addcommas(values.raw);
|
||||||
|
break;
|
||||||
|
case 'cal':
|
||||||
|
values.raw = (today.adjusted.calories || 0);
|
||||||
|
values.display = addcommas(values.raw);
|
||||||
|
break;
|
||||||
|
case 'dist':
|
||||||
|
values.raw = (today.adjusted.distance || 0);
|
||||||
|
values.display = (Math.round(values.raw/10)/100 || 0);
|
||||||
|
break;
|
||||||
|
case 'elev':
|
||||||
|
values.raw = values.display = (today.adjusted.elevationGain || 0);
|
||||||
|
break;
|
||||||
|
case 'actmin':
|
||||||
|
values.raw = (today.adjusted.activeMinutes || 0);
|
||||||
|
values.display = addcommas(values.raw);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addcommas(nStr) {
|
||||||
|
if (nStr < 1000) { return nStr; }
|
||||||
|
nStr += '';
|
||||||
|
let x = nStr.split('.');
|
||||||
|
let x1 = x[0];
|
||||||
|
let x2 = x.length > 1 ? '.' + x[1] : '';
|
||||||
|
let rgx = /(\d+)(\d{3})/;
|
||||||
|
while (rgx.test(x1)) {
|
||||||
|
x1 = x1.replace(rgx, '$1' + ',' + '$2');
|
||||||
|
}
|
||||||
|
return x1 + x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateOverlay() {
|
||||||
|
console.log("Updating Health Overlay Labels");
|
||||||
|
healthLabels.steps.text = getActivityNumber('steps').display;
|
||||||
|
healthLabels.cal.text = getActivityNumber('cal').display;
|
||||||
|
healthLabels.dist.text = getActivityNumber('dist').display;
|
||||||
|
healthLabels.elev.text = getActivityNumber('elev').display;
|
||||||
|
healthLabels.actmin.text = getActivityNumber('actmin').display;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOverlay() {
|
||||||
|
updateOverlay();
|
||||||
|
overlay.style.display = 'inline';
|
||||||
|
hasOverlay = true;
|
||||||
|
overlayTimer = setTimeout(() => {
|
||||||
|
removeOverlay();
|
||||||
|
},6000);
|
||||||
|
document.getElementById('overlayShadeInstance').animate('enable');
|
||||||
|
for(let i in healthTextInstances) {
|
||||||
|
setTimeout(() => {
|
||||||
|
healthTextInstances[i].animate('enable');
|
||||||
|
}, 200+i*100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addOverlay() {
|
||||||
|
updateOverlay();
|
||||||
|
overlay.style.display = 'inline';
|
||||||
|
hasOverlay = true;
|
||||||
|
overlayTimer = setTimeout(() => {
|
||||||
|
removeOverlay();
|
||||||
|
},6000);
|
||||||
|
document.getElementById('overlayShadeInstance').animate('enable');
|
||||||
|
for(let i in healthTextInstances) {
|
||||||
|
setTimeout(() => {
|
||||||
|
healthTextInstances[i].animate('enable');
|
||||||
|
}, 200+i*100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeOverlay() {
|
||||||
|
clearTimeout(overlayTimer);
|
||||||
|
overlayShadeInstance.animate('disable');
|
||||||
|
for(var i = 0; i < healthTextInstances.length; i++) {
|
||||||
|
healthTextInstances[i].animate('disable');
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
overlay.style.display = 'none';
|
||||||
|
}, 100);
|
||||||
|
hasOverlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function init() {
|
||||||
|
console.log("Health Overlay Loaded");
|
||||||
|
touchArea.onclick = (e) => {
|
||||||
|
console.log("Tap Detected");
|
||||||
|
if (hasOverlay == false) {
|
||||||
|
addOverlay();
|
||||||
|
} else {
|
||||||
|
removeOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function continuousUpdate(ms) {
|
||||||
|
console.log("Activated Continuous Updates");
|
||||||
|
setInterval(() => {
|
||||||
|
if (hasOverlay) {
|
||||||
|
updateOverlay();
|
||||||
|
}
|
||||||
|
}, ms);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import document from "document";
|
||||||
|
import * as healthOverlay from "healthOverlay.js"
|
||||||
|
|
||||||
|
console.log("App Started");
|
||||||
|
|
||||||
|
healthOverlay.init();
|
||||||
|
healthOverlay.continuousUpdate(1000); // update every 2 seconds while visible
|
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"fitbit": {
|
||||||
|
"appUUID": "7ebafab3-2bad-4cf6-b59c-726625cb3c62",
|
||||||
|
"appType": "app",
|
||||||
|
"appDisplayName": "HealthOverlay",
|
||||||
|
"iconFile": "resources/icon.png",
|
||||||
|
"wipeColor": "#607d8b",
|
||||||
|
"requestedPermissions": [
|
||||||
|
"access_activity"
|
||||||
|
],
|
||||||
|
"buildTargets": [
|
||||||
|
"higgs",
|
||||||
|
"meson"
|
||||||
|
],
|
||||||
|
"i18n": {
|
||||||
|
"en": {
|
||||||
|
"name": "HealthOverlay"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<svg>
|
||||||
|
<symbol id="overlayShade">
|
||||||
|
<rect id="overlayShadeColor" width="100%" height="100%" opacity="0.85" />
|
||||||
|
<animate attributeName="opacity" begin="enable" from="0" to="1" dur="0.25" final="freeze" />
|
||||||
|
<animate attributeName="opacity" begin="disable" from="1" to="0" dur="0.1" final="freeze" />
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="healthText">
|
||||||
|
<g opacity="0">
|
||||||
|
<text x="0" y="14" class="healthTextLabel" id="healthTextLabel" />
|
||||||
|
<image x="11" y="-12" width="30" height="30" href="" fill="white" id="healthTextIcon" />
|
||||||
|
<animate attributeName="opacity" begin="enable" from="0" to="1" dur="0.25" final="freeze" />
|
||||||
|
<animateTransform attributeType="translate" begin="enable" from="0, -10" to="0, 0" dur="0.25" final="freeze" easing="ease-out" />
|
||||||
|
<animate attributeName="opacity" begin="disable" from="1" to="0" dur="0.1" final="freeze" />
|
||||||
|
<animateTransform attributeType="translate" begin="disable" from="0, 0" to="0, 10" dur="0.1" final="freeze" easing="ease-out" />
|
||||||
|
</g>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="healthOverlay">
|
||||||
|
<g id="overlay">
|
||||||
|
<use href="#overlayShade" id="overlayShadeInstance" />
|
||||||
|
<use href="#healthText" x="35%" y="22%" class="healthTextInstance" id="stepsText">
|
||||||
|
<set href="healthTextIcon" attributeName="href" to="img/stat_steps_solid_32px.png" />
|
||||||
|
</use>
|
||||||
|
<use href="#healthText" x="35%" y="47%" class="healthTextInstance" id="calText">
|
||||||
|
<set href="healthTextIcon" attributeName="href" to="img/stat_cals_solid_32px.png" />
|
||||||
|
</use>
|
||||||
|
<use href="#healthText" x="35%" y="72%" class="healthTextInstance" id="distText">
|
||||||
|
<set href="healthTextIcon" attributeName="href" to="img/stat_dist_solid_32px.png" />
|
||||||
|
</use>
|
||||||
|
<use href="#healthText" x="76%" y="22%" class="healthTextInstance" id="elevText">
|
||||||
|
<set href="healthTextIcon" attributeName="href" to="img/stat_floors_solid_32px.png" />
|
||||||
|
</use>
|
||||||
|
<use href="#healthText" x="76%" y="47%" class="healthTextInstance" id="actminText">
|
||||||
|
<set href="healthTextIcon" attributeName="href" to="img/stat_am_solid_32px.png" />
|
||||||
|
</use>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
|
||||||
|
<rect x="0" y="0" width="100%" height="100%" opacity="0" id="touchArea" pointer-events="visible" />
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 468 B |
After Width: | Height: | Size: 527 B |
After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 275 B |
After Width: | Height: | Size: 531 B |
|
@ -0,0 +1,7 @@
|
||||||
|
<svg id="background">
|
||||||
|
<text x="50%" y="50%" text-anchor="middle" fill="white">Touch Me</text>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Add the health overlay last so touch area is on top of everything else -->
|
||||||
|
<use href="#healthOverlay" id="healthOverlayInstance" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 252 B |
|
@ -0,0 +1,20 @@
|
||||||
|
#background {
|
||||||
|
viewport-fill: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.healthTextLabel {
|
||||||
|
font-size: 28;
|
||||||
|
font-family: System-Regular;
|
||||||
|
font-weight: regular;
|
||||||
|
text-length: 8;
|
||||||
|
text-anchor: end;
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlay {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#overlayShadeColor {
|
||||||
|
fill: black;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<svg>
|
||||||
|
<defs>
|
||||||
|
<link rel="stylesheet" href="styles.css" />
|
||||||
|
<link rel="import" href="/mnt/sysassets/widgets_common.gui" />
|
||||||
|
|
||||||
|
<!-- line below required to import the health overlay -->
|
||||||
|
<link rel="import" href="healthOverlay.gui" />
|
||||||
|
|
||||||
|
</defs>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 270 B |