diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index bb8a292a0..398396c96 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -38,3 +38,6 @@ 0.35: Add automatic translation of more strings 0.36: alarm widget moved out of app 0.37: add message input and dated Events +0.38: Display date in locale + When switching 'repeat' from 'Workdays', 'Weekends' to 'Custom' preset Custom menu with previous selection + Display alarm label in delete prompt diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 74007d04b..e97b61917 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -40,6 +40,14 @@ function handleFirstDayOfWeek(dow) { // Check the first day of week and update the dow field accordingly (alarms only!) alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow)); +function getLabel(e) { + const dateStr = e.date && require("locale").date(new Date(e.date), 1); + return (e.timer + ? require("time_utils").formatDuration(e.timer) + : (dateStr ? `${dateStr} ${require("time_utils").formatTime(e.t)}` : require("time_utils").formatTime(e.t) + (e.rp ? ` ${decodeDOW(e)}` : "")) + ) + (e.msg ? " " + e.msg : ""); +} + function showMainMenu() { const menu = { "": { "title": /*LANG*/"Alarms & Timers" }, @@ -48,11 +56,7 @@ function showMainMenu() { }; alarms.forEach((e, index) => { - var label = (e.timer - ? require("time_utils").formatDuration(e.timer) - : (e.date ? `${e.date.substring(5,10)} ${require("time_utils").formatTime(e.t)}` : require("time_utils").formatTime(e.t) + (e.rp ? ` ${decodeDOW(e)}` : "")) - ) + (e.msg ? " " + e.msg : ""); - menu[label] = { + menu[getLabel(e)] = { value: e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff), onchange: () => setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index) }; @@ -184,7 +188,7 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { if (!isNew) { menu[/*LANG*/"Delete"] = () => { - E.showPrompt(/*LANG*/"Are you sure?", { title: /*LANG*/"Delete Alarm" }).then((confirm) => { + E.showPrompt(getLabel(alarm) + "\n" + /*LANG*/"Are you sure?", { title: /*LANG*/"Delete Alarm" }).then((confirm) => { if (confirm) { alarms.splice(alarmIndex, 1); saveAndReload(); @@ -264,7 +268,7 @@ function showEditRepeatMenu(repeat, dow, dowChangeCallback) { }, /*LANG*/"Custom": { value: isCustom ? decodeDOW({ rp: true, dow: dow }) : false, - onchange: () => setTimeout(showCustomDaysMenu, 10, isCustom ? dow : EVERY_DAY, dowChangeCallback, originalRepeat, originalDow) + onchange: () => setTimeout(showCustomDaysMenu, 10, dow, dowChangeCallback, originalRepeat, originalDow) } }; @@ -372,7 +376,7 @@ function showEditTimerMenu(selectedTimer, timerIndex) { if (!keyboard) delete menu[/*LANG*/"Message"]; if (!isNew) { menu[/*LANG*/"Delete"] = () => { - E.showPrompt(/*LANG*/"Are you sure?", { title: /*LANG*/"Delete Timer" }).then((confirm) => { + E.showPrompt(getLabel(timer) + "\n" + /*LANG*/"Are you sure?", { title: /*LANG*/"Delete Timer" }).then((confirm) => { if (confirm) { alarms.splice(timerIndex, 1); saveAndReload(); diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index 29e71b3d9..28d48daab 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.37", + "version": "0.38", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm", diff --git a/apps/chargent/ChangeLog b/apps/chargent/ChangeLog index ae4aa0e36..3003cd07d 100644 --- a/apps/chargent/ChangeLog +++ b/apps/chargent/ChangeLog @@ -1,2 +1,3 @@ 0.01: First version 0.02: Support BangleJS2 +0.03: Added threshold diff --git a/apps/chargent/README.md b/apps/chargent/README.md index 56bc763b4..db93615a6 100644 --- a/apps/chargent/README.md +++ b/apps/chargent/README.md @@ -6,6 +6,8 @@ The first stage of charging Li-ion ends at ~80% capacity when the charge voltage This app has no UI and no configuration. To disable the app, you have to uninstall it. +New in v0.03: before the very first buzz, the average value after the peak is written to chargent.json and used as threshold for future charges. This reduces the time spent in the second charge stage. + Side notes - Full capacity is reached after charge current drops to an insignificant level. This is quite some time after charge voltage reached its peak / `E.getBattery()` returns 100. - This app starts buzzing some time after `E.getBattery()` returns 100 (~15min on my watch), and at least 5min after the peak to account for noise. diff --git a/apps/chargent/boot.js b/apps/chargent/boot.js index b02d00a8e..c62003a21 100644 --- a/apps/chargent/boot.js +++ b/apps/chargent/boot.js @@ -6,19 +6,27 @@ if (charging) { if (!id) { var max = 0; - var count = 0; + var cnt = 0; + var sum = 0; + var lim = (require('Storage').readJSON('chargent.json', true) || {}).limit || 0; id = setInterval(() => { - var battlvl = analogRead(pin); - if (max < battlvl) { - max = battlvl; - count = 0; + var val = analogRead(pin); + if (max < val) { + max = val; + cnt = 1; + sum = val; } else { - count++; - if (10 <= count) { // 10 * 30s == 5 min // TODO ? customizable - // TODO ? customizable - Bangle.buzz(500); - setTimeout(() => Bangle.buzz(500), 1000); + cnt++; + sum += val; + } + if (10 < cnt || (lim && lim <= max)) { // 10 * 30s == 5 min // TODO ? customizable + if (!lim) { + lim = sum / cnt; + require('Storage').writeJSON('chargent.json', {limit: lim}); } + // TODO ? customizable + Bangle.buzz(500); + setTimeout(() => Bangle.buzz(500), 1000); } }, 30*1000); } diff --git a/apps/chargent/metadata.json b/apps/chargent/metadata.json index e2e6f5a61..653cb7d74 100644 --- a/apps/chargent/metadata.json +++ b/apps/chargent/metadata.json @@ -1,6 +1,6 @@ { "id": "chargent", "name": "Charge Gently", - "version": "0.02", + "version": "0.03", "description": "When charging, reminds you to disconnect the watch to prolong battery life.", "icon": "icon.png", "type": "bootloader", @@ -9,5 +9,8 @@ "readme": "README.md", "storage": [ {"name": "chargent.boot.js", "url": "boot.js"} + ], + "data": [ + {"name": "chargent.json"} ] } diff --git a/apps/fuzzyw/ChangeLog b/apps/fuzzyw/ChangeLog index 206efb10f..dd73475f9 100644 --- a/apps/fuzzyw/ChangeLog +++ b/apps/fuzzyw/ChangeLog @@ -1,3 +1,4 @@ 0.01: First release 0.02: Move translations to locale module (removed watch settings, now pick language in Bangle App Loader, More..., Settings) -0.03: Change for fast loading, use widget_utils to hide widgets \ No newline at end of file +0.03: Change for fast loading, use widget_utils to hide widgets +0.04: Add animation when display changes \ No newline at end of file diff --git a/apps/fuzzyw/README.md b/apps/fuzzyw/README.md index 49d0fe0d5..062c9ac25 100644 --- a/apps/fuzzyw/README.md +++ b/apps/fuzzyw/README.md @@ -16,7 +16,6 @@ Most translations are taken from the original Fuzzy Text International code. ## TODO * Bold hour word (as the pebble version has) -* Animation when changing time? ## References Based on Pebble app Fuzzy Text International: https://github.com/hallettj/Fuzzy-Text-International diff --git a/apps/fuzzyw/fuzzyw.app.js b/apps/fuzzyw/fuzzyw.app.js index e185e2ccf..8bc51710f 100644 --- a/apps/fuzzyw/fuzzyw.app.js +++ b/apps/fuzzyw/fuzzyw.app.js @@ -33,13 +33,17 @@ ] }; -let text_scale = 3.5; +let text_scale = 4; let timeout = 2.5*60; let drawTimeout; +let animInterval; +let time_string = ""; +let time_string_old = ""; +let time_string_old_wrapped = ""; let loadSettings = function() { settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false}; -} +}; let queueDraw = function(seconds) { let millisecs = seconds * 1000; @@ -48,10 +52,7 @@ let queueDraw = function(seconds) { drawTimeout = undefined; draw(); }, millisecs - (Date.now() % millisecs)); -} - -const h = g.getHeight(); -const w = g.getWidth(); +}; let getTimeString = function(date) { let segment = Math.round((date.getMinutes()*60 + date.getSeconds() + 1)/300); @@ -63,18 +64,47 @@ let getTimeString = function(date) { f_string = f_string.replace('$2', fuzzy_string.hours[(hour + 1) % 12]); } return f_string; -} +}; let draw = function() { - let time_string = getTimeString(new Date()).replace('*', ''); - // print(time_string); - g.setFont('Vector', (h-24*2)/text_scale); - g.setFontAlign(0, 0); - g.clearRect(0, 24, w, h-24); - g.setColor(g.theme.fg); - g.drawString(g.wrapString(time_string, w).join("\n"), w/2, h/2); + time_string = getTimeString(new Date()).replace('*', ''); + //print(time_string); + if (time_string != time_string_old) { + g.setFont('Vector', R.h/text_scale).setFontAlign(0, 0); + animate(3); + } queueDraw(timeout); -} +}; + +let animate = function(step) { + if (animInterval) clearInterval(animInterval); + let time_string_new_wrapped = g.wrapString(time_string, R.w).join("\n"); + slideX = 0; + animInterval = setInterval(function() { + let time_start = getTime() + //blank old time + g.setColor(g.theme.bg); + g.drawString(time_string_old_wrapped, R.x + R.w/2 + slideX, R.y + R.h/2); + g.drawString(time_string_new_wrapped, R.x - R.w/2 + slideX, R.y + R.h/2); + g.setColor(g.theme.fg); + slideX += step; + let stop = false; + if (slideX>=R.w) { + slideX=R.w; + stop = true; + } + //draw shifted new time + g.drawString(time_string_old_wrapped, R.x + R.w/2 + slideX, R.y + R.h/2); + g.drawString(time_string_new_wrapped, R.x - R.w/2 + slideX, R.y + R.h/2); + if (stop) { + time_string_old = time_string; + clearInterval(animInterval); + animInterval=undefined; + time_string_old_wrapped = time_string_new_wrapped; + } + print(Math.round((getTime() - time_start)*1000)) + }, 30); +}; g.clear(); loadSettings(); @@ -95,6 +125,8 @@ Bangle.setUI({ // Called to unload all of the clock app if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; + if (animInterval) clearInterval(animInterval); + animInterval = undefined; require('widget_utils').show(); // re-show widgets } }); @@ -106,5 +138,6 @@ if (settings.showWidgets) { require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe } +R = Bangle.appRect; draw(); } \ No newline at end of file diff --git a/apps/fuzzyw/metadata.json b/apps/fuzzyw/metadata.json index d1040fda3..97f060866 100644 --- a/apps/fuzzyw/metadata.json +++ b/apps/fuzzyw/metadata.json @@ -2,7 +2,7 @@ "id":"fuzzyw", "name":"Fuzzy Text Clock", "shortName": "Fuzzy Text", - "version": "0.03", + "version": "0.04", "description": "An imprecise clock for when you're not in a rush", "readme": "README.md", "icon":"fuzzyw.png", diff --git a/apps/inspire/ChangeLog b/apps/inspire/ChangeLog index 267ee22c2..e8e154f2f 100644 --- a/apps/inspire/ChangeLog +++ b/apps/inspire/ChangeLog @@ -1 +1,2 @@ 0.01: First public version +0.02: Disable screen lock when breathing diff --git a/apps/inspire/README.md b/apps/inspire/README.md index f5f8e3aa9..43df1b760 100644 --- a/apps/inspire/README.md +++ b/apps/inspire/README.md @@ -2,7 +2,7 @@ A minimalistic app that will help you practive breathing. -Author: Written by pancake in 2022, powered by insomnia +Author: Written by pancake in 2022, updated in 2023, powered by insomnia ## Features @@ -10,6 +10,7 @@ Author: Written by pancake in 2022, powered by insomnia * [x] Tap to start * [x] Subtle vibrations * [x] Drag to pause breathing +* [x] Dont lock screen while breathing * [ ] Automatic buzz every hour during day ## Screenshots diff --git a/apps/inspire/app.js b/apps/inspire/app.js index 92b2c4ef2..818a6af76 100644 --- a/apps/inspire/app.js +++ b/apps/inspire/app.js @@ -14,6 +14,7 @@ var mode = 0; var sin = 0; var dragged = 0; var lastTime = Date.now(); + function breath(t) { var r = Math.abs(Math.sin(t / 100)) * w2; g.fillCircle(w/2,h/2, r); @@ -26,7 +27,7 @@ setTimeout(()=>{Bangle.buzz(60);}, 500); function showTouchScreen() { g.setColor(1,1,1); - g.fillCircle (w2, h2, h2-5); + g.fillCircle(w2, h2, h2-5); g.setColor(0,0,0); g.setFont("Vector", 32); g.drawString("Tap to", w/6, h2-fs); @@ -40,7 +41,7 @@ g.clear(); function animateCircle() { g.clear(); g.setColor(1,1,1); - g.fillCircle (w2, h2, radius); + g.fillCircle(w2, h2, radius); radius-=2; if (radius < 40) { breathing = true; @@ -68,6 +69,9 @@ function main() { return; } started = true; + Bangle.setLCDPower(1); + Bangle.setLocked(0); + Bangle.setLCDTimeout(0); animateCircle(); Bangle.buzz(40); } @@ -78,48 +82,48 @@ function main() { main(); function startBreathing() { -var cicles = 3; -g.setFont("Vector", fs); - -var interval = setInterval(function() { -if (lastTime + 10 > Date.now()) { - return; -} - lastTime = Date.now(); - g.setColor(0, 0, 0); - g.clear(); - - g.setColor(0, 0.5, 1); - var b = breath(count); - g.setColor(0.5, 0.5, 1); - var c = breath(count + 50); - count++; - g.setColor(1, 1, 1); - if (b < c) { - g.drawString("inspire",8,ty); - if (mode) { - mode = 0; - Bangle.buzz(20); - if (!dragged ) { - cicles--; + var cicles = 3; + g.setFont("Vector", fs); + + function breathTime() { + if (lastTime + 10 > Date.now()) { + return; + } + lastTime = Date.now(); + g.setColor(0, 0, 0); + g.clear(); + + g.setColor(0, 0.5, 1); + var b = breath(count); + g.setColor(0.5, 0.5, 1); + var c = breath(count + 50); + count++; + g.setColor(1, 1, 1); + if (b < c) { + g.drawString("inspire",8,ty); + if (mode) { + mode = 0; + Bangle.buzz(20); + if (!dragged ) { + cicles--; + } + } + } else { + g.drawString("expire",8,ty); + if (!mode) { + mode = 1; + Bangle.buzz(20); } } - } else { - g.drawString("expire",8,ty); - if (!mode) { - mode = 1; - Bangle.buzz(20); + g.drawString(cicles, w-fs, ty); + if (cicles < 1) { + clearInterval(interval); + g.clear(); + g.drawString("Thanks for",20,h/3); + g.drawString(" breathing!",20,(h/3) + 16); + Bangle.showClock(); } - } - g.drawString(cicles, w-fs, ty); - if (cicles < 1) { - clearInterval(interval); - g.clear(); - g.drawString("Thanks for",20,h/3); - g.drawString(" breathing!",20,(h/3) + 16); - Bangle.showClock(); - } dragged = 0; - -}, 4); + } + var interval = setInterval(breathTime, 4); } diff --git a/apps/inspire/metadata.json b/apps/inspire/metadata.json index 85b7365be..3ffbc40e7 100644 --- a/apps/inspire/metadata.json +++ b/apps/inspire/metadata.json @@ -2,7 +2,7 @@ "id": "inspire", "name": "Inspire Breathing", "shortName": "Inspire", - "version": "0.01", + "version": "0.02", "description": "exercise breathing every now and then", "icon": "app-icon.png", "tags": "tools,health",