diff --git a/apps/bikespeedo/ChangeLog b/apps/bikespeedo/ChangeLog
index 10752ee2b..b47f8cdc3 100644
--- a/apps/bikespeedo/ChangeLog
+++ b/apps/bikespeedo/ChangeLog
@@ -1,3 +1,4 @@
0.01: New App!
0.02: Barometer altitude adjustment setting
0.03: Use default Bangle formatter for booleans
+0.04: Add options for units in locale and recording GPS
diff --git a/apps/bikespeedo/app.js b/apps/bikespeedo/app.js
index a62a429e5..6f462a820 100644
--- a/apps/bikespeedo/app.js
+++ b/apps/bikespeedo/app.js
@@ -403,6 +403,8 @@ function onGPS(fix) {
if ( sp < 10 ) sp = sp.toFixed(1);
else sp = Math.round(sp);
+ if (isNaN(sp)) sp = '---';
+
if (parseFloat(sp) > parseFloat(max.spd) && max.n > 15 ) max.spd = parseFloat(sp);
// Altitude
@@ -416,6 +418,12 @@ function onGPS(fix) {
// Age of last fix (secs)
age = Math.max(0,Math.round(getTime())-(lf.time.getTime()/1000));
+ } else {
+ // populate spd_unit
+ if (cfg.spd == 0) {
+ m = require("locale").speed(0).match(/[0-9,\.]+(.*)/);
+ cfg.spd_unit = m[1];
+ }
}
if ( cfg.modeA == 1 ) {
@@ -465,7 +473,7 @@ function updateClock() {
// Read settings.
let cfg = require('Storage').readJSON('bikespeedo.json',1)||{};
-cfg.spd = 1; // Multiplier for speed unit conversions. 0 = use the locale values for speed
+cfg.spd = !cfg.localeUnits; // Multiplier for speed unit conversions. 0 = use the locale values for speed
cfg.spd_unit = 'km/h'; // Displayed speed unit
cfg.alt = 1; // Multiplier for altitude unit conversions. (feet:'0.3048')
cfg.alt_unit = 'm'; // Displayed altitude units ('feet')
@@ -499,14 +507,6 @@ function onPressure(dat) {
altiBaro = Number(dat.altitude.toFixed(0)) + Number(cfg.altDiff);
}
-Bangle.setBarometerPower(1); // needs some time...
-g.clearRect(0,screenYstart,screenW,screenH);
-onGPS(lf);
-Bangle.setGPSPower(1);
-Bangle.on('GPS', onGPS);
-Bangle.on('pressure', onPressure);
-
-Bangle.setCompassPower(1);
var CALIBDATA = require("Storage").readJSON("magnav.json",1)||null;
if (!CALIBDATA) calibrateCompass = true;
function Compass_tiltfixread(O,S){
@@ -544,11 +544,33 @@ function Compass_reading() {
Compass_heading = Compass_newHeading(d,Compass_heading);
hdngCompass = Compass_heading.toFixed(0);
}
-if (!calibrateCompass) setInterval(Compass_reading,200);
-setButtons();
-if (emulator) setInterval(updateClock, 2000);
-else setInterval(updateClock, 10000);
+function start() {
+ Bangle.setBarometerPower(1); // needs some time...
+ g.clearRect(0,screenYstart,screenW,screenH);
+ onGPS(lf);
+ Bangle.setGPSPower(1);
+ Bangle.on('GPS', onGPS);
+ Bangle.on('pressure', onPressure);
+
+ Bangle.setCompassPower(1);
+ if (!calibrateCompass) setInterval(Compass_reading,200);
+
+ setButtons();
+ if (emulator) setInterval(updateClock, 2000);
+ else setInterval(updateClock, 10000);
+
+ Bangle.drawWidgets();
+}
Bangle.loadWidgets();
-Bangle.drawWidgets();
+if (cfg.record && WIDGETS["recorder"]) {
+ WIDGETS["recorder"]
+ .setRecording(true)
+ .then(start);
+
+ if (cfg.recordStopOnExit)
+ E.on('kill', () => WIDGETS["recorder"].setRecording(false));
+} else {
+ start();
+}
diff --git a/apps/bikespeedo/metadata.json b/apps/bikespeedo/metadata.json
index 80b91427c..ea74db9a1 100644
--- a/apps/bikespeedo/metadata.json
+++ b/apps/bikespeedo/metadata.json
@@ -2,7 +2,7 @@
"id": "bikespeedo",
"name": "Bike Speedometer (beta)",
"shortName": "Bike Speedometer",
- "version": "0.03",
+ "version": "0.04",
"description": "Shows GPS speed, GPS heading, Compass heading, GPS altitude and Barometer altitude from internal sources",
"icon": "app.png",
"screenshots": [{"url":"Screenshot.png"}],
diff --git a/apps/bikespeedo/settings.js b/apps/bikespeedo/settings.js
index f41524263..bb943c081 100644
--- a/apps/bikespeedo/settings.js
+++ b/apps/bikespeedo/settings.js
@@ -11,9 +11,34 @@
'< Back': back,
'< Load Bike Speedometer': ()=>{load('bikespeedo.app.js');},
'Barometer Altitude adjustment' : function() { E.showMenu(altdiffMenu); },
- 'Kalman Filters' : function() { E.showMenu(kalMenu); }
+ 'Kalman Filters' : function() { E.showMenu(kalMenu); },
+ 'Speed units': {
+ value: !!settings.localeUnits,
+ format: b => b ? "Locale" : "km/h",
+ onchange: b => {
+ settings.localeUnits = b;
+ writeSettings();
+ }
+ },
};
+ if (global.WIDGETS && WIDGETS["recorder"]) {
+ appMenu[/*LANG*/"Record rides"] = {
+ value : !!settings.record,
+ onchange : v => {
+ settings.record = v;
+ writeSettings();
+ }
+ };
+ appMenu[/*LANG*/"Stop record on exit"] = {
+ value : !!settings.recordStopOnExit,
+ onchange : v => {
+ settings.recordStopOnExit = v;
+ writeSettings();
+ }
+ };
+ }
+
const altdiffMenu = {
'': { 'title': 'Altitude adjustment' },
'< Back': function() { E.showMenu(appMenu); },
diff --git a/apps/calendar/ChangeLog b/apps/calendar/ChangeLog
index 27e1e2517..c7902e263 100644
--- a/apps/calendar/ChangeLog
+++ b/apps/calendar/ChangeLog
@@ -13,3 +13,4 @@
0.12: Mark dated events on a day
0.13: Switch to swipe left/right for month and up/down for year selection
Display events for current month on touch
+0.14: Add support for holidays
diff --git a/apps/calendar/README.md b/apps/calendar/README.md
index ec1c0c55a..5f90d0d52 100644
--- a/apps/calendar/README.md
+++ b/apps/calendar/README.md
@@ -10,6 +10,7 @@ Basic calendar
- Swipe down (Bangle.js 2 only) to go to the next year
- Touch to display events for current month
- Press the button (button 3 on Bangle.js 1) to exit
+- Holidays have same color as weekends and can be edited with the 'Download'-interface, e.g. by uploading an iCalendar file.
## Settings
diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js
index 6aab1aecd..d7c43eb1f 100644
--- a/apps/calendar/calendar.js
+++ b/apps/calendar/calendar.js
@@ -16,6 +16,7 @@ const white = "#ffffff";
const red = "#d41706";
const blue = "#0000ff";
const yellow = "#ffff00";
+const cyan = "#00ffff";
let bgColor = color4;
let bgColorMonth = color1;
let bgColorDow = color2;
@@ -23,6 +24,7 @@ let bgColorWeekend = color3;
let fgOtherMonth = gray1;
let fgSameMonth = white;
let bgEvent = blue;
+let bgOtherEvent = "#ff8800";
const eventsPerDay=6; // how much different events per day we can display
const date = new Date();
@@ -36,9 +38,17 @@ const events = (require("Storage").readJSON("sched.json",1) || []).filter(a => a
date.setHours(time.h);
date.setMinutes(time.m);
date.setSeconds(time.s);
- return {date: date, msg: a.msg};
+ return {date: date, msg: a.msg, type: "e"};
+});
+// add holidays & other events
+(require("Storage").readJSON("calendar.days.json",1) || []).forEach(d => {
+ const date = new Date(d.date);
+ const o = {date: date, msg: d.name, type: d.type};
+ if (d.repeat) {
+ o.repeat = d.repeat;
+ }
+ events.push(o);
});
-events.sort((a,b) => a.date - b.date);
if (settings.ndColors === undefined) {
settings.ndColors = !g.theme.dark;
@@ -52,68 +62,16 @@ if (settings.ndColors === true) {
fgOtherMonth = blue;
fgSameMonth = black;
bgEvent = color2;
+ bgOtherEvent = cyan;
}
function getDowLbls(locale) {
- let dowLbls;
- //TODO: Find some clever way to generate this programmatically from locale lib
- switch (locale) {
- case "de_AT":
- case "de_CH":
- case "de_DE":
- if (startOnSun) {
- dowLbls = ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"];
- } else {
- dowLbls = ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"];
- }
- break;
- case "nl_NL":
- if (startOnSun) {
- dowLbls = ["zo", "ma", "di", "wo", "do", "vr", "za"];
- } else {
- dowLbls = ["ma", "di", "wo", "do", "vr", "za", "zo"];
- }
- break;
- case "fr_BE":
- case "fr_CH":
- case "fr_FR":
- if (startOnSun) {
- dowLbls = ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"];
- } else {
- dowLbls = ["Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di"];
- }
- break;
- case "sv_SE":
- if (startOnSun) {
- dowLbls = ["Di", "Lu", "Ma", "Me", "Je", "Ve", "Sa"];
- } else {
- dowLbls = ["Lu", "Ma", "Me", "Je", "Ve", "Sa", "Di"];
- }
- break;
- case "it_CH":
- case "it_IT":
- if (startOnSun) {
- dowLbls = ["Do", "Lu", "Ma", "Me", "Gi", "Ve", "Sa"];
- } else {
- dowLbls = ["Lu", "Ma", "Me", "Gi", "Ve", "Sa", "Do"];
- }
- break;
- case "oc_FR":
- if (startOnSun) {
- dowLbls = ["dg", "dl", "dm", "dc", "dj", "dv", "ds"];
- } else {
- dowLbls = ["dl", "dm", "dc", "dj", "dv", "ds", "dg"];
- }
- break;
- default:
- if (startOnSun) {
- dowLbls = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
- } else {
- dowLbls = ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"];
- }
- break;
- }
- return dowLbls;
+ let days = startOnSun ? [0, 1, 2, 3, 4, 5, 6] : [1, 2, 3, 4, 5, 6, 0];
+ const d = new Date();
+ return days.map(i => {
+ d.setDate(d.getDate() + (i + 7 - d.getDay()) % 7);
+ return require("locale").dow(d, 1);
+ });
}
function sameDay(d1, d2) {
@@ -206,8 +164,13 @@ function drawCalendar(date) {
weekBeforeMonth.setDate(weekBeforeMonth.getDate() - 7);
const week2AfterMonth = new Date(date.getFullYear(), date.getMonth()+1, 0);
week2AfterMonth.setDate(week2AfterMonth.getDate() + 14);
+ events.forEach(ev => {
+ if (ev.repeat === "y") {
+ ev.date.setFullYear(ev.date.getMonth() < 6 ? week2AfterMonth.getFullYear() : weekBeforeMonth.getFullYear());
+ }
+ });
const eventsThisMonth = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth);
-
+ eventsThisMonth.sort((a,b) => a.date - b.date);
let i = 0;
for (y = 0; y < rowN - 1; y++) {
for (x = 0; x < colN; x++) {
@@ -220,6 +183,33 @@ function drawCalendar(date) {
const y1 = y * rowH + headerH + rowH;
const x2 = x * colW + colW;
const y2 = y * rowH + headerH + rowH + rowH;
+
+ if (eventsThisMonth.length > 0) {
+ // Display events for this day
+ eventsThisMonth.forEach((ev, idx) => {
+ if (sameDay(ev.date, curDay)) {
+ switch(ev.type) {
+ case "e": // alarm/event
+ const hour = ev.date.getHours() + ev.date.getMinutes()/60.0;
+ const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
+ const height = (y2-2) - (y1+2); // height of a cell
+ const sliceHeight = height/eventsPerDay;
+ const ystart = (y1+2) + slice*sliceHeight;
+ g.setColor(bgEvent).fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
+ break;
+ case "h": // holiday
+ g.setColor(bgColorWeekend).fillRect(x1+1, y1+1, x2-1, y2-1);
+ break;
+ case "o": // other
+ g.setColor(bgOtherEvent).fillRect(x1+1, y1+1, x2-1, y2-1);
+ break;
+ }
+
+ eventsThisMonth.splice(idx, 1); // this event is no longer needed
+ }
+ });
+ }
+
if (isToday) {
g.setColor(red);
g.drawRect(x1, y1, x2, y2);
@@ -231,23 +221,6 @@ function drawCalendar(date) {
);
}
- if (eventsThisMonth.length > 0) {
- // Display events for this day
- g.setColor(bgEvent);
- eventsThisMonth.forEach((ev, idx) => {
- if (sameDay(ev.date, curDay)) {
- const hour = ev.date.getHours() + ev.date.getMinutes()/60.0;
- const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
- const height = (y2-2) - (y1+2); // height of a cell
- const sliceHeight = height/eventsPerDay;
- const ystart = (y1+2) + slice*sliceHeight;
- g.fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
-
- eventsThisMonth.splice(idx, 1); // this event is no longer needed
- }
- });
- }
-
require("Font8x12").add(Graphics);
g.setFont("8x12", fontSize);
g.setColor(day < 50 ? fgOtherMonth : fgSameMonth);
@@ -286,10 +259,11 @@ function setUI() {
},
btn: (n) => n === (process.env.HWVERSION === 2 ? 1 : 3) && load(),
touch: (n,e) => {
+ events.sort((a,b) => a.date - b.date);
const menu = events.filter(ev => ev.date.getFullYear() === date.getFullYear() && ev.date.getMonth() === date.getMonth()).map(e => {
const dateStr = require("locale").date(e.date, 1);
const timeStr = require("locale").time(e.date, 1);
- return { title: `${dateStr} ${timeStr}` + (e.msg ? " " + e.msg : "") };
+ return { title: `${dateStr} ${e.type === "e" ? timeStr : ""}` + (e.msg ? " " + e.msg : "") };
});
if (menu.length === 0) {
menu.push({title: /*LANG*/"No events"});
diff --git a/apps/calendar/interface.html b/apps/calendar/interface.html
new file mode 100644
index 000000000..280a96c0b
--- /dev/null
+++ b/apps/calendar/interface.html
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+ Holidays
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Upload
+ Reload
+
+
diff --git a/apps/calendar/metadata.json b/apps/calendar/metadata.json
index 87599e3f4..44a68d879 100644
--- a/apps/calendar/metadata.json
+++ b/apps/calendar/metadata.json
@@ -1,7 +1,7 @@
{
"id": "calendar",
"name": "Calendar",
- "version": "0.13",
+ "version": "0.14",
"description": "Simple calendar",
"icon": "calendar.png",
"screenshots": [{"url":"screenshot_calendar.png"}],
@@ -9,10 +9,11 @@
"supports": ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
+ "interface": "interface.html",
"storage": [
{"name":"calendar.app.js","url":"calendar.js"},
{"name":"calendar.settings.js","url":"settings.js"},
{"name":"calendar.img","url":"calendar-icon.js","evaluate":true}
],
- "data": [{"name":"calendar.json"}]
+ "data": [{"name":"calendar.json"}, {"name":"calendar.days.json"}]
}
diff --git a/apps/clkinfom/ChangeLog b/apps/clkinfom/ChangeLog
new file mode 100644
index 000000000..7f837e50e
--- /dev/null
+++ b/apps/clkinfom/ChangeLog
@@ -0,0 +1 @@
+0.01: First version
diff --git a/apps/clkinfom/README.md b/apps/clkinfom/README.md
new file mode 100644
index 000000000..baa241fc7
--- /dev/null
+++ b/apps/clkinfom/README.md
@@ -0,0 +1,11 @@
+# RAM Clock Info
+
+
+
+A clock info that displays the % memory used
+
+## Screenshots
+
+
+
+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/)
diff --git a/apps/clkinfom/app.png b/apps/clkinfom/app.png
new file mode 100644
index 000000000..aea4bcbcd
Binary files /dev/null and b/apps/clkinfom/app.png differ
diff --git a/apps/clkinfom/clkinfo.js b/apps/clkinfom/clkinfo.js
new file mode 100644
index 000000000..a3dae43e1
--- /dev/null
+++ b/apps/clkinfom/clkinfo.js
@@ -0,0 +1,61 @@
+(function () {
+ var timeout;
+
+ var debug = function(o) {
+ //console.log(o);
+ };
+
+ var clearTimer = function() {
+ if (timeout) {
+ clearTimeout(timeout);
+ timeout = undefined;
+ debug("timer cleared");
+ }
+ };
+
+ var queueRedraw = function() {
+ clearTimer();
+ timeout = setTimeout(function() {
+ timeout = undefined;
+ queueRedraw();
+ }, 60000);
+ info.items[0].emit("redraw");
+ debug("queued");
+ };
+
+ var img = function() {
+ return atob("GBgBAAAAAAAAAAAAB//gD//wH//4HgB4HAA4HAA4HAA4HDw4HDw4HDw4HDw4HAA4HAA4HAA4HgB4H//4D//wB//gAAAAAAAAAAAA");
+ };
+
+ var text = function() {
+ var val = process.memory(false);
+ return '' + Math.round(val.usage*100 / val.total) + '%';
+ };
+
+ var info = {
+ name: "Bangle",
+ items: [
+ {
+ name: "ram",
+ get: function () { return ({
+ img: img(),
+ text: text()
+ }); },
+ run : function() {
+ debug("run");
+ queueRedraw();
+ },
+ show: function () {
+ debug("show");
+ this.run();
+ },
+ hide: function() {
+ debug("hide");
+ clearTimer();
+ }
+ }
+ ]
+ };
+
+ return info;
+});
diff --git a/apps/clkinfom/metadata.json b/apps/clkinfom/metadata.json
new file mode 100644
index 000000000..36ab221cd
--- /dev/null
+++ b/apps/clkinfom/metadata.json
@@ -0,0 +1,15 @@
+{
+ "id": "clkinfom",
+ "name": "RAM Clock Info",
+ "version":"0.01",
+ "description": "Clockinfo that displays % used memory",
+ "icon": "app.png",
+ "screenshots": [{"url":"screenshot.png"}],
+ "type": "clkinfo",
+ "tags": "clkinfo",
+ "supports" : ["BANGLEJS2"],
+ "readme":"README.md",
+ "storage": [
+ {"name":"ram.clkinfo.js","url":"clkinfo.js"}
+ ]
+}
diff --git a/apps/clkinfom/screenshot.png b/apps/clkinfom/screenshot.png
new file mode 100644
index 000000000..4ae613edd
Binary files /dev/null and b/apps/clkinfom/screenshot.png differ
diff --git a/apps/cscsensor/metadata.json b/apps/cscsensor/metadata.json
index ba250c914..87eb5d12f 100644
--- a/apps/cscsensor/metadata.json
+++ b/apps/cscsensor/metadata.json
@@ -5,7 +5,7 @@
"version": "0.08",
"description": "Read BLE enabled cycling speed and cadence sensor and display readings on watch",
"icon": "icons8-cycling-48.png",
- "tags": "outdoors,exercise,ble,bluetooth",
+ "tags": "outdoors,exercise,ble,bluetooth,bike,cycle,bicycle",
"supports": ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",
"storage": [
diff --git a/apps/health/README.md b/apps/health/README.md
index 960e5565b..b5f6191cc 100644
--- a/apps/health/README.md
+++ b/apps/health/README.md
@@ -2,8 +2,6 @@
Logs health data to a file in a defined interval, and provides an app to view it
-**BETA - requires firmware 2v11 or later**
-
## Usage
Once installed, health data is logged automatically.
diff --git a/apps/kanagsec/ChangeLog b/apps/kanagsec/ChangeLog
new file mode 100644
index 000000000..edcc4a199
--- /dev/null
+++ b/apps/kanagsec/ChangeLog
@@ -0,0 +1,2 @@
+0.01: New App!
+0.02: Fixes temperature not loading at start.
diff --git a/apps/kanagsec/README.md b/apps/kanagsec/README.md
new file mode 100644
index 000000000..d396badec
--- /dev/null
+++ b/apps/kanagsec/README.md
@@ -0,0 +1,14 @@
+# Kanagawa clock
+
+This clock displays the great wave of kanagawa in the background.
+
+It also displays:
+- Hours, minutes and seconds.
+- Seconds are only displayed when screen is unlocked.
+- Years, monts and day as in numbers.
+- Name representation of the current day.
+- Current temperature from weather, if available.
+- Battery level in percent.
+
+
+
\ No newline at end of file
diff --git a/apps/kanagsec/app-icon.js b/apps/kanagsec/app-icon.js
new file mode 100644
index 000000000..2d3758579
--- /dev/null
+++ b/apps/kanagsec/app-icon.js
@@ -0,0 +1 @@
+require("heatshrink").decompress(atob("mEwxH+1YA/ABusBJIACGMwnFF0paGC6wvYDKATDCweHK54YGSY4RKAAOIwIaJC5YVKCJmHF4QzDF6gyFAYIMHwIABBgICGF7OlFYwvEqwEBMQWIL6gOCChAjBq8yruBrsyllXBgaRBAAIuRahQgBAIMyhFXGYMHmQ5Bw5eBJBIvUJoJZBq0shEIFoMIlkyF4IfFMgQtSF4kyQ4IpBAYICBFwQ4BrtdZogYBMRgvMFgQpBAIQHCg8HYQeIwRiESZiPKFoIvFMAQABqwZBwLDCMQaaGGRgHDw6ABqwvEAQUzrur0ouBXYa/LGBIIGwItDFwZXEw4WCGYKOMABReBGwJfBq4CBYIS9DGAOlCAI3CwOlFqgXBAAIFBGgKSCL4KEILgItUFgJ7BDQL1EAANdMIIvJMIKPUF4OHroqCE4IBCrqPBciQvOEILoCmVWAwOrR4Usca4AIbAWrMAIqBRILABFwJfkAAOIXIIwBq5lBd5QvYLgOrw+sdISSBFwQEBSDgcCEoWBLwNXFQIBBBQIGBY4OrAAgkLBgIOEDAssQwWBq4qBLIYHBGoQWFACWl0q7BAAKICcwIuCXIzzBq4VDDYOlEAQjDAgIBBBwITDwAACwK0EAYKGBdA4QBCgIaBD4YAJFIeAvVWqwCCJ4IvDEgIuHSYIPBEAIZBDwYATXQQsBhAuFcgqhCD5erFpZ3BDwIADw4pFGAoSCFxJFCFhGAZIIOBPwNXRRAIH1mHFxBCDwAuFFoZMDEg+rw5mFFoIHBKggaBAwRrBAoeA0mlFweIwNdLZCVHHIYaCE4LWBhA0ClkrlYEBqGACQddq8zq9dwOIxB0Cw+rFwIHBIAWIq5vCIoRHCw4yCfQTfDH4YEBrtdKIQoBE4TyGMgQ/Bq+IJYInBAwKFBN5BwCD4oeBq5FBJAISELoaFCHQRGClhaBPQMsbRC0HrtWF4LxGN4TnBGgIQBwOlq5bBA4Msg8yGBLnBIwddmcylh4BNQKqCEAJwBFwQ8BE4MyvWAaoQKBqwwBq5mBwQYBEQLqDq6jBAAIuCK4Q8DL4YyBAwOrCQMIq2AJQIxBAQIeBlkIliwCA4NWRAI8BAAL8BdQjLDFYQPBKwQIBEgQwBPwYDCEAI9BFgIGBhBcDCwLjDD4NdGYgoDGIIFBSIIhBGAQADveA0mk0oGBGgI3CAAN7ZgbBBSYQ3BHAaKBb4LsBHgI4ChBPBvWlAAJFCFoIyBGYd6PIRWDUQQACBYOragRGBBwMyg5FCBgIwBGIOB0pGBAAR7DAwWHd4JGBg8HLgIxCYoIpCZgSvDg8yrrNDqwcCJIaHCFwR8DSQb2BcwIUCEQLWBCgJIFmUrZ4NdEAWrRoVcCQgKBw4ACNYgXDA"))
\ No newline at end of file
diff --git a/apps/kanagsec/app.js b/apps/kanagsec/app.js
new file mode 100644
index 000000000..f2dfb009f
--- /dev/null
+++ b/apps/kanagsec/app.js
@@ -0,0 +1,144 @@
+function getKanagawa() {
+ return require("heatshrink").decompress(atob("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"));
+}
+
+
+
+Graphics.prototype.setFontDarumadropOneRegular = function () {
+ // Actual height 36 (42 - 7)
+ return this.setFontCustom(
+ E.toString(require('heatshrink').decompress(atob('ACHwAol+Aokf4AFDg4SEgP8CQl/AokPwASEJT1wAol8G4oxEv5KEn5KEn//CIn/DAYFF/4FJgILKDoQpDBY4FDj//TIcH//gDAilEn6rFAokAC4gAah/4AohLEAoIMDAoIMDKIP/UIUDAoP+QQgSDAoQfCOwISDOwOPCQQkBBwJgBEgOAIoZ8BgIYCn4PBcAQPCj4+BgYPBh7gBHoPAEIIYC+AICB4ISBVQQPB4F/GIf+JQoABN4i9DAoSxCCQR8CCQSPDOAJDBSoYFDGQTbEar4AJRgV8KAQwBn58CJwMPSokDJYS0BBAQeB8Z2DQQYYBQQauDR4jmCDDuAcAZQBJQYACSwgVBSs8DAQMwAQMBIIM/TwMBHYMPZ4RUBg7tCv/wgZjCj5UBMYTyBBwR8CwE/PgZvBPgfgCgJ8C/AUBDAX+AoIYD4auS/bgDDoIYCn///z5CCQT5CCQUBDARICv6CCOwMfPgKkeAoabCvBmBG4U/MwQCBVYUfAQMHB4ICCPgMH4BjC/+D+E/CQICB/kPYIJmBv+DLIJcBEYKxBDAOP/AYDQQIYDPgPDDAShCDAauN/75CAoRjD/1/EgISCFoKbC/+BAocDfIKncg4wCSwQqDKIStCAoRPCOwYLENAR8DfwR8CDAf/+YYE+AYDg/gn4YCgHAEAJEDZ4ITDHAImDHASJEVwYXCLAd/DAhLCDATIDGIQGBTYk/GwQZCJQYyBYwRlDAokfDAkDSoYAYIYpvBHoYFB/kBA4J1CgJFBMQXAv5ICDAMfH4KUB/kHPgJ7CgJ8BRwOfDAIzB/+HDAcf8P+DAQCBv/nGIIbBWoSnCw7HDDAK0Dg/wHIIeBJoI5BSwU/HIK6ChBMCVAiiFn6bbPwTBEG4Z3CBgYFCKAIFDHwYFCCQQFCCQV/AoIlCLYP1Z4SHB/EfY4J0BTYbHCFoI8Ev4rBv/H/E/SoMPTYMfSoXwGQIxCnC0EgjuDKIQSBDwIABHII9BAAISBKwQSCXQSuCBYgAXaQpJBIQY8HGwimEDwQYLJIaSCDAgXBgauBh4XBg52BgaMBh4aCXwLHE8CPDj/7AoIbBTQRMDAoTgEKQZKBAoYYCJYYFFPgK5Dg5pEgB7EADMD+EPFgQ+Bh4nCRIPvOQJdEPgZXEMYZ8CCQhQB//zOwIkBBQN/EoP/g/8HAU/wP/gYYBBAN/4AYBBAMf+E/DAN/JIMfDAMf84xGVAQxCJQ7gCMYSXC//xZoQlB/E/AoRJBgIFCgEMVDsPbIY+CAoowDWgJbBWgbnEfIpjBCQauC4FgKwP+R4N8DwUD/t/CQKxBCYKuC8AgBSoX4H4KVC/w/BJgV/4KVDcAZFBCASbEAohEDMYZdEv4FEZwIFDgF+VDsHZokH+KJDgf8PAKcDz57BTgXvUQcP+YYGJQkPKIcOgIkDABQ'))),
+ 46,
+ atob("DBkiGhobHxkbHBsbDQ=="),
+ 50 | 65536
+ );
+};
+
+Graphics.prototype.setFontDarumadropOneRegular_small = function () {
+ // Actual height 15 (16 - 2)
+ return this.setFontCustom(
+ E.toString(require('heatshrink').decompress(atob('AAcwgEHwAECAAkHgEB/EAv8An/Ag/wgP8gEfC4PgC4oVD8EP/8A//wj8PgPwAgWA/PwBwfgg4lCEAegkEOg+B8/4j//wP/Agf8F4JKBAAlwuEPx4xB/Eej4dHh/nwF4NoeAuEeg8B814jnnCYN4DAZUBJ4PzNwsD+BZBKwKBBAgMIAQM//ED/+AAgMAvCmHj/hgP+nEf8eB904jw2B9/wjiuBg42DgQCB/wsBSoQdBJQPHgff+EZHYMPDAN8QwqmC4DRCj0BgPhNARtDFgIBBhzzEA4J8DCYM4jnzXomABwMHxg2FvxCBQwUQj1/XoRtCd4MPRAITBUgu8NoPAAgQABA'))),
+ 46,
+ atob("BQoNCgoLDAoLCwsLBQ=="),
+ 20 | 65536
+ );
+};
+
+// returns the temperature from weather json, if weather is provided trough
+//android/ios .. if no temperature is available, it wont be displayed.
+//(returns empty string).
+function getTemperature() {
+ try {
+ var weatherJson = storage.readJSON('weather.json');
+ var weather = weatherJson.weather;
+ return "Temp: " + Math.round(weather.temp - 273.15);
+ } catch (ex) {
+ return "";
+ }
+}
+
+const storage = require('Storage');
+require("Font8x16").add(Graphics);
+
+var IMAGEWIDTH = 176;
+var IMAGEHEIGHT = 176;
+var energySave = false;
+var batteryLvl = E.getBattery() + "%";
+var temperature = getTemperature();
+
+// timeout used to update every minute
+var drawTimeout;
+
+// schedule a draw for the next minute
+function queueDraw() {
+ if (drawTimeout) clearTimeout(drawTimeout);
+ drawTimeout = setTimeout(function () {
+ drawTimeout = undefined;
+ draw();
+ }, (energySave == true ? 60000 : 1000) - (Date.now() % (energySave == true ? 60000 : 1000)));
+}
+
+
+function draw() {
+ var date = new Date();
+ var x = 10;
+ var y = 2;
+
+ g.reset();
+
+ //draw main background image
+ g.drawImage(getKanagawa(), 0, 0);
+
+ // only update the batterylvl and temperature every 30 seconds
+ if (date.getSeconds() % 30 == 0) {
+ batteryLvl = E.getBattery() + "%";
+ temperature = getTemperature();
+ }
+
+ g.setFont("8x16");
+ g.drawString(temperature, 4, g.getHeight() - 40);
+ g.drawString(batteryLvl, g.getWidth() - g.stringWidth(batteryLvl) - 2, y);
+
+ // work out locale-friendly date/time
+ var h = date.getHours();
+ var m = date.getMinutes();
+ var s = date.getSeconds();
+
+ var timeStr = h.toString().padStart(2, 0) + ':' + m.toString().padStart(2, 0);
+ var timeStr2 = s.toString().padStart(2, 0);
+
+ var dateStr = require("locale").date(new Date(), 1);
+ dateStr = dateStr.replace(new RegExp('/', 'g'), '.');
+
+ var nameOfCurrentDay = require("locale").dow(date, 0).toUpperCase();
+
+ //---Hour and minute---
+ g.setColor("#000000");
+ g.setFont("DarumadropOneRegular");
+ g.drawString(timeStr, x, y);
+
+ // ---Seconds---
+ x += 2 + g.stringWidth(timeStr);
+ y += 24;
+
+ //only print seconds if screen is active and not locked
+ if (!energySave) {
+ g.setFont("DarumadropOneRegular_small");
+ g.drawString(timeStr2, x, y);
+ }
+
+ // ---draw date---
+ y += 45;
+ g.setColor("#000000");
+ g.setFont("8x16");
+ g.drawString(nameOfCurrentDay, 65, y);
+ y += 15;
+ g.drawString(dateStr, 65, y);
+
+ queueDraw();
+}
+
+
+// Stop updates when LCD is off, restart when on
+Bangle.on('lock', on => {
+ if (!on) {
+ energySave = false;
+ queueDraw();
+ }
+ else {
+ energySave = true;
+ }
+});
+
+g.clear();
+draw();
+
+// Show launcher when middle button pressed
+Bangle.setUI("clock");
+Bangle.loadWidgets();
+try {
+ require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe
+}
+catch (ex) {
+ require("widget_utils").hide();
+}
diff --git a/apps/kanagsec/app.png b/apps/kanagsec/app.png
new file mode 100644
index 000000000..347ef3851
Binary files /dev/null and b/apps/kanagsec/app.png differ
diff --git a/apps/kanagsec/metadata.json b/apps/kanagsec/metadata.json
new file mode 100644
index 000000000..9987ffdb4
--- /dev/null
+++ b/apps/kanagsec/metadata.json
@@ -0,0 +1,23 @@
+{
+ "id": "kanagsec",
+ "name": "Kanagawa clock",
+ "shortName":"kanagawa",
+ "version":"0.02",
+ "description": "A clock that displays the great wave of kanagawa (image from wikipedia) with seconds in active mode.",
+ "icon": "app.png",
+ "tags": "clock, kanagawa, wave",
+ "type": "clock",
+ "supports" : ["BANGLEJS2"],
+ "readme": "README.md",
+ "allow_emulator":true,
+ "storage":
+ [
+ {"name":"kanagsec.app.js","url":"app.js"},
+ {"name":"kanagsec.img","url":"app-icon.js","evaluate":true}
+ ],
+ "screenshots" :
+ [
+ { "url":"screenshot.png" },
+ { "url":"screenshot2.png" }
+ ]
+}
\ No newline at end of file
diff --git a/apps/kanagsec/screenshot.png b/apps/kanagsec/screenshot.png
new file mode 100644
index 000000000..167eef0a8
Binary files /dev/null and b/apps/kanagsec/screenshot.png differ
diff --git a/apps/kanagsec/screenshot2.png b/apps/kanagsec/screenshot2.png
new file mode 100644
index 000000000..43ed6751b
Binary files /dev/null and b/apps/kanagsec/screenshot2.png differ
diff --git a/apps/patriotclk/ChangeLog b/apps/patriotclk/ChangeLog
new file mode 100644
index 000000000..c9f08fcc2
--- /dev/null
+++ b/apps/patriotclk/ChangeLog
@@ -0,0 +1,2 @@
+0.01: New App!
+0.02: Show the date inside the widget bar
\ No newline at end of file
diff --git a/apps/patriotclk/app-icon.js b/apps/patriotclk/app-icon.js
new file mode 100644
index 000000000..1dfde113e
--- /dev/null
+++ b/apps/patriotclk/app-icon.js
@@ -0,0 +1 @@
+require("heatshrink").decompress(atob("mEw4UA///8H55lCsHZHmEKgEVqoLIBQNVqgLGh4KBAANQBAUQBY1VoApBB4QLFDYoL/Bf4L/BbLrBBZAKBgEBBY0KAQIABgoLCCYQLEgEVBQYLGAAoL/Bf4LPAFw"))
\ No newline at end of file
diff --git a/apps/patriotclk/app-preview-btm.png b/apps/patriotclk/app-preview-btm.png
new file mode 100644
index 000000000..98008996b
Binary files /dev/null and b/apps/patriotclk/app-preview-btm.png differ
diff --git a/apps/patriotclk/app-preview.png b/apps/patriotclk/app-preview.png
new file mode 100644
index 000000000..b79009c94
Binary files /dev/null and b/apps/patriotclk/app-preview.png differ
diff --git a/apps/patriotclk/app.js b/apps/patriotclk/app.js
new file mode 100644
index 000000000..e618b0106
--- /dev/null
+++ b/apps/patriotclk/app.js
@@ -0,0 +1,89 @@
+Graphics.prototype.setFontAudiowide = function() {
+ // Actual height 33 (36 - 4)
+ return this.setFontCustom(
+ E.toString(require('heatshrink').decompress(atob('AB/wAgcB/AFVgFgHbkYAok4AogvEgYFEg4FEj4FEn4FE//gKQf/4AcD/4QDh/8Djf+DhN/T4YcFgYcKh4cEh68Eh4cDAoOAAocORYkMf1JxBIYcf/6PDn//MIYEB/5KBOIIABKwIFFO4V/UQMHEIMfFQMHAQP3AQJ3BDIKABh/ggf7ApHAg/5AonxAocPAokf8IFE4IFDn4FEv+BAokBAof/AofB/wFE/gFD4YFE4/4AohgBAoXPAonvMAIFD4AFCVgIFBQYX3wCGCR4T+CTYqtLX4rLC/zXIcYoAQQYIFiJoR9CArgAlToIpDRQIFDSwI7C4CiBApN/Apb1D4F+Av4Fd8H+Aof/AoaTB/gFIgaBBAoSrB+AFCgF/8AFDAESP/Av3wv0HZYYABYoYAB+AFGZYIAB8DLCAAPAZYQFBZUhHC/gFE/wFaAAN+Av4Fqv53EboYFdAFIvB4EBGofwAon4Aon8ApX+AofAAot+Av4Fev8DAojFDAo0/S4IFGAAMf//gV4mAAoUD/zYgFwP8AoRGB/4FCAgI1CgIFC4A5BAoRHBg4FCKYMH/l+n5fC+F+g5rC8F+PoYFFZf7XVw7XNAALXNTYLXCVoYAQF4IFZjAFEnAFELIZCBAojRDAoMfAol/AohrCAoJfBNYIFBNYOAAoUf/xBDv/8AoXBRAcP4aCDh/PDgSNCDgQFCHIIFDUoafFAoJ3EGYQFCDgYFBXgZuBGYQAba4pDEhzvE/4ABKoMBAogbBAAJKBg4EBw4FEX4Z9BgIFC8AFE4F+Av5HFKYhfFAoRxCO4qDFgF/AokATYgfCZwcD/zTdAAV/Z4RBCHIZNBJYI5D/gFFOJEP+DF/a7N+ZYQFG+F+g7XFRYIFFbobLBboajCAoTRCcYTiEUQYAdgYCBsACBMwJlCAqUHJYLxDAAMgHSQ'))),
+ 46,
+ atob("CiAsESQjJSQkHyQkDA=="),
+ 48|65536
+ );
+};
+
+{
+
+ let img = require("Storage").read("patriotclk.bg.img");
+ let options = require("Storage").readJSON("patriotclk.opts",1)||{};
+
+ // timeout used to update every minute
+ let drawTimeout, widgetTimeout;
+
+ // draw everything
+ let draw = function() {
+ var x = g.getWidth()/2;
+ var y;
+ if (options.bottomText)
+ y = g.getHeight() - 24;
+ else
+ y = 4+(g.getHeight())/2; // middle
+ g.reset();
+ g.drawImage(img,0,0);
+ // work out locale-friendly date/time
+ var date = new Date();
+ var timeStr = require("locale").time(date,1);
+ var dateStr = require("locale").date(date);
+ // draw time
+ g.setFontAlign(0,0).setFont("Audiowide");
+ // draw a shadow by shifting left/right/up/down
+ g.drawString(timeStr,x-6,y);
+ g.drawString(timeStr,x+6,y);
+ g.drawString(timeStr,x,y-6);
+ g.drawString(timeStr,x,y+6);
+ g.drawString(timeStr,x-4,y+4);
+ g.drawString(timeStr,x+4,y+4);
+ g.drawString(timeStr,x-4,y-4);
+ g.drawString(timeStr,x+4,y-4);
+ // finally draw in the foreground color
+ g.setColor(g.theme.bg).drawString(timeStr,x,y);
+ // draw date
+ //y += 35;
+ //g.setFontAlign(0,0).setFont("6x8").g.setColor(g.theme.fg);
+ //g.drawString(dateStr,x,y);
+ // queue draw in one minute
+ if (drawTimeout) clearTimeout(drawTimeout);
+ drawTimeout = setTimeout(function() {
+ drawTimeout = undefined;
+ draw();
+ }, 60000 - (Date.now() % 60000));
+ };
+
+ // Show launcher when middle button pressed
+ Bangle.setUI({mode:"clock", remove:function() { //f ree memory
+ if (drawTimeout) clearTimeout(drawTimeout);
+ if (widgetTimeout) clearTimeout(widgetTimeout);
+ require("widget_utils").show();
+ var e = WIDGETS["patriot"];
+ g.reset().clearRect(e.x,e.y,e.x+63,e.y+23);
+ delete WIDGETS["patriot"];
+ delete Graphics.prototype.setFontAudiowide;
+ }});
+ // Load widgets (make them swipeable)
+ Bangle.loadWidgets();
+ WIDGETS["patriot"] = {
+ area:"tl",
+ width: 64, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout
+ draw : function(e) {
+ g.reset().clearRect(e.x,e.y,e.x+63,e.y+23);
+ var d = new Date();
+ g.setFont("6x8").setFontAlign(-1,0).drawString(require("locale").dow(d,0), e.x+2, e.y+8);
+ g.setFont("6x8").setFontAlign(-1,0).drawString(require("locale").date(d).trim(), e.x+2, e.y+16);
+ widgetTimeout = setTimeout(function() { // redraw every hour (it's just easier that working out timezones)
+ widgetTimeout = undefined;
+ WIDGETS["patriot"].draw(WIDGETS["patriot"]);
+ }, 3600000 - (Date.now() % 3600000));
+ }
+ };
+ require("widget_utils").swipeOn();
+ // Clear the screen once, at startup
+ g.clear();
+ // draw immediately at first, queue update
+ draw();
+}
\ No newline at end of file
diff --git a/apps/patriotclk/app.png b/apps/patriotclk/app.png
new file mode 100644
index 000000000..781ab8c60
Binary files /dev/null and b/apps/patriotclk/app.png differ
diff --git a/apps/patriotclk/custom.html b/apps/patriotclk/custom.html
new file mode 100644
index 000000000..a6fc36abc
--- /dev/null
+++ b/apps/patriotclk/custom.html
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+ Please choose your country's flag:
+
+ Is your flag not here? Please add it here !
+ Preview:
+
+
+
+ Zoom
+
+
+
+ Time at bottom
+
+
+
+
+ Click Upload
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/patriotclk/img/README.md b/apps/patriotclk/img/README.md
new file mode 100644
index 000000000..53c26165c
--- /dev/null
+++ b/apps/patriotclk/img/README.md
@@ -0,0 +1,9 @@
+Flags
+------
+
+These flags come from https://icons8.com/icon/set/flags/color and are 480x480px
+
+If you want to add your own flag ensure it's in the same style and then also list the image file in custom.html in the root directory.
+
+If your flag is listed in https://icons8.com/icon/set/flags/color and you can't download it in the right size, please file an issue and we'll download it with our account.
+
diff --git a/apps/patriotclk/img/icons8-australia-480.png b/apps/patriotclk/img/icons8-australia-480.png
new file mode 100644
index 000000000..edf34cdee
Binary files /dev/null and b/apps/patriotclk/img/icons8-australia-480.png differ
diff --git a/apps/patriotclk/img/icons8-austria-480.png b/apps/patriotclk/img/icons8-austria-480.png
new file mode 100644
index 000000000..8450a8840
Binary files /dev/null and b/apps/patriotclk/img/icons8-austria-480.png differ
diff --git a/apps/patriotclk/img/icons8-belgium-480.png b/apps/patriotclk/img/icons8-belgium-480.png
new file mode 100644
index 000000000..395fef8d1
Binary files /dev/null and b/apps/patriotclk/img/icons8-belgium-480.png differ
diff --git a/apps/patriotclk/img/icons8-brazil-480.png b/apps/patriotclk/img/icons8-brazil-480.png
new file mode 100644
index 000000000..570ee39f9
Binary files /dev/null and b/apps/patriotclk/img/icons8-brazil-480.png differ
diff --git a/apps/patriotclk/img/icons8-canada-480.png b/apps/patriotclk/img/icons8-canada-480.png
new file mode 100644
index 000000000..3d3080768
Binary files /dev/null and b/apps/patriotclk/img/icons8-canada-480.png differ
diff --git a/apps/patriotclk/img/icons8-china-480.png b/apps/patriotclk/img/icons8-china-480.png
new file mode 100644
index 000000000..c3c3faba7
Binary files /dev/null and b/apps/patriotclk/img/icons8-china-480.png differ
diff --git a/apps/patriotclk/img/icons8-denmark-480.png b/apps/patriotclk/img/icons8-denmark-480.png
new file mode 100644
index 000000000..2add9dbce
Binary files /dev/null and b/apps/patriotclk/img/icons8-denmark-480.png differ
diff --git a/apps/patriotclk/img/icons8-england-480.png b/apps/patriotclk/img/icons8-england-480.png
new file mode 100644
index 000000000..5c9a836a6
Binary files /dev/null and b/apps/patriotclk/img/icons8-england-480.png differ
diff --git a/apps/patriotclk/img/icons8-flag-of-europe-480.png b/apps/patriotclk/img/icons8-flag-of-europe-480.png
new file mode 100644
index 000000000..654da87ba
Binary files /dev/null and b/apps/patriotclk/img/icons8-flag-of-europe-480.png differ
diff --git a/apps/patriotclk/img/icons8-france-480.png b/apps/patriotclk/img/icons8-france-480.png
new file mode 100644
index 000000000..e3cb56348
Binary files /dev/null and b/apps/patriotclk/img/icons8-france-480.png differ
diff --git a/apps/patriotclk/img/icons8-germany-480.png b/apps/patriotclk/img/icons8-germany-480.png
new file mode 100644
index 000000000..0f86aa568
Binary files /dev/null and b/apps/patriotclk/img/icons8-germany-480.png differ
diff --git a/apps/patriotclk/img/icons8-great-britain-480.png b/apps/patriotclk/img/icons8-great-britain-480.png
new file mode 100644
index 000000000..0acdcc191
Binary files /dev/null and b/apps/patriotclk/img/icons8-great-britain-480.png differ
diff --git a/apps/patriotclk/img/icons8-greece-480.png b/apps/patriotclk/img/icons8-greece-480.png
new file mode 100644
index 000000000..319cf93cb
Binary files /dev/null and b/apps/patriotclk/img/icons8-greece-480.png differ
diff --git a/apps/patriotclk/img/icons8-hungary-480.png b/apps/patriotclk/img/icons8-hungary-480.png
new file mode 100644
index 000000000..ab838afea
Binary files /dev/null and b/apps/patriotclk/img/icons8-hungary-480.png differ
diff --git a/apps/patriotclk/img/icons8-italy-480.png b/apps/patriotclk/img/icons8-italy-480.png
new file mode 100644
index 000000000..f917cd85a
Binary files /dev/null and b/apps/patriotclk/img/icons8-italy-480.png differ
diff --git a/apps/patriotclk/img/icons8-lgbt-flag-480.png b/apps/patriotclk/img/icons8-lgbt-flag-480.png
new file mode 100644
index 000000000..10f869a0a
Binary files /dev/null and b/apps/patriotclk/img/icons8-lgbt-flag-480.png differ
diff --git a/apps/patriotclk/img/icons8-netherlands-480.png b/apps/patriotclk/img/icons8-netherlands-480.png
new file mode 100644
index 000000000..b271c5448
Binary files /dev/null and b/apps/patriotclk/img/icons8-netherlands-480.png differ
diff --git a/apps/patriotclk/img/icons8-new-zealand-480.png b/apps/patriotclk/img/icons8-new-zealand-480.png
new file mode 100644
index 000000000..fc1ca7ec1
Binary files /dev/null and b/apps/patriotclk/img/icons8-new-zealand-480.png differ
diff --git a/apps/patriotclk/img/icons8-norway-480.png b/apps/patriotclk/img/icons8-norway-480.png
new file mode 100644
index 000000000..270f5af8b
Binary files /dev/null and b/apps/patriotclk/img/icons8-norway-480.png differ
diff --git a/apps/patriotclk/img/icons8-scotland-480.png b/apps/patriotclk/img/icons8-scotland-480.png
new file mode 100644
index 000000000..991652211
Binary files /dev/null and b/apps/patriotclk/img/icons8-scotland-480.png differ
diff --git a/apps/patriotclk/img/icons8-spain-480.png b/apps/patriotclk/img/icons8-spain-480.png
new file mode 100644
index 000000000..19c8dac04
Binary files /dev/null and b/apps/patriotclk/img/icons8-spain-480.png differ
diff --git a/apps/patriotclk/img/icons8-sweden-480.png b/apps/patriotclk/img/icons8-sweden-480.png
new file mode 100644
index 000000000..60f412840
Binary files /dev/null and b/apps/patriotclk/img/icons8-sweden-480.png differ
diff --git a/apps/patriotclk/img/icons8-switzerland-480.png b/apps/patriotclk/img/icons8-switzerland-480.png
new file mode 100644
index 000000000..801ba4776
Binary files /dev/null and b/apps/patriotclk/img/icons8-switzerland-480.png differ
diff --git a/apps/patriotclk/img/icons8-ukraine-480.png b/apps/patriotclk/img/icons8-ukraine-480.png
new file mode 100644
index 000000000..3762c1112
Binary files /dev/null and b/apps/patriotclk/img/icons8-ukraine-480.png differ
diff --git a/apps/patriotclk/img/icons8-usa-480.png b/apps/patriotclk/img/icons8-usa-480.png
new file mode 100644
index 000000000..d6288404e
Binary files /dev/null and b/apps/patriotclk/img/icons8-usa-480.png differ
diff --git a/apps/patriotclk/img/icons8-wales-480.png b/apps/patriotclk/img/icons8-wales-480.png
new file mode 100644
index 000000000..6c2941342
Binary files /dev/null and b/apps/patriotclk/img/icons8-wales-480.png differ
diff --git a/apps/patriotclk/metadata.json b/apps/patriotclk/metadata.json
new file mode 100644
index 000000000..689f1422d
--- /dev/null
+++ b/apps/patriotclk/metadata.json
@@ -0,0 +1,18 @@
+{ "id": "patriotclk",
+ "name": "Patriotic Clock",
+ "shortName":"Patriot",
+ "version":"0.02",
+ "description": "Show your Patriotism with your Country's flag as a clock face (configurable). Swipe down to show widgets and date.",
+ "icon": "app.png",
+ "screenshots": [{"url":"screenshot.png"}],
+ "type": "clock",
+ "tags": "clock,flag",
+ "supports" : ["BANGLEJS2"],
+ "custom": "custom.html",
+ "storage": [
+ {"name":"patriotclk.app.js","url":"app.js"},
+ {"name":"patriotclk.bg.img"},
+ {"name":"patriotclk.opts"},
+ {"name":"patriotclk.img","url":"app-icon.js","evaluate":true}
+ ]
+}
diff --git a/apps/patriotclk/screenshot.png b/apps/patriotclk/screenshot.png
new file mode 100644
index 000000000..1f8b1f5f5
Binary files /dev/null and b/apps/patriotclk/screenshot.png differ
diff --git a/apps/popconlaunch/ChangeLog b/apps/popconlaunch/ChangeLog
index 5560f00bc..8a2124e33 100644
--- a/apps/popconlaunch/ChangeLog
+++ b/apps/popconlaunch/ChangeLog
@@ -1 +1,2 @@
0.01: New App!
+0.02: Trim old entries from the popcon app cache
diff --git a/apps/popconlaunch/README.md b/apps/popconlaunch/README.md
index 2814082a7..18a5354a4 100644
--- a/apps/popconlaunch/README.md
+++ b/apps/popconlaunch/README.md
@@ -3,6 +3,6 @@ Popcon
Display apps sorted by regular use. No config - install the app and all your launchers will sort apps by most popular, based off launch counts within the last month, and then sort them by the most recently launched app.
-:warning: Warning: this app overrides [`Storage.readJSON`], so may slow down your watch when using apps that perform I/O.
+⚠️ Warning: this app overrides [`Storage.readJSON`], so may slow down your watch when using apps that perform I/O.
[`Storage.readJSON`]: https://www.espruino.com/ReferenceBANGLEJS2#l_Storage_readJSON
diff --git a/apps/popconlaunch/boot.js b/apps/popconlaunch/boot.js
index e918fffcf..0080a66f9 100644
--- a/apps/popconlaunch/boot.js
+++ b/apps/popconlaunch/boot.js
@@ -1,6 +1,7 @@
(function () {
var oldRead = require("Storage").readJSON;
- var monthAgo = Date.now() - 1000 * 86400 * 28;
+ var oneMonth = 1000 * 86400 * 28;
+ var monthAgo = Date.now() - oneMonth;
var cache;
var ensureCache = function () {
if (!cache) {
@@ -10,7 +11,19 @@
}
return cache;
};
- var saveCache = function (orderChanged) {
+ var trimCache = function (cache) {
+ var threeMonthsBack = Date.now() - oneMonth * 3;
+ var del = [];
+ for (var k in cache)
+ if (cache[k].last < threeMonthsBack)
+ del.push(k);
+ for (var _i = 0, del_1 = del; _i < del_1.length; _i++) {
+ var k = del_1[_i];
+ delete cache[k];
+ }
+ };
+ var saveCache = function (cache, orderChanged) {
+ trimCache(cache);
require("Storage").writeJSON("popcon.cache.json", cache);
if (orderChanged) {
var info = oldRead("popcon.info", true);
@@ -74,7 +87,7 @@
ent.pop++;
ent.last = Date.now();
var orderChanged = sortCache();
- saveCache(orderChanged);
+ saveCache(cache_2, orderChanged);
}
return oldLoad(src);
};
diff --git a/apps/popconlaunch/boot.ts b/apps/popconlaunch/boot.ts
index 2fa101927..4fe638f75 100644
--- a/apps/popconlaunch/boot.ts
+++ b/apps/popconlaunch/boot.ts
@@ -1,9 +1,6 @@
(() => {
type Timestamp = number;
-
-const oldRead = require("Storage").readJSON;
-const monthAgo = Date.now() - 1000 * 86400 * 28;
-let cache: undefined | {
+type Cache = {
[key: string]: {
sortorder: number,
pop: number, // amount of launches
@@ -11,6 +8,11 @@ let cache: undefined | {
}
};
+const oldRead = require("Storage").readJSON;
+const oneMonth = 1000 * 86400 * 28;
+const monthAgo = Date.now() - oneMonth;
+let cache: undefined | Cache;
+
const ensureCache = (): NonNull => {
if(!cache){
cache = oldRead("popcon.cache.json", true);
@@ -20,7 +22,19 @@ const ensureCache = (): NonNull => {
return cache;
};
-const saveCache = (orderChanged: boolean) => {
+const trimCache = (cache: Cache) => {
+ const threeMonthsBack = Date.now() - oneMonth * 3;
+ const del = [];
+ for(const k in cache)
+ if(cache[k]!.last < threeMonthsBack)
+ del.push(k);
+
+ for(const k of del)
+ delete cache[k];
+};
+
+const saveCache = (cache: Cache, orderChanged: boolean) => {
+ trimCache(cache);
require("Storage").writeJSON("popcon.cache.json", cache);
if(orderChanged){
// ensure launchers reload their caches:
@@ -94,7 +108,7 @@ global.load = (src: string) => {
ent.pop++;
ent.last = Date.now();
const orderChanged = sortCache();
- saveCache(orderChanged);
+ saveCache(cache, orderChanged);
}
return oldLoad(src);
diff --git a/apps/popconlaunch/metadata.json b/apps/popconlaunch/metadata.json
index 0ccc54d9e..1acab2b6c 100644
--- a/apps/popconlaunch/metadata.json
+++ b/apps/popconlaunch/metadata.json
@@ -2,7 +2,7 @@
"id": "popconlaunch",
"name": "Popcon Launcher",
"shortName": "Popcon",
- "version": "0.01",
+ "version": "0.02",
"description": "Launcher modification - your launchers will display your favourite (popular) apps first. Overrides `readJSON`, may slow down your watch",
"readme": "README.md",
"icon": "app.png",
diff --git a/apps/powermanager/ChangeLog b/apps/powermanager/ChangeLog
index d1c288f97..de3fd021c 100644
--- a/apps/powermanager/ChangeLog
+++ b/apps/powermanager/ChangeLog
@@ -9,4 +9,4 @@
0.07: Convert Yes/No On/Off in settings to checkboxes
0.08: Fix the wrapping of intervals/timeouts with parameters
Fix the widget drawing if widgets are hidden and Bangle.setLCDBrightness is called
-0.09: Cache the app-launch info
\ No newline at end of file
+0.09: Accidental version bump
\ No newline at end of file
diff --git a/apps/ratchet_launch/ChangeLog b/apps/ratchet_launch/ChangeLog
index af7f83942..e60ca42d2 100644
--- a/apps/ratchet_launch/ChangeLog
+++ b/apps/ratchet_launch/ChangeLog
@@ -1 +1,2 @@
0.01: Initial release
+0.02: Cache the app-launch info
diff --git a/apps/ratchet_launch/metadata.json b/apps/ratchet_launch/metadata.json
index 45057b0b9..7ebe0c4cd 100644
--- a/apps/ratchet_launch/metadata.json
+++ b/apps/ratchet_launch/metadata.json
@@ -2,7 +2,7 @@
"id": "ratchet_launch",
"name": "Ratchet Launcher",
"shortName": "Ratchet",
- "version": "0.01",
+ "version": "0.02",
"description": "Launcher with discrete scrolling for quicker app selection",
"icon": "app.png",
"type": "launch",
diff --git a/apps/recorder/README.md b/apps/recorder/README.md
index 34955b986..0dd208af5 100644
--- a/apps/recorder/README.md
+++ b/apps/recorder/README.md
@@ -15,10 +15,11 @@ You can record
* **Time** The current time
* **GPS** GPS Latitude, Longitude and Altitude
-* **Steps** Steps counted by the step counter
* **HR** Heart rate and confidence
* **BAT** Battery percentage and voltage
-* **Core** CoreTemp body temperature
+* **Steps** Steps counted by the step counter
+* **Baro** (Bangle.js 2) Using the built-in barometer to record Temperature, Pressure and Altitude
+* **Core** CoreTemp body temperature *if* you have a CoreTemp device and the https://banglejs.com/apps/?id=coretemp app installed
You can then start/stop recording from the Recorder app itself (and as long as widgets are
enabled in the app you're using, you can move to another app and continue recording).
diff --git a/apps/sched/interface.html b/apps/sched/interface.html
index 366e597a2..f1ace7d0c 100644
--- a/apps/sched/interface.html
+++ b/apps/sched/interface.html
@@ -3,7 +3,7 @@
-
+
+
+
3-Bit Color Picker
+
+
Light/Dark
+
+
+
+
Upload
+
+
+
+