Merge pull request #3860 from voloved/daisy_updates

Daisy Multiple Rings
master
Rob Pilling 2025-06-03 21:55:30 +01:00 committed by GitHub
commit 991b896f22
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 545 additions and 148 deletions

View File

@ -14,3 +14,4 @@
0.14: Use `power_usage` module 0.14: Use `power_usage` module
0.15: Ring can now show hours, minute, or seconds hand, day/night left, or battery; Allowed for 12hr time; Ring now goes up in 5% increments; Step goal can be changed; The info that is set on the watchface will retain when leaving the face 0.15: Ring can now show hours, minute, or seconds hand, day/night left, or battery; Allowed for 12hr time; Ring now goes up in 5% increments; Step goal can be changed; The info that is set on the watchface will retain when leaving the face
0.16: Ring is now dynamically-created, rather than displaying pre-rendered rings; Seconds update every second; Ability to see Day ring; Settings options moved around to avoid popping of Steps option disappearing when not used; In Sun setting, ring is fully illuminated between during all of sunrise and sunset. 0.16: Ring is now dynamically-created, rather than displaying pre-rendered rings; Seconds update every second; Ability to see Day ring; Settings options moved around to avoid popping of Steps option disappearing when not used; In Sun setting, ring is fully illuminated between during all of sunrise and sunset.
0.17: Made the display show three rings with different ring displays.

View File

@ -17,10 +17,10 @@ See [#1248](https://github.com/espruino/BangleApps/issues/1248)
* Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location * Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location
* If your Sunrise, Sunset times look odd make sure you have setup your location using * If your Sunrise, Sunset times look odd make sure you have setup your location using
[MyLocation](https://banglejs.com/apps/?id=mylocation) [MyLocation](https://banglejs.com/apps/?id=mylocation)
* The screen is updated every minute to save battery power, unless the ring is set to display seconds, then it updates every 3 seconds. * The screen is updated every minute to save battery power, unless a ring is set to display seconds or steps.
* Uses the [BloggerSansLight](https://www.1001fonts.com/rounded-fonts.html?page=3) font, which if free for commercial use * Uses the [BloggerSansLight](https://www.1001fonts.com/rounded-fonts.html?page=3) font, which if free for commercial use
* You need to run >2V22 to show the battery estimate in hours * You need to run >2V22 to show the battery estimate in hours
* In the settings, the ring can be set to: * In the settings, the rings can be set to:
* Hours - Displays the ring as though it's the hour hand on an analog clock. * Hours - Displays the ring as though it's the hour hand on an analog clock.
* Minutes - Displays the ring as though it's the minute hand on an analog clock. * Minutes - Displays the ring as though it's the minute hand on an analog clock.
* Seconds - Displays the ring as though it's the seconds hand on an analog clock. This option uses far more battery than any other option as it updates the screen 60 times more often. * Seconds - Displays the ring as though it's the seconds hand on an analog clock. This option uses far more battery than any other option as it updates the screen 60 times more often.
@ -28,6 +28,11 @@ See [#1248](https://github.com/espruino/BangleApps/issues/1248)
* Steps - Displays the ring as the amount of steps taken that day out of Step Target setting. * Steps - Displays the ring as the amount of steps taken that day out of Step Target setting.
* Battery - Displays the ring as the amount of battery percentage left. * Battery - Displays the ring as the amount of battery percentage left.
* Sun - Displays the ring as the amount of time that has passed from sunrise to sunset in the day and the amount of time between sunset and sunrise at night. * Sun - Displays the ring as the amount of time that has passed from sunrise to sunset in the day and the amount of time between sunset and sunrise at night.
* The rings have the following displays
* None - Don't display the ring at all.
* Full - Display a full circle, where the filled-in part of the circle's color differs with the unfilled section.
* Semi - Similar to full, but the unfilled section does not display.
* C - Displays a full circle with a notch.
## Future Development ## Future Development
* Use mini icons in the information line rather that text * Use mini icons in the information line rather that text
@ -37,5 +42,6 @@ See [#1248](https://github.com/espruino/BangleApps/issues/1248)
## Screenshots ## Screenshots
![](screenshot_daisy1.png) ![](screenshot_daisy1.png)
![](screenshot_daisy3.png) ![](screenshot_daisy3.png)
![](screenshot_daisy4.png)
It is worth looking at the real thing though as the screenshots do not do it justice. It is worth looking at the real thing though as the screenshots do not do it justice.

View File

@ -17,16 +17,26 @@ let warned = 0;
let idle = false; let idle = false;
let IDLE_MINUTES = 26; let IDLE_MINUTES = 26;
let pal1; // palette for 0-49% var pals = Array(3).fill().map(() => (
let pal2; // palette for 50-100% { pal1: null, // palette for 0-49%
const infoLine = (3*h/4) - 6; pal2: null // palette for 50-100%
const infoWidth = 56; }));
const infoHeight = 11;
let palbg;
const infoLineDefault = (3*h/4) - 6;
const infoWidthDefault = 64;
const infoHeightDefault = 8;
const ringEdge = 4; const ringEdge = 4;
const ringIterOffset = 10;
const ringThick = 6; const ringThick = 6;
const minStepToUpdate = 10; // In number of steps as a minumum to update the text.
const minStepPctUpdateRings = 3; // If the current step is less percent than last updated, don't redraw the rings
let nextUpdateMs; let nextUpdateMs;
var drawingSteps = false; var drawingSteps = false;
var prevRing = {start: null, end: null, max: null}; var innerMostRing = 0;
var outerMostRing = 0;
var prevStepDisplayed = 0;
var prevRing = Array(3).fill().map(() => ({ start: null, end: null, max: null }));
function log_debug(o) { function log_debug(o) {
//print(o); //print(o);
@ -35,12 +45,37 @@ function log_debug(o) {
var hrmImg = require("heatshrink").decompress(atob("i0WgIKHgPh8Ef5/g///44CBz///1///5A4PnBQk///wA4PBA4MDA4MH/+Ah/8gEP4EAjw0GA")); var hrmImg = require("heatshrink").decompress(atob("i0WgIKHgPh8Ef5/g///44CBz///1///5A4PnBQk///wA4PBA4MDA4MH/+Ah/8gEP4EAjw0GA"));
// https://www.1001fonts.com/rounded-fonts.html?page=3 // https://www.1001fonts.com/rounded-fonts.html?page=3
//one ring
Graphics.prototype.setFontBloggerSansLight46 = function(scale) { Graphics.prototype.setFontBloggerSansLight46 = function(scale) {
// Actual height 46 (45 - 0) // Actual height 46 (45 - 0)
this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAAA/AAAAAAAAPwAAAAAAAD4AAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAH/gAAAAAAP/wAAAAAAf/gAAAAAAf/AAAAAAA//AAAAAAB/+AAAAAAD/8AAAAAAH/4AAAAAAH/wAAAAAAP/gAAAAAAf/gAAAAAA//AAAAAAB/+AAAAAAA/8AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///8AAAAP////4AAAP/////AAAH/////4AAD+AAAB/AAA8AAAAHwAAeAAAAA+AAHgAAAAHgADwAAAAB4AA8AAAAAPAAPAAAAADwADwAAAAA8AA8AAAAAPAAPAAAAADwAB4AAAAB4AAeAAAAAeAAHwAAAAPgAA/AAAAPwAAH/////4AAA/////8AAAH////+AAAAf///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAPAAAAAAAAHwAAAAAAAB4AAAAAAAA+AAAAAAAAfAAAAAAAAHgAAAAAAAD4AAAAAAAB8AAAAAAAAeAAAAAAAAPgAAAAAAADwAAAAAAAB//////4AAf//////AAH//////gAA//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAD4AAHAAAAD+AAD4AAAB/gAA8AAAB/4AAfAAAA/+AAHgAAAf3gAB4AAAPx4AA8AAAH4eAAPAAAD4HgADwAAB8B4AA8AAA+AeAAPAAAfAHgADwAAPgB4AA8AAHwAeAAHgAD4AHgAB4AD8AB4AAfAB+AAeAAD8B/AAHgAAf//gAB4AAH//wAAeAAAf/wAAHgAAB/wAAA4AAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AADgAAAAPAAB4AAAADwAAeAAAAA+AAHgAAAAHgAB4ABgAB4AAeAA8AAeAAHgA/AADwAB4AfwAA8AAeAP8AAPAAHgH/AADwAB4H7wAA8AAeD48AAPAAHh8PAAHgAB5+BwAB4AAe/AeAA+AAH/AHwAfAAB/gA/AfgAAfwAH//wAAHwAA//4AAA4AAH/8AAAAAAAf4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAD+AAAAAAAD/gAAAAAAH/4AAAAAAH/+AAAAAAP/ngAAAAAP/h4AAAAAf/AeAAAAAf/AHgAAAA/+AB4AAAA/+AAeAAAB/8AAHgAAA/8AAB4AAAP4AAAeAAAB4AAAHgAAAAAAAB4AAAAAAAAeAAAAAAP///4AAAAH////AAAAA////gAAAAP///4AAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAD4AA8AAD///gAPAAB///4AD4AAf//+AAeAAH+APAAHgAB4AHgAA4AAeAB4AAOAAHgAcAADwAB4AHAAA8AAeADwAAPAAHgAcAADwAB4AHAAA8AAeAB4AAeAAHgAeAAHgAB4AHwAD4AAeAA+AB8AAHgAP4B+AAB4AB///gAAOAAP//gAABAAA//wAAAAAAD/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAAB///4AAAAD////wAAAD////+AAAB/////4AAA/gPgB/AAAfgDwAHwAAPgA8AA+AADwAeAAHgAB4AHgAB4AAeAB4AAfAAHgAeAADwABwAHgAA8AAcAB4AAPAAHAAeAAHwAB4AHgAB4AAeAB8AAeAAHgAPAAPgAB4AD8APwAAOAAfwP4AADgAD//8AAAAAAf/+AAAAAAB/+AAAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAAB4AAAAA4AAeAAAAB/AAHgAAAB/wAB4AAAB/4AAeAAAD/4AAHgAAD/wAAB4AAH/wAAAeAAH/gAAAHgAP/gAAAB4AP/AAAAAeAf/AAAAAHgf+AAAAAB4/+AAAAAAe/8AAAAAAH/8AAAAAAB/4AAAAAAAf4AAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAA/AB/+AAAA/8B//wAAA//gf/+AAAf/8PgPgAAH4fngB8AAD4B/wAPgAA8AP8AB4AAeAB+AAeAAHgAfgADwAB4ADwAA8AAcAA8AAPAAHAAPAADwAB4ADwAA8AAeAB+AAPAAHgAfgAHgAB8AP8AB4AAPgH/AA+AAD8H54AfAAAf/8fgPwAAD/+D//4AAAf/Af/8AAAB/AD/+AAAAAAAP+AAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAAAf/wAAAAAAf/+AAAAAAP//4AAwAAH//+AAeAAD+APwAHgAA+AA+AB4AAfAAHgAOAAHgAB4ADwAB4AAPAA8AAeAADwAPAAHgAA8ADwAB4AAPAA8AAeAADwAPAAHgAA8AHgAB8AAeAB4AAPgAHgA+AAD8ADwA/AAAfwA8A/gAAD/wef/wAAAf////4AAAB////4AAAAH///wAAAAAD/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AB4AAAAAfgA/AAAAAH4APwAAAAB+AD4AAAAAPAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DRAcHBwcHBwcHBwcDQ=="), 56+(scale<<8)+(1<<16)); this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAAA/AAAAAAAAPwAAAAAAAD4AAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAAAAAH/gAAAAAAP/wAAAAAAf/gAAAAAAf/AAAAAAA//AAAAAAB/+AAAAAAD/8AAAAAAH/4AAAAAAH/wAAAAAAP/gAAAAAAf/gAAAAAA//AAAAAAB/+AAAAAAA/8AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///8AAAAP////4AAAP/////AAAH/////4AAD+AAAB/AAA8AAAAHwAAeAAAAA+AAHgAAAAHgADwAAAAB4AA8AAAAAPAAPAAAAADwADwAAAAA8AA8AAAAAPAAPAAAAADwAB4AAAAB4AAeAAAAAeAAHwAAAAPgAA/AAAAPwAAH/////4AAA/////8AAAH////+AAAAf///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAPAAAAAAAAHwAAAAAAAB4AAAAAAAA+AAAAAAAAfAAAAAAAAHgAAAAAAAD4AAAAAAAB8AAAAAAAAeAAAAAAAAPgAAAAAAADwAAAAAAAB//////4AAf//////AAH//////gAA//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAD4AAHAAAAD+AAD4AAAB/gAA8AAAB/4AAfAAAA/+AAHgAAAf3gAB4AAAPx4AA8AAAH4eAAPAAAD4HgADwAAB8B4AA8AAA+AeAAPAAAfAHgADwAAPgB4AA8AAHwAeAAHgAD4AHgAB4AD8AB4AAfAB+AAeAAD8B/AAHgAAf//gAB4AAH//wAAeAAAf/wAAHgAAB/wAAA4AAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AADgAAAAPAAB4AAAADwAAeAAAAA+AAHgAAAAHgAB4ABgAB4AAeAA8AAeAAHgA/AADwAB4AfwAA8AAeAP8AAPAAHgH/AADwAB4H7wAA8AAeD48AAPAAHh8PAAHgAB5+BwAB4AAe/AeAA+AAH/AHwAfAAB/gA/AfgAAfwAH//wAAHwAA//4AAA4AAH/8AAAAAAAf4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAAAD+AAAAAAAD/gAAAAAAH/4AAAAAAH/+AAAAAAP/ngAAAAAP/h4AAAAAf/AeAAAAAf/AHgAAAA/+AB4AAAA/+AAeAAAB/8AAHgAAA/8AAB4AAAP4AAAeAAAB4AAAHgAAAAAAAB4AAAAAAAAeAAAAAAP///4AAAAH////AAAAA////gAAAAP///4AAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAD4AA8AAD///gAPAAB///4AD4AAf//+AAeAAH+APAAHgAB4AHgAA4AAeAB4AAOAAHgAcAADwAB4AHAAA8AAeADwAAPAAHgAcAADwAB4AHAAA8AAeAB4AAeAAHgAeAAHgAB4AHwAD4AAeAA+AB8AAHgAP4B+AAB4AB///gAAOAAP//gAABAAA//wAAAAAAD/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAAB///4AAAAD////wAAAD////+AAAB/////4AAA/gPgB/AAAfgDwAHwAAPgA8AA+AADwAeAAHgAB4AHgAB4AAeAB4AAfAAHgAeAADwABwAHgAA8AAcAB4AAPAAHAAeAAHwAB4AHgAB4AAeAB8AAeAAHgAPAAPgAB4AD8APwAAOAAfwP4AADgAD//8AAAAAAf/+AAAAAAB/+AAAAAAAH8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAB4AAAAAAAAeAAAAAAAAHgAAAAAAAB4AAAAA4AAeAAAAB/AAHgAAAB/wAB4AAAB/4AAeAAAD/4AAHgAAD/wAAB4AAH/wAAAeAAH/gAAAHgAP/gAAAB4AP/AAAAAeAf/AAAAAHgf+AAAAAB4/+AAAAAAe/8AAAAAAH/8AAAAAAB/4AAAAAAAf4AAAAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAA/AB/+AAAA/8B//wAAA//gf/+AAAf/8PgPgAAH4fngB8AAD4B/wAPgAA8AP8AB4AAeAB+AAeAAHgAfgADwAB4ADwAA8AAcAA8AAPAAHAAPAADwAB4ADwAA8AAeAB+AAPAAHgAfgAHgAB8AP8AB4AAPgH/AA+AAD8H54AfAAAf/8fgPwAAD/+D//4AAAf/Af/8AAAB/AD/+AAAAAAAP+AAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAAAf/wAAAAAAf/+AAAAAAP//4AAwAAH//+AAeAAD+APwAHgAA+AA+AB4AAfAAHgAOAAHgAB4ADwAB4AAPAA8AAeAADwAPAAHgAA8ADwAB4AAPAA8AAeAADwAPAAHgAA8AHgAB8AAeAB4AAPgAHgA+AAD8ADwA/AAAfwA8A/gAAD/wef/wAAAf////4AAAB////4AAAAH///wAAAAAD/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AB4AAAAAfgA/AAAAAH4APwAAAAB+AD4AAAAAPAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DRAcHBwcHBwcHBwcDQ=="), 56+(scale<<8)+(1<<16));
return this; return this;
}; };
//Two Rings
Graphics.prototype.setFontBloggerSansLight42 = function() {
// Actual height 28 (31 - 4)
// 1 BPP
return this.setFontCustom(
atob('AAAAAAAAAAAAAAAAAAAAAAAAAHwAAAAAHwAAAAAHwAAAAAHwAAAAADgAAAAAAAAAAAAAwAAAAAHwAAAAA/wAAAAH+AAAAA/wAAAAH+AAAAA/wAAAAH+AAAAA/wAAAAD+AAAAADwAAAAACAAAAAAAAAAAAAAAAAAAAAAP8AAAAD//wAAAP//8AAA////AAB////gAB4AAPgADwAADwADgAAAwADAAAAwADAAAAwADAAAAwADgAAAwADwAADwAB8AAPgAB////gAA////AAAP//8AAAD//wAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAMAAAQAAYAAAwAAYAAAwAA4AAAwAAwAAAwAB////wAD////wAD////wAD////wAAAAAAwAAAAAAwAAAAAAwAAAAAAwAAAAAAQAAAAAAQAAAAAAAAAAAAAAAAAAAAAAB8AADwAB+AAHwAD8AAPwADgAAfwADAAA7wADAABzwADAABzwADAAHjwADAAPDwADAAeDwADgA8DwAD4H4DwAB//wDwAB//gDwAA/+ADwAAP8ADwAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAfgAB8AAfwAD8AABwADgAABwADAAAAwADADAAwADADAAwADADAAwADADAAwADAHAAwADgHgBwADwfgBwAB//4DgAB/8//gAA/4//AAAfwf+AAAAAP8AAAAABgAAAAAAAAAAAAAAAAAAADwAAAAAPwAAAAAfwAAAAA9wAAAADxwAAAAHhwAAAAeBwAAAA8BwAAADwBwAAAHgBwAAAfABwAAA8ABwAAB////wAD////wAD////wAD////wAAAABwAAAAABwAAAAABwAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAfgAD//AfgAD//AHwAD//ABwADwHAAwADwHAAwADwGAAwADwGAAwADwGAAwADwHAAwADwHABwADwHABwADwDgDgADwD//gADwB//AADgB/+AAAAAf8AAAAADAAAAAAAAAAAAAAAAAAAAAAAAAA//gAAAH//8AAAP//+AAAf///AAA/DAfgAB4DAHwABwHABwADgGAAwADgGAAwADAGAAwADAHAAwADAHAAwADAHgBwADgH8fgAD4D//gAD8D//AAAAA/+AAAAAf4AAAAAAAAAAAAAAAAAAAAAAAD8AAAAAD+AAAAAD8AAAAADwAAAwADwAADwADwAAPwADwAA/gADwAD8AADwAPwAADwA/AAADwD8AAADwPwAAADw/AAAADz4AAAAD/gAAAAD+AAAAAD4AAAAADgAAAAAAAAAAAAAAAAAAAAAADgAAAHgP8AAAf4f/AAA/8//gAB////gAD8/wDwADgHgBwADAHAAwADADAAwADADAAwADADAAwADAHAAwADgHgBwAB8/wDwAB////gAA/8//gAAf4f/AAAHgP8AAAAADgAAAAAAAAAAAAAAAAAD8AAAAAP/AHgAA//gPwAB//wDwAB/f4AwADwB4AwADgA4AwADAAYAwADAAYAwADAAYAwADAAYBwADgA4DwADwAwHgAB+Aw/gAB////AAA///+AAAf//4AAAD//gAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMADgAAAeAHwAAA/AHwAAA/AHwAAAeAHwAAAAABAAAAAAAAAA'),
46,
atob("CQ0VFBQVFhUVFRUVCg=="),
42|65536
);
};
// Three rings
Graphics.prototype.setFontBloggerSansLight38 = function() {
// Actual height 25 (28 - 4)
// 1 BPP
return this.setFontCustom(
atob('AAAAAAAAAAAAAAAAAwAAAAAeAAAAAPgAAAAD4AAAAAcAAAAAAAAAAAAYAAAAA+AAAAB/AAAAD+AAAAH8AAAAP4AAAAP4AAAAfwAAAA/gAAAAPAAAAACAAAAAAAAAAAAAAAAAAAA/4AAAB//wAAB///AAA///8AAfgA/AAPAAB4ADAAAGAAwAABgAMAAAYADAAAGAA4AABgAPAAB4AB+AD8AAP//+AAB///AAAH//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAACAAGAAAgABgAAYAAwAAGAAcAABgAH///4AD///+AA////gAP///4AAAAAGAAAAABgAAAAAYAAAAACAAAAAAgAAAAAAAAAAAAAAAAADgAHwAB4AD8AA+AA4AAfgAMAAG4ADAADOAAwABjgAMAA44ADAAcOAAwAeDgAOAPA4AB8/gOAAf/wDgAD/4A4AAf4AOAAB4ADgAAAAAAAAAAAAAAAAAAAAHwAH4AD8AA+AA8AABgAMAAAYADAGAGAAwBgBgAMAYAYADAGAGAAwDgBgAOA4AYAD5/AOAAf+8PAAH/n/wAA/x/4AABgP8AAAAA8AAAAAAAAAAABgAAAAA8AAAAA/AAAAAdwAAAAecAAAAPHAAAAHBwAAAHgcAAADgHAAADwBwAAB4AcAAA8AHAAA////gAP///4AD///+AAAABwAAAAAcAAAAAHAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAHwAD/8B+AA//ADgAOAwAYADgMAGAA4DABgAOAwAYADgMAGAA4DABgAOA4A4ADgOAOAA4B4PAAOAf/wADgD/4AAAAf8AAAAB4AAAAAAAAAAAAAAAAA+AAAAD//AAAD//8AAB///gAA/2f8AAfBgHAAHAwA4ADgMAGAAwDABgAMAwAYADAMAGAAwDgDgAMA8B4ADwP/8AA+B//AAHgP/AAAAA/AAAAAAAAAAAAAAAAAAAAAA/AAAAAPwAAAADwAACAA4AADgAOAAD4ADgAD8AA4AD8AAOAD8AADgD8AAA4D8AAAOD8AAADj4AAAA74AAAAP4AAAAD4AAAAA4AAAAAAAAAAAAAAAAAAAAHwAAB8H/AAA/z/4AAf+//AAH/+B4ADgeAOAAwDgBgAMAwAYADAMAGAAwDABgAMA4AYADgeAOAAf/4PgAH/v/wAA/z/8AAHwP8AAAAB8AAAAAAAAAAAAAAAAfgAAAAf+A+AAP/wPgAH/8AYADwHgGAA4A4BgAMAOAYADABgGAAwAYBgAMAGA4ADgDgeAA8AwPAAH+N/wAA///4AAH//4AAAf/8AAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgBwAAB8A+AAAfAPgAAHgB4AAAwAMAAAAAAAAA=='),
46,
atob("CAwTEhITFBMTExMTCQ=="),
38|65536
);
};
Graphics.prototype.setFontRoboto20 = function(scale) { Graphics.prototype.setFontRoboto20 = function(scale) {
// Actual height 21 (20 - 0) // Actual height 21 (20 - 0)
this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAH/zA/+YAAAAAAAHwAAwAAHwAA+AAAAAAAAAAAQACDAAYbADP4B/8A/zAGYZADH4A/+A/7AHYYADCAAAAAAAQAeHgH4eBzgwMMHnhw88GGBw4wHj+AcPgAAAAAAAAAAB4AA/gAGMAAwhwGMcAfuABzgABzgAc+AOMYBhBAAMYAB/AAHwAAAAAHwD5+A/8YGPDAw8YGPzA/HYD4fAADwAB/AAOYAABAAAAHwAA4AAAAAAAAAAH/gD//B8A+cAA7AADAAAAAAAYAAbwAHHgHwf/4A/8AAAAEAABiAAGwAA8AA/AAH+AAGwAByAAEAAAAAAAMAABgAAMAABgAH/wA/+AAMAABgAAMAABgAAAAAAAIAAfAADwAAAABgAAMAABgAAMAABgAAAAAAAAAAAAADAAAYAAAAAAAAADgAB8AB+AA+AA+AA/AAHAAAgAAAAAAB8AB/8Af/wHAHAwAYGADAwAYHAHAf/wB/8AAAAAAAAAAABgAAcAADAAAYAAH//A//4AAAAAAAAAAAAAAAAAAAAABwDAeA4HAPAwHYGBzAwcYHHDAfwYB8DAAAYAAAAAAABgOAcBwHADAwwYGGDAwwYHPHAf/wB58AAAAAAAAADAAB4AAfAAPYAHjAB4YA8DAH//A//4AAYAADAAAAAAAAAEMA/xwH+HAxgYGMDAxgYGODAw/4GD+AAHAAAAAAAAAf8AP/wD2HA5wYGMDAxgYGOHAA/wAD8AAAAAAAAAAAGAAAwAAGADAwB4GB+Aw+AGfAA/gAHwAAwAAAAAAADAB5+Af/wHPDAwwYGGDAwwYHPHAfvwB58AAAAAAAAAAAB+AAf4AHDjAwMYGBjAwM4HDOAf/gB/4AAAAAAAAAAAAYDADAYAAAAAAAAAAYDAfAYHwAAAABAAAcAADgAA+AAGwAB3AAMYABjgAYMAAAAAAAAAAAAAAABmAAMwABmAAMwABmAAMwABmAAMwAAiAAAAAAAAAYMADjgAMYAB3AAGwAA2AADgAAcAABAAAAAAAAAMAADgAA4AAGBzAweYGHAA/wAD8AAEAAAAwAB/4A/PwOAGDgAYYPxmH/Mw4ZmMDMxgZmM+Mx/5mHDAYAIDgDAPBwAf8AAMAAAAAAAYAAfAAPwAP4AH+AH4wA8GAH4wAP2AAPwAAfwAAfAAAYAAAAAAAAAAA//4H//AwwYGGDAwwYGGDAwwYH/HAf/wB58AAAAADAAH/AD/+AcBwHADAwAYGADAwAYGADA4A4DweAODgAAAAAAAAAAAAAAH//A//4GADAwAYGADAwAYGADAYAwD4+AP/gAfwAAAAAAAAAAAH//A//4GDDAwYYGDDAwYYGDDAwYYGCDAgAYAAAAAAAH//A//4GDAAwYAGDAAwYAGDAAwYAGAAAAAAAAAAH/AD/8AcBwHAHAwAYGADAwYYGDDA4YYDz/AOfwAAAAAAAAAAA//4H//A//4ADAAAYAADAAAYAADAAAYAADAA//4H//AAAAAAAAAAAAAAA//4H//AAAAAAAAABAAAeAAB4AADAAAYAADAAAYAAHA//wH/8AAAAAAAAAAAAAAA//4H//AAcAAPAAD4AA/wAOPADg8A4B4GAHAgAYAAAAAAAH//A//4AADAAAYAADAAAYAADAAAYAADAAAAAAAA//4H//A+AAB+AAD8AAD8AAH4AAPAAH4AH4AD8AD8AA+AAH//A//4AAAAAAAH//A//4H//AeAAB8AADwAAPgAAeAAA8AADwH//A//4AAAAAAAAAAAH/AB/8AeDwHAHAwAYGADAwAYGADA4A4DweAP/gA/4AAAAAAAAAAAH//A//4GBgAwMAGBgAwMAGBgAwcAH/AAfwAA8AAAAAA/4AP/gDgOA4A4GADAwAYGADAwAYHAHgeD+B/8wD+GAAAAAAAAAAA//4H//AwYAGDAAwYAGDgAweAHH8Afz4B8HAAAIAAYAPDwD8OA5w4GGDAwwYGHDAwYYHDnAePwBw8AAAAGAAAwAAGAAAwAAGAAA//4H//AwAAGAAAwAAGAAAwAAAAAAAAAH/4A//wAAPAAAYAADAAAYAADAAAYAAPA//wH/8AAAAAAAAgAAHAAA/AAB/AAD+AAD+AAD4AAfAAfwAfwAfwAH4AA4AAEAAA+AAH/AAH/gAD/AAD4AD+AH+AH8AA+AAH+AAD+AAD/AAD4AH/AP/AH+AA8AAAAAAAAAGADA4A4HweAPPgA/wAB8AAfwAPvgDweA8B4GADAAAIGAAA4AAHwAAPgAAfAAA/4AH/AD4AB8AA+AAHgAAwAAAAAAAAAGADAwB4GAfAwPYGDzAx4YGeDA/AYHwDA4AYGADAAAAAAAA///3//+wAA2AAGAAAGAAA+AAD8AAD8AAD4AAH4AAHgAAMAAAAwAA2AAG///3//+AAAAAAAAAAAOAAHwAD4AA8AAD8AADwAAGAAAAAAABgAAMAABgAAMAABgAAMAABgAAMAABgAAAEAAAwAADAAAIAAAAAAAAAAEeABn4Ad3ADMYAZjADMYAZmAB/4AP/AAAAAAAA//4H//ABgwAYDADAYAYDADg4AP+AA/gABwAAAAAAAAA/gAP+ADg4AYDADAYAYDADAYAOOABxwAAAAAEAAH8AB/wAcHADAYAYDADAYAcDA//4H//AAAAAAAAAAAAH8AB/wAdnADMYAZjADMYAZjAB84AHmAAMAAMAABgAB//gf/8HMAAxgAGIAAAAAAH8IB/zAcHMDAZgYDMDAZgcHcD//Af/wAAAAAAAAAAH//A//4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAGf/Az/4AAAAAAAAAAMz//mf/4AAAAAAAAAAH//A//4ABwAAeAAH4ABzwAcPACAYAABAAAAAAAA//4H//AAAAAAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/ABgAAYAADAAAYAADgAAP/AA/4AAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAAH8AB/wAcHADAYAYDADAYAYDADx4AP+AA/gAAAAAAAAf/8D//gYDADAYAYDADAYAcHAB/wAH8AAEAAAAAAEAAH8AB/wAcHADAYAYDADAYAYDAD//gf/8AAAAAAAAAAAf/AD/4AcAADAAAYAACAAAAEAB5wAfnADMYAZjADGYAYzADn4AOeAAAAAAAADAAAYAAf/wD//ADAYAYDAAAAAAAAD/gAf/AAA4AADAAAYAADAAAwAf/AD/4AAAAAAAAYAAD4AAP4AAP4AAPAAH4AH4AD8AAcAAAAAAQAADwAAf4AAf4AAPAAP4AP4ADwAAfgAA/gAA/AAD4AH+AD+AAeAAAAAAAAACAYAcHADzwAH8AAfAAH8ADx4AcHACAIAcAMD4BgP4MAP/AAPwAP4AP4AD4AAcAAAAAAAAADAYAYHADD4AY7ADOYAfjADwYAcDADAYAAAAADAAA4AH//B/v8cABzAACAAAH//w//+AAAAAAACAACcAAx/n+H//AA4AAHAAAAAAAAAAAAAOAADgAAYAADAAAcAABgAAGAAAwAAGAADwAAcAAAAA"), 32, atob("BQUHDQwPDQQHBwkMBAYGCQwMDAwMDAwMDAwFBAsMCwoTDg0ODgwMDg8GDA0LEg8ODQ4NDA0ODRMNDQ0GCQYJCQYLDAsMCwcMDAUFCwUSDAwMDAcLBwwKEAoKCgcFBw4A"), 21+(scale<<8)+(1<<16)); this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAH/zA/+YAAAAAAAHwAAwAAHwAA+AAAAAAAAAAAQACDAAYbADP4B/8A/zAGYZADH4A/+A/7AHYYADCAAAAAAAQAeHgH4eBzgwMMHnhw88GGBw4wHj+AcPgAAAAAAAAAAB4AA/gAGMAAwhwGMcAfuABzgABzgAc+AOMYBhBAAMYAB/AAHwAAAAAHwD5+A/8YGPDAw8YGPzA/HYD4fAADwAB/AAOYAABAAAAHwAA4AAAAAAAAAAH/gD//B8A+cAA7AADAAAAAAAYAAbwAHHgHwf/4A/8AAAAEAABiAAGwAA8AA/AAH+AAGwAByAAEAAAAAAAMAABgAAMAABgAH/wA/+AAMAABgAAMAABgAAAAAAAIAAfAADwAAAABgAAMAABgAAMAABgAAAAAAAAAAAAADAAAYAAAAAAAAADgAB8AB+AA+AA+AA/AAHAAAgAAAAAAB8AB/8Af/wHAHAwAYGADAwAYHAHAf/wB/8AAAAAAAAAAABgAAcAADAAAYAAH//A//4AAAAAAAAAAAAAAAAAAAAABwDAeA4HAPAwHYGBzAwcYHHDAfwYB8DAAAYAAAAAAABgOAcBwHADAwwYGGDAwwYHPHAf/wB58AAAAAAAAADAAB4AAfAAPYAHjAB4YA8DAH//A//4AAYAADAAAAAAAAAEMA/xwH+HAxgYGMDAxgYGODAw/4GD+AAHAAAAAAAAAf8AP/wD2HA5wYGMDAxgYGOHAA/wAD8AAAAAAAAAAAGAAAwAAGADAwB4GB+Aw+AGfAA/gAHwAAwAAAAAAADAB5+Af/wHPDAwwYGGDAwwYHPHAfvwB58AAAAAAAAAAAB+AAf4AHDjAwMYGBjAwM4HDOAf/gB/4AAAAAAAAAAAAYDADAYAAAAAAAAAAYDAfAYHwAAAABAAAcAADgAA+AAGwAB3AAMYABjgAYMAAAAAAAAAAAAAAABmAAMwABmAAMwABmAAMwABmAAMwAAiAAAAAAAAAYMADjgAMYAB3AAGwAA2AADgAAcAABAAAAAAAAAMAADgAA4AAGBzAweYGHAA/wAD8AAEAAAAwAB/4A/PwOAGDgAYYPxmH/Mw4ZmMDMxgZmM+Mx/5mHDAYAIDgDAPBwAf8AAMAAAAAAAYAAfAAPwAP4AH+AH4wA8GAH4wAP2AAPwAAfwAAfAAAYAAAAAAAAAAA//4H//AwwYGGDAwwYGGDAwwYH/HAf/wB58AAAAADAAH/AD/+AcBwHADAwAYGADAwAYGADA4A4DweAODgAAAAAAAAAAAAAAH//A//4GADAwAYGADAwAYGADAYAwD4+AP/gAfwAAAAAAAAAAAH//A//4GDDAwYYGDDAwYYGDDAwYYGCDAgAYAAAAAAAH//A//4GDAAwYAGDAAwYAGDAAwYAGAAAAAAAAAAH/AD/8AcBwHAHAwAYGADAwYYGDDA4YYDz/AOfwAAAAAAAAAAA//4H//A//4ADAAAYAADAAAYAADAAAYAADAA//4H//AAAAAAAAAAAAAAA//4H//AAAAAAAAABAAAeAAB4AADAAAYAADAAAYAAHA//wH/8AAAAAAAAAAAAAAA//4H//AAcAAPAAD4AA/wAOPADg8A4B4GAHAgAYAAAAAAAH//A//4AADAAAYAADAAAYAADAAAYAADAAAAAAAA//4H//A+AAB+AAD8AAD8AAH4AAPAAH4AH4AD8AD8AA+AAH//A//4AAAAAAAH//A//4H//AeAAB8AADwAAPgAAeAAA8AADwH//A//4AAAAAAAAAAAH/AB/8AeDwHAHAwAYGADAwAYGADA4A4DweAP/gA/4AAAAAAAAAAAH//A//4GBgAwMAGBgAwMAGBgAwcAH/AAfwAA8AAAAAA/4AP/gDgOA4A4GADAwAYGADAwAYHAHgeD+B/8wD+GAAAAAAAAAAA//4H//AwYAGDAAwYAGDgAweAHH8Afz4B8HAAAIAAYAPDwD8OA5w4GGDAwwYGHDAwYYHDnAePwBw8AAAAGAAAwAAGAAAwAAGAAA//4H//AwAAGAAAwAAGAAAwAAAAAAAAAH/4A//wAAPAAAYAADAAAYAADAAAYAAPA//wH/8AAAAAAAAgAAHAAA/AAB/AAD+AAD+AAD4AAfAAfwAfwAfwAH4AA4AAEAAA+AAH/AAH/gAD/AAD4AD+AH+AH8AA+AAH+AAD+AAD/AAD4AH/AP/AH+AA8AAAAAAAAAGADA4A4HweAPPgA/wAB8AAfwAPvgDweA8B4GADAAAIGAAA4AAHwAAPgAAfAAA/4AH/AD4AB8AA+AAHgAAwAAAAAAAAAGADAwB4GAfAwPYGDzAx4YGeDA/AYHwDA4AYGADAAAAAAAA///3//+wAA2AAGAAAGAAA+AAD8AAD8AAD4AAH4AAHgAAMAAAAwAA2AAG///3//+AAAAAAAAAAAOAAHwAD4AA8AAD8AADwAAGAAAAAAABgAAMAABgAAMAABgAAMAABgAAMAABgAAAEAAAwAADAAAIAAAAAAAAAAEeABn4Ad3ADMYAZjADMYAZmAB/4AP/AAAAAAAA//4H//ABgwAYDADAYAYDADg4AP+AA/gABwAAAAAAAAA/gAP+ADg4AYDADAYAYDADAYAOOABxwAAAAAEAAH8AB/wAcHADAYAYDADAYAcDA//4H//AAAAAAAAAAAAH8AB/wAdnADMYAZjADMYAZjAB84AHmAAMAAMAABgAB//gf/8HMAAxgAGIAAAAAAH8IB/zAcHMDAZgYDMDAZgcHcD//Af/wAAAAAAAAAAH//A//4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAGf/Az/4AAAAAAAAAAMz//mf/4AAAAAAAAAAH//A//4ABwAAeAAH4ABzwAcPACAYAABAAAAAAAA//4H//AAAAAAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/ABgAAYAADAAAYAADgAAP/AA/4AAAAAAAAf/AD/4AMAADAAAYAADAAAcAAD/4AP/AAAAAAAAAAAAH8AB/wAcHADAYAYDADAYAYDADx4AP+AA/gAAAAAAAAf/8D//gYDADAYAYDADAYAcHAB/wAH8AAEAAAAAAEAAH8AB/wAcHADAYAYDADAYAYDAD//gf/8AAAAAAAAAAAf/AD/4AcAADAAAYAACAAAAEAB5wAfnADMYAZjADGYAYzADn4AOeAAAAAAAADAAAYAAf/wD//ADAYAYDAAAAAAAAD/gAf/AAA4AADAAAYAADAAAwAf/AD/4AAAAAAAAYAAD4AAP4AAP4AAPAAH4AH4AD8AAcAAAAAAQAADwAAf4AAf4AAPAAP4AP4ADwAAfgAA/gAA/AAD4AH+AD+AAeAAAAAAAAACAYAcHADzwAH8AAfAAH8ADx4AcHACAIAcAMD4BgP4MAP/AAPwAP4AP4AD4AAcAAAAAAAAADAYAYHADD4AY7ADOYAfjADwYAcDADAYAAAAADAAA4AH//B/v8cABzAACAAAH//w//+AAAAAAACAACcAAx/n+H//AA4AAHAAAAAAAAAAAAAOAADgAAYAADAAAcAABgAAGAAAwAAGAADwAAcAAAAA"), 32, atob("BQUHDQwPDQQHBwkMBAYGCQwMDAwMDAwMDAwFBAsMCwoTDg0ODgwMDg8GDA0LEg8ODQ4NDA0ODRMNDQ0GCQYJCQYLDAsMCwcMDAUFCwUSDAwMDAcLBwwKEAoKCgcFBw4A"), 21+(scale<<8)+(1<<16));
@ -48,29 +83,84 @@ Graphics.prototype.setFontRoboto20 = function(scale) {
}; };
function assignPalettes() { function assignPalettes() {
if (g.theme.dark) { palbg = new Uint16Array([g.toColor(g.theme.bg)]);
for (let i = 0; i < settings.rings.length; i++) {
let ring = settings.rings[i];
if (ring.type == 'Full' && ring.color == 'Blk/Wht') {
// BLK/WHT is the outside in light mode, so all of it gets filled in.
// Using the dark theme stops it from being a one-color circle.
pals[i].pal1 = new Uint16Array([g.theme.bg, g.toColor(ring.gy), g.toColor(ring.fg), g.toColor("#00f")]);
pals[i].pal2 = new Uint16Array([g.theme.bg, g.toColor(ring.fg), g.toColor(ring.gy), g.toColor("#00f")]);
} else if (g.theme.dark) {
// palette for 0-49% // palette for 0-49%
pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.fg), g.toColor("#00f")]); pals[i].pal1 = new Uint16Array([g.theme.bg, g.toColor(ring.gy), g.toColor(ring.fg), g.toColor("#00f")]);
// palette for 50-100% // palette for 50-100%
pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.toColor(settings.gy), g.toColor("#00f")]); pals[i].pal2 = new Uint16Array([g.theme.bg, g.toColor(ring.fg), g.toColor(ring.gy), g.toColor("#00f")]);
} else { } else {
// palette for 0-49% // palette for 0-49%
pal1 = new Uint16Array([g.theme.bg, g.theme.fg, g.toColor(settings.fg), g.toColor("#00f")]); pals[i].pal1 = new Uint16Array([g.theme.bg, g.theme.fg, g.toColor(ring.fg), g.toColor("#00f")]);
// palette for 50-100% // palette for 50-100%
pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.theme.fg, g.toColor("#00f")]); pals[i].pal2 = new Uint16Array([g.theme.bg, g.toColor(ring.fg), g.theme.fg, g.toColor("#00f")]);
if (ring.type !== 'Full') pals[i].pal1 = pals[i].pal2; // In light mode, we only want the full circle's filled portion to be black
} }
} }
}
function rotate_points(end, max) {
const midH = h/2;
const midW = w/2;
const off = 5;
const points = [midW-off,0, midW+off,0, midW+off,midH, midW-off,midH];
var rotate = (2 * Math.PI) / (max / end);
var rotated_arr = [];
for (let i = 0; i < points.length; i += 2) {
let x = points[i];
let y = points[i + 1];
x -= midW;
y -= midH;
let x_new = x * Math.cos(rotate) - y * Math.sin(rotate);
let y_new = x * Math.sin(rotate) + y * Math.cos(rotate);
x = x_new + midW;
y = y_new + midH;
rotated_arr.push(x);
rotated_arr.push(y);
}
return rotated_arr;
}
function setSmallFont20() { function setSmallFont20() {
g.setFontRoboto20(); g.setFontRoboto20();
} }
function setLargeFont() { function setLargeFont() {
switch (innerMostRing) {
case 3:
g.setFontBloggerSansLight38();
break;
case 2:
g.setFontBloggerSansLight42();
break;
default:
g.setFontBloggerSansLight46(1); g.setFontBloggerSansLight46(1);
break;
}
} }
function setSmallFont() { function setSmallFont() {
g.setFont('Vector', 16); let size = 16;
if (infoMode == "ID_HRM" ) {
g.setFont('Vector', size);
return;
}
switch (innerMostRing) {
case 2:
size = 13;
break;
case 3:
size = 12;
break;
}
g.setFont('Vector', size);
} }
function getSteps() { function getSteps() {
@ -88,14 +178,52 @@ function getSteps() {
function loadSettings() { function loadSettings() {
settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
settings.gy = settings.gy||'#020'; settings.rings = settings.rings || [{}, {}, {}];
settings.rings[0].gy = settings.rings[0].gy||'#020';
settings.rings[0].fg = settings.rings[0].fg||'#0f0';
settings.rings[0].type = settings.rings[0].type||'Full';
settings.rings[0].ring = settings.rings[0].ring||'Steps';
settings.rings[0].step_target = settings.rings[0].step_target||10000;
settings.rings[1].gy = settings.rings[1].gy||'#020';
settings.rings[1].fg = settings.rings[1].fg||'#0f0';
settings.rings[1].type = settings.rings[1].type||'None';
settings.rings[1].ring = settings.rings[1].ring||'Minutes';
settings.rings[1].step_target = settings.rings[1].step_target||10000;
settings.rings[2].gy = settings.rings[2].gy||'#020';
settings.rings[2].fg = settings.rings[2].fg||'#0f0';
settings.rings[2].type = settings.rings[2].type||'None';
settings.rings[2].ring = settings.rings[2].ring||'Hours';
settings.rings[2].step_target = settings.rings[2].step_target||10000;
for (let i = 0; i < settings.rings.length; i++) {
// Needed in case the user swaps themes
if (settings.rings[i].color == 'Blk/Wht') {
settings.rings[i].gy = g.theme.dark ? '#222' : '#888';
settings.rings[i].fg = g.theme.fg;
}
}
getInnerOuterMostRing();
settings.color = settings.color||'Outer';
settings.fg = settings.fg||'#0f0'; settings.fg = settings.fg||'#0f0';
switch (settings.color) {
case 'Outer':
if (outerMostRing == 0) break;
settings.fg = settings.rings[outerMostRing - 1].fg;
break;
case 'Inner':
if (innerMostRing == 0) break;
settings.fg = settings.rings[innerMostRing - 1].fg;
break;
}
settings.idle_check = (settings.idle_check === undefined ? true : settings.idle_check); settings.idle_check = (settings.idle_check === undefined ? true : settings.idle_check);
settings.batt_hours = (settings.batt_hours === undefined ? false : settings.batt_hours); settings.batt_hours = (settings.batt_hours === undefined ? false : settings.batt_hours);
settings.hr_12 = (global_settings["12hour"] === undefined ? false : global_settings["12hour"]); settings.hr_12 = (global_settings["12hour"] === undefined ? false : global_settings["12hour"]);
settings.ring = settings.ring||'Steps';
settings.idxInfo = settings.idxInfo||0; settings.idxInfo = settings.idxInfo||0;
settings.step_target = settings.step_target||10000;
assignPalettes(); assignPalettes();
} }
@ -108,12 +236,12 @@ function loadLocation() {
} }
function extractTime(d){ function extractTime(d){
var h = d.getHours(), m = d.getMinutes(); var hh = d.getHours(), mm = d.getMinutes();
if (settings.hr_12) { if (settings.hr_12) {
h = h % 12; hh = hh % 12;
if (h == 0) h = 12; if (hh == 0) hh = 12;
} }
return(("0"+h).substr(-2) + ":" + ("0"+m).substr(-2)); return(("0"+hh).substr(-2) + ":" + ("0"+mm).substr(-2));
} }
var sunRise = "00:00"; var sunRise = "00:00";
@ -202,7 +330,7 @@ const infoData = {
ID_DAY: { calc: () => {var d = require("locale").dow(new Date()).toLowerCase(); return d[0].toUpperCase() + d.substring(1);} }, ID_DAY: { calc: () => {var d = require("locale").dow(new Date()).toLowerCase(); return d[0].toUpperCase() + d.substring(1);} },
ID_SR: { calc: () => 'SUNRISE ' + sunRise }, ID_SR: { calc: () => 'SUNRISE ' + sunRise },
ID_SS: { calc: () => 'SUNSET ' + sunSet }, ID_SS: { calc: () => 'SUNSET ' + sunSet },
ID_STEP: { calc: () => 'STEPS ' + getSteps() }, ID_STEP: { calc: () => {var steps = getSteps(); prevStepDisplayed = steps; return 'STEPS ' + steps;}},
ID_BATT: { calc: batteryString}, ID_BATT: { calc: batteryString},
ID_HRM: { calc: () => hrmCurrent } ID_HRM: { calc: () => hrmCurrent }
}; };
@ -225,10 +353,36 @@ function prevInfo(idx) {
return idx; return idx;
} }
function getInfoDims() {
var line = infoLineDefault;
var width = infoWidthDefault;
var height = infoHeightDefault;
switch (innerMostRing) {
case 2:
width -= 10;
height -= 2;
line -= 7;
break;
case 3:
width -= 17;
height -= 3;
line -= 10;
break;
}
if (infoMode == "ID_HRM") {
width = 30;
height = infoHeightDefault;
}
return[line, width, height];
}
function clearInfo() { function clearInfo() {
var dims = getInfoDims();
var line = dims[0];
var width = dims[1];
var height = dims[2];
g.setColor(g.theme.bg); g.setColor(g.theme.bg);
//g.setColor(g.theme.fg); g.fillRect((w/2) - width, line - height, (w/2) + width, line + height);
g.fillRect((w/2) - infoWidth, infoLine - infoHeight, (w/2) + infoWidth, infoLine + infoHeight);
} }
function drawInfo() { function drawInfo() {
@ -236,18 +390,19 @@ function drawInfo() {
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
setSmallFont(); setSmallFont();
g.setFontAlign(0,0); g.setFontAlign(0,0);
var dims = getInfoDims();
var line = dims[0];
var height = dims[2];
if (infoMode == "ID_HRM") { if (infoMode == "ID_HRM") {
clearInfo();
g.setColor('#f00'); // red g.setColor('#f00'); // red
drawHeartIcon(); drawHeartIcon(line, height);
} else { } else {
g.drawString((infoData[infoMode].calc().toUpperCase()), w/2, infoLine); g.drawString((infoData[infoMode].calc().toUpperCase()), w/2, line);
} }
} }
function drawHeartIcon() { function drawHeartIcon(line, height) {
g.drawImage(hrmImg, (w/2) - infoHeight - 20, infoLine - infoHeight); g.drawImage(hrmImg, (w/2) - height - 20, line - height);
} }
function drawHrm() { function drawHrm() {
@ -255,17 +410,44 @@ function drawHrm() {
var d = new Date(); var d = new Date();
clearInfo(); clearInfo();
g.setColor(d.getSeconds()&1 ? '#f00' : g.theme.bg); g.setColor(d.getSeconds()&1 ? '#f00' : g.theme.bg);
drawHeartIcon(); var dims = getInfoDims();
var line = dims[0];
var height = dims[2];
drawHeartIcon(line, height);
setSmallFont(); setSmallFont();
g.setFontAlign(-1,0); // left g.setFontAlign(-1,0); // left
g.setColor(hrmConfidence >= 50 ? g.theme.fg : '#f00'); g.setColor(hrmConfidence >= 50 ? g.theme.fg : '#f00');
g.drawString(hrmCurrent, (w/2) + 10, infoLine); g.drawString(hrmCurrent, (w/2) + 10, line);
} }
function draw(drawRingOnly) { function drawHour(date) {
// Run setLargeFont before running this function
var hh = date.getHours();
if (settings.hr_12) {
hh = hh % 12;
if (hh == 0) hh = 12;
}
hh = hh.toString().padStart(2, '0');
if (settings.color == 'Fullest') {
settings.fg = settings.rings[getFullestRing()].fg;
}
g.setColor(settings.fg);
g.setFontAlign(1,0); // right aligned
g.drawString(hh, (w/2) - 1, h/2);
}
function draw(updateSeconds) {
if (!idle) { if (!idle) {
if (drawRingOnly) { if (updateSeconds) {
drawGaugeImage(new Date()); let date = new Date();
drawAllRings(date, 'Seconds');
if (settings.color == 'Fullest') {
let fgNew = settings.rings[getFullestRing()].fg;
if (settings.fg != fgNew) {
setLargeFont();
drawHour(date);
}
}
} }
else { else {
drawClock(); drawClock();
@ -276,16 +458,16 @@ function draw(drawRingOnly) {
queueDraw(); queueDraw();
} }
function drawGaugeImage(date) { function getGaugeImage(date, ringType, step_target) {
var hh = date.getHours(); var hh = date.getHours();
var mm = date.getMinutes(); var mm = date.getMinutes();
var ring_fill; var ring_fill;
var invertRing = false; var invertRing = false;
var ring_max = 100; var ring_max = 100;
switch (settings.ring) { switch (ringType) {
case 'Hours': case 'Hours':
ring_fill = ((hh % 12) * 60) + mm; ring_fill = ((hh % 12) * 60) + mm;
ring_max = 720; ring_max = 12 * 60;
break; break;
case 'Minutes': case 'Minutes':
ring_fill = mm; ring_fill = mm;
@ -300,8 +482,9 @@ function drawGaugeImage(date) {
ring_max = 1440; ring_max = 1440;
break; break;
case 'Steps': case 'Steps':
ring_max = 100;
ring_fill = getSteps(); ring_fill = getSteps();
ring_max = settings.step_target; ring_max = step_target;
break; break;
case 'Battery': case 'Battery':
ring_fill = E.getBattery(); ring_fill = E.getBattery();
@ -321,40 +504,58 @@ function drawGaugeImage(date) {
} }
var start = 0; var start = 0;
var end = Math.round(ring_fill); var end = Math.round(ring_fill);
if ((end - start) > ring_max) end = ring_max; // Capping end var so the ring doesn't need to update if already full.
if (invertRing) { if (invertRing) {
start = ring_max - end; start = ring_max - end;
end = ring_max; end = ring_max;
} }
if (end !== prevRing.end || start !== prevRing.start || ring_max !== prevRing.max) {
drawRing(start, end, ring_max);
prevRing.start = start;
prevRing.end = end;
prevRing.max = ring_max;
log_debug("Redrew ring at " + hh + ":" + mm);
}
log_debug("Start: "+ start + " end: " +end); log_debug("Start: "+ start + " end: " +end);
return [start, end, ring_max];
}
function drawIfChanged(start, end, ring_max, idx, type) {
if (end === prevRing[idx].end && start === prevRing[idx].start && ring_max === prevRing[idx].max) return;
switch (type) {
case 'Full':
drawRing(start, end, ring_max, idx);
break;
case 'Semi':
drawSemi(start, end, ring_max, idx);
break;
case 'C':
drawC(end, ring_max, idx);
break;
}
prevRing[idx].start = start;
prevRing[idx].end = end;
prevRing[idx].max = ring_max;
log_debug("Redrew ring #" + idx);
}
function drawAllRings(date, drawOnlyThisType) {
for (let i = 0; i < settings.rings.length; i++) {
let ring = settings.rings[i];
if (ring.type == "None") continue;
if (drawOnlyThisType != null && ring.ring != drawOnlyThisType) continue;
var result = getGaugeImage(date, ring.ring, ring.step_target);
drawIfChanged(result[0], result[1], result[2], i, ring.type);
}
} }
function drawClock() { function drawClock() {
var date = new Date(); var date = new Date();
var hh = date.getHours();
var mm = date.getMinutes(); var mm = date.getMinutes();
if (settings.hr_12) {
hh = hh % 12;
if (hh == 0) hh = 12;
}
hh = hh.toString().padStart(2, '0');
mm = mm.toString().padStart(2, '0'); mm = mm.toString().padStart(2, '0');
g.reset(); g.reset();
g.setColor(g.theme.bg); g.setColor(g.theme.bg);
g.fillEllipse(ringEdge+ringThick,ringEdge+ringThick,w-ringEdge-ringThick,h-ringEdge-ringThick); // Clears the text within the circle getInnerOuterMostRing();
drawGaugeImage(date); let edge = ringEdge + (innerMostRing * ringIterOffset);
g.fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick); // Clears the text within the circle
drawAllRings(date, null);
setLargeFont(); setLargeFont();
g.setColor(settings.fg); drawHour(date);
g.setFontAlign(1,0); // right aligned
g.drawString(hh, (w/2) - 1, h/2);
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.setFontAlign(-1,0); // left aligned g.setFontAlign(-1,0); // left aligned
@ -370,15 +571,31 @@ function drawClock() {
drawCount++; drawCount++;
} }
function checkRedrawSteps(steps) {
var redrawText = false;
var redrawRings = false;
if (infoMode == "ID_STEP" && (minStepToUpdate <= (steps - prevStepDisplayed))) {
redrawText = true;
}
for (let i = 0; i < settings.rings.length; i++) {
let ring = settings.rings[i];
if(ring.type == "None" || ring.ring != 'Steps') continue;
let percentChanged = 100 * ((steps - prevRing[i].end) / ring.step_target);
if(percentChanged >= minStepPctUpdateRings) {
redrawRings = true;
break;
}
}
return [redrawText, redrawRings];
}
function drawSteps() { function drawSteps() {
if (drawingSteps) return;
drawingSteps = true;
clearInfo(); clearInfo();
var dims = getInfoDims();
setSmallFont(); setSmallFont();
g.setFontAlign(0,0); g.setFontAlign(0,0);
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.drawString('STEPS ' + getSteps(), w/2, (3*h/4) - 4); g.drawString((infoData[infoMode].calc().toUpperCase()), w/2, dims[0]);
drawingSteps = false;
} }
///////////////// GAUGE images ///////////////////////////////////// ///////////////// GAUGE images /////////////////////////////////////
@ -392,7 +609,8 @@ function resetHrm() {
if (infoMode == "ID_HRM") { if (infoMode == "ID_HRM") {
clearInfo(); clearInfo();
g.setColor('#f00'); // red g.setColor('#f00'); // red
drawHeartIcon(); var dims = getInfoDims();
drawHeartIcon(dims[0], dims[2]);
} }
} }
@ -439,25 +657,80 @@ function polyArray(start, end, max) {
return array; return array;
} }
function drawRing(start, end, max) { function drawRing(start, end, max, idx) {
// Create persistent `buf` inside the function scope // Create persistent `buf` inside the function scope
if (!drawRing._buf) { if (!drawRing._buf) {
drawRing._buf = Graphics.createArrayBuffer(w, h, 2, { msb: true }); drawRing._buf = Graphics.createArrayBuffer(w, h, 2, { msb: true });
} }
const buf = drawRing._buf; const buf = drawRing._buf;
let img = { width: w, height: h, transparent: 0, let img = { width: w, height: h, transparent: 0,
bpp: 2, palette: pal1, buffer: buf.buffer }; bpp: 2, palette: pals[idx].pal1, buffer: buf.buffer };
let edge = ringEdge + (idx * ringIterOffset);
buf.clear(); buf.clear();
buf.setColor(1).fillEllipse(ringEdge,ringEdge,w-ringEdge,h-ringEdge); buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(ringEdge+ringThick,ringEdge+ringThick,w-ringEdge-ringThick,h-ringEdge-ringThick); buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
img.palette = pal2; img.palette = pals[idx].pal2;
g.drawImage(img, 0, 0); // Draws a filled-in circle g.drawImage(img, 0, 0); // Draws a filled-in circle
if((end - start) >= max) return; // No need to add the unfilled circle if((end - start) >= max) return; // No need to add the unfilled circle
buf.clear(); buf.clear();
buf.setColor(1).fillEllipse(ringEdge,ringEdge,w-ringEdge,h-ringEdge); buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(ringEdge+ringThick,ringEdge+ringThick,w-ringEdge-ringThick,h-ringEdge-ringThick); buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
buf.setColor(0).fillPoly(polyArray(start, end, max)); // Masks the filled-in part of the segment over the unfilled part buf.setColor(0).fillPoly(polyArray(start, end, max)); // Masks the filled-in part of the segment over the unfilled part
img.palette = pal1; img.palette = pals[idx].pal1;
g.drawImage(img, 0, 0); // Draws the unfilled-in segment
return;
}
function drawSemi(start, end, max, idx) {
// Create persistent `buf` inside the function scope
var fullCircle = (end - start) >= max;
if (!drawSemi._buf) {
drawSemi._buf = Graphics.createArrayBuffer(w, h, 2, { msb: true });
}
const buf = drawSemi._buf;
let img = { width: w, height: h, transparent: 0,
bpp: 2, palette: pals[idx].pal2, buffer: buf.buffer };
let edge = ringEdge + (idx * ringIterOffset);
buf.clear();
buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
if (fullCircle)
img.palette = pals[idx].pal2;
else
img.palette = palbg;
g.drawImage(img, 0, 0); // Draws a filled-in circle with the bg color, clearing it
if(end == start) return; //If the ring should be completely empty
if(fullCircle) return; // No need to add the unfilled circle
buf.clear();
buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
buf.setColor(0).fillPoly(polyArray(end, start, max)); // Masks the filled-in part of the segment over the unfilled part
img.palette = pals[idx].pal2;
g.drawImage(img, 0, 0); // Draws the unfilled-in segment
return;
}
function drawC(end, max, idx) {
// Create persistent `buf` inside the function scope
if (!drawC._buf) {
drawC._buf = Graphics.createArrayBuffer(w, h, 2, { msb: true });
}
const buf = drawC._buf;
let img = { width: w, height: h, transparent: 0,
bpp: 2, palette: pals[idx].pal2, buffer: buf.buffer };
let edge = ringEdge + (idx * ringIterOffset);
buf.clear();
buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
img.palette = palbg;
g.drawImage(img, 0, 0); // Draws a filled-in circle with the bg color, clearing it
buf.clear();
buf.setColor(1).fillEllipse(edge,edge,w-edge,h-edge);
buf.setColor(0).fillEllipse(edge+ringThick,edge+ringThick,w-edge-ringThick,h-edge-ringThick);
if (end > max) end = max;
var vertices = rotate_points(end, max);
buf.setColor(0).fillPoly(vertices);
img.palette = pals[idx].pal2;
g.drawImage(img, 0, 0); // Draws the unfilled-in segment g.drawImage(img, 0, 0); // Draws the unfilled-in segment
return; return;
} }
@ -514,12 +787,26 @@ BUTTON.prototype.draw = function() {
g.drawRect(this.x, this.y, (this.x + this.w), (this.y + this.h)); g.drawRect(this.x, this.y, (this.x + this.w), (this.y + this.h));
}; };
function redrawWholeFace() {
// Reset the prevRings to force all rings to update
prevRing = Array(3).fill().map(() => ({ start: null, end: null, max: null }));
g.clear();
draw(false);
}
function dismissPrompt() { function dismissPrompt() {
idle = false; idle = false;
warned = false; warned = false;
lastStep = getTime(); lastStep = getTime();
Bangle.buzz(100); Bangle.buzz(100);
draw(false); redrawWholeFace();
}
function resetIdle() {
if (idle == false) return;
// redraw if we had been idle
dismissPrompt();
idle = false;
} }
var dismissBtn = new BUTTON("big",0, 3*h/4 ,w, h/4, "#0ff", dismissPrompt, "Dismiss"); var dismissBtn = new BUTTON("big",0, 3*h/4 ,w, h/4, "#0ff", dismissPrompt, "Dismiss");
@ -540,20 +827,22 @@ Bangle.on('touch', function(button, xy) {
// if we get a step then we are not idle // if we get a step then we are not idle
Bangle.on('step', s => { Bangle.on('step', s => {
lastStep = getTime(); lastStep = getTime();
// redraw if we had been idle resetIdle();
if (idle == true) {
dismissPrompt();
}
idle = false;
warned = 0; warned = 0;
if (drawingSteps) return;
if (infoMode == "ID_STEP") drawSteps(); var steps = getSteps();
var ret = checkRedrawSteps(steps);
if (!ret[0] && !ret[1]) return;
drawingSteps = true;
if (ret[0]) drawSteps();
if (ret[1]) drawAllRings(new Date(), 'Steps');
drawingSteps = false;
}); });
function checkIdle() { function checkIdle() {
log_debug("checkIdle()"); log_debug("checkIdle()");
if (!settings.idle_check) { if (!settings.idle_check) {
idle = false; resetIdle();
warned = false; warned = false;
return; return;
} }
@ -572,7 +861,7 @@ function checkIdle() {
} }
idle = true; idle = true;
} else { } else {
idle = false; resetIdle();
warned = 0; warned = 0;
} }
} }
@ -600,7 +889,7 @@ function getDelayMs(prevDelayMs, ring_setting, now) {
const sec_batt = [20, 50]; const sec_batt = [20, 50];
const sec_delay = [10000, 2000, 1000]; const sec_delay = [10000, 2000, 1000];
const deadband = 5; const deadband = 5;
if (ring_setting == 'Seconds') { if (ring_setting.some(ring => ring.ring === 'Seconds')) {
const nearNextMinute = (now % 60000) >= (60000 - prevDelayMs); const nearNextMinute = (now % 60000) >= (60000 - prevDelayMs);
if (nearNextMinute) { if (nearNextMinute) {
let batt = E.getBattery(); let batt = E.getBattery();
@ -631,7 +920,7 @@ var drawTimeout;
// schedule a draw for the next minute or every sec_update ms // schedule a draw for the next minute or every sec_update ms
function queueDraw() { function queueDraw() {
let now = Date.now(); let now = Date.now();
var nextUpdateRet = getDelayMs(nextUpdateMs, settings.ring, now); var nextUpdateRet = getDelayMs(nextUpdateMs, settings.rings, now);
nextUpdateMs = nextUpdateRet[0]; nextUpdateMs = nextUpdateRet[0];
let delay = nextUpdateMs - (now % nextUpdateMs); let delay = nextUpdateMs - (now % nextUpdateMs);
if (drawTimeout) clearTimeout(drawTimeout); if (drawTimeout) clearTimeout(drawTimeout);
@ -642,6 +931,42 @@ function queueDraw() {
}, delay); }, delay);
} }
function getInnerOuterMostRing() {
// Outputs 1 through 3
let innerMost = 0;
let outerMost = 0;
for (let i = 0; i < settings.rings.length; i++) {
let j = settings.rings.length - 1 - i;
if (outerMost === 0 && settings.rings[i].type !== "None") {
outerMost = i + 1;
}
if (innerMost === 0 && settings.rings[j].type !== "None") {
innerMost = j + 1;
}
if (outerMost !== 0 && innerMost !== 0) {
break;
}
}
innerMostRing = innerMost;
outerMostRing = outerMost;
}
function getFullestRing() {
// Outputs 0 through 2
let largestPercent = 0;
let fullestRing = 0;
for (let i = 0; i < settings.rings.length; i++) {
if (settings.rings[i].type !== "None") {
let percent = (prevRing[i].end - prevRing[i].start) / prevRing[i].max;
if (largestPercent < percent) {
largestPercent = percent;
fullestRing = i;
}
}
}
return fullestRing;
}
// Stop updates when LCD is off, restart when on // Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{ Bangle.on('lcdPower',on=>{
if (on) { if (on) {
@ -653,6 +978,7 @@ Bangle.on('lcdPower',on=>{
}); });
Bangle.setUI("clockupdown", btn=> { Bangle.setUI("clockupdown", btn=> {
clearInfo(); // Used to clear infobox in case we're going to the HRM
if (btn<0) settings.idxInfo = prevInfo(settings.idxInfo); if (btn<0) settings.idxInfo = prevInfo(settings.idxInfo);
if (btn>0) settings.idxInfo = nextInfo(settings.idxInfo); if (btn>0) settings.idxInfo = nextInfo(settings.idxInfo);
// power HRM on/off accordingly // power HRM on/off accordingly
@ -668,12 +994,11 @@ loadSettings();
loadLocation(); loadLocation();
var infoMode = infoList[settings.idxInfo]; var infoMode = infoList[settings.idxInfo];
updateSunRiseSunSet(new Date(), location.lat, location.lon, true); updateSunRiseSunSet(new Date(), location.lat, location.lon, true);
nextUpdateMs = getDelayMs(1000, settings.ring, Date.now())[0]; nextUpdateMs = getDelayMs(1000, settings.rings, Date.now())[0];
g.clear();
Bangle.loadWidgets(); Bangle.loadWidgets();
/* /*
* we are not drawing the widgets as we are taking over the whole screen * we are not drawing the widgets as we are taking over the whole screen
*/ */
widget_utils.hide(); widget_utils.hide();
draw(false); redrawWholeFace();

View File

@ -1,6 +1,6 @@
{ "id": "daisy", { "id": "daisy",
"name": "Daisy", "name": "Daisy",
"version": "0.16", "version": "0.17",
"dependencies": {"mylocation":"app"}, "dependencies": {"mylocation":"app"},
"description": "A beautiful digital clock with large ring gauge, idle timer and a cyclic information line that includes, day, date, steps, battery, sunrise and sunset times", "description": "A beautiful digital clock with large ring gauge, idle timer and a cyclic information line that includes, day, date, steps, battery, sunrise and sunset times",
"icon": "app.png", "icon": "app.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -1,16 +1,43 @@
(function(back) { (function(back) {
const SETTINGS_FILE = "daisy.json"; const SETTINGS_FILE = "daisy.json";
// initialize with default settings... function getDefaultSettings() {
let s = {'gy' : '#020', return {
'fg' : '#0f0', rings: [
'color': 'Green', {
'check_idle' : true, color: 'Green',
'batt_hours' : false, fg: '#0f0',
'ring' : 'Steps', gy: '#020',
'idxInfo' : 0, ring: 'Steps',
'step_target' : 10000}; type: 'Full',
step_target: 10000,
},
{
color: 'Blk/Wht',
fg: null,
gy: null,
ring: 'Minutes',
type: 'None',
step_target: 10000,
},
{
color: 'Green',
fg: '#0f0',
gy: '#020',
ring: 'Hours',
type: 'None',
step_target: 10000,
}
],
color: 'Outer',
fg: '#0f0',
check_idle: true,
batt_hours: false,
idxInfo: 0,
};
}
let s = getDefaultSettings();
// ...and overwrite them with any saved values // ...and overwrite them with any saved values
// This way saved values are preserved if a new version adds more settings // This way saved values are preserved if a new version adds more settings
const storage = require('Storage'); const storage = require('Storage');
@ -25,68 +52,106 @@ function save() {
storage.write(SETTINGS_FILE, settings); storage.write(SETTINGS_FILE, settings);
} }
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; var color_options = ['Cyan','Green','Orange','Purple','Red','Blue', 'Blk/Wht'];
var fg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; var fg_code = ['#0ff','#0f0','#ff0','#f0f','#f00','#00f', null];
var gy_code = ['#020','#220','#022','#202','#200','#002']; var gy_code = ['#022','#020','#220','#202','#200','#002', null];
var ring_options = ['Hours', 'Minutes', 'Seconds', 'Day', 'Sun', 'Steps', 'Battery']; var ring_options = ['Hours', 'Minutes', 'Seconds', 'Day', 'Sun', 'Steps', 'Battery'];
var ring_types = ['None', 'Full', 'Semi', 'C'];
var step_options = [100, 1000, 5000, 10000, 15000, 20000]; var step_options = [100, 1000, 5000, 10000, 15000, 20000];
var color_options_font = ['Outer', 'Inner', 'Fullest'].concat(color_options);
var fg_code_font = [null, null].concat(color_options);
function showMainMenu() { function showRingMenu(ringIndex) {
let appMenu = { const ring = s.rings[ringIndex];
'': { 'title': 'Daisy Clock' }, let ringMenu = {
'< Back': back, '': { title: `Ring ${ringIndex + 1}` },
'Color': { '< Back': showMainMenu,
value: 0 | color_options.indexOf(s.color), 'Type': {
value: ring_types.indexOf(ring.type),
min: 0, max: ring_types.length - 1,
format: v => ring_types[v],
onchange: v => {
let prev = ring.type;
ring.type = ring_types[v];
save();
if (prev != ring.type && (prev === 'None' || ring.type === 'None')) {
setTimeout(showRingMenu, 0, ringIndex);
}
}
},
};
if (ring.type != 'None') {
ringMenu['Color'] = {
value: 0 | color_options.indexOf(ring.color),
min: 0, max: color_options.length - 1, min: 0, max: color_options.length - 1,
format: v => color_options[v], format: v => color_options[v],
onchange: v => { onchange: v => {
s.color = color_options[v]; ring.color = color_options[v];
s.fg = fg_code[v]; ring.fg = fg_code[v];
s.gy = gy_code[v]; ring.gy = gy_code[v];
save(); save();
} }
}, };
'Ring Display': { ringMenu['Display'] = {
value: 0 | ring_options.indexOf(s.ring), value: 0 | ring_options.indexOf(ring.ring),
min: 0, max: ring_options.length - 1, min: 0, max: ring_options.length - 1,
format: v => ring_options[v], format: v => ring_options[v],
onchange: v => { onchange: v => {
let prev = s.ring; let prev = ring.ring;
s.ring = ring_options[v]; ring.ring = ring_options[v];
save(); save();
if (prev != s.ring && (prev === 'Steps' || s.ring === 'Steps')) { if (prev != ring.ring && (prev === 'Steps' || ring.ring === 'Steps')) {
// redisplay the menu with/without ring setting setTimeout(showRingMenu, 0, ringIndex);
// Reference https://github.com/orgs/espruino/discussions/7697
setTimeout(showMainMenu, 0);
} }
}, },
}
}; };
if (s.ring == 'Steps') { if (ring.ring == 'Steps') {
appMenu[/*LANG*/"Step Target"] = { ringMenu[/*LANG*/"Step Target"] = {
value: 0 | step_options.indexOf(s.step_target), value: 0 | step_options.indexOf(ring.step_target),
min: 0, max: step_options.length - 1, min: 0, max: step_options.length - 1,
format: v => step_options[v], format: v => step_options[v],
onchange: v => { onchange: v => {
s.step_target = step_options[v]; ring.step_target = step_options[v];
save(); save();
}, },
}; };
} }
appMenu['Idle Warning'] = { }
value: !!s.idle_check, E.showMenu(ringMenu);
}
function showMainMenu() {
let appMenu = {
'': { title: 'Daisy Clock' },
'< Back': back,
'Ring 1': () => showRingMenu(0),
'Ring 2': () => showRingMenu(1),
'Ring 3': () => showRingMenu(2),
'Hour Color': {
value: 0 | color_options_font.indexOf(s.color),
min: 0, max: color_options_font.length - 1,
format: v => color_options_font[v],
onchange: v => { onchange: v => {
s.idle_check = v; s.color = color_options_font[v];
s.fg = fg_code_font[v];
save(); save();
}, },
}; },
appMenu['Battery Life Format'] = { 'Battery Life Format' : {
value: !!s.batt_hours, value: !!s.batt_hours,
format: value => value?"Days":"%", format: value => value?"Days":"%",
onchange: v => { onchange: v => {
s.batt_hours = v; s.batt_hours = v;
save(); save();
}, },
},
'Idle Warning' : {
value: !!s.idle_check,
onchange: v => {
s.idle_check = v;
save();
},
},
}; };
E.showMenu(appMenu); E.showMenu(appMenu);
} }