1
0
Fork 0
Le~Kat 2023-02-28 22:08:21 -05:00
commit 25046b6f92
20 changed files with 311 additions and 93 deletions

View File

@ -1 +1,2 @@
0.01: Initial fork from messages_light 0.01: Initial fork from messages_light
0.02: Fix touch/drag/swipe handlers not being restored correctly if a message is removed

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -389,19 +389,17 @@ let getTouchHandler = function(ovr){
}; };
}; };
let touchHandler;
let swipeHandler;
let restoreHandler = function(event){ let restoreHandler = function(event){
if (backup[event]){ LOG("Restore", event, backup[event]);
Bangle["#on" + event]=backup[event]; Bangle.removeAllListeners(event);
backup[event] = undefined; Bangle["#on" + event]=backup[event];
} backup[event] = undefined;
}; };
let backupHandler = function(event){ let backupHandler = function(event){
if (eventQueue.length > 1 && ovr) return; // do not backup, overlay is already up if (backupDone) return; // do not backup, overlay is already up
backup[event] = Bangle["#on" + event]; backup[event] = Bangle["#on" + event];
LOG("Backed up", backup[event]);
Bangle.removeAllListeners(event); Bangle.removeAllListeners(event);
}; };
@ -414,21 +412,16 @@ let cleanup = function(){
restoreHandler("swipe"); restoreHandler("swipe");
restoreHandler("drag"); restoreHandler("drag");
if (touchHandler) {
Bangle.removeListener("touch", touchHandler);
touchHandler = undefined;
}
if (swipeHandler) {
Bangle.removeListener("swipe", swipeHandler);
swipeHandler = undefined;
}
Bangle.setLCDOverlay(); Bangle.setLCDOverlay();
backupDone = false;
ovr = undefined; ovr = undefined;
quiet = undefined; quiet = undefined;
}; };
let backup = {}; let backup = {};
let backupDone = false;
let main = function(ovr, event) { let main = function(ovr, event) {
LOG("Main", event, settings); LOG("Main", event, settings);
@ -441,13 +434,11 @@ let main = function(ovr, event) {
backupHandler("touch"); backupHandler("touch");
backupHandler("swipe"); backupHandler("swipe");
backupHandler("drag"); backupHandler("drag");
if (!backupDone){
if (touchHandler) Bangle.removeListener("touch",touchHandler); Bangle.on('touch', getTouchHandler(ovr));
if (swipeHandler) Bangle.removeListener("swipe",swipeHandler); Bangle.on('swipe', getSwipeHandler(ovr));
touchHandler = getTouchHandler(ovr); }
swipeHandler = getSwipeHandler(ovr); backupDone=true;
Bangle.on('touch', touchHandler);
Bangle.on('swipe', swipeHandler);
if (event !== undefined){ if (event !== undefined){
drawBorder(ovr); drawBorder(ovr);

View File

@ -1,7 +1,7 @@
{ {
"id": "messagesoverlay", "id": "messagesoverlay",
"name": "Messages Overlay", "name": "Messages Overlay",
"version": "0.01", "version": "0.02",
"description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)", "description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)",
"icon": "app.png", "icon": "app.png",
"type": "bootloader", "type": "bootloader",
@ -10,7 +10,6 @@
"dependencies" : { "messageicons":"module","messages":"app" }, "dependencies" : { "messageicons":"module","messages":"app" },
"readme": "README.md", "readme": "README.md",
"storage": [ "storage": [
{"name":"messagesoverlay.settings.js","url":"settings.js"},
{"name":"messagesoverlay","url":"lib.js"}, {"name":"messagesoverlay","url":"lib.js"},
{"name":"messagesoverlay.boot.js","url":"boot.js"} {"name":"messagesoverlay.boot.js","url":"boot.js"}
], ],

View File

@ -1 +0,0 @@
eval(require("Storage").read("messages.settings.js"));

View File

@ -1,2 +1,3 @@
0.01: 1st version: saves values to csv 0.01: 1st version: saves values to csv
0.02: added HTML interface 0.02: added HTML interface
0.03: Added Stop/start recording, change BG color, filesize info

View File

@ -9,6 +9,12 @@ Bangle JS1
![](photo_banglejs1.jpg) ![](photo_banglejs1.jpg)
UI for bangleJS1
![](bangle.js_UI.png)
UI for bangleJS2
![](bangle.js2_UI.png)
Screenshot BJS2 Screenshot BJS2
![](ss_emul_bjs2.png) ![](ss_emul_bjs2.png)
@ -30,18 +36,35 @@ Screenshot data file content
Open and see a temperature in the screen Open and see a temperature in the screen
Download the CSV file and process in your favourite spreadsheet software Download the CSV file and process in your favourite spreadsheet software
if you have any problem enable the modedebug in code; v_mode_debug=1 or 2
## Features ## Features
Colours, all inputs , graph, widgets loaded - Cross compatibility (JS1,JS2) and widgets compatibility
Counter for Times Display - BG/FG Colour, Export to file and counter of saved records per session
- File operations: Info, delete (no yet)
## Pending/future Features
- Buttons layout: btn txt(BJS1) , on screen button (BJS2)
- Long press touch to delete file (BJS1,BJS2)
- File operations: Delete
## Controls ## Controls/UI
- Left area: Back/Exit/launcher
exit: left side - BTN3 (long press)(BJS1): default Exit/kill app
- BTN1 (BJS2): "Launcher" / open "Messages"
- BTN2 (BJS1): "Launcher" / open "Messages"
- BTN1 (BJS1): Change FG Color
- BTN3 (BJS1): Change BG Color
- Right area: Change FG Color
- Swipe left: Change BG Color
- Swipe right: Increase/Decrease Hour circle/Points
## Creator ## Creator
Daniel Perez Daniel Perez
For suggestions or feedback
https://github.com/dapgo/my_espruino_smartwatch_things

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

View File

@ -1,7 +1,7 @@
{ {
"id": "tempmonitor", "id": "tempmonitor",
"name": "Temperature monitor", "name": "Temperature monitor",
"version": "0.02", "version": "0.03",
"description": "Displays the current temperature and stores in a CSV file", "description": "Displays the current temperature and stores in a CSV file",
"icon": "app.png", "icon": "app.png",
"tags": "tool", "tags": "tool",

View File

@ -1,42 +1,69 @@
// Temperature monitor that saves a log of measures // Temperature monitor that saves a log of measures
// standalone ver for developer, to remove testing lines // standalone ver for developer, to remove testing lines
// delimiter ; (excel) or , (oldscool) // delimiter ; (excel) or , (oldscool)
/* REFACTOR and remove commented code related to
SetUI, Layout, and setWatch( function(b) { }, BTN1, { repeat: true, edge:'falling' })
*/
{ {
var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail
//var required for drawing with dynamic screen //var required for drawing with dynamic screen
var rect = Bangle.appRect; var rect = Bangle.appRect;
var history = []; var history = [];
var readFreq=5000; //ms //PEND add to settings var readFreq=4000; //ms //PEND add to settings
var saveFreq=60000; //ms 1min if (v_mode_debug>0) var saveFreq=6000; //ms for testin 6sec
else var saveFreq=60000; //ms 1min
var v_saveToFile= new Boolean(true); //true save //false var v_saveToFile= new Boolean(true); //true save //false
//with upload file º is not displayed properly //with upload file º is not displayed properly
//with upload RAM º is displayed //with upload RAM º is displayed
var v_t_symbol="";//ºC var v_t_symbol="";//ºC
var v_saved_entries=0; var v_saved_entries=0;
var filename ="temphistory.csv"; var v_filename ="temphistory.csv";
var lastMeasure = new String(); var lastMeasure = new String();
var v_model=process.env.BOARD; var v_model=process.env.BOARD;
var v_color_erase=g.getBgColor(); //original BG color overwritten on SetVariables
var v_color=g.getColor();//original FG color
var id_rec_intv; //var for the recording interval
if (readFreq>saveFreq) console.log("Read refresh freq should be higher than saving");
if (v_mode_debug>0) console.log("original BG/FG color="+v_color_erase+" / "+v_color);
function SetVariables(){
//EMSCRIPTEN,EMSCRIPTEN2 //EMSCRIPTEN,EMSCRIPTEN2
if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') { if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') {
v_font_size1=16; v_font_size1=16;
v_font_size2=60; v_font_size2=50;
//g.setColor("#0ff"); //light color
}else{ }else{
v_font_size1=11; //Banglejs2 or others
v_font_size2=40; v_font_size1=11; //too small?
//g.setColor("#000"); //black or dark v_font_size2=40;
} }
//overwriting default BG, is better detect?
if (g.theme.dark==1) v_color_erase=0x0000; //dynamic; //bg black
else if (g.theme.dark==0) v_color_erase=0xFFFF; //dynamic; //bg white
}
function onTemperature(v_temp) { //print result
if (v_mode_debug>1) console.log("v_temp in "+v_temp); function printTemperature(v_temp) {
if (v_mode_debug>1) console.log("v_temp in "+v_temp+" entries "+v_saved_entries);
ClearBox(); ClearBox();
//g.setFont("6x8",2).setFontAlign(0,0); //g.setFont("6x8",2).setFontAlign(0,0);
g.setFontVector(v_font_size1).setFontAlign(0,0); g.setFontVector(v_font_size1).setFontAlign(0,0);
var x = (rect.x+rect.x2)/2; var x = (rect.x+(rect.x2-60))/2;//-60 space for graph and layout buttons
var y = (rect.y+rect.y2)/2 + 20; var y = (rect.y+rect.y2)/2 + 20;
g.drawString("Records: "+v_saved_entries, x, rect.y+35);
g.drawString("Temperature:", x, rect.y+37+v_font_size1); if (v_saveToFile==true) {
// if (v_mode_debug>0) console.log("prev color="+v_color);
printInfo("Recording : "+v_saved_entries, '#CC3333',x,rect.y+30);
//g.setColor('#CC3333'); //red
// g.drawString("Recording : "+v_saved_entries, x, rect.y+35);
//g.setColor(v_color);//restore default color
}
else printInfo("Rec paused : "+v_saved_entries, v_color,x,rect.y+30);
//else g.drawString("Rec paused : "+v_saved_entries, x, rect.y+35);
//space for printing info
g.drawString("Temperature:", x, rect.y+45+(v_font_size1*2));
//dynamic font (g.getWidth() > 200 ? 60 : 40) //dynamic font (g.getWidth() > 200 ? 60 : 40)
g.setFontVector(v_font_size2).setFontAlign(0,0); g.setFontVector(v_font_size2).setFontAlign(0,0);
// Avg of temperature readings // Avg of temperature readings
@ -48,33 +75,68 @@ function onTemperature(v_temp) {
lastMeasure=avrTemp.toString(); lastMeasure=avrTemp.toString();
if (lastMeasure.length>4) lastMeasure=lastMeasure.substr(0,4); if (lastMeasure.length>4) lastMeasure=lastMeasure.substr(0,4);
//DRAW temperature in the center //DRAW temperature in the center
g.drawString(" ", x-20, y); //remove g.drawString(" ", x-20, y);
g.drawString(v_temp+v_t_symbol, x-20, y); g.drawString(v_temp+v_t_symbol, x, y);
g.flip(); g.flip();
} }
// from: BJS2 pressure sensor, BJS1 inbuilt thermistor // from: BJS2 pressure sensor, BJS1 inbuilt thermistor
function drawTemperature() { function getTemperature() {
if(v_model.substr(0,10)!='EMSCRIPTEN'){ if(v_model.substr(0,10)!='EMSCRIPTEN'){
if (Bangle.getPressure) { if (Bangle.getPressure) {
Bangle.getPressure().then(p =>{if (p) onTemperature(p);}); Bangle.getPressure().then(p =>{if (p) printTemperature(p);});
} else onTemperature(E.getTemperature()); } else printTemperature(E.getTemperature());
} }
else onTemperature(11);//fake temp for emulators else printTemperature(11.25);//fake temperature medition for emulators
} }
function saveToFile() { /* Note that it changes BG and also FG to an opposite*/
function changeBGcolor(){
//pend to refactor
if (v_mode_debug>1) console.log("before BG/FG "+v_color_erase+" /"+v_color);
v_color_erase=0xFFFF-v_color_erase;
v_color=0xFFFF-v_color;
if (v_mode_debug>1) console.log("after result BG/FG "+v_color_erase+" /"+v_color);
//g.setColor(color_result);
g.setBgColor(v_color_erase);// 0 white, 1 black
g.setColor(v_color);
//move to event?
ClearScreen();
ClearBox();
drawGraph();
getTemperature();
//setDrawLayout(); //uncomment if layout can work with setUI
//g.clear();//impact on widgets
}
function saveToFile(){
//input global vars: lastMeasure //input global vars: lastMeasure
var a=new Date(); var a=new Date();
var strlastSaveTime=new String(); var strlastSaveTime=new String();
strlastSaveTime=a.toISOString(); strlastSaveTime=a.toISOString();
//strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());; //strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());;
if (v_mode_debug==1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure); if (v_mode_debug>1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure);
if (v_saveToFile==true){ if (v_saveToFile==true){
//write(strlastSaveTime+";"+ //write(strlastSaveTime+";"+
require("Storage").open(filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n"); //var f = require("Storage").open(v_filename,"r");
//(getTime()+","); // f=require("Storage").read(v_filename+"\1");//suffix required load completely!!
v_saved_entries=v_saved_entries+1; //note that .read uses Storage Class .open uses StorageFile Class , difference in file chunks
// if (v_mode_debug>0) console.log("f "+f);
var f = require("Storage").open(v_filename,"r");
if ((v_mode_debug>0) && (v_saved_entries==0)) console.log("file info:"+f);
if (f.len>0) {
if (!f) {
require("Storage").open(v_filename,"w").write("Month;Day;Time;Temp"+"\n");
if (v_mode_debug>0) console.log("not exist but created "+f);
}
else{
require("Storage").open(v_filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n");
//(getTime()+",");
v_saved_entries=v_saved_entries+1;
if (v_mode_debug>1) console.log("append to already exist "+f.name+" , "+v_saved_entries);
}
}
} }
else if (v_mode_debug>0) console.log("recording mode stopped");
} }
function drawGraph(){ function drawGraph(){
@ -83,17 +145,19 @@ function drawGraph(){
transparent : 0, transparent : 0,
buffer : require("heatshrink").decompress(atob("AEFt2AMKm3bsAMJjdt23ABhEB+/7tgaJ///DRUP//7tuADRP923YDRXbDRfymwaJhu/koaK7eyiwaK3cLDRlWDRY1NKBY1Ztu5kjmJg3cyVI7YMHgdu5Mkyu2fxHkyVJjdgDRFJkmRDRPsDQNbDQ5QBGoONKBJrBoxQIQwO2eRcbtu24AMIFIQLJAH4AMA==")) buffer : require("heatshrink").decompress(atob("AEFt2AMKm3bsAMJjdt23ABhEB+/7tgaJ///DRUP//7tuADRP923YDRXbDRfymwaJhu/koaK7eyiwaK3cLDRlWDRY1NKBY1Ztu5kjmJg3cyVI7YMHgdu5Mkyu2fxHkyVJjdgDRFJkmRDRPsDQNbDQ5QBGoONKBJrBoxQIQwO2eRcbtu24AMIFIQLJAH4AMA=="))
}; };
g.drawImage(img_obj_thermo,rect.x2-50,rect.y2/2); g.drawImage(img_obj_thermo,rect.x2-60,rect.y2/2);
g.flip(); g.flip();
} }
function ClearScreen(){ function ClearScreen(){
//avoid widget areas //avoid widget areas
g.reset(1).clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24); g.setBgColor(v_color_erase);
g.clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24);
g.flip(); g.flip();
} }
function ClearBox(){ function ClearBox(){
//custom boxarea , left space for static graph at right //custom boxarea , left space for static graph at right
g.reset(1).clearRect(rect.x, rect.y+24, rect.x2-50, rect.y2-24); g.setBgColor(v_color_erase);
g.clearRect(rect.x, rect.y+24, rect.x2-60, rect.y2-24);
g.flip(); g.flip();
} }
function introPage(){ function introPage(){
@ -109,30 +173,140 @@ function introPage(){
g.drawString("Read freq(ms): "+readFreq, x, y ); g.drawString("Read freq(ms): "+readFreq, x, y );
g.drawString("Save to file: "+v_saveToFile, x, y+ ((v_font_size1*1)+2) ); g.drawString("Save to file: "+v_saveToFile, x, y+ ((v_font_size1*1)+2) );
g.drawString("Save freq(ms):"+saveFreq, x, y+((v_font_size1*2)+2) ); g.drawString("Save freq(ms):"+saveFreq, x, y+((v_font_size1*2)+2) );
fr=require("Storage").read(filename+"\1");//suffix required fr=require("Storage").read(v_filename+"\1");//suffix required
if (fr) g.drawString("Current filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) ); if (fr) g.drawString("Filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) );
else g.drawString("File not exist", x, y+((v_font_size1*3)+2)); else g.drawString("File not exist", x, y+((v_font_size1*3)+2));
} }
function printInfo(pmsg, pcolor,px,py){
g.setColor(pcolor);
g.setFontVector(v_font_size1).setFontAlign(0,0);
g.drawString(pmsg, px,py+v_font_size1);
g.setColor(v_color);//restore default color
}
function toggleRecMode(duration, exectime){
//bydefault float, standard epoch requires *1000
if (v_mode_debug>0) console.log("duration"+duration);
if (duration>2) { //delete file
var x = (rect.x+(rect.x2-60))/2;
printInfo("Deleting file",'#CC3333',x, rect.y+32+v_font_size1);
// g.setColor('#CC3333'); //red
//too long "Deleting file: "+v_filename,
// for StorageFiles created with require("Storage").open(filename, ...)
//require("Storage").erase(v_filename);
//TODO refactor in a new function
//var mifile = require("Storage").open(v_filename,"w");
var mifile = require("Storage").open("temphistory.csv","w");
var v_output=mifile.erase();
//mifile.StorageFile.erase();
if (v_mode_debug>0) console.log("output"+v_output);
setTimeout(function() { if (v_mode_debug>0) console.log("pause for 1 sec");},1000);
return; //leave this function
}
if (v_saveToFile) v_saveToFile=false;
else v_saveToFile=true;
if (v_mode_debug>0) console.log("recording? "+v_saveToFile);
setRecordingFreq();
}
function setRecordingFreq(){
if (v_saveToFile==true) { //TODO now start on false btn will no enable
id_rec_intv=setInterval(function() {
saveToFile();
}, saveFreq); //ms
if (v_mode_debug>0) console.log("interval id / frq"+id_rec_intv+" / "+saveFreq);
}
else if (id_rec_intv){
clearInterval(id_rec_intv);
if (v_mode_debug>0) console.log("rec interval removed, id "+id_rec_intv);
id_rec_intv=0; // to reset var
}
}
function UserInput(){
//theoretically incompatible with Layout
Bangle.setUI({
mode : "custom",
//adds a back icon on top widget area
back : function() {load();},
//touch : function(n,e) {}, // optional - handler for 'touch' events
// righ/Left 1/-1 , updown
swipe : function(dir_rl,dir_ud) {
if(dir_rl == 1) {
if (v_mode_debug>0) console.log("swipe right: ");
getFileInfo(v_filename);
}
else if (dir_rl == -1){
if (v_mode_debug>0) console.log("swipe left: ");
changeBGcolor();
}
},
touch : function(tzone,tobj){
if ((process.env.HWVERSION == 2)&&(v_mode_debug>0)){
console.log("tobj x,y,type : "+tobj.x+" "+tobj.y+" "+tobj.type);
}
switch(tzone){
//case 1: //left , back managed by setUI
case 2: // right disable/enable recording
toggleRecMode(0); //toggleRecMode(duration, exectime)
break;
// case 3: console.log("Touch 3 aka 1+2 not for BJS1 emul");//center 1+2
// break;
}
},
//inferior to
btn : function(btn) {
if(btn == 1) {
if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') toggleRecMode(1); //console.log("btn1 BJS1");
else mainBtnShortcut(); //console.log("btn1 BJS2");
}
else if (btn == 2) mainBtnShortcut(); //console.log("btn2 BJS1");
else if (btn == 3) changeBGcolor(); //console.log("btn3 BJS1");
}
}); //endof setUI
}
function mainBtnShortcut() {
//if messages app installed shortcut otherwise default access to launcher
if (require("Storage").read("messagegui.app.js")===undefined)
{
if (require("Storage").read("messagelist.app.js")===undefined) Bangle.showLauncher(); // implies btn2(js1) btn(js2)- launcher
else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagelist.app.js");
else load("messagelist.app.js");
}
else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagegui.app.js");
else load("messagegui.app.js");
}
// Show file size
function getFileInfo(v_filename) {
var f = require("Storage").open(v_filename,"r");
//todo refactor and reuse common code
g.setFontVector(v_font_size1).setFontAlign(0,0);
var x = (rect.x+(rect.x2-60))/2;
printInfo("file size:"+f.len,v_color,x, rect.y+32+v_font_size1);
// g.drawString("file size:"+f.len, x, rect.y+37+v_font_size1);
if (v_mode_debug>0) console.log("file "+v_filename+" size: "+f.len);
}// not used
//MAIN //MAIN
SetVariables();
Bangle.loadWidgets(); Bangle.loadWidgets();
Bangle.setUI({
mode : "custom",
back : function() {load();}
});
ClearScreen(); ClearScreen();
introPage(); introPage();
//setDrawLayout(); //uncomment if layout can work with setUI
UserInput(); //inc SetUI and back icon
setInterval(function() { setInterval(function() {
drawTemperature(); getTemperature();
}, readFreq); //ms }, readFreq); //ms
if (v_saveToFile==true) { setRecordingFreq();
setInterval(function() {
saveToFile();
}, saveFreq); //ms
}
setTimeout(ClearScreen, 3500);
setTimeout(drawGraph,4000);
setTimeout(drawTemperature,4500);
} }

View File

@ -1 +1 @@
{"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.01","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"} {"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.03","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"}

View File

@ -6,11 +6,11 @@
); );
const iconWidth = 18; const iconWidth = 18;
function draw(this: { x: number; y: number }) { function draw(this: { x?: number; y?: number }) {
g.reset(); g.reset();
if (Bangle.isCharging()) { if (Bangle.isCharging()) {
g.setColor('#FD0'); g.setColor('#FD0');
g.drawImage(icon, this.x + 1, this.y + 1, { g.drawImage(icon, this.x! + 1, this.y! + 1, {
scale: 0.6875, scale: 0.6875,
}); });
} }

View File

@ -8,3 +8,4 @@
0.05: Convert Yes/No On/Off in settings to checkboxes 0.05: Convert Yes/No On/Off in settings to checkboxes
0.06: Remember next alarm to reduce calculation amount 0.06: Remember next alarm to reduce calculation amount
Redraw only every hour when no alarm in next 24h Redraw only every hour when no alarm in next 24h
0.07: Fix when no alarms are present

View File

@ -2,7 +2,7 @@
"id": "widalarmeta", "id": "widalarmeta",
"name": "Alarm & Timer ETA", "name": "Alarm & Timer ETA",
"shortName": "Alarm ETA", "shortName": "Alarm ETA",
"version": "0.06", "version": "0.07",
"description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).", "description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",

View File

@ -9,13 +9,15 @@
function getNextAlarm(date) { function getNextAlarm(date) {
const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true);
WIDGETS["widalarmeta"].numActiveAlarms = alarms.length; WIDGETS["widalarmeta"].numActiveAlarms = alarms.length;
const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); if (alarms.length > 0) {
const eta = times.length > 0 ? Math.min.apply(null, times) : 0; const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY);
if (eta !== Number.POSITIVE_INFINITY) { const eta = Math.min.apply(null, times);
const idx = times.indexOf(eta); if (eta !== Number.POSITIVE_INFINITY) {
const alarm = alarms[idx]; const idx = times.indexOf(eta);
delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory const alarm = alarms[idx];
return alarm; delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory
return alarm;
}
} }
} // getNextAlarm } // getNextAlarm

View File

@ -1 +1,2 @@
0.01: First commit 0.01: First commit
0.02: Add tap-to-lock functionality

View File

@ -1,8 +1,8 @@
{ {
"id": "widlockunlock", "id": "widlockunlock",
"name": "Lock/Unlock Widget", "name": "Lock/Unlock Widget",
"version": "0.01", "version": "0.02",
"description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise", "description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise. Tap to lock the lcd",
"icon": "widget.png", "icon": "widget.png",
"type": "widget", "type": "widget",
"tags": "widget,lock", "tags": "widget,lock",

View File

@ -1,5 +1,28 @@
Bangle.on("lockunlock", function() { Bangle.on("lock", () => Bangle.drawWidgets());
Bangle.drawWidgets();
Bangle.on('touch', (_btn, xy) => {
const oversize = 5;
const w = WIDGETS.lockunlock;
const x = xy.x;
const y = xy.y;
if(w.x - oversize <= x && x < w.x + 14 + oversize
&& w.y - oversize <= y && y < w.y + 24 + oversize)
{
Bangle.setLocked(true);
const backlightTimeout = Bangle.getOptions().backlightTimeout; // ms
// seems to be a race/if we don't give the firmware enough time,
// it won't timeout the backlight and we'll restore it in our setTimeout below
Bangle.setOptions({ backlightTimeout: 100 });
setTimeout(() => {
Bangle.setOptions({ backlightTimeout });
}, 300);
}
}); });
WIDGETS["lockunlock"]={area:"tl",sortorder:10,width:14,draw:function(w) { WIDGETS["lockunlock"]={area:"tl",sortorder:10,width:14,draw:function(w) {
g.reset().drawImage(atob(Bangle.isLocked() ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x+1, w.y+3); g.reset().drawImage(atob(Bangle.isLocked() ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x+1, w.y+3);

View File

@ -83,7 +83,10 @@ type WidgetArea = "tl" | "tr" | "bl" | "br";
type Widget = { type Widget = {
area: WidgetArea; area: WidgetArea;
width: number; width: number;
draw: (this: { x: number; y: number }) => void; sortorder?: number;
draw: (this: Widget, w: Widget) => void;
x?: number;
y?: number;
}; };
declare const WIDGETS: { [key: string]: Widget }; declare const WIDGETS: { [key: string]: Widget };