forked from FOSS/BangleApps
Merge branch 'espruino:master' into master
commit
5f0511bd82
35
apps.json
35
apps.json
|
@ -4239,8 +4239,9 @@
|
|||
{
|
||||
"id": "antonclk",
|
||||
"name": "Anton Clock",
|
||||
"version": "0.03",
|
||||
"description": "A simple clock using the bold Anton font.",
|
||||
"version": "0.04",
|
||||
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
|
||||
"readme":"README.md",
|
||||
"icon": "app.png",
|
||||
"screenshots": [{"url":"screenshot.png"}],
|
||||
"type": "clock",
|
||||
|
@ -4249,8 +4250,10 @@
|
|||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"antonclk.app.js","url":"app.js"},
|
||||
{"name":"antonclk.settings.js","url":"settings.js"},
|
||||
{"name":"antonclk.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
],
|
||||
"data": [{"name":"antonclk.json"}]
|
||||
},
|
||||
{
|
||||
"id": "waveclk",
|
||||
|
@ -5162,15 +5165,16 @@
|
|||
{
|
||||
"id": "promenu",
|
||||
"name": "Pro Menu",
|
||||
"version": "0.01",
|
||||
"description": "Replace Bangle.js 1's built in menu function.",
|
||||
"version": "0.02",
|
||||
"description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.",
|
||||
"icon": "icon.png",
|
||||
"type": "boot",
|
||||
"tags": "system",
|
||||
"supports": ["BANGLEJS"],
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"screenshots": [{"url":"pro-menu-screenshot.png"}],
|
||||
"storage": [
|
||||
{"name":"promenu.boot.js","url":"boot.js"},
|
||||
{"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]},
|
||||
{"name":"promenu.boot.js","url":"bootb2.js","supports": ["BANGLEJS2"]},
|
||||
{"name":"promenu.img","url":"promenuIcon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
|
@ -5427,5 +5431,22 @@
|
|||
{"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [{"name":"puzzle15.json"}]
|
||||
},
|
||||
{
|
||||
"id": "flipper",
|
||||
"name": "flipper",
|
||||
"version": "0.01",
|
||||
"description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.",
|
||||
"readme":"README.md",
|
||||
"screenshots": [{"url":"flipper.png"}],
|
||||
"icon": "flipper.png",
|
||||
"type": "app",
|
||||
"tags": "game",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"flipper.app.js","url":"flipper.app.js"},
|
||||
{"name":"flipper.img","url":"flipper.icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
0.01: New App!
|
||||
0.02: Load widgets after setUI so widclk knows when to hide
|
||||
0.03: Clock now shows day of week under date.
|
||||
0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too.
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
# Anton Clock - Large font digital watch with seconds and date
|
||||
|
||||
Anton clock uses the "Anton" bold font to show the time in a clear, easily readable manner. On the Bangle.js 2, the time can be read easily even if the screen is locked and unlit.
|
||||
|
||||
## Features
|
||||
|
||||
The basic time representation only shows hours and minutes of the current time. However, Anton clock can show additional information:
|
||||
|
||||
* Seconds can be shown, either always or only if the screen is unlocked.
|
||||
* To help easy recognition, the seconds can be coloured in blue on the Bangle.js 2.
|
||||
* Date can be shown in three different formats:
|
||||
* ISO-8601: 2021-12-19
|
||||
* short local format: 19/12/2021, 19.12.2021
|
||||
* long local format: DEC 19 2021
|
||||
* Weekday can be shown (on seconds screen only instead of year)
|
||||
|
||||
## Usage
|
||||
|
||||
Install Anton clock through the Bangle.js app loader.
|
||||
Configure it through the default Bangle.js configuration mechanism
|
||||
(Settings app, "Apps" menu, "Anton clock" submenu).
|
||||
If you like it, make it your default watch face
|
||||
(Settings app, "System" menu, "Clock" submenu, select "Anton clock").
|
||||
|
||||
## Configuration
|
||||
|
||||
Anton clock is configured by the standard settings mechanism of Bangle.js's operating system:
|
||||
Open the "Settings" app, then the "Apps" submenu and below it the "Anton clock" menu.
|
||||
You configure Anton clock through several "on/off" switches in two menus.
|
||||
|
||||
### The main menu
|
||||
|
||||
The main menu contains several settings covering Anton clock in general.
|
||||
|
||||
* **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds.
|
||||
* **Date** - Format of the date representation. Possible values are
|
||||
* **Long** - "Long" date format in the current locale. Usually with the month as name, not number.
|
||||
* **Short** - "Short" date format in the current locale. Usually with the month as number.
|
||||
* **ISO8601** - Show the date in ISO-8601 format (YYYY-MM-DD), irrespective of the current locale.
|
||||
* **Show Weekday** - Weekday is shown in the time presentation without seconds.
|
||||
Weekday name depends on the current locale.
|
||||
If seconds are shown, the weekday is never shown as there is not enough space on the watch face.
|
||||
* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters.
|
||||
This can improve readability.
|
||||
* **Vector font** - Use the built-in vector font for dates and weekday.
|
||||
This can improve readability.
|
||||
Otherwise, a scaled version of the built-in 6x8 pixels font is used.
|
||||
|
||||
### The "Seconds" submenu
|
||||
|
||||
The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face.
|
||||
|
||||
* **Show** - Configure when the seconds should be shown at all:
|
||||
* **Never** - Seconds are never shown.
|
||||
In this case, hour and minute are a bit more centered on the screen and the clock will always only update every minute.
|
||||
This saves battery power.
|
||||
* **Unlocked** - Seconds are shown if the display is unlocked.
|
||||
On locked displays, only hour, minutes, date and optionally the weekday are shown.
|
||||
_This option is highly recommended on the Bangle.js 2!_
|
||||
* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state.
|
||||
_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._
|
||||
* **With ":"** - If enabled, a colon ":" is prepended to the seconds.
|
||||
This resembles the usual time representation "hh:mm:ss", even though the seconds are printed on a separate line.
|
||||
* **Color** - If enabled, seconds are shown in blue instead of black.
|
||||
If the date is shown on the seconds screen, it is colored read instead of black.
|
||||
This make the visual orientation much easier on the watch face.
|
||||
* **Date** - It is possible to show the date together with the seconds:
|
||||
* **No** - Date is _not_ shown in the seconds screen.
|
||||
In this case, the seconds are centered below hour and minute.
|
||||
* **Year** - Date is shown with day, month, and year. If "Date" in the main settings is configured to _ISO8601_, this is used here, too. Otherwise, the short local format is used.
|
||||
* **Weekday** - Date is shown with day, month, and weekday.
|
||||
|
||||
The date is coloured in red if the "Coloured" option is chosen.
|
||||
|
||||
## Compatibility
|
||||
|
||||
Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to hardware restrictions.
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
Before Width: | Height: | Size: 696 B After Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,99 @@
|
|||
// Settings menu for the enhanced Anton clock
|
||||
|
||||
(function(back) {
|
||||
var FILE = "antonclk.json";
|
||||
// Load settings
|
||||
var settings = Object.assign({
|
||||
secondsOnUnlock: false,
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
|
||||
// Helper method which uses int-based menu item for set of string values
|
||||
function stringItems(startvalue, writer, values) {
|
||||
return {
|
||||
value: (startvalue === undefined ? 0 : values.indexOf(startvalue)),
|
||||
format: v => values[v],
|
||||
min: 0,
|
||||
max: values.length - 1,
|
||||
wrap: true,
|
||||
step: 1,
|
||||
onchange: v => {
|
||||
writer(values[v]);
|
||||
writeSettings();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Helper method which breaks string set settings down to local settings object
|
||||
function stringInSettings(name, values) {
|
||||
return stringItems(settings[name], v => settings[name] = v, values);
|
||||
}
|
||||
|
||||
var mainmenu = {
|
||||
"": {
|
||||
"title": "Anton clock"
|
||||
},
|
||||
"< Back": () => back(),
|
||||
"Seconds...": () => E.showMenu(secmenu),
|
||||
"Date": stringInSettings("dateOnMain", ["Short", "Long", "ISO8601"]),
|
||||
"Show Weekday": {
|
||||
value: (settings.weekDay !== undefined ? settings.weekDay : true),
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.weekDay = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Uppercase": {
|
||||
value: (settings.upperCase !== undefined ? settings.upperCase : false),
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.upperCase = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Vector font": {
|
||||
value: (settings.vectorFont !== undefined ? settings.vectorFont : false),
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.vectorFont = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// Submenu
|
||||
var secmenu = {
|
||||
"": {
|
||||
"title": "Show seconds..."
|
||||
},
|
||||
"< Back": () => E.showMenu(mainmenu),
|
||||
"Show": stringInSettings("secondsMode", ["Never", "Unlocked", "Always"]),
|
||||
"With \":\"": {
|
||||
value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : false),
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.secondsWithColon = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Color": {
|
||||
value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false),
|
||||
format: v => v ? "On" : "Off",
|
||||
onchange: v => {
|
||||
settings.secondsColoured = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Date": stringInSettings("dateOnSecs", ["No", "Year", "Weekday"])
|
||||
};
|
||||
|
||||
// Actually display the menu
|
||||
E.showMenu(mainmenu);
|
||||
|
||||
});
|
||||
|
||||
// end of file
|
|
@ -11,4 +11,4 @@ The year itself begins on the December solstice. Because that always happens, th
|
|||
|
||||
The epoch (year numbering) begins in the last year when the perihelion coincided with the June solstice, near the beginning of the Holocene era. That astronomical basis makes the calendar free from politics, religion, or geography.
|
||||
|
||||
While the year number remains cardinal, BTN5 toggles between cardinal and ordinal for the rest of the calendar segments. BTN4 adds or removes a quickly changing digit to or from the clock.
|
||||
While the year number remains cardinal, tapping on the right side of the watch face toggles between cardinal and ordinal for the rest of the calendar segments. Tapping on the left adds or removes a quickly changing digit to or from the clock.
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: first release
|
|
@ -0,0 +1,20 @@
|
|||
# Flipper
|
||||
|
||||

|
||||
|
||||
*A utility to switch from the dark to the light theme and vice versa*
|
||||
|
||||
* If the current theme is dark it will switch to the light theme
|
||||
* If the current theme is light it will switch to the dark theme
|
||||
* Combine with the awesome pattern launcher and it saves loads of time
|
||||
|
||||
|
||||
## Demo Video
|
||||
|
||||
There's no screenshot but there is a [demo video.](https://espruino.microco.sm/api/v1/files/9caa1afef7e4cce1d9b518af2dd271f1a57c5ecc.mp4)
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
* Nothing left to add
|
||||
|
||||
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/)
|
|
@ -0,0 +1,39 @@
|
|||
const storage = require('Storage');
|
||||
let settings = storage.readJSON('setting.json', 1);
|
||||
|
||||
function cl(x) { return g.setColor(x).getColor(); }
|
||||
|
||||
function upd(th) {
|
||||
g.theme = th;
|
||||
settings.theme = th;
|
||||
storage.write('setting.json', settings);
|
||||
delete g.reset;
|
||||
g._reset = g.reset;
|
||||
g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); };
|
||||
g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); };
|
||||
g.clear(1);
|
||||
}
|
||||
|
||||
function flipTheme() {
|
||||
if (!g.theme.dark) {
|
||||
upd({
|
||||
fg:cl("#fff"), bg:cl("#000"),
|
||||
fg2:cl("#0ff"), bg2:cl("#000"),
|
||||
fgH:cl("#fff"), bgH:cl("#00f"),
|
||||
dark:true
|
||||
});
|
||||
} else {
|
||||
upd({
|
||||
fg:cl("#000"), bg:cl("#fff"),
|
||||
fg2:cl("#000"), bg2:cl("#cff"),
|
||||
fgH:cl("#000"), bgH:cl("#0ff"),
|
||||
dark:false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
flipTheme();
|
||||
setTimeout(load, 20);
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar"))
|
Binary file not shown.
After Width: | Height: | Size: 644 B |
|
@ -1 +1,2 @@
|
|||
0.01: New App!
|
||||
0.02: Add Bangle.js 2 Support
|
||||
|
|
|
@ -70,7 +70,7 @@ E.showMenu = function(items) {
|
|||
if(g.theme.dark){
|
||||
fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+20);
|
||||
}else{
|
||||
fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-10);
|
||||
fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20);
|
||||
}
|
||||
g.setColor(hl ? g.theme.fgH : g.theme.fg);
|
||||
g.setFontAlign(-1,-1);
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
E.showMenu = function(items) {
|
||||
function RectRnd(x1,y1,x2,y2,r) {
|
||||
pp = [];
|
||||
pp.push.apply(pp,g.quadraticBezier([x2-r,y1, x2,y1,x2,y1+r]));
|
||||
pp.push.apply(pp,g.quadraticBezier([x2,y2-r,x2,y2,x2-r,y2]));
|
||||
pp.push.apply(pp,g.quadraticBezier([x1+r,y2,x1,y2,x1,y2-r]));
|
||||
pp.push.apply(pp,g.quadraticBezier([x1,y1+r,x1,y1,x1+r,y1]));
|
||||
return pp;
|
||||
}
|
||||
function fillRectRnd(x1,y1,x2,y2,r,c) {
|
||||
g.setColor(c);
|
||||
g.fillPoly(RectRnd(x1,y1,x2,y2,r),1);
|
||||
g.setColor(255,255,255);
|
||||
}
|
||||
function drawRectRnd(x1,y1,x2,y2,r,c) {
|
||||
g.setColor(c);
|
||||
g.drawPoly(RectRnd(x1,y1,x2,y2,r),1);
|
||||
g.setColor(255,255,255);
|
||||
}
|
||||
g.reset().clearRect(Bangle.appRect); // clear if no menu supplied
|
||||
Bangle.setLCDPower(1); // ensure screen is on
|
||||
if (!items) {
|
||||
Bangle.setUI();
|
||||
return;
|
||||
}
|
||||
var menuItems = Object.keys(items);
|
||||
var options = items[""];
|
||||
if (options) menuItems.splice(menuItems.indexOf(""),1);
|
||||
if (!(options instanceof Object)) options = {};
|
||||
options.fontHeight = options.fontHeight||25;
|
||||
if (options.selected === undefined)
|
||||
options.selected = 0;
|
||||
var ar = Bangle.appRect;
|
||||
var x = ar.x;
|
||||
var x2 = ar.x2;
|
||||
var y = ar.y;
|
||||
var y2 = ar.y2 - 12; // padding at end for arrow
|
||||
if (options.title)
|
||||
y += 22;
|
||||
var loc = require("locale");
|
||||
var l = {
|
||||
lastIdx : 0,
|
||||
draw : function(rowmin,rowmax) {
|
||||
var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length);
|
||||
var idx = E.clip(options.selected-( rows>>1),0,menuItems.length-rows);
|
||||
if (idx!=l.lastIdx) rowmin=undefined; // redraw all if we scrolled
|
||||
l.lastIdx = idx;
|
||||
var iy = y;
|
||||
g.reset().setFontAlign(0,-1,0).setFont('12x20');
|
||||
if (options.predraw) options.predraw(g);
|
||||
if (rowmin===undefined && options.title)
|
||||
g.drawString(options.title,(x+x2)/2,y-21).drawLine(x,y-2,x2,y-2).
|
||||
setColor(g.theme.fg).setBgColor(g.theme.bg);
|
||||
iy += 4;
|
||||
if (rowmin!==undefined) {
|
||||
if (idx<rowmin) {
|
||||
iy += options.fontHeight*(rowmin-idx);
|
||||
idx=rowmin;
|
||||
}
|
||||
if (idx+rows>rowmax) {
|
||||
rows = 1+rowmax-rowmin;
|
||||
}
|
||||
}
|
||||
while (rows--) {
|
||||
var name = menuItems[idx];
|
||||
var item = items[name];
|
||||
var hl = (idx==options.selected && !l.selectEdit);
|
||||
if(g.theme.dark){
|
||||
fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+40);
|
||||
}else{
|
||||
fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20);
|
||||
}
|
||||
g.setColor(hl ? g.theme.fgH : g.theme.fg);
|
||||
g.setFontAlign(-1,-1);
|
||||
var v = item.value;
|
||||
v = loc.translate(""+v);
|
||||
if(loc.translate(name).length >= 17-v.length && "object" == typeof item){
|
||||
if (item.format) v=item.format(v);
|
||||
g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7);
|
||||
}else{
|
||||
if(loc.translate(name).length >= 15){
|
||||
g.drawString(loc.translate(name).substring(0, 15)+"...",x+3.7,iy+2.7);
|
||||
}else{
|
||||
g.drawString(loc.translate(name),x+3.7,iy+2.7);
|
||||
}
|
||||
}
|
||||
if ("object" == typeof item) {
|
||||
var xo = x2;
|
||||
var v = item.value;
|
||||
if (item.format) v=item.format(v);
|
||||
v = loc.translate(""+v);
|
||||
if (l.selectEdit && idx==options.selected) {
|
||||
xo -= 24 + 1;
|
||||
g.setColor(g.theme.fgH).drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2});
|
||||
}
|
||||
g.setFontAlign(1,-1);
|
||||
g.drawString(v,xo-2,iy+1);
|
||||
}
|
||||
g.setColor(g.theme.fg);
|
||||
iy += options.fontHeight;
|
||||
idx++;
|
||||
}
|
||||
g.setFontAlign(-1,-1);
|
||||
g.setColor((idx<menuItems.length)?g.theme.fg:g.theme.bg).fillPoly([72,166,104,166,88,174]);
|
||||
g.flip();
|
||||
},
|
||||
select : function() {
|
||||
var item = items[menuItems[options.selected]];
|
||||
if ("function" == typeof item) item(l);
|
||||
else if ("object" == typeof item) {
|
||||
// if a number, go into 'edit mode'
|
||||
if ("number" == typeof item.value)
|
||||
l.selectEdit = l.selectEdit?undefined:item;
|
||||
else { // else just toggle bools
|
||||
if ("boolean" == typeof item.value) item.value=!item.value;
|
||||
if (item.onchange) item.onchange(item.value);
|
||||
}
|
||||
l.draw();
|
||||
}
|
||||
},
|
||||
move : function(dir) {
|
||||
var item = l.selectEdit;
|
||||
if (item) {
|
||||
item.value -= (dir||1)*(item.step||1);
|
||||
if (item.min!==undefined && item.value<item.min) item.value = item.wrap ? item.max : item.min;
|
||||
if (item.max!==undefined && item.value>item.max) item.value = item.wrap ? item.min : item.max;
|
||||
if (item.onchange) item.onchange(item.value);
|
||||
l.draw(options.selected,options.selected);
|
||||
} else {
|
||||
var lastSelected=options.selected;
|
||||
options.selected = (dir+options.selected+menuItems.length)%menuItems.length;
|
||||
l.draw(Math.min(lastSelected,options.selected), Math.max(lastSelected,options.selected));
|
||||
}
|
||||
}
|
||||
};
|
||||
l.draw();
|
||||
Bangle.setUI("updown",dir => {
|
||||
if (dir) l.move(dir);
|
||||
else l.select();
|
||||
});
|
||||
return l;
|
||||
};
|
Loading…
Reference in New Issue