Merge branch 'master' of https://github.com/pinq-/BangleApps
|
@ -0,0 +1 @@
|
|||
E.toArrayBuffer(atob("MDADAAAAHA4HHAAAHA4HA4HA4HAAAAA4//////AAH//////6///AAAA///6//9AAV/////////XAAAA//////6AAv//X//////4AAAA//////4AA////X/////4AAAA//////4AA/////6////4AAAA//////4AA///6vX///v4AAAAAA////4AA///4A//6//AAAAAAF///64AAHA4CFX////AAAAAAH//X/oAAAAAAH6///4AAAAAAH////AAAAAAAH////QAAAAAAH////AAAAAAA/////AAAAAAAH////AAAAAAC////4AAAAAAAH////AAAAAAH////4AAAAAAA6v///AAAAAA//X/9QAAAAAAA////VAAAAAA////4AAAAAAAA////4AAAAAH////4AAAAAAAA////4AAAAA/6///AAAAAAAAA////4AAAAA////6AAAAAAAAF////4AAAAH/X/94AAAAAAAAH/X//oAAAAX////AAAAAAAAAH////AAAAA/////AAAAAAAAAH////AEQAB+///4AwEAAAAAAH////AigAH////4EUGEAAAAAX////A0GA///3/AmEUigAAAAjGMYxEw0AxxGOIGg0w0igAAGikUwmGmmgwEUwmmGmk0wwAAmmmmmmmGmmgimmmmmmmGmgAGmmmGgGmmmmAmmmmiE0w00wAE0000wE000wwmmmmiA0000wAE00U0AGmmmmA0000wE0U00wAAAAAAAmmmmmAAAAAAGmmmmAAAAAAAE0000wAAAAAE00U00AAAAAACk0000QAAAAAmmmmmgAAAAAAGmmmmigAAAAA00000AAAAAAA00000UAAAAAmmmmmEAAAAAA000w00AAAAAGmmmmmAAAAAAE00000QAAAAE0U000wAAAAAA00000wAAAAA000mmiAAAAAAmmmmmiAAAAAmimmmkQAAAAAGmmmmmAAAAAE00000QAAAAAA00000wmEwmAmmmmmmEwmEwAE0000w00000wmmmmmmimmmgAGmmmmmmmmmGEw00mmmmmmmgAGmmmmmmmmmGE0w00000000AA0000U000mmmA000000000wwAGmmmmmmmmmEU0GmmmmmmmmAAAAiAEACgAECAAgCEAAiAEAAA"))
|
|
@ -0,0 +1,107 @@
|
|||
var settings = Object.assign({
|
||||
// default values
|
||||
showWidgets: false,
|
||||
alternativeColor: false,
|
||||
}, require('Storage').readJSON("ashadyclock.json", true) || {});
|
||||
|
||||
let drawTimeout;
|
||||
// schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
draw();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}
|
||||
|
||||
let palBottom;
|
||||
if (settings.alternativeColor) {
|
||||
palBottom = new Uint16Array(E.toArrayBuffer(E.toFlatString(new Uint16Array([
|
||||
g.toColor("#000"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#0FF"),
|
||||
g.toColor("#0FF"),
|
||||
g.toColor("#00F"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#00F"),
|
||||
g.toColor("#000")
|
||||
]).buffer)));
|
||||
} else {
|
||||
palBottom = new Uint16Array(E.toArrayBuffer(E.toFlatString(new Uint16Array([
|
||||
g.toColor("#000"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#F00"),
|
||||
g.toColor("#FF0"),
|
||||
g.toColor("#00F"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#FF0"),
|
||||
g.toColor("#000")
|
||||
]).buffer)));
|
||||
}
|
||||
|
||||
let palTop = new Uint16Array(E.toArrayBuffer(E.toFlatString(new Uint16Array([
|
||||
g.toColor("#FFF"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#FFF"),
|
||||
g.toColor("#FFF"),
|
||||
g.toColor("#00F"),
|
||||
g.toColor("#000"),
|
||||
g.toColor("#FFF"),
|
||||
g.toColor("#000"),
|
||||
]).buffer)));
|
||||
|
||||
let xOffset = (g.getWidth() - 176) / 2;
|
||||
let yOffset = (g.getHeight() - 176) / 2;
|
||||
|
||||
function drawTop(d0, d1) {
|
||||
if (settings.showWidgets && g.getHeight()<=176) {
|
||||
drawNumber(d1, 82 + xOffset, 24 + yOffset, palTop, {scale: 0.825});
|
||||
drawNumber(d0, 13 + xOffset, 24 + yOffset, palTop, {scale: 0.825});
|
||||
} else {
|
||||
drawNumber(d1, 80, 0, palTop);
|
||||
drawNumber(d0, -1, 0, palTop);
|
||||
}
|
||||
}
|
||||
|
||||
function drawBottom(d0, d1) {
|
||||
if (settings.showWidgets && g.getHeight()<=176) {
|
||||
drawNumber(d1, 82 + xOffset, 92 + yOffset, palBottom, {scale: 0.825});
|
||||
drawNumber(d0, 13 + xOffset, 92 + yOffset, palBottom, {scale: 0.825});
|
||||
} else {
|
||||
drawNumber(d1, 80, 75, palBottom);
|
||||
drawNumber(d0, -1, 75, palBottom);
|
||||
}
|
||||
}
|
||||
|
||||
function drawNumber(number, x, y, palette, options) {
|
||||
let image =
|
||||
{
|
||||
width : 98, height : 100, bpp : 3,
|
||||
transparent: 4,
|
||||
buffer : require("Storage").read("ashadyclock." + number +".bin")
|
||||
};
|
||||
image.palette = palette;
|
||||
g.drawImage(image, x, y, options);
|
||||
}
|
||||
|
||||
function draw() {
|
||||
let d = new Date();
|
||||
g.clearRect(0, settings.showWidgets ? 24 : 0, g.getWidth(),g.getHeight());
|
||||
|
||||
drawBottom(Math.floor(d.getMinutes()/10), d.getMinutes() % 10);
|
||||
drawTop(Math.floor(d.getHours()/10), d.getHours() % 10);
|
||||
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
g.clear();
|
||||
// draw immediately at first
|
||||
draw();
|
||||
|
||||
// Show launcher when middle button pressed
|
||||
Bangle.setUI("clock");
|
||||
|
||||
if(settings.showWidgets) {
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
}
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1,27 @@
|
|||
{ "id": "ashadyclock",
|
||||
"name": "A Shady Clock",
|
||||
"shortName":"Shady Clk",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"description": "A nice clock with drop shadow. Hours and minutes. Configure color and widgets in settings. Create any color combination with the existing images by changing only the app color values.",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"screenshots": [{"url":"screenshot-1.png"},{"url":"screenshot.png"}],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"ashadyclock.app.js","url":"app.js"},
|
||||
{"name":"ashadyclock.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"ashadyclock.0.bin","url":"0.bin"},
|
||||
{"name":"ashadyclock.1.bin","url":"1.bin"},
|
||||
{"name":"ashadyclock.2.bin","url":"2.bin"},
|
||||
{"name":"ashadyclock.3.bin","url":"3.bin"},
|
||||
{"name":"ashadyclock.4.bin","url":"4.bin"},
|
||||
{"name":"ashadyclock.5.bin","url":"5.bin"},
|
||||
{"name":"ashadyclock.6.bin","url":"6.bin"},
|
||||
{"name":"ashadyclock.7.bin","url":"7.bin"},
|
||||
{"name":"ashadyclock.8.bin","url":"8.bin"},
|
||||
{"name":"ashadyclock.9.bin","url":"9.bin"},
|
||||
{"name":"ashadyclock.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [{"name":"ashadyclock.json"}]
|
||||
}
|
After Width: | Height: | Size: 1.4 KiB |
After Width: | Height: | Size: 956 B |
|
@ -0,0 +1,32 @@
|
|||
(function(back) {
|
||||
var FILE = "ashadyclock.json";
|
||||
// Load settings
|
||||
var settings = Object.assign({
|
||||
showWidgets: false,
|
||||
alternativeColor: false,
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
|
||||
// Show the menu
|
||||
E.showMenu({
|
||||
"" : { "title" : "Shady Clck" },
|
||||
"< Back" : () => back(),
|
||||
'Show Widgets': {
|
||||
value: !!settings.showWidgets, // !! converts undefined to false
|
||||
onchange: v => {
|
||||
settings.showWidgets = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
'Blue Color': {
|
||||
value: !!settings.alternativeColor, // !! converts undefined to false
|
||||
onchange: v => {
|
||||
settings.alternativeColor = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
});
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
|
@ -0,0 +1,23 @@
|
|||
# Delayed Locking
|
||||
|
||||
Delay the locking of the touchscreen to 5 seconds after the backlight turns off. Giving you the chance to interact with the watch without having to press the hardware button again.
|
||||
|
||||
## Usage
|
||||
|
||||
Just install and the behavior is tweaked at boot time.
|
||||
|
||||
## Features
|
||||
|
||||
- respects the LCD Timeout and Brightness as configured in the settings app.
|
||||
|
||||
## Requests
|
||||
|
||||
Tag @thyttan in an issue to https://gitbub.com/espruino/BangleApps/issues to report problems or suggestions.
|
||||
|
||||
## Creator
|
||||
|
||||
thyttan
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Inspired by the conversation between Gordon Williams and user156427 linked here: https://forum.espruino.com/conversations/392219/
|
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
let backlightTimeout = Bangle.getOptions().backlightTimeout;
|
||||
let brightness = require("Storage").readJSON("setting.json", true);
|
||||
brightness = brightness?brightness.brightness:1;
|
||||
|
||||
Bangle.setOptions({
|
||||
backlightTimeout: backlightTimeout,
|
||||
lockTimeout: backlightTimeout+5000
|
||||
});
|
||||
|
||||
let turnLightsOn = (_,numOrObj)=>{
|
||||
if (!Bangle.isBacklightOn()) {
|
||||
Bangle.setLCDPower(brightness);
|
||||
if (typeof numOrObj !== "number") E.stopEventPropagation(); // Touches will not be passed on to other listeners, but swipes will.
|
||||
}
|
||||
};
|
||||
|
||||
setWatch(turnLightsOn, BTN1, { repeat: true, edge: 'rising' });
|
||||
Bangle.prependListener("swipe", turnLightsOn);
|
||||
Bangle.prependListener("touch", turnLightsOn);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{ "id": "delaylock",
|
||||
"name": "Delayed Locking",
|
||||
"version":"0.01",
|
||||
"description": "Delay the locking of the screen to 5 seconds after the backlight turns off.",
|
||||
"icon": "app.png",
|
||||
"tags": "settings, configuration, backlight, touchscreen, screen",
|
||||
"type": "bootloader",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"delaylock.boot.js","url":"boot.js"}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
0.01: New Clock Nifty A ++ >> adding more information on the right side of the clock
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# Nifty-A ++ Clock
|
||||
|
||||
This is the clock:
|
||||
|
||||

|
||||
|
||||
The week number (ISO8601) can be turned off in settings (default is `On`)
|
||||
Weather and Steps can be also turned off in settings.
|
||||
|
||||

|
||||
|
||||
Based on the # Nifty-A Clock by @alessandrococco
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwwkEIf4A5gX/+AGEn//mIWLgP/C4gGCAAMgC5UvC4sDC4YICkIhBgMQiEBE4Uxn4XDj//iEAn/yA4ICBgUikEikYXBBAIXEn/xJYURAYMygERkQHBiYLBKYIXF+AVDC4czgUSmIXBCQgED+ZeBR4YXBLYICDC5CPGC4IAIC40zmaPDC4MSLQQXK+ayCR4QXCiRoEC44ECh4bCC4MTiTDBC6ZHOC5B3NLYcvC4kBgL5BAAUikT+BfIIrB/8ykf/eYQXBkUTI4cBW4YQCgQGDmAXDkJfEC46GBAoJKCR4geCAAMRAAZRDAoIODO4UBPRIAJR5QXWgKNCTApNDC5Mv/6/DAwR3GAAyHCC4anJIo3/+bvEa4Uia4oXHkEvC4cvIgUf+YXKHYIvEAgcPC5QSGC5UBSwYXJLYQXFkUhgABBC5Ef/4mBl4XEmETmIXKgaXBmYCBC4cTkMxiQXJS4IACL4p3MgESCwJHFR5oxCiB3FkERC5cSToQXFmUyiAZFR48Bn7zCAQMjkfykQkBN4n/XgKPBAAQgCUQIfBUwYXHFgIGCdI4XDmYADmIIEkAWJAH4A4A=="))
|
|
@ -0,0 +1,174 @@
|
|||
const w = require("weather");
|
||||
//const locale = require("locale");
|
||||
|
||||
// Weather icons from https://icons8.com/icon/set/weather/color
|
||||
function getSun() {
|
||||
return require("heatshrink").decompress(atob("kEggILIgOAAZkDAYPAgeBwPAgIFBBgPhw4TBp/yAYMcnADBnEcAYMwhgDBsEGgE/AYP8AYYLDCYgbDEYYrD8fHIwI7CIYZLDL54AHA=="));
|
||||
}
|
||||
function getPartSun() {
|
||||
return require("heatshrink").decompress(atob("kcjwIVSgOAAgUwAYUGAYVgBoQHBkAIBocIDIX4CIcOAYMYg/wgECgODgE8oFAmEDxEYgYZBgQLBGYNAg/ggcYgANBAIIxBsPAG4MYsAIBoQ3ChAQCgI4BHYUEBgUADIIPBh///4GBv//8Cda"));
|
||||
}
|
||||
//function getPartRain() {
|
||||
// return require("heatshrink").decompress(atob("kEggIHEmADJjEwsEAjkw8EAh0B4EAg35wEAgP+CYMDwv8AYMDBAP2g8HgH+g0DBYMMgPwAYX8gOMEwMG3kAg8OvgSBjg2BgcYGQIcBAY5CBg0Av//HAM///4MYgNBEIMOCoUMDoUAnBwGkEA"));
|
||||
//}
|
||||
function getCloud() {
|
||||
return require("heatshrink").decompress(atob("kEggIfcj+AAYM/8ADBuFwAYPAmADCCAMBwEf8ADBhFwg4aBnEPAYMYjAVBhgDDDoQDHCYc4jwDB+EP///FYIDBMTgA=="));
|
||||
}
|
||||
function getSnow() {
|
||||
return require("heatshrink").decompress(atob("kEggITQj/AAYM98ADBsEwAYPAjADCj+AgOAj/gAYMIuEHwEAjEPAYQVChk4AYQhCAYcYBYQTDnEPgEB+EH///IAQACE4IAB8EICIPghwDB4EeBYNAjgDBg8EAYQYCg4bCgZuFA=="));
|
||||
}
|
||||
function getRain() {
|
||||
return require("heatshrink").decompress(atob("kEggIPMh+AAYM/8ADBuFwAYPgmADB4EbAYOAj/ggOAhnwg4aBnAeCjEcCIMMjADCDoQDHjAPCnAXCuEP///8EDAYJECAAXBwkAgPDhwDBwUMgEEhkggEOjFgFgMQLYQAOA=="));
|
||||
}
|
||||
function getStorm() {
|
||||
return require("heatshrink").decompress(atob("kcjwIROgfwAYMB44ICsEwAYMYgYQCgAICoEHCwMYgFDwEHCYfgEAMA4AIBmAXCgUGFIVAwADBhEQFIQtCGwNggPgjAVBngCBv8Oj+AgfjwYpCGAIABn4kBgOBBAVwjBHBD4IdBgYNBGwUAkCdbA="));
|
||||
}
|
||||
// err icon - https://icons8.com/icons/set/error
|
||||
function getErr() {
|
||||
return require("heatshrink").decompress(atob("kEggILIgOAAYsD4ADBg/gAYMGsADBhkwAYsYjADCjgDBmEMAYNxxwDBsOGAYPBwYDEgOBwOAgYDB4EDHYPAgwDBsADDhgDBFIcwjAHBjE4AYMcmADBhhNCKIcG/4AGOw4A=="));
|
||||
}
|
||||
//function getDummy() {
|
||||
// return require("heatshrink").decompress(atob("gMBwMAwA"));
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Choose weather icon to display based on condition.
|
||||
Based on function from the Bangle weather app so it should handle all of the conditions
|
||||
sent from gadget bridge.
|
||||
*/
|
||||
function chooseIcon(condition) {
|
||||
condition = condition.toLowerCase();
|
||||
if (condition.includes("thunderstorm") ||
|
||||
condition.includes("squalls") ||
|
||||
condition.includes("tornado")) return getStorm;
|
||||
else if (condition.includes("freezing") || condition.includes("snow") ||
|
||||
condition.includes("sleet")) {
|
||||
return getSnow;
|
||||
}
|
||||
else if (condition.includes("drizzle") ||
|
||||
condition.includes("shower") ||
|
||||
condition.includes("rain")) return getRain;
|
||||
else if (condition.includes("clear")) return getSun;
|
||||
else if (condition.includes("clouds")) return getCloud;
|
||||
else if (condition.includes("few clouds") ||
|
||||
condition.includes("scattered clouds") ||
|
||||
condition.includes("mist") ||
|
||||
condition.includes("smoke") ||
|
||||
condition.includes("haze") ||
|
||||
condition.includes("sand") ||
|
||||
condition.includes("dust") ||
|
||||
condition.includes("fog") ||
|
||||
condition.includes("overcast") ||
|
||||
condition.includes("partly cloudy") ||
|
||||
condition.includes("ash")) {
|
||||
return getPartSun;
|
||||
} else return getErr;
|
||||
}
|
||||
/*function condenseWeather(condition) {
|
||||
condition = condition.toLowerCase();
|
||||
if (condition.includes("thunderstorm") ||
|
||||
condition.includes("squalls") ||
|
||||
condition.includes("tornado")) return "storm";
|
||||
if (condition.includes("freezing") || condition.includes("snow") ||
|
||||
condition.includes("sleet")) {
|
||||
return "snow";
|
||||
}
|
||||
if (condition.includes("drizzle") ||
|
||||
condition.includes("shower") ||
|
||||
condition.includes("rain")) return "rain";
|
||||
if (condition.includes("clear")) return "clear";
|
||||
if (condition.includes("clouds")) return "clouds";
|
||||
if (condition.includes("few clouds") ||
|
||||
condition.includes("scattered clouds") ||
|
||||
condition.includes("mist") ||
|
||||
condition.includes("smoke") ||
|
||||
condition.includes("haze") ||
|
||||
condition.includes("sand") ||
|
||||
condition.includes("dust") ||
|
||||
condition.includes("fog") ||
|
||||
condition.includes("overcast") ||
|
||||
condition.includes("partly cloudy") ||
|
||||
condition.includes("ash")) {
|
||||
return "scattered";
|
||||
} else { return "N/A"; }
|
||||
return "N/A";
|
||||
}
|
||||
*/
|
||||
// copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480
|
||||
function ISO8601_week_no(date) {
|
||||
var tdt = new Date(date.valueOf());
|
||||
var dayn = (date.getDay() + 6) % 7;
|
||||
tdt.setDate(tdt.getDate() - dayn + 3);
|
||||
var firstThursday = tdt.valueOf();
|
||||
tdt.setMonth(0, 1);
|
||||
if (tdt.getDay() !== 4) {
|
||||
tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7);
|
||||
}
|
||||
return 1 + Math.ceil((firstThursday - tdt) / 604800000);
|
||||
}
|
||||
|
||||
function format(value) {
|
||||
return ("0" + value).substr(-2);
|
||||
}
|
||||
|
||||
const ClockFace = require("ClockFace");
|
||||
const clock = new ClockFace({
|
||||
init: function () {
|
||||
const appRect = Bangle.appRect;
|
||||
|
||||
this.viewport = {
|
||||
width: appRect.w,
|
||||
height: appRect.h
|
||||
};
|
||||
|
||||
this.center = {
|
||||
x: this.viewport.width / 2,
|
||||
y: Math.round((this.viewport.height / 2) + appRect.y)
|
||||
};
|
||||
|
||||
this.scale = g.getWidth() / this.viewport.width;
|
||||
this.centerTimeScaleX = this.center.x + 32 * this.scale;
|
||||
this.centerDatesScaleX = this.center.x + 40 * this.scale;
|
||||
},
|
||||
draw: function (date) {
|
||||
const hour = date.getHours() - (this.is12Hour && date.getHours() > 12 ? 12 : 0);
|
||||
const month = date.getMonth() + 1;
|
||||
// const monthName = require("date_utils").month(month, 1);
|
||||
// const dayName = require("date_utils").dow(date.getDay(), 1);
|
||||
let steps = Bangle.getHealthStatus("day").steps;
|
||||
let curr = (w.get() === undefined ? "no data" : w.get()); // Get weather from weather app.
|
||||
//let cWea =(curr === "no data" ? "no data" : curr.txt);
|
||||
let cTemp= (curr === "no data" ? 273 : curr.temp);
|
||||
// const temp = locale.temp(curr.temp - 273.15).match(/^(\D*\d*)(.*)$/);
|
||||
let w_icon = chooseIcon(curr.txt === undefined ? "no data" : curr.txt );
|
||||
//let w_icon = chooseIcon(curr.txt);
|
||||
|
||||
g.setFontAlign(1, 0).setFont("Vector", 90 * this.scale);
|
||||
g.drawString(format(hour), this.centerTimeScaleX, this.center.y - 31 * this.scale);
|
||||
g.drawString(format(date.getMinutes()), this.centerTimeScaleX, this.center.y + 46 * this.scale);
|
||||
|
||||
g.fillRect(this.center.x + 30 * this.scale, this.center.y - 72 * this.scale, this.center.x + 32 * this.scale, this.center.y + 74 * this.scale);
|
||||
|
||||
g.setFontAlign(-1, 0).setFont("Vector", 16 * this.scale);
|
||||
g.drawString(format(date.getDate()), this.centerDatesScaleX, this.center.y - 62 * this.scale); //26
|
||||
g.drawString("." + format(month) + ".", this.centerDatesScaleX + 20, this.center.y - 62 * this.scale); //44
|
||||
g.drawString(date.getFullYear(date), this.centerDatesScaleX, this.center.y - 44 * this.scale); //62
|
||||
if (this.showWeekNum)
|
||||
g.drawString("CW" + format(ISO8601_week_no(date)), this.centerDatesScaleX, this.center.y + -26 * this.scale); //15
|
||||
// print(w_icon());
|
||||
if (this.showWeather) {
|
||||
g.drawImage(w_icon(), this.centerDatesScaleX, this.center.y - 8 * this.scale);
|
||||
// g.drawString(condenseWeather(curr.txt), this.centerDatesScaleX, this.center.y + 24 * this.scale);
|
||||
g.drawString((cTemp === undefined ? 273 : cTemp ) - 273 + "°C", this.centerDatesScaleX, this.center.y + 44 * this.scale); //48
|
||||
|
||||
}
|
||||
if (this.showSteps)
|
||||
g.drawString(steps, this.centerDatesScaleX, this.center.y + 66 * this.scale);
|
||||
|
||||
},
|
||||
settingsFile: "ffcniftyapp.json"
|
||||
});
|
||||
clock.start();
|
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"id": "ffcniftyapp",
|
||||
"name": "Nifty-A Clock ++",
|
||||
"version": "0.01",
|
||||
"description": "A nifty clock with time and date and more",
|
||||
"dependencies": {"weather":"app"},
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot_niftyapp.png"}],
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"ffcniftyapp.app.js","url":"app.js"},
|
||||
{"name":"ffcniftyapp.img","url":"app-icon.js","evaluate":true},
|
||||
{"name":"ffcniftyapp.settings.js","url":"settings.js"}
|
||||
],
|
||||
"data": [{"name":"ffcniftyapp.json"}]
|
||||
}
|
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 2.6 KiB |
|
@ -0,0 +1,35 @@
|
|||
|
||||
(function (back) {
|
||||
var DEFAULTS = {
|
||||
'showWeekNum': false,
|
||||
'showWeather': false,
|
||||
'showSteps': false,
|
||||
};
|
||||
let settings = require('Storage').readJSON("ffcniftyapp.json", 1) || DEFAULTS;
|
||||
E.showMenu({
|
||||
|
||||
"": { "title": "Nifty-A Clock ++" },
|
||||
"< Back": () => back(),
|
||||
/*LANG*/"Show Week Number": {
|
||||
value: settings.showWeekNum,
|
||||
onchange: v => {
|
||||
settings.showWeekNum = v;
|
||||
require("Storage").writeJSON("ffcniftyapp.json", settings);
|
||||
}
|
||||
},
|
||||
/*LANG*/"Show Weather": {
|
||||
value: settings.showWeather,
|
||||
onchange: w => {
|
||||
settings.showWeather = w;
|
||||
require("Storage").writeJSON("ffcniftyapp.json", settings);
|
||||
}
|
||||
},
|
||||
/*LANG*/"Show Steps": {
|
||||
value: settings.showSteps,
|
||||
onchange: z => {
|
||||
settings.showSteps = z;
|
||||
require("Storage").writeJSON("ffcniftyapp.json", settings);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
|
@ -0,0 +1 @@
|
|||
0.01: New Library!
|
|
@ -0,0 +1,23 @@
|
|||
# Canned Replies Library
|
||||
|
||||
A library that handles replying to messages received from Gadgetbridge/Messages apps.
|
||||
|
||||
## Replying to a message
|
||||
The user can define a set of canned responses via the customise page after installing the app, or alternatively if they have a keyboard installed, they can type a response back. The requesting app will receive either an object containing the full reply for GadgetBridge, or a string with the response from the user, depending on how they wish to handle the response.
|
||||
|
||||
## Integrating in your app
|
||||
To use this in your app, simply call
|
||||
|
||||
```js
|
||||
require("reply").reply(/*options*/{...}).then(result => ...);
|
||||
```
|
||||
|
||||
The ```options``` object can contain the following:
|
||||
|
||||
- ```msg```: A message object containing a field ```id```, the ID to respond to. If this is included in options, the result of the promise will be an object as follows: ```{t: "notify", id: msg.id, n: "REPLY", msg: "USER REPLY"}```. If not included, the result of the promise will be an object, ```{msg: "USER REPLY"}```
|
||||
- ```shouldReply```: Whether or not the library should send the response over Bluetooth with ```Bluetooth.println(...```. Useful if the calling app wants to handle the response a different way. Default is true.
|
||||
- ```title```: The title to show at the top of the menu. Defaults to ```"Reply with:"```.
|
||||
- ```fileOverride```: An override file to read canned responses from, which is an array of objects each with a ```text``` property. Default is ```replies.json```. Useful for apps which might want to make use of custom canned responses.
|
||||
|
||||
## Known Issues
|
||||
Emojis are currently not supported.
|
After Width: | Height: | Size: 720 B |
|
@ -0,0 +1,122 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
<link rel="stylesheet" href="../../css/spectre-icons.min.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<form id="replyForm">
|
||||
<label class="label">New Custom Reply:</label>
|
||||
<input class="form-input" id="msg" type="text" required></input>
|
||||
<input class="btn btn-primary" type="submit" value="Add">
|
||||
<br>
|
||||
<br>
|
||||
</form>
|
||||
<button class="btn btn-primary" onclick="updateDevice()">Update Device</button>
|
||||
<div>
|
||||
<div id="loading">
|
||||
<div class="empty">
|
||||
<div class="empty-icon">
|
||||
<div class="loading loading-lg"></div>
|
||||
</div>
|
||||
<p class="empty-title h5">Loading</p>
|
||||
<p class="empty-subtitle">Syncing custom replies with your watch</p>
|
||||
</div>
|
||||
</div>
|
||||
<div id="empty" class="d-hide">
|
||||
<div class="empty">
|
||||
<div class="empty-icon">
|
||||
<i class="icon icon-more-horiz"></i>
|
||||
</div>
|
||||
<p class="empty-title h5">No custom replies</p>
|
||||
<p class="empty-subtitle">Use the field above to add a custom reply</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table id="replyList" class="table table-striped table-hover"></table>
|
||||
</div>
|
||||
|
||||
<script src="../../core/lib/customize.js"></script>
|
||||
<script>
|
||||
const form = document.querySelector("#replyForm");
|
||||
form.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
saveReply();
|
||||
});
|
||||
var replies = [];
|
||||
var fetching = true; // Bit of a hack
|
||||
var el = document.getElementById('items');
|
||||
function onInit(device) {
|
||||
fetching = true;
|
||||
Util.readStorageJSON("replies.json", (arr) => {
|
||||
if (arr) {
|
||||
replies = replies.concat(arr);
|
||||
fetching = false;
|
||||
renderReplyList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function toggleVisibility() {
|
||||
let empty = document.getElementById("empty");
|
||||
let loading = document.getElementById("loading");
|
||||
if (fetching) {
|
||||
loading.setAttribute("class", "d-block");
|
||||
empty.setAttribute("class", "d-hide");
|
||||
}
|
||||
else if (replies.length == 0) {
|
||||
empty.setAttribute("class", "d-block");
|
||||
loading.setAttribute("class", "d-hide");
|
||||
}
|
||||
else {
|
||||
loading.setAttribute("class", "d-hide");
|
||||
empty.setAttribute("class", "d-hide");
|
||||
}
|
||||
}
|
||||
|
||||
function renderReplyList() {
|
||||
toggleVisibility();
|
||||
let table = document.getElementById("replyList");
|
||||
table.innerHTML = "";
|
||||
if (!fetching) {
|
||||
for (var i = 0; i < replies.length; i++) {
|
||||
var reply = replies[i];
|
||||
var li = document.createElement("tr");
|
||||
var label = document.createElement("td");
|
||||
label.innerHTML = reply.text + " ";
|
||||
var deleteButton = document.createElement("button");
|
||||
deleteButton.innerText = "Delete";
|
||||
deleteButton.setAttribute("onclick", `deleteReply(${i})`);
|
||||
deleteButton.setAttribute("class", "btn btn-error");
|
||||
li.appendChild(label);
|
||||
li.appendChild(deleteButton);
|
||||
table.appendChild(li);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function deleteReply(index) {
|
||||
replies.splice(index, 1);
|
||||
renderReplyList(replies);
|
||||
}
|
||||
|
||||
function saveReply() {
|
||||
var reply = {};
|
||||
reply.text = document.getElementById('msg').value;
|
||||
replies.push(reply);
|
||||
updateDevice();
|
||||
}
|
||||
|
||||
function updateDevice() {
|
||||
fetching = true;
|
||||
renderReplyList();
|
||||
Util.writeStorage("replies.json", JSON.stringify(replies), () => {
|
||||
fetching = false;
|
||||
renderReplyList();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,69 @@
|
|||
exports.reply = function (options) {
|
||||
var keyboard = "textinput";
|
||||
try {
|
||||
keyboard = require(keyboard);
|
||||
} catch (e) {
|
||||
keyboard = null;
|
||||
}
|
||||
|
||||
function constructReply(msg, replyText, resolve) {
|
||||
var responseMessage = {msg: replyText};
|
||||
if (msg.id) {
|
||||
responseMessage = { t: "notify", id: msg.id, n: "REPLY", msg: replyText };
|
||||
}
|
||||
E.showMenu();
|
||||
if (options.sendReply == null || options.sendReply) {
|
||||
Bluetooth.println(JSON.stringify(responseMessage));
|
||||
}
|
||||
resolve(responseMessage);
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
var menu = {
|
||||
"": {
|
||||
title: options.title || /*LANG*/ "Reply with:",
|
||||
back: function () {
|
||||
E.showMenu();
|
||||
reject("User pressed back");
|
||||
},
|
||||
}, // options
|
||||
/*LANG*/ "Compose": function () {
|
||||
keyboard.input().then((result) => {
|
||||
constructReply(options.msg ?? {}, result, resolve);
|
||||
});
|
||||
},
|
||||
};
|
||||
var replies =
|
||||
require("Storage").readJSON(
|
||||
options.fileOverride || "replies.json",
|
||||
true
|
||||
) || [];
|
||||
replies.forEach((reply) => {
|
||||
menu = Object.defineProperty(menu, reply.text, {
|
||||
value: () => constructReply(options.msg ?? {}, reply.text, resolve),
|
||||
});
|
||||
});
|
||||
if (!keyboard) delete menu[/*LANG*/ "Compose"];
|
||||
|
||||
if (replies.length == 0) {
|
||||
if (!keyboard) {
|
||||
E.showPrompt(
|
||||
/*LANG*/ "Please install a keyboard app, or set a custom reply via the app loader!",
|
||||
{
|
||||
buttons: { Ok: true },
|
||||
remove: function () {
|
||||
reject(
|
||||
"Please install a keyboard app, or set a custom reply via the app loader!"
|
||||
);
|
||||
},
|
||||
}
|
||||
);
|
||||
} else {
|
||||
keyboard.input().then((result) => {
|
||||
constructReply(options.msg.id, result, resolve);
|
||||
});
|
||||
}
|
||||
}
|
||||
E.showMenu(menu);
|
||||
});
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
{ "id": "reply",
|
||||
"name": "Reply Library",
|
||||
"version": "0.01",
|
||||
"description": "A library for replying to text messages via predefined responses or keyboard",
|
||||
"icon": "app.png",
|
||||
"type": "module",
|
||||
"provides_modules" : ["reply"],
|
||||
"tags": "",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"interface": "interface.html",
|
||||
"storage": [
|
||||
{"name":"reply","url":"lib.js"}
|
||||
],
|
||||
"data": [{"name":"replies.json"}]
|
||||
}
|
|
@ -81,3 +81,4 @@ of 'Select Clock'
|
|||
0.70: Fix load() typo
|
||||
0.71: Minor code improvements
|
||||
0.72: Add setting for configuring BLE privacy
|
||||
0.73: Fix `const` bug / work with fastload
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "setting",
|
||||
"name": "Settings",
|
||||
"version": "0.72",
|
||||
"version": "0.73",
|
||||
"description": "A menu for setting up Bangle.js",
|
||||
"icon": "settings.png",
|
||||
"tags": "tool,system",
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
|
@ -984,3 +985,4 @@ function showTouchscreenCalibration() {
|
|||
}
|
||||
|
||||
showMainMenu();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
0.01: New App!
|
||||
0.02: Fix case where we tried to push to Bangle.btnWatches but it wasn't
|
||||
defined.
|
|
@ -0,0 +1,24 @@
|
|||
# setUI Proposals Preview
|
||||
|
||||
Try out changes to setUI that may or may not eventually en up in the Bangle.js firmware.
|
||||
|
||||
## Usage
|
||||
|
||||
Just install it and it modifies setUI at boot time.
|
||||
|
||||
## Features
|
||||
|
||||
- Add custom handlers on top of the standard modes as well. Previously this was only possible for mode == "custom".
|
||||
- The goal here is to make it possible to move all input handling inside `setUI` where today some apps add on extra handlers outside of `setUI` calls.
|
||||
- Change the default behaviour of the hardware button to act immediately on press down. Previously it has been acting on button release.
|
||||
- This makes the interaction slightly snappier.
|
||||
- In addition to the existing `btn` key a new `btnRelease` key can now be specified. `btnRelease` will let you listen to the rising edge of the hardware button.
|
||||
|
||||
## Requests
|
||||
|
||||
Please report your experience and thoughts on this issue:
|
||||
[ Discussion: HW buttons should act on 'rising' edge #3435 ](https://github.com/espruino/BangleApps/issues/3435) or on the related forum conversation (Link will be added when the conversation has opened).
|
||||
|
||||
## Creator
|
||||
|
||||
The changes done here were done by thyttan with help from Gordon Williams.
|
After Width: | Height: | Size: 990 B |
|
@ -0,0 +1,152 @@
|
|||
Bangle.setUI = (function(mode, cb) {
|
||||
var options = {};
|
||||
if ("object"==typeof mode) {
|
||||
options = mode;
|
||||
mode = options.mode;
|
||||
if (!mode) throw new Error("Missing mode in setUI({...})");
|
||||
}
|
||||
var redraw = true;
|
||||
if (global.WIDGETS && WIDGETS.back) {
|
||||
redraw = false;
|
||||
WIDGETS.back.remove(mode && options.back);
|
||||
}
|
||||
if (Bangle.btnWatches) {
|
||||
Bangle.btnWatches.forEach(clearWatch);
|
||||
delete Bangle.btnWatches;
|
||||
}
|
||||
if (Bangle.swipeHandler) {
|
||||
Bangle.removeListener("swipe", Bangle.swipeHandler);
|
||||
delete Bangle.swipeHandler;
|
||||
}
|
||||
if (Bangle.dragHandler) {
|
||||
Bangle.removeListener("drag", Bangle.dragHandler);
|
||||
delete Bangle.dragHandler;
|
||||
}
|
||||
if (Bangle.touchHandler) {
|
||||
Bangle.removeListener("touch", Bangle.touchHandler);
|
||||
delete Bangle.touchHandler;
|
||||
}
|
||||
delete Bangle.uiRedraw;
|
||||
delete Bangle.CLOCK;
|
||||
if (Bangle.uiRemove) {
|
||||
let r = Bangle.uiRemove;
|
||||
delete Bangle.uiRemove; // stop recursion if setUI is called inside uiRemove
|
||||
r();
|
||||
}
|
||||
g.reset();// reset graphics state, just in case
|
||||
if (!mode) return;
|
||||
function b() {
|
||||
try{Bangle.buzz(30);}catch(e){}
|
||||
}
|
||||
if (mode=="updown") {
|
||||
var dy = 0;
|
||||
Bangle.dragHandler = e=>{
|
||||
dy += e.dy;
|
||||
if (!e.b) dy=0;
|
||||
while (Math.abs(dy)>32) {
|
||||
if (dy>0) { dy-=32; cb(1) }
|
||||
else { dy+=32; cb(-1) }
|
||||
Bangle.buzz(20);
|
||||
}
|
||||
};
|
||||
Bangle.on('drag',Bangle.dragHandler);
|
||||
Bangle.touchHandler = d => {b();cb();};
|
||||
Bangle.btnWatches = [
|
||||
setWatch(function() { b();cb(); }, BTN1, {repeat:1, edge:"rising"}),
|
||||
];
|
||||
} else if (mode=="leftright") {
|
||||
var dx = 0;
|
||||
Bangle.dragHandler = e=>{
|
||||
dx += e.dx;
|
||||
if (!e.b) dx=0;
|
||||
while (Math.abs(dx)>32) {
|
||||
if (dx>0) { dx-=32; cb(1) }
|
||||
else { dx+=32; cb(-1) }
|
||||
Bangle.buzz(20);
|
||||
}
|
||||
};
|
||||
Bangle.on('drag',Bangle.dragHandler);
|
||||
Bangle.touchHandler = d => {b();cb();};
|
||||
Bangle.btnWatches = [
|
||||
setWatch(function() { b();cb(); }, BTN1, {repeat:1, edge:"rising"}),
|
||||
];
|
||||
} else if (mode=="clock") {
|
||||
Bangle.CLOCK=1;
|
||||
Bangle.btnWatches = [
|
||||
setWatch(Bangle.showLauncher, BTN1, {repeat:1,edge:"rising"})
|
||||
];
|
||||
} else if (mode=="clockupdown") {
|
||||
Bangle.CLOCK=1;
|
||||
Bangle.touchHandler = (d,e) => {
|
||||
if (e.x < 120) return;
|
||||
b();cb((e.y > 88) ? 1 : -1);
|
||||
};
|
||||
Bangle.btnWatches = [
|
||||
setWatch(Bangle.showLauncher, BTN1, {repeat:1,edge:"rising"})
|
||||
];
|
||||
} else if (mode=="custom") {
|
||||
if (options.clock) {
|
||||
Bangle.btnWatches = [
|
||||
setWatch(Bangle.showLauncher, BTN1, {repeat:1,edge:"rising"})
|
||||
];
|
||||
}
|
||||
} else
|
||||
throw new Error("Unknown UI mode "+E.toJS(mode));
|
||||
if (options.clock) Bangle.CLOCK=1;
|
||||
if (options.touch)
|
||||
Bangle.touchHandler = options.touch;
|
||||
if (options.drag) {
|
||||
Bangle.dragHandler = options.drag;
|
||||
Bangle.on("drag", Bangle.dragHandler);
|
||||
}
|
||||
if (options.swipe) {
|
||||
Bangle.swipeHandler = options.swipe;
|
||||
Bangle.on("swipe", Bangle.swipeHandler);
|
||||
}
|
||||
if ((options.btn || options.btnRelease) && !Bangle.btnWatches) Bangle.btnWatches = [];
|
||||
if (options.btn) Bangle.btnWatches.push(setWatch(options.btn.bind(options), BTN1, {repeat:1,edge:"rising"}))
|
||||
if (options.btnRelease) Bangle.btnWatches.push(setWatch(options.btnRelease.bind(options), BTN1, {repeat:1,edge:"falling"}))
|
||||
if (options.remove) // handler for removing the UI (intervals/etc)
|
||||
Bangle.uiRemove = options.remove;
|
||||
if (options.redraw) // handler for redrawing the UI
|
||||
Bangle.uiRedraw = options.redraw;
|
||||
if (options.back) {
|
||||
var touchHandler = (_,e) => {
|
||||
if (e.y<36 && e.x<48) {
|
||||
e.handled = true;
|
||||
E.stopEventPropagation();
|
||||
options.back();
|
||||
}
|
||||
};
|
||||
Bangle.on("touch", touchHandler);
|
||||
// If a touch handler was needed for setUI, add it - but ignore touches if they've already gone to the 'back' handler
|
||||
if (Bangle.touchHandler) {
|
||||
var uiTouchHandler = Bangle.touchHandler;
|
||||
Bangle.touchHandler = (_,e) => {
|
||||
if (!e.handled) uiTouchHandler(_,e);
|
||||
};
|
||||
Bangle.on("touch", Bangle.touchHandler);
|
||||
}
|
||||
var btnWatch;
|
||||
if (Bangle.btnWatches===undefined) // only add back button handler if there's no existing watch on BTN1
|
||||
btnWatch = setWatch(function() {
|
||||
btnWatch = undefined;
|
||||
options.back();
|
||||
}, BTN1, {edge:"rising"});
|
||||
WIDGETS = Object.assign({back:{
|
||||
area:"tl", width:24,
|
||||
draw:e=>g.reset().setColor("#f00").drawImage(atob("GBiBAAAYAAH/gAf/4A//8B//+D///D///H/P/n+H/n8P/n4f/vwAP/wAP34f/n8P/n+H/n/P/j///D///B//+A//8Af/4AH/gAAYAA=="),e.x,e.y),
|
||||
remove:(noclear)=>{
|
||||
if (btnWatch) clearWatch(btnWatch);
|
||||
Bangle.removeListener("touch", touchHandler);
|
||||
if (!noclear) g.reset().clearRect({x:WIDGETS.back.x, y:WIDGETS.back.y, w:24,h:24});
|
||||
delete WIDGETS.back;
|
||||
if (!noclear) Bangle.drawWidgets();
|
||||
}
|
||||
}},global.WIDGETS);
|
||||
if (redraw) Bangle.drawWidgets();
|
||||
} else { // If a touch handler was needed for setUI, add it
|
||||
if (Bangle.touchHandler)
|
||||
Bangle.on("touch", Bangle.touchHandler);
|
||||
}
|
||||
})
|
|
@ -0,0 +1,13 @@
|
|||
{ "id": "setuichange",
|
||||
"name": "SetUI Proposals preview",
|
||||
"version":"0.02",
|
||||
"description": "Try out potential future changes to `Bangle.setUI`. Makes hardware button interaction snappier. Makes it possible to set custom event handlers on any type/mode, not just `\"custom\"`. Please provide feedback - see `Read more...` below.",
|
||||
"icon": "app.png",
|
||||
"tags": "",
|
||||
"type": "bootloader",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"setuichange.0.boot.js","url":"boot.js"}
|
||||
]
|
||||
}
|
|
@ -1 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: added check if settings file exists and create if missing
|
||||
|
|
|
@ -25,3 +25,9 @@ It reuses the widget from [Quiet Mode Schedule and Widget](https://github.com/es
|
|||
-optimization of code (and check if needed)
|
||||
|
||||
-feedback is always welcome
|
||||
|
||||
#### Attributions
|
||||
The app icon is downloaded from [https://icons8.com](https://icons8.com).
|
||||
|
||||
#### License
|
||||
[MIT License](LICENSE)
|
|
@ -1,5 +1,16 @@
|
|||
const SETTINGS_FILE = "quietSwitch.json";
|
||||
const storage = require("Storage");
|
||||
|
||||
//check if settings file exists and create if missing
|
||||
if (storage.read(SETTINGS_FILE)=== undefined) {
|
||||
print("data file not existing, using defaults");
|
||||
let saved = {
|
||||
quietWhenSleep: 0, //off
|
||||
quietMode: 1, //alerts
|
||||
};
|
||||
storage.writeJSON(SETTINGS_FILE,saved);
|
||||
}
|
||||
|
||||
let saved = storage.readJSON(SETTINGS_FILE, 1) || {};
|
||||
|
||||
// Main menu
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{ "id": "slpquiet",
|
||||
"name": "Sleep Quiet (activate quiet mode when asleep)",
|
||||
"shortName":"Sleep Quiet",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "Set Quiet mode (or alarms only mode), when the sleep tracking app detects sleep (each 10 min evaluated)",
|
||||
"icon": "app.png",
|
||||
"tags": "tool,widget",
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
0.04: Update to work with new 'fast switch' clock->launcher functionality
|
||||
0.05: Keep track of event listeners we "overwrite", and remove them at the start of setUI
|
||||
0.06: Handle apps that call setUI({}) to reset
|
||||
0.07: Use a more reliable method of detecting a clock
|
||||
|
|
|
@ -3,24 +3,21 @@
|
|||
var oldSwipe;
|
||||
|
||||
Bangle.setUI = function(mode, cb) {
|
||||
if (oldSwipe && oldSwipe !== Bangle.swipeHandler)
|
||||
if (oldSwipe) {
|
||||
Bangle.removeListener("swipe", oldSwipe);
|
||||
sui(mode,cb);
|
||||
oldSwipe = Bangle.swipeHandler;
|
||||
|
||||
if ("object"==typeof mode) mode = mode.mode;
|
||||
if (!mode) return;
|
||||
|
||||
if (mode.startsWith("clock")) {
|
||||
// clock -> launcher
|
||||
Bangle.swipeHandler = dir => { if (dir<0) Bangle.showLauncher(); };
|
||||
Bangle.on("swipe", Bangle.swipeHandler);
|
||||
} else {
|
||||
if (global.__FILE__ && __FILE__.endsWith(".app.js") && (require("Storage").readJSON(__FILE__.slice(0,-6)+"info",1)||{}).type=="launch") {
|
||||
// launcher -> clock
|
||||
Bangle.swipeHandler = dir => { if (dir>0) load(); };
|
||||
Bangle.on("swipe", Bangle.swipeHandler);
|
||||
oldSwipe = undefined;
|
||||
}
|
||||
|
||||
sui(mode,cb);
|
||||
|
||||
if (Bangle.CLOCK) {
|
||||
// clock -> launcher
|
||||
oldSwipe = dir => { if (dir<0) Bangle.showLauncher(); };
|
||||
Bangle.on("swipe", oldSwipe);
|
||||
} else if (global.__FILE__ && __FILE__.endsWith(".app.js") && (require("Storage").readJSON(__FILE__.slice(0,-6)+"info",1)||{}).type==="launch") {
|
||||
// launcher -> clock
|
||||
oldSwipe = dir => { if (dir>0) load(); };
|
||||
Bangle.on("swipe", oldSwipe);
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "swiperclocklaunch",
|
||||
"name": "Swiper Clock Launch",
|
||||
"version": "0.06",
|
||||
"version": "0.07",
|
||||
"description": "Navigate between clock and launcher with Swipe action",
|
||||
"icon": "swiperclocklaunch.png",
|
||||
"type": "bootloader",
|
||||
|
|
|
@ -33,3 +33,9 @@ The app functionality is inspired by the [Quiet Mode Schedule and Widget](https:
|
|||
-transfer of configuration into settings, so app can be used as a shortcut to switch theme.
|
||||
|
||||
-feedback is always welcome
|
||||
|
||||
#### Attributions
|
||||
The app icon is downloaded from [https://icons8.com](https://icons8.com).
|
||||
|
||||
#### License
|
||||
[MIT License](LICENSE)
|
||||
|
|