mirror of https://github.com/espruino/BangleApps
Merge branch 'master' into gpsmagdir
commit
d2e0bc8da0
|
@ -10,6 +10,12 @@ Standard # of drag handlers: 0-10 (Default: 0, must be changed for backswipe to
|
|||
|
||||
Standard # of handlers settings are used to fine tune when backswipe should trigger the back function. E.g. when using a keyboard that works on drags, we don't want the backswipe to trigger when we just wanted to select a letter. This might not be able to cover all cases however.
|
||||
|
||||
To get an indication for standard # of handlers `Bangle["#onswipe"]` and `Bangle["#ondrag"]` can be entered in the [Espruino Web IDE](https://www.espruino.com/ide) console field. They return `undefined` if no handler is active, a function if one is active, or a list of functions if multiple are active. Calling this on the clock app is a good start.
|
||||
|
||||
## TODO
|
||||
|
||||
- Possibly add option to tweak standard # of handlers on per app basis.
|
||||
|
||||
## Creator
|
||||
Kedlub
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
0.01: Initial fork from messages_light
|
||||
0.02: Fix touch/drag/swipe handlers not being restored correctly if a message is removed
|
|
@ -0,0 +1,24 @@
|
|||
# Messages overlay app
|
||||
|
||||
This app handles the display of messages and message notifications as an overlay pop up.
|
||||
|
||||
It is a GUI replacement for the `messages` apps.
|
||||
|
||||
Messages are ephemeral and not stored on the Bangle.
|
||||
|
||||
## Usage
|
||||
|
||||
Close app by tapping the X and scroll by swiping. The border of the pop up changes color if the Bangle is locked. The color depends on your currently active theme.
|
||||
|
||||
## Firmware hint
|
||||
Current stable firmware draws incorrect colors for emojis. Nightly firmware builds correct this.
|
||||
|
||||
## Low memory mode
|
||||
|
||||
If free memory is below 2000 blocks, the overlay automatically only uses 1 bit depth. Default uses roundabout 1300 blocks, while low memory mode uses about 600.
|
||||
|
||||
## Creator
|
||||
|
||||
[halemmerich](https://github.com/halemmerich)
|
||||
Forked from messages_light by Rarder44
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 2.2 KiB |
|
@ -0,0 +1,7 @@
|
|||
//override require to filter require("message")
|
||||
global.require_real=global.require;
|
||||
global.require = (_require => file => {
|
||||
if (file==="messages") file = "messagesoverlay";
|
||||
return _require(file);
|
||||
})(require);
|
||||
|
|
@ -0,0 +1,486 @@
|
|||
/* MESSAGES is a list of:
|
||||
{id:int,
|
||||
src,
|
||||
title,
|
||||
subject,
|
||||
body,
|
||||
sender,
|
||||
tel:string,
|
||||
new:true // not read yet
|
||||
}
|
||||
*/
|
||||
|
||||
const ovrx = 10;
|
||||
const ovry = 10;
|
||||
const ovrw = g.getWidth()-2*ovrx;
|
||||
const ovrh = g.getHeight()-2*ovry;
|
||||
let _g = g;
|
||||
|
||||
let lockListener;
|
||||
let quiet;
|
||||
|
||||
let LOG = function() {
|
||||
//print.apply(null, arguments);
|
||||
};
|
||||
|
||||
let isQuiet = function(){
|
||||
if (quiet == undefined) quiet = (require('Storage').readJSON('setting.json', 1) || {}).quiet;
|
||||
return quiet;
|
||||
};
|
||||
|
||||
let settings = {
|
||||
fontSmall:"6x8",
|
||||
fontMedium:"Vector:14",
|
||||
fontBig:"Vector:20",
|
||||
fontLarge:"Vector:30",
|
||||
};
|
||||
|
||||
let eventQueue = [];
|
||||
let callInProgress = false;
|
||||
|
||||
let show = function(ovr){
|
||||
let img = ovr;
|
||||
if (ovr.getBPP() == 1) {
|
||||
img = ovr.asImage();
|
||||
img.palette = new Uint16Array([_g.theme.fg,_g.theme.bg]);
|
||||
}
|
||||
Bangle.setLCDOverlay(img, ovrx, ovry);
|
||||
};
|
||||
|
||||
let manageEvent = function(ovr, event) {
|
||||
event.new = true;
|
||||
|
||||
LOG("manageEvent");
|
||||
if (event.id == "call") {
|
||||
showCall(ovr, event);
|
||||
return;
|
||||
}
|
||||
switch (event.t) {
|
||||
case "add":
|
||||
eventQueue.unshift(event);
|
||||
|
||||
if (!callInProgress)
|
||||
showMessage(ovr, event);
|
||||
break;
|
||||
|
||||
case "modify":
|
||||
let find = false;
|
||||
eventQueue.forEach(element => {
|
||||
if (element.id == event.id) {
|
||||
find = true;
|
||||
Object.assign(element, event);
|
||||
}
|
||||
});
|
||||
if (!find)
|
||||
eventQueue.unshift(event);
|
||||
|
||||
if (!callInProgress)
|
||||
showMessage(ovr, event);
|
||||
break;
|
||||
|
||||
case "remove":
|
||||
if (eventQueue.length == 0 && !callInProgress)
|
||||
next(ovr);
|
||||
|
||||
if (!callInProgress && eventQueue[0] !== undefined && eventQueue[0].id == event.id)
|
||||
next(ovr);
|
||||
|
||||
else {
|
||||
eventQueue.length = 0; // empty existing queue
|
||||
eventQueue.forEach(element => {
|
||||
if (element.id != event.id)
|
||||
neweventQueue.push(element);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
case "musicstate":
|
||||
case "musicinfo":
|
||||
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let roundedRect = function(ovr, x,y,w,h,filled){
|
||||
var poly = [
|
||||
x,y+4,
|
||||
x+4,y,
|
||||
x+w-5,y,
|
||||
x+w-1,y+4,
|
||||
x+w-1,y+h-5,
|
||||
x+w-5,y+h-1,
|
||||
x+4,y+h-1,
|
||||
x,y+h-5,
|
||||
x,y+4
|
||||
];
|
||||
ovr.drawPoly(poly,true);
|
||||
if (filled) ovr.fillPoly(poly,true);
|
||||
};
|
||||
|
||||
let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){
|
||||
ovr.setBgColor(ovr.theme.bg2);
|
||||
ovr.clearRect(2,2,ovr.getWidth()-3,37);
|
||||
|
||||
ovr.setColor(ovr.theme.fg2);
|
||||
ovr.setFont(settings.fontSmall);
|
||||
ovr.setFontAlign(0,-1);
|
||||
|
||||
let textCenter = (ovr.getWidth()+35-26)/2;
|
||||
|
||||
if (src) {
|
||||
let shortened = src;
|
||||
while (ovr.stringWidth(shortened) > ovr.getWidth()-80) shortened = shortened.substring(0,shortened.length-2);
|
||||
if (shortened.length != src.length) shortened += "...";
|
||||
ovr.drawString(shortened, textCenter, 2);
|
||||
}
|
||||
|
||||
ovr.setFontAlign(0,0);
|
||||
ovr.setFont(titleFont);
|
||||
if (title) ovr.drawString(title, textCenter, 38/2 + 5);
|
||||
|
||||
ovr.setColor(ovr.theme.fg2);
|
||||
|
||||
ovr.setFont(settings.fontMedium);
|
||||
roundedRect(ovr, ovr.getWidth()-26,5,22,30,false);
|
||||
ovr.setFont("Vector:16");
|
||||
ovr.drawString("X",ovr.getWidth()-14,21);
|
||||
|
||||
ovr.setColor("#888");
|
||||
roundedRect(ovr, 5,5,30,30,true);
|
||||
ovr.setColor(ovr.getBPP() != 1 ? iconcolor : ovr.theme.bg2);
|
||||
ovr.drawImage(icon,8,8);
|
||||
};
|
||||
|
||||
let showMessage = function(ovr, msg) {
|
||||
LOG("showMessage");
|
||||
ovr.setBgColor(ovr.theme.bg);
|
||||
|
||||
if (typeof msg.CanscrollDown === "undefined")
|
||||
msg.CanscrollDown = false;
|
||||
if (typeof msg.CanscrollUp === "undefined")
|
||||
msg.CanscrollUp = false;
|
||||
|
||||
// Normal text message display
|
||||
let title = msg.title,
|
||||
titleFont = settings.fontLarge,
|
||||
lines;
|
||||
if (title) {
|
||||
let w = ovr.getWidth() - 35 - 26;
|
||||
if (ovr.setFont(titleFont).stringWidth(title) > w)
|
||||
titleFont = settings.fontMedium;
|
||||
if (ovr.setFont(titleFont).stringWidth(title) > w) {
|
||||
lines = ovr.wrapString(title, w);
|
||||
title = (lines.length > 2) ? lines.slice(0, 2).join("\n") + "..." : lines.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg));
|
||||
|
||||
if (!isQuiet() && msg.new) {
|
||||
msg.new = false;
|
||||
Bangle.buzz();
|
||||
}
|
||||
|
||||
drawMessage(ovr, msg);
|
||||
};
|
||||
|
||||
let drawBorder = function(ovr) {
|
||||
if (Bangle.isLocked())
|
||||
ovr.setColor(ovr.theme.fgH);
|
||||
else
|
||||
ovr.setColor(ovr.theme.fg);
|
||||
ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1);
|
||||
ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2);
|
||||
show(ovr);
|
||||
if (!isQuiet()) Bangle.setLCDPower(1);
|
||||
};
|
||||
|
||||
let showCall = function(ovr, msg) {
|
||||
LOG("showCall");
|
||||
LOG(msg);
|
||||
|
||||
if (msg.t == "remove") {
|
||||
LOG("hide call screen");
|
||||
next(ovr); //dont shift
|
||||
return;
|
||||
}
|
||||
|
||||
callInProgress = true;
|
||||
|
||||
let title = msg.title,
|
||||
titleFont = settings.fontLarge,
|
||||
lines;
|
||||
if (title) {
|
||||
let w = ovr.getWidth() - 35 -26;
|
||||
if (ovr.setFont(titleFont).stringWidth(title) > w)
|
||||
titleFont = settings.fontMedium;
|
||||
if (ovr.setFont(titleFont).stringWidth(title) > w) {
|
||||
lines = ovr.wrapString(title, w);
|
||||
title = (lines.length > 2) ? lines.slice(0, 2).join("\n") + "..." : lines.join("\n");
|
||||
}
|
||||
}
|
||||
|
||||
drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg));
|
||||
|
||||
stopCallBuzz();
|
||||
if (!isQuiet()) {
|
||||
if (msg.new) {
|
||||
msg.new = false;
|
||||
if (callBuzzTimer) clearInterval(callBuzzTimer);
|
||||
callBuzzTimer = setInterval(function() {
|
||||
Bangle.buzz(500);
|
||||
}, 1000);
|
||||
|
||||
Bangle.buzz(500);
|
||||
}
|
||||
}
|
||||
drawMessage(ovr, msg);
|
||||
};
|
||||
|
||||
let next = function(ovr) {
|
||||
LOG("next");
|
||||
stopCallBuzz();
|
||||
|
||||
if (!callInProgress)
|
||||
eventQueue.shift();
|
||||
|
||||
callInProgress = false;
|
||||
if (eventQueue.length == 0) {
|
||||
LOG("no element in queue - closing");
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
|
||||
showMessage(ovr, eventQueue[0]);
|
||||
};
|
||||
|
||||
let showMapMessage = function(ovr, msg) {
|
||||
ovr.clearRect(2,2,ovr.getWidth()-3,ovr.getHeight()-3);
|
||||
drawMessage(ovr, {
|
||||
body: "Not implemented!"
|
||||
});
|
||||
};
|
||||
|
||||
let callBuzzTimer = null;
|
||||
let stopCallBuzz = function() {
|
||||
if (callBuzzTimer) {
|
||||
clearInterval(callBuzzTimer);
|
||||
callBuzzTimer = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
let drawTriangleUp = function(ovr) {
|
||||
ovr.reset();
|
||||
ovr.fillPoly([ovr.getWidth()-9, 46,ovr.getWidth()-14, 56,ovr.getWidth()-4, 56]);
|
||||
};
|
||||
|
||||
let drawTriangleDown = function(ovr) {
|
||||
ovr.reset();
|
||||
ovr.fillPoly([ovr.getWidth()-9, ovr.getHeight()-6, ovr.getWidth()-14, ovr.getHeight()-16, ovr.getWidth()-4, ovr.getHeight()-16]);
|
||||
};
|
||||
|
||||
let scrollUp = function(ovr) {
|
||||
msg = eventQueue[0];
|
||||
LOG("up", msg);
|
||||
if (typeof msg.FirstLine === "undefined")
|
||||
msg.FirstLine = 0;
|
||||
if (typeof msg.CanscrollUp === "undefined")
|
||||
msg.CanscrollUp = false;
|
||||
|
||||
if (!msg.CanscrollUp) return;
|
||||
|
||||
msg.FirstLine = msg.FirstLine > 0 ? msg.FirstLine - 1 : 0;
|
||||
|
||||
drawMessage(ovr, msg);
|
||||
};
|
||||
|
||||
let scrollDown = function(ovr) {
|
||||
msg = eventQueue[0];
|
||||
LOG("down", msg);
|
||||
if (typeof msg.FirstLine === "undefined")
|
||||
msg.FirstLine = 0;
|
||||
if (typeof msg.CanscrollDown === "undefined")
|
||||
msg.CanscrollDown = false;
|
||||
|
||||
if (!msg.CanscrollDown) return;
|
||||
|
||||
msg.FirstLine = msg.FirstLine + 1;
|
||||
drawMessage(ovr, msg);
|
||||
};
|
||||
|
||||
let drawMessage = function(ovr, msg) {
|
||||
let MyWrapString = function(str, maxWidth) {
|
||||
str = str.replace("\r\n", "\n").replace("\r", "\n");
|
||||
return ovr.wrapString(str, maxWidth);
|
||||
};
|
||||
|
||||
if (typeof msg.FirstLine === "undefined") msg.FirstLine = 0;
|
||||
|
||||
let bodyFont = typeof msg.bodyFont === "undefined" ? settings.fontMedium : msg.bodyFont;
|
||||
let Padding = 3;
|
||||
if (typeof msg.lines === "undefined") {
|
||||
ovr.setFont(bodyFont);
|
||||
msg.lines = MyWrapString(msg.body, ovr.getWidth() - (Padding * 2));
|
||||
if (msg.lines.length <= 2) {
|
||||
bodyFont = ovr.getFonts().includes("Vector") ? "Vector:20" : "6x8:3";
|
||||
ovr.setFont(bodyFont);
|
||||
msg.lines = MyWrapString(msg.body, ovr.getWidth() - (Padding * 2));
|
||||
msg.bodyFont = bodyFont;
|
||||
}
|
||||
}
|
||||
|
||||
let NumLines = 7;
|
||||
|
||||
let linesToPrint = (msg.lines.length > NumLines) ? msg.lines.slice(msg.FirstLine, msg.FirstLine + NumLines) : msg.lines;
|
||||
|
||||
let yText = 40;
|
||||
|
||||
ovr.setBgColor(ovr.theme.bg);
|
||||
ovr.setColor(ovr.theme.fg);
|
||||
ovr.clearRect(2, yText, ovrw-3, ovrh-3);
|
||||
let xText = Padding;
|
||||
yText += Padding;
|
||||
ovr.setFont(bodyFont);
|
||||
let HText = ovr.getFontHeight();
|
||||
|
||||
yText = ((ovrh - yText) / 2) - (linesToPrint.length * HText / 2) + yText;
|
||||
|
||||
if (linesToPrint.length <= 3) {
|
||||
ovr.setFontAlign(0, -1);
|
||||
xText = ovr.getWidth() / 2;
|
||||
} else
|
||||
ovr.setFontAlign(-1, -1);
|
||||
|
||||
|
||||
linesToPrint.forEach((line, i) => {
|
||||
ovr.drawString(line, xText, yText + HText * i);
|
||||
});
|
||||
|
||||
if (msg.FirstLine != 0) {
|
||||
msg.CanscrollUp = true;
|
||||
drawTriangleUp(ovr);
|
||||
} else
|
||||
msg.CanscrollUp = false;
|
||||
|
||||
if (msg.FirstLine + linesToPrint.length < msg.lines.length) {
|
||||
msg.CanscrollDown = true;
|
||||
drawTriangleDown(ovr);
|
||||
} else
|
||||
msg.CanscrollDown = false;
|
||||
show(ovr);
|
||||
if (!isQuiet()) Bangle.setLCDPower(1);
|
||||
};
|
||||
|
||||
let getSwipeHandler = function(ovr){
|
||||
return (lr, ud) => {
|
||||
if (ud == 1) {
|
||||
scrollUp(ovr);
|
||||
} else if (ud == -1){
|
||||
scrollDown(ovr);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let getTouchHandler = function(ovr){
|
||||
return (_, xy) => {
|
||||
if (xy.y < ovry + 40){
|
||||
next(ovr);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
let restoreHandler = function(event){
|
||||
LOG("Restore", event, backup[event]);
|
||||
Bangle.removeAllListeners(event);
|
||||
Bangle["#on" + event]=backup[event];
|
||||
backup[event] = undefined;
|
||||
};
|
||||
|
||||
let backupHandler = function(event){
|
||||
if (backupDone) return; // do not backup, overlay is already up
|
||||
backup[event] = Bangle["#on" + event];
|
||||
LOG("Backed up", backup[event]);
|
||||
Bangle.removeAllListeners(event);
|
||||
};
|
||||
|
||||
let cleanup = function(){
|
||||
if (lockListener) {
|
||||
Bangle.removeListener("lock", lockListener);
|
||||
lockListener = undefined;
|
||||
}
|
||||
restoreHandler("touch");
|
||||
restoreHandler("swipe");
|
||||
restoreHandler("drag");
|
||||
|
||||
Bangle.setLCDOverlay();
|
||||
backupDone = false;
|
||||
ovr = undefined;
|
||||
quiet = undefined;
|
||||
};
|
||||
|
||||
let backup = {};
|
||||
|
||||
let backupDone = false;
|
||||
|
||||
let main = function(ovr, event) {
|
||||
LOG("Main", event, settings);
|
||||
|
||||
if (!lockListener) {
|
||||
lockListener = function (){
|
||||
drawBorder(ovr);
|
||||
};
|
||||
Bangle.on('lock', lockListener);
|
||||
}
|
||||
backupHandler("touch");
|
||||
backupHandler("swipe");
|
||||
backupHandler("drag");
|
||||
if (!backupDone){
|
||||
Bangle.on('touch', getTouchHandler(ovr));
|
||||
Bangle.on('swipe', getSwipeHandler(ovr));
|
||||
}
|
||||
backupDone=true;
|
||||
|
||||
if (event !== undefined){
|
||||
drawBorder(ovr);
|
||||
manageEvent(ovr, event);
|
||||
} else {
|
||||
LOG("No event given");
|
||||
cleanup();
|
||||
}
|
||||
};
|
||||
|
||||
let ovr;
|
||||
|
||||
exports.pushMessage = function(event) {
|
||||
if( event.id=="music") return require_real("messages").pushMessage(event);
|
||||
|
||||
bpp = 4;
|
||||
if (process.memory().free < 2000) bpp = 1;
|
||||
|
||||
if (!ovr) {
|
||||
ovr = Graphics.createArrayBuffer(ovrw, ovrh, bpp, {
|
||||
msb: true
|
||||
});
|
||||
} else {
|
||||
ovr.clear();
|
||||
}
|
||||
|
||||
g = ovr;
|
||||
|
||||
if (bpp == 4)
|
||||
ovr.theme = g.theme;
|
||||
else
|
||||
ovr.theme = { fg:0, bg:1, fg2:1, bg2:0, fgH:1, bgH:0 };
|
||||
|
||||
main(ovr, event);
|
||||
|
||||
g = _g;
|
||||
};
|
||||
|
||||
|
||||
//Call original message library
|
||||
exports.clearAll = function() { return require_real("messages").clearAll();};
|
||||
exports.getMessages = function() { return require_real("messages").getMessages();};
|
||||
exports.status = function() { return require_real("messages").status();};
|
||||
exports.buzz = function() { return require_real("messages").buzz(msgSrc);};
|
||||
exports.stopBuzz = function() { return require_real("messages").stopBuzz();};
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"id": "messagesoverlay",
|
||||
"name": "Messages Overlay",
|
||||
"version": "0.02",
|
||||
"description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)",
|
||||
"icon": "app.png",
|
||||
"type": "bootloader",
|
||||
"tags": "tool,system",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"dependencies" : { "messageicons":"module","messages":"app" },
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"messagesoverlay","url":"lib.js"},
|
||||
{"name":"messagesoverlay.boot.js","url":"boot.js"}
|
||||
],
|
||||
"screenshots": [{"url":"screen_call.png"} ,{"url":"screen_message.png"} ]
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 3.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
|
@ -7,3 +7,5 @@
|
|||
0.06: Allow logging of some things using power
|
||||
Add widget for live monitoring of power use
|
||||
0.07: Convert Yes/No On/Off in settings to checkboxes
|
||||
0.08: Fix the wrapping of intervals/timeouts with parameters
|
||||
Fix the widget drawing if widgets are hidden and Bangle.setLCDBrightness is called
|
|
@ -19,6 +19,14 @@ You can switch on logging in the options to diagnose unexpected power use. Curre
|
|||
|
||||
Do not use trace logging for extended time, it uses a lot of storage and can fill up the flash quite quick.
|
||||
|
||||
### TODO
|
||||
|
||||
* Wrap functions given as strings to setTimeout/setInterval
|
||||
* Handle eval in setTimeout/setInterval
|
||||
* Track functions executed as event handlers
|
||||
* Track buzzer
|
||||
* Modify browser interface to estimate power use like widget does
|
||||
|
||||
## Internals
|
||||
|
||||
Battery calibration offset is set by writing `batFullVoltage` in setting.json
|
||||
|
|
|
@ -77,14 +77,14 @@
|
|||
|
||||
let functions = {};
|
||||
let wrapDeferred = ((o,t) => (a) => {
|
||||
if (a == eval){
|
||||
if (a == eval || typeof a == "string") {
|
||||
return o.apply(this, arguments);
|
||||
} else {
|
||||
let wrapped = a;
|
||||
if (!a.__wrapped){
|
||||
wrapped = ()=>{
|
||||
let start = Date.now();
|
||||
let result = a.apply(undefined, arguments.slice(1));
|
||||
let result = a.apply(undefined, arguments.slice(2)); // function arguments for deferred calls start at index 2, first is function, second is time
|
||||
let end = Date.now()-start;
|
||||
let f = a.toString().substring(0,100);
|
||||
if (settings.logDetails) logDeferred(t, end, f);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "powermanager",
|
||||
"name": "Power Manager",
|
||||
"shortName": "Power Manager",
|
||||
"version": "0.07",
|
||||
"version": "0.08",
|
||||
"description": "Allow configuration of warnings and thresholds for battery charging and display.",
|
||||
"icon": "app.png",
|
||||
"type": "bootloader",
|
||||
|
@ -20,6 +20,7 @@
|
|||
"data": [
|
||||
{"name":"powermanager.hw.json"},
|
||||
{"name":"powermanager.def.json"},
|
||||
{"name":"powermanager.json"},
|
||||
{"name":"powermanager.log"}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ currently-running apps */
|
|||
let brightnessSetting = settings.brightness || 1;
|
||||
Bangle.setLCDBrightness = ((o) => (a) => {
|
||||
brightnessSetting = a;
|
||||
draw(WIDGETS.powermanager);
|
||||
WIDGETS.powermanager.draw(WIDGETS.powermanager);
|
||||
return o(a);
|
||||
})(Bangle.setLCDBrightness);
|
||||
|
||||
|
|
|
@ -13,5 +13,7 @@
|
|||
0.12: Fix for recorder not stopping at end of run. Bug introduced in 0.11
|
||||
0.13: Revert #1578 (stop duplicate entries) as with 2v12 menus it causes other boxes to be wiped (fix #1643)
|
||||
0.14: Fix Bangle.js 1 issue where after the 'overwrite track' menu, the start/stop button stopped working
|
||||
0.15: Diverge from the standard "Run" app. Swipe to intensity interface a la Karvonnen (curtesy of FTeacher at https://github.com/f-teacher)
|
||||
0.15: Diverge from the standard "Run" app. Swipe to intensity interface a la Karvonen (curtesy of FTeacher at https://github.com/f-teacher)
|
||||
Keep run state between runs (allowing you to exit and restart the app)
|
||||
0.16: Don't clear zone 2b indicator segment when updating HRM reading.
|
||||
Write to correct settings file, fixing settings not working.
|
||||
|
|
|
@ -67,3 +67,10 @@ app loader, the module is automatically included in the app's source. However
|
|||
when developing via the IDE the module won't get pulled in by default.
|
||||
|
||||
There are some options to fix this easily - please check out the [modules README.md file](https://github.com/espruino/BangleApps/blob/master/modules/README.md)
|
||||
## Contributors (Run and Run+)
|
||||
gfwilliams
|
||||
hughbarney
|
||||
GrandVizierOlaf
|
||||
BartS23
|
||||
f-teacher
|
||||
thyttan
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
let wu = require("widget_utils");
|
||||
|
||||
let runInterval;
|
||||
let karvonnenActive = false;
|
||||
let karvonenActive = false;
|
||||
// Run interface wrapped in a function
|
||||
let ExStats = require("exstats");
|
||||
let B2 = process.env.HWVERSION===2;
|
||||
|
@ -63,7 +63,6 @@ function setStatus(running) {
|
|||
function onStartStop() {
|
||||
let running = !exs.state.active;
|
||||
let prepPromises = [];
|
||||
|
||||
// start/stop recording
|
||||
// Do this first in case recorder needs to prompt for
|
||||
// an overwrite before we start tracking exstats
|
||||
|
@ -155,7 +154,7 @@ Bangle.on("GPS", function(fix) {
|
|||
}
|
||||
});
|
||||
|
||||
// run() function used to switch between traditional run UI and karvonnen UI
|
||||
// run() function used to switch between traditional run UI and karvonen UI
|
||||
function run() {
|
||||
wu.show();
|
||||
layout.lazy = false;
|
||||
|
@ -165,35 +164,35 @@ function run() {
|
|||
if (!runInterval){
|
||||
runInterval = setInterval(function() {
|
||||
layout.clock.label = locale.time(new Date(),1);
|
||||
if (!isMenuDisplayed && !karvonnenActive) layout.render();
|
||||
if (!isMenuDisplayed && !karvonenActive) layout.render();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
run();
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Karvonnen
|
||||
// Karvonen
|
||||
///////////////////////////////////////////////
|
||||
|
||||
function stopRunUI() {
|
||||
// stop updating and drawing the traditional run app UI
|
||||
clearInterval(runInterval);
|
||||
runInterval = undefined;
|
||||
karvonnenActive = true;
|
||||
karvonenActive = true;
|
||||
}
|
||||
|
||||
function stopKarvonnenUI() {
|
||||
function stopKarvonenUI() {
|
||||
g.reset().clear();
|
||||
clearInterval(karvonnenInterval);
|
||||
karvonnenInterval = undefined;
|
||||
karvonnenActive = false;
|
||||
clearInterval(karvonenInterval);
|
||||
karvonenInterval = undefined;
|
||||
karvonenActive = false;
|
||||
}
|
||||
|
||||
let karvonnenInterval;
|
||||
let karvonenInterval;
|
||||
// Define the function to go back and forth between the different UI's
|
||||
function swipeHandler(LR,_) {
|
||||
if (LR==-1 && karvonnenActive && !isMenuDisplayed) {stopKarvonnenUI(); run();}
|
||||
if (LR==1 && !karvonnenActive && !isMenuDisplayed) {stopRunUI(); karvonnenInterval = eval(require("Storage").read("runplus_karvonnen"))(settings.HRM, exs.stats.bpm);}
|
||||
if (LR==-1 && karvonenActive && !isMenuDisplayed) {stopKarvonenUI(); run();}
|
||||
if (LR==1 && !karvonenActive && !isMenuDisplayed) {stopRunUI(); karvonenInterval = eval(require("Storage").read("runplus_karvonen"))(settings.HRM, exs.stats.bpm);}
|
||||
}
|
||||
// Listen for swipes with the swipeHandler
|
||||
Bangle.on("swipe", swipeHandler);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(function karvonnen(hrmSettings, exsHrmStats) {
|
||||
(function karvonen(hrmSettings, exsHrmStats) {
|
||||
//This app is an extra feature implementation for the Run.app of the bangle.js. It's called run+
|
||||
//The calculation of the Heart Rate Zones is based on the Karvonnen method. It requires to know maximum and minimum heart rates. More precise calculation methods require a lab.
|
||||
//The calculation of the Heart Rate Zones is based on the Karvonen method. It requires to know maximum and minimum heart rates. More precise calculation methods require a lab.
|
||||
//Other methods are even more approximative.
|
||||
let wu = require("widget_utils");
|
||||
wu.hide();
|
||||
|
@ -56,7 +56,7 @@
|
|||
let hr = exsHrmStats.getValue();
|
||||
let hr1 = hr;
|
||||
// These letiables display next and previous HR zone.
|
||||
//get the hrzones right. The calculation of the Heart rate zones here is based on the Karvonnen method
|
||||
//get the hrzones right. The calculation of the Heart rate zones here is based on the Karvonen method
|
||||
//60-70% of HRR+minHR = zone2. //70-80% of HRR+minHR = zone3. //80-90% of HRR+minHR = zone4. //90-99% of HRR+minHR = zone5. //=>99% of HRR+minHR = serious risk of heart attack
|
||||
let minzone2 = hrr * 0.6 + minhr;
|
||||
let maxzone2 = hrr * 0.7 + minhr;
|
||||
|
@ -67,7 +67,7 @@
|
|||
// HR data: large, readable, in the middle of the screen
|
||||
function drawHR() {
|
||||
g.setFontAlign(-1,0,0);
|
||||
g.clearRect(Rdiv(x,11/4),Rdiv(y,2)-25,Rdiv(x,11/4)+50*2,Rdiv(y,2)+25);
|
||||
g.clearRect(Rdiv(x,11/4),Rdiv(y,2)-25,Rdiv(x,11/4)+50*2-14,Rdiv(y,2)+25);
|
||||
g.setColor(g.theme.fg);
|
||||
g.setFont("Vector",50);
|
||||
g.drawString(hr, Rdiv(x,11/4), Rdiv(y,2)+4);
|
||||
|
@ -207,9 +207,9 @@
|
|||
initDraw();
|
||||
|
||||
// check for updates every second.
|
||||
karvonnenInterval = setInterval(function() {
|
||||
if (!isMenuDisplayed && karvonnenActive) updateUI();
|
||||
karvonenInterval = setInterval(function() {
|
||||
if (!isMenuDisplayed && karvonenActive) updateUI();
|
||||
}, 1000);
|
||||
|
||||
return karvonnenInterval;
|
||||
return karvonenInterval;
|
||||
})
|
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"id": "runplus",
|
||||
"name": "Run+",
|
||||
"version": "0.15",
|
||||
"version": "0.16",
|
||||
"description": "Displays distance, time, steps, cadence, pace and more for runners. Based on the Run app, but extended with additional screen for heart rate interval training.",
|
||||
"icon": "app.png",
|
||||
"tags": "run,running,fitness,outdoors,gps,karvonnen",
|
||||
"tags": "run,running,fitness,outdoors,gps,karvonen,karvonnen",
|
||||
"supports": [
|
||||
"BANGLEJS2"
|
||||
],
|
||||
|
@ -29,8 +29,8 @@
|
|||
"url": "settings.js"
|
||||
},
|
||||
{
|
||||
"name": "runplus_karvonnen",
|
||||
"url": "karvonnen.js"
|
||||
"name": "runplus_karvonen",
|
||||
"url": "karvonen.js"
|
||||
}
|
||||
],
|
||||
"data": [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(function(back) {
|
||||
const SETTINGS_FILE = "run.json";
|
||||
const SETTINGS_FILE = "runplus.json";
|
||||
var ExStats = require("exstats");
|
||||
var statsList = ExStats.getList();
|
||||
statsList.unshift({name:"-",id:""}); // add blank menu item
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
0.01: 1st version: saves values to csv
|
||||
0.02: added HTML interface
|
||||
0.03: Added Stop/start recording, change BG color, filesize info
|
||||
|
|
|
@ -9,6 +9,12 @@ Bangle JS1
|
|||
|
||||

|
||||
|
||||
UI for bangleJS1
|
||||

|
||||
|
||||
UI for bangleJS2
|
||||

|
||||
|
||||
Screenshot BJS2
|
||||
|
||||

|
||||
|
@ -30,18 +36,35 @@ Screenshot data file content
|
|||
|
||||
Open and see a temperature in the screen
|
||||
Download the CSV file and process in your favourite spreadsheet software
|
||||
if you have any problem enable the modedebug in code; v_mode_debug=1 or 2
|
||||
|
||||
## Features
|
||||
|
||||
Colours, all inputs , graph, widgets loaded
|
||||
Counter for Times Display
|
||||
- Cross compatibility (JS1,JS2) and widgets compatibility
|
||||
- BG/FG Colour, Export to file and counter of saved records per session
|
||||
- File operations: Info, delete (no yet)
|
||||
|
||||
## Pending/future Features
|
||||
- Buttons layout: btn txt(BJS1) , on screen button (BJS2)
|
||||
- Long press touch to delete file (BJS1,BJS2)
|
||||
- File operations: Delete
|
||||
|
||||
## Controls
|
||||
## Controls/UI
|
||||
- Left area: Back/Exit/launcher
|
||||
- BTN3 (long press)(BJS1): default Exit/kill app
|
||||
|
||||
- BTN1 (BJS2): "Launcher" / open "Messages"
|
||||
- BTN2 (BJS1): "Launcher" / open "Messages"
|
||||
- BTN1 (BJS1): Change FG Color
|
||||
- BTN3 (BJS1): Change BG Color
|
||||
- Right area: Change FG Color
|
||||
- Swipe left: Change BG Color
|
||||
- Swipe right: Increase/Decrease Hour circle/Points
|
||||
|
||||
exit: left side
|
||||
|
||||
|
||||
## Creator
|
||||
|
||||
Daniel Perez
|
||||
For suggestions or feedback
|
||||
https://github.com/dapgo/my_espruino_smartwatch_things
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "tempmonitor",
|
||||
"name": "Temperature monitor",
|
||||
"version": "0.02",
|
||||
"version": "0.03",
|
||||
"description": "Displays the current temperature and stores in a CSV file",
|
||||
"icon": "app.png",
|
||||
"tags": "tool",
|
||||
|
|
|
@ -1,42 +1,69 @@
|
|||
// Temperature monitor that saves a log of measures
|
||||
// standalone ver for developer, to remove testing lines
|
||||
// delimiter ; (excel) or , (oldscool)
|
||||
/* REFACTOR and remove commented code related to
|
||||
SetUI, Layout, and setWatch( function(b) { }, BTN1, { repeat: true, edge:'falling' })
|
||||
*/
|
||||
{
|
||||
var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail
|
||||
//var required for drawing with dynamic screen
|
||||
var rect = Bangle.appRect;
|
||||
var history = [];
|
||||
var readFreq=5000; //ms //PEND add to settings
|
||||
var saveFreq=60000; //ms 1min
|
||||
var readFreq=4000; //ms //PEND add to settings
|
||||
if (v_mode_debug>0) var saveFreq=6000; //ms for testin 6sec
|
||||
else var saveFreq=60000; //ms 1min
|
||||
var v_saveToFile= new Boolean(true); //true save //false
|
||||
//with upload file º is not displayed properly
|
||||
//with upload RAM º is displayed
|
||||
var v_t_symbol="";//ºC
|
||||
var v_saved_entries=0;
|
||||
var filename ="temphistory.csv";
|
||||
var v_filename ="temphistory.csv";
|
||||
var lastMeasure = new String();
|
||||
var v_model=process.env.BOARD;
|
||||
var v_color_erase=g.getBgColor(); //original BG color overwritten on SetVariables
|
||||
var v_color=g.getColor();//original FG color
|
||||
var id_rec_intv; //var for the recording interval
|
||||
|
||||
if (readFreq>saveFreq) console.log("Read refresh freq should be higher than saving");
|
||||
if (v_mode_debug>0) console.log("original BG/FG color="+v_color_erase+" / "+v_color);
|
||||
|
||||
|
||||
|
||||
function SetVariables(){
|
||||
//EMSCRIPTEN,EMSCRIPTEN2
|
||||
if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') {
|
||||
v_font_size1=16;
|
||||
v_font_size2=60;
|
||||
//g.setColor("#0ff"); //light color
|
||||
v_font_size2=50;
|
||||
}else{
|
||||
v_font_size1=11;
|
||||
//Banglejs2 or others
|
||||
v_font_size1=11; //too small?
|
||||
v_font_size2=40;
|
||||
//g.setColor("#000"); //black or dark
|
||||
}
|
||||
//overwriting default BG, is better detect?
|
||||
if (g.theme.dark==1) v_color_erase=0x0000; //dynamic; //bg black
|
||||
else if (g.theme.dark==0) v_color_erase=0xFFFF; //dynamic; //bg white
|
||||
}
|
||||
|
||||
function onTemperature(v_temp) {
|
||||
if (v_mode_debug>1) console.log("v_temp in "+v_temp);
|
||||
//print result
|
||||
function printTemperature(v_temp) {
|
||||
if (v_mode_debug>1) console.log("v_temp in "+v_temp+" entries "+v_saved_entries);
|
||||
ClearBox();
|
||||
//g.setFont("6x8",2).setFontAlign(0,0);
|
||||
g.setFontVector(v_font_size1).setFontAlign(0,0);
|
||||
var x = (rect.x+rect.x2)/2;
|
||||
var x = (rect.x+(rect.x2-60))/2;//-60 space for graph and layout buttons
|
||||
var y = (rect.y+rect.y2)/2 + 20;
|
||||
g.drawString("Records: "+v_saved_entries, x, rect.y+35);
|
||||
g.drawString("Temperature:", x, rect.y+37+v_font_size1);
|
||||
|
||||
if (v_saveToFile==true) {
|
||||
// if (v_mode_debug>0) console.log("prev color="+v_color);
|
||||
printInfo("Recording : "+v_saved_entries, '#CC3333',x,rect.y+30);
|
||||
//g.setColor('#CC3333'); //red
|
||||
// g.drawString("Recording : "+v_saved_entries, x, rect.y+35);
|
||||
//g.setColor(v_color);//restore default color
|
||||
}
|
||||
else printInfo("Rec paused : "+v_saved_entries, v_color,x,rect.y+30);
|
||||
//else g.drawString("Rec paused : "+v_saved_entries, x, rect.y+35);
|
||||
//space for printing info
|
||||
g.drawString("Temperature:", x, rect.y+45+(v_font_size1*2));
|
||||
//dynamic font (g.getWidth() > 200 ? 60 : 40)
|
||||
g.setFontVector(v_font_size2).setFontAlign(0,0);
|
||||
// Avg of temperature readings
|
||||
|
@ -48,33 +75,68 @@ function onTemperature(v_temp) {
|
|||
lastMeasure=avrTemp.toString();
|
||||
if (lastMeasure.length>4) lastMeasure=lastMeasure.substr(0,4);
|
||||
//DRAW temperature in the center
|
||||
g.drawString(" ", x-20, y);
|
||||
g.drawString(v_temp+v_t_symbol, x-20, y);
|
||||
//remove g.drawString(" ", x-20, y);
|
||||
g.drawString(v_temp+v_t_symbol, x, y);
|
||||
g.flip();
|
||||
}
|
||||
// from: BJS2 pressure sensor, BJS1 inbuilt thermistor
|
||||
function drawTemperature() {
|
||||
function getTemperature() {
|
||||
if(v_model.substr(0,10)!='EMSCRIPTEN'){
|
||||
if (Bangle.getPressure) {
|
||||
Bangle.getPressure().then(p =>{if (p) onTemperature(p);});
|
||||
} else onTemperature(E.getTemperature());
|
||||
Bangle.getPressure().then(p =>{if (p) printTemperature(p);});
|
||||
} else printTemperature(E.getTemperature());
|
||||
}
|
||||
else onTemperature(11);//fake temp for emulators
|
||||
else printTemperature(11.25);//fake temperature medition for emulators
|
||||
}
|
||||
|
||||
function saveToFile() {
|
||||
/* Note that it changes BG and also FG to an opposite*/
|
||||
function changeBGcolor(){
|
||||
//pend to refactor
|
||||
if (v_mode_debug>1) console.log("before BG/FG "+v_color_erase+" /"+v_color);
|
||||
v_color_erase=0xFFFF-v_color_erase;
|
||||
v_color=0xFFFF-v_color;
|
||||
if (v_mode_debug>1) console.log("after result BG/FG "+v_color_erase+" /"+v_color);
|
||||
//g.setColor(color_result);
|
||||
g.setBgColor(v_color_erase);// 0 white, 1 black
|
||||
g.setColor(v_color);
|
||||
//move to event?
|
||||
ClearScreen();
|
||||
ClearBox();
|
||||
drawGraph();
|
||||
getTemperature();
|
||||
//setDrawLayout(); //uncomment if layout can work with setUI
|
||||
//g.clear();//impact on widgets
|
||||
}
|
||||
|
||||
function saveToFile(){
|
||||
//input global vars: lastMeasure
|
||||
var a=new Date();
|
||||
var strlastSaveTime=new String();
|
||||
strlastSaveTime=a.toISOString();
|
||||
//strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());;
|
||||
if (v_mode_debug==1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure);
|
||||
if (v_mode_debug>1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure);
|
||||
if (v_saveToFile==true){
|
||||
//write(strlastSaveTime+";"+
|
||||
require("Storage").open(filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n");
|
||||
//var f = require("Storage").open(v_filename,"r");
|
||||
// f=require("Storage").read(v_filename+"\1");//suffix required load completely!!
|
||||
//note that .read uses Storage Class .open uses StorageFile Class , difference in file chunks
|
||||
// if (v_mode_debug>0) console.log("f "+f);
|
||||
var f = require("Storage").open(v_filename,"r");
|
||||
if ((v_mode_debug>0) && (v_saved_entries==0)) console.log("file info:"+f);
|
||||
if (f.len>0) {
|
||||
if (!f) {
|
||||
require("Storage").open(v_filename,"w").write("Month;Day;Time;Temp"+"\n");
|
||||
if (v_mode_debug>0) console.log("not exist but created "+f);
|
||||
}
|
||||
else{
|
||||
require("Storage").open(v_filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n");
|
||||
//(getTime()+",");
|
||||
v_saved_entries=v_saved_entries+1;
|
||||
if (v_mode_debug>1) console.log("append to already exist "+f.name+" , "+v_saved_entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (v_mode_debug>0) console.log("recording mode stopped");
|
||||
}
|
||||
|
||||
function drawGraph(){
|
||||
|
@ -83,17 +145,19 @@ function drawGraph(){
|
|||
transparent : 0,
|
||||
buffer : require("heatshrink").decompress(atob("AEFt2AMKm3bsAMJjdt23ABhEB+/7tgaJ///DRUP//7tuADRP923YDRXbDRfymwaJhu/koaK7eyiwaK3cLDRlWDRY1NKBY1Ztu5kjmJg3cyVI7YMHgdu5Mkyu2fxHkyVJjdgDRFJkmRDRPsDQNbDQ5QBGoONKBJrBoxQIQwO2eRcbtu24AMIFIQLJAH4AMA=="))
|
||||
};
|
||||
g.drawImage(img_obj_thermo,rect.x2-50,rect.y2/2);
|
||||
g.drawImage(img_obj_thermo,rect.x2-60,rect.y2/2);
|
||||
g.flip();
|
||||
}
|
||||
function ClearScreen(){
|
||||
//avoid widget areas
|
||||
g.reset(1).clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24);
|
||||
g.setBgColor(v_color_erase);
|
||||
g.clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24);
|
||||
g.flip();
|
||||
}
|
||||
function ClearBox(){
|
||||
//custom boxarea , left space for static graph at right
|
||||
g.reset(1).clearRect(rect.x, rect.y+24, rect.x2-50, rect.y2-24);
|
||||
g.setBgColor(v_color_erase);
|
||||
g.clearRect(rect.x, rect.y+24, rect.x2-60, rect.y2-24);
|
||||
g.flip();
|
||||
}
|
||||
function introPage(){
|
||||
|
@ -109,30 +173,140 @@ function introPage(){
|
|||
g.drawString("Read freq(ms): "+readFreq, x, y );
|
||||
g.drawString("Save to file: "+v_saveToFile, x, y+ ((v_font_size1*1)+2) );
|
||||
g.drawString("Save freq(ms):"+saveFreq, x, y+((v_font_size1*2)+2) );
|
||||
fr=require("Storage").read(filename+"\1");//suffix required
|
||||
if (fr) g.drawString("Current filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) );
|
||||
fr=require("Storage").read(v_filename+"\1");//suffix required
|
||||
if (fr) g.drawString("Filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) );
|
||||
else g.drawString("File not exist", x, y+((v_font_size1*3)+2));
|
||||
}
|
||||
//MAIN
|
||||
Bangle.loadWidgets();
|
||||
Bangle.setUI({
|
||||
function printInfo(pmsg, pcolor,px,py){
|
||||
g.setColor(pcolor);
|
||||
g.setFontVector(v_font_size1).setFontAlign(0,0);
|
||||
g.drawString(pmsg, px,py+v_font_size1);
|
||||
g.setColor(v_color);//restore default color
|
||||
}
|
||||
function toggleRecMode(duration, exectime){
|
||||
//bydefault float, standard epoch requires *1000
|
||||
if (v_mode_debug>0) console.log("duration"+duration);
|
||||
if (duration>2) { //delete file
|
||||
var x = (rect.x+(rect.x2-60))/2;
|
||||
printInfo("Deleting file",'#CC3333',x, rect.y+32+v_font_size1);
|
||||
// g.setColor('#CC3333'); //red
|
||||
|
||||
//too long "Deleting file: "+v_filename,
|
||||
// for StorageFiles created with require("Storage").open(filename, ...)
|
||||
//require("Storage").erase(v_filename);
|
||||
//TODO refactor in a new function
|
||||
//var mifile = require("Storage").open(v_filename,"w");
|
||||
var mifile = require("Storage").open("temphistory.csv","w");
|
||||
var v_output=mifile.erase();
|
||||
//mifile.StorageFile.erase();
|
||||
if (v_mode_debug>0) console.log("output"+v_output);
|
||||
setTimeout(function() { if (v_mode_debug>0) console.log("pause for 1 sec");},1000);
|
||||
return; //leave this function
|
||||
}
|
||||
if (v_saveToFile) v_saveToFile=false;
|
||||
else v_saveToFile=true;
|
||||
if (v_mode_debug>0) console.log("recording? "+v_saveToFile);
|
||||
setRecordingFreq();
|
||||
}
|
||||
|
||||
function setRecordingFreq(){
|
||||
if (v_saveToFile==true) { //TODO now start on false btn will no enable
|
||||
id_rec_intv=setInterval(function() {
|
||||
saveToFile();
|
||||
}, saveFreq); //ms
|
||||
if (v_mode_debug>0) console.log("interval id / frq"+id_rec_intv+" / "+saveFreq);
|
||||
}
|
||||
else if (id_rec_intv){
|
||||
clearInterval(id_rec_intv);
|
||||
if (v_mode_debug>0) console.log("rec interval removed, id "+id_rec_intv);
|
||||
id_rec_intv=0; // to reset var
|
||||
}
|
||||
}
|
||||
|
||||
function UserInput(){
|
||||
//theoretically incompatible with Layout
|
||||
Bangle.setUI({
|
||||
mode : "custom",
|
||||
back : function() {load();}
|
||||
});
|
||||
//adds a back icon on top widget area
|
||||
back : function() {load();},
|
||||
//touch : function(n,e) {}, // optional - handler for 'touch' events
|
||||
// righ/Left 1/-1 , updown
|
||||
swipe : function(dir_rl,dir_ud) {
|
||||
if(dir_rl == 1) {
|
||||
if (v_mode_debug>0) console.log("swipe right: ");
|
||||
getFileInfo(v_filename);
|
||||
}
|
||||
else if (dir_rl == -1){
|
||||
if (v_mode_debug>0) console.log("swipe left: ");
|
||||
changeBGcolor();
|
||||
}
|
||||
},
|
||||
touch : function(tzone,tobj){
|
||||
if ((process.env.HWVERSION == 2)&&(v_mode_debug>0)){
|
||||
console.log("tobj x,y,type : "+tobj.x+" "+tobj.y+" "+tobj.type);
|
||||
}
|
||||
switch(tzone){
|
||||
//case 1: //left , back managed by setUI
|
||||
case 2: // right disable/enable recording
|
||||
toggleRecMode(0); //toggleRecMode(duration, exectime)
|
||||
break;
|
||||
// case 3: console.log("Touch 3 aka 1+2 not for BJS1 emul");//center 1+2
|
||||
// break;
|
||||
}
|
||||
},
|
||||
//inferior to
|
||||
btn : function(btn) {
|
||||
if(btn == 1) {
|
||||
if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') toggleRecMode(1); //console.log("btn1 BJS1");
|
||||
else mainBtnShortcut(); //console.log("btn1 BJS2");
|
||||
}
|
||||
else if (btn == 2) mainBtnShortcut(); //console.log("btn2 BJS1");
|
||||
else if (btn == 3) changeBGcolor(); //console.log("btn3 BJS1");
|
||||
}
|
||||
}); //endof setUI
|
||||
|
||||
}
|
||||
|
||||
function mainBtnShortcut() {
|
||||
//if messages app installed shortcut otherwise default access to launcher
|
||||
if (require("Storage").read("messagegui.app.js")===undefined)
|
||||
{
|
||||
if (require("Storage").read("messagelist.app.js")===undefined) Bangle.showLauncher(); // implies btn2(js1) btn(js2)- launcher
|
||||
else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagelist.app.js");
|
||||
else load("messagelist.app.js");
|
||||
}
|
||||
else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagegui.app.js");
|
||||
else load("messagegui.app.js");
|
||||
}
|
||||
|
||||
|
||||
// Show file size
|
||||
function getFileInfo(v_filename) {
|
||||
var f = require("Storage").open(v_filename,"r");
|
||||
//todo refactor and reuse common code
|
||||
g.setFontVector(v_font_size1).setFontAlign(0,0);
|
||||
var x = (rect.x+(rect.x2-60))/2;
|
||||
printInfo("file size:"+f.len,v_color,x, rect.y+32+v_font_size1);
|
||||
// g.drawString("file size:"+f.len, x, rect.y+37+v_font_size1);
|
||||
if (v_mode_debug>0) console.log("file "+v_filename+" size: "+f.len);
|
||||
}// not used
|
||||
|
||||
|
||||
//MAIN
|
||||
SetVariables();
|
||||
Bangle.loadWidgets();
|
||||
|
||||
ClearScreen();
|
||||
introPage();
|
||||
|
||||
//setDrawLayout(); //uncomment if layout can work with setUI
|
||||
|
||||
UserInput(); //inc SetUI and back icon
|
||||
|
||||
setInterval(function() {
|
||||
drawTemperature();
|
||||
getTemperature();
|
||||
}, readFreq); //ms
|
||||
|
||||
if (v_saveToFile==true) {
|
||||
setInterval(function() {
|
||||
saveToFile();
|
||||
}, saveFreq); //ms
|
||||
}
|
||||
setTimeout(ClearScreen, 3500);
|
||||
setTimeout(drawGraph,4000);
|
||||
setTimeout(drawTemperature,4500);
|
||||
setRecordingFreq();
|
||||
|
||||
}
|
|
@ -1 +1 @@
|
|||
{"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.01","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"}
|
||||
{"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.03","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"}
|
|
@ -6,11 +6,11 @@
|
|||
);
|
||||
const iconWidth = 18;
|
||||
|
||||
function draw(this: { x: number; y: number }) {
|
||||
function draw(this: { x?: number; y?: number }) {
|
||||
g.reset();
|
||||
if (Bangle.isCharging()) {
|
||||
g.setColor('#FD0');
|
||||
g.drawImage(icon, this.x + 1, this.y + 1, {
|
||||
g.drawImage(icon, this.x! + 1, this.y! + 1, {
|
||||
scale: 0.6875,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,3 +6,6 @@
|
|||
Update to match the default alarm widget, and not show itself when an alarm is hidden.
|
||||
0.04: Fix check for active alarm
|
||||
0.05: Convert Yes/No On/Off in settings to checkboxes
|
||||
0.06: Remember next alarm to reduce calculation amount
|
||||
Redraw only every hour when no alarm in next 24h
|
||||
0.07: Fix when no alarms are present
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widalarmeta",
|
||||
"name": "Alarm & Timer ETA",
|
||||
"shortName": "Alarm ETA",
|
||||
"version": "0.05",
|
||||
"version": "0.07",
|
||||
"description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -1,24 +1,45 @@
|
|||
(() => {
|
||||
require("Font5x9Numeric7Seg").add(Graphics);
|
||||
const alarms = require("Storage").readJSON("sched.json",1) || [];
|
||||
const config = Object.assign({
|
||||
maxhours: 24,
|
||||
drawBell: false,
|
||||
showSeconds: 0, // 0=never, 1=only when display is unlocked, 2=for less than a minute
|
||||
}, require("Storage").readJSON("widalarmeta.json",1) || {});
|
||||
|
||||
function draw() {
|
||||
const times = alarms
|
||||
.map(alarm =>
|
||||
alarm.hidden !== true
|
||||
&& require("sched").getTimeToAlarm(alarm)
|
||||
)
|
||||
.filter(a => a !== undefined);
|
||||
const next = times.length > 0 ? Math.min.apply(null, times) : 0;
|
||||
function getNextAlarm(date) {
|
||||
const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true);
|
||||
WIDGETS["widalarmeta"].numActiveAlarms = alarms.length;
|
||||
if (alarms.length > 0) {
|
||||
const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY);
|
||||
const eta = Math.min.apply(null, times);
|
||||
if (eta !== Number.POSITIVE_INFINITY) {
|
||||
const idx = times.indexOf(eta);
|
||||
const alarm = alarms[idx];
|
||||
delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory
|
||||
return alarm;
|
||||
}
|
||||
}
|
||||
} // getNextAlarm
|
||||
|
||||
function draw(fromInterval) {
|
||||
if (this.nextAlarm === undefined) {
|
||||
let alarm = getNextAlarm();
|
||||
if (alarm === undefined) {
|
||||
// try again with next hour
|
||||
const nextHour = new Date();
|
||||
nextHour.setHours(nextHour.getHours()+1);
|
||||
alarm = getNextAlarm(nextHour);
|
||||
}
|
||||
if (alarm !== undefined) {
|
||||
this.nextAlarm = alarm;
|
||||
}
|
||||
}
|
||||
const next = this.nextAlarm !== undefined ? require("sched").getTimeToAlarm(this.nextAlarm) : 0;
|
||||
|
||||
let calcWidth = 0;
|
||||
let drawSeconds = false;
|
||||
|
||||
if (next > 0 && next < config.maxhours*60*60*1000) {
|
||||
if (next > 0 && next <= config.maxhours*60*60*1000) {
|
||||
const hours = Math.floor((next-1) / 3600000).toString();
|
||||
const minutes = Math.floor(((next-1) % 3600000) / 60000).toString();
|
||||
const seconds = Math.floor(((next-1) % 60000) / 1000).toString();
|
||||
|
@ -39,10 +60,14 @@
|
|||
if (drawSeconds) {
|
||||
calcWidth += 3*5;
|
||||
}
|
||||
} else if (config.drawBell && alarms.some(alarm=>alarm.on&&(alarm.hidden!==true))) {
|
||||
// next alarm too far in future, draw only widalarm bell
|
||||
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||
this.bellVisible = false;
|
||||
} else if (config.drawBell && this.numActiveAlarms > 0) {
|
||||
calcWidth = 24;
|
||||
// next alarm too far in future, draw only widalarm bell
|
||||
if (this.bellVisible !== true || fromInterval !== true) {
|
||||
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
|
||||
this.bellVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.width !== calcWidth) {
|
||||
|
@ -51,8 +76,8 @@
|
|||
Bangle.drawWidgets();
|
||||
}
|
||||
|
||||
// redraw next full minute or second
|
||||
const period = drawSeconds ? 1000 : 60000;
|
||||
// redraw next hour when no alarm else full minute or second
|
||||
const period = next === 0 ? 3600000 : (drawSeconds ? 1000 : 60000);
|
||||
let timeout = next > 0 ? next % period : period - (Date.now() % period);
|
||||
if (timeout === 0) {
|
||||
timeout += period;
|
||||
|
@ -62,8 +87,8 @@
|
|||
clearTimeout(this.timeoutId);
|
||||
}
|
||||
this.timeoutId = setTimeout(()=>{
|
||||
this.timeoutId = undefined;
|
||||
this.draw();
|
||||
WIDGETS["widalarmeta"].timeoutId = undefined;
|
||||
WIDGETS["widalarmeta"].draw(true);
|
||||
}, timeout);
|
||||
} /* draw */
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
Show difference of last measurement to pressure average of the the last three hours in the widget
|
||||
Only use valid pressure values
|
||||
0.06: Fix exception
|
||||
0.07: Ensure barometer gets turned off after a few readings (isBarometerOn broken in 2v16)
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widbaroalarm",
|
||||
"name": "Barometer Alarm Widget",
|
||||
"shortName": "Barometer Alarm",
|
||||
"version": "0.06",
|
||||
"version": "0.07",
|
||||
"description": "A widget that can alarm on when the pressure reaches defined thresholds.",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -211,19 +211,8 @@ function calculcate3hAveragePressure() {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
turn on barometer power
|
||||
take multiple measurements
|
||||
sort the results
|
||||
take the middle one (median)
|
||||
turn off barometer power
|
||||
*/
|
||||
function getPressureValue() {
|
||||
if (stop)
|
||||
return;
|
||||
function barometerPressureHandler(e) {
|
||||
const MEDIANLENGTH = 20;
|
||||
Bangle.setBarometerPower(true, "widbaroalarm");
|
||||
Bangle.on('pressure', function(e) {
|
||||
while (currentPressures.length > MEDIANLENGTH)
|
||||
currentPressures.pop();
|
||||
|
||||
|
@ -242,13 +231,24 @@ function getPressureValue() {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setTimeout(function() { turnOff(); }, 30000);
|
||||
/*
|
||||
turn on barometer power
|
||||
take multiple measurements
|
||||
sort the results
|
||||
take the middle one (median)
|
||||
turn off barometer power
|
||||
*/
|
||||
function getPressureValue() {
|
||||
if (stop) return;
|
||||
Bangle.setBarometerPower(true, "widbaroalarm");
|
||||
Bangle.on('pressure', barometerPressureHandler);
|
||||
setTimeout(turnOff, 30000);
|
||||
}
|
||||
|
||||
function turnOff() {
|
||||
if (Bangle.isBarometerOn())
|
||||
Bangle.removeListener('pressure', barometerPressureHandler);
|
||||
Bangle.setBarometerPower(false, "widbaroalarm");
|
||||
}
|
||||
|
||||
|
|
|
@ -7,3 +7,4 @@
|
|||
0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on
|
||||
0.09: Misc speed/memory tweaks
|
||||
0.10: Color changes due to the battery level
|
||||
0.11: Change level for medium charge (50% -> 40%), and darken color on light themes as yellow was almost invisible
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "widbat",
|
||||
"name": "Battery Level Widget",
|
||||
"version": "0.10",
|
||||
"version": "0.11",
|
||||
"description": "Show the current battery level and charging status in the top right of the clock",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
g.setColor(g.theme.fg).fillRect(x,y+2,x+s-4,y+21).clearRect(x+2,y+4,x+s-6,y+19).fillRect(x+s-3,y+10,x+s,y+14);
|
||||
var battery = E.getBattery();
|
||||
if(battery < 20) {g.setColor("#f00");}
|
||||
else if (battery < 50) {g.setColor("#ff0");}
|
||||
else if (battery < 40) {g.setColor(g.theme.dark ? "#ff0" : "#f80");}
|
||||
else {g.setColor("#0f0");}
|
||||
g.fillRect(x+4,y+6,x+4+battery*(s-12)/100,y+17);
|
||||
}};
|
||||
|
|
|
@ -15,3 +15,4 @@
|
|||
0.16: Increase screen update rate when charging
|
||||
0.17: Add option 'Remove Jitter'='Drop only' to prevent percentage from getting up again when not charging
|
||||
Add option to disable vibration when charger connects
|
||||
0.18: Only redraw when values change
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"id": "widbatpc",
|
||||
"name": "Battery Level Widget (with percentage)",
|
||||
"shortName": "Battery Widget",
|
||||
"version": "0.17",
|
||||
"version": "0.18",
|
||||
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
return changed;
|
||||
}
|
||||
|
||||
function draw() {
|
||||
function draw(fromInterval) {
|
||||
// if hidden, don't draw
|
||||
if (!WIDGETS["batpc"].width) return;
|
||||
// else...
|
||||
|
@ -103,6 +103,14 @@
|
|||
l = prevMin;
|
||||
}
|
||||
}
|
||||
|
||||
if (fromInterval === true && this.prevLevel === l && this.prevCharging === Bangle.isCharging()) {
|
||||
return; // unchanged, do nothing
|
||||
}
|
||||
|
||||
this.prevLevel = l;
|
||||
this.prevCharging = Bangle.isCharging();
|
||||
|
||||
const c = levelColor(l);
|
||||
|
||||
if (Bangle.isCharging() && setting('charger')) {
|
||||
|
@ -173,7 +181,7 @@
|
|||
if (on) update();
|
||||
});
|
||||
|
||||
var id = setInterval(()=>WIDGETS["batpc"].draw(), intervalLow);
|
||||
var id = setInterval(()=>WIDGETS["batpc"].draw(true), intervalLow);
|
||||
|
||||
WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload};
|
||||
setWidth();
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
0.01: First commit
|
||||
0.02: Add tap-to-lock functionality
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"id": "widlockunlock",
|
||||
"name": "Lock/Unlock Widget",
|
||||
"version": "0.01",
|
||||
"description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise",
|
||||
"version": "0.02",
|
||||
"description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise. Tap to lock the lcd",
|
||||
"icon": "widget.png",
|
||||
"type": "widget",
|
||||
"tags": "widget,lock",
|
||||
|
|
|
@ -1,5 +1,28 @@
|
|||
Bangle.on("lockunlock", function() {
|
||||
Bangle.drawWidgets();
|
||||
Bangle.on("lock", () => Bangle.drawWidgets());
|
||||
|
||||
Bangle.on('touch', (_btn, xy) => {
|
||||
const oversize = 5;
|
||||
|
||||
const w = WIDGETS.lockunlock;
|
||||
|
||||
const x = xy.x;
|
||||
const y = xy.y;
|
||||
|
||||
if(w.x - oversize <= x && x < w.x + 14 + oversize
|
||||
&& w.y - oversize <= y && y < w.y + 24 + oversize)
|
||||
{
|
||||
Bangle.setLocked(true);
|
||||
|
||||
const backlightTimeout = Bangle.getOptions().backlightTimeout; // ms
|
||||
|
||||
// seems to be a race/if we don't give the firmware enough time,
|
||||
// it won't timeout the backlight and we'll restore it in our setTimeout below
|
||||
Bangle.setOptions({ backlightTimeout: 100 });
|
||||
|
||||
setTimeout(() => {
|
||||
Bangle.setOptions({ backlightTimeout });
|
||||
}, 300);
|
||||
}
|
||||
});
|
||||
WIDGETS["lockunlock"]={area:"tl",sortorder:10,width:14,draw:function(w) {
|
||||
g.reset().drawImage(atob(Bangle.isLocked() ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x+1, w.y+3);
|
||||
|
|
|
@ -44,6 +44,7 @@ declare module ClockInfo {
|
|||
w: number,
|
||||
h: number,
|
||||
draw(itm: MenuItem, info: Item, options: InteractiveOptions): void,
|
||||
app?: string, // used to remember clock_info locations, per app
|
||||
};
|
||||
|
||||
type InteractiveOptions =
|
||||
|
|
|
@ -83,7 +83,10 @@ type WidgetArea = "tl" | "tr" | "bl" | "br";
|
|||
type Widget = {
|
||||
area: WidgetArea;
|
||||
width: number;
|
||||
draw: (this: { x: number; y: number }) => void;
|
||||
sortorder?: number;
|
||||
draw: (this: Widget, w: Widget) => void;
|
||||
x?: number;
|
||||
y?: number;
|
||||
};
|
||||
declare const WIDGETS: { [key: string]: Widget };
|
||||
|
||||
|
@ -8688,6 +8691,15 @@ interface ObjectConstructor {
|
|||
*/
|
||||
entries(object: any): Array<[string, any]>;
|
||||
|
||||
/**
|
||||
* Transforms an array of key-value pairs into an object
|
||||
*
|
||||
* @param {any} entries - An array of `[key,value]` pairs to be used to create an object
|
||||
* @returns {any} An object containing all the specified pairs
|
||||
* @url http://www.espruino.com/Reference#l_Object_fromEntries
|
||||
*/
|
||||
fromEntries(entries: any): any;
|
||||
|
||||
/**
|
||||
* Creates a new object with the specified prototype object and properties.
|
||||
* properties are currently unsupported.
|
||||
|
@ -8709,6 +8721,15 @@ interface ObjectConstructor {
|
|||
*/
|
||||
getOwnPropertyDescriptor(obj: any, name: any): any;
|
||||
|
||||
/**
|
||||
* Get information on all properties in the object (from `Object.getOwnPropertyDescriptor`), or just `{}` if no properties
|
||||
*
|
||||
* @param {any} obj - The object
|
||||
* @returns {any} An object containing all the property descriptors of an object
|
||||
* @url http://www.espruino.com/Reference#l_Object_getOwnPropertyDescriptors
|
||||
*/
|
||||
getOwnPropertyDescriptors(obj: any): any;
|
||||
|
||||
/**
|
||||
* Add a new property to the Object. 'Desc' is an object with the following fields:
|
||||
* * `configurable` (bool = false) - can this property be changed/deleted (not
|
||||
|
@ -8945,32 +8966,32 @@ interface Function {
|
|||
/**
|
||||
* This executes the function with the supplied 'this' argument and parameters
|
||||
*
|
||||
* @param {any} this - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} thisArg - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} params - Optional Parameters
|
||||
* @returns {any} The return value of executing this function
|
||||
* @url http://www.espruino.com/Reference#l_Function_call
|
||||
*/
|
||||
call(this: any, ...params: any[]): any;
|
||||
call(thisArg: any, ...params: any[]): any;
|
||||
|
||||
/**
|
||||
* This executes the function with the supplied 'this' argument and parameters
|
||||
*
|
||||
* @param {any} this - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} thisArg - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} args - Optional Array of Arguments
|
||||
* @returns {any} The return value of executing this function
|
||||
* @url http://www.espruino.com/Reference#l_Function_apply
|
||||
*/
|
||||
apply(this: any, args: any): any;
|
||||
apply(thisArg: any, args: ArrayLike<any>): any;
|
||||
|
||||
/**
|
||||
* This executes the function with the supplied 'this' argument and parameters
|
||||
*
|
||||
* @param {any} this - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} thisArg - The value to use as the 'this' argument when executing the function
|
||||
* @param {any} params - Optional Default parameters that are prepended to the call
|
||||
* @returns {any} The 'bound' function
|
||||
* @url http://www.espruino.com/Reference#l_Function_bind
|
||||
*/
|
||||
bind(this: any, ...params: any[]): any;
|
||||
bind(thisArg: any, ...params: any[]): any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue