initial commit
This commit is contained in:
298
app/index.js
Normal file
298
app/index.js
Normal file
@@ -0,0 +1,298 @@
|
||||
import document from "document";
|
||||
import clock from "clock";
|
||||
import * as messaging from "messaging";
|
||||
import * as fs from "fs";
|
||||
import { HeartRateSensor } from "heart-rate";
|
||||
import { today } from "user-activity";
|
||||
import { goals } from "user-activity";
|
||||
import { vibration } from "haptics";
|
||||
import { display } from "display";
|
||||
import { preferences } from "user-settings";
|
||||
import { me as device } from "device";
|
||||
|
||||
if (!device.screen) device.screen = { width: 348, height: 250 };
|
||||
|
||||
const placeholder = '···';
|
||||
|
||||
const colorSchemes = {
|
||||
blues: ["#343375", "#6795b1"],
|
||||
aurora: ["#320c72", "#24c2bf"],
|
||||
roast: ["#ba8867", "#3c2710"],
|
||||
blush: ["#d09593", "#c71d6f"],
|
||||
ponyhair: ["#e9438b", "#9acccd"],
|
||||
lime: ["#dde170", "#06a33e"],
|
||||
dawn: ["#3b93c5", "#9f59a9"],
|
||||
peach: ["#fcbd95", "#f795a4"],
|
||||
violet: ["#9d25eb", "#4e6cc3"],
|
||||
}
|
||||
|
||||
const weekdays = [
|
||||
'Sun',
|
||||
'Mon',
|
||||
'Tue',
|
||||
'Wed',
|
||||
'Thu',
|
||||
'Fri',
|
||||
'Sat'
|
||||
];
|
||||
|
||||
let progress = 0;
|
||||
let progressXPos = 1;
|
||||
|
||||
let progressEl = document.getElementById('progress');
|
||||
let timeEl = document.getElementById('time');
|
||||
let dateEl = document.getElementById('date');
|
||||
let hrEl = document.getElementById('hr');
|
||||
let heartEl = document.getElementById('heartbeat');
|
||||
let textElements = document.getElementsByClassName('text');
|
||||
|
||||
let textOffset = 20;
|
||||
let hrOffset = 42;
|
||||
|
||||
let hrm = new HeartRateSensor;
|
||||
let hrTimer;
|
||||
|
||||
var colorDef = [
|
||||
colorSchemes['violet'][0],
|
||||
colorSchemes['violet'][1]
|
||||
];
|
||||
|
||||
var storedColorDef;
|
||||
var fileSuccess = true;
|
||||
console.log('reading color def');
|
||||
try {
|
||||
storedColorDef = fs.readFileSync("colordef.txt", "cbor");
|
||||
}
|
||||
catch(err) {
|
||||
fileSuccess = false;
|
||||
console.log('color def not found');
|
||||
}
|
||||
if (fileSuccess) {
|
||||
colorDef = storedColorDef;
|
||||
}
|
||||
|
||||
hrEl.text = placeholder;
|
||||
|
||||
function zeroPad(i) {
|
||||
if (i < 10) {
|
||||
i = "0" + i;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
function updateClock() {
|
||||
let currDate = new Date();
|
||||
let hours = currDate.getHours();
|
||||
let displayHours = hours;
|
||||
if (preferences.clockDisplay === '12h') {
|
||||
displayHours = displayHours % 12;
|
||||
displayHours = displayHours ? displayHours : 12;
|
||||
}
|
||||
let minutes = zeroPad(currDate.getMinutes());
|
||||
let day = currDate.getDate();
|
||||
//let month = currDate.getMonth()+1;
|
||||
let weekday = weekdays[currDate.getDay()];
|
||||
|
||||
let timeString = `${displayHours}:${minutes}`;
|
||||
timeEl.text = timeString;
|
||||
let dateString = `${weekday} ${day}`;
|
||||
dateEl.text = dateString;
|
||||
|
||||
updateProgress();
|
||||
progressEl.width = progressXPos;
|
||||
|
||||
if (progress <= 0.5) {
|
||||
for(let i=0; i < textElements.length; i++) {
|
||||
textElements[i].x = progressXPos + textOffset;
|
||||
textElements[i].textAnchor = 'start';
|
||||
}
|
||||
heartEl.x = progressXPos + textOffset - 8;
|
||||
hrEl.x = progressXPos + textOffset + hrOffset;
|
||||
hrEl.textAnchor = 'start';
|
||||
} else {
|
||||
for(let i=0; i < textElements.length; i++) {
|
||||
textElements[i].x = progressXPos - textOffset;
|
||||
textElements[i].textAnchor = 'end';
|
||||
}
|
||||
heartEl.x = progressXPos - textOffset - 38;
|
||||
hrEl.x = progressXPos - textOffset - hrOffset + 4;
|
||||
hrEl.textAnchor = 'end';
|
||||
}
|
||||
}
|
||||
|
||||
function updateProgress() {
|
||||
let steps = (today.adjusted.steps || null);
|
||||
if (steps !== null) {
|
||||
let stepGoal = (goals.steps || 0);
|
||||
progress = Math.min(steps/stepGoal, 1);
|
||||
progressXPos = Math.max(device.screen.width*progress, 10);
|
||||
} else {
|
||||
progress = 1;
|
||||
progressXPos = 10;
|
||||
}
|
||||
}
|
||||
|
||||
function updateColor() {
|
||||
progressEl.gradient.colors.c1 = colorDef[0];
|
||||
progressEl.gradient.colors.c2 = colorDef[1];
|
||||
}
|
||||
|
||||
hrm.onreading = () => {
|
||||
if (display.on) {
|
||||
let heartRate = (hrm.heartRate || placeholder);
|
||||
hrEl.text = heartRate;
|
||||
}
|
||||
clearTimeout(hrTimer);
|
||||
hrTimer = setTimeout(() => {
|
||||
hrEl.text = placeholder;
|
||||
}, 5000);
|
||||
hrm.stop();
|
||||
}
|
||||
|
||||
clock.granularity = "minutes";
|
||||
clock.ontick = () => updateClock();
|
||||
updateColor();
|
||||
|
||||
setInterval(() => {
|
||||
hrm.start();
|
||||
}, 2000);
|
||||
|
||||
messaging.peerSocket.onmessage = e => {
|
||||
console.log("Message received -> "+e.data.key+": "+e.data.newValue);
|
||||
display.poke();
|
||||
vibration.start("bump");
|
||||
switch (e.data.key) {
|
||||
case 'progresscolor':
|
||||
colorDef[0] = colorSchemes[e.data.newValue][0];
|
||||
colorDef[1] = colorSchemes[e.data.newValue][1];
|
||||
break;
|
||||
};
|
||||
updateColor();
|
||||
updateClock();
|
||||
fs.writeFileSync("colordef.txt", colorDef, "cbor");
|
||||
}
|
||||
|
||||
messaging.peerSocket.onopen = () => {
|
||||
console.log("Clockface opened socket");
|
||||
};
|
||||
|
||||
messaging.peerSocket.close = () => {
|
||||
console.log("Clockface closed socket");
|
||||
};
|
||||
|
||||
messaging.peerSocket.onerror = (err) => {
|
||||
console.log("Clockface socket error: " + err.code + " - " + err.message);
|
||||
}
|
||||
|
||||
|
||||
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 getActivityNumber(activity) {
|
||||
let values = {raw: 0, display: 0};
|
||||
|
||||
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 getActivityText(activity) {
|
||||
let label = placeholder;
|
||||
switch (activity) {
|
||||
case 'hr':
|
||||
label = hrLabel;
|
||||
break;
|
||||
case 'steps':
|
||||
case 'cal':
|
||||
case 'actmin':
|
||||
case 'dist':
|
||||
case 'elev':
|
||||
label = getActivityNumber(activity).display;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
let touchArea = document.getElementById('touchArea');
|
||||
let overlay = document.getElementById('overlay');
|
||||
let healthTextInstances = document.getElementsByClassName('healthTextInstance');
|
||||
let timeElementsNum = timeElements.length;
|
||||
|
||||
let hasOverlay = false;
|
||||
let overlayTimer;
|
||||
|
||||
touchArea.onclick = (e) => {
|
||||
if (hasOverlay == false) {
|
||||
vibration.start("bump");
|
||||
addOverlay();
|
||||
} else {
|
||||
removeOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function updateOverlay() {
|
||||
document.getElementById('stepsText').getElementById('healthTextLabel').text = getActivityText('steps');
|
||||
document.getElementById('calText').getElementById('healthTextLabel').text = getActivityText('cal');
|
||||
document.getElementById('distText').getElementById('healthTextLabel').text = getActivityText('dist');
|
||||
document.getElementById('elevText').getElementById('healthTextLabel').text = getActivityText('elev');
|
||||
document.getElementById('actminText').getElementById('healthTextLabel').text = getActivityText('actmin');
|
||||
}
|
||||
|
||||
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);
|
||||
document.getElementById('overlayShadeInstance').animate('disable');
|
||||
for(var i = 0; i < healthTextInstances.length; i++) {
|
||||
healthTextInstances[i].animate('disable');
|
||||
}
|
||||
setTimeout(() => {
|
||||
overlay.style.display = 'none';
|
||||
}, 100);
|
||||
hasOverlay = false;
|
||||
}
|
||||
Reference in New Issue
Block a user