Merge branch 'master' of https://github.com/berkenbu/BangleApps
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"aclock.app.js","url":"clock-analog.js"},
|
||||
|
|
|
@ -8,4 +8,5 @@
|
|||
0.06: fixes #1271 - wrong settings name
|
||||
when weekday name and calendar weeknumber are on then display is <weekday short> #<calweek>
|
||||
week is buffered until date or timezone changes
|
||||
0.07: align default settings with app.js (otherwise the initial displayed settings will be confusing to users)
|
||||
0.07: align default settings with app.js (otherwise the initial displayed settings will be confusing to users)
|
||||
0.08: fixed calendar weeknumber not shortened to two digits
|
|
@ -99,7 +99,7 @@ function updateState() {
|
|||
}
|
||||
|
||||
function isoStr(date) {
|
||||
return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2);
|
||||
return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).slice(-2) + "-" + ("0" + date.getDate()).slice(-2);
|
||||
}
|
||||
|
||||
var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested)
|
||||
|
@ -140,7 +140,7 @@ function draw() {
|
|||
g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time
|
||||
if (secondsScreen) {
|
||||
y += 65;
|
||||
var secStr = (secondsWithColon ? ":" : "") + ("0" + date.getSeconds()).substr(-2);
|
||||
var secStr = (secondsWithColon ? ":" : "") + ("0" + date.getSeconds()).slice(-2);
|
||||
if (doColor())
|
||||
g.setColor(0, 0, 1);
|
||||
g.setFont("AntonSmall");
|
||||
|
@ -193,7 +193,7 @@ function draw() {
|
|||
if (calWeek || weekDay) {
|
||||
var dowcwStr = "";
|
||||
if (calWeek)
|
||||
dowcwStr = " #" + ("0" + ISO8601calWeek(date)).substring(-2);
|
||||
dowcwStr = " #" + ("0" + ISO8601calWeek(date)).slice(-2);
|
||||
if (weekDay)
|
||||
dowcwStr = require("locale").dow(date, calWeek ? 1 : 0) + dowcwStr; //weekDay e.g. Monday or weekDayShort #<calWeek> e.g. Mon #01
|
||||
else //week #01
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "antonclk",
|
||||
"name": "Anton Clock",
|
||||
"version": "0.07",
|
||||
"version": "0.08",
|
||||
"description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.",
|
||||
"readme":"README.md",
|
||||
"icon": "app.png",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"berlin-clock-screenshot.png"}],
|
||||
"storage": [
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
0.01: New App
|
||||
0.02: app keeps track of statistics now
|
|
@ -2,7 +2,7 @@
|
|||
"name": "Bordle",
|
||||
"shortName":"Bordle",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"version":"0.02",
|
||||
"description": "Bangle version of a popular word search game",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"screenshots": [{"url":"screenshot_calculator.png"}],
|
||||
"tags": "app,tool",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"calculator.app.js","url":"app.js"},
|
||||
{"name":"calculator.img","url":"calculator-icon.js","evaluate":true}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock,cli,command,bash,shell",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"cliock.app.js","url":"app.js"},
|
||||
|
|
|
@ -3,3 +3,4 @@
|
|||
0.03: fix metadata.json to allow setting as clock
|
||||
0.04: added heart rate which is switched on when cycled to it through up/down touch on rhs
|
||||
0.05: changed text to uppercase, just looks better, removed colons on text
|
||||
0.06: better contrast for light theme, use fg color instead of dithered for ring
|
||||
|
|
|
@ -28,5 +28,6 @@ See [#1248](https://github.com/espruino/BangleApps/issues/1248)
|
|||
|
||||
## Screenshots
|
||||

|
||||

|
||||
|
||||
It is worth looking at the real thing though as the screenshot does not do it justice.
|
||||
It is worth looking at the real thing though as the screenshots do not do it justice.
|
||||
|
|
|
@ -41,10 +41,17 @@ Graphics.prototype.setFontRoboto20 = function(scale) {
|
|||
};
|
||||
|
||||
function assignPalettes() {
|
||||
// palette for 0-40%
|
||||
pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.fg), g.toColor("#00f")]);
|
||||
// palette for 50-100%
|
||||
pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.toColor(settings.gy), g.toColor("#00f")]);
|
||||
if (g.theme.dark) {
|
||||
// palette for 0-40%
|
||||
pal1 = new Uint16Array([g.theme.bg, g.toColor(settings.gy), g.toColor(settings.fg), g.toColor("#00f")]);
|
||||
// palette for 50-100%
|
||||
pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.toColor(settings.gy), g.toColor("#00f")]);
|
||||
} else {
|
||||
// palette for 0-40%
|
||||
pal1 = new Uint16Array([g.theme.bg, g.theme.fg, g.toColor(settings.fg), g.toColor("#00f")]);
|
||||
// palette for 50-100%
|
||||
pal2 = new Uint16Array([g.theme.bg, g.toColor(settings.fg), g.theme.fg, g.toColor("#00f")]);
|
||||
}
|
||||
}
|
||||
|
||||
function setSmallFont20() {
|
||||
|
@ -109,10 +116,10 @@ function updateSunRiseSunSet(now, lat, lon, line){
|
|||
const infoData = {
|
||||
ID_DATE: { calc: () => {var d = (new Date()).toString().split(" "); return d[2] + ' ' + d[1] + ' ' + d[3];} },
|
||||
ID_DAY: { calc: () => {var d = require("locale").dow(new Date()).toLowerCase(); return d[0].toUpperCase() + d.substring(1);} },
|
||||
ID_SR: { calc: () => 'Sunrise ' + sunRise },
|
||||
ID_SS: { calc: () => 'Sunset ' + sunSet },
|
||||
ID_STEP: { calc: () => 'Steps ' + getSteps() },
|
||||
ID_BATT: { calc: () => 'Battery ' + E.getBattery() + '%' },
|
||||
ID_SR: { calc: () => 'SUNRISE ' + sunRise },
|
||||
ID_SS: { calc: () => 'SUNSET ' + sunSet },
|
||||
ID_STEP: { calc: () => 'STEPS ' + getSteps() },
|
||||
ID_BATT: { calc: () => 'BATTERY ' + E.getBattery() + '%' },
|
||||
ID_HRM: { calc: () => hrmCurrent }
|
||||
};
|
||||
|
||||
|
@ -225,7 +232,7 @@ function drawSteps() {
|
|||
setSmallFont();
|
||||
g.setFontAlign(0,0);
|
||||
g.setColor(g.theme.fg);
|
||||
g.drawString('Steps ' + getSteps(), w/2, (3*h/4) - 4);
|
||||
g.drawString('STEPS ' + getSteps(), w/2, (3*h/4) - 4);
|
||||
drawingSteps = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{ "id": "daisy",
|
||||
"name": "Daisy",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"dependencies": {"mylocation":"app"},
|
||||
"description": "A clock based on the Pastel clock with large ring guage for steps",
|
||||
"description": "A beautiful digital clock with large ring guage, idle timer and a cyclic information line that includes, day, date, steps, battery, sunrise and sunset times",
|
||||
"icon": "app.png",
|
||||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"screenshots": [{"url":"screenshot_daisy2.jpg"}],
|
||||
"screenshots": [{"url":"screenshot_daisy3.png"}],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"daisy.app.js","url":"app.js"},
|
||||
|
|
Before Width: | Height: | Size: 4.7 KiB |
After Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 3.2 KiB |
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"ffcniftyb.app.js","url":"app.js"},
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"floralclk.app.js","url":"app.js"},
|
||||
|
|
|
@ -5,4 +5,5 @@
|
|||
0.05: Chevron marker on the randomly added square
|
||||
0.06: Fixed issue 1609 added a message popup state handler to control unwanted screen redraw
|
||||
0.07: Optimized the mover algorithm for efficiency (work in progress)
|
||||
0.08: Bug fix at end of the game with victorious splash and glorious orchestra
|
||||
0.08: Bug fix at end of the game with victorious splash and glorious orchestra
|
||||
0.09: Added settings menu, removed symbol selection button (*), added highscore reset
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
# Play the game of 1024
|
||||
|
||||
Move the tiles by swiping to the lefthand, righthand or up- and downward side of the watch.
|
||||
Move the tiles by swiping left, right, up- or downward over the watchface.
|
||||
|
||||
When two tiles with the same number are squashed together they will add up as exponentials:
|
||||
|
||||
|
@ -21,16 +21,28 @@ Use the side **BTN** to exit the game, score and tile positions will be saved.
|
|||
|
||||
## Buttons on the screen
|
||||
|
||||
- Button **U**: Undo the last move. There are currently a maximum of 4 undo levels. The level is indicated with a small number in the lower righthand corner of the Undo button
|
||||
- Button **\***: Change the text on the tile to number, capitals or Roman numbers
|
||||
- Button **R**: Reset the game. The Higscore will be remembered. You will be prompted first.
|
||||
- Button **U**: Undo the last move. There are currently a maximum of 9 undo levels. The level is indicated with a small number in the lower righthand corner of the Undo button
|
||||
- You can set the maximum undo level in the Apps settings menu.
|
||||
|
||||
- Button **R**: Reset the game. The Highscore will be remembered. You will be prompted first.
|
||||
- The highscore value can be reset in the Apps settings menu.
|
||||
|
||||
Apps setting: 
|
||||
|
||||
- Stuff you can change in de 1024 Game settings:
|
||||
- Symbols on the cells: numerical, alphabetical or Roman
|
||||
- Undo levels [0-9]
|
||||
- Exit: how to exit the game: long or short press
|
||||
- Debug mode: on or off. This will log all kinds of stuff in the console of the Web IDE
|
||||
- Reset Highsccore: Tired of looking at the old highscore? Now you can set it to 0 again.
|
||||
|
||||
### Credits
|
||||
|
||||
Game 1024 is based on Saming's 2048 and Misho M. Petkovic 1024game.org and conceptually similar to Threes by Asher Vollmer.
|
||||
|
||||
In Dark theme with numbers:
|
||||

|
||||

|
||||
|
||||
In Light theme with characters:
|
||||

|
||||

|
||||
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
const debugMode = 'off'; // valid values are: off, test, production, development
|
||||
let settings = Object.assign({
|
||||
// default values
|
||||
maxUndoLevels: 4,
|
||||
charIndex: 0,
|
||||
clockMode: true,
|
||||
debugMode: false,
|
||||
}, require('Storage').readJSON("game1024.settings.json", true) || {});
|
||||
|
||||
const clockMode = settings.clockMode!==undefined ? settings.clockMode : true;
|
||||
const debugMode = settings.debugMode!==undefined ? settings.debugMode : false; // #settings -- valid values are: true or false
|
||||
const maxUndoLevels = settings.maxUndoLevels!==undefined ? settings.maxUndoLevels : 4; // #settings
|
||||
const charIndex = settings.charIndex!==undefined ? settings.charIndex : 0; // #settings -- plain numbers on the grid
|
||||
|
||||
delete settings; // remove unneeded settings from memory
|
||||
|
||||
const middle = {x:Math.floor(g.getWidth()/2)-20, y: Math.floor(g.getHeight()/2)};
|
||||
const rows = 4, cols = 4;
|
||||
const borderWidth = 6;
|
||||
const rows = 4, cols = 4; // #settings
|
||||
const borderWidth = 6;
|
||||
const sqWidth = (Math.floor(Bangle.appRect.w - 48) / rows) - borderWidth;
|
||||
const cellColors = [{bg:'#00FFFF', fg: '#000000'},
|
||||
{bg:'#FF00FF', fg: '#000000'}, {bg:'#808000', fg: '#FFFFFF'}, {bg:'#0000FF', fg: '#FFFFFF'}, {bg:'#008000', fg: '#FFFFFF'},
|
||||
|
@ -13,12 +27,8 @@ const cellChars = [
|
|||
['0','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'],
|
||||
['0','I', 'II', 'III', 'IV', 'V', 'VI', 'VII','VIII', 'IX', 'X']
|
||||
];
|
||||
// const numInitialCells = 2;
|
||||
const maxUndoLevels = 4;
|
||||
const noExceptions = true;
|
||||
let charIndex = 0; // plain numbers on the grid
|
||||
const themeBg = g.theme.bg;
|
||||
|
||||
const themeBg = g.theme.bg;
|
||||
|
||||
const scores = {
|
||||
currentScore: 0,
|
||||
|
@ -78,12 +88,12 @@ const snapshot = {
|
|||
updCounter: function() {
|
||||
this.counter = ++this.counter > this.interval ? 0 : this.counter;
|
||||
},
|
||||
dump: {gridsize: rows * cols, expVals: [], score: 0, highScore: 0, charIndex: charIndex},
|
||||
dump: {gridsize: rows * cols, expVals: [], score: 0, highScore: 0},
|
||||
write: function() {
|
||||
require("Storage").writeJSON(this.snFileName, this.dump);
|
||||
},
|
||||
read: function () {
|
||||
let sn = require("Storage").readJSON(this.snFileName, noExceptions);
|
||||
let sn = require("Storage").readJSON(this.snFileName, true);
|
||||
if ((typeof sn == "undefined") || (sn.gridsize !== rows * cols)) {
|
||||
require("Storage").writeJSON(this.snFileName, this.dump);
|
||||
return false;
|
||||
|
@ -101,7 +111,6 @@ const snapshot = {
|
|||
});
|
||||
this.dump.score = scores.currentScore;
|
||||
this.dump.highScore = scores.highScore;
|
||||
this.dump.charIndex = charIndex;
|
||||
},
|
||||
make: function () {
|
||||
this.updCounter();
|
||||
|
@ -118,7 +127,7 @@ const snapshot = {
|
|||
});
|
||||
scores.currentScore = this.dump.score ? this.dump.score : 0;
|
||||
scores.highScore = this.dump.highScore ? this.dump.highScore : 0 ;
|
||||
charIndex = this.dump.charIndex ? this.dump.charIndex : 0 ;
|
||||
if (this.dump.hasOwnProperty('charIndex')) delete this.dump.charIndex; // depricated in v0.09
|
||||
}
|
||||
},
|
||||
reset: function () {
|
||||
|
@ -129,12 +138,11 @@ const snapshot = {
|
|||
}
|
||||
this.dump.score = 0;
|
||||
this.dump.highScore = scores.highScore;
|
||||
this.dump.charIndex = charIndex;
|
||||
this.write();
|
||||
debug(() => console.log("reset D U M P E D!", this.dump));
|
||||
}
|
||||
};
|
||||
const btnAtribs = {x: 134, w: 42, h: 42, fg:'#C0C0C0', bg:'#800000'};
|
||||
const btnAtribs = {x: 134, w: 42, h: 50, fg:'#C0C0C0', bg:'#800000'};
|
||||
const buttons = {
|
||||
all: [],
|
||||
draw: function () {
|
||||
|
@ -314,7 +322,7 @@ class Cell {
|
|||
}
|
||||
drawBg() {
|
||||
debug(()=>console.log("Drawbg!!"));
|
||||
if (this.isRndm == true) {
|
||||
if (this.isRndm) {
|
||||
debug(()=>console.log('Random: (ax)', this.ax));
|
||||
g.setColor(this.getColor(this.expVal).bg)
|
||||
.fillRect(this.x0, this.y0, this.x1, this.y1)
|
||||
|
@ -365,7 +373,7 @@ class Cell {
|
|||
this.isRndm = true;
|
||||
}
|
||||
drawRndmIndicator(){
|
||||
if (this.isRndm == true) {
|
||||
if (this.isRndm) {
|
||||
debug(()=>console.log('Random: (ax)', this.ax));
|
||||
g.setColor(this.getColor(0).bg)
|
||||
.fillPoly(this.ax,this.ay,this.bx,this.by,this.cx,this.cy);
|
||||
|
@ -374,8 +382,9 @@ class Cell {
|
|||
}
|
||||
|
||||
function undoGame() {
|
||||
g.clear();
|
||||
if (scores.lastScores.length > 0) {
|
||||
|
||||
if (scores.lastScores.length) {
|
||||
g.clear();
|
||||
allSquares.forEach(sq => {
|
||||
sq.popFromUndo();
|
||||
sq.drawBg();
|
||||
|
@ -386,9 +395,9 @@ function undoGame() {
|
|||
buttons.draw();
|
||||
updUndoLvlIndex();
|
||||
snapshot.make();
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
}
|
||||
function addToUndo() {
|
||||
allSquares.forEach(sq => {
|
||||
|
@ -487,8 +496,8 @@ function initGame() {
|
|||
drawGrid();
|
||||
scores.draw();
|
||||
buttons.draw();
|
||||
// Clock mode allows short-press on button to exit
|
||||
Bangle.setUI("clock");
|
||||
// #settings Clock mode allows short-press on button to exit
|
||||
if(clockMode) Bangle.setUI("clock");
|
||||
// Load widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
@ -507,8 +516,8 @@ function drawPopUp(message,cb) {
|
|||
rDims.x+10, rDims.y2-40
|
||||
]);
|
||||
buttons.all.forEach(btn => {btn.disable();});
|
||||
const btnYes = new Button('yes', rDims.x+16, rDims.y2-80, 54, btnAtribs.h, 'YES', btnAtribs.fg, btnAtribs.bg, cb, true);
|
||||
const btnNo = new Button('no', rDims.x2-80, rDims.y2-80, 54, btnAtribs.h, 'NO', btnAtribs.fg, btnAtribs.bg, cb, true);
|
||||
const btnYes = new Button('yes', rDims.x+16, rDims.y2-88, 54, btnAtribs.h, 'YES', btnAtribs.fg, btnAtribs.bg, cb, true);
|
||||
const btnNo = new Button('no', rDims.x2-80, rDims.y2-88, 54, btnAtribs.h, 'NO', btnAtribs.fg, btnAtribs.bg, cb, true);
|
||||
btnYes.draw();
|
||||
btnNo.draw();
|
||||
g.setColor('#000000');
|
||||
|
@ -560,14 +569,8 @@ function resetGame() {
|
|||
* @param {function} func function to call like console.log()
|
||||
*/
|
||||
const debug = (func) => {
|
||||
switch (debugMode) {
|
||||
case "development":
|
||||
if (typeof func === 'function') {
|
||||
func();
|
||||
}
|
||||
break;
|
||||
case "off":
|
||||
default: break;
|
||||
if (debugMode) {
|
||||
if (typeof func === 'function') func();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -690,13 +693,9 @@ function updUndoLvlIndex() {
|
|||
.drawString(scores.lastScores.length, x, y);
|
||||
}
|
||||
}
|
||||
function incrCharIndex() {
|
||||
charIndex++;
|
||||
if (charIndex >= cellChars.length) charIndex = 0;
|
||||
drawGrid();
|
||||
}
|
||||
|
||||
buttons.add(new Button('undo', btnAtribs.x, 25, btnAtribs.w, btnAtribs.h, 'U', btnAtribs.fg, btnAtribs.bg, undoGame, true));
|
||||
buttons.add(new Button('chars', btnAtribs.x, 71, btnAtribs.w, 31, '*', btnAtribs.fg, btnAtribs.bg, function(){incrCharIndex();}, true));
|
||||
|
||||
buttons.add(new Button('restart', btnAtribs.x, 106, btnAtribs.w, btnAtribs.h, 'R', btnAtribs.fg, btnAtribs.bg, function(){drawPopUp('Do you want\nto restart?',handlePopUpClicks);}, true));
|
||||
|
||||
initGame();
|
||||
|
|
After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.3 KiB |
After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 3.6 KiB |
|
@ -1,7 +1,7 @@
|
|||
{ "id": "game1024",
|
||||
"name": "1024 Game",
|
||||
"shortName" : "1024 Game",
|
||||
"version": "0.08",
|
||||
"version": "0.09",
|
||||
"icon": "game1024.png",
|
||||
"screenshots": [ {"url":"screenshot.png" } ],
|
||||
"readme":"README.md",
|
||||
|
@ -12,6 +12,7 @@
|
|||
"supports" : ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"game1024.app.js","url":"app.js"},
|
||||
{"name":"game1024.settings.js","url":"settings.js"},
|
||||
{"name":"game1024.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
||||
|
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 3.4 KiB |
|
@ -0,0 +1,70 @@
|
|||
(function(back) {
|
||||
var FILE = "game1024.settings.json";
|
||||
var scoreFile = "game1024.json";
|
||||
// Load settings
|
||||
var settings = Object.assign({
|
||||
maxUndoLevels: 5,
|
||||
charIndex: 0,
|
||||
clockMode: true,
|
||||
debugMode: false,
|
||||
}, require('Storage').readJSON(FILE, true) || {});
|
||||
|
||||
function writeSettings() {
|
||||
require('Storage').writeJSON(FILE, settings);
|
||||
}
|
||||
var symbols = ["1 2 3 ...", "A B C ...", "I II III..."];
|
||||
var settingsMenu = {
|
||||
"" : { "title" : "1024 Game" },
|
||||
"< Back" : () => back(),
|
||||
"Symbols": {
|
||||
value: 0|settings.charIndex,
|
||||
min:0,max:symbols.length-1,
|
||||
format: v=>symbols[v],
|
||||
onchange: v=> { settings.charIndex=v; writeSettings();}
|
||||
}
|
||||
,
|
||||
"Undo levels:": {
|
||||
value: 0|settings.maxUndoLevels, // 0| converts undefined to 0
|
||||
min: 0, max: 9,
|
||||
onchange: v => {
|
||||
settings.maxUndoLevels = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Exit press:": {
|
||||
value: !settings.debugMode, // ! converts undefined to true
|
||||
format: v => v?"short":"long",
|
||||
onchange: v => {
|
||||
settings.debugMode = v;
|
||||
writeSettings();
|
||||
},
|
||||
},
|
||||
"Debug mode:": {
|
||||
value: !!settings.debugMode, // !! converts undefined to false
|
||||
format: v => v?"On":"Off",
|
||||
onchange: v => {
|
||||
settings.debugMode = v;
|
||||
writeSettings();
|
||||
}
|
||||
},
|
||||
"Reset Highscore": () => {
|
||||
E.showPrompt('Reset Highscore?').then((v) => {
|
||||
let delay = 50;
|
||||
if (v) {
|
||||
delay = 500;
|
||||
let sF = require("Storage").readJSON(scoreFile, true);
|
||||
if (typeof sF !== "undefined") {
|
||||
E.showMessage('Resetting');
|
||||
sF.highScore = 0;
|
||||
require("Storage").writeJSON(scoreFile, sF);
|
||||
} else {
|
||||
E.showMessage('No highscore!');
|
||||
}
|
||||
}
|
||||
setTimeout(() => E.showMenu(settingsMenu), delay);
|
||||
});
|
||||
}
|
||||
}
|
||||
// Show the menu
|
||||
E.showMenu(settingsMenu);
|
||||
})
|
|
@ -8,6 +8,7 @@
|
|||
"tags": "clock",
|
||||
"screenshots": [{"url":"bangle1-high-contrast-clock-screenshot.png"}],
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"hcclock.app.js","url":"hcclock.app.js"},
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}],
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"intclock.app.js","url":"app.js"},
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"icon": "intervals.png",
|
||||
"tags": "",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"intervals.app.js","url":"intervals.app.js"},
|
||||
{"name":"intervals.img","url":"intervals-icon.js","evaluate":true}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"tags": "tool,system,ios,apple,messages,notifications",
|
||||
"dependencies": {"messages":"app"},
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"ios.app.js","url":"app.js"},
|
||||
{"name":"ios.img","url":"app-icon.js","evaluate":true},
|
||||
|
|
|
@ -42,3 +42,4 @@
|
|||
0.27: Add 'mark all read' option to popup menu (fix #1624)
|
||||
0.28: Option to auto-unlock the watch when a new message arrives
|
||||
0.29: Fix message list overwrites on Bangle.js 1 (fix #1642)
|
||||
0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel)
|
||||
|
|
|
@ -82,31 +82,45 @@ function getNegImage() {
|
|||
return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA=");
|
||||
}
|
||||
/*
|
||||
* icons should be 24x24px with 1bpp colors and transparancy
|
||||
* icons should be 24x24px with 1bpp colors and 'Transparency to Color'
|
||||
* http://www.espruino.com/Image+Converter
|
||||
*/
|
||||
function getMessageImage(msg) {
|
||||
if (msg.img) return atob(msg.img);
|
||||
var s = (msg.src||"").toLowerCase();
|
||||
if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA=");
|
||||
if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA=");
|
||||
if (s=="bibel") return atob("GBgBAAAAA//wD//4D//4H//4H/f4H/f4H+P4H4D4H4D4H/f4H/f4H/f4H/f4H/f4H//4H//4H//4GAAAEAAAEAAACAAAB//4AAAA");
|
||||
if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA==");
|
||||
if (s=="corona-warn") return atob("GBgBAAAAABwAAP+AAf/gA//wB/PwD/PgDzvAHzuAP8EAP8AAPAAAPMAAP8AAH8AAHzsADzuAB/PAB/PgA//wAP/gAH+AAAwAAAAA");
|
||||
if (s=="discord") return atob("GBgBAAAAAAAAAAAAAIEABwDgDP8wH//4H//4P//8P//8P//8Pjx8fhh+fzz+f//+f//+e//ePH48HwD4AgBAAAAAAAAAAAAAAAAA");
|
||||
if (s=="facebook") return getFBIcon();
|
||||
if (s=="gmail") return getNotificationImage();
|
||||
if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA==");
|
||||
if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA=");
|
||||
if (s=="home assistant") return atob("FhaBAAAAAADAAAeAAD8AAf4AD/3AfP8D7fwft/D/P8ec572zbzbNsOEhw+AfD8D8P4fw/z/D/P8P8/w/z/AAAAA=");
|
||||
if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA==");
|
||||
if (s=="gmail") return getNotificationImage();
|
||||
if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA==");
|
||||
if (s=="kalender") return atob("GBgBBgBgBQCgff++RQCiRgBiQAACf//+QAACQAACR//iRJkiRIEiR//iRNsiRIEiRJkiR//iRIEiRIEiR//iQAACQAACf//+AAAA");
|
||||
if (s=="lieferando") return atob("GBgBABgAAH5wAP9wAf/4A//4B//4D//4H//4P/88fV8+fV4//V4//Vw/HVw4HVw4HBg4HBg4HBg4HDg4Hjw4Hj84Hj44Hj44Hj44");
|
||||
if (s=="mail") return getNotificationImage();
|
||||
if (s=="messenger") return getFBIcon();
|
||||
if (s=="outlook mail") return getNotificationImage();
|
||||
if (s=="nina") return atob("GBgBAAAABAAQCAAICAAIEAAEEgAkJAgSJBwSKRxKSj4pUn8lVP+VVP+VUgAlSgApKQBKJAASJAASEgAkEAAECAAICAAIBAAQAAAA");
|
||||
if (s=="outlook mail") return atob("HBwBAAAAAAAAAAAIAAAfwAAP/gAB/+AAP/5/A//v/D/+/8P/7/g+Pv8Dye/gPd74w5znHDnOB8Oc4Pw8nv/Dwe/8Pj7/w//v/D/+/8P/7/gf/gAA/+AAAfwAAACAAAAAAAAAAAA=");
|
||||
if (s=="phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA=");
|
||||
if (s=="post & dhl") return atob("GBgBAPgAE/5wMwZ8NgN8NgP4NgP4HgP4HgPwDwfgD//AB/+AAf8AAAAABs7AHcdgG4MwAAAAGESAFESAEkSAEnyAEkSAFESAGETw");
|
||||
if (s=="signal") return atob("GBgBAAAAAGwAAQGAAhggCP8QE//AB//oJ//kL//wD//0D//wT//wD//wL//0J//kB//oA//ICf8ABfxgBYBAADoABMAABAAAAAAA");
|
||||
if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA==");
|
||||
if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA==");
|
||||
if (s=="sms message") return getNotificationImage();
|
||||
if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=");
|
||||
if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA");
|
||||
if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA");
|
||||
if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA");
|
||||
if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA==");
|
||||
if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=");
|
||||
if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA");
|
||||
if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA");
|
||||
if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA");
|
||||
if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA==");
|
||||
if (s=="wordfeud") return atob("GBgCWqqqqqqlf//////9v//////+v/////++v/////++v8///Lu+v8///L++v8///P/+v8v//P/+v9v//P/+v+fx/P/+v+Pk+P/+v/PN+f/+v/POuv/+v/Ofdv/+v/NvM//+v/I/Y//+v/k/k//+v/i/w//+v/7/6//+v//////+v//////+f//////9Wqqqqqql");
|
||||
if (s=="youtube") return atob("GBgBAAAAAAAAAAAAAAAAAf8AH//4P//4P//8P//8P5/8P4/8f4P8f4P8P4/8P5/8P//8P//8P//4H//4Af8AAAAAAAAAAAAAAAAA");
|
||||
if (msg.id=="music") return atob("FhaBAH//+/////////////h/+AH/4Af/gB/+H3/7/f/v9/+/3/7+f/vB/w8H+Dwf4PD/x/////////////3//+A=");
|
||||
if (msg.id=="back") return getBackImage();
|
||||
return getNotificationImage();
|
||||
|
@ -115,28 +129,38 @@ function getMessageImageCol(msg,def) {
|
|||
return {
|
||||
// generic colors, using B2-safe colors
|
||||
"alarm": "#fff",
|
||||
"calendar": "#f00",
|
||||
"mail": "#ff0",
|
||||
"music": "#f0f",
|
||||
"phone": "#0f0",
|
||||
"sms message": "#0ff",
|
||||
// brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos)
|
||||
// all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?)
|
||||
"bibel": "#54342c",
|
||||
"discord": "#738adb",
|
||||
"facebook": "#4267b2",
|
||||
"gmail": "#ea4335",
|
||||
"google home": "#fbbc05",
|
||||
"home assistant": "#fff", // ha-blue is #41bdf5, but that's the background
|
||||
"hangouts": "#1ba261",
|
||||
"home assistant": "#fff", // ha-blue is #41bdf5, but that's the background
|
||||
"instagram": "#dd2a7b",
|
||||
"liferando": "#ee5c00",
|
||||
"messenger": "#0078ff",
|
||||
"nina": "#e57004",
|
||||
"outlook mail": "#0072c6",
|
||||
"post & dhl": "#f2c101",
|
||||
"signal": "#00f",
|
||||
"skype": "#00aff0",
|
||||
"slack": "#e51670",
|
||||
"threema": "#000",
|
||||
"snapchat": "#ff0",
|
||||
"teams": "#464eb8",
|
||||
"telegram": "#0088cc",
|
||||
"threema": "#000",
|
||||
"to do": "#3999e5",
|
||||
"twitch": "#6441A4",
|
||||
"twitter": "#1da1f2",
|
||||
"whatsapp": "#4fce5d",
|
||||
"wordfeud": "#e7d3c7",
|
||||
"youtube": "#f00",
|
||||
}[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "messages",
|
||||
"name": "Messages",
|
||||
"version": "0.29",
|
||||
"version": "0.30",
|
||||
"description": "App to display notifications from iOS and Gadgetbridge/Android",
|
||||
"icon": "app.png",
|
||||
"type": "app",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "numerals,clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"bangle1-numerals-screenshot.png"}],
|
||||
"storage": [
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"screenshots": [{"url":"bangle1-pipboy-themed-clock-screenshot.png"}],
|
||||
"storage": [
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"type": "boot",
|
||||
"tags": "system",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"screenshots": [{"url":"pro-menu-screenshot.png"}],
|
||||
"storage": [
|
||||
{"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]},
|
||||
|
|
|
@ -14,7 +14,8 @@ the red `STOP` in the bottom right turns to a green `RUN`.
|
|||
shown will increase, even if you are standing still.
|
||||
* `TIME` - the elapsed time for your run
|
||||
* `PACE` - the number of minutes it takes you to run a given distance, configured in settings (default 1km) **based on your run so far**
|
||||
* `HEART` - Your heart rate
|
||||
* `HEART (BPM)` - Your current heart rate
|
||||
* `Max BPM` - Your maximum heart rate reached during the run
|
||||
* `STEPS` - Steps since you started exercising
|
||||
* `CADENCE` - Steps per second based on your step rate *over the last minute*
|
||||
* `GPS` - this is green if you have a GPS lock. GPS is turned on automatically
|
||||
|
@ -35,7 +36,7 @@ Under `Settings` -> `App` -> `Run` you can change settings for this app.
|
|||
record GPS/HRM/etc data every time you start a run?
|
||||
* `Pace` is the distance that pace should be shown over - 1km, 1 mile, 1/2 Marathon or 1 Marathon
|
||||
* `Boxes` leads to a submenu where you can configure what is shown in each of the 6 boxes on the display.
|
||||
Available stats are "Time", "Distance", "Steps", "Heart (BPM)", "Pace (avg)", "Pace (curr)", "Speed", and "Cadence".
|
||||
Available stats are "Time", "Distance", "Steps", "Heart (BPM)", "Max BPM", "Pace (avg)", "Pace (curr)", "Speed", and "Cadence".
|
||||
Any box set to "-" will display no information.
|
||||
* Box 1 is the top left (defaults to "Distance")
|
||||
* Box 2 is the top right (defaults to "Time")
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "app",
|
||||
"tags": "",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"score.app.js","url":"score.app.js"},
|
||||
{"name":"score.settings.js","url":"score.settings.js"},
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"icon": "app.png",
|
||||
"tags": "tool",
|
||||
"supports" : ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"showimg.app.js","url":"app.js"},
|
||||
{"name":"showimg.img","url":"app-icon.js","evaluate":true}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
1.0: Initial release on the app repository for Bangle.js 1 and 2
|
|
@ -0,0 +1,23 @@
|
|||
# Stardate Clock
|
||||
|
||||
A clock face displaying a stardate along with a "standard" digital/analog clock
|
||||
in LCARS design.
|
||||
|
||||
That design has been made popular by various Star Trek shows. Credits for the
|
||||
original LCARS designs go to Michael Okuda, copyrights are owned by Paramount Global,
|
||||
usage of that type of design is permitted freely for non-profit use cases.
|
||||
The Bangle.js version has been created by Robert Kaiser <kairo@kairo.at>.
|
||||
|
||||
The stardate concept used leans on the shows released from the late 80s onward
|
||||
by using 1000 units per Earth year, but to apply this more cleanly, this split
|
||||
is applied exactly. Also, to give more relationship to the shows and
|
||||
incidentally make values look similar to those depicted there, the zero point
|
||||
is set to the first airing of the original 'Star Trek' series in the US on
|
||||
Thursday, September 8, 1966, at 8:30 p.m. Eastern Time.
|
||||
|
||||
The clock face supports Bangle.js 1 and 2 with some compromises (e.g. the
|
||||
colors will look best on Bangle.js 1, the font sizes will look best on
|
||||
Bangle.js 2).
|
||||
|
||||
Any tap on the diaply while unlocked switches the "standard" Earth-style clock
|
||||
between digital and analog display.
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwgkiAA0gDRwX/C/4X/C5MO9wBDgnkAIMAAQQXKAItehwECAQIXK8gBEIQIeDC5YAF8EAAIIECC48hE4oYCAogXIkQvHDIgCBiQXHiCPFAIaaCgECJBChDAIsOU4RIJbJwwIDIVEABIYBMJAXOAC8SmYAHmHdABJfBCxAXNCpEyRxoWVgETC46+OkYXHRpxGWC5EwBQMBkQDBiK4DKQMBiAXKNQMggQ2CgI7CkcgC5UjicwkYXCgUxmakBC5kCmERC4MiAoMjgMTC50AC4KYCkcAgYXRPgJFBC6YABgYEBC6iQBC6cRgMgL6ikBR4IXOiR3EX4IXPAgTXDBgIXNgUiiClCAAMikIKBC5YAMC64AXogAGoAX/C6w"))
|
|
@ -0,0 +1,362 @@
|
|||
// Stardate clock face, by KaiRo.at, 2021-2022
|
||||
|
||||
var redrawClock = true;
|
||||
var clockface = "digital";
|
||||
|
||||
// note: Bangle.js 1 has 240x240x16, 2 has 176x176x3 screen
|
||||
var bpp = g.getBPP ? g.getBPP() : 16;
|
||||
|
||||
// Load fonts
|
||||
Graphics.prototype.setFontAntonio27 = function(scale) {
|
||||
// Actual height 23 (23 - 1)
|
||||
g.setFontCustom(atob("AAAAAAGAAAAwAAAGAAAAwAAAGAAAAwAAAAAAAAAAAAAAAAAADAAAA4AAAHAAAAAAAAAAAAAAAAAAAAAA4AAB/AAD/4AH/4AP/wAf/gAD/AAAeAAAAAAAAAAAAA///AP//+D///4eAAPDgAA4cAAHD///4P//+A///gAAAAAAAAAAAAAAYAAAHAAAA4AAAOAAAD///4f///D///4AAAAAAAAAAAAAAAAAAAAAAA/gD4P8B/D/g/4cAfzDgP4Yf/8DD/+AYP/ADAGAAAAAAAAAAAAHwD8B+AfwfwD/DgMA4cDgHDgeA4f///B/3/wH8P8AAAAAAAAAAAAOAAAPwAAP+AAP/wAf8OAf4BwD///4f///D///4AABwAAAGAAAAAAAAAAAAAAD/4Pwf/h/D/4P4cMAHDjgA4cf//Dh//4cH/8AAAAAAAAAAAAAAH//8B///wf///Dg4A4cHAHDg4A4f3//B+f/wHh/8AAAAAAAAAAAAAAcAAADgAA4cAD/DgH/4cH//Dv/4Af/gAD/gAAfAAADgAAAAAAAAAAAAH4f8B///wf///Dg8A4cDAHDg8A4f///B///wH8/8AAAAAAAAAAAAAAH/h4B/+Pwf/5/DgHA4cA4HDgHA4f///B///wH//8AAAAAAAAAAAAAAAAAAAHgeAA8DwAHgeAAAAAAAAAA"), 45, atob("CQcKDAsMDAwMDAwMDAc="), 27+(scale<<8)+(1<<16));
|
||||
};
|
||||
Graphics.prototype.setFontAntonio42 = function(scale) {
|
||||
// Actual height 36 (36 - 1)
|
||||
g.setFontCustom(atob("AAAAAAAAAAAAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAAHgAAAAAHgAAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAfgAAAAH/gAAAB//gAAAf//gAAH//4AAB//+AAAf//gAAH//4AAAf/+AAAAf/gAAAAf4AAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAA////gAH////+AP/////Af/////gf/////gfAAAAPgeAAAAHgeAAAAHgfAAAAPgf/////gf/////gP/////AH////+AB////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAB4AAAAAB4AAAAADwAAAAAHwAAAAAP/////gf/////gf/////gf/////gf/////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAPgH/8AD/gP/8AP/gP/8A//gf/8B//gfAAH/ngeAAf+HgeAB/4HgfAH/gHgf//+AHgP//4AHgH//wAHgD/+AAHgAPgAAAAAAAAAAAAAAAAAAAAAAAAAA+AAfwAH+AAf+AP+AAf/AP+AAf/Af+AAf/gfADwAPgeADwAHgeADwAHgfAH4APgf///h/gf/////AP/+///AH/+f/+AB/4H/4AAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAA/gAAAAH/gAAAB//gAAAP//gAAB//HgAAf/wHgAD/8AHgAf/AAHgAf/////gf/////gf/////gf/////gf/////gAAAAHgAAAAAHgAAAAAHAAAAAAAAAAAAAAAAAAAAAAAf//gP8Af//gP+Af//gP/Af//gP/gf/+AAfgeB8AAHgeB4AAHgeB8AAHgeB////geB////geA////AeAf//+AAAD//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf///gAD////8AH/////AP/////Af/////gfAPgAfgeAPAAHgeAPAAHgeAPAAHgf+PgAPgf+P///gP+H///AH+H//+AB+B//8AAAAD8AAAAAAAAAAAAAAAAAAAAAAAeAAAAAAeAAAAAAeAAAAPgeAAAP/geAAD//geAA///geAH///geB///+AeP//4AAe//8AAAf//AAAAf/wAAAAf+AAAAAfwAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAB/wH/4AH/8f/+AP/////Af/////gf/////geAH4APgeADgAHgeADgAHgeAHwAHgf/////gf/////gP/////AH/8//+AB/wH/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//gPgAH//4P+AP//8P/Af//+P/AfwB+P/geAAeAPgeAAeAHgeAAeAHgfAAeAPgf/////gP/////AP/////AH////8AA////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4APgAAH4AfgAAH4AfgAAH4AfgAAH4AfgAAD4APgAAAAAAAAAAAAAAA="), 45, atob("DgsPEhESEhISEhISEgo="), 42+(scale<<8)+(1<<16));
|
||||
};
|
||||
const fontName = "Antonio27";
|
||||
const fontNameLarge = "Antonio42";
|
||||
const fontSize = 1;
|
||||
const fontSizeLarge = 1;
|
||||
const fontHeightLarge = 42 * fontSizeLarge;
|
||||
|
||||
// LCARS dimensions
|
||||
if (g.getWidth() < 200) { // Bangle.js 2
|
||||
const baseUnit1 = 3;
|
||||
const baseUnit2 = 2;
|
||||
const baseUnit3 = 7;
|
||||
}
|
||||
else {
|
||||
const baseUnit1 = 5;
|
||||
const baseUnit2 = 3;
|
||||
const baseUnit3 = 10;
|
||||
}
|
||||
const widgetsHeight = 24;
|
||||
const sbarWid = baseUnit3 * 5;
|
||||
const hbarHt = baseUnit1;
|
||||
const outRad = baseUnit1 * 5;
|
||||
const inRad = outRad - hbarHt;
|
||||
const gap = baseUnit2;
|
||||
const divisionPos = baseUnit3 * 8;
|
||||
const sbarGapPos = baseUnit3 * 15;
|
||||
const lowerTop = divisionPos+gap+1;
|
||||
|
||||
// Star Trek famously premiered on Thursday, September 8, 1966, at 8:30 p.m.
|
||||
// See http://www.startrek.com/article/what-if-the-original-star-trek-had-debuted-on-friday-nights
|
||||
const gSDBase = new Date("September 8, 1966 20:30:00 EST");
|
||||
const sdatePosBottom = divisionPos - hbarHt - 1;
|
||||
const sdatePosRight = g.getWidth() - baseUnit2;
|
||||
const sdateDecimals = 1;
|
||||
const secondsPerYear = 86400 * 365.2425;
|
||||
const sdateDecFactor = Math.pow(10, sdateDecimals);
|
||||
|
||||
const clockAreaLeft = sbarWid + inRad / 2;
|
||||
const clockAreaTop = lowerTop + hbarHt + inRad / 2;
|
||||
const clockWid = g.getWidth() - clockAreaLeft;
|
||||
const clockHt = g.getHeight() - clockAreaTop;
|
||||
|
||||
const ctimePosTop = clockAreaTop + baseUnit1 * 5;
|
||||
const ctimePosCenter = clockAreaLeft + clockWid / 2;
|
||||
const cdatePosTop = ctimePosTop + fontHeightLarge;
|
||||
const cdatePosCenter = clockAreaLeft + clockWid / 2;
|
||||
|
||||
const clockCtrX = Math.floor(clockAreaLeft + clockWid / 2);
|
||||
const clockCtrY = Math.floor(clockAreaTop + clockHt / 2);
|
||||
const analogRad = Math.floor(Math.min(clockWid, clockHt) / 2);
|
||||
|
||||
const analogMainLineLength = baseUnit1 * 2;
|
||||
const analogSubLineLength = baseUnit1;
|
||||
|
||||
const analogHourHandLength = analogRad / 2;
|
||||
const analogMinuteHandLength = analogRad - analogMainLineLength / 2;
|
||||
|
||||
const colorBg = "#000000";
|
||||
const colorTime = "#9C9CFF";
|
||||
const colorDate = "#A09090";
|
||||
const colorStardate = "#FFCF00";
|
||||
// On low-bpp devices (Bangle.js 2), use basic colors for analog clock.
|
||||
const colorHours = bpp > 3 ? "#9C9CFF" : "#00FF00";
|
||||
const colorSeconds = bpp > 3 ? "#E7ADE7" : "#FFFF00";
|
||||
const colorHands = bpp > 3 ? "#A09090" : "#00FFFF";
|
||||
const colorLCARSGray = "#A09090";
|
||||
const colorLCARSOrange = "#FF9F00";
|
||||
const colorLCARSPink = "#E7ADE7";
|
||||
const colorLCARSPurple = "#A06060";
|
||||
const colorLCARSBrown = "#C09070";
|
||||
// More colors: teal #008484, yellow FFCF00, purple #6050B0
|
||||
|
||||
var lastSDateString;
|
||||
var lastTimeStringToMin;
|
||||
var lastTimeStringSec;
|
||||
var lastDateString;
|
||||
var lastAnalogDate;
|
||||
|
||||
function updateStardate() {
|
||||
var curDate = new Date();
|
||||
|
||||
// Note that the millisecond division and the 1000-unit multiplier cancel each other out.
|
||||
var sdateval = (curDate - gSDBase) / secondsPerYear;
|
||||
|
||||
var sdatestring = (Math.floor(sdateval * sdateDecFactor) / sdateDecFactor).toFixed(sdateDecimals);
|
||||
|
||||
// Reset the state of the graphics library.
|
||||
g.reset();
|
||||
g.setBgColor(colorBg);
|
||||
// Set Font
|
||||
g.setFont(fontName, fontSize);
|
||||
if (lastSDateString) {
|
||||
// Clear the area where we want to draw the time.
|
||||
//g.setBgColor("#FF6600"); // for debugging
|
||||
g.clearRect(sdatePosRight - g.stringWidth(lastSDateString) - 1,
|
||||
sdatePosBottom - g.getFontHeight(),
|
||||
sdatePosRight,
|
||||
sdatePosBottom);
|
||||
}
|
||||
// Draw the current stardate.
|
||||
g.setColor(colorStardate);
|
||||
g.setFontAlign(1, 1, 0); // Align following string to bottom right.
|
||||
g.drawString(sdatestring, sdatePosRight, sdatePosBottom);
|
||||
lastSDateString = sdatestring;
|
||||
|
||||
// Schedule next when an update to the last decimal is due.
|
||||
var mstonextUpdate = (Math.ceil(sdateval * sdateDecFactor) / sdateDecFactor - sdateval) * secondsPerYear;
|
||||
if (redrawClock) {
|
||||
setTimeout(updateStardate, mstonextUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
function updateConventionalTime() {
|
||||
var curDate = new Date();
|
||||
|
||||
if (clockface == "digital") {
|
||||
drawDigitalClock(curDate);
|
||||
}
|
||||
else {
|
||||
drawAnalogClock(curDate);
|
||||
}
|
||||
|
||||
// Schedule next when an update to the last second is due.
|
||||
var mstonextUpdate = Math.ceil(curDate / 1000) * 1000 - curDate;
|
||||
if (redrawClock) {
|
||||
setTimeout(updateConventionalTime, mstonextUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
function drawDigitalClock(curDate) {
|
||||
var timestringToMin = ("0" + curDate.getHours()).substr(-2) + ":"
|
||||
+ ("0" + curDate.getMinutes()).substr(-2) + ":";
|
||||
var timestringSec = ("0" + curDate.getSeconds()).substr(-2);
|
||||
var datestring = "" + curDate.getFullYear() + "-"
|
||||
+ ("0" + (curDate.getMonth() + 1)).substr(-2) + "-"
|
||||
+ ("0" + curDate.getDate()).substr(-2);
|
||||
|
||||
// Reset the state of the graphics library.
|
||||
g.reset();
|
||||
g.setBgColor(colorBg);
|
||||
// Set Font
|
||||
g.setFont(fontNameLarge, fontSizeLarge);
|
||||
var ctimePosLeft = ctimePosCenter - g.stringWidth("12:34:56") / 2;
|
||||
if (ctimePosLeft + g.stringWidth("00:00:00") > g.getWidth()) {
|
||||
ctimePosLeft = g.getWidth() - g.stringWidth("00:00:00");
|
||||
}
|
||||
g.setColor(colorTime);
|
||||
if (timestringToMin != lastTimeStringToMin) {
|
||||
if (lastTimeStringToMin) {
|
||||
// Clear the area where we want to draw the time.
|
||||
//g.setBgColor("#FF6600"); // for debugging
|
||||
g.clearRect(ctimePosLeft,
|
||||
ctimePosTop,
|
||||
ctimePosLeft + g.stringWidth(lastTimeStringToMin) + 1,
|
||||
ctimePosTop + g.getFontHeight());
|
||||
}
|
||||
// Draw the current time.
|
||||
g.drawString(timestringToMin, ctimePosLeft, ctimePosTop);
|
||||
lastTimeStringToMin = timestringToMin;
|
||||
}
|
||||
var ctimePosLeftSec = ctimePosLeft + g.stringWidth(timestringToMin);
|
||||
if (lastTimeStringSec) {
|
||||
// Clear the area where we want to draw the seconds.
|
||||
//g.setBgColor("#FF6600"); // for debugging
|
||||
g.clearRect(ctimePosLeftSec,
|
||||
ctimePosTop,
|
||||
ctimePosLeftSec + g.stringWidth(lastTimeStringSec) + 1,
|
||||
ctimePosTop + g.getFontHeight());
|
||||
}
|
||||
// Draw the current seconds.
|
||||
g.drawString(timestringSec, ctimePosLeftSec, ctimePosTop);
|
||||
lastTimeStringSec = timestringSec;
|
||||
|
||||
if (datestring != lastDateString) {
|
||||
// Set Font
|
||||
g.setFont(fontName, fontSize);
|
||||
var cdatePosLeft = cdatePosCenter - g.stringWidth("1234-56-78") / 2;
|
||||
if (lastDateString) {
|
||||
// Clear the area where we want to draw the time.
|
||||
//g.setBgColor("#FF6600"); // for debugging
|
||||
g.clearRect(cdatePosLeft,
|
||||
cdatePosTop,
|
||||
cdatePosLeft + g.stringWidth(lastDateString) + 1,
|
||||
cdatePosTop + g.getFontHeight());
|
||||
}
|
||||
// Draw the current date.
|
||||
g.setColor(colorDate);
|
||||
//g.setFontAlign(0, -1, 0); // Align following string to bottom right.
|
||||
g.drawString(datestring, cdatePosLeft, cdatePosTop);
|
||||
lastDateString = datestring;
|
||||
}
|
||||
}
|
||||
|
||||
function drawLine(x1, y1, x2, y2, color) {
|
||||
g.setColor(color);
|
||||
// On high-bpp devices, use anti-aliasing. Low-bpp (Bangle.js 2) doesn't clear nicely with AA.
|
||||
if (bpp > 3 && g.drawLineAA) {
|
||||
g.drawLineAA(x1, y1, x2, y2);
|
||||
}
|
||||
else {
|
||||
g.drawLine(x1, y1, x2, y2);
|
||||
}
|
||||
}
|
||||
|
||||
function clearLine(x1, y1, x2, y2) {
|
||||
drawLine(x1, y1, x2, y2, colorBg);
|
||||
}
|
||||
|
||||
function drawAnalogClock(curDate) {
|
||||
// Reset the state of the graphics library.
|
||||
g.reset();
|
||||
g.setBgColor(colorBg);
|
||||
// Init variables for drawing any seconds we have not drawn.
|
||||
// If minute changed, we'll set for the full wheel below.
|
||||
var firstDrawSecond = lastAnalogDate ? lastAnalogDate.getSeconds() + 1 : curDate.getSeconds();
|
||||
var lastDrawSecond = curDate.getSeconds();
|
||||
if (!lastAnalogDate || curDate.getMinutes() != lastAnalogDate.getMinutes()) {
|
||||
// Draw the main hour lines.
|
||||
//g.setColor("#9C9CFF");
|
||||
//g.drawCircle(clockCtrX, clockCtrY, analogRad);
|
||||
for (let i = 0; i < 60; i = i + 15) {
|
||||
let edgeX = clockCtrX + analogRad * Math.sin(i * Math.PI / 30);
|
||||
let edgeY = clockCtrY - analogRad * Math.cos(i * Math.PI / 30);
|
||||
let innerX = clockCtrX + (analogRad - analogMainLineLength) * Math.sin(i * Math.PI / 30);
|
||||
let innerY = clockCtrY - (analogRad - analogMainLineLength) * Math.cos(i * Math.PI / 30);
|
||||
drawLine(edgeX, edgeY, innerX, innerY, colorHours);
|
||||
}
|
||||
// Set for drawing the full second wheel.
|
||||
firstDrawSecond = 0;
|
||||
lastDrawSecond = 59;
|
||||
}
|
||||
// Draw the second wheel, or the parts of it that we haven't done yet.
|
||||
for (let i = firstDrawSecond; i <= lastDrawSecond; i++) {
|
||||
let edgeX = clockCtrX + analogRad * Math.sin(i * Math.PI / 30);
|
||||
let edgeY = clockCtrY - analogRad * Math.cos(i * Math.PI / 30);
|
||||
let innerX = clockCtrX + (analogRad - analogSubLineLength) * Math.sin(i * Math.PI / 30);
|
||||
let innerY = clockCtrY - (analogRad - analogSubLineLength) * Math.cos(i * Math.PI / 30);
|
||||
if (i <= curDate.getSeconds()) {
|
||||
drawLine(edgeX, edgeY, innerX, innerY, colorSeconds);
|
||||
}
|
||||
else if (i % 5 == 0) {
|
||||
drawLine(edgeX, edgeY, innerX, innerY, colorHours);
|
||||
}
|
||||
else {
|
||||
clearLine(edgeX, edgeY, innerX, innerY);
|
||||
}
|
||||
}
|
||||
if (lastAnalogDate) {
|
||||
// Clear previous hands.
|
||||
if (curDate.getMinutes() != lastAnalogDate.getMinutes()) {
|
||||
// Clear hour hand.
|
||||
let HhAngle = (lastAnalogDate.getHours() + lastAnalogDate.getMinutes() / 60) * Math.PI / 6;
|
||||
let HhEdgeX = clockCtrX + analogHourHandLength * Math.sin(HhAngle);
|
||||
let HhEdgeY = clockCtrY - analogHourHandLength * Math.cos(HhAngle);
|
||||
clearLine(HhEdgeX, HhEdgeY, clockCtrX, clockCtrY);
|
||||
// Clear minute hand.
|
||||
let MhEdgeX = clockCtrX + analogMinuteHandLength * Math.sin(lastAnalogDate.getMinutes() * Math.PI / 30);
|
||||
let MhEdgeY = clockCtrY - analogMinuteHandLength * Math.cos(lastAnalogDate.getMinutes() * Math.PI / 30);
|
||||
clearLine(MhEdgeX, MhEdgeY, clockCtrX, clockCtrY);
|
||||
}
|
||||
}
|
||||
if (!lastAnalogDate || curDate.getMinutes() != lastAnalogDate.getMinutes()) {
|
||||
// Draw hour hand.
|
||||
let HhAngle = (curDate.getHours() + curDate.getMinutes() / 60) * Math.PI / 6;
|
||||
let HhEdgeX = clockCtrX + analogHourHandLength * Math.sin(HhAngle);
|
||||
let HhEdgeY = clockCtrY - analogHourHandLength * Math.cos(HhAngle);
|
||||
drawLine(HhEdgeX, HhEdgeY, clockCtrX, clockCtrY, colorHands);
|
||||
// Draw minute hand.
|
||||
let MhEdgeX = clockCtrX + analogMinuteHandLength * Math.sin(curDate.getMinutes() * Math.PI / 30);
|
||||
let MhEdgeY = clockCtrY - analogMinuteHandLength * Math.cos(curDate.getMinutes() * Math.PI / 30);
|
||||
drawLine(MhEdgeX, MhEdgeY, clockCtrX, clockCtrY, colorHands);
|
||||
}
|
||||
lastAnalogDate = curDate;
|
||||
}
|
||||
|
||||
function switchClockface() {
|
||||
if (clockface == "digital") {
|
||||
clockface = "analog";
|
||||
}
|
||||
else {
|
||||
clockface = "digital";
|
||||
}
|
||||
// Clear whole lower area.
|
||||
g.clearRect(clockAreaLeft,clockAreaTop,g.getWidth(),g.getHeight());
|
||||
lastTimeStringToMin = undefined;
|
||||
lastTimeStringSec = undefined;
|
||||
lastDateString = undefined;
|
||||
lastAnalogDate = undefined;
|
||||
}
|
||||
|
||||
// Clear the screen once, at startup.
|
||||
g.setBgColor(colorBg);
|
||||
g.clear();
|
||||
// Draw LCARS borders.
|
||||
// Upper section: rounded corner.
|
||||
g.setColor(colorLCARSGray);
|
||||
g.fillCircle(outRad, divisionPos - outRad, outRad);
|
||||
g.fillRect(outRad, divisionPos - outRad, sbarWid + inRad, divisionPos);
|
||||
g.fillRect(outRad, divisionPos - hbarHt, sbarWid + outRad, divisionPos); // div bar stub
|
||||
g.fillRect(0, 0, sbarWid, divisionPos - outRad); // side bar
|
||||
g.setColor(colorBg); // blocked out areas of corner
|
||||
g.fillCircle(sbarWid + inRad + 1, divisionPos - hbarHt - inRad - 1, inRad);
|
||||
g.fillRect(sbarWid + 1, divisionPos - outRad * 2, sbarWid + outRad, divisionPos - hbarHt - inRad);
|
||||
// upper division bar
|
||||
g.setColor(colorLCARSPurple);
|
||||
g.fillRect(sbarWid + outRad + gap + 1, divisionPos - hbarHt, g.getWidth(), divisionPos);
|
||||
// Lower section: rounded corner.
|
||||
g.setColor(colorLCARSPink);
|
||||
g.fillCircle(outRad, lowerTop + outRad, outRad);
|
||||
g.fillRect(outRad, lowerTop, sbarWid + inRad, lowerTop + outRad);
|
||||
g.fillRect(outRad, lowerTop, sbarWid + outRad, lowerTop + hbarHt); // div bar stub
|
||||
g.fillRect(0, lowerTop + outRad, sbarWid, sbarGapPos); // side bar
|
||||
g.setColor(colorBg); // blocked out areas of corner
|
||||
g.fillCircle(sbarWid + inRad + 1, lowerTop + hbarHt + inRad + 1, inRad);
|
||||
g.fillRect(sbarWid + 1, lowerTop + hbarHt + inRad, sbarWid + outRad, lowerTop + outRad * 2);
|
||||
// lower division bar
|
||||
g.setColor(colorLCARSOrange);
|
||||
g.fillRect(sbarWid + outRad + gap + 1, lowerTop, g.getWidth(), lowerTop + hbarHt);
|
||||
// second color of side bar
|
||||
g.setColor(colorLCARSBrown);
|
||||
g.fillRect(0, sbarGapPos + gap + 1, sbarWid, g.getHeight());
|
||||
// Draw immediately at first.
|
||||
updateStardate();
|
||||
updateConventionalTime();
|
||||
// Make sure widgets can be shown.
|
||||
//g.setColor("#FF0000"); g.fillRect(0, 0, g.getWidth(), widgetsHeight); // debug
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
// Show launcher on button press as usual for a clock face
|
||||
Bangle.setUI("clock", Bangle.showLauncher);
|
||||
// Stop updates when LCD is off, restart when on
|
||||
Bangle.on('lcdPower', on => {
|
||||
if (on) {
|
||||
redrawClock = true;
|
||||
// Draw immediately to kick things off.
|
||||
updateStardate();
|
||||
updateConventionalTime();
|
||||
}
|
||||
else {
|
||||
redrawClock = false;
|
||||
}
|
||||
});
|
||||
Bangle.on('touch', button => {
|
||||
// button == 1 is left, 2 is right
|
||||
switchClockface();
|
||||
});
|
After Width: | Height: | Size: 594 B |
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"id": "stardateclock",
|
||||
"name":"Stardate Clock",
|
||||
"shortName":"Stardate Clock",
|
||||
"description": "A clock displaying a stardate along with a 'standard' digital/analog clock in LCARS design",
|
||||
"version":"1.0",
|
||||
"icon": "app.png",
|
||||
"type":"clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||
"allow_emulator": true,
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name": "stardateclock.app.js","url": "app.js"},
|
||||
{"name": "stardateclock.img","url": "app-icon.js","evaluate": true}
|
||||
],
|
||||
"screenshots": [
|
||||
{"url": "screenshot1.png"},
|
||||
{"url": "screenshot2.png"},
|
||||
{"url": "screenshot3.png"},
|
||||
{"url": "screenshot4.png"}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 2.3 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 5.2 KiB |
|
@ -7,6 +7,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"sunclock.app.js","url":"app.js"},
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"supmariodark.app.js","url":"supmariodark.js"},
|
||||
{"name":"supmariodark.img","url":"supmariodark-icon.js","evaluate":true},
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "bootloader",
|
||||
"tags": "tool",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"storage": [
|
||||
{"name":"touchmenu.boot.js","url":"touchmenu.boot.js"}
|
||||
]
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"type": "clock",
|
||||
"tags": "clock",
|
||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{"name":"waveclk.app.js","url":"app.js"},
|
||||
|
|
|
@ -15,6 +15,7 @@ print(ExStats.getList());
|
|||
{name: "Distance", id:"dist"},
|
||||
{name: "Steps", id:"step"},
|
||||
{name: "Heart (BPM)", id:"bpm"},
|
||||
{name: "Max BPM", id:"maxbpm"},
|
||||
{name: "Pace (avr)", id:"pacea"},
|
||||
{name: "Pace (current)", id:"pacec"},
|
||||
{name: "Cadence", id:"caden"},
|
||||
|
@ -72,6 +73,7 @@ var state = {
|
|||
// cadence // steps per minute adjusted if <1 minute
|
||||
// BPM // beats per minute
|
||||
// BPMage // how many seconds was BPM set?
|
||||
// maxBPM // The highest BPM reached while active
|
||||
// Notifies: 0 for disabled, otherwise how often to notify in meters, seconds, or steps
|
||||
notify: {
|
||||
dist: {
|
||||
|
@ -159,6 +161,10 @@ Bangle.on("HRM", function(h) {
|
|||
if (h.confidence>=60) {
|
||||
state.BPM = h.bpm;
|
||||
state.BPMage = 0;
|
||||
if (state.maxBPM < h.bpm) {
|
||||
state.maxBPM = h.bpm;
|
||||
if (stats["maxbpm"]) stats["maxbpm"].emit("changed",stats["maxbpm"]);
|
||||
}
|
||||
if (stats["bpm"]) stats["bpm"].emit("changed",stats["bpm"]);
|
||||
}
|
||||
});
|
||||
|
@ -170,6 +176,7 @@ exports.getList = function() {
|
|||
{name: "Distance", id:"dist"},
|
||||
{name: "Steps", id:"step"},
|
||||
{name: "Heart (BPM)", id:"bpm"},
|
||||
{name: "Max BPM", id:"maxbpm"},
|
||||
{name: "Pace (avg)", id:"pacea"},
|
||||
{name: "Pace (curr)", id:"pacec"},
|
||||
{name: "Speed", id:"speed"},
|
||||
|
@ -230,6 +237,14 @@ exports.getStats = function(statIDs, options) {
|
|||
getString : function() { return state.BPM||"--" },
|
||||
};
|
||||
}
|
||||
if (statIDs.includes("maxbpm")) {
|
||||
needHRM = true;
|
||||
stats["maxbpm"]={
|
||||
title : "Max BPM",
|
||||
getValue : function() { return state.maxBPM; },
|
||||
getString : function() { return state.maxBPM||"--" },
|
||||
};
|
||||
}
|
||||
if (statIDs.includes("pacea")) {
|
||||
needGPS = true;
|
||||
stats["pacea"]={
|
||||
|
@ -299,6 +314,7 @@ exports.getStats = function(statIDs, options) {
|
|||
state.curSpeed = 0;
|
||||
state.BPM = 0;
|
||||
state.BPMage = 0;
|
||||
state.maxBPM = 0;
|
||||
state.notify = options.notify;
|
||||
if (options.notify.dist.increment > 0) {
|
||||
state.notify.dist.next = state.distance + options.notify.dist.increment;
|
||||
|
|