diff --git a/apps/advcasio/ChangeLog b/apps/advcasio/ChangeLog index bc4850635..0bca28a1c 100644 --- a/apps/advcasio/ChangeLog +++ b/apps/advcasio/ChangeLog @@ -2,4 +2,5 @@ 0.02: Remove un-needed fonts to improve memory usage 0.03: Tell clock widgets to hide. 0.04: Swipe down to see widgets, step counter now just uses getHealthStatus -0.05: Report latest HRM rather than HRM 10 minutes ago (fix #2395) \ No newline at end of file +0.05: Report latest HRM rather than HRM 10 minutes ago (fix #2395) +0.06: Use watch temperature \ No newline at end of file diff --git a/apps/advcasio/README.md b/apps/advcasio/README.md index 3ce771497..bce3f71d7 100644 --- a/apps/advcasio/README.md +++ b/apps/advcasio/README.md @@ -3,8 +3,7 @@ An over-engineered clock inspired by Casio watches.
-It has a dedicated timer, a scratchpad and can display the weather condition 4 days ahead.
-It uses a custom web app to update its content.
+It has a dedicated timer, a scratchpad and displays the current temperature.
Forked from the awesome Cassio Watch.
## Todo @@ -21,7 +20,7 @@ Forked from the awesome Cassio Watch.
- Footsteps - Battery - Simple Timer embedded -- Weather forecast (7 days) +- Current temperature - Scratchpad ## Screenshots @@ -36,14 +35,6 @@ Web interface to update weather & scratchpad
## Usage -### How to update the tasks list / weather -- you will need a free openweathermap.org api key. -- go to https://dotgreg.github.io/advCasioBangleClock/ - - Alternatively you can install it on your own server/heroku/service/github pages, the web-app code is here -- fill the location and the api key (it will be saved on your browser, no need to do it each time) -- edit the scratchpad with what you want -- click on sync -- reload your clock! ### How to start/stop the timer - swipe up : add time (+5min) diff --git a/apps/advcasio/app.js b/apps/advcasio/app.js index d951da4cc..796fac2a7 100644 --- a/apps/advcasio/app.js +++ b/apps/advcasio/app.js @@ -88,9 +88,9 @@ function drawRocket() { function getTemperature(){ try { - var weatherJson = storage.readJSON('weather.json'); - var weather = weatherJson.weather; - return Math.round(weather.temp-273.15); + var temperature = E.getTemperature() + var formatted = require("locale").temp(temperature).replace(/[^\d-]/g, ''); + return formatted; } catch(ex) { print(ex) diff --git a/apps/advcasio/metadata.json b/apps/advcasio/metadata.json index 32f5de7d3..e3df73555 100644 --- a/apps/advcasio/metadata.json +++ b/apps/advcasio/metadata.json @@ -1,8 +1,8 @@ { "id": "advcasio", "name": "Advanced Casio Clock", "shortName":"advcasio", - "version":"0.05", - "description": "An over-engineered clock inspired by Casio watches. It has a 4 days weather, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.", + "version":"0.06", + "description": "An over-engineered clock inspired by Casio watches. It has current temperature, a timer using swipe and a scratchpad. Can be updated using a dedicated webapp.", "icon": "app.png", "tags": "clock", "type": "clock", @@ -18,8 +18,5 @@ "storage": [ {"name":"advcasio.app.js","url":"app.js"}, {"name":"advcasio.img","url":"app-icon.js","evaluate":true} - ], - "data": [ - { "name": "advcasio.data.json", "url": "data.json", "storageFile": true } ] } diff --git a/apps/android/README.md b/apps/android/README.md index c76e6e528..f322e6a4e 100644 --- a/apps/android/README.md +++ b/apps/android/README.md @@ -44,6 +44,10 @@ The boot code also provides some useful functions: * `id` - a custom (string) ID * `timeout` - a timeout for the request in milliseconds (default 30000ms) * `xpath` an xPath query to run on the request (but right now the URL requested must be XML - HTML is rarely XML compliant) + * `return` for xpath, if not specified, one result is returned. If `return:"array"` an array of results is returned. + * `method` HTTP method (default is `get`) - `get/post/head/put/patch/delete` + * `body` the body of the HTTP request + * `headers` an object of headers, eg `{HeaderOne : "headercontents"}` eg: diff --git a/apps/ios/ChangeLog b/apps/ios/ChangeLog index 86ce9ff4e..904ad1f7d 100644 --- a/apps/ios/ChangeLog +++ b/apps/ios/ChangeLog @@ -15,4 +15,5 @@ Allow negative/positive actions to pass through to message GUI 0.15: Enable calendar and weather updates via custom notifications (via shortcuts app) 0.16: Always request Current Time service from iOS -0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font) \ No newline at end of file +0.17: Default to passing full UTF8 strings into messages app (which can now process them with an international font) +0.18: Fix UTF8 conversion (check for `font` library, not `fonts`) \ No newline at end of file diff --git a/apps/ios/boot.js b/apps/ios/boot.js index dd0cca511..fe9cde77d 100644 --- a/apps/ios/boot.js +++ b/apps/ios/boot.js @@ -298,7 +298,7 @@ E.emit("ANCS", { NRF.ctsGetTime().then(ctsUpdate, function(){ /* */ }) E.on('CTS',ctsUpdate); } - if (settings.no_utf8 || !require("Storage").read("fonts")) { + if (settings.no_utf8 || !require("Storage").read("font")) { // if UTF8 disabled or there is no fonts lib, convert UTF8 to ISO8859-1 let unicodeRemap = { '2019':"'", diff --git a/apps/ios/metadata.json b/apps/ios/metadata.json index c3427d3b8..6efcac15e 100644 --- a/apps/ios/metadata.json +++ b/apps/ios/metadata.json @@ -1,7 +1,7 @@ { "id": "ios", "name": "iOS Integration", - "version": "0.17", + "version": "0.18", "description": "Display notifications/music/etc from iOS devices", "icon": "app.png", "tags": "tool,system,ios,apple,messages,notifications", diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js index 83ab5cc02..d6fd6510d 100644 --- a/apps/lint_exemptions.js +++ b/apps/lint_exemptions.js @@ -59,13 +59,6 @@ module.exports = { "no-unused-vars" ] }, - "sleepphasealarm/app.js": { - "hash": "d234fea5d711ae5a149879e53b28bc9002860c6b6a75285e1fc04093fe400a88", - "rules": [ - "no-unused-vars", - "no-undef" - ] - }, "sleeplog/settings.js": { "hash": "bd5e3e1382321df6682ef1cb718b0e15ab355422bef77278eb086f213f643021", "rules": [ @@ -582,12 +575,6 @@ module.exports = { "no-undef" ] }, - "locale/locales.js": { - "hash": "bf2fd659e673b34a1ffa98c7ae7ca89de86a4ff9f823244d028e85bc465ed3c7", - "rules": [ - "no-unused-vars" - ] - }, "sleeplog/lib.js": { "hash": "755e0d4c02b92181281fd6990df39c9446c73ff896b50b64d7e14cb1c0188556", "rules": [ diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 9357ccef4..9cb4476c2 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -19,4 +19,5 @@ 0.16: Remove global variables that used RAM Add second 'dp' argument for decimal places in distance/speed/temp (fix #1523) 0.17: Fix regression where long month names were 'undefined' (fix #1641) +0.18: Fix lint warnings, change anv->janv for fr_BE and fr_CH : Deprecate currency information diff --git a/apps/locale/locales.js b/apps/locale/locales.js index ff5695c5f..11af6c1d8 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -1,4 +1,8 @@ /* jshint esversion: 6 */ +/* exported distanceUnits */ +/* exported speedUnits */ +/* exported codePages */ +/* exported locales */ const distanceUnits = { // how many meters per X? "m": 1, "ft": 0.3048, @@ -59,6 +63,14 @@ timePattern / datePattern: %S second (00..60) %p locale's equivalent of either AM or PM; blank if not known %P like %p, but lower case + + +in locales: + + abmonth: short months (must be <5 chars, ideally 3) + month: normal month names + abday: short days (must be <5 chars, ideally 3) + day: normal day names */ var locales = { @@ -413,7 +425,7 @@ var locales = { ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 - abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", + abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", @@ -461,7 +473,7 @@ var locales = { ampm: { 0: "AM", 1: "PM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 - abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", + abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", @@ -719,7 +731,7 @@ var locales = { timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" }, abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.", - month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octobre,novembre,desembre", + month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octubre,novembre,desembre", abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.", day: "diumenge,dilluns,dimarts,dimecres,dijous,divendres,dissabte", trans: { yes: "sí", Yes: "Sí", no: "no", No: "No", ok: "d'acord", on: "on", off: "off", diff --git a/apps/locale/metadata.json b/apps/locale/metadata.json index 54ad64e80..cb45f0622 100644 --- a/apps/locale/metadata.json +++ b/apps/locale/metadata.json @@ -1,7 +1,7 @@ { "id": "locale", "name": "Languages", - "version": "0.17", + "version": "0.18", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", diff --git a/apps/rep/app.ts b/apps/rep/app.ts index d1dd67179..14fb45482 100644 --- a/apps/rep/app.ts +++ b/apps/rep/app.ts @@ -196,7 +196,7 @@ const layout = new L({ ] } ] -}, {lazy: true}); +} as const, {lazy: true}); class State { paused: boolean = true; @@ -248,7 +248,7 @@ class State { } } -const repToLabel = (i: number, id: string) => { +const repToLabel = (i: number, id: "cur" | "next") => { const rep = reps[i]; if(rep) layout[`${id}_name`]!.label = `${rep.label} / ${msToMinSec(rep.dur)}`; @@ -256,7 +256,7 @@ const repToLabel = (i: number, id: string) => { emptyLabel(id); }; -const emptyLabel = (id: string) => { +const emptyLabel = (id: "cur" | "next") => { layout[`${id}_name`]!.label = " / 0m"; }; diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index d6e3cb30b..7dfd96bdd 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -19,3 +19,5 @@ Add plot logged data to settings 0.15: Convert Yes/No On/Off in settings to checkboxes 0.16: Fix Keep alarm enabled inverted settings +0.17: Fix handle dates saved as object with milliseconds +0.18: Fix lint warnings diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 25ca7e781..a9580fd47 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -105,8 +105,8 @@ function drawApp() { } const period = drawSeconds ? 1000 : 60000; - if (this.drawTimeTimeout !== undefined) { - clearTimeout(this.drawTimeTimeout); + if (drawTimeTimeout !== undefined) { + clearTimeout(drawTimeTimeout); } drawTimeTimeout = setTimeout(()=>{ drawTimeTimeout = undefined; @@ -136,7 +136,7 @@ function buzz() { } function addLog(time, type) { - logs.push({time: time, type: type}); + logs.push({time: time.toISOString(), type: type}); if (logs.length > 1) { // Do not write if there is only one state require("Storage").writeJSON(CONFIGFILE, config); } @@ -156,7 +156,7 @@ if (nextAlarmDate !== undefined) { // minimum alert 30 minutes early minAlarm.setTime(nextAlarmDate.getTime() - (30*60*1000)); - run = () => { + let run = () => { layout.state.label = /*LANG*/"Start"; layout.render(); Bangle.setOptions({powerSave: false}); // do not dynamically change accelerometer poll interval diff --git a/apps/sleepphasealarm/interface.html b/apps/sleepphasealarm/interface.html index 9b2004904..da73ed9c4 100644 --- a/apps/sleepphasealarm/interface.html +++ b/apps/sleepphasealarm/interface.html @@ -35,7 +35,7 @@ function getData() { logs.forEach((log, i) => { const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time; if (timeStr) { - const date = new Date(timeStr); + const date = new Date(typeof timeStr === 'string' ? timeStr : timeStr.ms); let option = document.createElement("option"); option.text = date.toLocaleDateString(); option.value = i; @@ -89,10 +89,10 @@ function getData() { select.onchange = () => { const log = logs[select.value]; - chart.data.labels = log.map(entry => new Date(entry.time)); + chart.data.labels = log.map(entry => new Date(typeof entry.time === 'string' ? entry.time : entry.time.ms)); chart.data.datasets[0].data = log.map(entry => yTicks.indexOf(entry.type)); const timeStr = log.filter(entry => entry.type === "alarm")[0]?.time; - chart.data.datasets[0].label = new Date(timeStr).toLocaleDateString(); + chart.data.datasets[0].label = new Date(typeof timeStr === 'string' ? timeStr : timeStr.ms).toLocaleDateString(); chart.update(); } }); diff --git a/apps/sleepphasealarm/metadata.json b/apps/sleepphasealarm/metadata.json index aa69694ab..2ba003cf7 100644 --- a/apps/sleepphasealarm/metadata.json +++ b/apps/sleepphasealarm/metadata.json @@ -2,7 +2,7 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.16", + "version": "0.18", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "tool,alarm", diff --git a/apps/sleepphasealarm/settings.js b/apps/sleepphasealarm/settings.js index e72d95e7f..f0661fc78 100644 --- a/apps/sleepphasealarm/settings.js +++ b/apps/sleepphasealarm/settings.js @@ -16,8 +16,8 @@ function draw(log) { const step = 10*60*1000; // resolution 10min const yTicks = ["sleep", "awake", "alarm"]; - const starttime = new Date(log[0].time); - const endtime = new Date(log[log.length-1].time); + const starttime = dateFromJson(log[0].time); + const endtime = dateFromJson(log[log.length-1].time); let logidx = 0; let curtime = starttime; @@ -29,7 +29,7 @@ if (logtime === undefined || curtime > logtime) { curval = yTicks.indexOf(log[logidx].type); logidx++; - logtime = new Date(log[logidx].time); + logtime = dateFromJson(log[logidx].time); } data[i++] = curval; @@ -70,8 +70,8 @@ const logs = config.logs.filter(log => log != null && log.filter(entry => entry.type === "alarm").length > 0); logs.sort(function(a, b) { // sort by alarm date desc - const adate = new Date(a.filter(entry => entry.type === "alarm")[0].time); - const bdate = new Date(b.filter(entry => entry.type === "alarm")[0].time); + const adate = dateFromJson(a.filter(entry => entry.type === "alarm")[0].time); + const bdate = dateFromJson(b.filter(entry => entry.type === "alarm")[0].time); return bdate - adate; }); @@ -79,12 +79,16 @@ menu[""] = { title: /*LANG*/"Select day" }; menu["< Back"] = () => settingsmenu(); logs.forEach((log, i) => { - const date = new Date(log.filter(entry => entry.type === "alarm")[0].time); + const date = dateFromJson(log.filter(entry => entry.type === "alarm")[0].time); menu[require("locale").date(date, 1)] = () => { E.showMenu(); draw(log); }; }); E.showMenu(menu); } + function dateFromJson(o) { + return new Date(typeof o === 'string' ? o : o.ms); + } + function settingsmenu() { // Show the menu E.showMenu({ diff --git a/core b/core index 0222d3c5a..2603ca6ff 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 0222d3c5ac608a1b842ffc1f1f79e19276d648fe +Subproject commit 2603ca6fff12cefc2d0c0e7665a669b032a78e4e diff --git a/typescript/types/layout.d.ts b/typescript/types/layout.d.ts index 167ede29d..55ddd7135 100644 --- a/typescript/types/layout.d.ts +++ b/typescript/types/layout.d.ts @@ -1,10 +1,13 @@ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; +type UnionToIntersection = + (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never + type ExtractIds = [Depth] extends [never] ? never - : (T extends { id: infer Id extends string } - ? { [k in Id]: T } + : (T extends { id?: infer Id extends string } + ? { [k in Id]: { -readonly [P in keyof T]: T[P] extends string ? string : T[P] } } : never) | ( @@ -15,7 +18,7 @@ type ExtractIds = declare module Layout { type Layouter = - ExtractIds + UnionToIntersection> & { // these actually change T @@ -31,6 +34,7 @@ declare module Layout { setUI(): void; }; + // Note: you must use new Layout({...} as const) to have ids inferred var Layout: { new ( hier: T,