mirror of https://github.com/espruino/BangleApps
Merge branch 'master' of github.com:espruino/BangleApps
commit
970a50b6c4
|
@ -0,0 +1 @@
|
|||
0.01: Initial upload
|
|
@ -0,0 +1,21 @@
|
|||
# Clock & Calendar by Michael
|
||||
|
||||
This is my "Hello World". I first made this watchface almost 10 years ago for my original Pebble and Pebble Time and I missed this so much, that I had to write it for the BangleJS2.
|
||||
I know that it seems redundant because there already **is** a *time&cal*-app, but it didn't fit my style.
|
||||
|
||||
- locked screen with only one minimal update/minute
|
||||
- 
|
||||
- unlocked screen (twist?) with seconds
|
||||
- 
|
||||
|
||||
## Configurable Features
|
||||
- Number of calendar rows (weeks)
|
||||
- Buzz on connect/disconnect (I know, this should be an extra widget, but for now, it is included)
|
||||
- Clock Mode (24h/12h). Doesn't have an am/pm indicator. It's only there because it was easy.
|
||||
- First day of the week
|
||||
- Red Saturday
|
||||
- Red Sunday
|
||||
|
||||
## Feedback
|
||||
The clock works for me in a 24h/MondayFirst/WeekendFree environment but is not well-tested with other settings.
|
||||
So if something isn't working, please tell me: https://github.com/foostuff/BangleApps/issues
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkECqMCkQACiEDkIXQuUnkUBkESiYXPgN/u8jgEx/8vC6E3k9xiH//8/C6BHCPQMSL6EDO4cgaf4A/ACEC+YFDl4FEAAM/+ISHbIIECh4FB+QWEA4PwCQsfC4gVBkYGDgP/mQ4CCQk/iAXEAQTiCgMiDQQSFiATDBgQXCgILBEQkQBwYrEC4sPLQRpCBwoXECgUCC4oSBAggXHNQRfDV4X/JgQXJBIIXFgYuDC5QKBiE/C4f/bwgXJmanGJgoSDiTQBmQMBE4JYBfwJ5BBYMiYQISEB4IAB+KdCAgfwAwTrCn4SDiczAAMwGwMTmR0CmECBgRSBCQwA/AGsBgEQAgYABAwcHu93s4GBqAXEmLrCiYICmICBj4XEgvABIMMqECiIXCgQXCegLYBC4NwF4VcAQNV4EPkEhF4REBgYXCiQvCu4UCAQMFJYRfKgxGBuxfGLgkjFgMCkMBmEjgEigZaBI4XFMYcRC4kBmRhBkMQgI5DF4MFgAXCLARfCFoIvDkZmBhnF4sA5gvDYghfEHIQJDAAhQBIAPwVQMTgQvCNIMhAwJfBR4MMU4JRB+RJBiUQgUDVwMgYwMBgcwX4amBqBQBiTqBgUQh8RmJhCL4IvC4HMR4ZaEAgIBBL4LBDL5EBmI5BkQvBXwIGBmMPMwMvkEFR4VcR4UgU4MSC4UQmIJBn7dBiQNBqoXBPYNQh8Q+MB+MvgEvG4JyBj8A+RkBhlQd4ZHBiBYCL4bBELxEAA=="))
|
|
@ -0,0 +1,119 @@
|
|||
Bangle.loadWidgets();
|
||||
|
||||
var s = Object.assign({
|
||||
CAL_ROWS: 4, //number of calendar rows.(weeks) Shouldn't exceed 5 when using widgets.
|
||||
BUZZ_ON_BT: true, //2x slow buzz on disconnect, 2x fast buzz on connect. Will be extra widget eventually
|
||||
MODE24: true, //24h mode vs 12h mode
|
||||
FIRSTDAYOFFSET: 6, //First day of the week: 0-6: Sun, Sat, Fri, Thu, Wed, Tue, Mon
|
||||
REDSUN: true, // Use red color for sunday?
|
||||
REDSAT: true, // Use red color for saturday?
|
||||
}, require('Storage').readJSON("clockcal.json", true) || {});
|
||||
|
||||
const h = g.getHeight();
|
||||
const w = g.getWidth();
|
||||
const CELL_W = w / 7;
|
||||
const CELL_H = 15;
|
||||
const CAL_Y = h - s.CAL_ROWS * CELL_H;
|
||||
const DEBUG = false;
|
||||
|
||||
function drawMinutes() {
|
||||
if (DEBUG) console.log("|-->minutes");
|
||||
var d = new Date();
|
||||
var hours = s.MODE24 ? d.getHours().toString().padStart(2, ' ') : ((d.getHours() + 24) % 12 || 12).toString().padStart(2, ' ');
|
||||
var minutes = d.getMinutes().toString().padStart(2, '0');
|
||||
var textColor = NRF.getSecurityStatus().connected ? '#fff' : '#f00';
|
||||
var size = 50;
|
||||
var clock_x = (w - 20) / 2;
|
||||
if (dimSeconds) {
|
||||
size = 65;
|
||||
clock_x = 4 + (w / 2);
|
||||
}
|
||||
g.setBgColor(0);
|
||||
g.setColor(textColor);
|
||||
g.setFont("Vector", size);
|
||||
g.setFontAlign(0, 1);
|
||||
g.drawString(hours + ":" + minutes, clock_x, CAL_Y - 10, 1);
|
||||
var nextminute = (61 - d.getSeconds());
|
||||
if (typeof minuteInterval !== "undefined") clearTimeout(minuteInterval);
|
||||
minuteInterval = setTimeout(drawMinutes, nextminute * 1000);
|
||||
}
|
||||
|
||||
function drawSeconds() {
|
||||
if (DEBUG) console.log("|--->seconds");
|
||||
var d = new Date();
|
||||
g.setColor();
|
||||
g.fillRect(w - 31, CAL_Y - 36, w - 3, CAL_Y - 19);
|
||||
g.setBgColor(0);
|
||||
g.setColor('#fff');
|
||||
g.setFont("Vector", 24);
|
||||
g.setFontAlign(1, 1);
|
||||
g.drawString(" " + d.getSeconds().toString().padStart(2, '0'), w, CAL_Y - 13);
|
||||
if (typeof secondInterval !== "undefined") clearTimeout(secondInterval);
|
||||
if (!dimSeconds) secondInterval = setTimeout(drawSeconds, 1000);
|
||||
}
|
||||
|
||||
function drawCalendar() {
|
||||
if (DEBUG) console.log("CALENDAR");
|
||||
var d = new Date();
|
||||
g.reset();
|
||||
g.setBgColor(0);
|
||||
g.clear();
|
||||
drawMinutes();
|
||||
if (!dimSeconds) drawSeconds();
|
||||
const dow = (s.FIRSTDAYOFFSET + d.getDay()) % 7; //MO=0, SU=6
|
||||
const today = d.getDate();
|
||||
var rD = new Date(d.getTime());
|
||||
rD.setDate(rD.getDate() - dow);
|
||||
var rDate = rD.getDate();
|
||||
g.setFontAlign(1, 1);
|
||||
for (var y = 1; y <= s.CAL_ROWS; y++) {
|
||||
for (var x = 1; x <= 7; x++) {
|
||||
bottomrightX = x * CELL_W - 2;
|
||||
bottomrightY = y * CELL_H + CAL_Y;
|
||||
g.setFont("Vector", 16);
|
||||
var fg = ((s.REDSUN && rD.getDay() == 0) || (s.REDSAT && rD.getDay() == 6)) ? '#f00' : '#fff';
|
||||
if (y == 1 && today == rDate) {
|
||||
g.setColor('#0f0');
|
||||
g.fillRect(bottomrightX - CELL_W + 1, bottomrightY - CELL_H - 1, bottomrightX, bottomrightY - 2);
|
||||
g.setColor('#000');
|
||||
g.drawString(rDate, bottomrightX, bottomrightY);
|
||||
}
|
||||
else {
|
||||
g.setColor(fg);
|
||||
g.drawString(rDate, bottomrightX, bottomrightY);
|
||||
}
|
||||
rD.setDate(rDate + 1);
|
||||
rDate = rD.getDate();
|
||||
}
|
||||
}
|
||||
Bangle.drawWidgets();
|
||||
|
||||
var nextday = (3600 * 24) - (d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds() + 1);
|
||||
if (DEBUG) console.log("Next Day:" + (nextday / 3600));
|
||||
if (typeof dayInterval !== "undefined") clearTimeout(dayInterval);
|
||||
dayInterval = setTimeout(drawCalendar, nextday * 1000);
|
||||
}
|
||||
|
||||
function BTevent() {
|
||||
drawMinutes();
|
||||
if (s.BUZZ_ON_BT) {
|
||||
var interval = (NRF.getSecurityStatus().connected) ? 100 : 500;
|
||||
Bangle.buzz(interval);
|
||||
setTimeout(function () { Bangle.buzz(interval); }, interval * 3);
|
||||
}
|
||||
}
|
||||
|
||||
//register events
|
||||
Bangle.on('lock', locked => {
|
||||
if (typeof secondInterval !== "undefined") clearTimeout(secondInterval);
|
||||
dimSeconds = locked; //dim seconds if lock=on
|
||||
drawCalendar();
|
||||
});
|
||||
NRF.on('connect', BTevent);
|
||||
NRF.on('disconnect', BTevent);
|
||||
|
||||
|
||||
dimSeconds = Bangle.isLocked();
|
||||
drawCalendar();
|
||||
|
||||
Bangle.setUI("clock");
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"id": "clockcal",
|
||||
"name": "Clock & Calendar",
|
||||
"version": "0.01",
|
||||
"description": "Clock with Calendar",
|
||||
"readme":"README.md",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"clockcal.app.js","url":"app.js"},
|
||||
{"name":"clockcal.settings.js","url":"settings.js"},
|
||||
{"name":"clockcal.img","url":"app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"clockcal.json"}]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
|
@ -0,0 +1,92 @@
|
|||
(function (back) {
|
||||
var FILE = "clockcal.json";
|
||||
|
||||
settings = Object.assign({
|
||||
CAL_ROWS: 4, //number of calendar rows.(weeks) Shouldn't exceed 5 when using widgets.
|
||||
BUZZ_ON_BT: true, //2x slow buzz on disconnect, 2x fast buzz on connect. Will be extra widget eventually
|
||||
MODE24: true, //24h mode vs 12h mode
|
||||
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
||||
REDSUN: true, // Use red color for sunday?
|
||||
REDSAT: true, // Use red color for saturday?
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
|
||||
menu = {
|
||||
"": { "title": "Clock & Calendar" },
|
||||
"< Back": () => back(),
|
||||
'Buzz(dis)conn.?': {
|
||||
value: settings.BUZZ_ON_BT,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.BUZZ_ON_BT = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'#Calendar Rows': {
|
||||
value: settings.CAL_ROWS,
|
||||
min: 0, max: 6,
|
||||
onchange: v => {
|
||||
settings.CAL_ROWS = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Clock mode': {
|
||||
value: settings.MODE24,
|
||||
format: v => v ? "24h" : "12h",
|
||||
onchange: v => {
|
||||
settings.MODE24 = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'First Day': {
|
||||
value: settings.FIRSTDAY,
|
||||
min: 0, max: 6,
|
||||
format: v => ["Sun", "Sat", "Fri", "Thu", "Wed", "Tue", "Mon"][v],
|
||||
onchange: v => {
|
||||
settings.FIRSTDAY = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Red Saturday?': {
|
||||
value: settings.REDSAT,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.REDSAT = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Red Sunday?': {
|
||||
value: settings.REDSUN,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.REDSUN = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Load deafauls?': {
|
||||
value: 0,
|
||||
min: 0, max: 1,
|
||||
format: v => ["No", "Yes"][v],
|
||||
onchange: v => {
|
||||
if (v == 1) {
|
||||
settings = {
|
||||
CAL_ROWS: 4, //number of calendar rows.(weeks) Shouldn't exceed 5 when using widgets.
|
||||
BUZZ_ON_BT: true, //2x slow buzz on disconnect, 2x fast buzz on connect.
|
||||
MODE24: true, //24h mode vs 12h mode
|
||||
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
||||
REDSUN: true, // Use red color for sunday?
|
||||
REDSAT: true, // Use red color for saturday?
|
||||
};
|
||||
writeSettings();
|
||||
load()
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
// Show the menu
|
||||
E.showMenu(menu);
|
||||
})
|
|
@ -1,3 +1,4 @@
|
|||
0.01: first release
|
||||
0.02: added settings menu to change color
|
||||
0.03: fix metadata.json to allow setting as clock
|
||||
0.04: added heart rate which is switched on when cycled to it through up/down touch on rhs
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Daisy
|
||||
# Daisy 
|
||||
|
||||
*A beautiful digital clock with large ring guage, idle timer and a
|
||||
cyclic information line that includes, day, date, steps, battery,
|
||||
|
@ -8,15 +8,20 @@ Written by: [Hugh Barney](https://github.com/hughbarney) For support
|
|||
and discussion please post in the [Bangle JS
|
||||
Forum](http://forum.espruino.com/microcosms/1424/)
|
||||
|
||||
* Derived from `The Ring` proof of concept and the [Pastel clock](https://banglejs.com/apps/?q=pastel)
|
||||
* Derived from [The Ring](https://banglejs.com/apps/?id=thering) proof of concept and the [Pastel clock](https://banglejs.com/apps/?q=pastel)
|
||||
* Includes the [Lazybones](https://banglejs.com/apps/?q=lazybones) Idle warning timer
|
||||
* Touch the top right/top left to cycle through the info display (Day, Date, Steps, Sunrise, Sunset)
|
||||
* Touch the top right/top left to cycle through the info display (Day, Date, Steps, Sunrise, Sunset, Heart Rate)
|
||||
* The heart rate monitor is turned on only when Heart rate is selected and will take a few seconds to settle
|
||||
* The heart value is displayed in RED if the confidence value is less than 50%
|
||||
* NOTE: The heart rate monitor of Bangle JS 2 is not very accurate when moving about.
|
||||
See [#1248](https://github.com/espruino/BangleApps/issues/1248)
|
||||
* 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
|
||||
[MyLocation](https://banglejs.com/apps/?id=mylocation)
|
||||
* The screen is updated every minute to save battery power
|
||||
* Uses the [BloggerSansLight](https://www.1001fonts.com/rounded-fonts.html?page=3) font, which if free for commercial use
|
||||
|
||||
## Future Development
|
||||
* Add a heart rate option in the information line that turns on when selected
|
||||
* Use mini icons in the information line rather that text
|
||||
* Add weather icons as per Pastel clock
|
||||
* Add a lock icon to the screen
|
||||
|
@ -25,5 +30,3 @@ Forum](http://forum.espruino.com/microcosms/1424/)
|
|||

|
||||
|
||||
It is worth looking at the real thing though as the screenshot does not do it justice.
|
||||
(Though I need to redo this photo at some point)
|
||||

|
||||
|
|
|
@ -14,16 +14,19 @@ let warned = 0;
|
|||
let idle = false;
|
||||
let IDLE_MINUTES = 26;
|
||||
|
||||
var pal1; // palette for 0-40%
|
||||
var pal2; // palette for 50-100%
|
||||
const infoWidth = 50;
|
||||
const infoHeight = 14;
|
||||
let pal1; // palette for 0-40%
|
||||
let pal2; // palette for 50-100%
|
||||
const infoLine = (3*h/4) - 6;
|
||||
const infoWidth = 56;
|
||||
const infoHeight = 11;
|
||||
var drawingSteps = false;
|
||||
|
||||
function log_debug(o) {
|
||||
//print(o);
|
||||
}
|
||||
|
||||
var hrmImg = require("heatshrink").decompress(atob("i0WgIKHgPh8Ef5/g///44CBz///1///5A4PnBQk///wA4PBA4MDA4MH/+Ah/8gEP4EAjw0GA"));
|
||||
|
||||
// https://www.1001fonts.com/rounded-fonts.html?page=3
|
||||
Graphics.prototype.setFontBloggerSansLight46 = function(scale) {
|
||||
// Actual height 46 (45 - 0)
|
||||
|
@ -109,7 +112,8 @@ const infoData = {
|
|||
ID_SR: { calc: () => 'Sunrise: ' + sunRise },
|
||||
ID_SS: { calc: () => 'Sunset: ' + sunSet },
|
||||
ID_STEP: { calc: () => 'Steps: ' + getSteps() },
|
||||
ID_BATT: { calc: () => 'Battery: ' + E.getBattery() + '%' }
|
||||
ID_BATT: { calc: () => 'Battery: ' + E.getBattery() + '%' },
|
||||
ID_HRM: { calc: () => hrmCurrent }
|
||||
};
|
||||
|
||||
const infoList = Object.keys(infoData).sort();
|
||||
|
@ -121,6 +125,9 @@ function nextInfo() {
|
|||
if (idx === infoList.length - 1) infoMode = infoList[0];
|
||||
else infoMode = infoList[idx + 1];
|
||||
}
|
||||
// power HRM on/off accordingly
|
||||
Bangle.setHRMPower(infoMode == "ID_HRM" ? 1 : 0);
|
||||
resetHrm();
|
||||
}
|
||||
|
||||
function prevInfo() {
|
||||
|
@ -129,8 +136,125 @@ function prevInfo() {
|
|||
if (idx === 0) infoMode = infoList[infoList.length - 1];
|
||||
else infoMode = infoList[idx - 1];
|
||||
}
|
||||
// power HRM on/off accordingly
|
||||
Bangle.setHRMPower(infoMode == "ID_HRM" ? 1 : 0);
|
||||
resetHrm();
|
||||
}
|
||||
|
||||
function clearInfo() {
|
||||
g.setColor(g.theme.bg);
|
||||
//g.setColor(g.theme.fg);
|
||||
g.fillRect((w/2) - infoWidth, infoLine - infoHeight, (w/2) + infoWidth, infoLine + infoHeight);
|
||||
}
|
||||
|
||||
function drawInfo() {
|
||||
clearInfo();
|
||||
g.setColor(g.theme.fg);
|
||||
setSmallFont();
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
if (infoMode == "ID_HRM") {
|
||||
clearInfo();
|
||||
g.setColor('#f00'); // red
|
||||
drawHeartIcon();
|
||||
} else {
|
||||
g.drawString((infoData[infoMode].calc()), w/2, infoLine);
|
||||
}
|
||||
}
|
||||
|
||||
function drawHeartIcon() {
|
||||
g.drawImage(hrmImg, (w/2) - infoHeight - 20, infoLine - infoHeight);
|
||||
}
|
||||
|
||||
function drawHrm() {
|
||||
if (idle) return; // dont draw while prompting
|
||||
var d = new Date();
|
||||
clearInfo();
|
||||
g.setColor(d.getSeconds()&1 ? '#f00' : g.theme.bg);
|
||||
drawHeartIcon();
|
||||
setSmallFont();
|
||||
g.setFontAlign(-1,0); // left
|
||||
g.setColor(hrmConfidence >= 50 ? g.theme.fg : '#f00');
|
||||
g.drawString(hrmCurrent, (w/2) + 10, infoLine);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
if (!idle)
|
||||
drawClock();
|
||||
else
|
||||
drawIdle();
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function drawClock() {
|
||||
var date = new Date();
|
||||
var timeStr = require("locale").time(date,1);
|
||||
var da = date.toString().split(" ");
|
||||
var time = da[4].substr(0,5);
|
||||
var hh = da[4].substr(0,2);
|
||||
var mm = da[4].substr(3,2);
|
||||
var steps = getSteps();
|
||||
var p_steps = Math.round(100*(steps/10000));
|
||||
|
||||
g.reset();
|
||||
g.setColor(g.theme.bg);
|
||||
g.fillRect(0, 0, w, h);
|
||||
g.drawImage(getGaugeImage(p_steps), 0, 0);
|
||||
setLargeFont();
|
||||
|
||||
g.setColor(settings.fg);
|
||||
g.setFontAlign(1,0); // right aligned
|
||||
g.drawString(hh, (w/2) - 1, h/2);
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFontAlign(-1,0); // left aligned
|
||||
g.drawString(mm, (w/2) + 1, h/2);
|
||||
|
||||
drawInfo();
|
||||
|
||||
// recalc sunrise / sunset every hour
|
||||
if (drawCount % 60 == 0)
|
||||
updateSunRiseSunSet(new Date(), location.lat, location.lon);
|
||||
drawCount++;
|
||||
}
|
||||
|
||||
function drawSteps() {
|
||||
if (drawingSteps) return;
|
||||
drawingSteps = true;
|
||||
clearInfo();
|
||||
setSmallFont();
|
||||
g.setFontAlign(0,0);
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawString('Steps ' + getSteps(), w/2, (3*h/4) - 4);
|
||||
drawingSteps = false;
|
||||
}
|
||||
|
||||
///////////////// GAUGE images /////////////////////////////////////
|
||||
|
||||
var hrmCurrent = "--";
|
||||
var hrmConfidence = 0;
|
||||
|
||||
function resetHrm() {
|
||||
hrmCurrent = "--";
|
||||
hrmConfidence = 0;
|
||||
if (infoMode == "ID_HRM") {
|
||||
clearInfo();
|
||||
g.setColor('#f00'); // red
|
||||
drawHeartIcon();
|
||||
}
|
||||
}
|
||||
|
||||
Bangle.on('HRM', function(hrm) {
|
||||
hrmCurrent = hrm.bpm;
|
||||
hrmConfidence = hrm.confidence;
|
||||
log_debug("HRM=" + hrm.bpm + " (" + hrm.confidence + ")");
|
||||
if (infoMode == "ID_HRM" ) drawHrm();
|
||||
});
|
||||
|
||||
|
||||
///////////////// GAUGE images /////////////////////////////////////
|
||||
|
||||
|
||||
// putting into 1 function like this, rather than individual variables
|
||||
// reduces ram usage from 70%-13%
|
||||
function getGaugeImage(p) {
|
||||
|
@ -247,68 +371,6 @@ function getGaugeImage(p) {
|
|||
};
|
||||
}
|
||||
|
||||
function draw() {
|
||||
if (!idle)
|
||||
drawClock();
|
||||
else
|
||||
drawIdle();
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
function drawClock() {
|
||||
var date = new Date();
|
||||
var timeStr = require("locale").time(date,1);
|
||||
var da = date.toString().split(" ");
|
||||
var time = da[4].substr(0,5);
|
||||
var hh = da[4].substr(0,2);
|
||||
var mm = da[4].substr(3,2);
|
||||
var steps = getSteps();
|
||||
var p_steps = Math.round(100*(steps/10000));
|
||||
|
||||
g.reset();
|
||||
g.setColor(g.theme.bg);
|
||||
g.fillRect(0, 0, w, h);
|
||||
g.drawImage(getGaugeImage(p_steps), 0, 0);
|
||||
setLargeFont();
|
||||
|
||||
g.setColor(settings.fg);
|
||||
g.setFontAlign(1,0); // right aligned
|
||||
g.drawString(hh, (w/2) - 1, h/2);
|
||||
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFontAlign(-1,0); // left aligned
|
||||
g.drawString(mm, (w/2) + 1, h/2);
|
||||
|
||||
setSmallFont();
|
||||
g.setFontAlign(0,0); // left aligned
|
||||
g.drawString((infoData[infoMode].calc()), w/2, (3*h/4) - 4);
|
||||
|
||||
// recalc sunrise / sunset every hour
|
||||
if (drawCount % 60 == 0)
|
||||
updateSunRiseSunSet(new Date(), location.lat, location.lon);
|
||||
drawCount++;
|
||||
}
|
||||
|
||||
function drawSteps() {
|
||||
if (drawingSteps) return;
|
||||
drawingSteps = true;
|
||||
setSmallFont();
|
||||
g.setFontAlign(0,0);
|
||||
var steps = getSteps();
|
||||
g.setColor(g.theme.bg);
|
||||
g.fillRect((w/2) - infoWidth, (3*h/4) - infoHeight, (w/2) + infoWidth, (3*h/4) + infoHeight);
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawString('Steps ' + steps, w/2, (3*h/4) - 4);
|
||||
drawingSteps = false;
|
||||
}
|
||||
|
||||
/*
|
||||
Bangle.on('step', s => {
|
||||
drawSteps();
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
///////////////// IDLE TIMER /////////////////////////////////////
|
||||
|
||||
function drawIdle() {
|
||||
|
@ -392,6 +454,8 @@ Bangle.on('step', s => {
|
|||
}
|
||||
idle = false;
|
||||
warned = 0;
|
||||
|
||||
if (infoMode == "ID_STEP") drawSteps();
|
||||
});
|
||||
|
||||
function checkIdle() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{ "id": "daisy",
|
||||
"name": "Daisy",
|
||||
"version":"0.03",
|
||||
"version":"0.04",
|
||||
"dependencies": {"mylocation":"app"},
|
||||
"description": "A clock based on the Pastel clock with large ring guage for steps",
|
||||
"icon": "app.png",
|
||||
|
|
|
@ -6,3 +6,5 @@
|
|||
0.06: Adds settings page (hide clocks or launchers)
|
||||
0.07: Adds setting for directly launching app on touch for Bangle 2
|
||||
0.08: Optimize line wrapping for Bangle 2
|
||||
0.09: fix the trasparent widget bar if there are no widgets for Bangle 2
|
||||
0.10: added "one click exit" setting for Bangle 2
|
||||
|
|
|
@ -6,8 +6,12 @@ var settings = Object.assign({
|
|||
showClocks: true,
|
||||
showLaunchers: true,
|
||||
direct: false,
|
||||
oneClickExit:false
|
||||
}, require('Storage').readJSON("dtlaunch.json", true) || {});
|
||||
|
||||
if( settings.oneClickExit)
|
||||
setWatch(_=> load(), BTN1);
|
||||
|
||||
var s = require("Storage");
|
||||
var apps = s.list(/\.info$/).map(app=>{
|
||||
var a=s.readJSON(app,1);
|
||||
|
@ -125,5 +129,6 @@ Bangle.on("touch",(_,p)=>{
|
|||
});
|
||||
|
||||
Bangle.loadWidgets();
|
||||
g.clear();
|
||||
Bangle.drawWidgets();
|
||||
drawPage(0);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "dtlaunch",
|
||||
"name": "Desktop Launcher",
|
||||
"version": "0.08",
|
||||
"version": "0.10",
|
||||
"description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.",
|
||||
"screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}],
|
||||
"icon": "icon.png",
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
var settings = Object.assign({
|
||||
showClocks: true,
|
||||
showLaunchers: true,
|
||||
direct: false
|
||||
direct: false,
|
||||
oneClickExit:false
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
|
@ -37,6 +38,14 @@
|
|||
settings.direct = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'One click exit': {
|
||||
value: settings.oneClickExit,
|
||||
format: v => v?"On":"Off",
|
||||
onchange: v => {
|
||||
settings.oneClickExit = v;
|
||||
writeSettings();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Set Bangle.js 2 compatible
|
||||
|
|
|
@ -2,12 +2,12 @@
|
|||
"id": "gpsautotime",
|
||||
"name": "GPS auto time",
|
||||
"shortName": "GPS auto time",
|
||||
"version": "0.01",
|
||||
"version": "0.02",
|
||||
"description": "A widget that automatically updates the Bangle.js time to the GPS time whenever there is a valid GPS fix.",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
"tags": "widget,gps",
|
||||
"supports": ["BANGLEJS"],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"gpsautotime.wid.js","url":"widget.js"}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: Initial release
|
|
@ -0,0 +1,15 @@
|
|||
# Rachet Launcher
|
||||
|
||||
Ratchet Launcher is a fork of the default Launcher with modified user interaction. Instead of free scrolling, apps are selected by swiping up and down, but in discrete "ticks", just like in the settings menus.
|
||||
|
||||
**WARNING: Untested on Bangle.js v1! Please test and give feedback.**
|
||||
|
||||
## Usage
|
||||
- Choose app: Swipe up/down (top/bottom button on Bangle.js v1)
|
||||
- Launch app: Tap screen (center button on Bangle.js v1)
|
||||
- Return to clock: Swipe three ticks beyond first/last app in list
|
||||
|
||||
## Installation
|
||||
1. Install Ratchet Launcher using App Loader
|
||||
2. Uninstall default Launcher
|
||||
3. Reload
|
|
@ -0,0 +1,149 @@
|
|||
var Storage = require("Storage");
|
||||
var Layout = require("Layout");
|
||||
|
||||
var font = g.getFonts().includes("6x15") ? "6x15" : "6x8:2";
|
||||
var largeFont = g.getFonts().includes("12x20") ? "12x20" : "6x8:3";
|
||||
var currentApp = 0;
|
||||
var overscroll = 0;
|
||||
var blankImage = Graphics.createImage(` `);
|
||||
var rowHeight = g.getHeight()/3;
|
||||
|
||||
// Load apps list
|
||||
var apps = Storage.list(/\.info$/).map(app=>{
|
||||
var a=Storage.readJSON(app,1);
|
||||
return a&&{
|
||||
name:a.name,
|
||||
type:a.type,
|
||||
icon:a.icon ? Storage.read(a.icon) : a.icon,
|
||||
sortorder:a.sortorder,
|
||||
src:a.src
|
||||
};
|
||||
}).filter(app=>app && (
|
||||
app.type=="app"
|
||||
// || (app.type=="clock" && settings.showClocks)
|
||||
|| !app.type
|
||||
));
|
||||
apps.sort((a,b)=>{
|
||||
var n=(0|a.sortorder)-(0|b.sortorder);
|
||||
if (n) return n; // do sortorder first
|
||||
if (a.name<b.name) return -1;
|
||||
if (a.name>b.name) return 1;
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Uncomment for testing in the emulator without apps:
|
||||
// apps = [
|
||||
// {
|
||||
// name:"Test",
|
||||
// type:"app",
|
||||
// icon:blankImage,
|
||||
// sortorder:undefined,
|
||||
// src:""
|
||||
// },
|
||||
// {
|
||||
// name:"Test 2",
|
||||
// type:"app",
|
||||
// icon:blankImage,
|
||||
// sortorder:undefined,
|
||||
// src:""
|
||||
// },
|
||||
// ];
|
||||
|
||||
// Initialize layout
|
||||
var layout = new Layout({
|
||||
type:"v", c:[
|
||||
// A row for the previous app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"prev_icon", src:blankImage, width:48, height:48, scale:0.8, pad:8},
|
||||
{type: "txt", id:"prev_name", label:"", font:font, fillx:1, wrap:1},
|
||||
]},
|
||||
// A row for the current app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"cur_icon", src:blankImage, width:48, height:48},
|
||||
{type: "txt", id:"cur_name", label:"", font:largeFont, fillx:1, wrap:1},
|
||||
]},
|
||||
// A row for the next app
|
||||
{ type:"h", height:rowHeight, c:[
|
||||
{type: "img", id:"next_icon", src:blankImage, width:48, height:48, scale:0.8, pad:8},
|
||||
{type: "txt", id:"next_name", label:"", font:font, fillx:1, wrap:1},
|
||||
]},
|
||||
]
|
||||
});
|
||||
|
||||
// Drawing logic
|
||||
function render() {
|
||||
if (!apps.length) {
|
||||
E.showMessage(/*LANG*/"No apps");
|
||||
return load();
|
||||
}
|
||||
|
||||
// Previous app
|
||||
if (currentApp > 0) {
|
||||
layout.prev_icon.src = apps[currentApp-1].icon;
|
||||
layout.prev_name.label = apps[currentApp-1].name;
|
||||
} else {
|
||||
layout.prev_icon.src = blankImage;
|
||||
layout.prev_name.label = "";
|
||||
}
|
||||
|
||||
// Current app
|
||||
layout.cur_icon.src = apps[currentApp].icon;
|
||||
layout.cur_name.label = apps[currentApp].name;
|
||||
|
||||
// Next app
|
||||
if (currentApp < apps.length-1) {
|
||||
layout.next_icon.src = apps[currentApp+1].icon;
|
||||
layout.next_name.label = apps[currentApp+1].name;
|
||||
} else {
|
||||
layout.next_icon.src = blankImage;
|
||||
layout.next_name.label = "";
|
||||
}
|
||||
|
||||
g.clear();
|
||||
layout.render();
|
||||
}
|
||||
|
||||
// Launch the currently selected app
|
||||
function launch() {
|
||||
var app = apps[currentApp];
|
||||
if (!app) return;
|
||||
if (!app.src || Storage.read(app.src)===undefined) {
|
||||
E.showMessage(/*LANG*/"App Source\nNot found");
|
||||
setTimeout(render, 2000);
|
||||
} else {
|
||||
E.showMessage(/*LANG*/"Loading...");
|
||||
load(app.src);
|
||||
}
|
||||
}
|
||||
|
||||
// Select previous/next app
|
||||
function move(step) {
|
||||
if ((currentApp == 0 && step < 0) || (currentApp >= apps.length-1 && step > 0)) {
|
||||
// When we hit the end of the list (top or bottom), the step is
|
||||
// counted towards the overscroll value. When the overscroll
|
||||
// threshold is exceeded, we return to the clock face.
|
||||
overscroll += step;
|
||||
} else {
|
||||
// This is the default case: the step is countedf towards the currentApp index
|
||||
currentApp += step;
|
||||
overscroll = 0;
|
||||
return render();
|
||||
}
|
||||
|
||||
// Overscroll threshold reached, return to clock
|
||||
if (Math.abs(overscroll) > 3) {
|
||||
Bangle.buzz(500, 1);
|
||||
return load();
|
||||
}
|
||||
}
|
||||
|
||||
// Wire up user input
|
||||
Bangle.setUI('updown', dir => {
|
||||
if (!dir) launch();
|
||||
else {
|
||||
if (process.env.HWVERSION==2) dir *= -1; // "natural scrolling" on touch screen
|
||||
move(dir);
|
||||
}
|
||||
});
|
||||
|
||||
render();
|
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"id": "ratchet_launch",
|
||||
"name": "Ratchet Launcher",
|
||||
"shortName": "Ratchet",
|
||||
"version": "0.01",
|
||||
"description": "Launcher with discrete scrolling for quicker app selection",
|
||||
"icon": "app.png",
|
||||
"type": "launch",
|
||||
"tags": "tool,system,launcher",
|
||||
"supports": ["BANGLEJS2","BANGLEJS"],
|
||||
"storage": [
|
||||
{"name":"ratchet_launch.app.js","url":"app.js"}
|
||||
],
|
||||
"sortorder": -10,
|
||||
"readme":"README.md"
|
||||
}
|
|
@ -1,2 +1,4 @@
|
|||
0.01: Initial version
|
||||
0.02: Add battery level
|
||||
0.03: Fix battery display when full
|
||||
0.04: Add support for settings
|
||||
|
|
|
@ -3,3 +3,21 @@
|
|||
Just a simple watch face for the Banglejs2.
|
||||
|
||||
It shows battery level in the upper left corner, date information in the upper right, and time information in the bottom.
|
||||
|
||||

|
||||
|
||||
## Settings
|
||||
|
||||
**Analog Clock:**
|
||||
|
||||
**Human Readable Date:** When the setting is on, the date is shown in a more human-friendly format (e.g. "Oct 2"), otherwise the date is shown in a standard format (e.g. "02/10"). Default is off.
|
||||
|
||||
**Show Week Info:** When the setting is on, the weekday and week number are shown in the upper right box. When the setting is off, the full year is shown instead. Default is off.
|
||||
|
||||
**Vector Font:** When the setting is on, the app uses Espruino's vector font, otherwise it uses the default font. Default is off.
|
||||
|
||||
## Using the app
|
||||
|
||||
Monogram Watch Face can be selected as the default clock or it can be run manually from the launcher. Its settings can be accessed and changed via the relevant menu.
|
||||
|
||||
Tapping on the "Alerts" area will replace the current time display with the time of the most immediate alert.
|
||||
|
|
|
@ -1,48 +1,81 @@
|
|||
const SETTINGSFILE = "smclock.json";
|
||||
const background = {
|
||||
width : 176, height : 176, bpp : 3,
|
||||
transparent : 1,
|
||||
buffer : require("heatshrink").decompress(atob("/4A/AH4ACUb8H9MkyVJAThB/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INP/AH4A/AAX8Yz4Afn5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INI="))
|
||||
width: 176,
|
||||
height: 176,
|
||||
bpp: 3,
|
||||
transparent: 1,
|
||||
buffer: require("heatshrink").decompress(
|
||||
atob(
|
||||
"/4A/AH4ACUb8H9MkyVJAThB/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INP/AH4A/AAX8Yz4Afn5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/IP5B/INI="
|
||||
)
|
||||
),
|
||||
};
|
||||
const monthName = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||
const weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
|
||||
|
||||
const weekday = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];
|
||||
var level = -1;
|
||||
// dynamic variables
|
||||
var batLevel = -1;
|
||||
var batColor = [0, 0, 0];
|
||||
|
||||
function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
|
||||
// settings variables
|
||||
var dateFormat;
|
||||
var drawInterval;
|
||||
var pollInterval;
|
||||
var showAnalogFace;
|
||||
var showWeekInfo;
|
||||
var useVectorFont;
|
||||
|
||||
// load settings
|
||||
function loadSettings() {
|
||||
// Helper function default setting
|
||||
function def(value, def) {return value !== undefined ? value : def;}
|
||||
var settings = require("Storage").readJSON(SETTINGSFILE, true) || {};
|
||||
|
||||
dateFormat = def(settings.dateFormat, "Short");
|
||||
drawInterval = def(settings.drawInterval, 10);
|
||||
pollInterval = def(settings.pollInterval, 60);
|
||||
showAnalogFace = def(settings.showAnalogFace, false);
|
||||
showWeekInfo = def(settings.showWeekInfo, false);
|
||||
useVectorFont = def(settings.useVectorFont, false);
|
||||
}
|
||||
|
||||
// copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
|
||||
function ISO8601_week_no(date) {
|
||||
var tdt = new Date(date.valueOf());
|
||||
var dayn = (date.getDay() + 6) % 7;
|
||||
tdt.setDate(tdt.getDate() - dayn + 3);
|
||||
var firstThursday = tdt.valueOf();
|
||||
tdt.setMonth(0, 1);
|
||||
if (tdt.getDay() !== 4) {
|
||||
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
|
||||
tdt.setMonth(0, 1 + ((4 - tdt.getDay() + 7) % 7));
|
||||
}
|
||||
return 1 + Math.ceil((firstThursday - tdt) / 604800000);
|
||||
}
|
||||
|
||||
function d02(value) {
|
||||
return ('0' + value).substr(-2);
|
||||
return ("0" + value).substr(-2);
|
||||
}
|
||||
|
||||
function pollBattery() {
|
||||
level = E.getBattery();
|
||||
return level;
|
||||
batLevel = E.getBattery();
|
||||
}
|
||||
|
||||
function getBatteryColor(level) {
|
||||
var color;
|
||||
if (level < 0) {
|
||||
level = pollBattery();
|
||||
pollBattery();
|
||||
level = batLevel;
|
||||
}
|
||||
if(level>80) {
|
||||
color = [0,0,1];
|
||||
} else if(level>60) {
|
||||
color = [0,1,1];
|
||||
} else if(level>40) {
|
||||
color = [0,1,0];
|
||||
} else if(level>20) {
|
||||
color = [1,1,0];
|
||||
if (level > 80) {
|
||||
color = [0, 0, 1];
|
||||
} else if (level > 60) {
|
||||
color = [0, 1, 1];
|
||||
} else if (level > 40) {
|
||||
color = [0, 1, 0];
|
||||
} else if (level > 20) {
|
||||
color = [1, 1, 0];
|
||||
} else {
|
||||
color = [1,0,0];
|
||||
color = [1, 0, 0];
|
||||
}
|
||||
return color;
|
||||
}
|
||||
|
@ -50,57 +83,110 @@ function getBatteryColor(level) {
|
|||
function draw() {
|
||||
g.drawImage(background);
|
||||
|
||||
const color = getBatteryColor();
|
||||
const bat = d02(E.getBattery()) + "%";
|
||||
const color = getBatteryColor(batLevel);
|
||||
var bat = "";
|
||||
const d = new Date();
|
||||
const day = d.getDate();
|
||||
const month = (d.getMonth() + 1);
|
||||
const month = d.getMonth() + 1;
|
||||
const week = d02(ISO8601_week_no(d));
|
||||
const date1 = d02(day) + "/" + d02(month);
|
||||
const date2 = weekday[d.getDay()] + " " + d02(week);
|
||||
var date1 = "";
|
||||
var date2 = "";
|
||||
const h = d.getHours();
|
||||
const m = d.getMinutes();
|
||||
const time = d02(h) + ":" + d02(m);
|
||||
|
||||
if (E.getBattery() < 100) {
|
||||
bat = d02(E.getBattery()) + "%";
|
||||
} else {
|
||||
bat = E.getBattery() + "%";
|
||||
}
|
||||
|
||||
g.reset();
|
||||
|
||||
g.setColor(0, 0, 0);
|
||||
g.setFont("Vector", 20);
|
||||
g.drawString(date1, 105, 20, false);
|
||||
g.setFont("Vector", 16);
|
||||
g.drawString(date2, 105, 55, false);
|
||||
|
||||
g.setColor(1, 1, 1);
|
||||
g.setFont("Vector", 60);
|
||||
g.drawString(time, 10, 108, false);
|
||||
|
||||
// draw battery info
|
||||
g.setColor(1, 1, 1);
|
||||
if (useVectorFont == true) {
|
||||
g.setFont("Vector", 16);
|
||||
g.drawString("Bat:", 12, 22, false);
|
||||
} else {
|
||||
g.setFont("4x6", 2);
|
||||
g.drawString("Bat:", 10, 22, false);
|
||||
}
|
||||
g.setColor(color[0], color[1], color[2]);
|
||||
if (batLevel < 100) {
|
||||
g.drawString(bat, 52, 22, false);
|
||||
} else {
|
||||
g.drawString(bat, 46, 22, false);
|
||||
}
|
||||
|
||||
// draw date info
|
||||
g.setColor(0, 0, 0);
|
||||
if (useVectorFont == true) {
|
||||
g.setFont("Vector", 20);
|
||||
} else {
|
||||
g.setFont("6x8", 2);
|
||||
}
|
||||
if (dateFormat == "Short") {
|
||||
date1 = d02(day) + "/" + d02(month);
|
||||
g.drawString(date1, 105, 20, false);
|
||||
} else {
|
||||
date1 = monthName[month - 1] + d02(day);
|
||||
g.drawString(date1, 104, 20, false);
|
||||
}
|
||||
|
||||
// draw week info
|
||||
if (showWeekInfo == true) {
|
||||
date2 = weekday[d.getDay()] + " " + d02(week)
|
||||
if (useVectorFont == true) {
|
||||
g.setFont("Vector", 18);
|
||||
} else {
|
||||
g.setFont("6x8", 2);
|
||||
}
|
||||
g.drawString(date2, 105, 55, false);
|
||||
} else {
|
||||
date2 = d.getFullYear();
|
||||
if (useVectorFont == true) {
|
||||
g.setFont("Vector", 22);
|
||||
g.drawString(date2, 105, 55, false);
|
||||
} else {
|
||||
g.setFont("4x6", 3);
|
||||
g.drawString(date2, 108, 55, false);
|
||||
}
|
||||
}
|
||||
|
||||
// draw time
|
||||
g.setColor(1, 1, 1);
|
||||
if (useVectorFont == true) {
|
||||
g.setFont("Vector", 60);
|
||||
g.drawString(time, 10, 108, false);
|
||||
} else {
|
||||
g.setFont("6x8", 5);
|
||||
g.drawString(time, 14, 112, false);
|
||||
}
|
||||
}
|
||||
|
||||
loadSettings();
|
||||
|
||||
g.clear();
|
||||
|
||||
pollBattery();
|
||||
draw();
|
||||
|
||||
var batInterval = setInterval(pollBattery, 60000);
|
||||
var drawInterval = setInterval(draw, 10000);
|
||||
var batInterval = setInterval(pollBattery, pollInterval * 1000);
|
||||
var actualDrawInterval = setInterval(draw, drawInterval * 1000);
|
||||
|
||||
// Stop updates when LCD is off, restart when on
|
||||
Bangle.on('lcdPower',on=>{
|
||||
Bangle.on("lcdPower", (on) => {
|
||||
if (batInterval) clearInterval(batInterval);
|
||||
batInterval = undefined;
|
||||
if (drawInterval) clearInterval(drawInterval);
|
||||
drawInterval = undefined;
|
||||
if (actualDrawInterval) clearInterval(actualDrawInterval);
|
||||
actualDrawInterval = undefined;
|
||||
if (on) {
|
||||
batInterval = setInterval(pollBattery, 60000);
|
||||
drawInterval = setInterval(draw, 10000);
|
||||
batInterval = setInterval(pollBattery, pollInterval * 1000);
|
||||
actualDrawInterval = setInterval(draw, drawInterval * 1000);
|
||||
|
||||
pollBattery();
|
||||
draw(); // draw immediately
|
||||
draw();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
{
|
||||
"id":"smclock",
|
||||
"name":"Monogram Watch Face",
|
||||
"shortName":"MonoClock",
|
||||
"icon":"app.png",
|
||||
"version":"0.02",
|
||||
"id": "smclock",
|
||||
"name": "Monogram Watch Face",
|
||||
"shortName": "MonoClock",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{ "url": "screenshot.png" }],
|
||||
"version": "0.04",
|
||||
"description": "A simple watchface based on my stylised monogram.",
|
||||
"tags":"clock",
|
||||
"readme":"README.md",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"readme": "README.md",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"smclock.app.js","url":"app.js"},
|
||||
{"name":"smclock.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
{ "name": "smclock.app.js", "url": "app.js" },
|
||||
{ "name": "smclock.settings.js", "url": "settings.js" },
|
||||
{ "name": "smclock.img", "url": "app-icon.js", "evaluate": true }
|
||||
],
|
||||
"data": [{ "name": "smclock.json" }]
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,94 @@
|
|||
// settings menu for Monogram Watch Face
|
||||
// Anton Clock settings were used as template
|
||||
// helper functions taken from Anton Clock
|
||||
|
||||
(function (back) {
|
||||
var FILE = "smclock.json";
|
||||
// load settings from the file
|
||||
// assign default values if it doesn't exist
|
||||
var settings = Object.assign({
|
||||
dateFormat: "Short",
|
||||
drawInterval: 10,
|
||||
pollInterval: 60,
|
||||
showAnalogFace: false,
|
||||
showWeekInfo: false,
|
||||
useVectorFont: false,
|
||||
}, require("Storage").readJSON(FILE, true) || {});
|
||||
|
||||
// write the new settings to the file
|
||||
function writeSettings() {require("Storage").writeJSON(FILE, settings);}
|
||||
|
||||
// helper method which uses int-based menu item for set of string values
|
||||
function stringItems(startvalue, writer, values) {
|
||||
return {
|
||||
value: startvalue === undefined ? 0 : values.indexOf(startvalue),
|
||||
format: v => values[v],
|
||||
min: 0,
|
||||
max: values.length - 1,
|
||||
wrap: true,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
writer(values[v]);
|
||||
writeSettings();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// helper method which breaks string set settings down to local settings object
|
||||
function stringInSettings(name, values) {
|
||||
return stringItems(settings[name], (v) => (settings[name] = v), values);
|
||||
}
|
||||
|
||||
// settings menu
|
||||
var mainmenu = {
|
||||
"": {title: "Monogram Clock",},
|
||||
"< Back": () => back(),
|
||||
"Analog Face": {
|
||||
value:
|
||||
settings.showAnalogFace !== undefined ? settings.showAnalogFace : false,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.showAnalogFace = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
Date: stringInSettings("dateFormat", ["Long", "Short"]),
|
||||
"Draw Interval": {
|
||||
value: settings.drawInterval,
|
||||
onchange: v => {
|
||||
settings.drawInterval = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
"Poll Interval": {
|
||||
value: settings.pollInterval,
|
||||
onchange: v => {
|
||||
settings.pollInterval = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
"Week Info": {
|
||||
value:
|
||||
settings.showWeekInfo !== undefined ? settings.showWeekInfo : false,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.showWeekInfo = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
"Vector Font": {
|
||||
value:
|
||||
settings.useVectorFont !== undefined ? settings.useVectorFont : false,
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.useVectorFont = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Actually display the menu
|
||||
E.showMenu(mainmenu);
|
||||
});
|
||||
|
||||
// end of file
|
|
@ -11,10 +11,10 @@
|
|||
"Back": "Terug",
|
||||
"Repeat": "Herhalen",
|
||||
"Delete": "Verwijderen",
|
||||
"ALARM!": "ALARV.",
|
||||
"Sleep": "Stand-by",
|
||||
"ALARM!": "ALARM!",
|
||||
"Sleep": "Standby",
|
||||
"New Timer": "Nieuwe Timer",
|
||||
"(repeat)": "(herhaling)",
|
||||
"(repeat)": "(herhaal)",
|
||||
"music": "muziek",
|
||||
"week": "week",
|
||||
"Auto snooze": "Auto snooze",
|
||||
|
@ -31,7 +31,7 @@
|
|||
"minimum": "minimum",
|
||||
"valid period": "geldige periode",
|
||||
"heartrate": "hartslag",
|
||||
"battery warn": "batterijwaarschuwing",
|
||||
"battery warn": "batterijwaarsch.",
|
||||
"data": "gegevens",
|
||||
"step length": "staplengte",
|
||||
"min. confidence": "min. vertrouwen",
|
||||
|
@ -47,7 +47,7 @@
|
|||
"Yes\ndefinitely": "Ja\nzeker",
|
||||
"STEPS": "STAPPEN",
|
||||
"Show clocks": "Toon klokken",
|
||||
"Record Run": "Record run",
|
||||
"Record Run": "Rondje opnemen",
|
||||
"No Messages": "Geen berichten.",
|
||||
"View Message": "Bekijk bericht",
|
||||
"Piezo": "Piëzo",
|
||||
|
@ -63,7 +63,7 @@
|
|||
"Make Connectable": "Maak Verbindbaar",
|
||||
"Quiet Mode": "Rustige modus",
|
||||
"BLE": "BLE",
|
||||
"Dark BW": "Donker BW",
|
||||
"Dark BW": "Donkere modus",
|
||||
"Apps": "Apps",
|
||||
"Programmable": "Programmeerbaar",
|
||||
"Vibration": "Trilling",
|
||||
|
@ -82,32 +82,32 @@
|
|||
"Remove": "Verwijder",
|
||||
"Add Device": "Apparaat toevoegen",
|
||||
"Connect device\nto add to\nwhitelist": "Apparaat aansluiten\ntoe te voegen aan\nwhitelist",
|
||||
"Wake on Twist": "Wake on Twist",
|
||||
"Wake on BTN2": "Wake op BTN2",
|
||||
"Wake on BTN1": "Wake op BTN1",
|
||||
"Wake on FaceUp": "Wakker worden op FaceUp",
|
||||
"Wake on Twist": "Aangaan bij draaien",
|
||||
"Wake on BTN2": "Aangaan bij BTN2",
|
||||
"Wake on BTN1": "Aangaan bij BTN1",
|
||||
"Wake on FaceUp": "Aangaan bij FaceUp",
|
||||
"Log": "Log",
|
||||
"Debug Info": "Debug info",
|
||||
"Wake on BTN3": "Wake op BTN3",
|
||||
"Flatten Battery": "Batterij plat maken",
|
||||
"Wake on BTN3": "Aangaan bij BTN3",
|
||||
"Flatten Battery": "Batterij leegmaken",
|
||||
"Rewrite Settings": "Instellingen herschrijven",
|
||||
"Compact Storage": "Compacte opslag",
|
||||
"Utilities": "Nutsbedrijven",
|
||||
"Compact Storage": "Comprimeer opslag",
|
||||
"Utilities": "Gereedschap",
|
||||
"Clock Style": "Klok Stijl",
|
||||
"Time Zone": "Tijdzone",
|
||||
"Twist Timeout": "Time-out draaien",
|
||||
"Twist Max Y": "Twist Max Y",
|
||||
"Twist Threshold": "Twist Drempel",
|
||||
"Wake on Touch": "Wakker worden bij aanraking",
|
||||
"Compacting...\nTakes approx\n1 minute": "Verdichten...\nDuurt ongeveer\n1 minuut",
|
||||
"Reset to Defaults": "Terugzetten op standaardwaarden",
|
||||
"Twist Timeout": "Draaien time-out",
|
||||
"Twist Max Y": "Draaien Max Y",
|
||||
"Twist Threshold": "Draaien vanaf",
|
||||
"Wake on Touch": "Aangaan bij aanraking",
|
||||
"Compacting...\nTakes approx\n1 minute": "Comprimeren...\nDuurt ongeveer\n1 minuut",
|
||||
"Reset to Defaults": "Terug naar standaardwaarden",
|
||||
"No Clocks Found": "Geen klokken gevonden",
|
||||
"Month": "Maand",
|
||||
"Minute": "Minuutje",
|
||||
"Minute": "Minuut",
|
||||
"Flattening battery - this can take hours.\nLong-press button to cancel": "Batterij leegmaken - dit kan uren duren.\nDruk lang op de knop om te annuleren",
|
||||
"Sleep Phase Alarm": "Slaapfase alarm",
|
||||
"Second": "Tweede",
|
||||
"Turn Off": "Zet uit.",
|
||||
"Turn Off": "Uitzetten",
|
||||
"Hour": "Uur",
|
||||
"Storage": "Opslag",
|
||||
"Date": "Datum",
|
||||
|
@ -144,7 +144,7 @@
|
|||
"Hide": "Verberg",
|
||||
"Messages": "Berichten",
|
||||
"Error in settings": "Fout in instellingen",
|
||||
"BACK": "ACHTER",
|
||||
"BACK": "TERUG",
|
||||
"Whitelist": "Whitelist",
|
||||
"Set Time": "Tijd instellen",
|
||||
"Disable": "Uitschakelen",
|
||||
|
@ -162,7 +162,7 @@
|
|||
"Loading": "Laden",
|
||||
"Music": "Muziek",
|
||||
"color": "kleur",
|
||||
"off": "van",
|
||||
"off": "uit",
|
||||
"Off": "Uit",
|
||||
"Theme": "Thema"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue