Merge branch 'espruino:master' into master

pull/1213/head
Peer David 2022-01-05 10:37:59 +01:00 committed by GitHub
commit 889f3687b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 823 additions and 99 deletions

View File

@ -77,7 +77,7 @@
{
"id": "messages",
"name": "Messages",
"version": "0.16",
"version": "0.17",
"description": "App to display notifications from iOS and Gadgetbridge",
"icon": "app.png",
"type": "app",
@ -116,7 +116,7 @@
{
"id": "ios",
"name": "iOS Integration",
"version": "0.07",
"version": "0.08",
"description": "Display notifications/music/etc from iOS devices",
"icon": "app.png",
"tags": "tool,system,ios,apple,messages,notifications",
@ -167,7 +167,7 @@
{
"id": "setting",
"name": "Settings",
"version": "0.39",
"version": "0.40",
"description": "A menu for setting up Bangle.js",
"icon": "settings.png",
"tags": "tool,system",
@ -936,7 +936,7 @@
"id": "widbatpc",
"name": "Battery Level Widget (with percentage)",
"shortName": "Battery Widget",
"version": "0.14",
"version": "0.15",
"description": "Show the current battery level and charging status in the top right of the clock, with charge percentage",
"icon": "widget.png",
"type": "widget",
@ -1749,8 +1749,9 @@
"icon": "grocery.png",
"type": "app",
"tags": "tool,outdoors,shopping,list",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS", "BANGLEJS2"],
"custom": "grocery.html",
"allow_emulator": true,
"storage": [
{"name":"grocery.app.js","url":"app.js"},
{"name":"grocery.img","url":"grocery-icon.js","evaluate":true}
@ -2970,11 +2971,11 @@
{
"id": "cprassist",
"name": "CPR Assist",
"version": "0.01",
"version": "0.02",
"description": "Provides assistance while performing a CPR",
"icon": "cprassist-icon.png",
"tags": "tool,firstaid",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-CPR-assist-screenshot.png"}],
@ -4210,13 +4211,13 @@
"id": "pastel",
"name": "Pastel Clock",
"shortName": "Pastel",
"version": "0.09",
"description": "A Configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times",
"version": "0.10",
"description": "A Configurable clock with custom fonts, background and weather display. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times",
"icon": "pastel.png",
"dependencies": {"mylocation":"app", "widpedom":"app"},
"screenshots": [{"url":"screenshot_pastel.png"}],
"dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"},
"screenshots": [{"url":"screenshot_pastel.png"}, {"url":"weather_icons.png"}],
"type": "clock",
"tags": "clock",
"tags": "clock, weather, tool",
"supports": ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"storage": [
@ -4382,7 +4383,7 @@
{
"id": "gpstouch",
"name": "GPS Touch",
"version": "0.01",
"version": "0.02",
"description": "A touch based GPS watch, shows OS map reference",
"icon": "gpstouch.png",
"screenshots": [{"url":"screenshot4.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"},{"url":"screenshot1.png"}],
@ -4621,7 +4622,7 @@
"shortName":"93 Dub",
"icon": "93dub.png",
"screenshots": [{"url":"screenshot.png"}],
"version":"0.05",
"version":"0.06",
"description": "Fan recreation of orviwan's 91 Dub app for the Pebble smartwatch. Uses assets from his 91-Dub-v2.0 repo",
"tags": "clock",
"type": "clock",
@ -4710,7 +4711,7 @@
"icon": "mylocation.png",
"type": "app",
"screenshots": [{"url":"screenshot_1.png"}],
"version":"0.01",
"version":"0.02",
"description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README",
"readme": "README.md",
"tags": "tool,utility",
@ -4727,7 +4728,7 @@
"id": "pebble",
"name": "Pebble Clock",
"shortName": "Pebble",
"version": "0.06",
"version": "0.07",
"description": "A pebble style clock to keep the rebellion going",
"dependencies": {"widpedom":"app"},
"readme": "README.md",
@ -4735,7 +4736,7 @@
"screenshots": [{"url":"pebble_screenshot.png"}],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"supports": ["BANGLEJS", "BANGLEJS2"],
"storage": [
{"name":"pebble.app.js","url":"pebble.app.js"},
{"name":"pebble.settings.js","url":"pebble.settings.js"},
@ -4769,7 +4770,7 @@
"screenshots": [{"url":"screenshot_widbata_1.png"}],
"version":"0.01",
"type": "widget",
"supports": ["BANGLEJS2"],
"supports": ["BANGLEJS", "BANGLEJS2"],
"readme": "README.md",
"description": "Shows the current battery level status in the top right using the clocks colour theme",
"tags": "widget,battery",
@ -4914,7 +4915,7 @@
"id": "rebble",
"name": "Rebble Clock",
"shortName": "Rebble",
"version": "0.03",
"version": "0.04",
"description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion",
"readme": "README.md",
"icon": "rebble.png",
@ -5357,5 +5358,36 @@
{ "name": "diract.app.js", "url": "diract.js" },
{ "name": "diract.img", "url": "diract-icon.js", "evaluate": true }
]
},
{
"id": "sonicclk",
"name": "Sonic Clock",
"version": "1.01",
"description": "A classic sonic clock featuring run, stop and wait animations.",
"icon": "app.png",
"screenshots": [{"url":"screenshot.png"}],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS2"],
"allow_emulator": true,
"readme": "README.md",
"storage": [
{"name":"sonicclk.app.js","url":"app.js"},
{"name":"sonicclk.img","url":"app-icon.js","evaluate":true}
]
},
{
"id": "touchmenu",
"name": "TouchMenu",
"version": "0.01",
"description": "Redesigned menu that uses the full touchscreen on the Bangle.js 2",
"screenshots": [{"url":"touchmenu.gif"}],
"icon": "touchmenu.png",
"type": "bootloader",
"tags": "tool",
"supports": ["BANGLEJS2"],
"storage": [
{"name":"touchmenu.boot.js","url":"touchmenu.boot.js"}
]
}
]

View File

@ -3,3 +3,4 @@
0.03: Code style cleanup
0.04: Set 00:00 to 12:00 for 12 hour time
0.05: Display time, even on Thursday
0.06: Fix light theme issue, where widgets would end up on a light strip

View File

@ -122,7 +122,13 @@ function draw(){
queueDraw();
}
/**
* This watch is mostly dark, it does not make sense to respect the
* light theme as you end up with a white strip at the top for the
* widgets and black watch. So set the colours to the dark theme.
*
*/
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
draw();
//the following section is also from waveclk

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Ported to Banglejs2

View File

@ -35,23 +35,24 @@ function provideFeedback() {
}
function drawHeart() {
g.fillCircle(40, 92, 12);
g.fillCircle(60, 92, 12);
g.fillPoly([29, 98, 50, 120, 71, 98]);
var lowestPoint = g.getHeight()*3/5;
g.fillCircle(40, lowestPoint-29, 12);
g.fillCircle(60, lowestPoint-29, 12);
g.fillPoly([29, lowestPoint-22, 50, lowestPoint, 71, lowestPoint-22]);
}
function updateScreen() {
const colors = [0xFFFF, 0x9492];
g.reset().clearRect(0, 50, 250, 150);
const colors = [0xFFFF-g.getBgColor(), 0x9492];
g.reset().clearRect(0, 24, g.getWidth(), g.getHeight()*5/6);
if (counter > 0) {
g.setFont("Vector", 40).setFontAlign(0, 0);
g.setColor(colors[counter%2]);
drawHeart();
g.drawString(counter + "", g.getWidth()/2, 100);
g.drawString(counter, 120, g.getHeight()*3/5-20);
} else {
g.setFont("Vector", 20).setFontAlign(0, 0);
g.drawString("RESCUE", g.getWidth()/2, 70);
g.drawString("BREATHS", g.getWidth()/2, 120);
g.drawString("RESCUE", g.getWidth()/2, g.getHeight()/3);
g.drawString("BREATHS", g.getWidth()/2, g.getHeight()*3/5);
}
}
@ -73,7 +74,7 @@ function tick() {
interval = setInterval(tick, 60000/setting('compression_rpm'));
g.clear(1).setFont("6x8");
g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, 200);
g.drawString(setting('compression_count') + ' / ' + setting('breath_count'), 30, g.getHeight()*5/6);
Bangle.loadWidgets();
Bangle.drawWidgets();

View File

@ -1 +1,2 @@
0.01: First version
0.02: Enchanced contrast of icon image

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEw4UA///j+EAYO/uYDB//wCYcPBA4AFh/ABZMDBbkX6gLIgtX6tQBY9VBYNVBY0BBYdABYsFqoACEgQLDitVtWpqtUBYtVq2q1WVGAQLErQLB0oLFHQNqBYIkBHgMDIwYKBAAJIDIweqz/2BYJtDBYI6Bv/9HgILHYwILGh4gBBYWfbooLF6AjPBYW//wLGL4Wv/RfGNZaDIBYibEBYizIBYjLDBYzXBd4TXCBZ60BBYRqEBZpUBBYRSFJAQLCA4b7BHgQLFgYLGIwYLEgoLBHQYLEgILBHQYLEgALBAoYLFi/UBZMHBZUD6ALKApQAFBbHwBZMP/4ABBwgIDA="))
require("heatshrink").decompress(atob("mEw4UA///iADCn+EqoAWqAuJgoLcn/8BZENGwNwBY/VBYNXBY0DJ4fABYoiCEggLDmtX1Wq6tcBYvVrQLB0owCBYdVtQLB1NVBYg6BBQIABHgQLCgIuCGAVABYcNqwtBGIOVJAILFyoCCBY5eBBdo7IgIIB1t6BYJfENZaDB9QKB1aDFBYKbEBYizBrwLB2qnFdwSmCX401cYdUBZTjGfYgHCBZB2BBYhUBAARSBBYhICAAIGCBYkVBQJSCBYpICIwQLFHgQ6CBYo8CHQQLFHgQFDBYsVQIQLHgo6DBY0BHQYLGgY6DBYwAFBbCjDACY"))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -2,9 +2,7 @@
0.02: Remove messages on disconnect
0.03: Handling of message actions (ok/clear)
0.04: Added common bundleId's
0.05: Added more bundleId's (app-id's which can be used to
determine a friendly app name in the notifications)
0.05: Added more bundleId's (app-id's which can be used to determine a friendly app name in the notifications)
0.06: Fix (not) popupping up old messages
0.07: Added more details from music (instead of Undefined)
Added more app identifiers
0.07: Added more details from music (instead of Undefined), added more app identifiers
0.08: Added more app identifiers, added 'cannot display' in case a message goes empty because of replacements

View File

@ -66,6 +66,7 @@ E.on('notify',msg=>{
"com.apple.mobilecal": "Calendar",
"com.apple.mobilemail": "Mail",
"com.apple.mobilephone": "Phone",
"com.apple.mobileslideshow": "Pictures",
"com.apple.MobileSMS": "SMS Message",
"com.apple.Passbook": "iOS Wallet",
"com.apple.podcasts": "Podcasts",
@ -83,6 +84,7 @@ E.on('notify',msg=>{
"com.ifttt.ifttt" : "IFTTT",
"com.jumbo.app" : "Jumbo",
"com.linkedin.LinkedIn" : "LinkedIn",
"com.marktplaats.iphone": "Marktplaats",
"com.microsoft.Office.Outlook" : "Outlook Mail",
"com.nestlabs.jasper.release" : "Nest",
"com.netflix.Netflix" : "Netflix",
@ -90,6 +92,7 @@ E.on('notify',msg=>{
"com.skype.skype": "Skype",
"com.skype.SkypeForiPad": "Skype",
"com.spotify.client": "Spotify",
"com.storytel.iphone": "Storytel",
"com.strava.stravaride": "Strava",
"com.tinyspeck.chatlyio": "Slack",
"com.toyopagroup.picaboo": "Snapchat",
@ -98,6 +101,8 @@ E.on('notify',msg=>{
"com.vilcsak.bitcoin2": "Coinbase",
"com.wordfeud.free": "WordFeud",
"com.zhiliaoapp.musically": "TikTok",
"io.robbie.HomeAssistant": "Home Assistant",
"net.weks.prowl": "Prowl",
"net.whatsapp.WhatsApp": "WhatsApp",
"nl.ah.Appie": "Albert Heijn",
"nl.postnl.TrackNTrace": "PostNL",
@ -118,7 +123,7 @@ E.on('notify',msg=>{
new : msg.new,
title : msg.title&&E.decodeUTF8(msg.title, unicodeRemap, replacer),
subject : msg.subtitle&&E.decodeUTF8(msg.subtitle, unicodeRemap, replacer),
body : msg.message&&E.decodeUTF8(msg.message, unicodeRemap, replacer)
body : msg.message&&E.decodeUTF8(msg.message, unicodeRemap, replacer) || "Cannot display"
});
// TODO: posaction/negaction?
});

View File

@ -23,3 +23,4 @@
0.14: Hide widget when all unread notifications are dismissed from phone
0.15: Don't buzz when Quiet Mode is active
0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147)
0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font

View File

@ -1,8 +1,9 @@
WIDGETS["messages"]={area:"tl",width:0,draw:function() {
WIDGETS["messages"]={area:"tl", width:0, iconwidth:23,
draw:function() {
Bangle.removeListener('touch', this.touch);
if (!this.width) return;
var c = (Date.now()-this.t)/1000;
g.reset().clearRect(this.x,this.y,this.x+this.width,this.y+23);
g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.iconwidth);
g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y);
//if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute
let settings = require('Storage').readJSON("messages.settings.json", true) || {};
@ -17,7 +18,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() {
WIDGETS["messages"].t=Date.now(); // first time
WIDGETS["messages"].l=Date.now()-10000; // last buzz
if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing
WIDGETS["messages"].width=64;
WIDGETS["messages"].width=this.iconwidth;
Bangle.drawWidgets();
Bangle.setLCDPower(1);// turns screen on
},hide:function() {
@ -37,7 +38,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() {
b();
},touch:function(b,c) {
var w=WIDGETS["messages"];
if (!w||!w.width||c.x<w.x||c.x>w.x+w.width||c.y<w.y||c.y>w.y+23) return;
if (!w||!w.width||c.x<w.x||c.x>w.x+w.width||c.y<w.y||c.y>w.y+w.iconwidth) return;
load("messages.app.js");
}};
/* We might have returned here if we were in the Messages app for a

View File

@ -1 +1,2 @@
0.01: First release
0.02: Enhanced icon, make it bolder

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEw4UA///t/7j/P3/vB4cBqtVoAbHBQIABBQ0FBYdQBYsVBYdUERIkGHIQADHoguEGAwuEGAwKFBZg8DHQw8EBYNf/1Vq3/8oLDIwNf/Wpv//0oLG9Wq3/qBYJUCBYuqBaBqBBYW+BepHEBbybCBYP+BYSnErYLDyoLFAANq/r8Ga5T7MBZZUBAAhSCfhA6DBZhIGBQg8FHQg8GHQgwGFwowFBQwwDFwwLMlS7Bqta1AKEn2q1K1C1WgBYf/1WqBYIDB1QKCgYLC0taBYoXB/QICBY0//7vBAAQ8EEgIABCwwME9QVEA"))
require("heatshrink").decompress(atob("mEw4UA///gH4AYPO/QPDgNVqtADY/1BYNfBQ0PBQIAB+ALFmoLDrgLF6oLDq4KEgYKDBYPABYcNBYlVuAuIGAwuEAANUBYYKFHgg6Bq4ZCr4DBHgQLBvWq2te1WlBYZGBBYOr1Wq1qSDBYNqBIILDKgQLLgoLHqBqDBfJHLBZBrOgKPCBYiPCU4NaBYe1WYrABBQLCCfgYGCrwVBa4kAirvKNgIAErgLDKgIAEKQQ8EAAY6DBZhIDIww8GHQg8GHQgwGFwowEFwx5EOog8GHQ0AlWpBYNq1AKFWIILBAYOgBYbICytWAgQKCgTgDcwYXGAAgvGAAY8EEgYWGBgoVEA=="))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -7,3 +7,4 @@
0.07: Added info line that cycles on BTN1/BTN3 (or vitual buttons on a bangle 2)
0.08: Added dependancy on MyLocation
0.09: Added dependancy on Pedometer Widget
0.10: Added Weather line, fixed issues on a Bangle 1, update every minute

View File

@ -1,45 +1,83 @@
# Pastel Clock
*a configurable clock with custom fonts and background. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times*
*a configurable clock with custom fonts, background and optional weather icons. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times*
* Designed specifically for Bangle 1 and Bangle 2
* A choice of 7 different custom fonts
* Supports the Light and Dark themes
* Has a settings menu, change font, enable/disable the grid
* Has a settings menu, change font, enable/disable the grid, weather icons
* On Bangle 1 use BTN1,BTN3 to cycle through the info display (Date, ID, Batt %, Ram % etc)
* On Bangle 2 touch the top right/top left to cycle through the info display (Date, ID, Batt %, Ram % etc)
* The information display will cycle on each screen update
* Uses mylocation.json from MyLocation app to calculate sunrise and sunset times for your location
* Uses pedometer widget to get latest step count
* Use the weather widget to get weather status
* Dependant apps are installed when Pastel installs
* The screen is updated every minute to save battery power
* The weather display will display temperature and wind speed on alternate screen refreshes
I came up with the name Pastel due to the shade of the grid background.
Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/)
## Lato
## Weather Support
![](screenshot_pastel.png)
Pastel installs the weather app and weather widget. You may want to
hide the weather widget display, this can be done through the weather
widget settings. You should first get the weather app working. If
the weather App is not working, then it is not going to work for
Pastel.
The following weather icons are supported.
![](weather_icons.png)
Mostly cloudy, Sunny, Mostly Sunny, Snow, Rain.
The triangle icon shows there is a problem connecting to GadgetBridge and the weather service.
You should follow the setup and trouble shooting guide for the Weather App.
If you find the weather / gadgetbridge service unreliable you can
disable weather updates to pastel through the settings app.
## Fonts
### Lato
![](screenshot_lato.png)
## Architect
### Architect
![](screenshot_architect.png)
## Gochihand
### Gochihand
![](screenshot_gochihand.png)
## Monoton
### Monoton
![](screenshot_monoton.png)
## Elite
### Elite
![](screenshot_elite.png)
## Cabin Sketch
### Cabin Sketch
![](screenshot_cabinsketch.png)
## Orbitron
### Orbitron
![](screenshot_orbitron.png)
### The Grid
Setting the grid on provides a graph paper style background to the App.
The grid is not supported on a Bangle 1 due to flicker issues.
![](screenshot_grid.png)

View File

@ -1,10 +1,22 @@
var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js");
require("f_latosmall").add(Graphics);
const storage = require('Storage');
const locale = require("locale");
const SETTINGS_FILE = "pastel.json";
const LOCATION_FILE = "mylocation.json";
let settings;
let location;
// cloud, sun, partSun, snow, rain, storm, error
// create 1 bit, max contrast, brightness set to 85
var cloudIcon = require("heatshrink").decompress(atob("kEggIfcj+AAYM/8ADBuFwAYPAmADCCAMBwEf8ADBhFwg4aBnEPAYMYjAVBhgDDDoQDHCYc4jwDB+EP///FYIDBMTgA=="));
var sunIcon = require("heatshrink").decompress(atob("kEggILIgOAAZkDAYPAgeBwPAgIFBBgPhw4TBp/yAYMcnADBnEcAYMwhgDBsEGgE/AYP8AYYLDCYgbDEYYrD8fHIwI7CIYZLDL54AHA=="));
var sunPartIcon = require("heatshrink").decompress(atob("kEggIHEmADJjEwsEAjkw8EAh0B4EAg35wEAgP+CYMDwv8AYMDBAP2g8HgH+g0DBYMMgPwAYX8gOMEwMG3kAg8OvgSBjg2BgcYGQIcBAY5CBg0Av//HAM///4MYgNBEIMOCoUMDoUAnBwGkEA"));
var snowIcon = require("heatshrink").decompress(atob("kEggITQj/AAYM98ADBsEwAYPAjADCj+AgOAj/gAYMIuEHwEAjEPAYQVChk4AYQhCAYcYBYQTDnEPgEB+EH///IAQACE4IAB8EICIPghwDB4EeBYNAjgDBg8EAYQYCg4bCgZuFA=="));
var rainIcon = require("heatshrink").decompress(atob("kEggIPMh+AAYM/8ADBuFwAYPgmADB4EbAYOAj/ggOAhnwg4aBnAeCjEcCIMMjADCDoQDHjAPCnAXCuEP///8EDAYJECAAXBwkAgPDhwDBwUMgEEhkggEOjFgFgMQLYQAOA=="));
var errIcon = require("heatshrink").decompress(atob("kEggILIgOAAYsD4ADBg/gAYMGsADBhkwAYsYjADCjgDBmEMAYNxxwDBsOGAYPBwYDEgOBwOAgYDB4EDHYPAgwDBsADDhgDBFIcwjAHBjE4AYMcmADBhhNCKIcG/4AGOw4A=="));
function loadSettings() {
settings = require("Storage").readJSON(SETTINGS_FILE,1)||{};
settings.grid = settings.grid||false;
@ -93,7 +105,49 @@ function prevInfo() {
}
}
var mm_prev = "xx";
/**
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")) return stormIcon;
if (condition.includes("freezing")||condition.includes("snow")||
condition.includes("sleet")) {
return snowIcon;
}
if (condition.includes("drizzle")||
condition.includes("shower")) {
return rainIcon;
}
if (condition.includes("rain")) return rainIcon;
if (condition.includes("clear")) return sunIcon;
if (condition.includes("few clouds")) return partSunIcon;
if (condition.includes("scattered clouds")) return cloudIcon;
if (condition.includes("clouds")) return cloudIcon;
if (condition.includes("mist") ||
condition.includes("smoke") ||
condition.includes("haze") ||
condition.includes("sand") ||
condition.includes("dust") ||
condition.includes("fog") ||
condition.includes("ash") ||
condition.includes("squalls") ||
condition.includes("tornado")) {
return cloudIcon;
}
return cloudIcon;
}
/**
Get weather stored in json file by weather app.
*/
function getWeather() {
let jsonWeather = storage.readJSON('weather.json');
return jsonWeather;
}
function draw() {
var d = new Date();
@ -115,19 +169,27 @@ function draw() {
var x = (g.getWidth()/2);
var y = (g.getHeight()/3);
g.reset();
var weatherJson = getWeather();
var w_temp;
var w_icon;
var w_wind;
if (process.env.HWVERSION == 1) {
// avoid flicker on a bangle 1 by comparing with previous minute
if (mm_prev != mm) {
mm_prev = mm;
g.clearRect(0, 30, w, h - 24);
}
if (settings.weather && weatherJson && weatherJson.weather) {
var currentWeather = weatherJson.weather;
const temp = locale.temp(currentWeather.temp-273.15).match(/^(\D*\d*)(.*)$/);
w_temp = temp[1] + " " + temp[2];
w_icon = chooseIcon(currentWeather.txt);
const wind = locale.speed(currentWeather.wind).match(/^(\D*\d*)(.*)$/);
w_wind = wind[1] + " " + wind[2] + " " + (currentWeather.wrose||'').toUpperCase();
} else {
// on a b2 safe to just clear anyway as there is no flicker
g.clearRect(0, 30, w, h - 24);
w_temp = "Err";
w_wind = "???";
w_icon = errIcon;
}
g.reset();
g.clearRect(0, 30, w, h - 24);
// draw a grid like graph paper
if (settings.grid && process.env.HWVERSION !=1) {
g.setColor("#0f0");
@ -139,6 +201,18 @@ function draw() {
g.setColor(g.theme.fg);
// draw weather line
if (settings.weather) {
g.drawImage(w_icon, (w/2) - 40, 24);
g.setFontLatoSmall();
g.setFontAlign(-1,0); // left aligned
if (drawCount % 2 == 0)
g.drawString(w_temp, (w/2) + 6, 24 + ((y - 24)/2));
else
g.drawString( (w_wind.split(' ').slice(0, 2).join(' ')), (w/2) + 6, 24 + ((y - 24)/2));
// display first 2 words of the wind string eg '4 mph'
}
if (settings.font == "Architect")
g.setFontArchitect();
else if (settings.font == "GochiHand")
@ -161,36 +235,39 @@ function draw() {
// for the colon
g.setFontAlign(0,-1); // centre aligned
if (d.getSeconds()&1) {
g.drawString(":", x,y);
} else {
// on bangle 1, we are not using clearRect(), hide : by printing over it in reverse color
if (process.env.HWVERSION == 1) {
g.setColor(g.theme.bg);
g.drawString(":", x,y);
g.setColor(g.theme.fg);
}
}
g.setFontLatoSmall();
g.setFontAlign(0, -1);
g.drawString((infoData[infoMode].calc()), w/2, h - 24 - 24);
if (drawCount % 3600 == 0)
// recalc sunrise / sunset every hour
if (drawCount % 60 == 0)
updateSunRiseSunSet(new Date(), location.lat, location.lon);
drawCount++;
queueDraw();
}
// Only update when display turns on
if (process.env.BOARD!="SMAQ3") // hack for Q3 which is always-on
Bangle.on('lcdPower', function(on) {
if (secondInterval)
clearInterval(secondInterval);
secondInterval = undefined;
if (on)
secondInterval = setInterval(draw, 1000);
// timeout used to update every minute
var drawTimeout;
// schedule a draw for the next minute
function queueDraw() {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(function() {
drawTimeout = undefined;
nextInfo();
draw();
}, 60000 - (Date.now() % 60000));
}
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{
if (on) {
draw(); // draw immediately, queue redraw
} else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
}
});
Bangle.setUI("clockupdown", btn=> {
@ -204,8 +281,6 @@ loadFonts();
loadLocation();
g.clear();
var secondInterval = setInterval(draw, 1000);
draw();
Bangle.loadWidgets();
Bangle.drawWidgets();
draw();

View File

@ -4,6 +4,7 @@
// initialize with default settings...
let s = {
'grid': false,
'weather': false,
'font': "Lato"
}
@ -39,8 +40,16 @@
value: s.grid,
format: () => (s.grid ? 'Yes' : 'No'),
onchange: () => {
s.grid = !s.grid
save()
s.grid = !s.grid;
save();
},
},
'Show Weather': {
value: s.weather,
format: () => (s.weather ? 'Yes' : 'No'),
onchange: () => {
s.weather = !s.weather;
save();
},
}
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -4,3 +4,4 @@
0.04: Fix widget hiding code (fix #1046)
0.05: Fix typo in settings - Purple
0.06: Added dependancy on Pedometer Widget
0.07: Fixed icon and ong file to 48x48

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("oFAwgNKiIAIFqofegIf/DAUzAAMyAwUQD60T/4ACD7Q/cPxIf/YCofcDhYiSXYYfuUZgf/D/4f/D6USkUgD/4fuogAID6vtDw/UD6vu6geF73kb6vuEAtN9wfYMIneD7JADDwIfaIAJdBD7YgBHwQfbAAgfkf6Qf/D/4feogAID6oAND/4f/iAdJD/4f/D/4fUDxYABD74iODiAftTZgfnYYczAAMyD7UT/4ACH/S+bD8DAKD9Y="))
require("heatshrink").decompress(atob("mEw4UA///ssp4XthFCBwUBqoABqAaGBZcFBZdX1W1qgLHrwLKqv/6oLJAAILHioLJn5qBAAYLEBQoLeHQQABv4LjGAgLYq2qAAOlBbBHFBdPAKcQLdWcb7jAAoLcn4LKgEVHQVUBQsAgoLLq//6oLIr2q2oXJBZQvCqALGgILTA="))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -1,3 +1,4 @@
0.01: First release
0.02: Fix typo to Purple
0.03: Added dependancy on Pedometer Widget
0.04: Fixed icon and png to 48x48 pixels

View File

@ -11,6 +11,7 @@
* Uses pedometer widget to get latest step count
* Dependant apps are installed when Rebble installs
* Uses the whole screen, widgets are made invisible but still run in the background
* The icon is James Dean - 'Rebel Without a Cause'
![](screenshot_rebble.png)
![](screenshot_rebble2.png)

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("oFA4X/AAIHBw3Aiv3HmE/HQQAF/gPEnWqAAOpy2VqoFB3gPIBoIABtQPJ1PVqv1q3qB5OlrNVEIQPK2tlBwOptQPIyvdH4VtrQPI3tbqtdB4OaB5FVH4NV0pgBB5F13//MIIPJ1O2TgWV/o/I1fbB4WpqoPI1NvB4REBJ5APD/wPBD5JOBB4WVqwPH0oPE0oPJ/NX//6AoNVF5HZq3pq2qSYIPI6tX+pNBB5Ol6v6B4IABH5P7//b1oPBN5GlLwPr9IPK1IPC/SvK1QPCOAIPL6te//5B5lW/5ABL5APB/wPB3IPJ1Y/C/yuBF5APC9X+yo/K34LB3QPBtQPJ//23SPB1QPI3eVs2qJwIPJ1flqyeBtQPJtZPBLwIPKzf/1ROCB5OWAQJOBB5QsBAAQGBf5FlB5tVvoPMNQO9B4daB5O+B4aPIqtX35tBB5M1qtbB4i/HB4WvOAjvGB4IpBIQIADB46aBB4t8B49VB54AFB6zrB1Wm1RTBywPI0oPCeQOaB4+ltOlq2V02VqwPOrQPIF5w/PFQIvPB71pH4uqX8g"))
require("heatshrink").decompress(atob("mEw4X/AoOG4EV+/I+dVAAVUCgcFBIYABpIJBgcFoIKEqkQgEH6EH0ILEqAhCgkBqEVBYdAhUBBoU9GAlAlw5CgERgILDIocEgEGoALDlEHwEAlkUg8EBYfAFwVA+BgEqmQjWrBgMQhgvDqmA9Wq1WsNoMALweDBQIAB4E8BYdTpwLD/kA4AXDjwKC1f/IAILDnQLC1//4ALEHQQLCKgILDFwYLB6EATgVABYe///MNgdA3kQEoILGqCNBlfQh//4NAPAVQ+YLBQYM/ocABYfAiEqgE0g6DBF4eAlFrYQZHDoOu1Xo8lgBYtCKIOo9aOBAAJrCBYWv9X/+gXEqSZC/f//4LHz/6DQIjEBYOhgG6BY1a1WggDCB3ojErYTBoEOa4QLF1X9jWrXwILGKYOvBYtfKYX+17iBHYdX1WQgf/34LBUwQLB1cLWIJqCBYdV9W+1+//oLBWQVVqnuD4M/KQoAB/+kBYJGBCwYLCI4P/DQILFnwLCEQ1Vp+q/46CBYtDXgJ1FAAVwfI4ABqAUCBY8A9gLIqEA9ALEKYYLB9YLERwQ="))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -42,3 +42,4 @@
0.37: Going into passkey menu now saves settings with passkey
0.38: Restructed menus as per forum discussion
0.39: Fix misbehaving debug info option
0.40: Moved off into Utils, put System after Apps

View File

@ -66,11 +66,10 @@ function showMainMenu() {
'': { 'title': 'Settings' },
'< Back': ()=>load(),
/*LANG*/'Apps': ()=>showAppSettingsMenu(),
/*LANG*/'Bluetooth': ()=>showBLEMenu(),
/*LANG*/'System': ()=>showSystemMenu(),
/*LANG*/'Bluetooth': ()=>showBLEMenu(),
/*LANG*/'Alerts': ()=>showAlertsMenu(),
/*LANG*/'Utils': ()=>showUtilMenu(),
/*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() }
/*LANG*/'Utils': ()=>showUtilMenu()
};
return E.showMenu(mainmenu);
@ -537,7 +536,8 @@ function showUtilMenu() {
setTimeout(showMainMenu, 50);
} else showUtilMenu();
});
}
},
/*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() }
};
if (Bangle.factoryReset) {
menu['Factory Reset'] = ()=>{

2
apps/sonicclk/Changelog Normal file
View File

@ -0,0 +1,2 @@
1.00 Added sonic clock app
1.01 Fixed text alignment issue; Increased acceleration required to activate twist;

13
apps/sonicclk/README.md Normal file
View File

@ -0,0 +1,13 @@
# Sonic Clock
A classic sonic clock featuring run, stop and wait animations.
![Sonic Clock screenshot](screenshot.png)
## Usage
- Sonic will run when the screen is unlocked
- Sonic will stop when the screen is locked
- Sonic will wait when looking at your watch face (when `Bangle.on("twist", fn)` is fired).
### Made with love by [Joseph](https://github.com/Johoseph) 🤗

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwkBiIA/AE0ZzIACBIgFFC7oTCylEzOIDYeZogX6LwWd7oYCAAOJC82UpoXFAAKnMC6x2CpIVFC/gSCxOYAYP///4C4X/DBIXWIIwWBDAWPAYIXedQJwG/8AgEP//wgAX2CwIADRoQXmSIoXtJAeEoi+C+lEoAcBogX7zOUondolEpvdAAQXgYIgXCAAwXlAAIYC6ENLx4XtAYMZDAvd6gWJC7IKJABgX/C74A/ADY"))

284
apps/sonicclk/app.js Normal file

File diff suppressed because one or more lines are too long

BIN
apps/sonicclk/app.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

1
apps/touchmenu/ChangeLog Normal file
View File

@ -0,0 +1 @@
0.01: App launched

40
apps/touchmenu/README.md Normal file
View File

@ -0,0 +1,40 @@
# TouchMenu
A redesign of the built-in `E.showMenu()` to take advantage of the full touch screen on the Bangle.js 2.
![screenshot](touchmenu.gif)
## Features
- All of the features of the built-in `E.showMenu()`
- Icon support for menu items:
```javascript
menu.items[0].icon = Graphics.createImage(...);
```
- Custom accent colors:
```javascript
E.showMenu({
"": {
cAB: g.theme.bg2, // Accent background
cAF: g.theme.fg2 // Accent foreground
}
})
```
- Automatic back button detection - name a button `< Back` and it will be given a special position and icon
## Controls
- Scroll through the options
- Tap on an option to select it
- Tap on a button again to use it
- Tap on a selected Boolean to toggle it
- Tap on a selected number to change - tap the right side of the screen to decrease, left side to increase
- If detected, tap on the back button in the upper left to go back
## Requests
Contact information is on my website: [kyleplo](https://kyleplo.com)
## Creator
[kyleplo](https://kyleplo.com)

View File

@ -0,0 +1,197 @@
E.showMenu = function(items) {
const gw = g.getWidth();
const gh = g.getHeight();
Bangle.removeAllListeners("drag");
if(!items){
delete m;
g.clearRect(0, 30, gw, gh - 30);
return false;
}
var loc = require("locale");
var m = {
info: {
title: "Menu",
cB: g.theme.bg,
cF: g.theme.fg,
cHB: g.theme.bgH,
cHF: g.theme.fgH,
cAB: g.theme.bg2,
cAF: g.theme.fg2,
predraw : () => {},
preflip : () => {}
},
scroll: 0,
items: [],
selected: -1,
draw: () => {
g.reset().setFont('12x20');
m.info.predraw(g);
g.setColor(m.info.cB).fillRect(0, 50, gw, gh - 30).setColor(m.info.cF);
m.items.forEach((e, i) => {
const s = (i * 48) - m.scroll + 50;
if(s < 30 || s > gh - 74){
return false;
}
if(i == m.selected){
g.setColor(m.info.cHB).fillRect(0, s, gw, Math.min(s + 48, gh - 30)).setColor(m.info.cHF);
}else{
g.setColor(m.info.cF);
}
g.drawString(e.title, (e.icon ? 30 : 10), s + 5);
if(e.icon){
g.drawImage(e.icon, 5, s + 5);
}
if(e.type && s < gh - 72){
if(e.format){
g.setFontAlign(1, -1, 0).drawString(e.format(e.value), gw - 10, s + 25).setFontAlign(-1, -1, 0);
}else{
g.setFontAlign(1, -1, 0).drawString(e.value, gw - 10, s + 25).setFontAlign(-1, -1, 0);
}
}
});
g.setColor(m.info.cAB).fillRect(0, 30, gw, 50);
g.setColor(m.info.cAF).drawString(m.info.title, (m.back ? 30 : 10), 32);
if(m.back){
g.drawLine(5, 40, 20, 40);
g.drawLine(5, 40, 15, 33);
g.drawLine(5, 40, 15, 47);
}
m.info.preflip(g, m.scroll > 0, m.scroll < (m.items.length - 1) * 48);
},
select: (x, y) => {
if(m.selected == -1 || m.selected !== Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0)){
if(y){
if(y < 50 || y > gh - 30){
return false;
}else{
m.selected = Math.max(Math.min(Math.floor((y + m.scroll - 50) / 48), m.items.length - 1), 0);
}
}else{
m.selected = Math.floor(m.scroll / 48);
}
m.draw();
}else{
if(m.items[m.selected].type && m.items[m.selected].type === "boolean"){
m.items[m.selected].value = !m.items[m.selected].value;
m.items[m.selected].onchange(m.items[m.selected].value);
m.draw();
}else if(m.items[m.selected].type && m.items[m.selected].type === "number"){
if(x && x < (gw / 2)){
m.items[m.selected].value = m.items[m.selected].value - (m.items[m.selected].step ? m.items[m.selected].step : 1);
}else{
m.items[m.selected].value = m.items[m.selected].value + (m.items[m.selected].step ? m.items[m.selected].step : 1);
}
if(m.items[m.selected].value > (m.items[m.selected].max ? m.items[m.selected].max : Infinity)){
m.items[m.selected].value = m.items[m.selected].min ? m.items[m.selected].min : 0;
}
if(m.items[m.selected].value < (m.items[m.selected].min ? m.items[m.selected].min : 0)){
m.items[m.selected].value = m.items[m.selected].max ? m.items[m.selected].max : 10;
}
m.items[m.selected].onchange(m.items[m.selected].value);
m.draw();
}else{
if(m.items[m.selected]){
m.items[m.selected]();
}
}
}
},
move: d => {
m.scroll += (d * 48);
m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * 48);
m.selected = Math.max(Math.min(Math.floor((m.scroll - 50) / 48), m.items.length - 1), 0);
m.draw();
},
};
Object.keys(items).forEach(i => {
if(i == ""){
m.info = Object.assign(m.info, items[i]);
}else if(i === "< Back" && items[i]){
m.back = items[i];
}else if(items[i]){
m.items.push(items[i]);
m.items[m.items.length - 1].title = loc.translate(i);
if(items[i].hasOwnProperty("value")){
if(typeof items[i].value === "boolean"){
m.items[m.items.length - 1].type = "boolean";
}else{
m.items[m.items.length - 1].type = "number";
}
}
}
});
m.info.title = loc.translate(m.info.title);
m.draw();
Bangle.on("drag", d => {
if(!d.b){
return false;
}
if(d.dx == 0 && d.dy == 0){
if(d.x < 30 && d.y < 50){
m.back();
return false;
}
m.select(d.x, d.y);
}else{
m.selected = -1;
m.scroll -= d.dy;
m.scroll = Math.min(Math.max(m.scroll, 0), (m.items.length - 1) * 48);
m.draw();
}
});
return m;
};
E.showAlert = function (e, t){
if(!e){
E.showMenu();
return false;
}
return new Promise(r => {
const menu = {
"": {
"title": (t ? t : "Alert")
},
Ok: () => {
E.showMenu();
r();
}
};
menu[e] = () => {};
E.showMenu(menu);
});
};
E.showMessage = E.showAlert;
E.showPrompt = function (e, t){
if(!e){
E.showMenu();
return false;
}
return new Promise(r => {
const menu = {
"": {
"title": (t && t.title ? t.title : "Choose")
}
};
menu[e] = () => {};
if(t && t.buttons){
Object.keys(t.buttons).forEach(b => {
menu[b] = () => {
E.showMenu();
r(t.buttons[b]);
};
});
}else{
menu.Yes = () => {
E.showMenu();
r(true);
};
menu.No = () => {
E.showMenu();
r(false);
};
}
E.showMenu(menu);
});
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 602 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -11,3 +11,4 @@
0.12: Fixed for Bangle 2
0.13: Fillbar setting added, see README
0.14: Fix drawing the bar when charging
0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled)

View File

@ -13,6 +13,7 @@
'fillbar': false,
'charger': true,
'hideifmorethan': 100,
'alwaysoncharge': false,
}
// ...and overwrite them with any saved values
// This way saved values are preserved if a new version adds more settings
@ -68,6 +69,11 @@
format: x => x+"%",
onchange: save('hideifmorethan'),
},
'Show on charge': { // Not sure if this is readable enough in the 'big' menu
value: s.alwaysoncharge,
format: onOffFormat,
onchange: save('alwaysoncharge'),
},
}
E.showMenu(menu)
})

View File

@ -29,6 +29,7 @@
'percentage': true,
'charger': true,
'hideifmorethan': 100,
'alwaysoncharge': false,
};
Object.keys(DEFAULTS).forEach(k=>{
if (settings[k]===undefined) settings[k]=DEFAULTS[k]
@ -67,8 +68,11 @@
var w = 40;
if (Bangle.isCharging() && setting('charger'))
w += 16;
if (E.getBattery() > setting('hideifmorethan'))
if (E.getBattery() > setting('hideifmorethan')) {
w = 0;
if( Bangle.isCharging() && setting('alwaysoncharge') === true)
w = 56;
}
var changed = WIDGETS["batpc"].width != w;
WIDGETS["batpc"].width = w;
return changed;

2
core

@ -1 +1 @@
Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf
Subproject commit ae9586977948279d267f2749bf3a48d3aa753c11

View File

@ -40,7 +40,7 @@ function onFoundDeviceInfo(deviceId, deviceVersion) {
if (deviceId != "BANGLEJS" && deviceId != "BANGLEJS2") {
showToast(`You're using ${deviceId}, not a Bangle.js. Did you want <a href="https://espruino.com/apps">espruino.com/apps</a> instead?` ,"warning", 20000);
} else if (versionLess(deviceVersion, RECOMMENDED_VERSION)) {
showToast(`You're using an old Bangle.js firmware (${deviceVersion}). You can <a href="${fwURL}" target="_blank">update with the instructions here</a>` ,"warning", 20000);
showToast(`You're using an old Bangle.js firmware (${deviceVersion}) and ${RECOMMENDED_VERSION} is available (<a href="http://www.espruino.com/ChangeLog" target="_blank">see changes</a>). You can <a href="${fwURL}" target="_blank">update with the instructions here</a>` ,"warning", 20000);
}