From b3f40e868d14d9b4d764f2d846e959d5a0a967ce Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Sat, 27 Aug 2022 22:25:28 +0100 Subject: [PATCH 01/72] Works - except that date_utils is gone?! --- apps/bigdclock/ChangeLog | 1 + apps/bigdclock/bigdclock.app.js | 12 ++++++++---- apps/bigdclock/metadata.json | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index 09cc978fb..60a8f703f 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -3,3 +3,4 @@ 0.03: Internationalisation; bug fix - battery icon responds promptly to charging state 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() +0.06: Better battery graphic - now has green, yellow and red sections diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index c013c6188..dba60183c 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -29,7 +29,8 @@ function draw() { const level = E.getBattery(); const width = level + (level/2); var is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; - var dows = require("date_utils").dows(0,1); +// var dows = require("date_utils").dows(0,1); + var dows = ["SU","MO","TU","WE","TH","FR","SA"]; g.reset(); g.clear(); @@ -53,12 +54,15 @@ function draw() { g.fillRect(167,163,170,167); if (Bangle.isCharging()) { g.setColor(1,1,0); - } else if (level > 40) { - g.setColor(0,1,0); + g.fillRect(12,162,12+width,168); } else { g.setColor(1,0,0); + g.fillRect(12,162,57,168); + g.setColor(1,1,0); + g.fillRect(58,162,72,168); + g.setColor(0,1,0); + g.fillRect(73,162,162,168); } - g.fillRect(12,162,12+width,168); if (level < 100) { g.setColor(g.theme.bg); g.fillRect(12+width+1,162,162,168); diff --git a/apps/bigdclock/metadata.json b/apps/bigdclock/metadata.json index 7359bcf20..ce91d921e 100644 --- a/apps/bigdclock/metadata.json +++ b/apps/bigdclock/metadata.json @@ -1,7 +1,7 @@ { "id": "bigdclock", "name": "Big digit clock containing just the essentials", "shortName":"Big digit clk", - "version":"0.05", + "version":"0.06", "description": "A clock containing just the essentials, made as easy to read as possible for those of us that need glasses. It contains the time, the day-of-week, the day-of-month, and the current battery state-of-charge.", "icon": "bigdclock.png", "type": "clock", From 876c5caff51d144c72c134960581a5f63b16cda8 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 11 Sep 2022 18:26:56 +0200 Subject: [PATCH 02/72] First tests with new clock_info --- apps/bwclk/app.js | 597 +++++++++------------------------------------- 1 file changed, 119 insertions(+), 478 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index cd1979e98..15de3f870 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -3,13 +3,12 @@ */ const locale = require('locale'); const storage = require('Storage'); +// const clock_info = require("clock_info"); /************ * Statics */ const SETTINGS_FILE = "bwclk.setting.json"; -const TIMER_IDX = "bwclk_timer"; -const TIMER_AGENDA_IDX = "bwclk_agenda"; const W = g.getWidth(); const H = g.getHeight(); @@ -86,279 +85,81 @@ function imgLock(){ } } -function imgSteps(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/H///wv4CBn4CD8ACCj4IBj8f+Eeh/wjgCBngCCg/4nEH//4h/+jEP/gRBAQX+jkf/wgB//8GwP4FoICDHgICCBwIA==")) - } -} -function imgBattery(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AN4EAg4TBgd///9oEAAQv8ARQRDDQQgCEwQ4OA")) - } -} - -function imgCharging() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) - } -} - -function imgBpm() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AOn4CD/wCCjgCCv/8jF/wGYgOA5MB//BC4PDAQnjAQPnAQgANA")) - } -} - -function imgTemperature() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//D///wICBjACBngCNkgCP/0kv/+s1//nDn/8wICEBAIOC/08v//IYJECA==")) - } -} - -function imgWeather(){ - return { - width : 24, height : 24, bpp : 1, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAcYAQ0MgEwAQUAngLB/8AgP/wACCgf/4Fz//OAQQICCIoaCEAQpGHA4ACA=")) - } -} - -function imgWind () { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/0f//8h///Pn//zAQXzwf/88B//mvGAh18gEevn/DIICB/PwgEBAQMHBAIADFwM/wEAGAP/54CD84CE+eP//wIQU/A==")) - } -} - -function imgHumidity () { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("//7///+YCB+ICB8ACE4F/AQX9AQP54H//AOB+F/34CBj/gn8f4E+h/Aj0H4Ecg+AjED4ACE8E4gfwvEDEgICB/kHGwMP")) - } -} - -function imgTimer() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/+B/4CD84CEBAPygFP+F+h/x/+P+fz5/n+HnAQNn5/wuYCBmYCC5kAAQfOgFz80As/ngHn+fD54mC/F+j/+gF/HAQA==")) - } -} - -function imgWatch() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC")) - } -} - -function imgHomeAssistant() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AF84CB4YCBwICBCAP+jFH/k8g/4kkH+AFB8ACB4cY4eHzPhgmZkHnzPn8fb4/gvwUD8EYARhAC")) - } -} - -function imgAgenda() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : require("heatshrink").decompress(atob("/4AFnPP+ALBAQX4CIgLFAQvggEBAQvAgEDAQMCwEAgwTBhgiB/AlCGQ8BGQQ")) - } -} - -function imgMountain() { - return { - width : 24, height : 24, bpp : 1, - transparent : 1, - buffer : atob("//////////////////////3///n///D//uZ//E8//A+/+Z+f8//P5//n7//3z//zn//5AAAAAAAA////////////////////") - } -} - -/************ - * 2D MENU with entries of: - * [name, icon, opt[customDownFun], opt[customUpFun], opt[customCenterFun]] - * - */ -var menu = [ - [ - function(){ return [ null, null ] }, - function(){ return [ "Week " + weekOfYear(), null ] }, - ], - [ - function(){ return [ "Bangle", imgWatch() ] }, - function(){ return [ E.getBattery() + "%", Bangle.isCharging() ? imgCharging() : imgBattery() ] }, - function(){ return [ getSteps(), imgSteps() ] }, - function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm()] }, - function(){ return [ measureAltitude, imgMountain() ]}, - ] -] - -/* - * Timer Menu - */ -try{ - require('sched'); - menu.push([ - function(){ - var text = isAlarmEnabled(TIMER_IDX) ? getAlarmMinutes(TIMER_IDX) + " min." : "Timer"; - return [text, imgTimer(), () => decreaseAlarm(TIMER_IDX), () => increaseAlarm(TIMER_IDX), null ] - }, - ]); -} catch(ex) { - // If sched is not installed, we hide this menu item -} - - -/* - * AGENDA MENU - * Note that we handle the agenda differently in order to hide old entries... - */ -var agendaIdx = 0; -var agendaTimerIdx = 0; -if(storage.readJSON("android.calendar.json") !== undefined){ - function nextAgendaEntry(){ - agendaIdx += 1; - } - - function previousAgendaEntry(){ - agendaIdx -= 1; - } - - menu.push([ - function(){ - var now = new Date(); - var agenda = storage.readJSON("android.calendar.json") - .filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000) - .sort((a,b)=>a.timestamp - b.timestamp); - - if(agenda.length <= 0){ - return ["All done", imgAgenda()] - } - - agendaIdx = agendaIdx < 0 ? 0 : agendaIdx; - agendaIdx = agendaIdx >= agenda.length ? agendaIdx -1 : agendaIdx; - - var entry = agenda[agendaIdx]; - var title = entry.title.slice(0,14); - var date = new Date(entry.timestamp*1000); - var dateStr = locale.date(date).replace(/\d\d\d\d/,""); - dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; - - function dynImgAgenda(){ - if(isAlarmEnabled(TIMER_AGENDA_IDX) && agendaTimerIdx == agendaIdx){ - return imgTimer(); - } else { - return imgAgenda(); - } - } - - return [title + "\n" + dateStr, dynImgAgenda(), () => nextAgendaEntry(), () => previousAgendaEntry(), function(){ - try{ - var alarm = require('sched') - - // If other time, we disable the old one and enable this one. - if(agendaIdx != agendaTimerIdx){ - agendaTimerIdx = -1; - alarm.setAlarm(TIMER_AGENDA_IDX, undefined); - } - - // Disable alarm if enabled - if(isAlarmEnabled(TIMER_AGENDA_IDX)){ - agendaTimerIdx = -1; - alarm.setAlarm(TIMER_AGENDA_IDX, undefined); - alarm.reload(); - return - } - - // Otherwise, set alarm for given event - agendaTimerIdx = agendaIdx; - alarm.setAlarm(TIMER_AGENDA_IDX, { - msg: title, - timer : parseInt((date - now)), - }); - alarm.reload(); - } catch(ex){ } - }] - }, - ]); -} - - -/* - * WEATHER MENU - */ -if(storage.readJSON('weather.json') !== undefined){ - menu.push([ - function(){ return [ "Weather", imgWeather() ] }, - function(){ return [ getWeather().temp, imgTemperature() ] }, - function(){ return [ getWeather().hum, imgHumidity() ] }, - function(){ return [ getWeather().wind, imgWind() ] }, - ]); -} - - -/* - * HOME ASSISTANT MENU - */ -try{ - var triggers = require("ha.lib.js").getTriggers(); - var haMenu = [ - function(){ return [ "Home", imgHomeAssistant() ] }, - ]; - - triggers.forEach(trigger => { - haMenu.push(function(){ - return [trigger.display, trigger.getIcon(), () => {}, () => {}, function(){ - var ha = require("ha.lib.js"); - ha.sendTrigger("TRIGGER_BW"); - ha.sendTrigger(trigger.trigger); - }] +// clock_info ######################################################## +function load() { + // info used for drawing... + var hrm = "--"; + var alt = "--"; + // callbacks (needed for easy removal of listeners) + function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } + function stepUpdateHandler() { bangleItems[1].emit("redraw"); } + function hrmUpdateHandler() { bangleItems[2].emit("redraw"); } + function altUpdateHandler() { + Bangle.getPressure().then(data=>{ + if (!data) return; + alt = Math.round(data.altitude) + "m"; + bangleItems[3].emit("redraw"); }); - }) - menu.push(haMenu); -} catch(ex){ - // If HomeAssistant is not installed, we hide this item -} - - -function getMenuEntry(){ - // In case the user removes HomeAssistant entries, showInfo - // could be larger than infoArray.length... - settings.menuPosX = settings.menuPosX % menu.length; - settings.menuPosY = settings.menuPosY % menu[settings.menuPosX].length; - var menuEntry = menu[settings.menuPosX][settings.menuPosY](); - - if(menuEntry[0] == null){ - return menuEntry; } - - // For the first entry we always convert it into a callback function - // such that the menu is compatible with async functions such as - // measuring the pressure, altitude or sending http requests... - if(typeof menuEntry[0] !== 'function'){ - var value = menuEntry[0]; - menuEntry[0] = function(callbackFun){ - callbackFun(String(value), settings.menuPosX, settings.menuPosY); + // actual items + var items = [ + { + name: "Bangle", + img: atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC"), + items: [ + { name : "Battery", + get : () => ({ + text : E.getBattery() + "%", + img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") }), + show : function() { + this.interval = setInterval(()=>this.emit('redraw'), 60000); + Bangle.on("charging", batteryUpdateHandler); + batteryUpdateHandler(); + }, + hide : function() { + clearInterval(this.interval); + delete this.interval; + Bangle.removeListener("charging", batteryUpdateHandler); + }, + }, + { name : "Steps", get : () => ({ + text : Bangle.getHealthStatus("day").steps, + img : atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA==") }), + show : function() { Bangle.on("step", stepUpdateHandler); stepUpdateHandler(); }, + hide : function() { Bangle.removeListener("step", stepUpdateHandler); }, + }, + { name : "HRM", get : () => ({ + text : Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", + img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA==") }), + show : function() { Bangle.setHRMPower(1,"clkinfo"); Bangle.on("HRM", hrmUpdateHandler); hrm = Math.round(Bangle.getHealthStatus("last").bpm); hrmUpdateHandler(); }, + hide : function() { Bangle.setHRMPower(0,"clkinfo"); Bangle.removeListener("HRM", hrmUpdateHandler); hrm = "--"; }, } + ], + }]; + var bangleItems = items[0].items; + + if (Bangle.getPressure){ // Altimeter may not exist + bangleItems.push({ name : "Altitude", get : () => ({ + text : alt, + img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA==") }), + show : function() { this.interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, + hide : function() { clearInterval(this.interval); delete this.interval; }, + }); } - return menuEntry; -} + + // now load extra data from a third party files + require("Storage").list(/clkinfo.js$/).forEach(fn => { + items = items.concat(eval(require("Storage").read(fn))()); + }); + + // return it all! + return items; +}; +// clock_info ######################################################## + + +var clock_items = load(); /************ @@ -373,144 +174,6 @@ function isFullscreen(){ } } -function getSteps() { - var steps = 0; - try{ - if (WIDGETS.wpedom !== undefined) { - steps = WIDGETS.wpedom.getSteps(); - } else if (WIDGETS.activepedom !== undefined) { - steps = WIDGETS.activepedom.getSteps(); - } else { - steps = Bangle.getHealthStatus("day").steps; - } - } catch(ex) { - // In case we failed, we can only show 0 steps. - } - - return steps; -} - - -function getWeather(){ - var weatherJson; - - try { - weatherJson = storage.readJSON('weather.json'); - var weather = weatherJson.weather; - - // Temperature - weather.temp = locale.temp(weather.temp-273.15); - - // Humidity - weather.hum = weather.hum + "%"; - - // Wind - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - weather.wind = Math.round(wind[1]) + "kph"; - - return weather - - } catch(ex) { - // Return default - } - - return { - temp: " ? ", - hum: " ? ", - txt: " ? ", - wind: " ? ", - wdir: " ? ", - wrose: " ? " - }; -} - -// From https://weeknumber.com/how-to/javascript -function weekOfYear() { - var date = new Date(); - date.setHours(0, 0, 0, 0); - // Thursday in current week decides the year. - date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); - // January 4 is always in week 1. - var week1 = new Date(date.getFullYear(), 0, 4); - // Adjust to Thursday in week 1 and count number of weeks from date to week1. - return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - - 3 + (week1.getDay() + 6) % 7) / 7); -} - - -function isAlarmEnabled(idx){ - try{ - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(idx); - if(alarmObj===undefined || !alarmObj.on){ - return false; - } - - return true; - - } catch(ex){ } - return false; -} - - -function getAlarmMinutes(idx){ - if(!isAlarmEnabled(idx)){ - return -1; - } - - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(idx); - return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); -} - - -function increaseAlarm(idx){ - try{ - var minutes = isAlarmEnabled(idx) ? getAlarmMinutes(idx) : 0; - var alarm = require('sched'); - alarm.setAlarm(idx, { - timer : (minutes+5)*60*1000, - }); - alarm.reload(); - } catch(ex){ } -} - - -function decreaseAlarm(idx){ - try{ - var minutes = getAlarmMinutes(idx); - minutes -= 5; - - var alarm = require('sched') - alarm.setAlarm(idx, undefined); - - if(minutes > 0){ - alarm.setAlarm(idx, { - timer : minutes*60*1000, - }); - } - - alarm.reload(); - } catch(ex){ } -} - - -function measureAltitude(callbackFun){ - var oldX = settings.menuPosX; - var oldY = settings.menuPosY; - try{ - Bangle.getPressure().then(data=>{ - if(data && data.altitude && data.altitude > -100){ - callbackFun(Math.round(data.altitude) + "m", oldX, oldY); - } else { - callbackFun("???", oldX, oldY); - } - }); - }catch(ex){ - callbackFun("err", oldX, oldY); - } -} - /************ * DRAW @@ -577,56 +240,34 @@ function drawTime(){ // Set y coordinates correctly y += parseInt((H - y)/2) + 5; - var menuEntry = getMenuEntry(); - var menuTextFun = menuEntry[0]; - var menuImg = menuEntry[1]; - var printImgLeft = settings.menuPosY != 0; - // Show large or small time depending on info entry - if(menuTextFun == null){ - g.setLargeFont(); - g.drawString(timeStr, W/2, y); - return; - } else { - y -= 15; - g.setMediumFont(); - g.drawString(timeStr, W/2, y); + y -= 15; + g.setMediumFont(); + g.drawString(timeStr, W/2, y); + + // Draw item if needed + var appItems = clock_items[0]; + console.log(appItems.name); + + var item = appItems.items[0]; + console.log(item.name); + function drawItem() { + console.log("Draw item", item.name); + + g.setFontAlign(0,0); + g.setSmallFont(); + + y += 35; + var info = item.get(); + var imgWidth = 24; + var strWidth = g.stringWidth(info.text); + g.setColor(g.theme.fg).fillRect(0, y-14, W, H); + g.setColor(g.theme.bg).drawString(info.text, W/2 + imgWidth/2 + 2, y+3); + g.drawImage(info.img, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); } - // Async set the menu (could be that some data is async fetched) - menuTextFun((menuText, oldX, oldY) => { - - // We display the text IFF the user did not change the menu - if(settings.menuPosX != oldX || settings.menuPosY != oldY){ - return; - } - - // As its a callback, we have to ensure that the color - // font etc. is still correct... - g.setColor(g.theme.bg); - g.setFontAlign(0,0); - y += 35; - - if(menuText.split('\n').length > 1){ - g.setMiniFont(); - } else { - g.setSmallFont(); - } - - var imgWidth = 0; - if(menuImg){ - imgWidth = 24.0; - var strWidth = g.stringWidth(menuText); - var scale = imgWidth / menuImg.width; - g.drawImage( - menuImg, - W/2 + (printImgLeft ? -strWidth/2-4 : strWidth/2+4) - parseInt(imgWidth/2), - y - parseInt(imgWidth/2), - { scale: scale } - ); - } - g.drawString(menuText, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); - }); + item.on('redraw', drawItem); + item.show(); } @@ -715,10 +356,10 @@ Bangle.on('touch', function(btn, e){ settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].length; // Handle custom menu entry function - var menuEntry = getMenuEntry(); - if(menuEntry.length > 2){ - menuEntry[2](); - } + // var menuEntry = getMenuEntry(); + // if(menuEntry.length > 2){ + // menuEntry[2](); + // } drawTime(); } @@ -733,10 +374,10 @@ Bangle.on('touch', function(btn, e){ settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].length-1 : settings.menuPosY; // Handle custom menu entry function - var menuEntry = getMenuEntry(); - if(menuEntry.length > 3){ - menuEntry[3](); - } + // var menuEntry = getMenuEntry(); + // if(menuEntry.length > 3){ + // menuEntry[3](); + // } drawTime(); } @@ -763,21 +404,21 @@ Bangle.on('touch', function(btn, e){ } if(is_center){ - var menuEntry = getMenuEntry(); - if(menuEntry.length > 4 && menuEntry[4] != null){ - Bangle.buzz(80, 0.6).then(()=>{ - try{ - menuEntry[4](); - setTimeout(()=>{ - Bangle.buzz(80, 0.6); - drawTime(); - }, 250); - } catch(ex){ - // In case it fails, we simply ignore it. - } - } - ); - } + // var menuEntry = getMenuEntry(); + // if(menuEntry.length > 4 && menuEntry[4] != null){ + // Bangle.buzz(80, 0.6).then(()=>{ + // try{ + // menuEntry[4](); + // setTimeout(()=>{ + // Bangle.buzz(80, 0.6); + // drawTime(); + // }, 250); + // } catch(ex){ + // // In case it fails, we simply ignore it. + // } + // } + // ); + // } } }); From daedc1068e2101a134c6bdf9fea01534245a04b8 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 12 Sep 2022 07:20:11 +0200 Subject: [PATCH 03/72] Some improvements --- apps/bwclk/app.js | 133 +++++++++++++++++++++++++--------------------- 1 file changed, 72 insertions(+), 61 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 15de3f870..93fc0f1d7 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -44,14 +44,12 @@ Graphics.prototype.setLargeFont = function(scale) { return this; }; - Graphics.prototype.setMediumFont = function(scale) { // Actual height 41 (42 - 2) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAB/AAAAAAAP/AAAAAAD//AAAAAA///AAAAAP///AAAAB///8AAAAf///AAAAH///wAAAB///+AAAAH///gAAAAH//4AAAAAH/+AAAAAAH/wAAAAAAH8AAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAH////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gAAH+AAD+AAAD/AAH8AAAB/AAH4AAAA/gAH4AAAAfgAH4AAAAfgAPwAAAAfgAPwAAAAfgAPwAAAAfgAHwAAAAfgAH4AAAAfgAH4AAAA/gAH8AAAA/AAD+AAAD/AAD/gAAH/AAB/////+AAB/////8AAA/////4AAAf////wAAAH////gAAAB///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAfwAAAAAAA/gAAAAAAA/AAAAAAAB/AAAAAAAD+AAAAAAAD8AAAAAAAH8AAAAAAAH//////AAH//////AAH//////AAH//////AAH//////AAH//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAA/AAAP4AAB/AAAf4AAD/AAA/4AAD/AAB/4AAH/AAD/4AAP/AAH/AAAf/AAH8AAA//AAH4AAB//AAP4AAD//AAPwAAH+/AAPwAAP8/AAPwAAf4/AAPwAA/4/AAPwAA/w/AAPwAB/g/AAPwAD/A/AAP4AH+A/AAH8AP8A/AAH/A/4A/AAD///wA/AAD///gA/AAB///AA/AAA//+AA/AAAP/8AA/AAAD/wAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAH4AAAHwAAH4AAAH4AAH4AAAH8AAH4AAAP+AAH4AAAH+AAH4A4AB/AAH4A+AA/AAH4B/AA/gAH4D/AAfgAH4H+AAfgAH4P+AAfgAH4f+AAfgAH4/+AAfgAH5/+AAfgAH5//AAfgAH7+/AA/gAH/8/gB/AAH/4f4H/AAH/wf//+AAH/gP//8AAH/AH//8AAH+AD//wAAH8AB//gAAD4AAf+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAD/AAAAAAAP/AAAAAAB//AAAAAAH//AAAAAAf//AAAAAB///AAAAAH///AAAAAf/8/AAAAB//w/AAAAH/+A/AAAA//4A/AAAD//gA/AAAH/+AA/AAAH/4AA/AAAH/gAA/AAAH+AAA/AAAHwAAA/AAAHAAf///AAEAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAP/AHgAAH///AP4AAH///gP8AAH///gP8AAH///gP+AAH///gD/AAH/A/AB/AAH4A/AA/gAH4A+AAfgAH4B+AAfgAH4B+AAfgAH4B8AAfgAH4B8AAfgAH4B+AAfgAH4B+AAfgAH4B+AA/gAH4B/AA/AAH4A/gD/AAH4A/4H+AAH4Af//+AAH4AP//8AAH4AP//4AAHwAD//wAAAAAB//AAAAAAAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAD////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gP4H+AAD/AfgD/AAH8A/AB/AAH8A/AA/gAH4B+AAfgAH4B+AAfgAPwB8AAfgAPwB8AAfgAPwB+AAfgAPwB+AAfgAH4B+AAfgAH4B/AA/gAH8B/AB/AAH+A/wD/AAD+A/8P+AAB8Af//+AAB4AP//8AAAwAH//4AAAAAD//gAAAAAA//AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAHAAPwAAAA/AAPwAAAD/AAPwAAAf/AAPwAAB//AAPwAAP//AAPwAA//8AAPwAH//wAAPwAf/+AAAPwB//4AAAPwP//AAAAPw//8AAAAP3//gAAAAP//+AAAAAP//wAAAAAP//AAAAAAP/4AAAAAAP/gAAAAAAP+AAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAAAH+A//gAAAf/h//4AAA//z//8AAB/////+AAD/////+AAD///+H/AAH+H/4B/AAH8B/wA/gAH4A/gAfgAH4A/gAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAH4A/gAfgAH4A/gAfgAH8B/wA/gAH/H/4B/AAD///+H/AAD/////+AAB/////+AAA//z//8AAAf/h//4AAAH+A//gAAAAAAH+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAD/8AAAAAAP/+AAAAAAf//AAcAAA///gA8AAB///wB+AAD/x/4B/AAD+AP4B/AAH8AH8A/gAH4AH8A/gAH4AD8AfgAP4AD8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAH4AD8AfgAH4AD4A/gAH8AH4B/AAD+APwD/AAD/g/wP+AAB/////+AAA/////8AAAf////4AAAP////wAAAH////AAAAA///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DxcjFyAfISAiHCAiEg=="), 54+(scale<<8)+(1<<16)); return this; }; - Graphics.prototype.setSmallFont = function(scale) { // Actual height 28 (27 - 0) this.setFontCustom( @@ -63,7 +61,6 @@ Graphics.prototype.setSmallFont = function(scale) { return this; }; - Graphics.prototype.setMiniFont = function(scale) { // Actual height 16 (15 - 0) this.setFontCustom( @@ -75,8 +72,6 @@ Graphics.prototype.setMiniFont = function(scale) { return this; }; - - function imgLock(){ return { width : 16, height : 16, bpp : 1, @@ -91,6 +86,7 @@ function load() { // info used for drawing... var hrm = "--"; var alt = "--"; + var interval = null; // callbacks (needed for easy removal of listeners) function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } function stepUpdateHandler() { bangleItems[1].emit("redraw"); } @@ -102,24 +98,29 @@ function load() { bangleItems[3].emit("redraw"); }); } + function deleteInterval(inter){ + if(inter){ + clearInterval(inter); + } + delete inter; + } // actual items - var items = [ - { + var items = [{ name: "Bangle", - img: atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC"), + img: atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA=="), items: [ { name : "Battery", get : () => ({ text : E.getBattery() + "%", img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") }), show : function() { - this.interval = setInterval(()=>this.emit('redraw'), 60000); + deleteInterval(interval); + interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); batteryUpdateHandler(); }, hide : function() { - clearInterval(this.interval); - delete this.interval; + deleteInterval(interval); Bangle.removeListener("charging", batteryUpdateHandler); }, }, @@ -143,8 +144,8 @@ function load() { bangleItems.push({ name : "Altitude", get : () => ({ text : alt, img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { this.interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, - hide : function() { clearInterval(this.interval); delete this.interval; }, + show : function() { deleteInterval(); interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, + hide : function() { deleteInterval(); }, }); } @@ -159,7 +160,41 @@ function load() { // clock_info ######################################################## -var clock_items = load(); +// Load menu +var menu = load(); + +// Set draw functions for each item +menu.forEach((menuItm, x) => { + menuItm.items.forEach((item, y) => { + function drawItem() { + // Once shown, we can disable it afterwards... + item.hide(); + + console.log("Draw item", item.name); + + g.setFontAlign(0,0); + g.setSmallFont(); + + var y = 147; + var info = item.get(); + var imgWidth = 24; + var strWidth = g.stringWidth(info.text); + g.setColor(g.theme.fg).fillRect(0, y-14, W, H); + g.setColor(g.theme.bg).drawString(info.text, W/2 + imgWidth/2 + 2, y+3); + g.drawImage(info.img, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); + } + + item.on('redraw', drawItem); + }) +}); + +/************ + * Custom menu elements + * Those are BW custom and should not be available + * for other clocks... + */ + + /************ @@ -185,6 +220,7 @@ function draw() { // Draw clock drawDate(); drawTime(); + drawMenu(); drawLock(); drawWidgets(); } @@ -244,30 +280,23 @@ function drawTime(){ y -= 15; g.setMediumFont(); g.drawString(timeStr, W/2, y); +} - // Draw item if needed - var appItems = clock_items[0]; - console.log(appItems.name); - var item = appItems.items[0]; - console.log(item.name); - function drawItem() { - console.log("Draw item", item.name); +function drawMenu(){ + if(settings.menuPosX < 0){ - g.setFontAlign(0,0); - g.setSmallFont(); + return; + } - y += 35; - var info = item.get(); - var imgWidth = 24; - var strWidth = g.stringWidth(info.text); - g.setColor(g.theme.fg).fillRect(0, y-14, W, H); - g.setColor(g.theme.bg).drawString(info.text, W/2 + imgWidth/2 + 2, y+3); - g.drawImage(info.img, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); - } + // Draw item if needed + var menuEntry = menu[settings.menuPosX]; + console.log(menuEntry.name); - item.on('redraw', drawItem); - item.show(); + var item = menuEntry.items[settings.menuPosY]; + console.log(item.name); + + item.show(); } @@ -333,8 +362,8 @@ Bangle.on('charging',function(charging) { drawTimeout = undefined; // Jump to battery - settings.menuPosX = 1; - settings.menuPosY = 1; + settings.menuPosX = 0; + settings.menuPosY = 0; draw(); }); @@ -353,15 +382,9 @@ Bangle.on('touch', function(btn, e){ if(is_lower){ Bangle.buzz(40, 0.6); - settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].length; + settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].items.length; - // Handle custom menu entry function - // var menuEntry = getMenuEntry(); - // if(menuEntry.length > 2){ - // menuEntry[2](); - // } - - drawTime(); + drawMenu(); } if(is_upper){ @@ -371,36 +394,24 @@ Bangle.on('touch', function(btn, e){ Bangle.buzz(40, 0.6); settings.menuPosY = settings.menuPosY-1; - settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].length-1 : settings.menuPosY; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length-1 : settings.menuPosY; - // Handle custom menu entry function - // var menuEntry = getMenuEntry(); - // if(menuEntry.length > 3){ - // menuEntry[3](); - // } - - drawTime(); + drawMenu(); } if(is_right){ - // A bit hacky but we ensure that always the first agenda entry is shown... - agendaIdx = 0; - Bangle.buzz(40, 0.6); settings.menuPosX = (settings.menuPosX+1) % menu.length; - settings.menuPosY = 0; - drawTime(); + settings.menuPosY = -1; + drawMenu(); } if(is_left){ - // A bit hacky but we ensure that always the first agenda entry is shown... - agendaIdx = 0; - Bangle.buzz(40, 0.6); - settings.menuPosY = 0; + settings.menuPosY = -1; settings.menuPosX = settings.menuPosX-1; settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; - drawTime(); + drawMenu(); } if(is_center){ From f4b1eb00328681c0fd50dd323bd3b1ba8b9a0ce2 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 12 Sep 2022 07:25:32 +0200 Subject: [PATCH 04/72] First menu is already working. --- apps/bwclk/app.js | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 93fc0f1d7..dd4856aa0 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -172,22 +172,15 @@ menu.forEach((menuItm, x) => { console.log("Draw item", item.name); - g.setFontAlign(0,0); - g.setSmallFont(); - - var y = 147; var info = item.get(); - var imgWidth = 24; - var strWidth = g.stringWidth(info.text); - g.setColor(g.theme.fg).fillRect(0, y-14, W, H); - g.setColor(g.theme.bg).drawString(info.text, W/2 + imgWidth/2 + 2, y+3); - g.drawImage(info.img, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); + drawMenuItem(info.text, info.img); } item.on('redraw', drawItem); }) }); + /************ * Custom menu elements * Those are BW custom and should not be available @@ -283,9 +276,24 @@ function drawTime(){ } -function drawMenu(){ - if(settings.menuPosX < 0){ +function drawMenuItem(text, image){ + g.setFontAlign(0,0); + g.setSmallFont(); + var y = 147; + var imgWidth = 24; + var strWidth = g.stringWidth(text); + g.setColor(g.theme.fg).fillRect(0, y-14, W, H); + g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, y+3); + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); +} + + +function drawMenu(){ + // Draw category if needed + if(settings.menuPosY < 0){ + var menuEntry = menu[settings.menuPosX]; + drawMenuItem(menuEntry.name, menuEntry.img); return; } From a1e03d322978191c4165aaa898548bcde7c0dfd3 Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 14 Sep 2022 21:53:04 +0200 Subject: [PATCH 05/72] [widbt_notify] Simplify code, add some options --- apps/widbt_notify/ChangeLog | 3 +- apps/widbt_notify/metadata.json | 4 +- apps/widbt_notify/settings.js | 90 +++++++--------- apps/widbt_notify/widget.js | 175 ++++++++++++++------------------ 4 files changed, 119 insertions(+), 153 deletions(-) diff --git a/apps/widbt_notify/ChangeLog b/apps/widbt_notify/ChangeLog index 8f1dab908..b9ecd7b7d 100644 --- a/apps/widbt_notify/ChangeLog +++ b/apps/widbt_notify/ChangeLog @@ -11,4 +11,5 @@ 0.12: Prevent repeated execution of `draw()` from the current app. 0.13: Added "connection restored" notification. Fixed restoring of the watchface. 0.14: Added configuration option -0.15: Added option to hide widget when connected \ No newline at end of file +0.15: Added option to hide widget when connected +0.16: Simplify code, add option to disable displaying a message \ No newline at end of file diff --git a/apps/widbt_notify/metadata.json b/apps/widbt_notify/metadata.json index 6def70c64..626ffcb8b 100644 --- a/apps/widbt_notify/metadata.json +++ b/apps/widbt_notify/metadata.json @@ -1,8 +1,8 @@ { "id": "widbt_notify", "name": "Bluetooth Widget with Notification", - "version": "0.15", - "description": "Show the current Bluetooth connection status in the top right of the watch. Optional buzz and/or and hide if disconnected", + "version": "0.16", + "description": "Show the current Bluetooth connection status with some optional features: show message, buzz on connect/loss, hide always/if connected.", "icon": "widget.png", "type": "widget", "tags": "widget,bluetooth", diff --git a/apps/widbt_notify/settings.js b/apps/widbt_notify/settings.js index 1e0d5036b..5c67fed7b 100644 --- a/apps/widbt_notify/settings.js +++ b/apps/widbt_notify/settings.js @@ -1,69 +1,57 @@ (function(back) { - var FILE = "widbt_notify.json"; + + var filename = "widbt_notify.json"; + + // set Storage and load settings + var storage = require("Storage"); var settings = Object.assign({ - secondsOnUnlock: false, - }, require('Storage').readJSON(FILE, true) || {}); + showWidget: true, + buzzOnConnect: true, + buzzOnLoss: true, + hideConnected: true, + showMessage: true, + nextBuzz: 30000 + }, storage.readJSON(filename, true) || {}); - function writeSettings() { - require('Storage').writeJSON(FILE, settings); - } - - // Helper method which uses int-based menu item for set of string values - function stringItems(startvalue, writer, values) { + // setup boolean menu entries + function boolEntry(key) { return { - value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), - format: v => values[v], - min: 0, - max: values.length - 1, - wrap: true, - step: 1, + value: settings[key], onchange: v => { - writer(values[v]); - writeSettings(); + // change the value of key + settings[key] = v; + // write to storage + storage.writeJSON(filename, settings); } }; } - // Helper method which breaks string set settings down to local settings object - function stringInSettings(name, values) { - return stringItems(settings[name], v => settings[name] = v, values); - } - - var mainmenu = { + // setup menu + var menu = { "": { "title": "Bluetooth Widget WN" }, "< Back": () => back(), - "Show Widget": { - value: (settings.showWidget !== undefined ? settings.showWidget : true), + "Show Widget": boolEntry("showWidget"), + "Buzz on connect": boolEntry("buzzOnConnect"), + "Buzz on loss": boolEntry("buzzOnLoss"), + "Hide connected": boolEntry("hideConnected"), + "Show Message": boolEntry("showMessage"), + "Next Buzz": { + value: settings.nextBuzz, + step: 1000, + min: 1000, + max: 120000, + wrap: true, + format: v => (v / 1000) + "s", onchange: v => { - settings.showWidget = v; - writeSettings(); + settings.nextBuzz = v; + storage.writeJSON(filename, settings); } - }, - "Buzz on Connect": { - value: (settings.buzzOnConnect !== undefined ? settings.buzzOnConnect : true), - onchange: v => { - settings.buzzOnConnect = v; - writeSettings(); - } - }, - "Buzz on loss": { - value: (settings.buzzOnLoss !== undefined ? settings.buzzOnLoss : true), - onchange: v => { - settings.buzzOnLoss = v; - writeSettings(); - } - }, - "Hide connected": { - value: (settings.hideConnected !== undefined ? settings.hideConnected : false), - onchange: v => { - settings.hideConnected = v; - writeSettings(); - } - } + } }; - E.showMenu(mainmenu); + // draw main menu + E.showMenu(menu); -}); +}) \ No newline at end of file diff --git a/apps/widbt_notify/widget.js b/apps/widbt_notify/widget.js index de2baa3cf..8828d5ca3 100644 --- a/apps/widbt_notify/widget.js +++ b/apps/widbt_notify/widget.js @@ -1,110 +1,87 @@ -WIDGETS.bluetooth_notify = { +(function() { + // load settings + var settings = Object.assign({ + showWidget: true, + buzzOnConnect: true, + buzzOnLoss: true, + hideConnected: true, + showMessage: true, + nextBuzz: 30000 + }, require("Storage").readJSON("widbt_notify.json", true) || {}); + + // setup widget with to hide if not connected and option set + var widWidth = settings.hideConnected && !NRF.getSecurityStatus().connected ? 0 : 15; + + // write widget with loaded settings + WIDGETS.bluetooth_notify = Object.assign(settings, { + + // set area and width area: "tr", - width: 15, + width: widWidth, + + // setup warning status warningEnabled: 1, - // ------------ Settings -------- very lame - need to improve - readshowWidget: function() { - var showWidget; - const SETTINGSFILE = "widbt_notify.json"; - function def (value, def) {return value !== undefined ? value : def;} - var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - showWidget = def(settings.showWidget, true); - return showWidget; - }, - - readBuzzOnConnect: function() { - var buzzOnConnect; - const SETTINGSFILE = "widbt_notify.json"; - function def (value, def) {return value !== undefined ? value : def;} - var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - buzzOnConnect = def(settings.buzzOnConnect, true); - return buzzOnConnect; - }, - - readBuzzOnLoss: function() { - var buzzOnLoss; - const SETTINGSFILE = "widbt_notify.json"; - function def (value, def) {return value !== undefined ? value : def;} - var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - buzzOnLoss = def(settings.buzzOnLoss, true); - return buzzOnLoss; - }, - - readHideConnected: function() { - var hideConnected; - const SETTINGSFILE = "widbt_notify.json"; - function def (value, def) {return value !== undefined ? value : def;} - var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - hideConnected = def(settings.hideConnected, true); - return hideConnected; - }, - - - // ------------ Settings -------- - draw: function() { - if (WIDGETS.bluetooth_notify.readshowWidget()){ - g.reset(); - if (NRF.getSecurityStatus().connected) { - if (!WIDGETS.bluetooth_notify.readHideConnected()) { - g.setColor((g.getBPP() > 8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f")); - g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y); - } - } else { - // g.setColor(g.theme.dark ? "#666" : "#999"); - g.setColor("#f00"); // red is easier to distinguish from blue - g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y); - } + if (this.showWidget) { + g.reset(); + if (NRF.getSecurityStatus().connected) { + if (!this.hideConnected) { + g.setColor((g.getBPP() > 8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f")); + g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y); + } + } else { + // g.setColor(g.theme.dark ? "#666" : "#999"); + g.setColor("#f00"); // red is easier to distinguish from blue + g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="), 2 + this.x, 2 + this.y); } + } }, - - redrawCurrentApp: function(){ - if(typeof(draw)=='function'){ - g.clear(); - draw(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - }else{ - load(); // fallback. This might reset some variables + + redrawCurrentApp: function() { + if (typeof(draw) == 'function') { + g.clear(); + draw(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + } else { + load(); // fallback. This might reset some variables + } + }, + + onNRF: function(connect) { + if (this.warningEnabled) { + if (this.showMessage) { + E.showMessage( /*LANG*/ 'Connection\n' + (connect ? /*LANG*/ 'restored.' : /*LANG*/ 'lost.'), 'Bluetooth'); + setTimeout(() => { + WIDGETS.bluetooth_notify.redrawCurrentApp(); + }, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'. } - }, - - connect: function() { - if(WIDGETS.bluetooth_notify.warningEnabled == 1){ - E.showMessage(/*LANG*/'Connection\nrestored.', 'Bluetooth'); - setTimeout(()=>{WIDGETS.bluetooth_notify.redrawCurrentApp();}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'. - - WIDGETS.bluetooth_notify.warningEnabled = 0; - setTimeout('WIDGETS.bluetooth_notify.warningEnabled = 1;', 30000); // don't buzz for the next 30 seconds. - - var quiet = (require('Storage').readJSON('setting.json',1)||{}).quiet; - if(!quiet && WIDGETS.bluetooth_notify.readBuzzOnConnect()){ - Bangle.buzz(700, 1); // buzz on connection resume - } - } - WIDGETS.bluetooth_notify.draw(); + this.warningEnabled = 0; + setTimeout('WIDGETS.bluetooth_notify.warningEnabled = 1;', this.nextBuzz); // don't buzz for the next X seconds. - }, - - disconnect: function() { - if(WIDGETS.bluetooth_notify.warningEnabled == 1){ - E.showMessage(/*LANG*/ 'Connection\nlost.', 'Bluetooth'); - setTimeout(()=>{WIDGETS.bluetooth_notify.redrawCurrentApp();}, 3000); // clear message - this will reload the widget, resetting 'warningEnabled'. - - WIDGETS.bluetooth_notify.warningEnabled = 0; - setTimeout('WIDGETS.bluetooth_notify.warningEnabled = 1;', 30000); // don't buzz for the next 30 seconds. - - var quiet = (require('Storage').readJSON('setting.json',1)||{}).quiet; - if(!quiet && WIDGETS.bluetooth_notify.readBuzzOnLoss()){ - Bangle.buzz(700, 1); // buzz on connection loss - } - } - - WIDGETS.bluetooth_notify.draw(); + var quiet = (require('Storage').readJSON('setting.json', 1) || {}).quiet; + if (!quiet && (connect ? this.buzzOnConnect : this.buzzOnLoss)) { + Bangle.buzz(700, 1); // buzz on connection resume or loss + } + } + // if hideConnected is en- and showMessage disabled, redraw widgets to hide + if (this.hideConnected && !this.showMessage) { + Bangle.drawWidgets(); + } else { + this.draw(); + } } -}; -NRF.on('connect', WIDGETS.bluetooth_notify.connect); -NRF.on('disconnect', WIDGETS.bluetooth_notify.disconnect); + }); + + // clear variables + settings = undefined; + widWidth = undefined; + + // setup bluetooth connection events + NRF.on('connect', (addr) => WIDGETS.bluetooth_notify.onNRF(addr)); + NRF.on('disconnect', () => WIDGETS.bluetooth_notify.onNRF()); + +})() \ No newline at end of file From d02e5db24b8cb5f526c6acccc7b9c314cb6da023 Mon Sep 17 00:00:00 2001 From: David Peer Date: Thu, 15 Sep 2022 21:01:43 +0200 Subject: [PATCH 06/72] Improvements --- apps/bwclk/app.js | 93 +++++++++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index dd4856aa0..b88bb894c 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -88,14 +88,14 @@ function load() { var alt = "--"; var interval = null; // callbacks (needed for easy removal of listeners) - function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } - function stepUpdateHandler() { bangleItems[1].emit("redraw"); } - function hrmUpdateHandler() { bangleItems[2].emit("redraw"); } + function batteryUpdateHandler() { bangleItems[1].emit("redraw"); } + function stepUpdateHandler() { bangleItems[2].emit("redraw"); } + function hrmUpdateHandler() { bangleItems[3].emit("redraw"); } function altUpdateHandler() { Bangle.getPressure().then(data=>{ if (!data) return; alt = Math.round(data.altitude) + "m"; - bangleItems[3].emit("redraw"); + bangleItems[4].emit("redraw"); }); } function deleteInterval(inter){ @@ -109,6 +109,11 @@ function load() { name: "Bangle", img: atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA=="), items: [ + { name: "Overview", + get: () => ({ text: "Bangle", img: null}), + show: function() { bangleItems[0].emit("redraw"); }, + hide: function () {} + }, { name : "Battery", get : () => ({ text : E.getBattery() + "%", @@ -169,9 +174,6 @@ menu.forEach((menuItm, x) => { function drawItem() { // Once shown, we can disable it afterwards... item.hide(); - - console.log("Draw item", item.name); - var info = item.get(); drawMenuItem(info.text, info.img); } @@ -212,8 +214,7 @@ function draw() { // Draw clock drawDate(); - drawTime(); - drawMenu(); + drawMenuAndTime(); drawLock(); drawWidgets(); } @@ -221,8 +222,8 @@ function draw() { function drawDate(){ // Draw background - var y = H/5*2; - g.reset().clearRect(0,0,W,W); + var y = H/5*2 + (isFullscreen() ? 0 : 8); + g.reset().clearRect(0,0,W,y); // Draw date y = parseInt(y/2)+4; @@ -249,11 +250,8 @@ function drawDate(){ } -function drawTime(){ +function drawTime(y, smallText){ // Draw background - var y = H/5*2 + (isFullscreen() ? 0 : 8); - g.setColor(g.theme.fg); - g.fillRect(0,y,W,H); var date = new Date(); // Draw time @@ -270,40 +268,47 @@ function drawTime(){ y += parseInt((H - y)/2) + 5; // Show large or small time depending on info entry - y -= 15; - g.setMediumFont(); + if(smallText){ + y -= 15; + g.setMediumFont(); + } else { + g.setLargeFont(); + } g.drawString(timeStr, W/2, y); } - function drawMenuItem(text, image){ - g.setFontAlign(0,0); - g.setSmallFont(); + // First clear the time region + var y = H/5*2 + (isFullscreen() ? 0 : 8); - var y = 147; - var imgWidth = 24; - var strWidth = g.stringWidth(text); - g.setColor(g.theme.fg).fillRect(0, y-14, W, H); - g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, y+3); - g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), y - parseInt(imgWidth/2)); + g.setColor(g.theme.fg); + g.fillRect(0,y,W,H); + + // Draw menu text + var hasText = (text != null && text != ""); + if(hasText){ + g.setFontAlign(0,0); + g.setSmallFont(); + + var imgWidth = image == null ? 0 : 24; + var strWidth = g.stringWidth(text); + g.setColor(g.theme.fg).fillRect(0, 147-14, W, H); + g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, 147+3); + + if(image != null){ + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 147 - parseInt(imgWidth/2)); + } + } + + // Draw time + drawTime(y, hasText); } -function drawMenu(){ - // Draw category if needed - if(settings.menuPosY < 0){ - var menuEntry = menu[settings.menuPosX]; - drawMenuItem(menuEntry.name, menuEntry.img); - return; - } - +function drawMenuAndTime(){ // Draw item if needed var menuEntry = menu[settings.menuPosX]; - console.log(menuEntry.name); - var item = menuEntry.items[settings.menuPosY]; - console.log(item.name); - item.show(); } @@ -392,7 +397,7 @@ Bangle.on('touch', function(btn, e){ Bangle.buzz(40, 0.6); settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].items.length; - drawMenu(); + drawMenuAndTime(); } if(is_upper){ @@ -404,22 +409,22 @@ Bangle.on('touch', function(btn, e){ settings.menuPosY = settings.menuPosY-1; settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length-1 : settings.menuPosY; - drawMenu(); + drawMenuAndTime(); } if(is_right){ Bangle.buzz(40, 0.6); settings.menuPosX = (settings.menuPosX+1) % menu.length; - settings.menuPosY = -1; - drawMenu(); + settings.menuPosY = 0; + drawMenuAndTime(); } if(is_left){ Bangle.buzz(40, 0.6); - settings.menuPosY = -1; + settings.menuPosY = 0; settings.menuPosX = settings.menuPosX-1; settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; - drawMenu(); + drawMenuAndTime(); } if(is_center){ From 61bff3306f8087ef7938750095dd9a8bbbbf9c45 Mon Sep 17 00:00:00 2001 From: David Peer Date: Thu, 15 Sep 2022 21:16:00 +0200 Subject: [PATCH 07/72] Next improvements --- apps/bwclk/app.js | 52 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index b88bb894c..8a4b69aaa 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -106,11 +106,10 @@ function load() { } // actual items var items = [{ - name: "Bangle", - img: atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA=="), + id: "bangle", items: [ { name: "Overview", - get: () => ({ text: "Bangle", img: null}), + get: () => ({ text: "Bangle", img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w==")}), show: function() { bangleItems[0].emit("redraw"); }, hide: function () {} }, @@ -165,15 +164,39 @@ function load() { // clock_info ######################################################## +// Custom menus +var clockItems = { + id: "bw_clock", + items: [ + { name: "Overview", + get: () => ({ text: null, img: null}), + show: function() { clockItems.items[0].emit("redraw"); }, + hide: function () {} + }, + { name: "Overview", + get: () => ({ text: "Week " + weekOfYear(), img: null}), + show: function() { clockItems.items[1].emit("redraw"); }, + hide: function () {} + }, + ] +}; + + // Load menu var menu = load(); +menu = menu.concat(clockItems); + // Set draw functions for each item menu.forEach((menuItm, x) => { menuItm.items.forEach((item, y) => { function drawItem() { - // Once shown, we can disable it afterwards... + // For the clock, we have a special case, as we don't wanna redraw + // immediately when something changes. Instead, we update data each minute + // to save some battery etc. Therefore, we hide (and disable the listener) + // immedeately after redraw... item.hide(); + var info = item.get(); drawMenuItem(info.text, info.img); } @@ -183,14 +206,6 @@ menu.forEach((menuItm, x) => { }); -/************ - * Custom menu elements - * Those are BW custom and should not be available - * for other clocks... - */ - - - /************ * Helper @@ -205,6 +220,19 @@ function isFullscreen(){ } +function weekOfYear() { + var date = new Date(); + date.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); + // January 4 is always in week 1. + var week1 = new Date(date.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 + - 3 + (week1.getDay() + 6) % 7) / 7); +} + + /************ * DRAW */ From 77e1821cf44ca70cd95718bd00de4a84421509d5 Mon Sep 17 00:00:00 2001 From: David Peer Date: Thu, 15 Sep 2022 21:44:47 +0200 Subject: [PATCH 08/72] Minor changes --- apps/bwclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 8a4b69aaa..e031ef556 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -173,7 +173,7 @@ var clockItems = { show: function() { clockItems.items[0].emit("redraw"); }, hide: function () {} }, - { name: "Overview", + { name: "WeekOfYear", get: () => ({ text: "Week " + weekOfYear(), img: null}), show: function() { clockItems.items[1].emit("redraw"); }, hide: function () {} From 274544ec0f83d78738f4bb02eaa808e7215ac3e9 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 17 Sep 2022 17:14:20 +0200 Subject: [PATCH 09/72] Several improvements --- apps/bwclk/app.js | 45 ++++++++++++++++++++++----------------------- 1 file changed, 22 insertions(+), 23 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index e031ef556..a0035222e 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -88,14 +88,14 @@ function load() { var alt = "--"; var interval = null; // callbacks (needed for easy removal of listeners) - function batteryUpdateHandler() { bangleItems[1].emit("redraw"); } - function stepUpdateHandler() { bangleItems[2].emit("redraw"); } - function hrmUpdateHandler() { bangleItems[3].emit("redraw"); } + function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } + function stepUpdateHandler() { bangleItems[1].emit("redraw"); } + function hrmUpdateHandler() { bangleItems[2].emit("redraw"); } function altUpdateHandler() { Bangle.getPressure().then(data=>{ if (!data) return; alt = Math.round(data.altitude) + "m"; - bangleItems[4].emit("redraw"); + bangleItems[3].emit("redraw"); }); } function deleteInterval(inter){ @@ -106,13 +106,9 @@ function load() { } // actual items var items = [{ - id: "bangle", + name: "Bangle", + img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), items: [ - { name: "Overview", - get: () => ({ text: "Bangle", img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w==")}), - show: function() { bangleItems[0].emit("redraw"); }, - hide: function () {} - }, { name : "Battery", get : () => ({ text : E.getBattery() + "%", @@ -166,16 +162,12 @@ function load() { // Custom menus var clockItems = { - id: "bw_clock", + name: null, + img: null, items: [ - { name: "Overview", - get: () => ({ text: null, img: null}), - show: function() { clockItems.items[0].emit("redraw"); }, - hide: function () {} - }, { name: "WeekOfYear", get: () => ({ text: "Week " + weekOfYear(), img: null}), - show: function() { clockItems.items[1].emit("redraw"); }, + show: function() { clockItems.items[0].emit("redraw"); }, hide: function () {} }, ] @@ -334,10 +326,17 @@ function drawMenuItem(text, image){ function drawMenuAndTime(){ - // Draw item if needed - var menuEntry = menu[settings.menuPosX]; - var item = menuEntry.items[settings.menuPosY]; - item.show(); + var menuEntry = menu[settings.menuPosX]; + + // The first entry is the overview... + if(settings.menuPosY == 0){ + drawMenuItem(menuEntry.name, menuEntry.img); + return; + } + + // Draw item if needed + var item = menuEntry.items[settings.menuPosY-1]; + item.show(); } @@ -423,7 +422,7 @@ Bangle.on('touch', function(btn, e){ if(is_lower){ Bangle.buzz(40, 0.6); - settings.menuPosY = (settings.menuPosY+1) % menu[settings.menuPosX].items.length; + settings.menuPosY = (settings.menuPosY+1) % (menu[settings.menuPosX].items.length+1); drawMenuAndTime(); } @@ -435,7 +434,7 @@ Bangle.on('touch', function(btn, e){ Bangle.buzz(40, 0.6); settings.menuPosY = settings.menuPosY-1; - settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length-1 : settings.menuPosY; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length : settings.menuPosY; drawMenuAndTime(); } From 37ff21b7fa7a8534ecc66a1cd6e5008b0366c3f4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 17 Sep 2022 17:26:43 +0200 Subject: [PATCH 10/72] Improved input through locking --- apps/bwclk/app.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index a0035222e..0474cacf1 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -28,6 +28,7 @@ for (const key in saved_settings) { settings[key] = saved_settings[key] } +var lock_input = false; /************ * Assets @@ -189,6 +190,9 @@ menu.forEach((menuItm, x) => { // immedeately after redraw... item.hide(); + // After drawing the item, we enable inputs again... + lock_input = false; + var info = item.get(); drawMenuItem(info.text, info.img); } @@ -335,6 +339,7 @@ function drawMenuAndTime(){ } // Draw item if needed + lock_input = true; var item = menuEntry.items[settings.menuPosY-1]; item.show(); } @@ -420,6 +425,10 @@ Bangle.on('touch', function(btn, e){ var is_right = e.x > right && !is_upper && !is_lower; var is_center = !is_upper && !is_lower && !is_left && !is_right; + if(lock_input){ + return; + } + if(is_lower){ Bangle.buzz(40, 0.6); settings.menuPosY = (settings.menuPosY+1) % (menu[settings.menuPosX].items.length+1); From b60f0c4687e078b6fae52e9be1764f064370efbf Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 17 Sep 2022 18:07:43 +0200 Subject: [PATCH 11/72] Added basic version of agenda --- apps/bwclk/app.js | 54 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 0474cacf1..e7fbf6a08 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -82,7 +82,7 @@ function imgLock(){ } -// clock_info ######################################################## +// ----clock_info ------------------------------------------------------ function load() { // info used for drawing... var hrm = "--"; @@ -158,7 +158,7 @@ function load() { // return it all! return items; }; -// clock_info ######################################################## +// ----clock_info ------------------------------------------------------ // Custom menus @@ -175,11 +175,45 @@ var clockItems = { }; +// ----agenda_clock_info ------------------------------------------------------ +var agendaItems = { + name: "Agenda", + img: atob("GBiBAf////////85z/AAAPAAAPgAAP////AAAPAAAPAAAPAAAOAAAeAAAeAAAcAAA8AAAoAABgAADP//+P//8PAAAPAAAPgAAf///w=="), + items: [] +}; + +var now = new Date(); +var agenda = storage.readJSON("android.calendar.json") + .filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000) + .sort((a,b)=>a.timestamp - b.timestamp); + +agenda.forEach((entry, i) => { + + var title = entry.title.slice(0,14); + var date = new Date(entry.timestamp*1000); + var dateStr = locale.date(date).replace(/\d\d\d\d/,""); + dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; + + agendaItems.items.push({ + name: "agendaEntry", + get: () => ({ text: title + "\n" + dateStr, img: null}), + show: function() { agendaItems.items[i].emit("redraw"); }, + hide: function () {} + }); +}); +// ----agenda_clock_info ------------------------------------------------------ + + +var timerItems = {}; +var weatherItems = {}; +var homeAssistantItems = {}; + + // Load menu var menu = load(); +menu = menu.concat(agendaItems); menu = menu.concat(clockItems); - // Set draw functions for each item menu.forEach((menuItm, x) => { menuItm.items.forEach((item, y) => { @@ -312,15 +346,21 @@ function drawMenuItem(text, image){ var hasText = (text != null && text != ""); if(hasText){ g.setFontAlign(0,0); - g.setSmallFont(); + + // For multiline text we show an even smaller font... + if(text.split('\n').length > 1){ + g.setMiniFont(); + } else { + g.setSmallFont(); + } var imgWidth = image == null ? 0 : 24; var strWidth = g.stringWidth(text); - g.setColor(g.theme.fg).fillRect(0, 147-14, W, H); - g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, 147+3); + g.setColor(g.theme.fg).fillRect(0, 149-14, W, H); + g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, 149+3); if(image != null){ - g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 147 - parseInt(imgWidth/2)); + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 149 - parseInt(imgWidth/2)); } } From b06f3a9cc2902dcd0281d4d0b297c6f9735bfb35 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 17 Sep 2022 18:21:54 +0200 Subject: [PATCH 12/72] Added weather --- apps/bwclk/app.js | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index e7fbf6a08..5cbc80bc7 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -204,14 +204,62 @@ agenda.forEach((entry, i) => { // ----agenda_clock_info ------------------------------------------------------ + +// ----weather_clock_info ------------------------------------------------------ +var weather = { + temp: "?", + hum: "?", + wind: "?", +}; + +var weatherJson = storage.readJSON('weather.json'); +if(weatherJson !== undefined && weatherJson.weather !== undefined){ + weather = weatherJson.weather; + weather.temp = locale.temp(weather.temp-273.15); + weather.hum = weather.hum + "%"; + weather.wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + weather.wind = Math.round(weather.wind[1]) + "kph"; +} + +var weatherItems = { + name: "Weather", + img: atob("GBiBAf+///u5//n7//8f/9wHP8gDf/gB//AB/7AH/5AcP/AQH/DwD/uAD84AD/4AA/wAAfAAAfAAAfAAAfgAA/////+bP/+zf/+zfw=="), + items: [ + { + name: "temperature", + get: () => ({ text: weather.temp, img: atob("GBiBAf/D//+B//8Y//88//88//88//88//88//8k//8k//8k//8k//8k//8k//4kf/5mf/zDP/yBP/yBP/zDP/5mf/48f/8A///D/w==")}), + show: function() { weatherItems.items[0].emit("redraw"); }, + hide: function () {} + }, + { + name: "humidity", + get: () => ({ text: weather.hum, img: atob("GBiBAf/7///z///x///g///g///Af//Af/3Af/nA//jg//B/v/B/H+A/H8A+D8AeB8AcB4AYA8AYA8AYA+A4A/B4A//4A//8B///Dw==")}), + show: function() { weatherItems.items[1].emit("redraw"); }, + hide: function () {} + }, + { + name: "wind", + get: () => ({ text: weather.wind, img: atob("GBiBAf4f//wP//nn//Pn//Pzg//nAf/meIAOfAAefP///P//+fAAAfAAB////////wAAP4AAH///z///z//nz//nz//zj//wH//8Pw==")}), + show: function() { weatherItems.items[2].emit("redraw"); }, + hide: function () {} + }, + ] +}; + + + +// ----weather_clock_info ------------------------------------------------------ + + +// Still missing var timerItems = {}; -var weatherItems = {}; var homeAssistantItems = {}; // Load menu var menu = load(); menu = menu.concat(agendaItems); +menu = menu.concat(weatherItems); menu = menu.concat(clockItems); // Set draw functions for each item @@ -348,6 +396,7 @@ function drawMenuItem(text, image){ g.setFontAlign(0,0); // For multiline text we show an even smaller font... + text = String(text); if(text.split('\n').length > 1){ g.setMiniFont(); } else { From 2254fdd04911b6f71993bdf9686eb27683b4ed66 Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sun, 18 Sep 2022 09:28:11 +0000 Subject: [PATCH 13/72] If midnight clear the display to clean up artifacts Since slash is (wisely) very conservative about clearing / redrawing, artifacts from past dates that aren't overwritten tend to stack up. On my watch now where it says "Sun 9/18" there is some left over "T" from last Thursday sticking out to the left of the "S" in "Sun", and some leftover "6" sticking out to the right of the "8" in "18" from two days ago. This should clear everything once a day at midnight so these artifacts get cleared out. --- apps/slash/app.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/slash/app.js b/apps/slash/app.js index f548bcaf7..c594e5916 100644 --- a/apps/slash/app.js +++ b/apps/slash/app.js @@ -57,6 +57,10 @@ function draw() { var minutes = ("0"+m).substr(-2); g.reset(); + // If midnight clear display to remove day / date artifacts + if (h == 0 && m == 0) + g.clear(); + // Convert to 12hr time mode if (is12Hour && h > 12) { h = h - 12; From 3696cff42ac35d358e7d1192078bf66f7299df62 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 18 Sep 2022 11:46:25 +0200 Subject: [PATCH 14/72] Minor fix -- otherwise clock works not properly --- apps/bwclk/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 5cbc80bc7..dea7484af 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -83,7 +83,7 @@ function imgLock(){ // ----clock_info ------------------------------------------------------ -function load() { +function loadClockInfo() { // info used for drawing... var hrm = "--"; var alt = "--"; @@ -257,7 +257,7 @@ var homeAssistantItems = {}; // Load menu -var menu = load(); +var menu = loadClockInfo(); menu = menu.concat(agendaItems); menu = menu.concat(weatherItems); menu = menu.concat(clockItems); From 1d8008c127a5bf2c4d010af79d222bac22947555 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 18 Sep 2022 12:00:58 +0200 Subject: [PATCH 15/72] Added home assistant --- apps/bwclk/app.js | 38 ++++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index dea7484af..e6e621e36 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -195,7 +195,7 @@ agenda.forEach((entry, i) => { dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; agendaItems.items.push({ - name: "agendaEntry", + name: "agendaEntry-" + i, get: () => ({ text: title + "\n" + dateStr, img: null}), show: function() { agendaItems.items[i].emit("redraw"); }, hide: function () {} @@ -245,21 +245,46 @@ var weatherItems = { }, ] }; - - - // ----weather_clock_info ------------------------------------------------------ +// ----ha_clock_info ------------------------------------------------------ +var triggers = require("ha.lib.js").getTriggers(); + +var haItems = { + name: "Home", + img: atob("GBiBAf/////////n///D//+B//8A//48T/wkD/gkD/A8D+AYB8AYA4eZ4QyZMOyZN+fb5+D/B+B+B+A8B+AYB+AYB+AYB+AYB+A8Bw=="), + items: [ + // { + // name: "item1", + // get: () => ({ text: "Item1", img: atob("GBiBAf/D//+B//8Y//88//88//88//88//88//8k//8k//8k//8k//8k//8k//4kf/5mf/zDP/yBP/yBP/zDP/5mf/48f/8A///D/w==")}), + // show: function() { haItems.items[0].emit("redraw"); }, + // hide: function () {} + // }, + ] +}; + +triggers.forEach((trigger, i) => { + haItems.items.push({ + name: "haTrigger-" + i, + get: () => ({ text: trigger.display, img: trigger.getIcon()}), + show: function() { haItems.items[i].emit("redraw"); }, + hide: function () {} + }); +}); + +// ----ha_clock_info ------------------------------------------------------ + + // Still missing var timerItems = {}; -var homeAssistantItems = {}; // Load menu var menu = loadClockInfo(); menu = menu.concat(agendaItems); menu = menu.concat(weatherItems); +menu = menu.concat(haItems); menu = menu.concat(clockItems); // Set draw functions for each item @@ -409,7 +434,8 @@ function drawMenuItem(text, image){ g.setColor(g.theme.bg).drawString(text, W/2 + imgWidth/2 + 2, 149+3); if(image != null){ - g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 149 - parseInt(imgWidth/2)); + var scale = imgWidth / image.width; + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 149 - parseInt(imgWidth/2), {scale: scale}); } } From aeb2ec50021fe93da7c1f60930030f0ade84a11f Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 18 Sep 2022 12:01:53 +0200 Subject: [PATCH 16/72] Fix build --- apps/bwclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index e6e621e36..b456b5e3b 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -157,7 +157,7 @@ function loadClockInfo() { // return it all! return items; -}; +} // ----clock_info ------------------------------------------------------ From 2c1b29eb534a598ba6f1416e3c41571dacde50f6 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 18 Sep 2022 12:10:14 +0200 Subject: [PATCH 17/72] Added action to HA --- apps/bwclk/app.js | 55 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index b456b5e3b..edc4a9272 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -249,7 +249,8 @@ var weatherItems = { // ----ha_clock_info ------------------------------------------------------ -var triggers = require("ha.lib.js").getTriggers(); +var ha = require("ha.lib.js"); +var triggers = ha.getTriggers(); var haItems = { name: "Home", @@ -269,7 +270,11 @@ triggers.forEach((trigger, i) => { name: "haTrigger-" + i, get: () => ({ text: trigger.display, img: trigger.getIcon()}), show: function() { haItems.items[i].emit("redraw"); }, - hide: function () {} + hide: function () {}, + run: function() { + ha.sendTrigger("TRIGGER_BW"); + ha.sendTrigger(trigger.trigger); + } }); }); @@ -460,6 +465,34 @@ function drawMenuAndTime(){ } +function canRunItem(){ + if(settings.menuPosY == 0){ + return false; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + return item.run !== undefined; +} + +function runItem(){ + if(settings.menuPosY == 0){ + return; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + + Bangle.buzz(160, 0.6).then(()=>{ + try{ + item.run(); + } catch (ex) { + // Simply ignore it... + } + }); +} + + function drawLock(){ if(settings.showLock && Bangle.isLocked()){ g.setColor(g.theme.fg); @@ -579,21 +612,9 @@ Bangle.on('touch', function(btn, e){ } if(is_center){ - // var menuEntry = getMenuEntry(); - // if(menuEntry.length > 4 && menuEntry[4] != null){ - // Bangle.buzz(80, 0.6).then(()=>{ - // try{ - // menuEntry[4](); - // setTimeout(()=>{ - // Bangle.buzz(80, 0.6); - // drawTime(); - // }, 250); - // } catch(ex){ - // // In case it fails, we simply ignore it. - // } - // } - // ); - // } + if(canRunItem()){ + runItem(); + } } }); From 24972e31280b8247339111aba6ee6c87f79fbb27 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 19 Sep 2022 17:23:37 +0200 Subject: [PATCH 18/72] Refactored into clkinfo.js files --- apps/agenda/ChangeLog | 1 + apps/agenda/agenda.clkinfo.js | 29 +++++ apps/agenda/metadata.json | 3 +- apps/bwclk/ChangeLog | 3 +- apps/bwclk/app.js | 234 ++++------------------------------ apps/bwclk/metadata.json | 2 +- apps/ha/ChangeLog | 3 +- apps/ha/ha.clkinfo.js | 25 ++++ apps/ha/metadata.json | 3 +- apps/weather/ChangeLog | 1 + apps/weather/clkinfo.js | 43 +++++++ apps/weather/metadata.json | 5 +- modules/clock_info.js | 47 ++++--- 13 files changed, 167 insertions(+), 232 deletions(-) create mode 100644 apps/agenda/agenda.clkinfo.js create mode 100644 apps/ha/ha.clkinfo.js create mode 100644 apps/weather/clkinfo.js diff --git a/apps/agenda/ChangeLog b/apps/agenda/ChangeLog index 2c59c3cc2..16a90242b 100644 --- a/apps/agenda/ChangeLog +++ b/apps/agenda/ChangeLog @@ -3,3 +3,4 @@ 0.03: Disable past events display from settings 0.04: Added awareness of allDay field 0.05: Displaying calendar colour and name +0.06: Added clkinfo for clocks. \ No newline at end of file diff --git a/apps/agenda/agenda.clkinfo.js b/apps/agenda/agenda.clkinfo.js new file mode 100644 index 000000000..9e89b2ac8 --- /dev/null +++ b/apps/agenda/agenda.clkinfo.js @@ -0,0 +1,29 @@ +(function() { + var agendaItems = { + name: "Agenda", + img: atob("GBiBAf////////85z/AAAPAAAPgAAP////AAAPAAAPAAAPAAAOAAAeAAAeAAAcAAA8AAAoAABgAADP//+P//8PAAAPAAAPgAAf///w=="), + items: [] + }; + + var now = new Date(); + var agenda = storage.readJSON("android.calendar.json") + .filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000) + .sort((a,b)=>a.timestamp - b.timestamp); + + agenda.forEach((entry, i) => { + + var title = entry.title.slice(0,14); + var date = new Date(entry.timestamp*1000); + var dateStr = locale.date(date).replace(/\d\d\d\d/,""); + dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; + + agendaItems.items.push({ + name: "agendaEntry-" + i, + get: () => ({ text: title + "\n" + dateStr, img: null}), + show: function() { agendaItems.items[i].emit("redraw"); }, + hide: function () {} + }); + }); + + return agendaItems; +}) \ No newline at end of file diff --git a/apps/agenda/metadata.json b/apps/agenda/metadata.json index 982870905..2bce8ca56 100644 --- a/apps/agenda/metadata.json +++ b/apps/agenda/metadata.json @@ -1,7 +1,7 @@ { "id": "agenda", "name": "Agenda", - "version": "0.05", + "version": "0.06", "description": "Simple agenda", "icon": "agenda.png", "screenshots": [{"url":"screenshot_agenda_overview.png"}, {"url":"screenshot_agenda_event1.png"}, {"url":"screenshot_agenda_event2.png"}], @@ -12,6 +12,7 @@ "storage": [ {"name":"agenda.app.js","url":"agenda.js"}, {"name":"agenda.settings.js","url":"settings.js"}, + {"name":"agenda.clkinfo.js","url":"agenda.clkinfo.js"}, {"name":"agenda.img","url":"agenda-icon.js","evaluate":true} ], "data": [{"name":"agenda.settings.json"}] diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 59bf9eb96..72919e37f 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -18,4 +18,5 @@ 0.18: Set timer for an agenda entry by simply clicking in the middle of the screen. Only one timer can be set. 0.19: Fix - Compatibility with "Digital clock widget" 0.20: Better handling of async data such as getPressure. -0.21: On the default menu the week of year can be shown. \ No newline at end of file +0.21: On the default menu the week of year can be shown. +0.22: Use the new clkinfo module for the menu. \ No newline at end of file diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index edc4a9272..c69a4acdc 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -3,7 +3,7 @@ */ const locale = require('locale'); const storage = require('Storage'); -// const clock_info = require("clock_info"); +const clock_info = require("clock_info"); /************ * Statics @@ -82,215 +82,42 @@ function imgLock(){ } -// ----clock_info ------------------------------------------------------ -function loadClockInfo() { - // info used for drawing... - var hrm = "--"; - var alt = "--"; - var interval = null; - // callbacks (needed for easy removal of listeners) - function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } - function stepUpdateHandler() { bangleItems[1].emit("redraw"); } - function hrmUpdateHandler() { bangleItems[2].emit("redraw"); } - function altUpdateHandler() { - Bangle.getPressure().then(data=>{ - if (!data) return; - alt = Math.round(data.altitude) + "m"; - bangleItems[3].emit("redraw"); - }); - } - function deleteInterval(inter){ - if(inter){ - clearInterval(inter); - } - delete inter; - } - // actual items - var items = [{ - name: "Bangle", - img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), - items: [ - { name : "Battery", - get : () => ({ - text : E.getBattery() + "%", - img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { - deleteInterval(interval); - interval = setInterval(()=>this.emit('redraw'), 60000); - Bangle.on("charging", batteryUpdateHandler); - batteryUpdateHandler(); - }, - hide : function() { - deleteInterval(interval); - Bangle.removeListener("charging", batteryUpdateHandler); - }, - }, - { name : "Steps", get : () => ({ - text : Bangle.getHealthStatus("day").steps, - img : atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA==") }), - show : function() { Bangle.on("step", stepUpdateHandler); stepUpdateHandler(); }, - hide : function() { Bangle.removeListener("step", stepUpdateHandler); }, - }, - { name : "HRM", get : () => ({ - text : Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", - img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { Bangle.setHRMPower(1,"clkinfo"); Bangle.on("HRM", hrmUpdateHandler); hrm = Math.round(Bangle.getHealthStatus("last").bpm); hrmUpdateHandler(); }, - hide : function() { Bangle.setHRMPower(0,"clkinfo"); Bangle.removeListener("HRM", hrmUpdateHandler); hrm = "--"; }, - } - ], - }]; - var bangleItems = items[0].items; - - if (Bangle.getPressure){ // Altimeter may not exist - bangleItems.push({ name : "Altitude", get : () => ({ - text : alt, - img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { deleteInterval(); interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, - hide : function() { deleteInterval(); }, - }); - } - - // now load extra data from a third party files - require("Storage").list(/clkinfo.js$/).forEach(fn => { - items = items.concat(eval(require("Storage").read(fn))()); - }); - - // return it all! - return items; -} -// ----clock_info ------------------------------------------------------ - - -// Custom menus -var clockItems = { +// Custom bwItems menu - therefore, its added here and not in a clkinfo.js file. +var bwItems = { name: null, img: null, items: [ { name: "WeekOfYear", get: () => ({ text: "Week " + weekOfYear(), img: null}), - show: function() { clockItems.items[0].emit("redraw"); }, + show: function() { bwItems.items[0].emit("redraw"); }, hide: function () {} }, ] }; - -// ----agenda_clock_info ------------------------------------------------------ -var agendaItems = { - name: "Agenda", - img: atob("GBiBAf////////85z/AAAPAAAPgAAP////AAAPAAAPAAAPAAAOAAAeAAAeAAAcAAA8AAAoAABgAADP//+P//8PAAAPAAAPgAAf///w=="), - items: [] -}; - -var now = new Date(); -var agenda = storage.readJSON("android.calendar.json") - .filter(ev=>ev.timestamp + ev.durationInSeconds > now/1000) - .sort((a,b)=>a.timestamp - b.timestamp); - -agenda.forEach((entry, i) => { - - var title = entry.title.slice(0,14); - var date = new Date(entry.timestamp*1000); - var dateStr = locale.date(date).replace(/\d\d\d\d/,""); - dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; - - agendaItems.items.push({ - name: "agendaEntry-" + i, - get: () => ({ text: title + "\n" + dateStr, img: null}), - show: function() { agendaItems.items[i].emit("redraw"); }, - hide: function () {} - }); -}); -// ----agenda_clock_info ------------------------------------------------------ - - - -// ----weather_clock_info ------------------------------------------------------ -var weather = { - temp: "?", - hum: "?", - wind: "?", -}; - -var weatherJson = storage.readJSON('weather.json'); -if(weatherJson !== undefined && weatherJson.weather !== undefined){ - weather = weatherJson.weather; - weather.temp = locale.temp(weather.temp-273.15); - weather.hum = weather.hum + "%"; - weather.wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - weather.wind = Math.round(weather.wind[1]) + "kph"; +function weekOfYear() { + var date = new Date(); + date.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); + // January 4 is always in week 1. + var week1 = new Date(date.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 + - 3 + (week1.getDay() + 6) % 7) / 7); } -var weatherItems = { - name: "Weather", - img: atob("GBiBAf+///u5//n7//8f/9wHP8gDf/gB//AB/7AH/5AcP/AQH/DwD/uAD84AD/4AA/wAAfAAAfAAAfAAAfgAA/////+bP/+zf/+zfw=="), - items: [ - { - name: "temperature", - get: () => ({ text: weather.temp, img: atob("GBiBAf/D//+B//8Y//88//88//88//88//88//8k//8k//8k//8k//8k//8k//4kf/5mf/zDP/yBP/yBP/zDP/5mf/48f/8A///D/w==")}), - show: function() { weatherItems.items[0].emit("redraw"); }, - hide: function () {} - }, - { - name: "humidity", - get: () => ({ text: weather.hum, img: atob("GBiBAf/7///z///x///g///g///Af//Af/3Af/nA//jg//B/v/B/H+A/H8A+D8AeB8AcB4AYA8AYA8AYA+A4A/B4A//4A//8B///Dw==")}), - show: function() { weatherItems.items[1].emit("redraw"); }, - hide: function () {} - }, - { - name: "wind", - get: () => ({ text: weather.wind, img: atob("GBiBAf4f//wP//nn//Pn//Pzg//nAf/meIAOfAAefP///P//+fAAAfAAB////////wAAP4AAH///z///z//nz//nz//zj//wH//8Pw==")}), - show: function() { weatherItems.items[2].emit("redraw"); }, - hide: function () {} - }, - ] -}; -// ----weather_clock_info ------------------------------------------------------ - - -// ----ha_clock_info ------------------------------------------------------ -var ha = require("ha.lib.js"); -var triggers = ha.getTriggers(); - -var haItems = { - name: "Home", - img: atob("GBiBAf/////////n///D//+B//8A//48T/wkD/gkD/A8D+AYB8AYA4eZ4QyZMOyZN+fb5+D/B+B+B+A8B+AYB+AYB+AYB+AYB+A8Bw=="), - items: [ - // { - // name: "item1", - // get: () => ({ text: "Item1", img: atob("GBiBAf/D//+B//8Y//88//88//88//88//88//8k//8k//8k//8k//8k//8k//4kf/5mf/zDP/yBP/yBP/zDP/5mf/48f/8A///D/w==")}), - // show: function() { haItems.items[0].emit("redraw"); }, - // hide: function () {} - // }, - ] -}; - -triggers.forEach((trigger, i) => { - haItems.items.push({ - name: "haTrigger-" + i, - get: () => ({ text: trigger.display, img: trigger.getIcon()}), - show: function() { haItems.items[i].emit("redraw"); }, - hide: function () {}, - run: function() { - ha.sendTrigger("TRIGGER_BW"); - ha.sendTrigger(trigger.trigger); - } - }); -}); - -// ----ha_clock_info ------------------------------------------------------ - - -// Still missing -var timerItems = {}; - // Load menu -var menu = loadClockInfo(); -menu = menu.concat(agendaItems); -menu = menu.concat(weatherItems); -menu = menu.concat(haItems); -menu = menu.concat(clockItems); +var menu = clock_info.load(); +menu = menu.concat(bwItems); + + +// Ensure that our settings are still in range (e.g. app uninstall). Otherwise reset the position it. +if(settings.menuPosX >= menu.length || settings.menuPosY > menu[settings.menuPosX].items.length ){ + settings.menuPosX = 0; + settings.menuPosY = 0; +} // Set draw functions for each item menu.forEach((menuItm, x) => { @@ -328,19 +155,6 @@ function isFullscreen(){ } -function weekOfYear() { - var date = new Date(); - date.setHours(0, 0, 0, 0); - // Thursday in current week decides the year. - date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); - // January 4 is always in week 1. - var week1 = new Date(date.getFullYear(), 0, 4); - // Adjust to Thursday in week 1 and count number of weeks from date to week1. - return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 - - 3 + (week1.getDay() + 6) % 7) / 7); -} - - /************ * DRAW */ @@ -363,7 +177,7 @@ function drawDate(){ // Draw date y = parseInt(y/2)+4; - y += isFullscreen() ? 0 : 13; + y += isFullscreen() ? 0 : 8; var date = new Date(); var dateStr = date.getDate(); dateStr = ("0" + dateStr).substr(-2); diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index b6896ab5e..35e707f68 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.21", + "version": "0.22", "description": "A very minimalistic clock to mainly show date and time.", "readme": "README.md", "icon": "app.png", diff --git a/apps/ha/ChangeLog b/apps/ha/ChangeLog index e78b4ccd0..493854eb4 100644 --- a/apps/ha/ChangeLog +++ b/apps/ha/ChangeLog @@ -1,2 +1,3 @@ 0.01: Release -0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. \ No newline at end of file +0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. +0.03: Added clkinfo for clocks. \ No newline at end of file diff --git a/apps/ha/ha.clkinfo.js b/apps/ha/ha.clkinfo.js new file mode 100644 index 000000000..bb3b7e5a1 --- /dev/null +++ b/apps/ha/ha.clkinfo.js @@ -0,0 +1,25 @@ +(function() { + var ha = require("ha.lib.js"); + var triggers = ha.getTriggers(); + + var haItems = { + name: "Home", + img: atob("GBiBAf/////////n///D//+B//8A//48T/wkD/gkD/A8D+AYB8AYA4eZ4QyZMOyZN+fb5+D/B+B+B+A8B+AYB+AYB+AYB+AYB+A8Bw=="), + items: [] + }; + + triggers.forEach((trigger, i) => { + haItems.items.push({ + name: "haTrigger-" + i, + get: () => ({ text: trigger.display, img: trigger.getIcon()}), + show: function() { haItems.items[i].emit("redraw"); }, + hide: function () {}, + run: function() { + ha.sendTrigger("TRIGGER_BW"); + ha.sendTrigger(trigger.trigger); + } + }); + }); + + return haItems; +}) \ No newline at end of file diff --git a/apps/ha/metadata.json b/apps/ha/metadata.json index 63308b933..e59e63c91 100644 --- a/apps/ha/metadata.json +++ b/apps/ha/metadata.json @@ -1,7 +1,7 @@ { "id": "ha", "name": "HomeAssistant", - "version": "0.02", + "version": "0.03", "description": "Integrates your BangleJS into HomeAssistant.", "icon": "ha.png", "type": "app", @@ -20,6 +20,7 @@ "storage": [ {"name":"ha.app.js","url":"ha.app.js"}, {"name":"ha.lib.js","url":"ha.lib.js"}, + {"name":"ha.clkinfo.js","url":"ha.clkinfo.js"}, {"name":"ha.img","url":"ha.icon.js","evaluate":true} ] } diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index 49e23e1d6..da28d8d5a 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -13,3 +13,4 @@ 0.14: Use weather condition code for icon selection 0.15: Fix widget icon 0.16: Don't mark app as clock +0.17: Added clkinfo for clocks. \ No newline at end of file diff --git a/apps/weather/clkinfo.js b/apps/weather/clkinfo.js new file mode 100644 index 000000000..8e502b7fc --- /dev/null +++ b/apps/weather/clkinfo.js @@ -0,0 +1,43 @@ +(function() { + var weather = { + temp: "?", + hum: "?", + wind: "?", + }; + + var weatherJson = storage.readJSON('weather.json'); + if(weatherJson !== undefined && weatherJson.weather !== undefined){ + weather = weatherJson.weather; + weather.temp = locale.temp(weather.temp-273.15); + weather.hum = weather.hum + "%"; + weather.wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + weather.wind = Math.round(weather.wind[1]) + "kph"; + } + + var weatherItems = { + name: "Weather", + img: atob("GBiBAf+///u5//n7//8f/9wHP8gDf/gB//AB/7AH/5AcP/AQH/DwD/uAD84AD/4AA/wAAfAAAfAAAfAAAfgAA/////+bP/+zf/+zfw=="), + items: [ + { + name: "temperature", + get: () => ({ text: weather.temp, img: atob("GBiBAf/D//+B//8Y//88//88//88//88//88//8k//8k//8k//8k//8k//8k//4kf/5mf/zDP/yBP/yBP/zDP/5mf/48f/8A///D/w==")}), + show: function() { weatherItems.items[0].emit("redraw"); }, + hide: function () {} + }, + { + name: "humidity", + get: () => ({ text: weather.hum, img: atob("GBiBAf/7///z///x///g///g///Af//Af/3Af/nA//jg//B/v/B/H+A/H8A+D8AeB8AcB4AYA8AYA8AYA+A4A/B4A//4A//8B///Dw==")}), + show: function() { weatherItems.items[1].emit("redraw"); }, + hide: function () {} + }, + { + name: "wind", + get: () => ({ text: weather.wind, img: atob("GBiBAf4f//wP//nn//Pn//Pzg//nAf/meIAOfAAefP///P//+fAAAfAAB////////wAAP4AAH///z///z//nz//nz//zj//wH//8Pw==")}), + show: function() { weatherItems.items[2].emit("redraw"); }, + hide: function () {} + }, + ] + }; + + return weatherItems; +}) \ No newline at end of file diff --git a/apps/weather/metadata.json b/apps/weather/metadata.json index 25037de3d..125041ec4 100644 --- a/apps/weather/metadata.json +++ b/apps/weather/metadata.json @@ -1,7 +1,7 @@ { "id": "weather", "name": "Weather", - "version": "0.16", + "version": "0.17", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], @@ -13,7 +13,8 @@ {"name":"weather.wid.js","url":"widget.js"}, {"name":"weather","url":"lib.js"}, {"name":"weather.img","url":"icon.js","evaluate":true}, - {"name":"weather.settings.js","url":"settings.js"} + {"name":"weather.settings.js","url":"settings.js"}, + {"name":"weather.clkinfo.js","url":"clkinfo.js"} ], "data": [{"name":"weather.json"}] } diff --git a/modules/clock_info.js b/modules/clock_info.js index 2ee7fc2f7..df35d4e22 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -37,57 +37,74 @@ exports.load = function() { // info used for drawing... var hrm = "--"; var alt = "--"; + var interval = null; // callbacks (needed for easy removal of listeners) - function batteryUpdateHandler() { items[0].emit("redraw"); } - function stepUpdateHandler() { items[1].emit("redraw"); } - function hrmUpdateHandler() { items[2].emit("redraw"); } + function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } + function stepUpdateHandler() { bangleItems[1].emit("redraw"); } + function hrmUpdateHandler() { bangleItems[2].emit("redraw"); } function altUpdateHandler() { Bangle.getPressure().then(data=>{ if (!data) return; alt = Math.round(data.altitude) + "m"; - items[3].emit("redraw"); + bangleItems[3].emit("redraw"); }); } + function deleteInterval(inter){ + if(inter){ + clearInterval(inter); + } + delete inter; + } // actual items - var items = [ + var items = [{ + name: "Bangle", + img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), + items: [ { name : "Battery", get : () => ({ text : E.getBattery() + "%", img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") }), show : function() { - this.interval = setInterval(()=>this.emit('redraw'), 60000); + deleteInterval(interval); + interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); + batteryUpdateHandler(); }, hide : function() { - clearInterval(this.interval); - delete this.interval; + deleteInterval(interval); Bangle.removeListener("charging", batteryUpdateHandler); }, }, { name : "Steps", get : () => ({ text : Bangle.getHealthStatus("day").steps, img : atob("GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA==") }), - show : function() { Bangle.on("step", stepUpdateHandler); }, + show : function() { Bangle.on("step", stepUpdateHandler); stepUpdateHandler(); }, hide : function() { Bangle.removeListener("step", stepUpdateHandler); }, }, { name : "HRM", get : () => ({ text : Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { Bangle.setHRMPower(1,"clkinfo"); Bangle.on("HRM", hrmUpdateHandler); hrm = Math.round(Bangle.getHealthStatus("last").bpm); }, + show : function() { Bangle.setHRMPower(1,"clkinfo"); Bangle.on("HRM", hrmUpdateHandler); hrm = Math.round(Bangle.getHealthStatus("last").bpm); hrmUpdateHandler(); }, hide : function() { Bangle.setHRMPower(0,"clkinfo"); Bangle.removeListener("HRM", hrmUpdateHandler); hrm = "--"; }, } - ]; - if (Bangle.getPressure) // Altimeter may not exist - items.push({ name : "Altitude", get : () => ({ + ], + }]; + var bangleItems = items[0].items; + + if (Bangle.getPressure){ // Altimeter may not exist + bangleItems.push({ name : "Altitude", get : () => ({ text : alt, img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { this.interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, - hide : function() { clearInterval(this.interval); delete this.interval; }, + show : function() { deleteInterval(interval); interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, + hide : function() { deleteInterval(interval); }, }); + } + // now load extra data from a third party files require("Storage").list(/clkinfo.js$/).forEach(fn => { items = items.concat(eval(require("Storage").read(fn))()); }); + // return it all! return items; }; From 99999cbc88bbf743a23289b0a85f4a9ab3132488 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 19 Sep 2022 17:37:43 +0200 Subject: [PATCH 19/72] Minor changes --- apps/bwclk/app.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index c69a4acdc..15212ea21 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -296,14 +296,12 @@ function runItem(){ var menuEntry = menu[settings.menuPosX]; var item = menuEntry.items[settings.menuPosY-1]; - - Bangle.buzz(160, 0.6).then(()=>{ - try{ - item.run(); - } catch (ex) { - // Simply ignore it... - } - }); + try{ + item.run(); + Bangle.buzz(300, 0.6).then(() => {}); + } catch (ex) { + // Simply ignore it... + } } From d5ccb4919c4911c075fe21958491b13b535586c7 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 19 Sep 2022 17:43:55 +0200 Subject: [PATCH 20/72] Updated readme --- apps/bwclk/README.md | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index dfb9bf515..3a5061e81 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -4,9 +4,12 @@ A very minimalistic clock to mainly show date and time. ![](screenshot.png) ## Features -The BW clock provides many features and also 3rd party integrations: +The BW clock implements 3rd party integrations of other apps through the `clkinfo` module. +For example if you install the HomeAssistant app, this menu item will show up in BWClock +and additionally allows to send your triggers directly from the clock. Here are some +features that are supported: + - Bangle data such as steps, heart rate, battery or charging state. -- A timer can be set directly. *Requirement: Scheduler library* - Show agenda entries. A timer for an agenda entry can also be set by simply clicking in the middle of the screen. This can be used to not forget a meeting etc. Note that only one agenda-timer can be set at a time. *Requirement: Gadgetbridge calendar sync enabled* - Weather temperature as well as the wind speed can be shown. *Requirement: Weather app* - HomeAssistant triggers can be executed directly. *Requirement: HomeAssistant app* @@ -20,27 +23,29 @@ Note: If some apps are not installed (e.gt. weather app), then this menu item is - Your bangle uses the sys color settings so you can change the color too. ## Menu structure -2D menu allows you to display lots of different data including data from 3rd party apps and it's also possible to control things e.g. to set a timer or send a HomeAssistant trigger. +2D menu allows you to display lots of different data including data from 3rd party apps and it's also possible to control things e.g. to trigger HomeAssistant. -Simply click left / right to go through the menu entries such as Bangle, Timer etc. +Simply click left / right to go through the menu entries such as Bangle, Weather etc. and click up/down to move into this sub-menu. You can then click in the middle of the screen -to e.g. send a trigger via HomeAssistant once you selected it. +to e.g. send a trigger via HomeAssistant once you selected it. The actions really depend +on the app that provide this sub-menu through the `clkinfo` module. ``` - +5min - | - Bangle -- Timer[Optional] -- Agenda 1[Optional] -- Weather[Optional] -- HomeAssistant [Optional] - | | | | | - Bpm -5min Agenda 2 Temperature Trigger1 - | | | | - Steps ... ... ... + Bangle -- Agenda -- Weather -- HomeAssistant + | | | | + Battery Entry 1 Temperature Trigger1 + | | | | + Steps ... ... ... | - Battery + ... ``` ## Thanks to -Icons created by Flaticon +- Thanks to Gordon not only for the great BangleJs, but specifically also for the implementation of `clkinfo` which simplified the BWClock a lot and moved complexety to the apps where it should be located. +- Icons created by Flaticon ## Creator [David Peer](https://github.com/peerdavid) + +## Changes From 00783857ba333325967d3b048956d0d1a094325d Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 19 Sep 2022 17:44:46 +0200 Subject: [PATCH 21/72] Minor change --- apps/bwclk/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index 3a5061e81..14e442ee4 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -42,7 +42,7 @@ on the app that provide this sub-menu through the `clkinfo` module. ## Thanks to -- Thanks to Gordon not only for the great BangleJs, but specifically also for the implementation of `clkinfo` which simplified the BWClock a lot and moved complexety to the apps where it should be located. +- Thanks to Gordon Williams not only for the great BangleJs, but specifically also for the implementation of `clkinfo` which simplified the BWClock a lot and moved complexety to the apps where it should be located. - Icons created by Flaticon ## Creator From bdb695c17fe074d83af8f7e7facebaeac1327bdd Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 19 Sep 2022 17:46:13 +0200 Subject: [PATCH 22/72] Minor changes --- apps/bwclk/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index 14e442ee4..64483943f 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -47,5 +47,3 @@ on the app that provide this sub-menu through the `clkinfo` module. ## Creator [David Peer](https://github.com/peerdavid) - -## Changes From af315be7123ad0f1d0a554554e5398020c17a1a6 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 20 Sep 2022 18:38:17 +0200 Subject: [PATCH 23/72] Fix: On charge should show battery... --- apps/bwclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 15212ea21..ba77f2848 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -368,7 +368,7 @@ Bangle.on('charging',function(charging) { // Jump to battery settings.menuPosX = 0; - settings.menuPosY = 0; + settings.menuPosY = 1; draw(); }); From 96ae6140f0e3879d094f3b5b9108804f98ef3fe8 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 20 Sep 2022 18:45:01 +0200 Subject: [PATCH 24/72] Minor refactorings --- apps/bwclk/app.js | 102 +++++++++++++++++++++++----------------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index ba77f2848..c8c885ee1 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -1,18 +1,21 @@ -/************ +/************************************************ * Includes */ const locale = require('locale'); const storage = require('Storage'); const clock_info = require("clock_info"); -/************ - * Statics + +/************************************************ + * Globals */ const SETTINGS_FILE = "bwclk.setting.json"; const W = g.getWidth(); const H = g.getHeight(); +var lock_input = false; -/************ + +/************************************************ * Settings */ let settings = { @@ -28,9 +31,7 @@ for (const key in saved_settings) { settings[key] = saved_settings[key] } -var lock_input = false; - -/************ +/************************************************ * Assets */ // Manrope font @@ -82,6 +83,9 @@ function imgLock(){ } +/************************************************ + * Menu + */ // Custom bwItems menu - therefore, its added here and not in a clkinfo.js file. var bwItems = { name: null, @@ -141,22 +145,35 @@ menu.forEach((menuItm, x) => { }); +function canRunMenuItem(){ + if(settings.menuPosY == 0){ + return false; + } -/************ - * Helper - */ -function isFullscreen(){ - var s = settings.screen.toLowerCase(); - if(s == "dynamic"){ - return Bangle.isLocked() - } else { - return s == "full" + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + return item.run !== undefined; +} + + +function runMenuItem(){ + if(settings.menuPosY == 0){ + return; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + try{ + item.run(); + Bangle.buzz(300, 0.6).then(() => {}); + } catch (ex) { + // Simply ignore it... } } -/************ - * DRAW +/************************************************ + * Draw */ function draw() { // Queue draw again @@ -279,32 +296,6 @@ function drawMenuAndTime(){ } -function canRunItem(){ - if(settings.menuPosY == 0){ - return false; - } - - var menuEntry = menu[settings.menuPosX]; - var item = menuEntry.items[settings.menuPosY-1]; - return item.run !== undefined; -} - -function runItem(){ - if(settings.menuPosY == 0){ - return; - } - - var menuEntry = menu[settings.menuPosX]; - var item = menuEntry.items[settings.menuPosY-1]; - try{ - item.run(); - Bangle.buzz(300, 0.6).then(() => {}); - } catch (ex) { - // Simply ignore it... - } -} - - function drawLock(){ if(settings.showLock && Bangle.isLocked()){ g.setColor(g.theme.fg); @@ -322,9 +313,19 @@ function drawWidgets(){ } +function isFullscreen(){ + var s = settings.screen.toLowerCase(); + if(s == "dynamic"){ + return Bangle.isLocked() + } else { + return s == "full" + } +} -/* - * Draw timeout + + +/************************************************ + * Listener */ // timeout used to update every minute var drawTimeout; @@ -424,8 +425,8 @@ Bangle.on('touch', function(btn, e){ } if(is_center){ - if(canRunItem()){ - runItem(); + if(canRunMenuItem()){ + runMenuItem(); } } }); @@ -440,9 +441,10 @@ E.on("kill", function(){ }); -/* - * Draw clock the first time +/************************************************ + * Startup Clock */ + // The upper part is inverse i.e. light if dark and dark if light theme // is enabled. In order to draw the widgets correctly, we invert the // dark/light theme as well as the colors. From be4e289191950e85daafa969e5315dfa7f6f6cca Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 20 Sep 2022 18:50:57 +0200 Subject: [PATCH 25/72] Updated readme --- apps/bwclk/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index 64483943f..d869fa2cf 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -1,13 +1,13 @@ # BW Clock -A very minimalistic clock to mainly show date and time. +A very minimalistic clock. ![](screenshot.png) ## Features -The BW clock implements 3rd party integrations of other apps through the `clkinfo` module. -For example if you install the HomeAssistant app, this menu item will show up in BWClock -and additionally allows to send your triggers directly from the clock. Here are some -features that are supported: +The BW clock implements features that are exposed by other apps through the `clkinfo` module. +For example, if you install the HomeAssistant app, this menu item will be shown if you click right +and additionally allows you to send triggers directly from the clock (select triggers via up/down and +send via click center). Here are examples of other apps that are integrated: - Bangle data such as steps, heart rate, battery or charging state. - Show agenda entries. A timer for an agenda entry can also be set by simply clicking in the middle of the screen. This can be used to not forget a meeting etc. Note that only one agenda-timer can be set at a time. *Requirement: Gadgetbridge calendar sync enabled* From ceaae5614d09dda717df8fc35c60723b75c61f9e Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 20 Sep 2022 18:53:46 +0200 Subject: [PATCH 26/72] Minor changes --- apps/agenda/agenda.clkinfo.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/agenda/agenda.clkinfo.js b/apps/agenda/agenda.clkinfo.js index 9e89b2ac8..a80c09002 100644 --- a/apps/agenda/agenda.clkinfo.js +++ b/apps/agenda/agenda.clkinfo.js @@ -12,7 +12,7 @@ agenda.forEach((entry, i) => { - var title = entry.title.slice(0,14); + var title = entry.title.slice(0,18); var date = new Date(entry.timestamp*1000); var dateStr = locale.date(date).replace(/\d\d\d\d/,""); dateStr += entry.durationInSeconds < 86400 ? "/ " + locale.time(date,1) : ""; From df7dc9152016fb512b05c465c39d9af70bc5b29b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 21 Sep 2022 09:27:52 +0100 Subject: [PATCH 27/72] Trying to make the AGPS situation clearer - looks like the apps that don't actually directly upload AGPS data may be confusing --- apps/agpsdata/metadata.json | 4 ++-- apps/assistedgps/metadata.json | 7 ++++--- apps/widagps/metadata.json | 4 ++-- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/agpsdata/metadata.json b/apps/agpsdata/metadata.json index d3863be52..e2f818d97 100644 --- a/apps/agpsdata/metadata.json +++ b/apps/agpsdata/metadata.json @@ -1,9 +1,9 @@ { "id": "agpsdata", - "name": "A-GPS Data", + "name": "A-GPS Data Downloader App", "shortName":"A-GPS Data", "icon": "agpsdata.png", "version":"0.02", - "description": "Download assisted GPS (A-GPS) data directly to your Bangle.js **using Gadgetbridge**", + "description": "Once installed, this app allows you to download assisted GPS (A-GPS) data directly to your Bangle.js **via Gadgetbridge on an Android phone** when you run the app. If you just want to upload the latest AGPS data from this app loader, please use the `Assisted GPS Update (AGPS)` app.", "tags": "boot,tool,assisted,gps,agps,http", "allow_emulator":true, "supports": ["BANGLEJS2"], diff --git a/apps/assistedgps/metadata.json b/apps/assistedgps/metadata.json index 1dbc42c87..4c91dcd35 100644 --- a/apps/assistedgps/metadata.json +++ b/apps/assistedgps/metadata.json @@ -1,11 +1,12 @@ { "id": "assistedgps", - "name": "Assisted GPS Update (AGPS)", + "name": "Assisted GPS Updater (AGPS)", "version": "0.03", - "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", + "description": "Downloads assisted GPS (AGPS) data to Bangle.js for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", + "sortorder": -1, "icon": "app.png", "type": "RAM", - "tags": "tool,outdoors,agps", + "tags": "tool,outdoors,agps,gps,a-gps", "supports": ["BANGLEJS","BANGLEJS2"], "custom": "custom.html", "customConnect": true, diff --git a/apps/widagps/metadata.json b/apps/widagps/metadata.json index 8d3d37aab..ee1eb9f08 100644 --- a/apps/widagps/metadata.json +++ b/apps/widagps/metadata.json @@ -1,10 +1,10 @@ { "id": "widagps", - "name": "AGPS Widget", + "name": "AGPS Widget (automatic download)", "shortName":"AGPS Widget", "icon": "widget.png", "type": "widget", "version":"0.01", - "description": "Load AGPS data in the background **using Gadgetbridge**", + "description": "Once installed, this widget allows your Bangle.js 2 to load AGPS data in the background **via Gadgetbridge on an Android phone** so it is always up to date. If you just want to upload the latest AGPS data from this app loader, please use the `Assisted GPS Update (AGPS)` app.", "readme": "README.md", "tags": "widget,agps,http", "supports": ["BANGLEJS2"], From fef343887fd99677bcf27955a1c65c40b81728ca Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 21 Sep 2022 19:27:09 +0200 Subject: [PATCH 28/72] [widbt_notify] Correct widget drawing --- apps/widbt_notify/widget.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/widbt_notify/widget.js b/apps/widbt_notify/widget.js index 8828d5ca3..1b192412a 100644 --- a/apps/widbt_notify/widget.js +++ b/apps/widbt_notify/widget.js @@ -9,8 +9,8 @@ nextBuzz: 30000 }, require("Storage").readJSON("widbt_notify.json", true) || {}); - // setup widget with to hide if not connected and option set - var widWidth = settings.hideConnected && !NRF.getSecurityStatus().connected ? 0 : 15; + // setup widget with to hide if connected and option set + var widWidth = settings.hideConnected && NRF.getSecurityStatus().connected ? 0 : 15; // write widget with loaded settings WIDGETS.bluetooth_notify = Object.assign(settings, { @@ -50,6 +50,15 @@ }, onNRF: function(connect) { + // setup widget with and reload widgets to show/hide if hideConnected is enabled + if (this.hideConnected) { + this.width = connect ? 0 : 15; // ensures correct redraw + Bangle.drawWidgets(); + } else { + // redraw widget + this.draw(); + } + if (this.warningEnabled) { if (this.showMessage) { E.showMessage( /*LANG*/ 'Connection\n' + (connect ? /*LANG*/ 'restored.' : /*LANG*/ 'lost.'), 'Bluetooth'); @@ -66,12 +75,6 @@ Bangle.buzz(700, 1); // buzz on connection resume or loss } } - // if hideConnected is en- and showMessage disabled, redraw widgets to hide - if (this.hideConnected && !this.showMessage) { - Bangle.drawWidgets(); - } else { - this.draw(); - } } }); From 8036d976b3e47d1672ecb1afeafaef98f08e6fb1 Mon Sep 17 00:00:00 2001 From: David Peer Date: Thu, 22 Sep 2022 18:25:42 +0200 Subject: [PATCH 29/72] Use this.interval insntead of interval. --- modules/clock_info.js | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/modules/clock_info.js b/modules/clock_info.js index df35d4e22..d8068b69d 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -37,7 +37,6 @@ exports.load = function() { // info used for drawing... var hrm = "--"; var alt = "--"; - var interval = null; // callbacks (needed for easy removal of listeners) function batteryUpdateHandler() { bangleItems[0].emit("redraw"); } function stepUpdateHandler() { bangleItems[1].emit("redraw"); } @@ -49,12 +48,6 @@ exports.load = function() { bangleItems[3].emit("redraw"); }); } - function deleteInterval(inter){ - if(inter){ - clearInterval(inter); - } - delete inter; - } // actual items var items = [{ name: "Bangle", @@ -64,16 +57,8 @@ exports.load = function() { get : () => ({ text : E.getBattery() + "%", img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { - deleteInterval(interval); - interval = setInterval(()=>this.emit('redraw'), 60000); - Bangle.on("charging", batteryUpdateHandler); - batteryUpdateHandler(); - }, - hide : function() { - deleteInterval(interval); - Bangle.removeListener("charging", batteryUpdateHandler); - }, + show : function() { this.interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); batteryUpdateHandler(); }, + hide : function() { clearInterval(this.interval); delete this.interval; Bangle.removeListener("charging", batteryUpdateHandler); }, }, { name : "Steps", get : () => ({ text : Bangle.getHealthStatus("day").steps, @@ -95,8 +80,8 @@ exports.load = function() { bangleItems.push({ name : "Altitude", get : () => ({ text : alt, img : atob("GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA==") }), - show : function() { deleteInterval(interval); interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, - hide : function() { deleteInterval(interval); }, + show : function() { this.interval = setInterval(altUpdateHandler, 60000); alt = "--"; altUpdateHandler(); }, + hide : function() { clearInterval(this.interval); delete this.interval; }, }); } From 59d63885fa8b1ab2c384378d11234b88b9e7e926 Mon Sep 17 00:00:00 2001 From: David Peer Date: Thu, 22 Sep 2022 18:49:12 +0200 Subject: [PATCH 30/72] Advanced merge function of menu objects and items. --- modules/clock_info.js | 48 ++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/modules/clock_info.js b/modules/clock_info.js index d8068b69d..4d70f0013 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -2,9 +2,14 @@ var exports = {}; /* Module that allows for loading of clock 'info' displays that can be scrolled through on the clock face. -`load()` returns an array of menu items: +`load()` returns an array of menu objects, where each object contains a list of menu items: +* 'name' : text to display and identify menu object (e.g. weather) +* 'img' : a 24x24px image +* 'items' : menu items such as temperature, humidity, wind etc. -* 'item.name' : friendly name +Note that each item is an object with: + +* 'item.name' : friendly name to identify an item (e.g. temperature) * 'item.get' : function that resolves with: { 'text' : the text to display for this item @@ -20,14 +25,18 @@ See the bottom of this file for example usage... example.clkinfo.js : (function() { - return [ - { name : "Example", - get : () => ({ text : "Bangle.js", - img : atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA==") }), - show : () => {}, - hide : () => {} - } - ]; + return { + name: "Bangle", + img: atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA==") }), + items: [ + { name : "Item1", + get : () => ({ text : "TextOfItem1", + img : atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA==") }), + show : () => {}, + hide : () => {} + } + ] + }; }) // must not have a semi-colon! */ @@ -48,8 +57,8 @@ exports.load = function() { bangleItems[3].emit("redraw"); }); } - // actual items - var items = [{ + // actual menu + var menu = [{ name: "Bangle", img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), items: [ @@ -74,7 +83,7 @@ exports.load = function() { } ], }]; - var bangleItems = items[0].items; + var bangleItems = menu[0].items; if (Bangle.getPressure){ // Altimeter may not exist bangleItems.push({ name : "Altitude", get : () => ({ @@ -85,20 +94,25 @@ exports.load = function() { }); } - // now load extra data from a third party files + // In case there exists already a menu object b with the same name as the next + // object a, we append the items. Otherwise we add the new object a to the list. require("Storage").list(/clkinfo.js$/).forEach(fn => { - items = items.concat(eval(require("Storage").read(fn))()); + var a = eval(require("Storage").read(fn))(); + var b = menu.find(x => x.name === a.name) + if(b) b.items = b.items.concat(a.items); + else menu = menu.concat(a); }); // return it all! - return items; + return menu; }; // Code for testing /* g.clear(); -var items = exports.load(); // or require("clock_info").load() +var menu = exports.load(); // or require("clock_info").load() +var itemsFirstMenu = menu[0].items; items.forEach((itm,i) => { var y = i*24; console.log("Starting", itm.name); From f4d5e70fab15f86396b230aeaf193bbca8e7a521 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 16:28:20 -0400 Subject: [PATCH 31/72] Creating app.js --- apps/numberchaser/app.js | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 apps/numberchaser/app.js diff --git a/apps/numberchaser/app.js b/apps/numberchaser/app.js new file mode 100644 index 000000000..f68119fb2 --- /dev/null +++ b/apps/numberchaser/app.js @@ -0,0 +1,104 @@ +var randomNumber; +var guessNumber = 1; + +function mathRandomInt(a, b) { + if (a > b) { + // Swap a and b to ensure a is smaller. + var c = a; + a = b; + b = c; + } + return Math.floor(Math.random() * (b - a + 1) + a); +} + +/** + * Describe this function... + */ +function game() { + + g.drawString('',0,20,true); + E.showMenu(numMenu); + console.log(randomNumber); +} + +var numMenu = { + "" : { + "title" : "Number Chaser", + }, + "Guess Number" : { + value : guessNumber, + min:1,max:100,step:1, + onchange : v => { guessNumber=v; } + }, + "OK" : function () { + g.clear(); + if (guessNumber == randomNumber) { + //if guess is correct + g.setFont("Vector",13);g.setFontAlign(-1,-1); + status = "You won! "; + gameOver(); + } else { + //if guess is incorrect + g.setFont("Vector",13);g.setFontAlign(-1,-1); + if (guessNumber > randomNumber) { + //Decreases number if guess is greater + randomNumber = randomNumber - 1; + status = "Too high!"; + } else if (guessNumber < randomNumber) { + //Increases number if guess is lower + status = "Too low!"; + randomNumber = randomNumber + 1; + } + if (randomNumber < 0 || randomNumber > 100) { + //You lose when the number is out of the 1 to 100 range + g.setFont("Vector",13);g.setFontAlign(-1,-1); + g.drawString('You have lost\nNumber is out\nof range.',10,10,true); + status = "You lost!"; + } else { + g.drawString(status+"\nTry again!",10,10); + Bangle.on('tap', function() { + delay(3000).then(() => game()); + } + ); + } + } + } +}; + +function gameOver() +{ + E.showPrompt(status+'Play again?',{title:""+'Number Chaser'}).then(function(a) { + if (a) { + randomNumber = mathRandomInt(1, 100); + game(); + } else { + load(); + } + } + ); +} + +function delay(time) { + return new Promise(resolve => setTimeout(resolve, time)); +} + +function instructions() +{ + g.setFont("Vector",13);g.setFontAlign(-1,-1); + g.drawString('Guess the number\nbetween 1 and 100.\nGuess too high, it\ndecreases by 1.\nToo low, it increases\nby 1.\nIf the number\ngoes below 0 or\nabove 100, it\nis out of range\nand you have\nlost.',10,10,true); + randomNumber = mathRandomInt(1, 100); + delay(10000).then(() => game()); +} + + +g.clear(); +E.showPrompt('Do you need instructions?',{title:""+'Number Chaser'}).then(function(a) + { if (a) { + instructions(); + } else + { + randomNumber = mathRandomInt(1, 100); + game(); + } + } +); From 639163c683117b06075a35da254811e2e421062c Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 16:42:31 -0400 Subject: [PATCH 32/72] Create app-icon.js --- apps/numberchaser/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/numberchaser/app-icon.js diff --git a/apps/numberchaser/app-icon.js b/apps/numberchaser/app-icon.js new file mode 100644 index 000000000..a4bb5054d --- /dev/null +++ b/apps/numberchaser/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkA/4AC+c/AoYAR+QTTj4DBkYXS+YUB+cSl4YS+P/mUiL4RLQ+chiUziPyAAIXPmJEC+Ui+UhO6QABj8iVKocEACUTC60j+YXWPoZHTkcyC6sibYaPpC63ziXzkYXUkXyO6nykMykIXUl8xmcykQ2BSZ4XBkTXB+LdBMgPyDRnzj8vmf/AIMyDgMjAoIALiQSCVYI0CD4QAL+MTIILFCI4TJOmMRkUzn40CGQRLBMRipBiIABkR2DTAIAQmURF4KcBZScxn5qBACgWWbwUhMCT7CmU/WQQAR+awBF6jdBVggXSPCwXXVAPyJCkimUieKinBI6sxAQIvUeAMyMQIXT+MjI6iNC+RIT+bAB+cSYiZdBMQMzSCkf+ZIUGAMiYKsjkTbVkMSl4A==")) From c8e9da0f62c5d24336085aece4bbf89cc13a4432 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 16:55:09 -0400 Subject: [PATCH 33/72] Create metadata.json --- apps/numberchaser/metadata.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 apps/numberchaser/metadata.json diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json new file mode 100644 index 000000000..0bbebd3e5 --- /dev/null +++ b/apps/numberchaser/metadata.json @@ -0,0 +1,12 @@ +{ "id": "nuberchaser", + "name": "Number Chaser", + "shortName":"Number Chaser", + "version":"0.01", + "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", + "icon": "app.png", + "tags": "", + "storage": [ + {"name":"numberchaser.app.js","url":"app.js"}, + {"name":"numberchaser.img","url":"app-icon.js","evaluate":true} + ] +} From 78a53d5a2443b9ae29a9141820cd39647f03d858 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 16:59:29 -0400 Subject: [PATCH 34/72] Fixed a spelling mistake --- apps/numberchaser/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index 0bbebd3e5..078d174b7 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -1,4 +1,4 @@ -{ "id": "nuberchaser", +{ "id": "numberchaser", "name": "Number Chaser", "shortName":"Number Chaser", "version":"0.01", From 70899f56bb2e67461ccb2bd59f37c47298b10e49 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 17:05:47 -0400 Subject: [PATCH 35/72] Add files via upload --- apps/numberchaser/numberchaser.png | Bin 0 -> 1882 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/numberchaser/numberchaser.png diff --git a/apps/numberchaser/numberchaser.png b/apps/numberchaser/numberchaser.png new file mode 100644 index 0000000000000000000000000000000000000000..2042cc22b2dc63f53e15dd5da27fceba29ced4ea GIT binary patch literal 1882 zcmV-g2c`IlP)pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H12Iomc zK~!jg&6!(BR9zd#f1^36Wrm7MD5jN^)<_ma88oRSRGJiZQB=@Lu#2FR1d(EaVJB}S zwS!s2KxI}?FkPe!R1`I8lqurqL@9ZmNu2{TJ@3Vb!|Q9M)0a9w7?{2Gv)2CqXFqGN zXRlF+i0}*Sb~{R?60KItz`y`ow{HDa=#=3FU^E(OYik>IQmIq|pw((gNlBShVdKRM zpuD`Cf`Wpd1{4<;vu)cpX3w5IslvvKcV1pzUQkdFB0^tZA2Bg8u9Gibyx{!#^H{A` z8XFr~v0}xj0Yn6w&BnB8(|KyGd>zP`Q$1_sjG+dCx&T=)I{{rlwQ<&lw*!PBQt2@4Aw5x8;V zMoynT&4mjW5E1NlJ6>L1C-yZQC|!Z*Q01VK$p3K0aPP zfBr1l+1XN1Q1ILM$p8@%yWKwS4r;Y}Orw*D7l4nC&$#c{ym|957z`7Z5$@tOcF0I( z&Ya26&=3}j1+7*)5t`h>Z39lH6K`*CzI^$DMx&vqsL1troeJDGU^bhvTCG%9SF>*2 zI+Bx<$<58hX0uI%zAtp<=0HnJ3(?Whl$MqP@aWMa zu3x{7Uay}JapS=)15Hg$L`FusCTwkOElEj9T)TE{Ld1;+w+wW4b`ld4!`ruS(P%Vu zb#?Lj^=r&#^N0#{GI47T*lafZ{QM{?Dnh5z(cRrmVqzlm=g+66rUso(hs9#S+uNJ$ z>}(<;A`lUtJ$pt#Kme;&t(sZ`N~IEu#X?X}5RHwEtXZ>$TeohJlaoV8NC?Tv$pB!25rcIk%PpQPjMC$75`1b7^v9YnPxJ#EVk(!!{)9IwTx_WX9s8lNa{rxE| zEk&(XbNu*m-n@B(TCE14zrUaA>T1%{(_MYES}k#LaagTZrca;lYVYdmV%Dr#`1||Q z+1dHW25`50{r>&CY}v9!GBYzpr_+hk>2#etdi1Cm42BW$d-v{@{{DU`FE5wp&!4;6 zO(v6ExpGA^Gc%>Ft?dtsX%V+q;$doPYA7o!L$B8p8ym~Qg$tQCZysS`VFU*UyFP=1 zgWS7!kMQttcJJPeLZLuJC@U*-Z6usLdGfzMD#gXctX;d7`1ttW>iA;=|Grprb2E*N zjkL71(ACvNPfrg$Jw0@Hchl3;gTvuKp->PK5`s#lV(HSQL`6lhV8H^SqN08}Zb?ZA zO-)T)zI=IN4Y)&BR~L14b=20@Qd?V#Uax2U`t_VRae~OmNB|rT2WQWoB_bk%{rmTi zJ?I}N-(SFPw~I!jk;RJ_%kA5@#csFDu3fuCuh)-zj43rRjLBpYwOTDzRaIiOTHWe9 zsVVe3Iy*a2tJUcBdPIaPSFX^|(122@BtAZ#Lx&FiwBOVg^Zz0=G?Wb+Ht_iIW9sYc z$;`~;$dMxeFDe0`>A-CV?g@xGd_EGU3XCO88pmoHt%ZEbC` zZ{I%GJNSbK52UiP(lb*?M5LjiK@t)Yq_3|}1_uXa$BrFhGMPj~ Date: Thu, 22 Sep 2022 17:07:00 -0400 Subject: [PATCH 36/72] Update metadata.json --- apps/numberchaser/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index 078d174b7..3b3e2f6db 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -3,7 +3,7 @@ "shortName":"Number Chaser", "version":"0.01", "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", - "icon": "app.png", + "icon": "numberchaser.png", "tags": "", "storage": [ {"name":"numberchaser.app.js","url":"app.js"}, From ecb6c640c02129aa92174be393e75c8f19746aed Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 17:09:02 -0400 Subject: [PATCH 37/72] Update metadata.json --- apps/numberchaser/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index 3b3e2f6db..d3f8da40d 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -4,7 +4,7 @@ "version":"0.01", "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", "icon": "numberchaser.png", - "tags": "", + "tags": "games", "storage": [ {"name":"numberchaser.app.js","url":"app.js"}, {"name":"numberchaser.img","url":"app-icon.js","evaluate":true} From d5d105bcb297af29a4fea7e3eb44d1bef9618cd2 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Thu, 22 Sep 2022 17:23:48 -0400 Subject: [PATCH 38/72] Update metadata.json --- apps/numberchaser/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index d3f8da40d..a3e54f381 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -5,6 +5,7 @@ "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", "icon": "numberchaser.png", "tags": "games", + "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"numberchaser.app.js","url":"app.js"}, {"name":"numberchaser.img","url":"app-icon.js","evaluate":true} From 435ad5c730cce20f80cbc5a40ebb7f8e64b9a9ad Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 21 Sep 2022 23:03:21 +0200 Subject: [PATCH 39/72] Swipe Menus initial release --- apps/swscroll/ChangeLog | 1 + apps/swscroll/README.md | 9 ++++ apps/swscroll/app.png | Bin 0 -> 279 bytes apps/swscroll/boot.js | 100 ++++++++++++++++++++++++++++++++++++ apps/swscroll/metadata.json | 14 +++++ 5 files changed, 124 insertions(+) create mode 100644 apps/swscroll/ChangeLog create mode 100644 apps/swscroll/README.md create mode 100644 apps/swscroll/app.png create mode 100644 apps/swscroll/boot.js create mode 100644 apps/swscroll/metadata.json diff --git a/apps/swscroll/ChangeLog b/apps/swscroll/ChangeLog new file mode 100644 index 000000000..c650baf72 --- /dev/null +++ b/apps/swscroll/ChangeLog @@ -0,0 +1 @@ +0.01: Inital release. diff --git a/apps/swscroll/README.md b/apps/swscroll/README.md new file mode 100644 index 000000000..f97d59b71 --- /dev/null +++ b/apps/swscroll/README.md @@ -0,0 +1,9 @@ +This first release seems servicable in testing so far. + +To get the standard menu scrolling back, just remove this app from your Bangle. + +TODO: +- Maybe have how much of "trailing space" there are after the last entry should be dynamic in size, now it's always 8 pixels which corresponds to if there are a widget field and a menu title present. +- I want to change the size of menu entries to be a little bigger vertically. + +Drag List Down icon by Icons8 diff --git a/apps/swscroll/app.png b/apps/swscroll/app.png new file mode 100644 index 0000000000000000000000000000000000000000..7abd582c27522003f81ffe3d748e48f84e6f73e4 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCwj^(N7l!{JxM1({$v}}ao-U3d z8I5nR`f?pI5MX^^zV5d34C6{p?HwV4Z|*x~+~xczGH<1=3!i}a(cT+bg-K@bqqnKP z=WXS2Z~+35?w-97x&8m`rk=y!x8Id6Wldq9^6$XpojXr4|4donaeM9Ly4+ItsBI4ya(>4|`rwnTDl<{Itf?+UX% ZFl31uo;m1P84UCngQu&X%Q~loCIA(bbEg0R literal 0 HcmV?d00001 diff --git a/apps/swscroll/boot.js b/apps/swscroll/boot.js new file mode 100644 index 000000000..fc5650cad --- /dev/null +++ b/apps/swscroll/boot.js @@ -0,0 +1,100 @@ +E.showScroller = (function(options) { + /* options = { + h = height + c = # of items + scroll = initial scroll position + scrollMin = minimum scroll amount (can be negative) + draw = function(idx, rect) + select = function(idx) + } + + returns { + draw = draw all + drawItem(idx) = draw specific item + } + */ +if (!options) return Bangle.setUI(); // remove existing handlers + +var menuShowing = false; +var R = Bangle.appRect; +var Y = Bangle.appRect.y; +var n = Math.ceil(R.h/options.h); +var menuScrollMin = 0|options.scrollMin; +var menuScrollMax = options.h*options.c - R.h; +if (menuScrollMax { + g.reset().clearRect(R.x,R.y,R.x2,R.y2); + g.setClipRect(R.x,R.y,R.x2,R.y2); + var a = YtoIdx(R.y); + var b = Math.min(YtoIdx(R.y2),options.c-1); + for (var i=a;i<=b;i++) + options.draw(i, {x:R.x,y:idxToY(i),w:R.w,h:options.h}); + g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); +}, drawItem : i => { + var y = idxToY(i); + g.reset().setClipRect(R.x,y,R.x2,y+options.h); + options.draw(i, {x:R.x,y:y,w:R.w,h:options.h}); + g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); +}}; +var rScroll = s.scroll&~1; // rendered menu scroll (we only shift by 2 because of dither) +s.draw(); // draw the full scroller +g.flip(); // force an update now to make this snappier +Bangle.setUI({ + mode : "custom", + back : options.back, + swipe : (hor,ver)=>{ + pixels = 120; + var dy = ver*pixels; + if (s.scroll - dy > menuScrollMax) + dy = s.scroll - menuScrollMax-8; // Makes it so the last 'page' has the same position as previous pages. This should be done dynamically (change the static 8 to be a variable) so the offset is correct even when no widget field or title field is present. + if (s.scroll - dy < menuScrollMin) + dy = s.scroll - menuScrollMin; + s.scroll -= dy; + var oldScroll = rScroll; + rScroll = s.scroll &~1; + dy = oldScroll-rScroll; + if (!dy || options.c<=3) return; //options.c<=3 should maybe be dynamic, so 3 would be replaced by a variable dependent on R=Bangle.appRect. It's here so we don't try to scroll if all entries fit in the app rectangle. + g.reset().setClipRect(R.x,R.y,R.x2,R.y2); + g.scroll(0,dy); + var d = ver*pixels; + if (d < 0) { + g.setClipRect(R.x,R.y2-(1-d),R.x2,R.y2); + let i = YtoIdx(R.y2-(1-d)); + let y = idxToY(i); + //print(i, options.c, options.c-i); //debugging info + while (y < R.y2 - (options.h*((options.c-i)<=0)) ) { //- (options.h*((options.c-i)<=0)) makes sure we don't go beyond the menu entries in the menu object "options". This has to do with "dy = s.scroll - menuScrollMax-8" above. + options.draw(i, {x:R.x,y:y,w:R.w,h:options.h}); + i++; + y += options.h; + } + } else { // d>0 + g.setClipRect(R.x,R.y,R.x2,R.y+d); + let i = YtoIdx(R.y+d); + let y = idxToY(i); + //print(i, options.c, options.c-i); //debugging info + while (y > R.y-options.h) { + options.draw(i, {x:R.x,y:y,w:R.w,h:options.h}); + y -= options.h; + i--; + } + } + g.setClipRect(0,0,g.getWidth()-1,g.getHeight()-1); + }, touch : (_,e)=>{ + if (e.y=0) && i Date: Fri, 23 Sep 2022 00:08:21 +0200 Subject: [PATCH 40/72] Bangle2 add software back via setUI --- apps/about/ChangeLog | 1 + apps/about/app-bangle2.js | 6 +++++- apps/about/metadata.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/about/ChangeLog b/apps/about/ChangeLog index f5638fdd2..ffe9de081 100644 --- a/apps/about/ChangeLog +++ b/apps/about/ChangeLog @@ -10,3 +10,4 @@ 0.10: Added separate Bangle.js 2 file with Bangle.js 2 kickstarter pixels (as of 28 Oct 2021) 0.11: Bangle.js2: New pixels, btn1 to exit 0.12: Actual pixels as of 29th Nov 2021 +0.13: Bangle.js 2: Use setUI to add software back button diff --git a/apps/about/app-bangle2.js b/apps/about/app-bangle2.js index 978d36193..62558462e 100644 --- a/apps/about/app-bangle2.js +++ b/apps/about/app-bangle2.js @@ -69,4 +69,8 @@ function drawImage() { // TODO: a nice little animation before setTimeout(drawInfo, 1000); -setWatch(_=>load(), BTN1); +Bangle.setUI({ + mode : "custom", + back : load, + btn : load +}); diff --git a/apps/about/metadata.json b/apps/about/metadata.json index 6c22bdc56..648576576 100644 --- a/apps/about/metadata.json +++ b/apps/about/metadata.json @@ -1,7 +1,7 @@ { "id": "about", "name": "About", - "version": "0.12", + "version": "0.13", "description": "Bangle.js About page - showing software version, stats, and a collaborative mural from the Bangle.js KickStarter backers", "icon": "app.png", "tags": "tool,system", From 97f89db4a21e8eda63cc9c3a2dcff96422b32aee Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 23 Sep 2022 00:21:35 +0200 Subject: [PATCH 41/72] sofware back button via setUI --- apps/activityreminder/ChangeLog | 3 ++- apps/activityreminder/app.js | 7 ++++++- apps/activityreminder/metadata.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/activityreminder/ChangeLog b/apps/activityreminder/ChangeLog index c913481ff..3811425ac 100644 --- a/apps/activityreminder/ChangeLog +++ b/apps/activityreminder/ChangeLog @@ -6,4 +6,5 @@ 0.06: Add a temperature threshold to detect (and not alert) if the BJS isn't worn. Better support for the peoples using the app at night 0.07: Fix bug on the cutting edge firmware 0.08: Use default Bangle formatter for booleans -0.09: New app screen (instead of showing settings or the alert) and some optimisations \ No newline at end of file +0.09: New app screen (instead of showing settings or the alert) and some optimisations +0.10: Add software back button via setUI diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 97f03ce97..9859956f8 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -47,8 +47,13 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); drawInfo(); + Bangle.setUI({ + mode : "custom", + back : load, + btn : load + }) } run(); -})(); \ No newline at end of file +})(); diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 9e8c552b1..a7fb0c487 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -3,7 +3,7 @@ "name": "Activity Reminder", "shortName":"Activity Reminder", "description": "A reminder to take short walks for the ones with a sedentary lifestyle", - "version":"0.09", + "version":"0.10", "icon": "app.png", "type": "app", "tags": "tool,activity", From a1e6bae39fd457fd526a3c0bfa3ee56503f14bf0 Mon Sep 17 00:00:00 2001 From: Spencer Churchill Date: Thu, 22 Sep 2022 15:29:59 -0700 Subject: [PATCH 42/72] only vibrate during work hours --- apps/widtwenties/widget.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/widtwenties/widget.js b/apps/widtwenties/widget.js index 58bc622eb..745e50391 100644 --- a/apps/widtwenties/widget.js +++ b/apps/widtwenties/widget.js @@ -7,9 +7,13 @@ they don't interfere with currently-running apps */ const look = 20 * 1000; // 20 seconds buzz = _ => { - Bangle.buzz().then(_ => { - setTimeout(Bangle.buzz, look); - }); + const d = new Date(); + // run from 8 AM - 5 PM + if (d >= 8 && d <= 17) { + Bangle.buzz().then(_ => { + setTimeout(Bangle.buzz, look); + }); + } }; // add widget @@ -21,4 +25,4 @@ they don't interfere with currently-running apps */ setInterval(WIDGETS.twenties.buzz, move); // buzz to stand / sit })(); -// Bangle.drawWidgets(); // <-- for development only \ No newline at end of file +// Bangle.drawWidgets(); // <-- for development only From 9f16ca2183ea039f54c1aa74478e423d685241ab Mon Sep 17 00:00:00 2001 From: Spencer Churchill Date: Thu, 22 Sep 2022 15:35:31 -0700 Subject: [PATCH 43/72] updates app version --- apps/widtwenties/ChangeLog | 3 ++- apps/widtwenties/metadata.json | 2 +- apps/widtwenties/widget.js | 3 +-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/widtwenties/ChangeLog b/apps/widtwenties/ChangeLog index 87935d810..b1cd84c9e 100644 --- a/apps/widtwenties/ChangeLog +++ b/apps/widtwenties/ChangeLog @@ -1,2 +1,3 @@ 0.01: New Widget! -0.02: Fix calling null on draw \ No newline at end of file +0.02: Fix calling null on draw +0.03: Only vibrate during working hours \ No newline at end of file diff --git a/apps/widtwenties/metadata.json b/apps/widtwenties/metadata.json index 2e51457ac..5695a0ed9 100644 --- a/apps/widtwenties/metadata.json +++ b/apps/widtwenties/metadata.json @@ -2,7 +2,7 @@ "id": "widtwenties", "name": "Twenties", "shortName": "twenties", - "version": "0.02", + "version": "0.03", "description": "Buzzes every 20m to stand / sit and look 20ft away for 20s.", "icon": "widget.png", "type": "widget", diff --git a/apps/widtwenties/widget.js b/apps/widtwenties/widget.js index 745e50391..224cbe5ac 100644 --- a/apps/widtwenties/widget.js +++ b/apps/widtwenties/widget.js @@ -8,8 +8,7 @@ they don't interfere with currently-running apps */ buzz = _ => { const d = new Date(); - // run from 8 AM - 5 PM - if (d >= 8 && d <= 17) { + if (d >= 8 && d <= 17) { // run from 8 AM - 5 PM Bangle.buzz().then(_ => { setTimeout(Bangle.buzz, look); }); From 91cfd487a325ea701258f4b80bc8481c744a57ab Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Thu, 22 Sep 2022 23:36:08 +0100 Subject: [PATCH 44/72] Now only checks battery every 15 minutes --- apps/bigdclock/bigdclock.app.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index dba60183c..a3691539b 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -11,6 +11,8 @@ Graphics.prototype.setFontOpenSans = function(scale) { }; var drawTimeout; +var lastBattCheck = 0; +var width = 0; function queueDraw(millis_now) { if (drawTimeout) clearTimeout(drawTimeout); @@ -26,12 +28,16 @@ function draw() { m = date.getMinutes(); var d = date.getDate(), w = date.getDay(); // d=1..31; w=0..6 - const level = E.getBattery(); - const width = level + (level/2); var is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; // var dows = require("date_utils").dows(0,1); var dows = ["SU","MO","TU","WE","TH","FR","SA"]; + if (date.getTime() >= lastBattCheck + 15*60000) { + lastBattcheck = date.getTime(); + width = E.getBattery(); + width += width/2; + } + g.reset(); g.clear(); @@ -63,7 +69,7 @@ function draw() { g.setColor(0,1,0); g.fillRect(73,162,162,168); } - if (level < 100) { + if (width < 150) { g.setColor(g.theme.bg); g.fillRect(12+width+1,162,162,168); } From a5b909319f22af175a0e73e6aee4ac12549b4d44 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 23 Sep 2022 00:39:27 +0200 Subject: [PATCH 45/72] add software back button in main menu --- apps/banglexercise/ChangeLog | 1 + apps/banglexercise/app.js | 3 ++- apps/banglexercise/metadata.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/banglexercise/ChangeLog b/apps/banglexercise/ChangeLog index 5f1d3bd7d..6cf589541 100644 --- a/apps/banglexercise/ChangeLog +++ b/apps/banglexercise/ChangeLog @@ -2,3 +2,4 @@ 0.02: Add sit ups Add more feedback to the user about the exercises Clean up code +0.03: Add software back button on main menu diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index bc6e35f07..8a4187046 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -71,7 +71,8 @@ function showMainMenu() { let menu; menu = { "": { - title: "BanglExercise" + title: "BanglExercise", + back: load } }; diff --git a/apps/banglexercise/metadata.json b/apps/banglexercise/metadata.json index 9bb93f112..f4ce1894b 100644 --- a/apps/banglexercise/metadata.json +++ b/apps/banglexercise/metadata.json @@ -1,7 +1,7 @@ { "id": "banglexercise", "name": "BanglExercise", "shortName":"BanglExercise", - "version":"0.02", + "version":"0.03", "description": "Can automatically track exercises while wearing the Bangle.js watch.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], From 1963eea12c97b33d1a91c29e642b43f173e2dce4 Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Thu, 22 Sep 2022 23:47:11 +0100 Subject: [PATCH 46/72] Bar across the middle of the screen colour The bar across the middle of the screen will now also indicate the battery state of charge. BUT NOTE that the "date_utils" library seems to be missing from my watch! --- apps/bigdclock/bigdclock.app.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index a3691539b..b71a6b0a3 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -32,7 +32,7 @@ function draw() { // var dows = require("date_utils").dows(0,1); var dows = ["SU","MO","TU","WE","TH","FR","SA"]; - if (date.getTime() >= lastBattCheck + 15*60000) { + if ((date.getTime() >= lastBattCheck + 15*60000) || Bangle.isCharging()) { lastBattcheck = date.getTime(); width = E.getBattery(); width += width/2; @@ -74,7 +74,15 @@ function draw() { g.fillRect(12+width+1,162,162,168); } - g.setColor(0, 1, 0); + if (Bangle.isCharging()) { + g.setColor(1,1,0); + } else if (width <= 45) { + g.setColor(1,0,0); + } else if (width <= 60) { + g.setColor(1,1,0); + } else { + g.setColor(0, 1, 0); + } g.fillRect(0, 90, g.getWidth(), 94); // widget redraw From 4ad1ec52984e83f03dc06aa144456860b633c3b3 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 23 Sep 2022 00:53:45 +0200 Subject: [PATCH 47/72] add loadWidgets to make back button and title work together --- apps/banglexercise/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 8a4187046..9659ee81f 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -382,4 +382,5 @@ Bangle.on('HRM', function(hrm) { }); g.clear(1); +Bangle.loadWidgets(); showMainMenu(); From 085b58084c9907ecd5ea7abc2d5bf1565527be8b Mon Sep 17 00:00:00 2001 From: Spencer Churchill Date: Thu, 22 Sep 2022 23:46:27 -0700 Subject: [PATCH 48/72] fix bug and check day of week --- apps/widtwenties/ChangeLog | 2 +- apps/widtwenties/widget.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/widtwenties/ChangeLog b/apps/widtwenties/ChangeLog index b1cd84c9e..c2fbd70a2 100644 --- a/apps/widtwenties/ChangeLog +++ b/apps/widtwenties/ChangeLog @@ -1,3 +1,3 @@ 0.01: New Widget! 0.02: Fix calling null on draw -0.03: Only vibrate during working hours \ No newline at end of file +0.03: Only vibrate during work \ No newline at end of file diff --git a/apps/widtwenties/widget.js b/apps/widtwenties/widget.js index 224cbe5ac..f722f8d03 100644 --- a/apps/widtwenties/widget.js +++ b/apps/widtwenties/widget.js @@ -7,8 +7,11 @@ they don't interfere with currently-running apps */ const look = 20 * 1000; // 20 seconds buzz = _ => { - const d = new Date(); - if (d >= 8 && d <= 17) { // run from 8 AM - 5 PM + const date = new Date(); + const day = date.getDay(); + const hour = date.getHours(); + // buzz at work + if (day <= 5 && hour >= 8 && hour <= 17) { Bangle.buzz().then(_ => { setTimeout(Bangle.buzz, look); }); From c0b49b33598040b9a6517eda12239de562cf0e8e Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Fri, 23 Sep 2022 07:16:58 +0000 Subject: [PATCH 49/72] Update ChangeLog --- apps/slash/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/slash/ChangeLog b/apps/slash/ChangeLog index f3fae1785..734df26dd 100644 --- a/apps/slash/ChangeLog +++ b/apps/slash/ChangeLog @@ -1 +1,2 @@ 0.01: First version for upload +0.02: Fix for leftover date artifacts on display. From 2e8bb01e55df47dda52851c0921b61291df86a8c Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Fri, 23 Sep 2022 07:17:52 +0000 Subject: [PATCH 50/72] Update metadata.json --- apps/slash/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/slash/metadata.json b/apps/slash/metadata.json index 6bdb4cd53..b08aa7c44 100644 --- a/apps/slash/metadata.json +++ b/apps/slash/metadata.json @@ -4,7 +4,7 @@ "shortName":"Slash", "icon": "slash.png", "screenshots": [{"url":"screenshot.png"}], - "version":"0.01", + "version":"0.02", "description": "Slash Watch based on Pebble watch face by Nikki.", "tags": "clock", "type": "clock", From e1d1df200244a8b93db294fa03357e5db65009f5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 23 Sep 2022 08:37:38 +0100 Subject: [PATCH 51/72] Make openstmap use https map tiles so it works from gadgetbridge (fix #2136) --- apps/openstmap/custom.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openstmap/custom.html b/apps/openstmap/custom.html index 6f611dd86..3bba997e7 100644 --- a/apps/openstmap/custom.html +++ b/apps/openstmap/custom.html @@ -66,20 +66,20 @@ TODO: However some don't allow cross-origin use */ //var TILELAYER = 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png'; // simple, high contrast, TOO SLOW //var TILELAYER = 'http://a.tile.stamen.com/toner/{z}/{x}/{y}.png'; // black and white - var TILELAYER = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; - var PREVIEWTILELAYER = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; + var TILELAYER = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; + var PREVIEWTILELAYER = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; // Create map and try and set the location to where the browser thinks we are var map = L.map('map').locate({setView: true, maxZoom: 16, enableHighAccuracy:true}); // Tiles used for Bangle.js itself var bangleTileLayer = L.tileLayer(TILELAYER, { maxZoom: 18, - attribution: 'Map data © OpenStreetMap contributors' + attribution: 'Map data © OpenStreetMap contributors' }); // Tiles used for the may the user sees (faster) var previewTileLayer = L.tileLayer(PREVIEWTILELAYER, { maxZoom: 18, - attribution: 'Map data © OpenStreetMap contributors' + attribution: 'Map data © OpenStreetMap contributors' }); // Could optionally overlay trails: https://wiki.openstreetmap.org/wiki/Tiles From ca206def9461fbdd0fb8327b03befb04c1d566c4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 23 Sep 2022 08:51:02 +0100 Subject: [PATCH 52/72] Just removed `btn:` as this doesn't work anyway (the callback is called with `1` as an argument so `load` would fail) and back via button is added automatically #2139 #2140 --- apps/about/app-bangle2.js | 3 +-- apps/activityreminder/app.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/about/app-bangle2.js b/apps/about/app-bangle2.js index 62558462e..0c40314a8 100644 --- a/apps/about/app-bangle2.js +++ b/apps/about/app-bangle2.js @@ -71,6 +71,5 @@ function drawImage() { setTimeout(drawInfo, 1000); Bangle.setUI({ mode : "custom", - back : load, - btn : load + back : load }); diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 9859956f8..81e10d8dd 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -49,8 +49,7 @@ drawInfo(); Bangle.setUI({ mode : "custom", - back : load, - btn : load + back : load }) } From c362881de1e48d6b41433a386c6704713250ebb5 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 23 Sep 2022 16:08:16 +0200 Subject: [PATCH 53/72] Added clockinfo to simple timer and improved the clkinfo module (run with optional feedback). --- apps/bwclk/ChangeLog | 3 +- apps/bwclk/app.js | 6 ++- apps/bwclk/metadata.json | 2 +- apps/ha/ChangeLog | 3 +- apps/ha/ha.clkinfo.js | 1 + apps/ha/metadata.json | 2 +- apps/smpltmr/ChangeLog | 3 +- apps/smpltmr/clkinfo.js | 97 ++++++++++++++++++++++++++++++++++++++ apps/smpltmr/metadata.json | 3 +- modules/clock_info.js | 2 +- 10 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 apps/smpltmr/clkinfo.js diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 72919e37f..546c83894 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -19,4 +19,5 @@ 0.19: Fix - Compatibility with "Digital clock widget" 0.20: Better handling of async data such as getPressure. 0.21: On the default menu the week of year can be shown. -0.22: Use the new clkinfo module for the menu. \ No newline at end of file +0.22: Use the new clkinfo module for the menu. +0.23: Feedback of apps after run is now optional and decided by the corresponding clkinfo. \ No newline at end of file diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index c8c885ee1..7dcca9d75 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -164,8 +164,10 @@ function runMenuItem(){ var menuEntry = menu[settings.menuPosX]; var item = menuEntry.items[settings.menuPosY-1]; try{ - item.run(); - Bangle.buzz(300, 0.6).then(() => {}); + var ret = item.run(); + if(ret){ + Bangle.buzz(300, 0.6); + } } catch (ex) { // Simply ignore it... } diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index 35e707f68..fbae0e1e7 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.22", + "version": "0.23", "description": "A very minimalistic clock to mainly show date and time.", "readme": "README.md", "icon": "app.png", diff --git a/apps/ha/ChangeLog b/apps/ha/ChangeLog index 493854eb4..c28526abd 100644 --- a/apps/ha/ChangeLog +++ b/apps/ha/ChangeLog @@ -1,3 +1,4 @@ 0.01: Release 0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. -0.03: Added clkinfo for clocks. \ No newline at end of file +0.03: Added clkinfo for clocks. +0.04: Feedback if clkinfo run is called. \ No newline at end of file diff --git a/apps/ha/ha.clkinfo.js b/apps/ha/ha.clkinfo.js index bb3b7e5a1..ad7f51c57 100644 --- a/apps/ha/ha.clkinfo.js +++ b/apps/ha/ha.clkinfo.js @@ -17,6 +17,7 @@ run: function() { ha.sendTrigger("TRIGGER_BW"); ha.sendTrigger(trigger.trigger); + return true; } }); }); diff --git a/apps/ha/metadata.json b/apps/ha/metadata.json index e59e63c91..8ccaea598 100644 --- a/apps/ha/metadata.json +++ b/apps/ha/metadata.json @@ -1,7 +1,7 @@ { "id": "ha", "name": "HomeAssistant", - "version": "0.03", + "version": "0.04", "description": "Integrates your BangleJS into HomeAssistant.", "icon": "ha.png", "type": "app", diff --git a/apps/smpltmr/ChangeLog b/apps/smpltmr/ChangeLog index bf128e2fb..572aaa91e 100644 --- a/apps/smpltmr/ChangeLog +++ b/apps/smpltmr/ChangeLog @@ -1,2 +1,3 @@ 0.01: Release -0.02: Rewrite with new interface \ No newline at end of file +0.02: Rewrite with new interface +0.03: Added clock infos to expose timer functionality to clocks. \ No newline at end of file diff --git a/apps/smpltmr/clkinfo.js b/apps/smpltmr/clkinfo.js new file mode 100644 index 000000000..dfc70aab9 --- /dev/null +++ b/apps/smpltmr/clkinfo.js @@ -0,0 +1,97 @@ +(function() { + const TIMER_IDX = "smpltmr"; + + function isAlarmEnabled(){ + try{ + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; + + } catch(ex){ } + return false; + } + + function getAlarmMinutes(){ + if(!isAlarmEnabled()){ + return -1; + } + + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); + } + + function getAlarmMinutesText(){ + var min = getAlarmMinutes(); + if(min < 0){ + return "OFF"; + } + + return "T-" + String(min); + } + + function increaseAlarm(t){ + try{ + var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, { + timer : (minutes+t)*60*1000, + }); + alarm.reload(); + } catch(ex){ } + } + + function decreaseAlarm(t){ + try{ + var minutes = getAlarmMinutes(); + minutes -= t; + + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, undefined); + + if(minutes > 0){ + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); + } + + alarm.reload(); + } catch(ex){ } + } + + var img = atob("GBiBAeAAB+AAB/v/3/v/3/v/3/v/3/v/n/n/H/z+P/48//85//+b//+b//8p//4E//yCP/kBH/oAn/oAX/oAX/oAX/oAX+AAB+AABw==") + var smpltmrItems = { + name: "Timer", + img: img, + items: [ + { + name: "Timer", + get: () => ({ text: getAlarmMinutesText() + (isAlarmEnabled() ? " min" : ""), img: null}), + show: function() { smpltmrItems.items[0].emit("redraw"); }, + hide: function () {}, + run: function() { } + }, + ] + }; + + var offsets = [+1,+5,-1,-5]; + offsets.forEach((o, i) => { + smpltmrItems.items = smpltmrItems.items.concat({ + name: String(o), + get: () => ({ text: getAlarmMinutesText() + " (" + (o > 0 ? "+" : "") + o + ")", img: null}), + show: function() { smpltmrItems.items[i+1].emit("redraw"); }, + hide: function () {}, + run: function() { + if(o > 0) increaseAlarm(o); + else decreaseAlarm(Math.abs(o)); + this.show(); + } + }); + }); + + return smpltmrItems; +}) \ No newline at end of file diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json index cb1ef6eab..4a219fad2 100644 --- a/apps/smpltmr/metadata.json +++ b/apps/smpltmr/metadata.json @@ -2,7 +2,7 @@ "id": "smpltmr", "name": "Simple Timer", "shortName": "Simple Timer", - "version": "0.02", + "version": "0.03", "description": "A very simple app to start a timer.", "icon": "app.png", "tags": "tool,alarm,timer", @@ -12,6 +12,7 @@ "readme": "README.md", "storage": [ {"name":"smpltmr.app.js","url":"app.js"}, + {"name":"smpltmr.clkinfo.js","url":"clkinfo.js"}, {"name":"smpltmr.img","url":"app-icon.js","evaluate":true} ] } diff --git a/modules/clock_info.js b/modules/clock_info.js index 4d70f0013..6a810371a 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -18,7 +18,7 @@ Note that each item is an object with: * 'item.show' : called when item should be shown. Enables updates. Call BEFORE 'get' * 'item.hide' : called when item should be hidden. Disables updates. * .on('redraw', ...) : event that is called when 'get' should be called again (only after 'item.show') -* 'item.run' : (optional) called if the info screen is tapped - can perform some action +* 'item.run' : (optional) called if the info screen is tapped - can perform some action. Return true if the caller should feedback the user. See the bottom of this file for example usage... From c1c9a98c4591e891091812bac660a27eec1853a4 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Fri, 23 Sep 2022 10:08:27 -0400 Subject: [PATCH 54/72] Updated tags on metadata.json --- apps/numberchaser/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index a3e54f381..2cb280d95 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -4,7 +4,7 @@ "version":"0.01", "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", "icon": "numberchaser.png", - "tags": "games", + "tags": "game,fun" "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"numberchaser.app.js","url":"app.js"}, From 399c9f0de65ceba5c988d05605dfa1e59bdba480 Mon Sep 17 00:00:00 2001 From: fearlessgeekmedia <114188406+fearlessgeekmedia@users.noreply.github.com> Date: Fri, 23 Sep 2022 10:14:59 -0400 Subject: [PATCH 55/72] Adding comma I accidentally left out --- apps/numberchaser/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/numberchaser/metadata.json b/apps/numberchaser/metadata.json index 2cb280d95..f9b6ff4b2 100644 --- a/apps/numberchaser/metadata.json +++ b/apps/numberchaser/metadata.json @@ -4,7 +4,7 @@ "version":"0.01", "description": "A number guessing game, but the number goes up or down based on if you're guessing too high or too low.", "icon": "numberchaser.png", - "tags": "game,fun" + "tags": "game,fun", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"numberchaser.app.js","url":"app.js"}, From 013685b01d34d3ef68ed771e75c048533b7869de Mon Sep 17 00:00:00 2001 From: Spencer Churchill Date: Fri, 23 Sep 2022 08:12:39 -0700 Subject: [PATCH 56/72] convert Twenties to boot code instead of widget --- apps/twenties/ChangeLog | 4 +++ apps/twenties/README.md | 17 +++++++++++++ .../widget.png => twenties/app.png} | Bin apps/twenties/boot.js | 18 +++++++++++++ apps/{widtwenties => twenties}/metadata.json | 12 ++++----- apps/widtwenties/ChangeLog | 2 -- apps/widtwenties/README.md | 15 ----------- apps/widtwenties/widget.js | 24 ------------------ 8 files changed, 45 insertions(+), 47 deletions(-) create mode 100644 apps/twenties/ChangeLog create mode 100644 apps/twenties/README.md rename apps/{widtwenties/widget.png => twenties/app.png} (100%) create mode 100644 apps/twenties/boot.js rename apps/{widtwenties => twenties}/metadata.json (52%) delete mode 100644 apps/widtwenties/ChangeLog delete mode 100644 apps/widtwenties/README.md delete mode 100644 apps/widtwenties/widget.js diff --git a/apps/twenties/ChangeLog b/apps/twenties/ChangeLog new file mode 100644 index 000000000..89eb9547f --- /dev/null +++ b/apps/twenties/ChangeLog @@ -0,0 +1,4 @@ +0.01: New Widget! +0.02: Fix calling null on draw +0.03: Only vibrate during work +0.04: Convert to boot code \ No newline at end of file diff --git a/apps/twenties/README.md b/apps/twenties/README.md new file mode 100644 index 000000000..8ee917b0e --- /dev/null +++ b/apps/twenties/README.md @@ -0,0 +1,17 @@ +# Twenties + +Follow the [20-20-20 rule](https://www.aoa.org/AOA/Images/Patients/Eye%20Conditions/20-20-20-rule.pdf) with discrete reminders. Your Bangle will buzz every 20 minutes for you to look away from your screen, and then buzz 20 seconds later to look back. Additionally, alternate between standing and sitting every 20 minutes to be standing for [more than 30 minutes](https://uwaterloo.ca/kinesiology-health-sciences/how-long-should-you-stand-rather-sit-your-work-station) per hour. + +## Usage + +Download this app and it will automatically run in the background. + +## Features + +Vibrates to remind you to stand up and look away for healthy living. + +Only vibrates during work days and hours. + +## Creator + +[@splch](https://github.com/splch/) diff --git a/apps/widtwenties/widget.png b/apps/twenties/app.png similarity index 100% rename from apps/widtwenties/widget.png rename to apps/twenties/app.png diff --git a/apps/twenties/boot.js b/apps/twenties/boot.js new file mode 100644 index 000000000..180f4cbb7 --- /dev/null +++ b/apps/twenties/boot.js @@ -0,0 +1,18 @@ +(() => { + const move = 20 * 60 * 1000; // 20 minutes + const look = 20 * 1000; // 20 seconds + + buzz = _ => { + const date = new Date(); + const day = date.getDay(); + const hour = date.getHours(); + // buzz at work + if (day <= 5 && hour >= 8 && hour <= 17) { + Bangle.buzz().then(_ => { + setTimeout(Bangle.buzz, look); + }); + } + }; + + setInterval(buzz, move); // buzz to stand / sit +})(); \ No newline at end of file diff --git a/apps/widtwenties/metadata.json b/apps/twenties/metadata.json similarity index 52% rename from apps/widtwenties/metadata.json rename to apps/twenties/metadata.json index 2e51457ac..b1dfe2134 100644 --- a/apps/widtwenties/metadata.json +++ b/apps/twenties/metadata.json @@ -1,13 +1,13 @@ { - "id": "widtwenties", + "id": "twenties", "name": "Twenties", "shortName": "twenties", - "version": "0.02", + "version": "0.04", "description": "Buzzes every 20m to stand / sit and look 20ft away for 20s.", - "icon": "widget.png", - "type": "widget", - "tags": "widget,tools", + "icon": "app.png", + "type": "bootloader", + "tags": "alarm,tool", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", - "storage": [{ "name": "widtwenties.wid.js", "url": "widget.js" }] + "storage": [{ "name": "twenties.boot.js", "url": "boot.js" }] } diff --git a/apps/widtwenties/ChangeLog b/apps/widtwenties/ChangeLog deleted file mode 100644 index 87935d810..000000000 --- a/apps/widtwenties/ChangeLog +++ /dev/null @@ -1,2 +0,0 @@ -0.01: New Widget! -0.02: Fix calling null on draw \ No newline at end of file diff --git a/apps/widtwenties/README.md b/apps/widtwenties/README.md deleted file mode 100644 index 1dea18b8e..000000000 --- a/apps/widtwenties/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Twenties - -Follow the [20-20-20 rule](https://www.aoa.org/AOA/Images/Patients/Eye%20Conditions/20-20-20-rule.pdf) with discrete reminders. Your BangleJS will buzz every 20 minutes for you to look away from your screen, and then buzz 20 seconds later to look back. Additionally, alternate between standing and sitting every 20 minutes to be standing for [more than 30 minutes](https://uwaterloo.ca/kinesiology-health-sciences/how-long-should-you-stand-rather-sit-your-work-station) per hour. - -## Usage - -Download this widget and, as long as your watch-face supports widgets, it will automatically run in the background. - -## Features - -Vibrate to remind you to stand up and look away for healthy living. - -## Creator - -[@splch](https://github.com/splch/) diff --git a/apps/widtwenties/widget.js b/apps/widtwenties/widget.js deleted file mode 100644 index 58bc622eb..000000000 --- a/apps/widtwenties/widget.js +++ /dev/null @@ -1,24 +0,0 @@ -// WIDGETS = {}; // <-- for development only - -/* run widgets in their own function scope so -they don't interfere with currently-running apps */ -(() => { - const move = 20 * 60 * 1000; // 20 minutes - const look = 20 * 1000; // 20 seconds - - buzz = _ => { - Bangle.buzz().then(_ => { - setTimeout(Bangle.buzz, look); - }); - }; - - // add widget - WIDGETS.twenties = { - buzz: buzz, - draw: _ => { return null; }, - }; - - setInterval(WIDGETS.twenties.buzz, move); // buzz to stand / sit -})(); - -// Bangle.drawWidgets(); // <-- for development only \ No newline at end of file From f6b38b34437572498b9ab8403dc333164b0b193a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 23 Sep 2022 17:43:09 +0100 Subject: [PATCH 57/72] Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16 --- apps/antonclk/ChangeLog | 3 +- apps/antonclk/app.js | 59 +++++++++++++++++++++---------------- apps/antonclk/metadata.json | 2 +- apps/launch/ChangeLog | 1 + apps/launch/app.js | 33 ++++++++++++++------- apps/launch/metadata.json | 2 +- 6 files changed, 61 insertions(+), 39 deletions(-) diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index f7e95b5fa..9e75d889a 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -10,4 +10,5 @@ week is buffered until date or timezone changes 0.07: align default settings with app.js (otherwise the initial displayed settings will be confusing to users) 0.08: fixed calendar weeknumber not shortened to two digits -0.09: Use default Bangle formatter for booleans \ No newline at end of file +0.09: Use default Bangle formatter for booleans +0.10: Use Bangle.setUI({remove:...}) to allow loading the launcher without a full reset on 2v16 diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 4b1e71bda..07f67f696 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,7 +1,4 @@ // Clock with large digits using the "Anton" bold font - -const SETTINGSFILE = "antonclk.json"; - Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78 + (scale << 8) + (1 << 16)); @@ -12,23 +9,28 @@ Graphics.prototype.setFontAntonSmall = function(scale) { g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAAAAAAAAAAAAAMAAAAAAAAD8AAAAAAAA/8AAAAAAAf/8AAAAAAH//8AAAAAB///8AAAAA////8AAAAP////8AAAD/////8AAB//////8AAf//////8AH///////4A///////+AA///////AAA//////wAAA/////8AAAA////+AAAAA////gAAAAA///4AAAAAA//8AAAAAAA//AAAAAAAA/wAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/////wAAA//////8AAB//////+AAH///////gAH///////gAP///////wAf///////4Af///////4A////////8A////////8A////////8A//AAAAD/8A/8AAAAA/8A/8AAAAA/8A/8AAAAA/8A/+AAAAB/8A////////8A////////8A////////8Af///////4Af///////4AP///////wAP///////wAH///////gAD///////AAA//////8AAAP/////wAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAA/4AAAAAAAA/4AAAAAAAB/wAAAAAAAB/wAAAAAAAD/wAAAAAAAD/gAAAAAAAH///////8AP///////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAP8AA//4AAA/8AB//4AAH/8AH//4AAP/8AP//4AA//8AP//4AB//8Af//4AD//8Af//4AP//8A///4Af//8A///4A///8A///4D///8A//AAH///8A/8AAP///8A/8AA//+/8A/8AD//8/8A/+Af//w/8A//////g/8A/////+A/8A/////8A/8Af////4A/8Af////wA/8AP////AA/8AP///+AA/8AH///8AA/8AD///wAA/8AA///AAA/8AAP/4AAA/8AAAAAAAAAAAAAAAAAAAAAAH4AAf/gAAA/4AAf/8AAD/4AAf//AAH/4AAf//gAP/4AAf//wAP/4AAf//wAf/4AAf//4Af/4AAf//4A//4AAf//8A//4AAf//8A//4AAP//8A//A/8AB/8A/8A/8AA/8A/8B/8AA/8A/8B/8AA/8A/+D//AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////gAH//9////gAD//4///+AAB//wf//4AAAP/AH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAAAB//wAAAAAAP//wAAAAAD///wAAAAA////wAAAAH////wAAAB/////wAAAf/////wAAD//////wAA///////wAA/////h/wAA////wB/wAA///8AB/wAA///AAB/wAA//gAAB/wAA////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AA////4P/+AA////4P//AA////4P//gA////4P//wA////4P//wA////4P//4A////4P//4A////4P//8A////4P//8A////4P//8A/8H/AAB/8A/8H+AAA/8A/8P+AAA/8A/8P+AAA/8A/8P/gAD/8A/8P/////8A/8P/////8A/8P/////8A/8P/////4A/8H/////4A/8H/////wA/8D/////wA/8B/////gA/8A////+AA/8AP///4AAAAAB///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAf/////8AAB///////AAH///////gAP///////wAP///////wAf///////4Af///////4A////////8A////////8A////////8A/+AH/AB/8A/8AP+AA/8A/4Af+AA/8A/8Af+AA/8A/8Af/gH/8A//4f////8A//4f////8A//4f////8Af/4f////4Af/4f////4AP/4P////wAP/4P////gAH/4H////AAD/4D///+AAB/4B///4AAAP4AP//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAAAAAAA/8AAAAAAAA/8AAAAAB8A/8AAAAB/8A/8AAAAf/8A/8AAAH//8A/8AAA///8A/8AAH///8A/8AA////8A/8AD////8A/8Af////8A/8B/////8A/8P/////8A/8//////8A////////AA///////AAA//////gAAA/////4AAAA/////AAAAA////4AAAAA////AAAAAA///8AAAAAA///gAAAAAA//+AAAAAAA//wAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gD//gAAA//4P//8AAD//8f///AAH//+////gAH///////wAP///////4AP///////8Af///////8Af///////+Af///////+A////////+A//B//AB/+A/+A/+AA/+A/8Af+AA/+A/+Af+AA/+A//A//AB/+A////////+Af///////+Af///////+Af///////8Af///////8AP///////4AH///////4AH//+////wAD//+////AAA//4P//+AAAP/gH//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAfgAAA///8A/8AAB///+A//AAH////A//gAH////g//wAP////g//wAf////w//4Af////w//4A/////w//8A/////w//8A/////w//8A//gP/wA/8A/8AD/wA/8A/8AD/wAf8A/8AD/gA/8A/+AH/AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////wAH///////gAD//////+AAA//////4AAAP/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DhgeFB4eHh4eHh4eDw=="), 60 + (scale << 8) + (1 << 16)); }; +{ // must be inside our own scope here so that when we are unloaded everything disappears + +const SETTINGSFILE = "antonclk.json"; +const isBangle1 = (process.env.HWVERSION == 1); + // variables defined from settings -var secondsMode; -var secondsColoured; -var secondsWithColon; -var dateOnMain; -var dateOnSecs; -var weekDay; -var calWeek; -var upperCase; -var vectorFont; +let secondsMode; +let secondsColoured; +let secondsWithColon; +let dateOnMain; +let dateOnSecs; +let weekDay; +let calWeek; +let upperCase; +let vectorFont; // dynamic variables -var drawTimeout; -var queueMillis = 1000; -var secondsScreen = true; +let drawTimeout; +let queueMillis = 1000; +let secondsScreen = true; + -var isBangle1 = (process.env.HWVERSION == 1); //For development purposes /* @@ -102,7 +104,7 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2); } -var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) +let calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 dateNoTime = date; dateNoTime.setHours(0,0,0,0); if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; @@ -215,16 +217,21 @@ g.clear(); // Set dynamic state and perform initial drawing updateState(); // Register hooks for LCD on/off event and screen lock on/off event -Bangle.on('lcdPower', on => { - updateState(); -}); -Bangle.on('lock', on => { - updateState(); -}); +Bangle.on('lcdPower', updateState); +Bangle.on('lock', updateState); // Show launcher when middle button pressed -Bangle.setUI("clock"); +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + Bangle.removeListener('lcdPower', updateState); + Bangle.removeListener('lock', updateState); + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + delete Graphics.prototype.setFontAnton; + delete Graphics.prototype.setFontAntonSmall; + }}); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); - -// end of file \ No newline at end of file +} diff --git a/apps/antonclk/metadata.json b/apps/antonclk/metadata.json index 16bdf3aa8..b6134d1a1 100644 --- a/apps/antonclk/metadata.json +++ b/apps/antonclk/metadata.json @@ -1,7 +1,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.09", + "version": "0.10", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/launch/ChangeLog b/apps/launch/ChangeLog index 44866b9f3..36852e0b7 100644 --- a/apps/launch/ChangeLog +++ b/apps/launch/ChangeLog @@ -14,3 +14,4 @@ Add /*LANG*/ tags for internationalisation 0.13: Add fullscreen mode 0.14: Use default Bangle formatter for booleans +0.15: Support for unload and quick return to the clock on 2v16 diff --git a/apps/launch/app.js b/apps/launch/app.js index 556e61bfd..d53f0dcdf 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -1,7 +1,8 @@ -var s = require("Storage"); -var scaleval = 1; -var vectorval = 20; -var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; +{ // must be inside our own scope here so that when we are unloaded everything disappears +let s = require("Storage"); +let scaleval = 1; +let vectorval = 20; +let font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; let settings = Object.assign({ showClocks: true, fullscreen: false @@ -20,7 +21,7 @@ if ("font" in settings){ scaleval = (font.split("x")[1])/20; } } -var apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || !app.type)); +let apps = s.list(/\.info$/).map(app=>{var a=s.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src};}).filter(app=>app && (app.type=="app" || (app.type=="clock" && settings.showClocks) || !app.type)); apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first @@ -69,18 +70,30 @@ E.showScroller({ } }); +function returnToClock() { + // unload everything manually + // ... or we could just call `load();` but it will be slower + Bangle.setUI(); // remove scroller's handling + if (lockTimeout) clearTimeout(lockTimeout); + Bangle.removeListener("lock", lockHandler); + // now load the default clock - just call .bootcde as this has the code already + setTimeout(eval,0,s.read(".bootcde")); +} + // on bangle.js 2, the screen is used for navigating, so the single button goes back // on bangle.js 1, the buttons are used for navigating if (process.env.HWVERSION==2) { - setWatch(_=>load(), BTN1, {edge:"falling"}); + setWatch(returnToClock, BTN1, {edge:"falling"}); } // 10s of inactivity goes back to clock Bangle.setLocked(false); // unlock initially -var lockTimeout; -Bangle.on("lock", locked => { +let lockTimeout; +function lockHandler(locked) { if (lockTimeout) clearTimeout(lockTimeout); lockTimeout = undefined; if (locked) - lockTimeout = setTimeout(_=>load(), 10000); -}); + lockTimeout = setTimeout(returnToClock, 10000); +} +Bangle.on("lock", lockHandler); +} diff --git a/apps/launch/metadata.json b/apps/launch/metadata.json index 19ca74e73..ec070e44e 100644 --- a/apps/launch/metadata.json +++ b/apps/launch/metadata.json @@ -2,7 +2,7 @@ "id": "launch", "name": "Launcher", "shortName": "Launcher", - "version": "0.14", + "version": "0.15", "description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", "readme": "README.md", "icon": "app.png", From b239fa69b5a0a06aad20451892d08d96ee595d39 Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Fri, 23 Sep 2022 20:14:51 +0100 Subject: [PATCH 58/72] Fix for various locale methods Someone may or may not have a locale set up, and also it seems that date_utils aren't available when a locale is set??? --- apps/bigdclock/bigdclock.app.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index b71a6b0a3..75e66397c 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -26,12 +26,19 @@ function draw() { var date = new Date(); var h = date.getHours(), m = date.getMinutes(); - var d = date.getDate(), - w = date.getDay(); // d=1..31; w=0..6 + var d = date.getDate(); var is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; -// var dows = require("date_utils").dows(0,1); - var dows = ["SU","MO","TU","WE","TH","FR","SA"]; - + var dow; + + try { + dow = require("locale").dow(date,1); + } catch (e) { + try { + dow = require("date_utils").dows(0,1)[date.getDay()]; + } catch (e) { + dow = ["SU","MO","TU","WE","TH","FR","SA"][date.getDay()]; + } + } if ((date.getTime() >= lastBattCheck + 15*60000) || Bangle.isCharging()) { lastBattcheck = date.getTime(); width = E.getBattery(); @@ -54,7 +61,7 @@ function draw() { g.drawString(d, g.getWidth() -6, 98); g.setFont('Vector', 52); g.setFontAlign(-1, -1); - g.drawString(dows[w].slice(0,2).toUpperCase(), 6, 103); + g.drawString(dow.slice(0,2).toUpperCase(), 6, 103); g.fillRect(9,159,166,171); g.fillRect(167,163,170,167); From b952599c6e73bcaf986917934094b7bbb1828e9f Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Fri, 23 Sep 2022 20:20:37 +0100 Subject: [PATCH 59/72] Update screenshot.png --- apps/bigdclock/screenshot.png | Bin 3180 -> 3053 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/bigdclock/screenshot.png b/apps/bigdclock/screenshot.png index 8a12b266e71005631235cacc50750f08c59e247d..acac53ea90176de276c693e957cc44a8d0da134f 100644 GIT binary patch delta 3035 zcmV<13ncXH80{C3Fnc;0u7a z@zTl(72tg_?*dzkd)y!uaIe5_dcHu2S>SGk{R8lEk{&y_f`9T1SV27b8Sn=94K6r| zGkEv~um$gj`jfLw08b9=o=}uRF<#6OVsHyF48VJ3wwpa|E#kbCJaP{)a1)ma@2?4r-oV}6 z$er)=^*F60h<`0b?H`~01>!Vf7l6I+dLY*Jp@o#f$AZs*9|QRKy!Q<9$cqZ=Nk?JJ zRN7vFRRR8Uv#M>y&}YL4TL{(!zPpLL+qy)i`_NE~QhddmxGRwMPZG}bMIl4>!J5hg z5FB`nmhJ1$o49O%5o@v=MQYHR8wD!A$PmCnH>5z7H-B-NkI_(JG=Wj23ata*#AV*N zf4D%toe|cMaM%yC*a+(hs{fBCQPb zz)y*KWkM7p1{l%YZlF3}`5xIqM8tfX7(LEwLdNS_NfJUd9%Jtq(h1tKQ`%uxA>eutZ`;g+&bZ#%`(KswWaVBc@lA&&geF0*@}J zW$tmRBI_fXWS-ns%`NqMLDmF5D0XI!#}Lch`AtcXr6NOj)>zl&vw&@)b!F{~c$AYkQS#c2Wd zcn zInln@wV`=SY$2FJ9vgpJSkwqa16D6cF0}3{dOtRSGsPTf8Y4O|07mje;eAr?M*#MS z8Ts~BwSC&tPa$U3yF0+BnAX%mVJI`hX{ch zhQ#VEsMj2%2UL&f4Kf-ZskOJ>T_-Ri04k>EF;s6+JrHMT;?ZVwy@v<*ZB`}(9vCBQ zGi%R^ofS8tUnzjS(_r6lB~d*_WY%rPoINR*Wn|th||!MPp~yY@P7O z&&vV46^HGLFX-R7^Bx z6r?+&klZbKk@){iwPd{+;C{UA{bimg#L=b^^HGzLSl&93+^u<$9NxOG*0PlKat{IIBR9xNH%Rx!Lip-kxI3*g}`Tz|WPuh;kMdu<8S{m2Rk z;E~-^?Jof=2!>Wb01s`SiWk6QU}y#O6k=%mRJ;Hd14AnyfQPnE#S36DFth>!cxd}n zyZ{yhLn|PF2ec3QCCpyGjEdB=;I`08^Bmo6&7}HSMfY2hyZ4|QZxp8+A-Q>*W?D+b9S^e%(#?VV)g2!MTeGS zt^S|560vKV8enT5D1dq2NkC6D0lfPsd<@ZMhL{Zts`uSGc1_by;FYH^8x{fVP=K)q z-qNw2t$#YoFR`>5z!~*u0tdDvCFlf-$N&aNd$}Z|9sxWlz!|Va;YDhRJ`oYX0yxTL z)1*Bf9KD$qz!L(DOuQ&C)=hEbY-p*)4REglbrTm+`p+?=0NeuZrq1*Lul58Y8(#DT zxjX$B;4T5MWhPU|_`KvDY4!Uty>Z)w=0Q4Z^?zX632cenDjZ@?&ox%REO;3c_)M3m zAHxC6f+8vyD?c+%Pk6Hc?)DfhB76iE)RbQJMDp}F2GuFzL9~9fCdMRQasu}>GYSE6 z912Q>e$iUJlh_S#FEKm~BW5%AfS!C=Yf*iA`GxeEQS&kYS27YY`)*AJ2(2}t$Fpl+ z27h4hr3p2p_c}HJz3WGB0?~mp9Kc9pv%b8T0bT(NK7?n!ihg2B9dphCFA6Yv#hh{i zTOuJ-yaKda4Ku-Od9&9Y@o8Fs?}S2xsRHn9@CsmX3tm@IYx$xHd>Eah-q6ho zFA6X^V5Z(eSbIoRq$jo$2*8!=ztRlp3xB&#?|hPNX*vyvs~rYv08%hXFNeFeBG7#!&;S7LR6DEUT8g zewWxnSbJgbS)T!r*JO4LUVz#8w|JftW2p&jLF^TdZJ+@Dqo~)1r6zFYt%Lyf!+(1_ zf!PyA@$MB^8DQ_!-7BeobXerfss^xiwPMNE0O}^@ z6NQ*q0WZ)jVE=jKCV(fVY=PFa2VTJBnOhXVGrPM$ZvuD$lV@&G0MG310=)^~1x%i~ zMFBjsy9@LtfEO@%<`xC;%CG=vl2qe^EJSpWkpX#xWx zAxi`>qSD10Z6O-OBONM$8-x_V4dRgw6~GNb3g8CuNQVmG1|bD-gLtGvom2qlJVqn+ zqA*gxQa}J(3hDFG3JBoR_NX{Z0UE$oB7H6eo>BmMk?~Y<$}0sd1q86AkUlT1fB-IS dkBYMt_zycRM`ir7oW%eD002ovPDHLkV1h6mn_vI{ delta 3163 zcmZ|Qdpy&N{|E5TZdUHO47udGPRHdiyC|9Zb)@5lS!=X+UZNj6KDB8+shv$;UNvRpI~!8k2! z_ho;7&Lp)^B~_PN9`29*JJL`)=d}C_{|Wt)>gsB%t3U2S&MNL6;xmh)OP8!DaRWmG z__mE7E`W#V{MJo4h7Syi%kKcy0aexr4xQCJ`;oTH)k-2C34yL#0VR{Lx09uoulr~) zKI{|MsgJV0BjgoOs~jg+ig}^Q=_NXes|g1kUsK`WqcaSR>s~ZoA6*m+@e&G=;DUES zmz~|;@Df@N^Oxh?B*~|-Na=>;U8Z&dP<$^FQP(K`?{{(b7GbRCx3ib;YVFleZ$eV~ zNM1X%cG4|S7h%sf4#0i>;BRLsxvYvP1nuuDQ0NraX9@lDbB6NMbj!O;jZsVV9 z0kc7Gp@)afWpC@u<6`KnS9ad5QytOs!lt@Bz454f+p&V)pzEzl_4d7H#=0ADIYjBm zqT_!LQ=3koKHraYqZ1QGa+>WXjbbH8KW@}>holxnM5PL0 z6p#3DE90%yG$ShJ;j z^4(2U6m{Uxn%In!q^t)D3mgs#5 z_@mzgME^AB3#jpxLY+a`d!xmyC<>;@^uyOyl^y_{R)v!7j>WmNF?tG<_ID#ted$7@Ct zYGdTUHBbH?=2n0$BDLGMtMPMoVHr;o6Up^VwUQptHX z-0CQdxg>?NlZ5mIMiHoN@vG97Z;UnJ?`1U+U?mAiiezHK7^0t3SUc7`jCLM)^1TOcoJ4+_D=+FKL&#y(5+HBe-A7Zd<2LgbpQ}nzS zC*e0xMvur{9EJ$+k$Dso9VG5y1|#B)FVU{lZ+~x z&FI!hE<#nvw>o92vusfusPdWgy#Ls$Y&8_{z^PCM?S$>8S);zgo80C2MsXSSerPC? z!>~cuJG8`cp=f8HCsT9itMe7*e}P4(kC&O1KeXV`o#?bJHebx;e0tRe&L-^^Wbg0*hJXr=1SRug zC=NFq&(#}^^uL$j3&v;Vxg;42{jtgH?m131VjF`)bJs?EyJKQ~J=JbDSil>dZ(HL! zR*Vy~3+fhZ!|Z>sUe_Kop{WU^2U*WPvPexFR;Q9yRG5+06}MmZRA*R$KgNnaVhU5U z&5Mh#7V}7ZrhW}hAJ$;s*O?_dqd`Kh6cIP#&z6zT+2~;d)h^eLWdNPwuNr)wWC-rc zekt+n$>R3s+9%@KNp2zzK^ZLBk#WBwqDb;;o)}7NK=oJ6LhKB5`)DrjkY=Y`=^jx| z*#nC)E_;z>&QriETOqudCXSFSGNF)x!v@F!m2UfmkK=xdVF)_t*M>xPHJbvJ9fKbW z+BHhIP2cy+K{8FAsPec z%t2EOq&y#dAg|s8FIp`Wv8x(A4vjdnZ8$TY*BIhc7Bp6=?LvRg*3;xBhL5slMy6ZVV@~d5ou|{ERyNSP z1F8a9tN~&^7PZZGw|JUyz7bx9sM-zV@1dWYCT6vUc_l!=WH*I6o{!@|%U4iI!` zs#Ne3J;X-^NR$8HbqwXz@8O>g$$qz`-9!Tq$b9p#0RnC!?x|k^QfVUx=OfE^$wjvG z|LZ|o0$4L;st4O;8df7qSf&C&la?tm9G}u*+QKo0Ab)7PRo_@>c}ineW*WR(l$LWr z5k`{Mpq?3Ll;TBwX`0lIk0J27&z^#g`J79XH+j%BhFTaZ>C%U8GHS6QEi+IgZS_es z|A_9gP(`1dUZLK-8<^2WwK%Mye%wm{*VUpyj+{g#oVfmA;C3ouW2rx{X|l@CVryG; z?Q1Q-LaN~o`$i9@ZNC)>nUz9&U0d-{SAs0@8q$ghRqi8$pxOD>>4rBjOYDOpU;Xjn`JfA9^)Th0N|Hm6#?cfJe6U98Ms6bn`vJp95)Mh`X_ zfUQOGk7hFjIfPI70Wusr5I>A+I+b_xk|w5e(|(7W|ANpXD3i9C zryVaq_8)S$AwaZG;b3H*pTC2JmppNF3)AWlFXaAZGHNB(5hk1e#yRw@((a#EV9vR} zZx@oFJ&y$RSt}GAIEuF3pwhVgLG=#!#w6FZ7U0+oSf1M) zrc9W>?3r*ih?Mbn(*=talNV8C(>+@)Bx{IyMY7|IrG=s>=M|(;_H8? z{WE4X@W-&gpNk}Ln)9X<^*Ov*ZDP#g&bOB@-+E-h4-cfzcI&qvg?d#F$koDhol^Xo z+4+ysyzhH#sh(eV4n!{*Q1ed|nw-^^tfL(*3YL9#Jmt^D28xfGQ8Iu$)U8|SXw>l- z)1M9U?obldMI}}XZm(!-tEnROUEaAzGL?6#>8FFAe+2IaOQJYEy3t5oSM3}ko_lW6 zwvt);?Nzj7tE92%f7v)J4*yA=p1~V+BdVRR>p%6W52zk@8_W_w7Z@LPbg}G(jGRxs z`y8zq(G9hv6wq_U18$>7SLN{?tb)$GB^r)tNSDbiaoFr!~D=W0F@rQwmifLaKok z$Nq!@HRb3w&l`gXA6sS9GqzqCwlB9F020%Fd|-g~HCo|RR1_8T;)JIrT z0CrFbSIA3ma2y2s)Eq1E7q!DW01gdV+;(aK5Rm7JQ~+(M6u5kg>oO0lXS0CfI-*3w zfo~l)0r1nn?-)v~EhRJ5t1M!LT@K#WyC;o6>2dbTGpWoSP5~!Tck&1p`1f;j7}G?V z`o8i)so8;Yq^7Du{{!3%G%rZciNcWrO*2x{qM11xMF$~i`vijYUh3#H From bb823639d59c08cda1c7d1a590807824f894d430 Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Fri, 23 Sep 2022 20:22:22 +0100 Subject: [PATCH 60/72] Update ChangeLog --- apps/bigdclock/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index 60a8f703f..a5441d6d1 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -3,4 +3,4 @@ 0.03: Internationalisation; bug fix - battery icon responds promptly to charging state 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() -0.06: Better battery graphic - now has green, yellow and red sections +0.06: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale From 181157eedf1f2d50b86f203885694651fea9f232 Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Fri, 23 Sep 2022 20:36:32 +0100 Subject: [PATCH 61/72] Incorporate @thyttan commit Incorporate https://github.com/espruino/BangleApps/commit/5b1b3553c5a028c595845434762147b28de317a6 --- apps/bigdclock/ChangeLog | 3 ++- apps/bigdclock/bigdclock.app.js | 3 ++- apps/bigdclock/metadata.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index a5441d6d1..e9791dab8 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -3,4 +3,5 @@ 0.03: Internationalisation; bug fix - battery icon responds promptly to charging state 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() -0.06: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale +0.06: Tell clock widgets to hide. +0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index 75e66397c..2f8b7cd4d 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -110,7 +110,8 @@ Bangle.on('charging', (charging) => { draw(); }); +Bangle.setUI("clock"); + Bangle.loadWidgets(); draw(); -Bangle.setUI("clock"); diff --git a/apps/bigdclock/metadata.json b/apps/bigdclock/metadata.json index ce91d921e..30352ca1a 100644 --- a/apps/bigdclock/metadata.json +++ b/apps/bigdclock/metadata.json @@ -1,7 +1,7 @@ { "id": "bigdclock", "name": "Big digit clock containing just the essentials", "shortName":"Big digit clk", - "version":"0.06", + "version":"0.07", "description": "A clock containing just the essentials, made as easy to read as possible for those of us that need glasses. It contains the time, the day-of-week, the day-of-month, and the current battery state-of-charge.", "icon": "bigdclock.png", "type": "clock", From d3a5f4cdb21ec914973afc56acc90832ce46ef47 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 14:24:49 +0200 Subject: [PATCH 62/72] messages: minor library refactor --- apps/messages/lib.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/messages/lib.js b/apps/messages/lib.js index d8599c93d..50e14a07b 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -12,11 +12,7 @@ function openMusic() { {t:"modify",id:int, title:string} // modified */ exports.pushMessage = function(event) { - var messages, inApp = "undefined"!=typeof MESSAGES; - if (inApp) - messages = MESSAGES; // we're in an app that has already loaded messages - else // no app - load messages - messages = require("Storage").readJSON("messages.json",1)||[]; + var messages = exports.getMessages(); // now modify/delete as appropriate var mIdx = messages.findIndex(m=>m.id==event.id); if (event.t=="remove") { @@ -39,7 +35,7 @@ exports.pushMessage = function(event) { } require("Storage").writeJSON("messages.json",messages); // if in app, process immediately - if (inApp) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]); + if ("undefined"!= typeof MESSAGES) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]); // update the widget icons shown if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages,true); // if no new messages now, make sure we don't load the messages app From fb10f8125e847a7cc15ba5737b8296fd05885f6d Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 14:48:59 +0200 Subject: [PATCH 63/72] messages: emit "message" events --- apps/messages/ChangeLog | 3 ++- apps/messages/README.md | 13 +++++++++++++ apps/messages/lib.js | 11 +++++++++-- apps/messages/metadata.json | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 262cba1fa..0b3cb276d 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -66,4 +66,5 @@ 0.50: Add `getMessages` and `status` functions to library Option to disable auto-open of messages Option to make message icons monochrome (not colored) - messages widget buzz now returns a promise \ No newline at end of file + messages widget buzz now returns a promise +0.51: Emit "message events" \ No newline at end of file diff --git a/apps/messages/README.md b/apps/messages/README.md index 2e583d1c2..0ef783188 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -56,6 +56,19 @@ _2. What the notify icon looks like (it's touchable on Bangle.js2!)_ ![](screenshot-notify.gif) +## Events (for app/widget developers) + +When a new message arrives, a `"message"` event is emitted, you can listen for +it like this: + +```js +myMessageListener = Bangle.on("message", (type, message)=>{ + // is one of "text", "call", "alarm", "map", or "music" + // see `messages/lib.js` for possible formats + E.showMessage(`${message.title}\n${message.body}`, `${message.t} ${type} message`); +}); +``` + ## Requests diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 50e14a07b..3e8ff64dd 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -8,7 +8,7 @@ function openMusic() { /* Push a new message onto messages queue, event is: {t:"add",id:int, src,title,subject,body,sender,tel, important:bool, new:bool} {t:"add",id:int, id:"music", state, artist, track, etc} // add new - {t:"remove-",id:int} // remove + {t:"remove",id:int} // remove {t:"modify",id:int, title:string} // modified */ exports.pushMessage = function(event) { @@ -31,11 +31,18 @@ exports.pushMessage = function(event) { else Object.assign(messages[mIdx], event); if (event.id=="music" && messages[mIdx].state=="play") { messages[mIdx].new = true; // new track, or playback (re)started + type = 'music'; } } require("Storage").writeJSON("messages.json",messages); + var message = mIdx<0 ? {id:event.id, t:'remove'} : messages[mIdx]; // if in app, process immediately - if ("undefined"!= typeof MESSAGES) return onMessagesModified(mIdx<0 ? {id:event.id} : messages[mIdx]); + if ("undefined"!=typeof MESSAGES) return onMessagesModified(message); + // emit message event + var type = 'text'; + if (["call", "music", "map"].includes(message.id)) type = message.id; + if (message.src && message.src.toLowerCase().startsWith("alarm")) type = "alarm"; + Bangle.emit("message", type, message); // update the widget icons shown if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages,true); // if no new messages now, make sure we don't load the messages app diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index da2e0945a..057a95026 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.50", + "version": "0.51", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From 3994869df132d09198390522b575121f4bab9a79 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 15:50:20 +0200 Subject: [PATCH 64/72] messages: setting to hide widget In case users want to use a custom widget --- apps/messages/ChangeLog | 3 ++- apps/messages/README.md | 2 +- apps/messages/settings.js | 3 ++- apps/messages/widget.js | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 0b3cb276d..06704d22f 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -67,4 +67,5 @@ Option to disable auto-open of messages Option to make message icons monochrome (not colored) messages widget buzz now returns a promise -0.51: Emit "message events" \ No newline at end of file +0.51: Emit "message events" + Setting to hide widget \ No newline at end of file diff --git a/apps/messages/README.md b/apps/messages/README.md index 0ef783188..1ae53e63c 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -25,7 +25,7 @@ it starts getting clipped. * `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? * `Flash Icon` - Toggle flashing of the widget icon. -* `Widget messages` - The maximum amount of message icons to show on the widget. +* `Widget messages` - The maximum amount of message icons to show on the widget, or `Hide` the widget completely. ## New Messages diff --git a/apps/messages/settings.js b/apps/messages/settings.js index 0edb17797..09c9db455 100644 --- a/apps/messages/settings.js +++ b/apps/messages/settings.js @@ -73,7 +73,8 @@ }, /*LANG*/'Widget messages': { value:0|settings().maxMessages, - min: 1, max: 5, + min: 0, max: 5, + format: v => v ? v :/*LANG*/"Hide", onchange: v => updateSetting("maxMessages", v) }, /*LANG*/'Icon color mode': { diff --git a/apps/messages/widget.js b/apps/messages/widget.js index a5e1f8b6c..f871918d3 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,4 +1,5 @@ (() => { +if ((require('Storage').readJSON("messages.settings.json", true) || {}).maxMessages===0) return; function filterMessages(msgs) { return msgs.filter(msg => msg.new && msg.id != "music") From dc6839a67b927e407fc37be4b6481af8ba087849 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 16:17:21 +0200 Subject: [PATCH 65/72] messages: allow event handlers to prevent default app from loading --- apps/messages/ChangeLog | 3 +- apps/messages/README.md | 3 ++ apps/messages/lib.js | 81 ++++++++++++++++++++++------------------- 3 files changed, 48 insertions(+), 39 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 06704d22f..4a81c3237 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -68,4 +68,5 @@ Option to make message icons monochrome (not colored) messages widget buzz now returns a promise 0.51: Emit "message events" - Setting to hide widget \ No newline at end of file + Setting to hide widget + Add custom event handlers to prevent default app form loading \ No newline at end of file diff --git a/apps/messages/README.md b/apps/messages/README.md index 1ae53e63c..0ccef2998 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -63,9 +63,12 @@ it like this: ```js myMessageListener = Bangle.on("message", (type, message)=>{ + if (message.handled) return; // another app already handled this message // is one of "text", "call", "alarm", "map", or "music" // see `messages/lib.js` for possible formats E.showMessage(`${message.title}\n${message.body}`, `${message.t} ${type} message`); + // You can prevent the default `message` app from loading by setting `message.handled = true`: + message.handled = true; }); ``` diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 3e8ff64dd..b842e7459 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -45,46 +45,51 @@ exports.pushMessage = function(event) { Bangle.emit("message", type, message); // update the widget icons shown if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages,true); + var handleMessage = () => { // if no new messages now, make sure we don't load the messages app - if (event.t=="remove" && exports.messageTimeout && !messages.some(m=>m.new)) { - clearTimeout(exports.messageTimeout); - delete exports.messageTimeout; - } - // ok, saved now - if (event.id=="music" && Bangle.CLOCK && messages[mIdx].new && openMusic()) { - // just load the app to display music: no buzzing - load("messages.app.js"); - } else if (event.t!="add") { - // we only care if it's new - return; - } else if(event.new == false) { - return; - } - // otherwise load messages/show widget - var loadMessages = Bangle.CLOCK || event.important; - var quiet = (require('Storage').readJSON('setting.json',1)||{}).quiet; - var appSettings = require('Storage').readJSON('messages.settings.json',1)||{}; - var unlockWatch = appSettings.unlockWatch; - // don't auto-open messages in quiet mode if quietNoAutOpn is true - if((quiet && appSettings.quietNoAutOpn) || appSettings.noAutOpn) - loadMessages = false; - delete appSettings; - // after a delay load the app, to ensure we have all the messages - if (exports.messageTimeout) clearTimeout(exports.messageTimeout); - exports.messageTimeout = setTimeout(function() { - exports.messageTimeout = undefined; - // if we're in a clock or it's important, go straight to messages app - if (loadMessages){ - if(!quiet && unlockWatch){ - Bangle.setLocked(false); - Bangle.setLCDPower(1); // turn screen on - } - // we will buzz when we enter the messages app - return load("messages.new.js"); + if (event.t=="remove" && exports.messageTimeout && !messages.some(m => m.new)) { + clearTimeout(exports.messageTimeout); + delete exports.messageTimeout; } - if (!quiet && (!global.WIDGETS || !WIDGETS.messages)) return Bangle.buzz(); // no widgets - just buzz once to let someone know - if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages); - }, 500); + // ok, saved now + if (event.id=="music" && Bangle.CLOCK && messages[mIdx].new && openMusic()) { + // just load the app to display music: no buzzing + load("messages.app.js"); + } else if (event.t!="add") { + // we only care if it's new + return; + } else if (event.new==false) { + return; + } + // otherwise load messages/show widget + var loadMessages = Bangle.CLOCK || event.important; + var quiet = (require('Storage').readJSON('setting.json', 1) || {}).quiet; + var appSettings = require('Storage').readJSON('messages.settings.json', 1) || {}; + var unlockWatch = appSettings.unlockWatch; + // don't auto-open messages in quiet mode if quietNoAutOpn is true + if ((quiet && appSettings.quietNoAutOpn) || appSettings.noAutOpn) + loadMessages = false; + delete appSettings; + // after a delay load the app, to ensure we have all the messages + if (exports.messageTimeout) clearTimeout(exports.messageTimeout); + exports.messageTimeout = setTimeout(function() { + exports.messageTimeout = undefined; + // if we're in a clock or it's important, go straight to messages app + if (loadMessages) { + if (!quiet && unlockWatch) { + Bangle.setLocked(false); + Bangle.setLCDPower(1); // turn screen on + } + // we will buzz when we enter the messages app + return load("messages.new.js"); + } + if (!quiet && (!global.WIDGETS || !WIDGETS.messages)) return Bangle.buzz(); // no widgets - just buzz once to let someone know + if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages); + }, 500); + }; + setTimeout(()=>{ + if (!message.handled) handleMessage(); + },0); } /// Remove all messages exports.clearAll = function(event) { From 29fc8f4d1a5fde9938f633dd06d6516217d1043b Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 16:46:59 +0200 Subject: [PATCH 66/72] messages: move buzz from widget to library --- apps/messages/ChangeLog | 3 ++- apps/messages/app.js | 7 +++---- apps/messages/lib.js | 41 ++++++++++++++++++++++++++++++++++++++++- apps/messages/widget.js | 37 +++++-------------------------------- 4 files changed, 50 insertions(+), 38 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 4a81c3237..da3b3ab5c 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -69,4 +69,5 @@ messages widget buzz now returns a promise 0.51: Emit "message events" Setting to hide widget - Add custom event handlers to prevent default app form loading \ No newline at end of file + Add custom event handlers to prevent default app form loading + Move WIDGETS.messages.buzz() to require("messages").buzz() \ No newline at end of file diff --git a/apps/messages/app.js b/apps/messages/app.js index 40dff9635..20fa8aaa3 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -54,8 +54,7 @@ var onMessagesModified = function(msg) { // TODO: if new, show this new one if (msg && msg.id!=="music" && msg.new && active!="map" && !((require('Storage').readJSON('setting.json', 1) || {}).quiet)) { - if (WIDGETS["messages"]) WIDGETS["messages"].buzz(msg.src); - else Bangle.buzz(); + require("messages").buzz(msg.src); } if (msg && msg.id=="music") { if (msg.state && msg.state!="play") openMusic = false; // no longer playing music to go back to @@ -356,13 +355,13 @@ function checkMessages(options) { // If we have a new message, show it if (options.showMsgIfUnread && newMessages.length) { showMessage(newMessages[0].id); - // buzz after showMessage, so beingbusy during layout doesn't affect the buzz pattern + // buzz after showMessage, so being busy during layout doesn't affect the buzz pattern if (global.BUZZ_ON_NEW_MESSAGE) { // this is set if we entered the messages app by loading `messages.new.js` // ... but only buzz the first time we view a new message global.BUZZ_ON_NEW_MESSAGE = false; // messages.buzz respects quiet mode - no need to check here - WIDGETS.messages.buzz(newMessages[0].src); + require("messages").buzz(newMessages[0].src); } return; } diff --git a/apps/messages/lib.js b/apps/messages/lib.js index b842e7459..42d6c8586 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -83,8 +83,8 @@ exports.pushMessage = function(event) { // we will buzz when we enter the messages app return load("messages.new.js"); } - if (!quiet && (!global.WIDGETS || !WIDGETS.messages)) return Bangle.buzz(); // no widgets - just buzz once to let someone know if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.update(messages); + exports.buzz(message.src); }, 500); }; setTimeout(()=>{ @@ -134,6 +134,45 @@ exports.getMessages = function() { } }; +/** + * Start buzzing for new message + * @param {string} msgSrc Message src to buzz for + * @return {Promise} Resolves when initial buzz finishes (there might be repeat buzzes later) + */ +exports.buzz = function(msgSrc) { + exports.stopBuzz(); // cancel any previous buzz timeouts + if ((require('Storage').readJSON('setting.json',1)||{}).quiet) return Promise.resolve(); // never buzz during Quiet Mode + + var pattern; + if (msgSrc && msgSrc.toLowerCase() === "phone") { + // special vibration pattern for incoming calls + pattern = (require('Storage').readJSON("messages.settings.json", true) || {}).vibrateCalls; + } else { + pattern = (require('Storage').readJSON("messages.settings.json", true) || {}).vibrate; + } + if (pattern === undefined) { pattern = ":"; } // pattern may be "", so we can't use || ":" here + if (!pattern) return Promise.resolve(); + + var repeat = (require('Storage').readJSON("messages.settings.json", true) || {}).repeat; + if (repeat===undefined) repeat=4; // repeat may be zero + if (repeat) { + exports.buzzTimeout = setTimeout(()=>require("buzz").pattern(pattern), repeat*1000); + var vibrateTimeout = (require('Storage').readJSON("messages.settings.json", true) || {}).vibrateTimeout; + if (vibrateTimeout===undefined) vibrateTimeout=60; + if (vibrateTimeout && !exports.stopTimeout) exports.stopTimeout = setTimeout(exports.stopTimeout, vibrateTimeout*1000); + } + return require("buzz").pattern(pattern); +}; +/** + * Stop buzzing + */ +exports.stopBuzz = function() { + if (exports.buzzTimeout) clearTimeout(exports.buzzTimeout); + delete exports.buzzTimeout; + if (exports.stopTimeout) clearTimeout(exports.stopTimeout); + delete exports.stopTimeout; +}; + exports.getMessageImage = function(msg) { /* * icons should be 24x24px or less with 1bpp colors and 'Transparency to Color' diff --git a/apps/messages/widget.js b/apps/messages/widget.js index f871918d3..c8d132f82 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -15,15 +15,14 @@ WIDGETS["messages"]={area:"tl", width:0, draw:function(recall) { } Bangle.removeListener('touch', this.touch); if (!this.width) return; - var c = (Date.now()-this.t)/1000; - let settings = Object.assign({flash:true, maxMessages:3, repeat:4, vibrateTimeout:60},require('Storage').readJSON("messages.settings.json", true) || {}); + let settings = Object.assign({flash:true, maxMessages:3},require('Storage').readJSON("messages.settings.json", true) || {}); if (recall !== true || settings.flash) { var msgsShown = E.clip(this.msgs.length, 0, settings.maxMessages); g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+23); for(let i = 0;i < msgsShown;i++) { const msg = this.msgs[i]; const colors = [g.theme.bg, g.setColor(require("messages").getMessageImageCol(msg)).getColor()]; - if (settings.flash && (c&1)) { + if (settings.flash && ((Date.now()/1000)&1)) { if (colors[1] == g.theme.fg) { colors.reverse(); } else { @@ -36,38 +35,13 @@ WIDGETS["messages"]={area:"tl", width:0, draw:function(recall) { this.x + 12 + i * 24, this.y + 12, {rotate:0/*force centering*/}); } } - if (csettings.repeat*1000) { // the period between vibrations - this.l = Date.now(); - WIDGETS["messages"].buzz(); // buzz every 4 seconds - } WIDGETS["messages"].i=setTimeout(()=>WIDGETS["messages"].draw(true), 1000); if (process.env.HWVERSION>1) Bangle.on('touch', this.touch); -},update:function(rawMsgs, quiet) { +},update:function(rawMsgs) { const settings = Object.assign({maxMessages:3},require('Storage').readJSON("messages.settings.json", true) || {}); this.msgs = filterMessages(rawMsgs); - if (this.msgs.length === 0) { - delete this.t; - delete this.l; - } else { - this.t=Date.now(); // first time - this.l=Date.now()-10000; // last buzz - if (quiet) this.t -= 500000; // if quiet, set last time in the past so there is no buzzing - } this.width = 24 * E.clip(this.msgs.length, 0, settings.maxMessages); Bangle.drawWidgets(); -},buzz:function(msgSrc) { // return a promise - if ((require('Storage').readJSON('setting.json',1)||{}).quiet) return Promise.resolve(); // never buzz during Quiet Mode - var pattern; - if (msgSrc != undefined && msgSrc.toLowerCase() == "phone") { - // special vibration pattern for incoming calls - pattern = (require('Storage').readJSON("messages.settings.json", true) || {}).vibrateCalls; - } else { - pattern = (require('Storage').readJSON("messages.settings.json", true) || {}).vibrate; - } - if (pattern === undefined) { pattern = ":"; } // pattern may be "", so we can't use || ":" here - return require("buzz").pattern(pattern); },touch:function(b,c) { var w=WIDGETS["messages"]; if (!w||!w.width||c.xw.x+w.width||c.yw.y+24) return; @@ -75,8 +49,7 @@ WIDGETS["messages"]={area:"tl", width:0, draw:function(recall) { }}; /* We might have returned here if we were in the Messages app for a -message but then the watch was never viewed. In that case we don't -want to buzz but should still show that there are unread messages. */ +message but then the watch was never viewed. */ if (global.MESSAGES===undefined) - WIDGETS["messages"].update(require("messages").getMessages(), true); + WIDGETS["messages"].update(require("messages").getMessages()); })(); From 6f27a65143c70dd522e0ad84e97c379d650ba5a9 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 24 Sep 2022 17:08:58 +0200 Subject: [PATCH 67/72] messages: also emit "clearAll" message events --- apps/messages/README.md | 6 ++++-- apps/messages/lib.js | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/messages/README.md b/apps/messages/README.md index 0ccef2998..72a989146 100644 --- a/apps/messages/README.md +++ b/apps/messages/README.md @@ -64,8 +64,10 @@ it like this: ```js myMessageListener = Bangle.on("message", (type, message)=>{ if (message.handled) return; // another app already handled this message - // is one of "text", "call", "alarm", "map", or "music" - // see `messages/lib.js` for possible formats + // is one of "text", "call", "alarm", "map", "music", or "clearAll" + if (type === "clearAll") return; // not a message + // see `messages/lib.js` for possible formats + // message.t could be "add", "modify" or "remove" E.showMessage(`${message.title}\n${message.body}`, `${message.t} ${type} message`); // You can prevent the default `message` app from loading by setting `message.handled = true`: message.handled = true; diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 42d6c8586..ed71ec04b 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -92,20 +92,20 @@ exports.pushMessage = function(event) { },0); } /// Remove all messages -exports.clearAll = function(event) { - var messages, inApp = "undefined"!=typeof MESSAGES; - if (inApp) { +exports.clearAll = function() { + if ("undefined"!= typeof MESSAGES) { // we're in a messages app, clear that as well MESSAGES = []; - messages = MESSAGES; // we're in an app that has already loaded messages - } else // no app - empty messages - messages = []; - // Save all messages - require("Storage").writeJSON("messages.json",messages); - // update app if in app - if (inApp) return onMessagesModified(); + } + // Clear all messages + require("Storage").writeJSON("messages.json", []); // if we have a widget, update it if (global.WIDGETS && WIDGETS.messages) - WIDGETS.messages.update(messages); + WIDGETS.messages.update([]); + // let message listeners know + Bangle.emit("message", "clearAll", {}); // guarantee listeners an object as `message` + // clearAll cannot be marked as "handled" + // update app if in app + if ("function"== typeof onMessagesModified) onMessagesModified(); } /** From b114677e5e0c4e7fd9155d0d3680f13759386158 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Sat, 24 Sep 2022 17:08:57 -0400 Subject: [PATCH 68/72] Add Power Save --- apps/powersave/README.md | 27 +++++++++++++++++++++++++++ apps/powersave/boot.js | 15 +++++++++++++++ apps/powersave/metadata.json | 15 +++++++++++++++ apps/powersave/screen.js | 7 +++++++ 4 files changed, 64 insertions(+) create mode 100644 apps/powersave/README.md create mode 100644 apps/powersave/boot.js create mode 100644 apps/powersave/metadata.json create mode 100644 apps/powersave/screen.js diff --git a/apps/powersave/README.md b/apps/powersave/README.md new file mode 100644 index 000000000..5be5e32b5 --- /dev/null +++ b/apps/powersave/README.md @@ -0,0 +1,27 @@ +# Power Saver + +Save your watch's battery power by halting foreground app execution while the screen is off. + +## Features +- Stops foreground app processes +- Background processes still run +- Clears screen +- Decreases accelerometer polls +- Foreground app is returned to when screen is turned back on (app state is not preserved) + +## Controls +- Automatically activates when screen times out, timing can be adjusted using normal timeout settings +- Deactivates when screen is turned back on + +## Warnings +- Due to an Espruino bug, this does not take affect immediately when installed. Switch apps for these features to take affect. +- This is not compatible with apps that need to run in the foreground even while the screen is off, such as most stopwatch apps and some health trackers. +- If you check your watch super often (like multiple times per minute), this may end of costing you more power than it saves since the app you are using will have to restart everytime you check it. + +## Requests + +[Contact information is on my website](https://kyleplo.com/#contact) + +## Creator + +[kyleplo](https://kyleplo.com) \ No newline at end of file diff --git a/apps/powersave/boot.js b/apps/powersave/boot.js new file mode 100644 index 000000000..d170e9d59 --- /dev/null +++ b/apps/powersave/boot.js @@ -0,0 +1,15 @@ +var Storage = Storage || require("Storage"); +Bangle.on("lock", locked => { + if(locked){ + g.clear().reset(); + Bangle.setLCDBrightness(0); + Bangle.setPollInterval(1000); + load("powersave.screen.js"); + }else{ + load(Storage.read("resumeaftersleep") || JSON.parse(Storage.read("setting.json")).clock); + } +}); +E.on("init", () => { + if(__FILE__ && __FILE__ !== "powersave.screen.js") + Storage.write("resumeaftersleep", __FILE__); +}); \ No newline at end of file diff --git a/apps/powersave/metadata.json b/apps/powersave/metadata.json new file mode 100644 index 000000000..50603b2c2 --- /dev/null +++ b/apps/powersave/metadata.json @@ -0,0 +1,15 @@ +{ + "id": "powersave", + "name": "Power Save", + "version": "0.01", + "description": "Halts foreground app execution while screen is off while still allowing background processes.", + "readme": "README.md", + "icon": "powersave.png", + "type": "bootloader", + "tags": "tool", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"powersave.boot.js","url":"boot.js"}, + {"name":"powersave.screen.js","url":"boot.js"} + ] +} \ No newline at end of file diff --git a/apps/powersave/screen.js b/apps/powersave/screen.js new file mode 100644 index 000000000..f987f0bbb --- /dev/null +++ b/apps/powersave/screen.js @@ -0,0 +1,7 @@ +var Storage = Storage || require("Storage"); +g.clear(); +Bangle.setLCDBrightness(0); +Bangle.setPollInterval(1000); +if(!Bangle.isLocked()){ + load(Storage.read("resumeaftersleep") || JSON.parse(Storage.read("setting.json")).clock); +} \ No newline at end of file From a65e1d7bcc9b40c6b37d635e97d5d29244df3d01 Mon Sep 17 00:00:00 2001 From: kyleplo <31634240+kyleplo@users.noreply.github.com> Date: Sat, 24 Sep 2022 17:14:00 -0400 Subject: [PATCH 69/72] Whoops - Add icon --- apps/powersave/powersave.png | Bin 0 -> 1429 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/powersave/powersave.png diff --git a/apps/powersave/powersave.png b/apps/powersave/powersave.png new file mode 100644 index 0000000000000000000000000000000000000000..fa0399b7304b895a18550bc00f5e8ff47ebe2051 GIT binary patch literal 1429 zcmV;G1#0?S(!3U%9 z3K302Vzl95ySrsOGu;*yN_S=oEuj}{E$wXS&P-`JerMY*)Bl`l_srC!CjOIuww*oS zcYbGP&YbVe*3|s3aVaLdLNV-jQ!VUr{BF*x!E_!_4X0Bz-8b>OIjxo!HeWHEodnNR z-Ra49vrDnfoR!vAx>hrsrZPOY>AZq%=BzYhBu4OE6?nt3vnSY9*ltcr)9rNxT=c+` z?QgMNSXsGMi&)FD`FMO*q_o*<33zxayu%s|=N@buB$iKJSgc=hiYh{zq4`vb{ z6f=qMtxTesJV0hvI<^$!BCD}bT1~L05uQ(8#@Kn-9#zaHekf*=C(D2{_|$>ql^7pM zYQesNVEcUV61NYX>CX@}z%Ir{5?`PQ^oSpP+%zY)VvI<11@0HX`aGCUbYg5Isk-|m zLVKNSb8f;IkyvWY#RNEnz&@vwhcGs@6y1Fsfx$x3oQwfi|687+;MDGzZ`##dLBrpX7X=VEd}|9b*>| zSho)}z>491jyXhPxmA}?-Sg65Hu)*RHj!;S^L(AaIB88(nm*7V)77fS96=(;4utl) zKec=b#z;%i?Hvd?gL^SYkgRlkCqjEYa4;6b7-`YMr3oOXb*_ai!aO1k)Fsy zT8A-Gnz;XM1f0p5>2APWBGElQ&&tI65xg>hbmB3Lky74tZbZ0hO!d-Nm@7zBsC|Lp z6{iy~V0$UaPT+HP|K?W@^NBfMa_f<&PE1n}Iuv8|LQ-mW27)mC)pKFldnF&lqc0MC5@+e&F- z)9wSS)>N7P!Qa$jUKD@hK(J>g!OL$Xvhj^WsTH?jTPZ1KX$eAw@OzkdQUtq;Jc?(Y zs?P_pZDu-Rg7YD{!j*uC7!&i@p~QQlmK%rw#`YAgcA>_m&6H+wdg+e^}L> zU+D8iwbi*986t~zT+1l=351B^e4&@NkSke_veoyUI{xz&-M;oW<+;e$CbD9BAvPIh=rMz_zy)oxWoiP!%8jRbZ0lPdc0 zuL>VITsQf5uV&c06~o@b%NgwJUl$(?U!>@gzsg@X5>STRP9F3CpXJ90Ql-!R Date: Sun, 25 Sep 2022 14:36:53 -0700 Subject: [PATCH 70/72] dont buzz on sunday --- apps/twenties/boot.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/twenties/boot.js b/apps/twenties/boot.js index 180f4cbb7..722af43bc 100644 --- a/apps/twenties/boot.js +++ b/apps/twenties/boot.js @@ -2,12 +2,13 @@ const move = 20 * 60 * 1000; // 20 minutes const look = 20 * 1000; // 20 seconds - buzz = _ => { + const buzz = _ => { const date = new Date(); const day = date.getDay(); const hour = date.getHours(); // buzz at work - if (day <= 5 && hour >= 8 && hour <= 17) { + if (day >= 1 && day <= 5 && + hour >= 8 && hour <= 17) { Bangle.buzz().then(_ => { setTimeout(Bangle.buzz, look); }); @@ -15,4 +16,4 @@ }; setInterval(buzz, move); // buzz to stand / sit -})(); \ No newline at end of file +})(); From a90b58bc0d67e0b6729d037cde07ee21f175bf31 Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Mon, 26 Sep 2022 16:01:23 +0100 Subject: [PATCH 71/72] Implementing locale fix --- apps/bigdclock/ChangeLog | 2 +- apps/bigdclock/bigdclock.app.js | 13 ++----------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index e9791dab8..98b232467 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -4,4 +4,4 @@ 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() 0.06: Tell clock widgets to hide. -0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale +0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale; current battery state checked only once every 15 minutes, leading to longer-lasting battery charge diff --git a/apps/bigdclock/bigdclock.app.js b/apps/bigdclock/bigdclock.app.js index 2f8b7cd4d..a8e2b38df 100644 --- a/apps/bigdclock/bigdclock.app.js +++ b/apps/bigdclock/bigdclock.app.js @@ -28,17 +28,8 @@ function draw() { m = date.getMinutes(); var d = date.getDate(); var is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; - var dow; - - try { - dow = require("locale").dow(date,1); - } catch (e) { - try { - dow = require("date_utils").dows(0,1)[date.getDay()]; - } catch (e) { - dow = ["SU","MO","TU","WE","TH","FR","SA"][date.getDay()]; - } - } + var dow = require("date_utils").dows(0,1)[date.getDay()]; + if ((date.getTime() >= lastBattCheck + 15*60000) || Bangle.isCharging()) { lastBattcheck = date.getTime(); width = E.getBattery(); From 43c522565e0bf1cf7cac1985714a92a7268abbce Mon Sep 17 00:00:00 2001 From: deirdreobyrne Date: Mon, 26 Sep 2022 16:18:46 +0100 Subject: [PATCH 72/72] Update ChangeLog Removing unnecessary note about locale! --- apps/bigdclock/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bigdclock/ChangeLog b/apps/bigdclock/ChangeLog index 98b232467..c92d139bb 100644 --- a/apps/bigdclock/ChangeLog +++ b/apps/bigdclock/ChangeLog @@ -4,4 +4,4 @@ 0.04: bug fix 0.05: proper fix for the race condition in queueDraw() 0.06: Tell clock widgets to hide. -0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; better handling of locale; current battery state checked only once every 15 minutes, leading to longer-lasting battery charge +0.07: Better battery graphic - now has green, yellow and red sections; battery status reflected in the bar across the middle of the screen; current battery state checked only once every 15 minutes, leading to longer-lasting battery charge