Merge branch 'master' of github.com:espruino/BangleApps
|
|
@ -18,3 +18,4 @@
|
|||
0.17: Moving alarm internals to 'sched' library
|
||||
0.18: Cope with >1 identical alarm at once (#1667)
|
||||
0.19: Ensure rescheduled alarms that already fired have 'last' reset
|
||||
0.20: Use the new 'sched' factories to initialize new alarms/timers
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
var alarms = require("sched").getAlarms();
|
||||
// An array of alarm objects (see sched/README.md)
|
||||
let alarms = require("sched").getAlarms();
|
||||
|
||||
// time in ms -> { hrs, mins }
|
||||
function decodeTime(t) {
|
||||
t = 0|t; // sanitise
|
||||
var hrs = 0|(t/3600000);
|
||||
return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) };
|
||||
t = 0 | t; // sanitise
|
||||
let hrs = 0 | (t / 3600000);
|
||||
return { hrs: hrs, mins: Math.round((t - hrs * 3600000) / 60000) };
|
||||
}
|
||||
|
||||
// time in { hrs, mins } -> ms
|
||||
function encodeTime(o) {
|
||||
return o.hrs*3600000 + o.mins*60000;
|
||||
return o.hrs * 3600000 + o.mins * 60000;
|
||||
}
|
||||
|
||||
function formatTime(t) {
|
||||
var o = decodeTime(t);
|
||||
return o.hrs+":"+("0"+o.mins).substr(-2);
|
||||
let o = decodeTime(t);
|
||||
return o.hrs + ":" + ("0" + o.mins).substr(-2);
|
||||
}
|
||||
|
||||
function getCurrentTime() {
|
||||
var time = new Date();
|
||||
let time = new Date();
|
||||
return (
|
||||
time.getHours() * 3600000 +
|
||||
time.getMinutes() * 60000 +
|
||||
|
|
@ -39,7 +39,7 @@ function showMainMenu() {
|
|||
// Timer img "\0"+atob("DhKBAP////MDDAwwMGGBzgPwB4AeAPwHOBhgwMMzDez////w")
|
||||
// Alarm img "\0"+atob("FBSBAABgA4YcMPDGP8Zn/mx/48//PP/zD/8A//AP/wD/8A//AP/wH/+D//w//8AAAADwAAYA")
|
||||
const menu = {
|
||||
'': { 'title': 'Alarm/Timer' },
|
||||
'': { 'title': /*LANG*/'Alarms&Timers' },
|
||||
/*LANG*/'< Back' : ()=>{load();},
|
||||
/*LANG*/'New Alarm': ()=>editAlarm(-1),
|
||||
/*LANG*/'New Timer': ()=>editTimer(-1)
|
||||
|
|
@ -76,13 +76,13 @@ function showMainMenu() {
|
|||
function editDOW(dow, onchange) {
|
||||
const menu = {
|
||||
'': { 'title': /*LANG*/'Days of Week' },
|
||||
'< Back' : () => onchange(dow)
|
||||
/*LANG*/'< Back' : () => onchange(dow)
|
||||
};
|
||||
for (var i = 0; i < 7; i++) (i => {
|
||||
var dayOfWeek = require("locale").dow({ getDay: () => i });
|
||||
for (let i = 0; i < 7; i++) (i => {
|
||||
let dayOfWeek = require("locale").dow({ getDay: () => i });
|
||||
menu[dayOfWeek] = {
|
||||
value: !!(dow&(1<<i)),
|
||||
format: v => v ? "Yes" : "No",
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: v => v ? dow |= 1<<i : dow &= ~(1<<i),
|
||||
};
|
||||
})(i);
|
||||
|
|
@ -90,23 +90,15 @@ function editDOW(dow, onchange) {
|
|||
}
|
||||
|
||||
function editAlarm(alarmIndex, alarm) {
|
||||
var newAlarm = alarmIndex<0;
|
||||
var a = {
|
||||
t : 12*3600000, // 12 o clock default
|
||||
on : true,
|
||||
rp : false, // repeat not the default
|
||||
as : false,
|
||||
dow : 0b1111111,
|
||||
last : 0,
|
||||
vibrate : ".."
|
||||
}
|
||||
let newAlarm = alarmIndex < 0;
|
||||
let a = require("sched").newDefaultAlarm();
|
||||
if (!newAlarm) Object.assign(a, alarms[alarmIndex]);
|
||||
if (alarm) Object.assign(a,alarm);
|
||||
var t = decodeTime(a.t);
|
||||
let t = decodeTime(a.t);
|
||||
|
||||
const menu = {
|
||||
'': { 'title': /*LANG*/'Alarm' },
|
||||
'< Back' : () => showMainMenu(),
|
||||
/*LANG*/'< Back' : () => showMainMenu(),
|
||||
/*LANG*/'Hours': {
|
||||
value: t.hrs, min : 0, max : 23, wrap : true,
|
||||
onchange: v => t.hrs=v
|
||||
|
|
@ -117,23 +109,23 @@ function editAlarm(alarmIndex, alarm) {
|
|||
},
|
||||
/*LANG*/'Enabled': {
|
||||
value: a.on,
|
||||
format: v=>v?"On":"Off",
|
||||
format: v => v ? /*LANG*/"On" : /*LANG*/"Off",
|
||||
onchange: v=>a.on=v
|
||||
},
|
||||
/*LANG*/'Repeat': {
|
||||
value: a.rp,
|
||||
format: v=>v?"Yes":"No",
|
||||
onchange: v=>a.rp=v
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: v => a.rp = v
|
||||
},
|
||||
/*LANG*/'Days': {
|
||||
value: "SMTWTFS".split("").map((d,n)=>a.dow&(1<<n)?d:".").join(""),
|
||||
onchange: () => editDOW(a.dow, d=>{a.dow=d;editAlarm(alarmIndex,a)})
|
||||
},
|
||||
/*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ),
|
||||
/*LANG*/'Auto snooze': {
|
||||
/*LANG*/'Auto Snooze': {
|
||||
value: a.as,
|
||||
format: v=>v?"Yes":"No",
|
||||
onchange: v=>a.as=v
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: v => a.as = v
|
||||
}
|
||||
};
|
||||
menu[/*LANG*/"Save"] = function() {
|
||||
|
|
@ -155,23 +147,15 @@ function editAlarm(alarmIndex, alarm) {
|
|||
}
|
||||
|
||||
function editTimer(alarmIndex, alarm) {
|
||||
var newAlarm = alarmIndex<0;
|
||||
var a = {
|
||||
timer : 5*60*1000, // 5 minutes
|
||||
on : true,
|
||||
rp : false,
|
||||
as : false,
|
||||
dow : 0b1111111,
|
||||
last : 0,
|
||||
vibrate : ".."
|
||||
}
|
||||
let newAlarm = alarmIndex < 0;
|
||||
let a = require("sched").newDefaultTimer();
|
||||
if (!newAlarm) Object.assign(a, alarms[alarmIndex]);
|
||||
if (alarm) Object.assign(a,alarm);
|
||||
var t = decodeTime(a.timer);
|
||||
let t = decodeTime(a.timer);
|
||||
|
||||
const menu = {
|
||||
'': { 'title': /*LANG*/'Timer' },
|
||||
'< Back' : () => showMainMenu(),
|
||||
/*LANG*/'< Back' : () => showMainMenu(),
|
||||
/*LANG*/'Hours': {
|
||||
value: t.hrs, min : 0, max : 23, wrap : true,
|
||||
onchange: v => t.hrs=v
|
||||
|
|
@ -182,8 +166,8 @@ function editTimer(alarmIndex, alarm) {
|
|||
},
|
||||
/*LANG*/'Enabled': {
|
||||
value: a.on,
|
||||
format: v=>v?"On":"Off",
|
||||
onchange: v=>a.on=v
|
||||
format: v => v ? /*LANG*/"On" : /*LANG*/"Off",
|
||||
onchange: v => a.on = v
|
||||
},
|
||||
/*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"id": "alarm",
|
||||
"name": "Alarm & Timer",
|
||||
"name": "Alarms & Timers",
|
||||
"shortName": "Alarms",
|
||||
"version": "0.19",
|
||||
"version": "0.20",
|
||||
"description": "Set alarms and timers on your Bangle",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,alarm,widget",
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Support Bangle.js 2
|
||||
0.03: Fix bug for Bangle.js 2 where g.flip was not being called.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
//g.setTheme({fg : 0xFFFF, fg2 : 0xFFFF,bg2 : 0x0007,fgH : 0xFFFF,bgH : 0x02F7,dark : true});
|
||||
|
||||
|
||||
/* Choozi - Choose people or things at random using Bangle.js.
|
||||
* Inspired by the "Chwazi" Android app
|
||||
*
|
||||
|
|
@ -133,6 +130,7 @@ function animateChoice(target) {
|
|||
g.fillCircle(x, y, ballSize);
|
||||
oldx=x;
|
||||
oldy=y;
|
||||
g.flip();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -154,7 +152,7 @@ function choose() {
|
|||
// draw the current value of N in the middle of the screen, with
|
||||
// up/down arrows
|
||||
function drawN() {
|
||||
g.setColor('#000000');
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFont("Vector",fontSize);
|
||||
g.drawString(N,centreX-g.stringWidth(N)/2+4,centreY-fontSize/2);
|
||||
if (N < maxN)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "choozi",
|
||||
"name": "Choozi",
|
||||
"version": "0.02",
|
||||
"version": "0.03",
|
||||
"description": "Choose people or things at random using Bangle.js.",
|
||||
"icon": "app.png",
|
||||
"tags": "tool",
|
||||
|
|
|
|||
|
|
@ -10,3 +10,4 @@
|
|||
0.09: Fix file naming so months are 1-based (not 0) (fix #1119)
|
||||
0.10: Adds additional 3 minute setting for HRM
|
||||
0.11: Pre-minified boot&lib - folds constants and saves RAM
|
||||
0.12: Add setting for Daily Step Goal
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ Stores:
|
|||
* **Off** - Don't turn HRM on, but record heart rate if the HRM was turned on by another app/widget
|
||||
* **10 Min** - Turn HRM on every 10 minutes (for each heath entry) and turn it off after 2 minutes, or when a good reading is found
|
||||
* **Always** - Keep HRM on all the time (more accurate recording, but reduces battery life to ~36 hours)
|
||||
* **Daily Step Goal** - Default 10000, daily step goal for pedometer apps to use
|
||||
|
||||
|
||||
## Technical Info
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ function getSettings() {
|
|||
return require("Storage").readJSON("health.json",1)||{};
|
||||
}
|
||||
|
||||
function setSettings(s) {
|
||||
require("Storage").writeJSON("health.json",s);
|
||||
function setSettings(healthSettings) {
|
||||
require("Storage").writeJSON("health.json",healthSettings);
|
||||
}
|
||||
|
||||
function menuMain() {
|
||||
|
|
@ -22,15 +22,21 @@ function menuMain() {
|
|||
function menuSettings() {
|
||||
swipe_enabled = false;
|
||||
clearButton();
|
||||
var s=getSettings();
|
||||
var healthSettings=getSettings();
|
||||
//print(healthSettings);
|
||||
E.showMenu({
|
||||
"":{title:"Health Tracking"},
|
||||
"< Back":()=>menuMain(),
|
||||
"Heart Rt":{
|
||||
value : 0|s.hrm,
|
||||
value : 0|healthSettings.hrm,
|
||||
min : 0, max : 3,
|
||||
format : v=>["Off","3 mins","10 mins","Always"][v],
|
||||
onchange : v => { s.hrm=v;setSettings(s); }
|
||||
onchange : v => { healthSettings.hrm=v;setSettings(healthSettings); }
|
||||
},
|
||||
"Daily Step Goal":{
|
||||
value : (healthSettings.stepGoal ? healthSettings.stepGoal : 10000),
|
||||
min : 0, max : 20000, step : 100,
|
||||
onchange : v => { healthSettings.stepGoal=v;setSettings(healthSettings); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -199,7 +205,7 @@ function drawBarChart() {
|
|||
for (bar = 1; bar < 10; bar++) {
|
||||
if (bar == 5) {
|
||||
g.setFont('6x8', 2);
|
||||
g.setFontAlign(0,-1)
|
||||
g.setFontAlign(0,-1);
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawString(chart_label + " " + (chart_index + bar -1) + " " + chart_data[chart_index + bar - 1], g.getWidth()/2, 150);
|
||||
g.setColor("#00f");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "health",
|
||||
"name": "Health Tracking",
|
||||
"version": "0.11",
|
||||
"version": "0.12",
|
||||
"description": "Logs health data and provides an app to view it",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,system,health",
|
||||
|
|
|
|||
|
|
@ -12,3 +12,4 @@
|
|||
0.11: Merge Bangle.js 1 and 2 launchers, again
|
||||
0.12: Add an option to hide clocks from the app list (fix #1015)
|
||||
Add /*LANG*/ tags for internationalisation
|
||||
0.13: Add fullscreen mode
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ var s = require("Storage");
|
|||
var scaleval = 1;
|
||||
var vectorval = 20;
|
||||
var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2";
|
||||
let settings = Object.assign({ showClocks: true }, s.readJSON("launch.json", true) || {});
|
||||
let settings = Object.assign({
|
||||
showClocks: true,
|
||||
fullscreen: false
|
||||
}, s.readJSON("launch.json", true) || {});
|
||||
|
||||
if ("vectorsize" in settings) {
|
||||
vectorval = parseInt(settings.vectorsize);
|
||||
|
|
@ -44,8 +47,11 @@ function drawApp(i, r) {
|
|||
}
|
||||
|
||||
g.clear();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
if (!settings.fullscreen) {
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
|
||||
E.showScroller({
|
||||
h : 64*scaleval, c : apps.length,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
"id": "launch",
|
||||
"name": "Launcher",
|
||||
"shortName": "Launcher",
|
||||
"version": "0.12",
|
||||
"version": "0.13",
|
||||
"description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.",
|
||||
"icon": "app.png",
|
||||
"type": "launch",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
// make sure to enclose the function in parentheses
|
||||
(function(back) {
|
||||
let settings = Object.assign({ showClocks: true }, require("Storage").readJSON("launch.json", true) || {});
|
||||
let settings = Object.assign({
|
||||
showClocks: true,
|
||||
fullscreen: false
|
||||
}, require("Storage").readJSON("launch.json", true) || {});
|
||||
|
||||
let fonts = g.getFonts();
|
||||
function save(key, value) {
|
||||
|
|
@ -8,7 +11,7 @@
|
|||
require("Storage").write("launch.json",settings);
|
||||
}
|
||||
const appMenu = {
|
||||
"": {"title": /*LANG*/"Launcher Settings"},
|
||||
"": { "title": /*LANG*/"Launcher" },
|
||||
/*LANG*/"< Back": back,
|
||||
/*LANG*/"Font": {
|
||||
value: fonts.includes(settings.font)? fonts.indexOf(settings.font) : fonts.indexOf("12x20"),
|
||||
|
|
@ -16,15 +19,20 @@
|
|||
onchange: (m) => {save("font", fonts[m])},
|
||||
format: v => fonts[v]
|
||||
},
|
||||
/*LANG*/"Vector font size": {
|
||||
/*LANG*/"Vector Font Size": {
|
||||
value: settings.vectorsize || 10,
|
||||
min:10, max: 20,step:1,wrap:true,
|
||||
onchange: (m) => {save("vectorsize", m)}
|
||||
},
|
||||
/*LANG*/"Show clocks": {
|
||||
/*LANG*/"Show Clocks": {
|
||||
value: settings.showClocks == true,
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: (m) => {save("showClocks", m)}
|
||||
onchange: (m) => { save("showClocks", m) }
|
||||
},
|
||||
/*LANG*/"Fullscreen": {
|
||||
value: settings.fullscreen == true,
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: (m) => { save("fullscreen", m) }
|
||||
}
|
||||
};
|
||||
E.showMenu(appMenu);
|
||||
|
|
|
|||
|
|
@ -18,3 +18,5 @@
|
|||
0.18: Fullscreen mode can now be enabled or disabled in the settings.
|
||||
0.19: Alarms can not go bigger than 100.
|
||||
0.20: Use alarm for alarm functionality instead of own implementation.
|
||||
0.21: Add custom theming.
|
||||
0.22: Fix alarm and add build in function for step counting.
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
# LCARS clock
|
||||
|
||||
A simple LCARS inspired clock.
|
||||
Note: To display the steps, the wpedom app is required. To show weather data
|
||||
such as temperature, humidity or window you BangleJS must be connected
|
||||
To show weather data such as temperature, humidity or window you BangleJS must be connected
|
||||
with Gadgetbride and the weather app must be installed. To use the timer
|
||||
the "sched" app must be installed on your device.
|
||||
|
||||
|
|
@ -19,6 +18,7 @@ the "sched" app must be installed on your device.
|
|||
* Tap on top/bottom of screen 1 to activate an alarm. Depends on widtmr.
|
||||
* The lower orange line indicates the battery level.
|
||||
* Display graphs (day or month) for steps + hrm on the second screen.
|
||||
* Customizable theming colors in the settings menu of the app.
|
||||
|
||||
## Data that can be configured
|
||||
* Steps - Steps loaded via the wpedom app.
|
||||
|
|
@ -43,3 +43,4 @@ Access different screens via tap on the left/ right side of the screen
|
|||
## Contributors
|
||||
- [Adam Schmalhofer](https://github.com/adamschmalhofer)
|
||||
- [Jon Warrington](https://github.com/BartokW)
|
||||
- [Ronin Stegner](https://github.com/Ronin0000)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 795 B After Width: | Height: | Size: 789 B |
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 760 B |
|
Before Width: | Height: | Size: 791 B After Width: | Height: | Size: 771 B |
|
Before Width: | Height: | Size: 769 B After Width: | Height: | Size: 742 B |
|
|
@ -1,14 +1,17 @@
|
|||
const TIMER_IDX = "lcars";
|
||||
const SETTINGS_FILE = "lcars.setting.json";
|
||||
const locale = require('locale');
|
||||
const storage = require('Storage');
|
||||
const storage = require('Storage')
|
||||
let settings = {
|
||||
alarm: -1,
|
||||
dataRow1: "Steps",
|
||||
dataRow2: "Temp",
|
||||
dataRow2: "HRM",
|
||||
dataRow3: "Battery",
|
||||
speed: "kph",
|
||||
fullscreen: false,
|
||||
themeColor1BG: "#FF9900",
|
||||
themeColor2BG: "#FF00DC",
|
||||
themeColor3BG: "#0094FF",
|
||||
};
|
||||
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
||||
for (const key in saved_settings) {
|
||||
|
|
@ -18,9 +21,9 @@ for (const key in saved_settings) {
|
|||
/*
|
||||
* Colors to use
|
||||
*/
|
||||
let cBlue = "#0094FF";
|
||||
let cOrange = "#FF9900";
|
||||
let cPurple = "#FF00DC";
|
||||
let color1 = settings.themeColor3BG;
|
||||
let color2 = settings.themeColor1BG;
|
||||
let color3 = settings.themeColor2BG;
|
||||
let cWhite = "#FFFFFF";
|
||||
let cBlack = "#000000";
|
||||
let cGrey = "#424242";
|
||||
|
|
@ -33,33 +36,77 @@ let lcarsViewPos = 0;
|
|||
var plotMonth = false;
|
||||
|
||||
|
||||
/*
|
||||
* Requirements and globals
|
||||
*/
|
||||
function convert24to16(input)
|
||||
{
|
||||
let RGB888 = parseInt(input.replace(/^#/, ''), 16);
|
||||
let r = (RGB888 & 0xFF0000) >> 16;
|
||||
let g = (RGB888 & 0xFF00) >> 8;
|
||||
let b = RGB888 & 0xFF;
|
||||
|
||||
r = (r * 249 + 1014) >> 11;
|
||||
g = (g * 253 + 505) >> 10;
|
||||
b = (b * 249 + 1014) >> 11;
|
||||
let RGB565 = 0;
|
||||
RGB565 = RGB565 | (r << 11);
|
||||
RGB565 = RGB565 | (g << 5);
|
||||
RGB565 = RGB565 | b;
|
||||
|
||||
return "0x"+RGB565.toString(16);
|
||||
}
|
||||
|
||||
var color1C = convert24to16(color1);
|
||||
var color2C = convert24to16(color2);
|
||||
var color3C = convert24to16(color3);
|
||||
|
||||
/*
|
||||
* Requirements and globals
|
||||
*/
|
||||
|
||||
var colorPalette = new Uint16Array([
|
||||
0x0000, // not used
|
||||
color2C, // second
|
||||
color3C, // third
|
||||
0x0000, // not used
|
||||
color1C, // first
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000, // not used
|
||||
0x0000 // not used
|
||||
],0,1);
|
||||
|
||||
var bgLeftFullscreen = {
|
||||
width : 27, height : 176, bpp : 3,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=="))
|
||||
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAoUP7y/KH5QGDoQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyDCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4"))),
|
||||
palette: colorPalette
|
||||
};
|
||||
|
||||
var bgLeftNotFullscreen = {
|
||||
width : 27, height : 152, bpp : 3,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A="))
|
||||
buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=="))),
|
||||
palette: colorPalette
|
||||
};
|
||||
|
||||
var bgRightFullscreen = {
|
||||
width : 27, height : 176, bpp : 3,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAnUP7y/KH4yGeVYAJrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgAA="))
|
||||
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAnUP7y/KH4yGeVYAJ0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkp4CS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A=="))),
|
||||
palette: colorPalette
|
||||
};
|
||||
|
||||
var bgRightNotFullscreen = {
|
||||
width : 27, height : 152, bpp : 3,
|
||||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAxrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgA="))
|
||||
buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAx0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A="))),
|
||||
palette: colorPalette
|
||||
};
|
||||
|
||||
var bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen;
|
||||
|
|
@ -191,7 +238,7 @@ function _drawData(key, y, c){
|
|||
value = E.getAnalogVRef().toFixed(2) + "V";
|
||||
|
||||
} else if(key == "HRM"){
|
||||
value = Math.round(Bangle.getHealthStatus("day").bpm);
|
||||
value = Math.round(Bangle.getHealthStatus("last").bpm);
|
||||
|
||||
} else if (key == "TEMP"){
|
||||
var weather = getWeather();
|
||||
|
|
@ -244,9 +291,11 @@ function drawInfo(){
|
|||
return;
|
||||
}
|
||||
|
||||
// Draw Infor is called from different sources so
|
||||
// we have to ensure that the alignment is always the same.
|
||||
g.setFontAlign(-1, -1, 0);
|
||||
g.setFontAntonioMedium();
|
||||
g.setColor(cOrange);
|
||||
g.setColor(color2);
|
||||
g.clearRect(120, 10, g.getWidth(), 75);
|
||||
g.drawString("LCARS", 128, 13);
|
||||
|
||||
|
|
@ -256,7 +305,7 @@ function drawInfo(){
|
|||
g.drawString("NOCON", 128, 33);
|
||||
}
|
||||
if(Bangle.isLocked()){
|
||||
g.setColor(cPurple);
|
||||
g.setColor(color3);
|
||||
g.drawString("LOCK", 128, 53);
|
||||
}
|
||||
}
|
||||
|
|
@ -287,7 +336,7 @@ function drawState(){
|
|||
g.drawString("STATUS", 23+26, 108);
|
||||
} else {
|
||||
// Alarm within symbol
|
||||
g.setColor(cOrange);
|
||||
g.setColor(color2);
|
||||
g.drawString("ALARM", 23+26, 108);
|
||||
g.setColor(cWhite);
|
||||
g.setFontAntonioLarge();
|
||||
|
|
@ -302,19 +351,19 @@ function drawPosition0(){
|
|||
// Draw background image
|
||||
var offset = settings.fullscreen ? 0 : 24;
|
||||
g.drawImage(bgLeft, 0, offset);
|
||||
drawHorizontalBgLine(cBlue, 25, 120, offset, 4);
|
||||
drawHorizontalBgLine(cBlue, 130, 176, offset, 4);
|
||||
drawHorizontalBgLine(cPurple, 20, 70, 80, 4);
|
||||
drawHorizontalBgLine(cPurple, 80, 176, 80, 4);
|
||||
drawHorizontalBgLine(cOrange, 35, 110, 87, 4);
|
||||
drawHorizontalBgLine(cOrange, 120, 176, 87, 4);
|
||||
drawHorizontalBgLine(color1, 25, 120, offset, 4);
|
||||
drawHorizontalBgLine(color1, 130, 176, offset, 4);
|
||||
drawHorizontalBgLine(color3, 20, 70, 80, 4);
|
||||
drawHorizontalBgLine(color3, 80, 176, 80, 4);
|
||||
drawHorizontalBgLine(color2, 35, 110, 87, 4);
|
||||
drawHorizontalBgLine(color2, 120, 176, 87, 4);
|
||||
|
||||
// The last line is a battery indicator too
|
||||
var bat = E.getBattery() / 100.0;
|
||||
var batStart = 19;
|
||||
var batWidth = 172 - batStart;
|
||||
var batX2 = parseInt(batWidth * bat + batStart);
|
||||
drawHorizontalBgLine(cOrange, batStart, batX2, 171, 5);
|
||||
drawHorizontalBgLine(color2, batStart, batX2, 171, 5);
|
||||
drawHorizontalBgLine(cGrey, batX2, 172, 171, 5);
|
||||
for(var i=0; i+batStart<=172; i+=parseInt(batWidth/4)){
|
||||
drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8)
|
||||
|
|
@ -353,9 +402,9 @@ function drawPosition0(){
|
|||
// Draw data
|
||||
g.setFontAlign(-1, -1, 0);
|
||||
g.setColor(cWhite);
|
||||
drawData(settings.dataRow1, 97, cOrange);
|
||||
drawData(settings.dataRow2, 122, cPurple);
|
||||
drawData(settings.dataRow3, 147, cBlue);
|
||||
drawData(settings.dataRow1, 97, color2);
|
||||
drawData(settings.dataRow2, 122, color3);
|
||||
drawData(settings.dataRow3, 147, color1);
|
||||
|
||||
// Draw state
|
||||
drawState();
|
||||
|
|
@ -366,13 +415,13 @@ function drawPosition1(){
|
|||
var offset = settings.fullscreen ? 0 : 24;
|
||||
g.drawImage(bgRight, 149, offset);
|
||||
if(settings.fullscreen){
|
||||
drawHorizontalBgLine(cBlue, 0, 140, offset, 4);
|
||||
drawHorizontalBgLine(color1, 0, 140, offset, 4);
|
||||
}
|
||||
drawHorizontalBgLine(cPurple, 0, 80, 80, 4);
|
||||
drawHorizontalBgLine(cPurple, 90, 150, 80, 4);
|
||||
drawHorizontalBgLine(cOrange, 0, 50, 87, 4);
|
||||
drawHorizontalBgLine(cOrange, 60, 140, 87, 4);
|
||||
drawHorizontalBgLine(cOrange, 0, 150, 171, 5);
|
||||
drawHorizontalBgLine(color3, 0, 80, 80, 4);
|
||||
drawHorizontalBgLine(color3, 90, 150, 80, 4);
|
||||
drawHorizontalBgLine(color2, 0, 50, 87, 4);
|
||||
drawHorizontalBgLine(color2, 60, 140, 87, 4);
|
||||
drawHorizontalBgLine(color2, 0, 150, 171, 5);
|
||||
|
||||
// Draw steps bars
|
||||
g.setColor(cWhite);
|
||||
|
|
@ -511,17 +560,20 @@ function draw(){
|
|||
* Step counter via widget
|
||||
*/
|
||||
function getSteps() {
|
||||
var steps = 0;
|
||||
try{
|
||||
if (WIDGETS.wpedom !== undefined) {
|
||||
return WIDGETS.wpedom.getSteps();
|
||||
steps = WIDGETS.wpedom.getSteps();
|
||||
} else if (WIDGETS.activepedom !== undefined) {
|
||||
return WIDGETS.activepedom.getSteps();
|
||||
steps = WIDGETS.activepedom.getSteps();
|
||||
} else {
|
||||
steps = Bangle.getHealthStatus("day").steps;
|
||||
}
|
||||
} catch(ex) {
|
||||
// In case we failed, we can only show 0 steps.
|
||||
}
|
||||
|
||||
return 0;
|
||||
return steps;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -530,21 +582,6 @@ function getWeather(){
|
|||
|
||||
try {
|
||||
weatherJson = storage.readJSON('weather.json');
|
||||
} catch(ex) {
|
||||
// Return default
|
||||
}
|
||||
|
||||
if(weatherJson === undefined){
|
||||
return {
|
||||
temp: "-",
|
||||
hum: "-",
|
||||
txt: "-",
|
||||
wind: "-",
|
||||
wdir: "-",
|
||||
wrose: "-"
|
||||
};
|
||||
}
|
||||
|
||||
var weather = weatherJson.weather;
|
||||
|
||||
// Temperature
|
||||
|
|
@ -559,8 +596,20 @@ function getWeather(){
|
|||
weather.wind = Math.round(wind[1] * speedFactor);
|
||||
|
||||
return weather
|
||||
}
|
||||
|
||||
} catch(ex) {
|
||||
// Return default
|
||||
}
|
||||
|
||||
return {
|
||||
temp: " ? ",
|
||||
hum: " ? ",
|
||||
txt: " ? ",
|
||||
wind: " ? ",
|
||||
wdir: " ? ",
|
||||
wrose: " ? "
|
||||
};
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle alarm
|
||||
|
|
@ -642,7 +691,6 @@ Bangle.on('charging',function(charging) {
|
|||
drawState();
|
||||
});
|
||||
|
||||
|
||||
function feedback(){
|
||||
Bangle.buzz(40, 0.3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,14 @@
|
|||
const storage = require('Storage')
|
||||
let settings = {
|
||||
alarm: -1,
|
||||
dataRow1: "Battery",
|
||||
dataRow2: "Steps",
|
||||
dataRow3: "Temp",
|
||||
dataRow1: "Steps",
|
||||
dataRow2: "HRM",
|
||||
dataRow3: "Battery",
|
||||
speed: "kph",
|
||||
fullscreen: false,
|
||||
themeColor1BG: "#FF9900",
|
||||
themeColor2BG: "#FF00DC",
|
||||
themeColor3BG: "#0094FF",
|
||||
};
|
||||
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
||||
for (const key in saved_settings) {
|
||||
|
|
@ -20,8 +23,11 @@
|
|||
storage.write(SETTINGS_FILE, settings)
|
||||
}
|
||||
|
||||
|
||||
var dataOptions = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"];
|
||||
var speedOptions = ["kph", "mph"];
|
||||
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White'];
|
||||
var bg_code = ['#00ff00','#FF9900','#0094FF','#FF00DC','#ff0000','#0000ff','#ffef00','#FFFFFF'];
|
||||
|
||||
E.showMenu({
|
||||
'': { 'title': 'LCARS Clock' },
|
||||
|
|
@ -69,6 +75,33 @@
|
|||
settings.speed = speedOptions[v];
|
||||
save();
|
||||
},
|
||||
},
|
||||
'Theme Color 1': {
|
||||
value: 0 | bg_code.indexOf(settings.themeColor1BG),
|
||||
min: 0, max: 7,
|
||||
format: v => color_options[v],
|
||||
onchange: v => {
|
||||
settings.themeColor1BG = bg_code[v];
|
||||
save();
|
||||
},
|
||||
},
|
||||
'Theme Color 2': {
|
||||
value: 0 | bg_code.indexOf(settings.themeColor2BG),
|
||||
min: 0, max: 7,
|
||||
format: v => color_options[v],
|
||||
onchange: v => {
|
||||
settings.themeColor2BG = bg_code[v];
|
||||
save();
|
||||
},
|
||||
},
|
||||
'Theme Color 3': {
|
||||
value: 0 | bg_code.indexOf(settings.themeColor3BG),
|
||||
min: 0, max: 7,
|
||||
format: v => color_options[v],
|
||||
onchange: v => {
|
||||
settings.themeColor3BG = bg_code[v];
|
||||
save();
|
||||
},
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
"name": "LCARS Clock",
|
||||
"shortName":"LCARS",
|
||||
"icon": "lcars.png",
|
||||
"version":"0.20",
|
||||
"version":"0.22",
|
||||
"readme": "README.md",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
||||
|
|
|
|||
|
|
@ -44,3 +44,5 @@
|
|||
0.29: Fix message list overwrites on Bangle.js 1 (fix #1642)
|
||||
0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel)
|
||||
0.31: Option to disable icon flashing
|
||||
0.32: Added an option to allow quiet mode to override message auto-open
|
||||
0.33: Timeout from the message list screen if the message being displayed is removed and there is a timer going
|
||||
|
|
|
|||
|
|
@ -470,8 +470,6 @@ function checkMessages(options) {
|
|||
// no new messages - go to clock?
|
||||
if (options.clockIfAllRead && newMessages.length==0)
|
||||
return load();
|
||||
// we don't have to time out of this screen...
|
||||
cancelReloadTimeout();
|
||||
active = "main";
|
||||
// Otherwise show a menu
|
||||
E.showScroller({
|
||||
|
|
|
|||
|
|
@ -56,9 +56,16 @@ exports.pushMessage = function(event) {
|
|||
}
|
||||
// otherwise load messages/show widget
|
||||
var loadMessages = Bangle.CLOCK || event.important;
|
||||
// first, buzz
|
||||
var quiet = (require('Storage').readJSON('setting.json',1)||{}).quiet;
|
||||
var unlockWatch = (require('Storage').readJSON('messages.settings.json',1)||{}).unlockWatch;
|
||||
var appSettings = require('Storage').readJSON('messages.settings.json',1)||{};
|
||||
var unlockWatch = appSettings.unlockWatch;
|
||||
var quietNoAutOpn = appSettings.quietNoAutOpn;
|
||||
delete appSettings;
|
||||
// don't auto-open messages in quiet mode if quietNoAutOpn is true
|
||||
if(quiet && quietNoAutOpn) {
|
||||
loadMessages = false;
|
||||
}
|
||||
// first, buzz
|
||||
if (!quiet && loadMessages && global.WIDGETS && WIDGETS.messages){
|
||||
WIDGETS.messages.buzz();
|
||||
if(unlockWatch != false){
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "messages",
|
||||
"name": "Messages",
|
||||
"version": "0.31",
|
||||
"version": "0.33",
|
||||
"description": "App to display notifications from iOS and Gadgetbridge/Android",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
|
|
|
|||
|
|
@ -53,6 +53,11 @@
|
|||
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||
onchange: v => updateSetting("flash", v)
|
||||
},
|
||||
/*LANG*/'Quiet mode disables auto-open': {
|
||||
value: !!settings().quietNoAutOpn,
|
||||
format: v => v?/*LANG*/'Yes':/*LANG*/'No',
|
||||
onchange: v => updateSetting("quietNoAutOpn", v)
|
||||
},
|
||||
};
|
||||
E.showMenu(mainmenu);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
0.02: Fix scheduling of other alarms if there is a pending alarm from the past (fix #1667)
|
||||
0.03: Fix `getTimeToAlarm` for a timer already used at same day, don't set `last` for timers.
|
||||
0.04: Fix `getTimeToAlarm` to check for next dow if alarm.t lower currentTime.
|
||||
0.05: Export new functions (`newDefaultAlarm/Timer`), add Settings page
|
||||
|
|
|
|||
|
|
@ -8,8 +8,17 @@ Other apps can use this to provide alarm functionality.
|
|||
App
|
||||
---
|
||||
|
||||
The Alarm app allows you to add/modify any running timers.
|
||||
The **Alarms & Timers** app allows you to add/modify any running alarms and timers.
|
||||
|
||||
Global Settings
|
||||
---------------
|
||||
|
||||
- `Unlock at Buzz` - If `Yes` the alarm/timer will unlock the watch
|
||||
- `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only)
|
||||
- `Default Snooze` - Default _Snooze_ value for newly created alarms/timers
|
||||
- `Buzz Count` - The number of buzzes before the watch goes silent
|
||||
- `Buzz Interval` - The interval between one buzz and the next
|
||||
- `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers
|
||||
|
||||
Internals / Library
|
||||
-------------------
|
||||
|
|
@ -53,21 +62,27 @@ use too much RAM.
|
|||
It can be used as follows:
|
||||
|
||||
```
|
||||
// add/update an existing alarm
|
||||
// Get a new alarm with default values
|
||||
let alarm = require("sched").newDefaultAlarm();
|
||||
|
||||
// Get a new timer with default values
|
||||
let timer = require("sched").newDefaultTimer();
|
||||
|
||||
// Add/update an existing alarm
|
||||
require("sched").setAlarm("mytimer", {
|
||||
msg : "Wake up",
|
||||
timer : 10*60*1000, // 10 Minutes
|
||||
timer : 10 * 60 * 1000 // 10 minutes
|
||||
});
|
||||
// Ensure the widget and alarm timer updates to schedule the new alarm properly
|
||||
require("sched").reload();
|
||||
|
||||
// Get the time to the next alarm for us
|
||||
var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer"));
|
||||
// timeToNext===undefined if no alarm or alarm disabled
|
||||
let timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer"));
|
||||
// timeToNext === undefined if no alarm or alarm disabled
|
||||
|
||||
// delete an alarm
|
||||
// Delete an alarm
|
||||
require("sched").setAlarm("mytimer", undefined);
|
||||
// reload after deleting...
|
||||
// Reload after deleting
|
||||
require("sched").reload();
|
||||
|
||||
// Or add an alarm that runs your own code - in this case
|
||||
|
|
@ -76,12 +91,15 @@ require("sched").reload();
|
|||
require("sched").setAlarm("customrunner", {
|
||||
appid : "myapp",
|
||||
js : "load('setting.app.js')",
|
||||
timer : 1*60*1000, // 1 Minute
|
||||
timer : 1 * 60 * 1000 // 1 minute
|
||||
});
|
||||
|
||||
// If you have been specifying `appid` you can also find any alarms that
|
||||
// your app has created with the following:
|
||||
require("sched").getAlarms().filter(a=>a.appid=="myapp");
|
||||
require("sched").getAlarms().filter(a => a.appid == "myapp");
|
||||
|
||||
// Get the scheduler settings
|
||||
let settings = require("sched").getSettings();
|
||||
```
|
||||
|
||||
If your app requires alarms, you can specify that the alarms app needs to
|
||||
|
|
|
|||
|
|
@ -52,3 +52,58 @@ exports.reload = function() {
|
|||
Bangle.drawWidgets();
|
||||
}
|
||||
};
|
||||
// Factory that creates a new alarm with default values
|
||||
exports.newDefaultAlarm = function () {
|
||||
const settings = exports.getSettings();
|
||||
|
||||
let alarm = {
|
||||
t: 12 * 3600000, // Default to 12:00
|
||||
on: true,
|
||||
rp: false, // repeat not the default
|
||||
as: settings.defaultAutoSnooze || false,
|
||||
dow: 0b1111111,
|
||||
last: 0,
|
||||
vibrate: settings.defaultAlarmPattern,
|
||||
};
|
||||
|
||||
delete settings;
|
||||
|
||||
return alarm;
|
||||
}
|
||||
// Factory that creates a new timer with default values
|
||||
exports.newDefaultTimer = function () {
|
||||
const settings = exports.getSettings();
|
||||
|
||||
let timer = {
|
||||
timer: 5 * 60 * 1000, // 5 minutes
|
||||
on: true,
|
||||
rp: false,
|
||||
as: false,
|
||||
dow: 0b1111111,
|
||||
last: 0,
|
||||
vibrate: settings.defaultTimerPattern
|
||||
}
|
||||
|
||||
delete settings;
|
||||
|
||||
return timer;
|
||||
};
|
||||
// Return the scheduler settings
|
||||
exports.getSettings = function () {
|
||||
return Object.assign(
|
||||
{
|
||||
unlockAtBuzz: false,
|
||||
defaultSnoozeMillis: 600000, // 10 minutes
|
||||
defaultAutoSnooze: false,
|
||||
buzzCount: 10,
|
||||
buzzIntervalMillis: 3000, // 3 seconds
|
||||
defaultAlarmPattern: "..",
|
||||
defaultTimerPattern: ".."
|
||||
},
|
||||
require("Storage").readJSON("sched.settings.json", true) || {}
|
||||
);
|
||||
}
|
||||
// Write the updated settings back to storage
|
||||
exports.setSettings = function(settings) {
|
||||
require("Storage").writeJSON("sched.settings.json", settings);
|
||||
};
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "sched",
|
||||
"name": "Scheduler",
|
||||
"version": "0.04",
|
||||
"version": "0.05",
|
||||
"description": "Scheduling library for alarms and timers",
|
||||
"icon": "app.png",
|
||||
"type": "scheduler",
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
{"name":"sched.boot.js","url":"boot.js"},
|
||||
{"name":"sched.js","url":"sched.js"},
|
||||
{"name":"sched.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"sched","url":"lib.js"}
|
||||
{"name":"sched","url":"lib.js"},
|
||||
{"name":"sched.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [{"name":"sched.json"}]
|
||||
"data": [{"name":"sched.json"}, {"name":"sched.settings.json"}]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,9 @@ function formatTime(t) {
|
|||
}
|
||||
|
||||
function showAlarm(alarm) {
|
||||
var msg = "";
|
||||
const settings = require("sched").getSettings();
|
||||
|
||||
let msg = "";
|
||||
msg += alarm.timer ? formatTime(alarm.timer) : formatTime(alarm.t);
|
||||
if (alarm.msg) {
|
||||
msg += "\n"+alarm.msg;
|
||||
|
|
@ -28,9 +30,12 @@ function showAlarm(alarm) {
|
|||
else
|
||||
msg = atob("AC0swgF97///RcEpMlVVVVVVf9VVVVVVVVX/9VVf9VVf/1VVV///1Vf9VX///VVX///VWqqlV///1Vf//9aqqqqpf//9V///2qqqqqqn///V///6qqqqqqr///X//+qqoAAKqqv//3//6qoAAAAKqr//3//qqAAAAAAqq//3/+qoAADwAAKqv/3/+qgAADwAACqv/3/aqAAADwAAAqp/19qoAAADwAAAKqfV1qgAAADwAAACqXVWqgAAADwAAACqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAAOsAAAAKpVaoAAAAOsAAAAKpVaoAAAAL/AAAAKpVaoAAAAgPwAAAKpVaoAAACAD8AAAKpVWqAAAIAA/AAAqlVWqAAAgAAPwAAqlVWqAACAAADwAAqlVWqgAIAAAAAACqlVVqgAgAAAAAACqVVVqoAAAAAAAAKqVVVaqAAAAAAAAqpVVVWqgAAAAAACqlVVVWqoAAAAAAKqlVVVVqqAAAAAAqqVVVVVaqoAAAAKqpVVVVVeqqoAAKqqtVVVVV/6qqqqqqr/VVVVX/2qqqqqqn/1VVVf/VaqqqqpV/9VVVf9VVWqqlVVf9VVVf1VVVVVVVVX9VQ==")+" "+msg;
|
||||
}
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
var buzzCount = 10;
|
||||
|
||||
let buzzCount = settings.buzzCount;
|
||||
|
||||
E.showPrompt(msg,{
|
||||
title:alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!",
|
||||
buttons : {/*LANG*/"Snooze":true,/*LANG*/"Ok":false} // default is sleep so it'll come back in 10 mins
|
||||
|
|
@ -38,7 +43,7 @@ function showAlarm(alarm) {
|
|||
buzzCount = 0;
|
||||
if (sleep) {
|
||||
if(alarm.ot===undefined) alarm.ot = alarm.t;
|
||||
alarm.t += 10*60*1000; // 10 minutes
|
||||
alarm.t += settings.defaultSnoozeMillis;
|
||||
} else {
|
||||
if (!alarm.timer) alarm.last = (new Date()).getDate();
|
||||
if (alarm.ot!==undefined) {
|
||||
|
|
@ -51,24 +56,35 @@ function showAlarm(alarm) {
|
|||
require("sched").setAlarms(alarms);
|
||||
load();
|
||||
});
|
||||
|
||||
function buzz() {
|
||||
require("buzz").pattern(alarm.vibrate===undefined?"..":alarm.vibrate).then(function() {
|
||||
if (buzzCount--)
|
||||
setTimeout(buzz, 3000);
|
||||
else if(alarm.as) { // auto-snooze
|
||||
buzzCount = 10;
|
||||
setTimeout(buzz, 600000);
|
||||
if (settings.unlockAtBuzz) {
|
||||
Bangle.setLocked(false);
|
||||
}
|
||||
|
||||
require("buzz").pattern(alarm.vibrate === undefined ? ".." : alarm.vibrate).then(() => {
|
||||
if (buzzCount--) {
|
||||
setTimeout(buzz, settings.buzzIntervalMillis);
|
||||
} else if (alarm.as) { // auto-snooze
|
||||
buzzCount = settings.buzzCount;
|
||||
setTimeout(buzz, settings.defaultSnoozeMillis);
|
||||
}
|
||||
});
|
||||
}
|
||||
if ((require('Storage').readJSON('setting.json',1)||{}).quiet>1) return;
|
||||
|
||||
if ((require("Storage").readJSON("setting.json", 1) || {}).quiet > 1)
|
||||
return;
|
||||
|
||||
buzz();
|
||||
}
|
||||
|
||||
// Check for alarms
|
||||
var alarms = require("sched").getAlarms();
|
||||
var active = require("sched").getActiveAlarms(alarms);
|
||||
if (active.length) // if there's an alarm, show it
|
||||
let alarms = require("sched").getAlarms();
|
||||
let active = require("sched").getActiveAlarms(alarms);
|
||||
if (active.length) {
|
||||
// if there's an alarm, show it
|
||||
showAlarm(active[0]);
|
||||
else // otherwise just go back to default app
|
||||
} else {
|
||||
// otherwise just go back to default app
|
||||
setTimeout(load, 100);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
(function (back) {
|
||||
let settings = require("sched").getSettings();
|
||||
|
||||
E.showMenu({
|
||||
"": { "title": /*LANG*/"Scheduler" },
|
||||
|
||||
/*LANG*/"< Back": () => back(),
|
||||
|
||||
/*LANG*/"Unlock at Buzz": {
|
||||
value: settings.unlockAtBuzz,
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: v => {
|
||||
settings.unlockAtBuzz = v;
|
||||
require("sched").setSettings(settings);
|
||||
}
|
||||
},
|
||||
|
||||
/*LANG*/"Default Auto Snooze": {
|
||||
value: settings.defaultAutoSnooze,
|
||||
format: v => v ? /*LANG*/"Yes" : /*LANG*/"No",
|
||||
onchange: v => {
|
||||
settings.defaultAutoSnooze = v;
|
||||
require("sched").setSettings(settings);
|
||||
}
|
||||
},
|
||||
|
||||
/*LANG*/"Default Snooze": {
|
||||
value: settings.defaultSnoozeMillis / 60000,
|
||||
min: 5,
|
||||
max: 30,
|
||||
step: 5,
|
||||
format: v => v + /*LANG*/" min",
|
||||
onchange: v => {
|
||||
settings.defaultSnoozeMillis = v * 60000;
|
||||
require("sched").setSettings(settings);
|
||||
}
|
||||
},
|
||||
|
||||
/*LANG*/"Buzz Count": {
|
||||
value: settings.buzzCount,
|
||||
min: 5,
|
||||
max: 15,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
settings.buzzCount = v;
|
||||
require("sched").setSettings(settings);
|
||||
}
|
||||
},
|
||||
|
||||
/*LANG*/"Buzz Interval": {
|
||||
value: settings.buzzIntervalMillis / 1000,
|
||||
min: 1,
|
||||
max: 5,
|
||||
step: 1,
|
||||
format: v => v + /*LANG*/"s",
|
||||
onchange: v => {
|
||||
settings.buzzIntervalMillis = v * 1000;
|
||||
require("sched").setSettings(settings);
|
||||
}
|
||||
},
|
||||
|
||||
/*LANG*/"Default Alarm Pattern": require("buzz_menu").pattern(settings.defaultAlarmPattern, v => {
|
||||
settings.defaultAlarmPattern = v;
|
||||
require("sched").setSettings(settings);
|
||||
}),
|
||||
|
||||
/*LANG*/"Default Timer Pattern": require("buzz_menu").pattern(settings.defaultTimerPattern, v => {
|
||||
settings.defaultTimerPattern = v;
|
||||
require("sched").setSettings(settings);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1 @@
|
|||
0.01: New widget
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# Step counter widget
|
||||
This is my step counter. There are many like it, but this one is mine.
|
||||
|
||||
A pedometer widget designed to be as narrow as possible, but still easy to read, by sacrificing accuracy and only showing to the nearest 100 steps (0.1k).
|
||||
Shows a subtle fill colour in the background for progress to the goal. The goal is picked up from the health tracker settings.
|
||||
|
||||
|
||||

|
||||

|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "widstep",
|
||||
"name": "Step counter widget",
|
||||
"version": "0.01",
|
||||
"description": "Step counter widget, narrow but clearly readable",
|
||||
"readme": "README.md",
|
||||
"icon": "icons8-winter-boots-48.png",
|
||||
"screenshots": [{"url":"widstep-light.png"},{"url":"widstep-dark.png"}],
|
||||
"type": "widget",
|
||||
"tags": "widget,health",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"dependencies" : {"health":"app"},
|
||||
"allow_emulator":false,
|
||||
"storage": [
|
||||
{"name":"widstep.wid.js","url":"widstep.wid.js"}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
|
|
@ -0,0 +1,23 @@
|
|||
let wsSettingsGoal = (require('Storage').readJSON("health.json", 1) || {}).stepGoal || 10000;
|
||||
|
||||
Bangle.on('step', function(s) { WIDGETS["widstep"].draw(); });
|
||||
Bangle.on('lcdPower', function(on) {
|
||||
if (on) WIDGETS["widstep"].draw();
|
||||
});
|
||||
WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28,
|
||||
draw:function() {
|
||||
if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off
|
||||
var steps = Bangle.getHealthStatus("day").steps;
|
||||
g.reset();
|
||||
g.setColor(g.theme.bg);
|
||||
g.fillRect(this.x, this.y, this.x + this.width, this.y + 23);
|
||||
g.setColor(g.theme.dark ? '#00f' : '#0ff');
|
||||
var progress = this.width * Math.min(steps/wsSettingsGoal, 1);
|
||||
g.fillRect(this.x+1, this.y+1, this.x + progress -1, this.y + 23);
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFontAlign(0, -1);
|
||||
var steps_k = (steps/1000).toFixed(1) + 'k';
|
||||
g.setFont('6x15').drawString(steps_k, this.x+this.width/2, this.y + 10);
|
||||
g.setFont('4x6').drawString('steps', this.x+this.width/2, this.y + 2);
|
||||
}
|
||||
};
|
||||
|
|
@ -81,7 +81,7 @@ a.btn.btn-link.dropdown-toggle {
|
|||
min-height: 8em;
|
||||
}
|
||||
|
||||
.tile-content { position: relative; word-break: break-all; }
|
||||
.tile-content { position: relative; }
|
||||
.link-github {
|
||||
position:absolute;
|
||||
top: 36px;
|
||||
|
|
|
|||