diff --git a/android.html b/android.html index 48b41e72b..fb5d2557f 100644 --- a/android.html +++ b/android.html @@ -135,15 +135,17 @@

Utilities

+ + + +

+

- - -

Settings

@@ -172,6 +174,10 @@ Minify apps before upload (⚠️DANGER⚠️: Not recommended. Uploads smaller, faster apps but this will break many apps) + diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 6f306f61a..a41167e76 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -44,3 +44,6 @@ 0.39: Dated event repeat option 0.40: Use substring of message when it's longer than fits the designated menu entry. 0.41: Fix a menu bug affecting alarms with empty messages. +0.42: Fix date not getting saved in event edit menu when tapping Confirm +0.43: New settings: Show confirm, Show Overflow, Show Type. +0.44: Add "delete timer after expiration" setting to events. diff --git a/apps/alarm/README.md b/apps/alarm/README.md index 9da142dab..43f72665e 100644 --- a/apps/alarm/README.md +++ b/apps/alarm/README.md @@ -13,7 +13,7 @@ It uses the [`sched` library](https://github.com/espruino/BangleApps/blob/master - `Repeat` → Select when the alarm will fire. You can select a predefined option (_Once_, _Every Day_, _Workdays_ or _Weekends_ or you can configure the days freely) - `New Timer` → Configure a new timer (triggered based on amount of time elapsed in hours/minutes/seconds) - `New Event` → Configure a new event (triggered based on time and date) - - `Repeat` → Alarm can be be fired only once or repeated (every X number of _days_, _weeks_, _months_ or _years_) + - `Repeat` → Alarm can be fired only once or repeated (every X number of _days_, _weeks_, _months_ or _years_) - `Advanced` - `Scheduler settings` → Open the [Scheduler](https://github.com/espruino/BangleApps/tree/master/apps/sched) settings page, see its [README](https://github.com/espruino/BangleApps/blob/master/apps/sched/README.md) for details - `Enable All` → Enable _all_ disabled alarms & timers diff --git a/apps/alarm/app.js b/apps/alarm/app.js index f8ed0322e..52dbe40fd 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -1,6 +1,11 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); +const settings = Object.assign({ + showConfirm : true, + showAutoSnooze : true, + showHidden : true +}, require('Storage').readJSON('alarm.json',1)||{}); // 0 = Sunday (default), 1 = Monday const firstDayOfWeek = (require("Storage").readJSON("setting.json", true) || {}).firstDayOfWeek || 0; const WORKDAYS = 62; @@ -51,12 +56,14 @@ function getLabel(e) { } function trimLabel(label, maxLength) { + if(settings.showOverflow) return label; return (label.length > maxLength ? label.substring(0,maxLength-3) + "..." : label.substring(0,maxLength)); } -function formatAlarmMessage(msg) { +function formatAlarmProperty(msg) { + if(settings.showOverflow) return msg; if (msg == null) { return msg; } else if (msg.length > 7) { @@ -99,6 +106,9 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { var isNew = alarmIndex === undefined; var alarm = require("sched").newDefaultAlarm(); + if (withDate || selectedAlarm.date) { + alarm.del = require("sched").getSettings().defaultDeleteExpiredTimers; + } alarm.dow = handleFirstDayOfWeek(alarm.dow); if (selectedAlarm) { @@ -155,7 +165,7 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { }, /*LANG*/"Message": { value: alarm.msg, - format: formatAlarmMessage, + format: formatAlarmProperty, onchange: () => { setTimeout(() => { keyboard.input({text:alarm.msg}).then(result => { @@ -166,6 +176,19 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { }, 100); } }, + /*LANG*/"Group": { + value: alarm.group, + format: formatAlarmProperty, + onchange: () => { + setTimeout(() => { + keyboard.input({text:alarm.group}).then(result => { + alarm.group = result; + prepareAlarmForSave(alarm, alarmIndex, time, date, true); + setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate); + }); + }, 100); + } + }, /*LANG*/"Enabled": { value: alarm.on, onchange: v => alarm.on = v @@ -173,6 +196,9 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { /*LANG*/"Repeat": { value: decodeRepeat(alarm), onchange: () => setTimeout(showEditRepeatMenu, 100, alarm.rp, date || alarm.dow, (repeat, dow) => { + if (repeat) { + alarm.del = false; // do not auto delete a repeated alarm + } alarm.rp = repeat; alarm.dow = dow; prepareAlarmForSave(alarm, alarmIndex, time, date, true); @@ -184,23 +210,32 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate) { value: alarm.as, onchange: v => alarm.as = v }, + /*LANG*/"Delete After Expiration": { + value: alarm.del, + onchange: v => alarm.del = v + }, /*LANG*/"Hidden": { value: alarm.hidden || false, onchange: v => alarm.hidden = v }, /*LANG*/"Cancel": () => showMainMenu(), /*LANG*/"Confirm": () => { - prepareAlarmForSave(alarm, alarmIndex, time); + prepareAlarmForSave(alarm, alarmIndex, time, date); saveAndReload(); showMainMenu(); } }; if (!keyboard) delete menu[/*LANG*/"Message"]; + if (!keyboard || !settings.showGroup) delete menu[/*LANG*/"Group"]; + if (!settings.showConfirm) delete menu[/*LANG*/"Confirm"]; + if (!settings.showAutoSnooze) delete menu[/*LANG*/"Auto Snooze"]; + if (!settings.showHidden) delete menu[/*LANG*/"Hidden"]; if (!alarm.date) { delete menu[/*LANG*/"Day"]; delete menu[/*LANG*/"Month"]; delete menu[/*LANG*/"Year"]; + delete menu[/*LANG*/"Delete After Expiration"]; } if (!isNew) { @@ -259,7 +294,6 @@ function decodeRepeat(alarm) { } function showEditRepeatMenu(repeat, day, dowChangeCallback) { - var originalRepeat = repeat; var dow; const menu = { @@ -292,26 +326,32 @@ function showEditRepeatMenu(repeat, day, dowChangeCallback) { }, /*LANG*/"Custom": { value: isCustom ? decodeRepeat({ rp: true, dow: dow }) : false, - onchange: () => setTimeout(showCustomDaysMenu, 10, dow, dowChangeCallback, originalRepeat, originalDow) + onchange: () => setTimeout(showCustomDaysMenu, 10, dow, dowChangeCallback, repeat, originalDow) } }; } else { // var date = day; // eventually: detect day of date and configure a repeat e.g. 3rd Monday of Month dow = EVERY_DAY; - repeat = repeat || {interval: "month", num: 1}; + const repeatObj = repeat || {interval: "month", num: 1}; restOfMenu = { /*LANG*/"Every": { - value: repeat.num, + value: repeatObj.num, min: 1, - onchange: v => repeat.num = v + onchange: v => { + repeat = repeatObj; + repeat.num = v; + } }, /*LANG*/"Interval": { - value: INTERVALS.indexOf(repeat.interval), + value: INTERVALS.indexOf(repeatObj.interval), format: v => INTERVAL_LABELS[v], min: 0, max: INTERVALS.length - 1, - onchange: v => repeat.interval = INTERVALS[v] + onchange: v => { + repeat = repeatObj; + repeat.interval = INTERVALS[v]; + } } }; } @@ -387,7 +427,7 @@ function showEditTimerMenu(selectedTimer, timerIndex) { }, /*LANG*/"Message": { value: timer.msg, - format: formatAlarmMessage, + format: formatAlarmProperty, onchange: () => { setTimeout(() => { keyboard.input({text:timer.msg}).then(result => { @@ -420,6 +460,8 @@ function showEditTimerMenu(selectedTimer, timerIndex) { }; if (!keyboard) delete menu[/*LANG*/"Message"]; + if (!settings.showConfirm) delete menu[/*LANG*/"Confirm"]; + if (!settings.showHidden) delete menu[/*LANG*/"Hidden"]; if (!isNew) { menu[/*LANG*/"Delete"] = () => { E.showPrompt(getLabel(timer) + "\n" + /*LANG*/"Are you sure?", { title: /*LANG*/"Delete Timer" }).then((confirm) => { diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index b986512bc..31a3e5bf0 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.41", + "version": "0.44", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm", @@ -11,7 +11,8 @@ "dependencies": { "scheduler":"type", "alarm":"widget" }, "storage": [ { "name": "alarm.app.js", "url": "app.js" }, - { "name": "alarm.img", "url": "app-icon.js", "evaluate": true } + { "name": "alarm.img", "url": "app-icon.js", "evaluate": true }, + { "name": "alarm.settings.js", "url":"settings.js" } ], "screenshots": [ { "url": "screenshot-1.png" }, @@ -25,5 +26,6 @@ { "url": "screenshot-9.png" }, { "url": "screenshot-10.png" }, { "url": "screenshot-11.png" } - ] + ], + "data":[ {"name":"alarm.settings.json"} ] } diff --git a/apps/alarm/settings.js b/apps/alarm/settings.js new file mode 100644 index 000000000..765e5a5fa --- /dev/null +++ b/apps/alarm/settings.js @@ -0,0 +1,51 @@ +(function(back) { + let settings = Object.assign({ + showConfirm : true, + showAutoSnooze : true, + showHidden : true + }, require('Storage').readJSON('alarm.json',1)||{}); + + const save = () => require('Storage').write('alarm.json', settings); + const DATE_FORMATS = ['default', 'mmdd']; + const DATE_FORMATS_LABELS = [/*LANG*/'Default', /*LANG*/'MMDD']; + + const appMenu = { + '': {title: 'alarm'}, '< Back': back, + /*LANG*/'Menu Date Format': { + value: DATE_FORMATS.indexOf(settings.menuDateFormat || 'default'), + format: v => DATE_FORMATS_LABELS[v], + min: 0, + max: DATE_FORMATS.length - 1, + onchange : v => { + if(v > 0) { + settings.menuDateFormat=DATE_FORMATS[v]; + } else { + delete settings.menuDateFormat; + } + save(); + } + }, + /*LANG*/'Show Menu Auto Snooze': { + value : !!settings.showAutoSnooze, + onchange : v => { settings.showAutoSnooze=v; save();} + }, + /*LANG*/'Show Menu Confirm': { + value : !!settings.showConfirm, + onchange : v => { settings.showConfirm=v; save();} + }, + /*LANG*/'Show Menu Hidden': { + value : !!settings.showHidden, + onchange : v => { settings.showHidden=v; save();} + }, + /*LANG*/'Show Menu Group': { + value : !!settings.showGroup, + onchange : v => { settings.showGroup=v; save();} + }, + /*LANG*/'Show Text Overflow': { + value : !!settings.showOverflow, + onchange : v => { settings.showOverflow=v; save();} + }, + }; + + E.showMenu(appMenu); +}); diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index d966c1440..d531e43a9 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -27,4 +27,8 @@ 0.26: Change handling of GPS status to depend on GPS events instead of connection events 0.27: Issue newline before GB commands (solves issue with console.log and ignored commands) 0.28: Navigation messages no longer launch the Maps view unless they're new -0.29: Support for http request xpath return format \ No newline at end of file +0.29: Support for http request xpath return format +0.30: Send firmware and hardware versions on connection + Allow alarm enable/disable +0.31: Implement API for activity fetching +0.32: Added support for loyalty cards from gadgetbridge diff --git a/apps/android/boot.js b/apps/android/boot.js index 7988c378f..846fc40a8 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -86,7 +86,7 @@ var a = require("sched").newDefaultAlarm(); a.id = "gb"+j; a.appid = "gbalarms"; - a.on = true; + a.on = event.d[j].on !== undefined ? event.d[j].on : true; a.t = event.d[j].h * 3600000 + event.d[j].m * 60000; a.dow = ((dow&63)<<1) | (dow>>6); // Gadgetbridge sends DOW in a different format a.last = last; @@ -193,10 +193,37 @@ Bangle.on('HRM',actHRMHandler); actInterval = setInterval(function() { var steps = Bangle.getStepCount(); - gbSend({ t: "act", stp: steps-lastSteps, hrm: lastBPM }); + gbSend({ t: "act", stp: steps-lastSteps, hrm: lastBPM, rt:1 }); lastSteps = steps; }, event.int*1000); }, + // {t:"actfetch", ts:long} + "actfetch": function() { + gbSend({t: "actfetch", state: "start"}); + var actCount = 0; + var actCb = function(r) { + // The health lib saves the samples at the start of the 10-minute block + // However, GB expects them at the end of the block, so let's offset them + // here to keep a consistent API in the health lib + var sampleTs = r.date.getTime() + 600000; + if (sampleTs >= event.ts) { + gbSend({ + t: "act", + ts: sampleTs, + stp: r.steps, + hrm: r.bpm, + mov: r.movement + }); + actCount++; + } + } + if (event.ts != 0) { + require("health").readAllRecordsSince(new Date(event.ts - 600000), actCb); + } else { + require("health").readFullDatabase(actCb); + } + gbSend({t: "actfetch", state: "end", count: actCount}); + }, "nav": function() { event.id="nav"; if (event.instr) { @@ -209,6 +236,11 @@ event.t="remove"; } require("messages").pushMessage(event); + }, + "cards" : function() { + // we receive all, just override what we have + if (Array.isArray(event.d)) + require("Storage").writeJSON("android.cards.json", event.d); } }; var h = HANDLERS[event.t]; @@ -253,6 +285,7 @@ Bangle.on("charging", sendBattery); NRF.on("connect", () => setTimeout(function() { sendBattery(); + gbSend({t: "ver", fw: process.env.VERSION, hw: process.env.HWVERSION}); GB({t:"force_calendar_sync_start"}); // send a list of our calendar entries to start off the sync process }, 2000)); NRF.on("disconnect", () => { @@ -264,10 +297,9 @@ require("messages").clearAll(); }); setInterval(sendBattery, 10*60*1000); - // Health tracking - Bangle.on('health', health=>{ - if (actInterval===undefined) // if 'realtime' we do it differently - gbSend({ t: "act", stp: health.steps, hrm: health.bpm }); + // Health tracking - if 'realtime' data is sent with 'rt:1', but let's still send our activity log every 10 mins + Bangle.on('health', h=>{ + gbSend({ t: "act", stp: h.steps, hrm: h.bpm, mov: h.movement }); }); // Music control Bangle.musicControl = cmd => { diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 8489570f7..68bd946c5 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.29", + "version": "0.32", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", @@ -15,6 +15,6 @@ {"name":"android.img","url":"app-icon.js","evaluate":true}, {"name":"android.boot.js","url":"boot.js"} ], - "data": [{"name":"android.settings.json"}, {"name":"android.calendar.json"}], + "data": [{"name":"android.settings.json"}, {"name":"android.calendar.json"}, {"name":"android.cards.json"}], "sortorder": -8 } diff --git a/apps/assistedgps/custom.html b/apps/assistedgps/custom.html index 30cdb3eed..994f6d053 100644 --- a/apps/assistedgps/custom.html +++ b/apps/assistedgps/custom.html @@ -31,7 +31,7 @@