Merge branch 'master' into nbDateOrder
commit
72efc0a3b7
|
|
@ -16,3 +16,5 @@
|
||||||
0.15: Fix hour/minute wrapping code for new menu system
|
0.15: Fix hour/minute wrapping code for new menu system
|
||||||
0.16: Adding alarm library
|
0.16: Adding alarm library
|
||||||
0.17: Moving alarm internals to 'sched' library
|
0.17: Moving alarm internals to 'sched' library
|
||||||
|
0.18: Cope with >1 identical alarm at once (#1667)
|
||||||
|
0.19: Ensure rescheduled alarms that already fired have 'last' reset
|
||||||
|
|
|
||||||
|
|
@ -45,12 +45,22 @@ function showMainMenu() {
|
||||||
/*LANG*/'New Timer': ()=>editTimer(-1)
|
/*LANG*/'New Timer': ()=>editTimer(-1)
|
||||||
};
|
};
|
||||||
alarms.forEach((alarm,idx)=>{
|
alarms.forEach((alarm,idx)=>{
|
||||||
var txt; // a leading space is currently required (JS error in Espruino 2v12)
|
var type,txt; // a leading space is currently required (JS error in Espruino 2v12)
|
||||||
if (alarm.timer)
|
if (alarm.timer) {
|
||||||
txt = /*LANG*/"Timer"+" "+formatTime(alarm.timer);
|
type = /*LANG*/"Timer";
|
||||||
else
|
txt = " "+formatTime(alarm.timer);
|
||||||
txt = /*LANG*/"Alarm"+" "+formatTime(alarm.t);
|
} else {
|
||||||
|
type = /*LANG*/"Alarm";
|
||||||
|
txt = " "+formatTime(alarm.t);
|
||||||
|
}
|
||||||
if (alarm.rp) txt += "\0"+atob("FBaBAAABgAAcAAHn//////wAHsABzAAYwAAMAADAAAAAAwAAMAADGAAzgAN4AD//////54AAOAABgAA=");
|
if (alarm.rp) txt += "\0"+atob("FBaBAAABgAAcAAHn//////wAHsABzAAYwAAMAADAAAAAAwAAMAADGAAzgAN4AD//////54AAOAABgAA=");
|
||||||
|
// rename duplicate alarms
|
||||||
|
if (menu[type+txt]) {
|
||||||
|
var n = 2;
|
||||||
|
while (menu[type+" "+n+txt]) n++;
|
||||||
|
txt = type+" "+n+txt;
|
||||||
|
} else txt = type+txt;
|
||||||
|
// add to menu
|
||||||
menu[txt] = {
|
menu[txt] = {
|
||||||
value : "\0"+atob(alarm.on?"EhKBAH//v/////////////5//x//j//H+eP+Mf/A//h//z//////////3//g":"EhKBAH//v//8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA///3//g"),
|
value : "\0"+atob(alarm.on?"EhKBAH//v/////////////5//x//j//H+eP+Mf/A//h//z//////////3//g":"EhKBAH//v//8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA8AA///3//g"),
|
||||||
onchange : function() {
|
onchange : function() {
|
||||||
|
|
@ -84,7 +94,7 @@ function editAlarm(alarmIndex, alarm) {
|
||||||
var a = {
|
var a = {
|
||||||
t : 12*3600000, // 12 o clock default
|
t : 12*3600000, // 12 o clock default
|
||||||
on : true,
|
on : true,
|
||||||
rp : true,
|
rp : false, // repeat not the default
|
||||||
as : false,
|
as : false,
|
||||||
dow : 0b1111111,
|
dow : 0b1111111,
|
||||||
last : 0,
|
last : 0,
|
||||||
|
|
@ -128,8 +138,7 @@ function editAlarm(alarmIndex, alarm) {
|
||||||
};
|
};
|
||||||
menu[/*LANG*/"Save"] = function() {
|
menu[/*LANG*/"Save"] = function() {
|
||||||
a.t = encodeTime(t);
|
a.t = encodeTime(t);
|
||||||
if (a.t < getCurrentTime())
|
a.last = (a.t < getCurrentTime()) ? (new Date()).getDate() : 0;
|
||||||
a.day = (new Date()).getDate();
|
|
||||||
if (newAlarm) alarms.push(a);
|
if (newAlarm) alarms.push(a);
|
||||||
else alarms[alarmIndex] = a;
|
else alarms[alarmIndex] = a;
|
||||||
saveAndReload();
|
saveAndReload();
|
||||||
|
|
@ -181,6 +190,7 @@ function editTimer(alarmIndex, alarm) {
|
||||||
menu[/*LANG*/"Save"] = function() {
|
menu[/*LANG*/"Save"] = function() {
|
||||||
a.timer = encodeTime(t);
|
a.timer = encodeTime(t);
|
||||||
a.t = getCurrentTime() + a.timer;
|
a.t = getCurrentTime() + a.timer;
|
||||||
|
a.last = 0;
|
||||||
if (newAlarm) alarms.push(a);
|
if (newAlarm) alarms.push(a);
|
||||||
else alarms[alarmIndex] = a;
|
else alarms[alarmIndex] = a;
|
||||||
saveAndReload();
|
saveAndReload();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "alarm",
|
"id": "alarm",
|
||||||
"name": "Alarm & Timer",
|
"name": "Alarm & Timer",
|
||||||
"shortName": "Alarms",
|
"shortName": "Alarms",
|
||||||
"version": "0.17",
|
"version": "0.19",
|
||||||
"description": "Set alarms and timers on your Bangle",
|
"description": "Set alarms and timers on your Bangle",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,alarm,widget",
|
"tags": "tool,alarm,widget",
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New app!
|
0.01: New app!
|
||||||
0.02: Fix bug with regenerating index, fix bug in word lookups
|
0.02: Fix bug with regenerating index, fix bug in word lookups
|
||||||
|
0.03: Improve word search performance
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,7 @@ least once and yields an additional 7 points. Each game contains at least one pa
|
||||||
The game uses an internal dictionary consisting of a newline separated list of English words ('bee.words', using the '2of12inf' word list).
|
The game uses an internal dictionary consisting of a newline separated list of English words ('bee.words', using the '2of12inf' word list).
|
||||||
The dictionary is fairly large (~700kB of flash space) and thus requires appropriate space on the watch and will make installing the app somewhat
|
The dictionary is fairly large (~700kB of flash space) and thus requires appropriate space on the watch and will make installing the app somewhat
|
||||||
slow. Because of its size it cannot be compressed (heatshrink needs to hold the compressed/uncompressed data in memory).
|
slow. Because of its size it cannot be compressed (heatshrink needs to hold the compressed/uncompressed data in memory).
|
||||||
In order to make checking the validity of a guessed word faster an index file ('bee_lindex.json') is installed with
|
This file can be replaced with a custom dictionary, an ASCII file containing a newline-separated (single "\n", not DOS-style "\r\n") alphabetically
|
||||||
the app that facilitates faster word lookups. This index file is specific to the dictionary file used. If one were to
|
sorted (sorting is important for the word lookup algorithm) list of words.
|
||||||
replace the dictionary file with a different version (e.g. a different language) the index file has to be regenerated. The easiest
|
|
||||||
way to do so is to delete (via the Web IDE or the fileman app on the watch) the file 'bee_lindex.json' - it will be regenerated (and saved,
|
|
||||||
i.e. it only happens once) on app startup automatically, a process that takes roughly 30 seconds.
|
|
||||||
|
|
||||||

|

|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
const S = require("Storage");
|
const S = require("Storage");
|
||||||
|
const words = S.read("bee.words");
|
||||||
var letters = [];
|
var letters = [];
|
||||||
var letterIdx = [];
|
|
||||||
|
|
||||||
var centers = [];
|
var centers = [];
|
||||||
|
|
||||||
|
|
@ -12,29 +12,17 @@ var score = 0;
|
||||||
|
|
||||||
var intervalID = -1;
|
var intervalID = -1;
|
||||||
|
|
||||||
function prepareLetterIdx () {
|
function biSearch(w, ws, start, end, count) {
|
||||||
"compile"
|
"compile"
|
||||||
var li = [0];
|
if (start>end-w.legnth || count--<=0) return ws.substr(start, end-start).indexOf("\n"+w+"\n");
|
||||||
if (S.read("bee_lindex.json")!==undefined) li = S.readJSON("bee_lindex.json"); // check for cached index
|
var mid = (end+start)>>1;
|
||||||
else {
|
if (ws[mid-1]==="\n") --mid;
|
||||||
for (var i=1; i<26; ++i) {
|
else while (mid<end && ws[mid]!=="\n") mid++;
|
||||||
var prefix = String.fromCharCode(97+i%26);
|
var i = 0;
|
||||||
console.log(prefix);
|
while (i<w.length && ws[mid+i+1]==w[i]) ++i;
|
||||||
li.push(S.read('bee.words').indexOf("\n"+prefix, li[i-1])+1);
|
if (i==w.length && ws[mid+i+1]==="\n") return mid+1;
|
||||||
}
|
if (i==w.length || w[i]<ws[mid+i+1]) return biSearch(w, ws, start, mid+1, count);
|
||||||
li.push(S.read('bee.words').length);
|
if (w[i]>ws[mid+i+1]) return biSearch(w, ws, mid+1, end, count);
|
||||||
S.writeJSON("bee_lindex.json", li);
|
|
||||||
}
|
|
||||||
for (var i=0; i<26; ++i) letterIdx[i] = S.read("bee.words", li[i], li[i+1]-li[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function findWord (w) {
|
|
||||||
"compile"
|
|
||||||
var ci = w.charCodeAt(0)-97;
|
|
||||||
var f = letterIdx[ci].indexOf("\n"+w+"\n");
|
|
||||||
if (f>=0) return true;
|
|
||||||
if (letterIdx[ci].substr(0, w.length)==w) return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPangram(w) {
|
function isPangram(w) {
|
||||||
|
|
@ -46,7 +34,7 @@ function isPangram(w) {
|
||||||
function checkWord (w) {
|
function checkWord (w) {
|
||||||
if (w.indexOf(String.fromCharCode(97+letters[0]))==-1) return false; // does it contain central letter?
|
if (w.indexOf(String.fromCharCode(97+letters[0]))==-1) return false; // does it contain central letter?
|
||||||
if (foundWords.indexOf(w)>=0) return false; // already found
|
if (foundWords.indexOf(w)>=0) return false; // already found
|
||||||
if (findWord(w)) {
|
if (biSearch(w, words, 0, words.length, 20)>-1) {
|
||||||
foundWords.push(w);
|
foundWords.push(w);
|
||||||
foundWords.sort();
|
foundWords.sort();
|
||||||
if (w.length==4) score++;
|
if (w.length==4) score++;
|
||||||
|
|
@ -93,13 +81,12 @@ function pickLetters() {
|
||||||
var ltrs = "";
|
var ltrs = "";
|
||||||
while (ltrs.length!==7) {
|
while (ltrs.length!==7) {
|
||||||
ltrs = [];
|
ltrs = [];
|
||||||
var j = Math.floor(26*Math.random());
|
var i = Math.floor((words.length-10)*Math.random());
|
||||||
var i = Math.floor((letterIdx[j].length-10)*Math.random());
|
while (words[i]!="\n" && i<words.length) ++i;
|
||||||
while (letterIdx[j][i]!="\n" && i<letterIdx[j].length) ++i;
|
if (i<words.length-1) {
|
||||||
if (i<letterIdx[j].length-1) {
|
|
||||||
++i;
|
++i;
|
||||||
while (letterIdx[j][i]!=="\n") {
|
while (words[i]!=="\n") {
|
||||||
var c = letterIdx[j][i];
|
var c = words[i];
|
||||||
if (ltrs.indexOf(c)===-1) ltrs += c;
|
if (ltrs.indexOf(c)===-1) ltrs += c;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
@ -187,7 +174,6 @@ function showWordList() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareLetterIdx();
|
|
||||||
pickLetters();
|
pickLetters();
|
||||||
drawHive();
|
drawHive();
|
||||||
drawScore();
|
drawScore();
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
[0,41048,80445,152390,198606,228714,257919,279071,303726,337982,343582,348026,367246,404452,419780,438696,496250,499697,544600,624304,659085,680996,691270,708186,708341,709916,710883]
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "Bee",
|
"name": "Bee",
|
||||||
"shortName":"Bee",
|
"shortName":"Bee",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"version":"0.02",
|
"version":"0.03",
|
||||||
"description": "Spelling bee",
|
"description": "Spelling bee",
|
||||||
"supports" : ["BANGLEJS2"],
|
"supports" : ["BANGLEJS2"],
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"bee.app.js","url":"bee.app.js"},
|
{"name":"bee.app.js","url":"bee.app.js"},
|
||||||
{"name":"bee.words","url":"bee_words_2of12"},
|
{"name":"bee.words","url":"bee_words_2of12"},
|
||||||
{"name":"bee_lindex.json","url":"bee_lindex.json"},
|
|
||||||
{"name":"bee.img","url":"app-icon.js","evaluate":true}
|
{"name":"bee.img","url":"app-icon.js","evaluate":true}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,29 @@
|
||||||
],
|
],
|
||||||
"text_scale":3.5
|
"text_scale":3.5
|
||||||
},
|
},
|
||||||
|
"nn_NO":{
|
||||||
|
"hours":[
|
||||||
|
"tolv", "eitt", "to", "tre", "fire", "fem",
|
||||||
|
"seks", "sju", "åtte", "ni", "ti", "elleve",
|
||||||
|
"tolv", "eitt", "to", "tre", "fire", "fem",
|
||||||
|
"seks", "sju", "åtte", "ni", "ti", "elleve"
|
||||||
|
],
|
||||||
|
"minutes":[
|
||||||
|
"klokka er *$1",
|
||||||
|
"fem over *$1",
|
||||||
|
"ti over *$1",
|
||||||
|
"kvart over *$1",
|
||||||
|
"ti på halv *$2",
|
||||||
|
"fem på halv *$2",
|
||||||
|
"halv *$2",
|
||||||
|
"fem over halv *$2",
|
||||||
|
"ti over halv *$2",
|
||||||
|
"kvart på *$2",
|
||||||
|
"ti på *$2",
|
||||||
|
"fem på *$2"
|
||||||
|
],
|
||||||
|
"text_scale":3.5
|
||||||
|
},
|
||||||
"sv_SE":{
|
"sv_SE":{
|
||||||
"hours":[
|
"hours":[
|
||||||
"tolv", "ett", "två", "tre", "fyra", "fem",
|
"tolv", "ett", "två", "tre", "fyra", "fem",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
<p>Then click <button id="upload" class="btn btn-primary">Upload</button></p>
|
<p>Then click <button id="upload" class="btn btn-primary">Upload</button></p>
|
||||||
|
|
||||||
<script src="../../core/lib/customize.js"></script>
|
<script src="../../core/lib/customize.js"></script>
|
||||||
|
<script src="../../core/js/utils.js"></script>
|
||||||
<script src="locales.js" charset="utf-8"></script>
|
<script src="locales.js" charset="utf-8"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -59,7 +60,7 @@ exports = { name : "en_GB", currencySym:"£",
|
||||||
/*else if (chCode<256) // it's non-ascii, but <256 - just escape it
|
/*else if (chCode<256) // it's non-ascii, but <256 - just escape it
|
||||||
n = chCode;*/
|
n = chCode;*/
|
||||||
else {
|
else {
|
||||||
if (charFallbacks[ch]) return charFallbacks[ch];
|
if (CODEPAGE_CONVERSIONS[ch]) return CODEPAGE_CONVERSIONS[ch];
|
||||||
console.error(`Locale ${lang}: Character ${ch} (${chCode}) is not in Code Page ${codePage.name}`);
|
console.error(`Locale ${lang}: Character ${ch} (${chCode}) is not in Code Page ${codePage.name}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,36 +34,8 @@ const codePages = {
|
||||||
`.replace(/[ \n]/g,"")
|
`.replace(/[ \n]/g,"")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
/* When it's not in the codepage, try and use
|
|
||||||
these conversions */
|
// charFallbacks is now in core/js/utils.js as CODEPAGE_CONVERSIONS
|
||||||
const charFallbacks = {
|
|
||||||
"ą":"a",
|
|
||||||
"ā":"a",
|
|
||||||
"å":"a",
|
|
||||||
"č":"c",
|
|
||||||
"ć":"c",
|
|
||||||
"ě":"e",
|
|
||||||
"ę":"e",
|
|
||||||
"ē":"e",
|
|
||||||
"æ":"e",
|
|
||||||
"ģ":"g",
|
|
||||||
"i":"ī",
|
|
||||||
"ķ":"k",
|
|
||||||
"ļ":"l",
|
|
||||||
"ł":"l",
|
|
||||||
"ń":"n",
|
|
||||||
"ņ":"n",
|
|
||||||
"ő":"o",
|
|
||||||
"ó":"o",
|
|
||||||
"ø":"o",
|
|
||||||
"ř":"r",
|
|
||||||
"ś":"s",
|
|
||||||
"š":"s",
|
|
||||||
"ū":"u",
|
|
||||||
"ż":"z",
|
|
||||||
"ź":"z",
|
|
||||||
"ž":"z",
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
timePattern / datePattern:
|
timePattern / datePattern:
|
||||||
|
|
@ -594,7 +566,7 @@ var locales = {
|
||||||
day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado",
|
day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado",
|
||||||
trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" }
|
trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" }
|
||||||
},
|
},
|
||||||
"cs_CZ": { // THIS NEVER WORKED PROPERLY - many chars are not in the ISO8859-1 codepage and we use charFallbacks
|
"cs_CZ": { // THIS NEVER WORKED PROPERLY - many chars are not in the ISO8859-1 codepage and we use CODEPAGE_CONVERSIONS
|
||||||
lang: "cs_CZ",
|
lang: "cs_CZ",
|
||||||
decimal_point: ",",
|
decimal_point: ",",
|
||||||
thousands_sep: " ",
|
thousands_sep: " ",
|
||||||
|
|
@ -684,8 +656,26 @@ var locales = {
|
||||||
day: "Pirmdiena,Otrdiena,Trešdiena,Ceturtdiena,Piektdiena,Sestdiena,Svētdiena",
|
day: "Pirmdiena,Otrdiena,Trešdiena,Ceturtdiena,Piektdiena,Sestdiena,Svētdiena",
|
||||||
trans: { yes: "jā", Yes: "Jā", no: "nē", No: "Nē", ok: "labi", on: "Ieslēgt", off: "Izslēgt", "< Back": "< Atpakaļ" }
|
trans: { yes: "jā", Yes: "Jā", no: "nē", No: "Nē", ok: "labi", on: "Ieslēgt", off: "Izslēgt", "< Back": "< Atpakaļ" }
|
||||||
},
|
},
|
||||||
"no_NB": { // Using charfallbacks
|
"nn_NO": { // Using charfallbacks
|
||||||
lang: "no_NB",
|
lang: "nn_NO",
|
||||||
|
decimal_point: ",",
|
||||||
|
thousands_sep: " ",
|
||||||
|
currency_symbol: "kr",
|
||||||
|
int_curr_symbol: "NOK",
|
||||||
|
speed: "kmh",
|
||||||
|
distance: { 0: "m", 1: "km" },
|
||||||
|
temperature: "°C",
|
||||||
|
ampm: { 0: "", 1: "" },
|
||||||
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
|
datePattern: { 0: "%d. %b %Y", "1": "%d.%m.%Y" }, // 1. Mar 2020 // 01.03.20
|
||||||
|
abmonth: "Jan,Feb,Mar,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Des",
|
||||||
|
month: "Januar,Februar,Mars,April,Mai,Juni,Juli,August,September,Oktober,November,Desember",
|
||||||
|
abday: "Su,Må,Ty,On,To,Fr,La",
|
||||||
|
day: "Sundag,Måndag,Tysdag,Onsdag,Torsdag,Fredag,Laurdag",
|
||||||
|
trans: { yes: "ja", Yes: "Ja", no: "nei", No: "Nei", ok: "ok", on: "på", off: "av", "< Back": "< Tilbake", "Delete": "Slett", "Mark Unread": "Merk som ulesen" }
|
||||||
|
},
|
||||||
|
"nb_NO": { // Using charfallbacks
|
||||||
|
lang: "nb_NO",
|
||||||
decimal_point: ",",
|
decimal_point: ",",
|
||||||
thousands_sep: " ",
|
thousands_sep: " ",
|
||||||
currency_symbol: "kr",
|
currency_symbol: "kr",
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,4 @@
|
||||||
0.28: Option to auto-unlock the watch when a new message arrives
|
0.28: Option to auto-unlock the watch when a new message arrives
|
||||||
0.29: Fix message list overwrites on Bangle.js 1 (fix #1642)
|
0.29: Fix message list overwrites on Bangle.js 1 (fix #1642)
|
||||||
0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel)
|
0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel)
|
||||||
|
0.31: Option to disable icon flashing
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ is chosen if there isn't much message text, but this specifies the smallest the
|
||||||
it starts getting clipped.
|
it starts getting clipped.
|
||||||
* `Auto-Open Music` - Should the app automatically open when the phone starts playing music?
|
* `Auto-Open Music` - Should the app automatically open when the phone starts playing music?
|
||||||
* `Unlock Watch` - Should the app unlock the watch when a new message arrives, so you can touch the buttons at the bottom of the app?
|
* `Unlock Watch` - Should the app unlock the watch when a new message arrives, so you can touch the buttons at the bottom of the app?
|
||||||
|
* `Flash Icon` - Toggle flashing of the widget icon.
|
||||||
|
|
||||||
## New Messages
|
## New Messages
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "messages",
|
"id": "messages",
|
||||||
"name": "Messages",
|
"name": "Messages",
|
||||||
"version": "0.30",
|
"version": "0.31",
|
||||||
"description": "App to display notifications from iOS and Gadgetbridge/Android",
|
"description": "App to display notifications from iOS and Gadgetbridge/Android",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
settings.unlockWatch=!!settings.unlockWatch;
|
settings.unlockWatch=!!settings.unlockWatch;
|
||||||
settings.openMusic=!!settings.openMusic;
|
settings.openMusic=!!settings.openMusic;
|
||||||
settings.maxUnreadTimeout=240;
|
settings.maxUnreadTimeout=240;
|
||||||
|
if (settings.flash===undefined) settings.flash=true;
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
function updateSetting(setting, value) {
|
function updateSetting(setting, value) {
|
||||||
|
|
@ -47,6 +48,11 @@
|
||||||
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||||
onchange: v => updateSetting("unlockWatch", v)
|
onchange: v => updateSetting("unlockWatch", v)
|
||||||
},
|
},
|
||||||
|
/*LANG*/'Flash Icon': {
|
||||||
|
value: !!settings().flash,
|
||||||
|
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||||
|
onchange: v => updateSetting("flash", v)
|
||||||
|
},
|
||||||
};
|
};
|
||||||
E.showMenu(mainmenu);
|
E.showMenu(mainmenu);
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
WIDGETS["messages"]={area:"tl", width:0, iconwidth:24,
|
WIDGETS["messages"]={area:"tl", width:0, iconwidth:24,
|
||||||
draw:function() {
|
draw:function(recall) {
|
||||||
// If we had a setTimeout queued from the last time we were called, remove it
|
// If we had a setTimeout queued from the last time we were called, remove it
|
||||||
if (WIDGETS["messages"].i) {
|
if (WIDGETS["messages"].i) {
|
||||||
clearTimeout(WIDGETS["messages"].i);
|
clearTimeout(WIDGETS["messages"].i);
|
||||||
|
|
@ -8,15 +8,18 @@ draw:function() {
|
||||||
Bangle.removeListener('touch', this.touch);
|
Bangle.removeListener('touch', this.touch);
|
||||||
if (!this.width) return;
|
if (!this.width) return;
|
||||||
var c = (Date.now()-this.t)/1000;
|
var c = (Date.now()-this.t)/1000;
|
||||||
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth);
|
|
||||||
g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y);
|
|
||||||
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
|
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
|
||||||
|
if (settings.flash===undefined) settings.flash = true;
|
||||||
|
if (recall !== true || settings.flash) {
|
||||||
|
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+23);
|
||||||
|
g.drawImage(settings.flash && (c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y-1);
|
||||||
|
}
|
||||||
if (settings.repeat===undefined) settings.repeat = 4;
|
if (settings.repeat===undefined) settings.repeat = 4;
|
||||||
if (c<120 && (Date.now()-this.l)>settings.repeat*1000) {
|
if (c<120 && (Date.now()-this.l)>settings.repeat*1000) {
|
||||||
this.l = Date.now();
|
this.l = Date.now();
|
||||||
WIDGETS["messages"].buzz(); // buzz every 4 seconds
|
WIDGETS["messages"].buzz(); // buzz every 4 seconds
|
||||||
}
|
}
|
||||||
WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(), 1000);
|
WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(true), 1000);
|
||||||
if (process.env.HWVERSION>1) Bangle.on('touch', this.touch);
|
if (process.env.HWVERSION>1) Bangle.on('touch', this.touch);
|
||||||
},show:function(quiet) {
|
},show:function(quiet) {
|
||||||
WIDGETS["messages"].t=Date.now(); // first time
|
WIDGETS["messages"].t=Date.now(); // first time
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
|
0.02: Fix scheduling of other alarms if there is a pending alarm from the past (fix #1667)
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,19 @@
|
||||||
}
|
}
|
||||||
var alarms = require('Storage').readJSON('sched.json',1)||[];
|
var alarms = require('Storage').readJSON('sched.json',1)||[];
|
||||||
var time = new Date();
|
var time = new Date();
|
||||||
var active = alarms.filter(a=>a.on && (a.dow>>time.getDay())&1 && (!a.date || a.date==time.toISOString().substr(0,10)));
|
|
||||||
if (active.length) {
|
|
||||||
active = active.sort((a,b)=>(a.t-b.t)+(a.last-b.last)*86400000);
|
|
||||||
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000);
|
||||||
|
var d = time.getDate();
|
||||||
|
var active = alarms.filter(
|
||||||
|
a=>a.on && // enabled
|
||||||
|
a.last!=d && // not already fired today
|
||||||
|
a.t+60000>currentTime && // is not in the past by >1 minute
|
||||||
|
(a.dow>>time.getDay())&1 && // is allowed on this day of the week
|
||||||
|
(!a.date || a.date==time.toISOString().substr(0,10)) // is allowed on this date
|
||||||
|
);
|
||||||
|
if (active.length) {
|
||||||
|
active = active.sort((a,b)=>a.t-b.t); // sort by time
|
||||||
var t = active[0].t-currentTime;
|
var t = active[0].t-currentTime;
|
||||||
if (active[0].last == time.getDate() || t < -60000) t += 86400000;
|
if (t<1000) t=1000; // start alarm minimum 1 sec from now
|
||||||
if (t<1000) t=1000; // start alarm min 1 sec from now
|
|
||||||
/* execute alarm at the correct time. We avoid execing immediately
|
/* execute alarm at the correct time. We avoid execing immediately
|
||||||
since this code will get called AGAIN when alarm.js is loaded. alarm.js
|
since this code will get called AGAIN when alarm.js is loaded. alarm.js
|
||||||
will then clearInterval() to get rid of this call so it can proceed
|
will then clearInterval() to get rid of this call so it can proceed
|
||||||
|
|
@ -23,3 +29,16 @@
|
||||||
Bangle.SCHED = setTimeout('eval(require("Storage").read("sched.boot.js"))', 86400000 - (Date.now()%86400000));
|
Bangle.SCHED = setTimeout('eval(require("Storage").read("sched.boot.js"))', 86400000 - (Date.now()%86400000));
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
/* DEBUGGING
|
||||||
|
===============
|
||||||
|
|
||||||
|
// show the current timer for the next event
|
||||||
|
global["\xff"].timers[Bangle.SCHED]
|
||||||
|
|
||||||
|
// time in hours of scheduled timer event
|
||||||
|
global["\xff"].timers[Bangle.SCHED].time / (1024*1024*60*60)
|
||||||
|
|
||||||
|
// set time 1 hour in the past
|
||||||
|
setTime(getTime() - 60*60)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "sched",
|
"id": "sched",
|
||||||
"name": "Scheduler",
|
"name": "Scheduler",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Scheduling library for alarms and timers",
|
"description": "Scheduling library for alarms and timers",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "scheduler",
|
"type": "scheduler",
|
||||||
|
|
|
||||||
2
core
2
core
|
|
@ -1 +1 @@
|
||||||
Subproject commit e9097fa680182069a5814c3e566a0bcbcb5e72a1
|
Subproject commit 8e45211d8f90ff165406f61f2c8a4604b66cbb51
|
||||||
Loading…
Reference in New Issue