diff --git a/apps/grandfatherclock/ChangeLog b/apps/grandfatherclock/ChangeLog new file mode 100644 index 000000000..a21dc397d --- /dev/null +++ b/apps/grandfatherclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: New Widget! +0.02: rename, new icon, settings menu! diff --git a/apps/grandfatherclock/README.md b/apps/grandfatherclock/README.md new file mode 100644 index 000000000..b701164cc --- /dev/null +++ b/apps/grandfatherclock/README.md @@ -0,0 +1,26 @@ +# Grandfather Clock + +A widget that runs in the background and chimes on every (configurable) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. + +## Usage + +Once installed, see the App Settings page for options. + +Defaults: +- Twelve hour mode is ENABLED. +- Swap meridian is DISABLED. (in the AM, there will be a single buzz after counting the hours. in the PM, there will be two buzzes after counting the hours) +- The attention buzz for the hour chime is 1000ms long. +- The buzz for each hour count is 250ms long. +- The buzz for each fraction count is 250ms long. +- The widget will count out 4 fractions of an hour (a 15 min interval). +- The time between count buzzes is 500ms. +- The meridian buzzes are 50ms long. +- The time between meridian buzzes is 300ms. + +## Requests + +Drop me a message at @yogsoy on Discord if you need help / discover a bug that I can squash for you. + +## Creator + +Written by June B (yogsoy), inspired by aaronrolls' Chimer. diff --git a/apps/grandfatherclock/icon.png b/apps/grandfatherclock/icon.png new file mode 100644 index 000000000..8dc851c04 Binary files /dev/null and b/apps/grandfatherclock/icon.png differ diff --git a/apps/grandfatherclock/metadata.json b/apps/grandfatherclock/metadata.json new file mode 100644 index 000000000..053e384d6 --- /dev/null +++ b/apps/grandfatherclock/metadata.json @@ -0,0 +1,18 @@ +{ "id": "grandfatherclock", + "name": "Grandfather Clock Widget", + "shortName":"Grandfather Clock", + "version":"0.02", + "description": "A widget that chimes every fraction of an hour (similar to Chimer), and counts out the fractions and the o'clock hour.", + "icon": "icon.png", + "type": "widget", + "tags": "widget", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"grandfatherclock.wid.js","url":"widget.js"}, + {"name":"grandfatherclock.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"grandfatherclock.json"} + ] +} diff --git a/apps/grandfatherclock/settings.js b/apps/grandfatherclock/settings.js new file mode 100644 index 000000000..6401dffa5 --- /dev/null +++ b/apps/grandfatherclock/settings.js @@ -0,0 +1,89 @@ +(function(back) { + + const configFile = "grandfatherclock.json"; + + let config = Object.assign({ + draw_widget: true, + twelve_hour: true, + swap_meridian: false, + hour_attention_buzz_ms: 1000, + hour_count_buzz_ms: 250, + fraction_count_buzz_ms: 250, + fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals + wait_ms: 500, + meridian_buzz_ms: 50, + meridian_buzz_wait_ms: 300 + }, require('Storage').readJSON("grandfatherclock.json", true) || {}); + + let writeConfig = function() { + require('Storage').writeJSON(configFile, config); + }; + + E.showMenu({ + "": {"title" : "Grandfather Clock"}, + "< Back": () => back(), + "Draw widget": { + value: config.draw_widget, + onchange: v => { + config.draw_widget = v; + writeConfig(); + } + }, + "12 hour": { + value: config.twelve_hour, + onchange: v => { + config.twelve_hour = v; + writeConfig(); + } + },"Swap meridian": { + value: config.swap_meridian, + onchange: v => { + config.swap_meridian = v; + writeConfig(); + } + },"Hr attn. buzz length (ms)": { + value: config.hour_attention_buzz_ms, + onchange: v => { + config.hour_attention_buzz_ms = v; + writeConfig(); + } + },"Hr count buzz (ms)": { + value: config.hour_count_buzz_ms, + onchange: v => { + config.hour_count_buzz_ms = v; + writeConfig(); + } + },"Frac. count buzz (ms)": { + value: config.fraction_count_buzz_ms, + onchange: v => { + config.fraction_count_buzz_ms = v; + writeConfig(); + } + },"Fracs. of hour": { + value: config.fractions_of_hour, + onchange: v => { + config.fractions_of_hour = v; + writeConfig(); + } + },"Count wait (ms)": { + value: config.wait_ms, + onchange: v => { + config.wait_ms = v; + writeConfig(); + } + },"Meridian buzz (ms)": { + value: config.meridian_buzz_ms, + onchange: v => { + config.meridian_buzz_ms = v; + writeConfig(); + } + },"Meridian wait (ms)": { + value: config.meridian_buzz_wait_ms, + onchange: v => { + config.meridian_buzz_wait_ms = v; + writeConfig(); + } + } + }); + +}) diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js new file mode 100644 index 000000000..96e121e63 --- /dev/null +++ b/apps/grandfatherclock/widget.js @@ -0,0 +1,81 @@ +(() => { + + // sensible defaults + let config = Object.assign({ + draw_widget: true, + twelve_hour: true, + swap_meridian: false, + hour_attention_buzz_ms: 1000, + hour_count_buzz_ms: 250, + fraction_count_buzz_ms: 250, + fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals + wait_ms: 500, + meridian_buzz_ms: 50, + meridian_buzz_wait_ms: 300 + }, require('Storage').readJSON("grandfatherclock.json", true) || {}); // or, load the app settings file. + + WIDGETS["grandfatherclock"] = { + area: "tr", + width: config.draw_widget ? 16 : 0, + draw: function() { + if (config.draw_widget) { + g.reset(); + g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); + } + } + }; + + let date; + let fractionMs = 3600000 / config.fractions_of_hour; + + let chime = function () { + date = new Date(); + let hourFrac = Math.floor(date.getMinutes() / (60 / config.fractions_of_hour)); + + if (hourFrac == 0) { // if it's an o'clock hour + let chimeHour = (config.twelve_hour ? date.getHours() % 12 : date.getHours()); + if (chimeHour == 0) (config.twelve_hour ? chimeHour += 12 : chimeHour += 24); + + Bangle.buzz(config.hour_attention_buzz_ms).then(() => { // initial buzz + setTimeout(hourChime, config.wait_ms, chimeHour); // wait a period before doing the first chime + }); + } else { // if it's a fraction of an hour + fractionChime(hourFrac); + } + + queueNextChime(); + }; + + let hourChime = function (hoursLeftToChime) { + hoursLeftToChime--; + Bangle.buzz(config.hour_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + if (hoursLeftToChime > 0) { + setTimeout(hourChime, config.wait_ms, hoursLeftToChime); + } else if (config.twelve_hour) { // once finished with the hour count + setTimeout(meridianChime, config.wait_ms, (date.getHours() >= 12)); // if in twelve hour mode, queue up the meridian chime. + } + }); + }; + + let fractionChime = function (fractionsLeftToChime) { + fractionsLeftToChime--; + Bangle.buzz(config.fraction_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + if (fractionsLeftToChime > 0) setTimeout(fractionChime, config.wait_ms, fractionsLeftToChime); + }); + }; + + let meridianChime = function (meridian) { + if ((config.swap_meridian ? !meridian : meridian)) { // default: if PM + Bangle.buzz(config.meridian_buzz_ms).then(setTimeout(Bangle.buzz, config.meridian_buzz_wait_ms, config.meridian_buzz_ms)); // buzz once, wait, buzz again. + } else { // default: if AM + Bangle.buzz(config.meridian_buzz_ms); // buzz once. + } + }; + + let queueNextChime = function () { + let msUntilNextFraction = fractionMs - (Date.now() % fractionMs); + setTimeout(chime, msUntilNextFraction); + }; + + queueNextChime(); +})()