Merge branch 'espruino:master' into master
commit
3fe40c7fe7
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: attempt to import
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Bad Apple demo 
|
||||||
|
|
||||||
|
"Bad Apple" is like "Hello World" for graphics system. So this is it
|
||||||
|
for Bangle.js2. Watch have no speaker, so vibration motor is used,
|
||||||
|
instead, to produce (pretty quiet) sound.
|
||||||
|
|
||||||
|
Tools for preparing bad.araw and bad.vraw are in prep/ directory. Full
|
||||||
|
3 minute demo should actually fit to the watch.
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwgIifiAFWj//Aod///gAgMH///+AFBn4FB/AQDAoYEB//8gEBAokDAoX+ApguCAAIFqGoYFNLIZHBApZxFAoyDCAoqJCSoqsBUIcPAoKtF4AFBJAS/DHIQAeA="))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
|
|
@ -0,0 +1,65 @@
|
||||||
|
/* sox Rear_Right.wav -r 4k -b 8 -c 1 -e unsigned-integer 0.raw vol 2
|
||||||
|
aplay -r 4000 /tmp/0.raw
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* https://forum.espruino.com/conversations/348912/ */
|
||||||
|
|
||||||
|
let pin = D19;
|
||||||
|
|
||||||
|
function play(name, callback) {
|
||||||
|
function playChar(offs) {
|
||||||
|
var l = 10240;
|
||||||
|
var s = require("Storage").read(name, offs, l);
|
||||||
|
//print("Waveform " + name + " " + s.length);
|
||||||
|
if (!s.length) {
|
||||||
|
digitalWrite(pin,0);
|
||||||
|
if (callback) callback();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var w = new Waveform(s.length);
|
||||||
|
var b = w.buffer;
|
||||||
|
b.set(s);
|
||||||
|
//print("Buffer", s.length);
|
||||||
|
//for (var i=s.length-1;i>=0;i--)b[i]/=4;
|
||||||
|
w.startOutput(pin, 4000);
|
||||||
|
w.on("finish", function(buf) {
|
||||||
|
playChar(offs+l);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
analogWrite(pin, 0.1, {freq:40000});
|
||||||
|
playChar(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function video(name, callback) {
|
||||||
|
function frame() {
|
||||||
|
var s = require("Storage").read(name, offs, l);
|
||||||
|
if (!s)
|
||||||
|
return;
|
||||||
|
g.drawImage(s, 0, 0, { scale: 2 });
|
||||||
|
g.flip();
|
||||||
|
offs += l;
|
||||||
|
}
|
||||||
|
g.clear();
|
||||||
|
var offs = 0;
|
||||||
|
//var l = 3875; for 176x176
|
||||||
|
//var l = 515; for 64x64
|
||||||
|
var l = 971;
|
||||||
|
setInterval(frame, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run() {
|
||||||
|
clearInterval(i);
|
||||||
|
print("Running");
|
||||||
|
play('bad.araw');
|
||||||
|
t1 = getTime();
|
||||||
|
video('bad.vraw');
|
||||||
|
print("100 frames in ", getTime()-t1);
|
||||||
|
// 1.7s, unscaled
|
||||||
|
// 2.68s, scale 1.01
|
||||||
|
// 5.73s, scale 2.00
|
||||||
|
// 9.93s, scale 2, full screen
|
||||||
|
// 14.4s scaled. 176/64
|
||||||
|
}
|
||||||
|
|
||||||
|
print("Loaded");
|
||||||
|
i = setInterval(run, 100);
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,16 @@
|
||||||
|
{ "id": "bad",
|
||||||
|
"name": "Bad Apple",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Bad Apple demo",
|
||||||
|
"icon": "app.png",
|
||||||
|
"readme": "README.md",
|
||||||
|
"supports" : ["BANGLEJS2"],
|
||||||
|
"allow_emulator": false,
|
||||||
|
"tags": "game",
|
||||||
|
"storage": [
|
||||||
|
{"name":"bad.app.js","url":"bad.app.js"},
|
||||||
|
{"name":"bad.vraw","url":"bad.vraw"},
|
||||||
|
{"name":"bad.araw","url":"bad.araw"},
|
||||||
|
{"name":"bad.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
from PIL import Image
|
||||||
|
import os
|
||||||
|
|
||||||
|
def convert_image(input_path, output_width, output_height):
|
||||||
|
img = Image.open(input_path)
|
||||||
|
img_resized = img.resize((output_width, output_height), Image.ANTIALIAS)
|
||||||
|
img_gray = img_resized.convert('L')
|
||||||
|
img_1bpp = img_gray.point(lambda x: 0 if x < 128 else 255, '1')
|
||||||
|
return img_1bpp
|
||||||
|
|
||||||
|
def convert_and_append_header(input_directory, size):
|
||||||
|
input_files = [f for f in os.listdir(input_directory) if f.startswith("image_") and f.endswith(".png")]
|
||||||
|
input_files.sort()
|
||||||
|
header_bytes = size.to_bytes(1, byteorder='big') + size.to_bytes(1, byteorder='big') + b'\x01'
|
||||||
|
|
||||||
|
for i, input_file in enumerate(input_files):
|
||||||
|
input_path = os.path.join(input_directory, input_file)
|
||||||
|
img_1bpp = convert_image(input_path, size, size)
|
||||||
|
output_file = input_path + ".raw"
|
||||||
|
|
||||||
|
with open(output_file, 'wb') as raw_file:
|
||||||
|
raw_file.write(header_bytes)
|
||||||
|
raw_file.write(img_1bpp.tobytes())
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
input_directory = "." # Replace with the path to your image directory
|
||||||
|
output_width = 88
|
||||||
|
output_file_path = "output_with_header.raw" # Replace with the desired output file path
|
||||||
|
|
||||||
|
convert_and_append_header(input_directory, output_width)
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# aplay -r 4000 /tmp/0.raw
|
||||||
|
#bug: Terminal exists on b.js, it is dumb terminal, not vt100.
|
||||||
|
|
||||||
|
rm image_*.png image_*.png.raw output.wav ../bad.araw ../bad.vraw
|
||||||
|
|
||||||
|
I=bad.mp4
|
||||||
|
S=1:18
|
||||||
|
E=1:50
|
||||||
|
|
||||||
|
ffmpeg -i $I -ss $S -to $E -vn -acodec pcm_u8 -ar 4000 -ac 1 -y output.wav
|
||||||
|
./wav_divider.py
|
||||||
|
mv output.raw ../bad.araw
|
||||||
|
|
||||||
|
ffmpeg -i $I -ss $S -to $E -r 5 -vf fps=5 image_%04d.png
|
||||||
|
./img_convert.py
|
||||||
|
cat *.png.raw > ../bad.vraw
|
||||||
|
|
||||||
|
ls -al ../bad.*
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
|
||||||
|
def divide_bytes(input_file, output_file):
|
||||||
|
with open(input_file, 'rb') as infile:
|
||||||
|
with open(output_file, 'wb') as outfile:
|
||||||
|
byte = infile.read(1)
|
||||||
|
while byte:
|
||||||
|
# Convert byte to integer, divide by 4, and write back as byte
|
||||||
|
new_byte = bytes([int.from_bytes(byte, byteorder='big') // 3])
|
||||||
|
outfile.write(new_byte)
|
||||||
|
byte = infile.read(1)
|
||||||
|
|
||||||
|
divide_bytes("output.wav", "output.raw")
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.01: Added app
|
||||||
|
0.02: Removed unneeded squares
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwwhC/AEUiAAQEEkECBRAX/C/4Xrd+hCDI4kgR/4X/C/4XIAF53/C/4X/A4gSDC4kgC5AAvR/4X/C/4A/ADoA=="))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 407 B |
|
|
@ -0,0 +1,39 @@
|
||||||
|
function draw() {
|
||||||
|
var dt = new Date();
|
||||||
|
var h = dt.getHours(), m = dt.getMinutes();
|
||||||
|
const t = [];
|
||||||
|
t[0] = Math.floor(h/10);
|
||||||
|
t[1] = Math.floor(h%10);
|
||||||
|
t[2] = Math.floor(m/10);
|
||||||
|
t[3] = Math.floor(m%10);
|
||||||
|
|
||||||
|
g.reset();
|
||||||
|
g.clearRect(Bangle.appRect);
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
const sq = 29;
|
||||||
|
const gap = 8;
|
||||||
|
const mgn = 20;
|
||||||
|
const pos = sq + gap;
|
||||||
|
|
||||||
|
for (let r = 3; r >= 0; r--) {
|
||||||
|
for (let c = 0; c < 4; c++) {
|
||||||
|
if (t[c] & Math.pow(2, r)) {
|
||||||
|
g.fillRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq);
|
||||||
|
} else {
|
||||||
|
g.drawRect(mgn/2 + gap + c * pos, mgn + gap + i * pos, mgn/2 + gap + c * pos + sq, mgn + gap + i * pos + sq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
g.clearRect(mgn/2 + gap, mgn + gap, mgn/2 + gap + sq, mgn + 2 * gap + 2 * sq);
|
||||||
|
g.clearRect(mgn/2 + 3 * gap + 2 * sq, mgn + gap, mgn/2 + 3 * gap + 3 * sq, mgn + gap + sq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
g.clear();
|
||||||
|
draw();
|
||||||
|
var secondInterval = setInterval(draw, 60000);
|
||||||
|
Bangle.setUI("clock");
|
||||||
|
Bangle.loadWidgets();
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"id": "binaryclk",
|
||||||
|
"name": "Bin Clock",
|
||||||
|
"version": "0.02",
|
||||||
|
"description": "Clock face to show binary time in 24 hr format",
|
||||||
|
"icon": "app-icon.png",
|
||||||
|
"screenshots": [{"url":"screenshot.png"}],
|
||||||
|
"type": "clock",
|
||||||
|
"tags": "clock",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"allow_emulator": true,
|
||||||
|
"storage": [
|
||||||
|
{"name":"binaryclk.app.js","url":"app.js"},
|
||||||
|
{"name":"binaryclk.img","url":"app-icon.js","evaluate":true}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
|
|
@ -5,3 +5,4 @@
|
||||||
0.05: Show calendar colors & improved all day events.
|
0.05: Show calendar colors & improved all day events.
|
||||||
0.06: Improved multi-line locations & titles
|
0.06: Improved multi-line locations & titles
|
||||||
0.07: Buzz 30, 15 and 1 minute before an event
|
0.07: Buzz 30, 15 and 1 minute before an event
|
||||||
|
0.08: No buzz during quiet hours & tweaked 30-minute buzz
|
||||||
|
|
|
||||||
|
|
@ -119,10 +119,12 @@ function fullRedraw() {
|
||||||
|
|
||||||
function buzzForEvents() {
|
function buzzForEvents() {
|
||||||
let nextEvent = next[0]; if (!nextEvent) return;
|
let nextEvent = next[0]; if (!nextEvent) return;
|
||||||
if (nextEvent.allDay) return;
|
// No buzz for all day events or events before 7am
|
||||||
|
// TODO: make this configurable
|
||||||
|
if (nextEvent.allDay || (new Date(nextEvent.timestamp * 1000)).getHours() < 7) return;
|
||||||
let minToEvent = Math.round((nextEvent.timestamp - getTime()) / 60.0);
|
let minToEvent = Math.round((nextEvent.timestamp - getTime()) / 60.0);
|
||||||
switch (minToEvent) {
|
switch (minToEvent) {
|
||||||
case 30: require("buzz").pattern(","); break;
|
case 30: require("buzz").pattern(":"); break;
|
||||||
case 15: require("buzz").pattern(", ,"); break;
|
case 15: require("buzz").pattern(", ,"); break;
|
||||||
case 1: require("buzz").pattern(": : :"); break;
|
case 1: require("buzz").pattern(": : :"); break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "calclock",
|
"id": "calclock",
|
||||||
"name": "Calendar Clock",
|
"name": "Calendar Clock",
|
||||||
"shortName": "CalClock",
|
"shortName": "CalClock",
|
||||||
"version": "0.07",
|
"version": "0.08",
|
||||||
"description": "Show the current and upcoming events synchronized from Gadgetbridge",
|
"description": "Show the current and upcoming events synchronized from Gadgetbridge",
|
||||||
"icon": "calclock.png",
|
"icon": "calclock.png",
|
||||||
"type": "clock",
|
"type": "clock",
|
||||||
|
|
|
||||||
|
|
@ -32,12 +32,14 @@ function readFile(input) {
|
||||||
const jCalData = ICAL.parse(icalText);
|
const jCalData = ICAL.parse(icalText);
|
||||||
const comp = new ICAL.Component(jCalData);
|
const comp = new ICAL.Component(jCalData);
|
||||||
const vtz = comp.getFirstSubcomponent('vtimezone');
|
const vtz = comp.getFirstSubcomponent('vtimezone');
|
||||||
const tz = new ICAL.Timezone(vtz);
|
const tz = vtz != null ? new ICAL.Timezone(vtz) : null;
|
||||||
|
|
||||||
// Fetch the VEVENT part
|
// Fetch the VEVENT part
|
||||||
comp.getAllSubcomponents('vevent').forEach(vevent => {
|
comp.getAllSubcomponents('vevent').forEach(vevent => {
|
||||||
const event = new ICAL.Event(vevent);
|
const event = new ICAL.Event(vevent);
|
||||||
event.startDate.zone = tz;
|
if (tz != null) {
|
||||||
|
event.startDate.zone = tz;
|
||||||
|
}
|
||||||
holidays = holidays.filter(holiday => !sameDay(new Date(holiday.date), event.startDate.toJSDate())); // remove if already exists
|
holidays = holidays.filter(holiday => !sameDay(new Date(holiday.date), event.startDate.toJSDate())); // remove if already exists
|
||||||
|
|
||||||
const holiday = eventToHoliday(event);
|
const holiday = eventToHoliday(event);
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
0.01: New App!
|
0.01: New App!
|
||||||
0.02: Bugfixes
|
0.02: Bugfixes
|
||||||
|
0.03: Use Bangle.setBacklight()
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ Bangle.loadWidgets(); // load before first appRect call
|
||||||
const FIELD_WIDTH = Bangle.appRect.w/8;
|
const FIELD_WIDTH = Bangle.appRect.w/8;
|
||||||
const FIELD_HEIGHT = Bangle.appRect.h/8;
|
const FIELD_HEIGHT = Bangle.appRect.h/8;
|
||||||
const SETTINGS_FILE = "chess.json";
|
const SETTINGS_FILE = "chess.json";
|
||||||
const DEFAULT_TIMEOUT = Bangle.getOptions().lockTimeout;
|
|
||||||
const ICON_SIZE=45;
|
const ICON_SIZE=45;
|
||||||
const ICON_BISHOP = require("heatshrink").decompress(atob("lstwMB/4Ac/wFE4IED/kPAofgn4FDGon8j4QEBQgQE4EHBQcACwfAgF/BQYWD8EAHAX+NgI4C+AQEwAQDDYIhDDYMDCAQKBGQQsHHogKDCAJODCAI3CHoQKCHoIQDHoIQCFgoQBFgfgIQYmBEIQECKgIrCBYQKDC4OBg/8iCvEAC+AA="));
|
const ICON_BISHOP = require("heatshrink").decompress(atob("lstwMB/4Ac/wFE4IED/kPAofgn4FDGon8j4QEBQgQE4EHBQcACwfAgF/BQYWD8EAHAX+NgI4C+AQEwAQDDYIhDDYMDCAQKBGQQsHHogKDCAJODCAI3CHoQKCHoIQDHoIQCFgoQBFgfgIQYmBEIQECKgIrCBYQKDC4OBg/8iCvEAC+AA="));
|
||||||
const ICON_PAWN = require("heatshrink").decompress(atob("lstwMB/4At/AFEGon4h4FDwE/AgX8CAngCAkAv4bDgYbECAf4gAhD4AhD/kAg4mDCAkACAYbBEIYQBG4gbDEII9DFhXAgEfBQYWDEwJUC/wKBGQXwCAgEBE4RCBCAYmBCAQmCCAQmBCAbdCCAIbCQ4gAYwA="));
|
const ICON_PAWN = require("heatshrink").decompress(atob("lstwMB/4At/AFEGon4h4FDwE/AgX8CAngCAkAv4bDgYbECAf4gAhD4AhD/kAg4mDCAkACAYbBEIYQBG4gbDEII9DFhXAgEfBQYWDEwJUC/wKBGQXwCAgEBE4RCBCAYmBCAQmCCAQmBCAbdCCAIbCQ4gAYwA="));
|
||||||
|
|
@ -192,6 +191,7 @@ Bangle.drawWidgets();
|
||||||
|
|
||||||
// drag selected field
|
// drag selected field
|
||||||
Bangle.on('drag', (ev) => {
|
Bangle.on('drag', (ev) => {
|
||||||
|
if (showmenu) return;
|
||||||
const newx = curfield[0]+ev.dx;
|
const newx = curfield[0]+ev.dx;
|
||||||
const newy = curfield[1]+ev.dy;
|
const newy = curfield[1]+ev.dy;
|
||||||
if (newx >= 0 && newx <= 7*FIELD_WIDTH) {
|
if (newx >= 0 && newx <= 7*FIELD_WIDTH) {
|
||||||
|
|
@ -230,7 +230,7 @@ Bangle.on('touch', (button, xy) => {
|
||||||
drawSelectedField();
|
drawSelectedField();
|
||||||
if (!finished) {
|
if (!finished) {
|
||||||
// do computer move
|
// do computer move
|
||||||
Bangle.setLCDTimeout(0.1); // this can take some time, turn off to save power
|
Bangle.setBacklight(false); // this can take some time, turn off to save power
|
||||||
showMessage(/*LANG*/"Calculating..");
|
showMessage(/*LANG*/"Calculating..");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const compMove = state.findmove(settings.computer_level+1);
|
const compMove = state.findmove(settings.computer_level+1);
|
||||||
|
|
@ -240,15 +240,15 @@ Bangle.on('touch', (button, xy) => {
|
||||||
}
|
}
|
||||||
Bangle.setLCDPower(true);
|
Bangle.setLCDPower(true);
|
||||||
Bangle.setLocked(false);
|
Bangle.setLocked(false);
|
||||||
Bangle.setLCDTimeout(DEFAULT_TIMEOUT/1000); // restore
|
Bangle.setBacklight(true);
|
||||||
if (!showmenu) {
|
if (!showmenu) {
|
||||||
showAlert(result.string);
|
showAlert(result.string);
|
||||||
}
|
}
|
||||||
}, 200); // execute after display update
|
}, 300); // execute after display update
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
move(posFrom, posTo,cb);
|
move(posFrom, posTo,cb);
|
||||||
}, 200); // execute after display update
|
}, 100); // execute after display update
|
||||||
} // piece_sel === 0
|
} // piece_sel === 0
|
||||||
startfield[0] = startfield[1] = undefined;
|
startfield[0] = startfield[1] = undefined;
|
||||||
piece_sel = 0;
|
piece_sel = 0;
|
||||||
|
|
@ -277,7 +277,9 @@ setWatch(() => {
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
"" : { title : /*LANG*/"Chess settings" },
|
"" : { title : /*LANG*/"Chess settings" },
|
||||||
"< Back" : () => closeMenu(),
|
"< Back" : () => closeMenu(),
|
||||||
|
/*LANG*/"Exit" : () => load(),
|
||||||
/*LANG*/"New Game" : () => {
|
/*LANG*/"New Game" : () => {
|
||||||
|
finished = false;
|
||||||
state = engine.p4_fen2state(engine.P4_INITIAL_BOARD);
|
state = engine.p4_fen2state(engine.P4_INITIAL_BOARD);
|
||||||
writeSettings();
|
writeSettings();
|
||||||
closeMenu();
|
closeMenu();
|
||||||
|
|
@ -296,6 +298,5 @@ setWatch(() => {
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/*LANG*/"Exit" : () => load(),
|
|
||||||
});
|
});
|
||||||
}, BTN, { repeat: true, edge: "falling" });
|
}, BTN, { repeat: true, edge: "falling" });
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "chess",
|
"id": "chess",
|
||||||
"name": "Chess",
|
"name": "Chess",
|
||||||
"shortName": "Chess",
|
"shortName": "Chess",
|
||||||
"version": "0.02",
|
"version": "0.03",
|
||||||
"description": "Chess game based on the [p4wn engine](https://p4wn.sourceforge.net/). Drag on the touchscreen to move the green cursor onto a piece, select it with a single touch and drag the now red cursor around. Release the piece with another touch to finish the move. The button opens a menu.",
|
"description": "Chess game based on the [p4wn engine](https://p4wn.sourceforge.net/). Drag on the touchscreen to move the green cursor onto a piece, select it with a single touch and drag the now red cursor around. Release the piece with another touch to finish the move. The button opens a menu.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "game",
|
"tags": "game",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
1.00: first release
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Colours Demo
|
||||||
|
|
||||||
|
This is a simple app to demonstrate colours on a Bangle 2.
|
||||||
|
|
||||||
|
The colours are "optimised" for the Bangle 2's 3-bit display. They only include values which use either the full, half or no primary RGB colour, which should reduce the artifacts due to dithering (the exception are light and dark grey).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Use this app for choosing colours for your own project, and copy the colour definitions from the source code.
|
||||||
|
|
||||||
|
|
||||||
|
## Use colours in other projects
|
||||||
|
|
||||||
|
Copy-and-paste the colour constants to be used in your own app from `coloursdemo.app.js`. They are sandwiched between the "BEGIN" and "END" comments at the beginning of the file.
|
||||||
|
|
||||||
|
With the constants available in your own code, you can for example set the foreground colour to yellow with:
|
||||||
|
|
||||||
|
g.setColor(COLOUR_YELLOW);
|
||||||
|
|
||||||
|
This works for any graphics call requiring a colour value (like `g.setBgColor()`).
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwxH+AH4A/AC8sAAYqpmVdr2Irwvklkzq4qBx4ADxAvDM0EyxAABFwgABF4k5rsyGTksF5MzBwdjAAVdnIzCF69dF5FdEYUyF4YADGQSPVF5LwCRwIvHAAIvVllXF5DwCRwgAFNobwbxFeEISOIAAMzF6zwCsgqBDoMsmUzWQMzF5MyeC4lBEwM5nNAsgABGgMyX5JeWF4IsBFYYADnIvBHgJmBrouDBYIvZnIvHLwIABnBvCMwSOXeAQvImU4F4QADMwReXF5csFwwxDF7IlCYAqOEF44uYF5MzF5ReZR4LwBF4qOKnAvalgvBYAk6RxYvaeAs6EYK+lMAZOBlgtBAQS+jF4QoBSQQjBGRKOcF4YjCMgM4AAIyCBoaOcF4YwCAYIvCGQxeceAQvDGoIvFGQYveSAguJF8iOHAAYueF4iOqeAksRyz8CAAzwNR1RgDMQZeIADJ0JqwmCGQoFB0gAEq2A5wAG0ky54AFrowGFQVXAAIyGmVWF8VWF4QyGlmAF8QsDLYIyFFwovbGAIuDSoqOHF8CJCF4aOHF7q/CqyVEAoIuGF7hgEAAiOIF7xhDYgiOHF7oxDXwLyCRxAvfGAYAhF5QA/AH4AEA"))
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* Demonstrate colours
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// BEGIN colour constants
|
||||||
|
const COLOUR_BLACK = 0x0000; // same as: g.setColor(0, 0, 0)
|
||||||
|
const COLOUR_DARK_GREY = 0x4208; // same as: g.setColor(0.25, 0.25, 0.25)
|
||||||
|
const COLOUR_GREY = 0x8410; // same as: g.setColor(0.5, 0.5, 0.5)
|
||||||
|
const COLOUR_LIGHT_GREY = 0xc618; // same as: g.setColor(0.75, 0.75, 0.75)
|
||||||
|
const COLOUR_WHITE = 0xffff; // same as: g.setColor(1, 1, 1)
|
||||||
|
|
||||||
|
const COLOUR_RED = 0xf800; // same as: g.setColor(1, 0, 0)
|
||||||
|
const COLOUR_GREEN = 0x07e0; // same as: g.setColor(0, 1, 0)
|
||||||
|
const COLOUR_BLUE = 0x001f; // same as: g.setColor(0, 0, 1)
|
||||||
|
const COLOUR_YELLOW = 0xffe0; // same as: g.setColor(1, 1, 0)
|
||||||
|
const COLOUR_MAGENTA = 0xf81f; // same as: g.setColor(1, 0, 1)
|
||||||
|
const COLOUR_CYAN = 0x07ff; // same as: g.setColor(0, 1, 1)
|
||||||
|
|
||||||
|
const COLOUR_LIGHT_RED = 0xfc10; // same as: g.setColor(1, 0.5, 0.5)
|
||||||
|
const COLOUR_LIGHT_GREEN = 0x87f0; // same as: g.setColor(0.5, 1, 0.5)
|
||||||
|
const COLOUR_LIGHT_BLUE = 0x841f; // same as: g.setColor(0.5, 0.5, 1)
|
||||||
|
const COLOUR_LIGHT_YELLOW = 0xfff0; // same as: g.setColor(1, 1, 0.5)
|
||||||
|
const COLOUR_LIGHT_MAGENTA = 0xfc1f; // same as: g.setColor(1, 0.5, 1)
|
||||||
|
const COLOUR_LIGHT_CYAN = 0x87ff; // same as: g.setColor(0.5, 1, 1)
|
||||||
|
|
||||||
|
const COLOUR_DARK_RED = 0x8000; // same as: g.setColor(0.5, 0, 0)
|
||||||
|
const COLOUR_DARK_GREEN = 0x0400; // same as: g.setColor(0, 0.5, 0)
|
||||||
|
const COLOUR_DARK_BLUE = 0x0010; // same as: g.setColor(0, 0, 0.5)
|
||||||
|
const COLOUR_DARK_YELLOW = 0x8400; // same as: g.setColor(0.5, 0.5, 0)
|
||||||
|
const COLOUR_DARK_MAGENTA = 0x8010; // same as: g.setColor(0.5, 0, 0.5)
|
||||||
|
const COLOUR_DARK_CYAN = 0x0410; // same as: g.setColor(0, 0.5, 0.5)
|
||||||
|
|
||||||
|
const COLOUR_PINK = 0xf810; // same as: g.setColor(1, 0, 0.5)
|
||||||
|
const COLOUR_LIMEGREEN = 0x87e0; // same as: g.setColor(0.5, 1, 0)
|
||||||
|
const COLOUR_ROYALBLUE = 0x041f; // same as: g.setColor(0, 0.5, 1)
|
||||||
|
const COLOUR_ORANGE = 0xfc00; // same as: g.setColor(1, 0.5, 0)
|
||||||
|
const COLOUR_INDIGO = 0x801f; // same as: g.setColor(0.5, 0, 1)
|
||||||
|
const COLOUR_TURQUOISE = 0x07f0; // same as: g.setColor(0, 1, 0.5)
|
||||||
|
// END colour constants
|
||||||
|
|
||||||
|
|
||||||
|
// array of colours to be demoed:
|
||||||
|
// [ colour value, label colour, label ]
|
||||||
|
const demo = [
|
||||||
|
[ COLOUR_LIGHT_RED, COLOUR_BLACK, 'LIGHT RED' ],
|
||||||
|
[ COLOUR_RED, COLOUR_WHITE, 'RED' ],
|
||||||
|
[ COLOUR_DARK_RED, COLOUR_WHITE, 'DARK RED' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_YELLOW, COLOUR_BLACK, 'LIGHT YELLOW' ],
|
||||||
|
[ COLOUR_YELLOW, COLOUR_BLACK, 'YELLOW' ],
|
||||||
|
[ COLOUR_DARK_YELLOW, COLOUR_WHITE, 'DARK YELLOW' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_GREEN, COLOUR_BLACK, 'LIGHT GREEN' ],
|
||||||
|
[ COLOUR_GREEN, COLOUR_BLACK, 'GREEN' ],
|
||||||
|
[ COLOUR_DARK_GREEN, COLOUR_WHITE, 'DARK GREEN' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_CYAN, COLOUR_BLACK, 'LIGHT CYAN' ],
|
||||||
|
[ COLOUR_CYAN, COLOUR_BLACK, 'CYAN' ],
|
||||||
|
[ COLOUR_DARK_CYAN, COLOUR_WHITE, 'DARK CYAN' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_BLUE, COLOUR_BLACK, 'LIGHT BLUE' ],
|
||||||
|
[ COLOUR_BLUE, COLOUR_WHITE, 'BLUE' ],
|
||||||
|
[ COLOUR_DARK_BLUE, COLOUR_WHITE, 'DARK BLUE' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_MAGENTA, COLOUR_BLACK, 'LIGHT MAGENTA' ],
|
||||||
|
[ COLOUR_MAGENTA, COLOUR_WHITE, 'MAGENTA' ],
|
||||||
|
[ COLOUR_DARK_MAGENTA, COLOUR_WHITE, 'DARK MAGENTA' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIMEGREEN, COLOUR_BLACK, 'LIMEGREEN' ],
|
||||||
|
[ COLOUR_TURQUOISE, COLOUR_BLACK, 'TURQUOISE' ],
|
||||||
|
[ COLOUR_ROYALBLUE, COLOUR_WHITE, 'ROYALBLUE' ],
|
||||||
|
|
||||||
|
[ COLOUR_ORANGE, COLOUR_BLACK, 'ORANGE' ],
|
||||||
|
[ COLOUR_PINK, COLOUR_WHITE, 'PINK' ],
|
||||||
|
[ COLOUR_INDIGO, COLOUR_WHITE, 'INDIGO' ],
|
||||||
|
|
||||||
|
[ COLOUR_LIGHT_GREY, COLOUR_BLACK, 'LIGHT GREY' ],
|
||||||
|
[ COLOUR_GREY, COLOUR_BLACK, 'GREY' ],
|
||||||
|
[ COLOUR_DARK_GREY, COLOUR_WHITE, 'DARK GREY' ],
|
||||||
|
|
||||||
|
[ COLOUR_WHITE, COLOUR_BLACK, 'WHITE' ],
|
||||||
|
[ COLOUR_BLACK, COLOUR_WHITE, 'BLACK' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns = 3;
|
||||||
|
const rows = 10;
|
||||||
|
|
||||||
|
|
||||||
|
// initialise
|
||||||
|
g.clear(true);
|
||||||
|
g.setFont('6x8').setFontAlign(-1, -1);
|
||||||
|
|
||||||
|
// calc some values required to draw the grid
|
||||||
|
const colWidth = Math.floor(g.getWidth() / columns);
|
||||||
|
const rowHeight = Math.floor(g.getHeight() / rows);
|
||||||
|
const xStart = Math.floor((g.getWidth() - (columns * colWidth)) / 2);
|
||||||
|
var x = xStart;
|
||||||
|
var y = Math.floor((g.getHeight() - (rows * rowHeight)) / 2);
|
||||||
|
|
||||||
|
// loop through the colours to be demoed
|
||||||
|
for (var idx in demo) {
|
||||||
|
var colour = demo[idx][0];
|
||||||
|
var labelColour = demo[idx][1];
|
||||||
|
var label = demo[idx][2];
|
||||||
|
|
||||||
|
// draw coloured box
|
||||||
|
g.setColor(colour).fillRect(x, y, x + colWidth - 1, y + rowHeight - 1);
|
||||||
|
|
||||||
|
// label it
|
||||||
|
g.setColor(labelColour).drawString(g.wrapString(label, colWidth).join("\n"), x, y);
|
||||||
|
|
||||||
|
x += colWidth;
|
||||||
|
if ((x + colWidth) >= g.getWidth()) {
|
||||||
|
x = xStart;
|
||||||
|
y += rowHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// there's an "unused" box left - cross it out
|
||||||
|
g.setColor(COLOUR_RED);
|
||||||
|
g.drawLine(x, y, x + colWidth - 1, y + rowHeight - 1);
|
||||||
|
g.drawLine(x, y + rowHeight - 1, x + colWidth - 1, y);
|
||||||
|
|
||||||
|
|
||||||
|
// exit on button press
|
||||||
|
setWatch(e => { Bangle.showClock(); }, BTN1);
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"id": "coloursdemo",
|
||||||
|
"name": "Colours Demo",
|
||||||
|
"shortName":"Colours Demo",
|
||||||
|
"version":"1.00",
|
||||||
|
"description": "Simple app to demonstrate colours",
|
||||||
|
"icon": "coloursdemo.png",
|
||||||
|
"screenshots": [{ "url": "screenshot.png" }],
|
||||||
|
"type": "app",
|
||||||
|
"tags": "tool",
|
||||||
|
"supports": ["BANGLEJS2"],
|
||||||
|
"readme": "README.md",
|
||||||
|
"storage": [
|
||||||
|
{ "name":"coloursdemo.app.js", "url":"coloursdemo.app.js" },
|
||||||
|
{ "name":"coloursdemo.img", "url":"coloursdemo-icon.js", "evaluate":true }
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
|
|
@ -29,3 +29,4 @@
|
||||||
0.26: Implement API for activity fetching
|
0.26: Implement API for activity fetching
|
||||||
0.27: Fix typo in daily summary graph code causing graph not to load
|
0.27: Fix typo in daily summary graph code causing graph not to load
|
||||||
Fix daily summaries for 31st of the month
|
Fix daily summaries for 31st of the month
|
||||||
|
0.28: Calculate distance from steps if myprofile is installed and stride length is set
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ To view data, run the `Health` app from your watch.
|
||||||
Stores:
|
Stores:
|
||||||
|
|
||||||
* Heart rate
|
* Heart rate
|
||||||
* Step count
|
* Step count (can calculate distance if myprofile is installed and stride length is set)
|
||||||
* Movement
|
* Movement
|
||||||
|
|
||||||
## Settings
|
## Settings
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
let settings;
|
||||||
|
const myprofile = require("Storage").readJSON("myprofile.json",1)||{};
|
||||||
|
|
||||||
function menuMain() {
|
function menuMain() {
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
"": { title: /*LANG*/"Health Tracking" },
|
"": { title: /*LANG*/"Health Tracking" },
|
||||||
|
|
@ -5,16 +8,31 @@ function menuMain() {
|
||||||
/*LANG*/"Step Counting": () => menuStepCount(),
|
/*LANG*/"Step Counting": () => menuStepCount(),
|
||||||
/*LANG*/"Movement": () => menuMovement(),
|
/*LANG*/"Movement": () => menuMovement(),
|
||||||
/*LANG*/"Heart Rate": () => menuHRM(),
|
/*LANG*/"Heart Rate": () => menuHRM(),
|
||||||
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>menuMain())
|
/*LANG*/"Settings": () => eval(require("Storage").read("health.settings.js"))(()=>{loadSettings();menuMain();})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function menuStepCount() {
|
function menuStepCount() {
|
||||||
E.showMenu({
|
const menu = {
|
||||||
"": { title:/*LANG*/"Steps" },
|
"": { title:/*LANG*/"Steps" },
|
||||||
/*LANG*/"< Back": () => menuMain(),
|
/*LANG*/"< Back": () => menuMain(),
|
||||||
/*LANG*/"per hour": () => stepsPerHour(),
|
/*LANG*/"per hour": () => stepsPerHour(menuStepCount),
|
||||||
/*LANG*/"per day": () => stepsPerDay()
|
/*LANG*/"per day": () => stepsPerDay(menuStepCount)
|
||||||
|
};
|
||||||
|
if (myprofile.strideLength) {
|
||||||
|
menu[/*LANG*/"distance"] = () => menuDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
E.showMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
function menuDistance() {
|
||||||
|
const distMult = 1*require("locale").distance(myprofile.strideLength, 2); // hackish: this removes the distance suffix, e.g. 'm'
|
||||||
|
E.showMenu({
|
||||||
|
"": { title:/*LANG*/"Distance" },
|
||||||
|
/*LANG*/"< Back": () => menuStepCount(),
|
||||||
|
/*LANG*/"per hour": () => stepsPerHour(menuDistance, distMult),
|
||||||
|
/*LANG*/"per day": () => stepsPerDay(menuDistance, distMult)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -36,23 +54,35 @@ function menuHRM() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepsPerHour() {
|
function stepsPerHour(back, mult) {
|
||||||
E.showMessage(/*LANG*/"Loading...");
|
E.showMessage(/*LANG*/"Loading...");
|
||||||
current_selection = "stepsPerHour";
|
current_selection = "stepsPerHour";
|
||||||
var data = new Uint16Array(24);
|
var data = new Uint16Array(24);
|
||||||
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
|
require("health").readDay(new Date(), h=>data[h.hr]+=h.steps);
|
||||||
setButton(menuStepCount);
|
if (mult !== undefined) {
|
||||||
barChart(/*LANG*/"HOUR", data);
|
// Calculate distance from steps
|
||||||
|
data.forEach((d, i) => data[i] = d*mult+0.5);
|
||||||
|
}
|
||||||
|
setButton(back, mult);
|
||||||
|
barChart(/*LANG*/"HOUR", data, mult);
|
||||||
}
|
}
|
||||||
|
|
||||||
function stepsPerDay() {
|
function stepsPerDay(back, mult) {
|
||||||
E.showMessage(/*LANG*/"Loading...");
|
E.showMessage(/*LANG*/"Loading...");
|
||||||
current_selection = "stepsPerDay";
|
current_selection = "stepsPerDay";
|
||||||
var data = new Uint16Array(32);
|
var data = new Uint16Array(32);
|
||||||
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
|
require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps);
|
||||||
setButton(menuStepCount);
|
// Include data for today
|
||||||
barChart(/*LANG*/"DAY", data);
|
if (data[(new Date()).getDate()] === 0) {
|
||||||
drawHorizontalLine(settings.stepGoal);
|
data[(new Date()).getDate()] = Bangle.getHealthStatus("day").steps;
|
||||||
|
}
|
||||||
|
if (mult !== undefined) {
|
||||||
|
// Calculate distance from steps
|
||||||
|
data.forEach((d, i) => data[i] = d*mult+0.5);
|
||||||
|
}
|
||||||
|
setButton(back, mult);
|
||||||
|
barChart(/*LANG*/"DAY", data, mult);
|
||||||
|
drawHorizontalLine(settings.stepGoal * (mult || 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
function hrmPerHour() {
|
function hrmPerHour() {
|
||||||
|
|
@ -64,7 +94,7 @@ function hrmPerHour() {
|
||||||
data[h.hr]+=h.bpm;
|
data[h.hr]+=h.bpm;
|
||||||
if (h.bpm) cnt[h.hr]++;
|
if (h.bpm) cnt[h.hr]++;
|
||||||
});
|
});
|
||||||
data.forEach((d,i)=>data[i] = d/cnt[i]);
|
data.forEach((d,i)=>data[i] = d/cnt[i]+0.5);
|
||||||
setButton(menuHRM);
|
setButton(menuHRM);
|
||||||
barChart(/*LANG*/"HOUR", data);
|
barChart(/*LANG*/"HOUR", data);
|
||||||
}
|
}
|
||||||
|
|
@ -78,7 +108,7 @@ function hrmPerDay() {
|
||||||
data[h.day]+=h.bpm;
|
data[h.day]+=h.bpm;
|
||||||
if (h.bpm) cnt[h.day]++;
|
if (h.bpm) cnt[h.day]++;
|
||||||
});
|
});
|
||||||
data.forEach((d,i)=>data[i] = d/cnt[i]);
|
data.forEach((d,i)=>data[i] = d/cnt[i]+0.5);
|
||||||
setButton(menuHRM);
|
setButton(menuHRM);
|
||||||
barChart(/*LANG*/"DAY", data);
|
barChart(/*LANG*/"DAY", data);
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +122,7 @@ function movementPerHour() {
|
||||||
data[h.hr]+=h.movement;
|
data[h.hr]+=h.movement;
|
||||||
cnt[h.hr]++;
|
cnt[h.hr]++;
|
||||||
});
|
});
|
||||||
data.forEach((d,i)=>data[i] = d/cnt[i]);
|
data.forEach((d,i)=>data[i] = d/cnt[i]+0.5);
|
||||||
setButton(menuMovement);
|
setButton(menuMovement);
|
||||||
barChart(/*LANG*/"HOUR", data);
|
barChart(/*LANG*/"HOUR", data);
|
||||||
}
|
}
|
||||||
|
|
@ -106,7 +136,7 @@ function movementPerDay() {
|
||||||
data[h.day]+=h.movement;
|
data[h.day]+=h.movement;
|
||||||
cnt[h.day]++;
|
cnt[h.day]++;
|
||||||
});
|
});
|
||||||
data.forEach((d,i)=>data[i] = d/cnt[i]);
|
data.forEach((d,i)=>data[i] = d/cnt[i]+0.5);
|
||||||
setButton(menuMovement);
|
setButton(menuMovement);
|
||||||
barChart(/*LANG*/"DAY", data);
|
barChart(/*LANG*/"DAY", data);
|
||||||
}
|
}
|
||||||
|
|
@ -180,7 +210,7 @@ function drawHorizontalLine(value) {
|
||||||
g.setColor(g.theme.fg).drawLine(0, top ,g.getWidth(), top);
|
g.setColor(g.theme.fg).drawLine(0, top ,g.getWidth(), top);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setButton(fn) {
|
function setButton(fn, mult) {
|
||||||
Bangle.setUI({mode:"custom",
|
Bangle.setUI({mode:"custom",
|
||||||
back:fn,
|
back:fn,
|
||||||
swipe:(lr,ud) => {
|
swipe:(lr,ud) => {
|
||||||
|
|
@ -194,12 +224,16 @@ function setButton(fn) {
|
||||||
}
|
}
|
||||||
drawBarChart();
|
drawBarChart();
|
||||||
if (current_selection == "stepsPerDay") {
|
if (current_selection == "stepsPerDay") {
|
||||||
drawHorizontalLine(settings.stepGoal);
|
drawHorizontalLine(settings.stepGoal * (mult || 1));
|
||||||
}
|
}
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadSettings() {
|
||||||
|
settings = require("Storage").readJSON("health.json",1)||{};
|
||||||
|
}
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
Bangle.drawWidgets();
|
Bangle.drawWidgets();
|
||||||
var settings = require("Storage").readJSON("health.json",1)||{};
|
loadSettings();
|
||||||
menuMain();
|
menuMain();
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "health",
|
"id": "health",
|
||||||
"name": "Health Tracking",
|
"name": "Health Tracking",
|
||||||
"shortName": "Health",
|
"shortName": "Health",
|
||||||
"version": "0.27",
|
"version": "0.28",
|
||||||
"description": "Logs health data and provides an app to view it",
|
"description": "Logs health data and provides an app to view it",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,system,health",
|
"tags": "tool,system,health",
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
function setSettings() {
|
function setSettings() {
|
||||||
require("Storage").writeJSON("health.json", settings);
|
require("Storage").writeJSON("health.json", settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
"": { title: /*LANG*/"Health Tracking" },
|
"": { title: /*LANG*/"Health Tracking" },
|
||||||
|
|
||||||
|
|
@ -39,6 +40,7 @@
|
||||||
setSettings();
|
setSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/*LANG*/"Step Goal Notification": {
|
/*LANG*/"Step Goal Notification": {
|
||||||
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
|
value: "stepGoalNotification" in settings ? settings.stepGoalNotification : false,
|
||||||
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
|
format: () => (settings.stepGoalNotification ? 'Yes' : 'No'),
|
||||||
|
|
@ -46,6 +48,6 @@
|
||||||
settings.stepGoalNotification = !settings.stepGoalNotification;
|
settings.stepGoalNotification = !settings.stepGoalNotification;
|
||||||
setSettings();
|
setSettings();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,4 @@
|
||||||
Remove calls to Bangle.loadWidgets as they are not needed and create warnings
|
Remove calls to Bangle.loadWidgets as they are not needed and create warnings
|
||||||
0.32: Added setting to show single timezone small, like where multiple ones are configured
|
0.32: Added setting to show single timezone small, like where multiple ones are configured
|
||||||
0.33: Tidy up and fix clearInterval(undefined) errors
|
0.33: Tidy up and fix clearInterval(undefined) errors
|
||||||
|
0.34: Fix 'fast load' so clock doesn't always redraw when screen unlocked/locked
|
||||||
|
|
@ -443,7 +443,7 @@ Bangle.setUI({
|
||||||
drawTimeout = undefined;
|
drawTimeout = undefined;
|
||||||
//if (BANGLEJS2)
|
//if (BANGLEJS2)
|
||||||
Bangle.removeListener("drag",onDrag);
|
Bangle.removeListener("drag",onDrag);
|
||||||
Bangle.removeListener("onLock",onLock);
|
Bangle.removeListener("lock",onLock);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
g.clear().setRotation(defaultRotation); // clean app screen and make sure the default rotation is set
|
g.clear().setRotation(defaultRotation); // clean app screen and make sure the default rotation is set
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "hworldclock",
|
"id": "hworldclock",
|
||||||
"name": "Hanks World Clock",
|
"name": "Hanks World Clock",
|
||||||
"shortName": "Hanks World Clock",
|
"shortName": "Hanks World Clock",
|
||||||
"version": "0.33",
|
"version": "0.34",
|
||||||
"description": "Current time zone plus up to three others",
|
"description": "Current time zone plus up to three others",
|
||||||
"allow_emulator":true,
|
"allow_emulator":true,
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,4 @@
|
||||||
0.27: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
|
0.27: Report latest HRM rather than HRM 10 minutes ago (fix #2395)
|
||||||
0.28: Battery Vref implemented correctly.
|
0.28: Battery Vref implemented correctly.
|
||||||
0.29: Support fastload.
|
0.29: Support fastload.
|
||||||
|
0.30: Add many new colors to the settings and allows random colors on startup if enabled.
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ the "sched" app must be installed on your device.
|
||||||
* The lower orange line indicates the battery level.
|
* The lower orange line indicates the battery level.
|
||||||
* Display graphs (day or month) for steps + hrm on the second screen.
|
* Display graphs (day or month) for steps + hrm on the second screen.
|
||||||
* Customizable theming colors in the settings menu of the app.
|
* Customizable theming colors in the settings menu of the app.
|
||||||
|
* Allow random colors on startup.
|
||||||
* Enable or disable the alarm feature.
|
* Enable or disable the alarm feature.
|
||||||
* Enable or disbale the graphs for steps + hrm.
|
* Enable or disbale the graphs for steps + hrm.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,18 +16,36 @@ let settings = {
|
||||||
themeColor3BG: "#0094FF",
|
themeColor3BG: "#0094FF",
|
||||||
disableAlarms: false,
|
disableAlarms: false,
|
||||||
disableData: false,
|
disableData: false,
|
||||||
|
randomColors: false,
|
||||||
};
|
};
|
||||||
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
||||||
for (const key in saved_settings) {
|
for (const key in saved_settings) {
|
||||||
settings[key] = saved_settings[key];
|
settings[key] = saved_settings[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Colors to use
|
//Colors to use
|
||||||
*/
|
var color_options = [
|
||||||
let color1 = settings.themeColor3BG;
|
'Green', 'Orange', 'Cyan', 'Purple', 'Red', 'Blue', 'Yellow', 'White',
|
||||||
let color2 = settings.themeColor1BG;
|
'Purple', 'Pink', 'Light Green', 'Brown', 'Turquoise', 'Magenta', 'Lime',
|
||||||
let color3 = settings.themeColor2BG;
|
'Gold', 'Sky Blue', 'Rose', 'Lavender', 'Amber', 'Indigo', 'Teal',
|
||||||
|
'Crimson', 'Maroon', 'Firebrick', 'Dark Red', 'Aqua', 'Emerald', 'Royal Blue',
|
||||||
|
'Sunset Orange', 'Turquoise Blue', 'Hot Pink', 'Goldenrod', 'Deep Sky Blue'
|
||||||
|
];
|
||||||
|
|
||||||
|
var bg_code = [
|
||||||
|
'#00ff00', '#FF9900', '#0094FF', '#FF00DC', '#ff0000', '#0000ff', '#ffef00', '#FFFFFF',
|
||||||
|
'#FF00FF', '#6C00FF', '#99FF00', '#8B4513', '#40E0D0', '#FF00FF', '#00FF00', '#FFD700',
|
||||||
|
'#87CEEB', '#FF007F', '#E6E6FA', '#FFBF00', '#4B0082', '#008080', '#DC143C', '#800000',
|
||||||
|
'#B22222', '#8B0000', '#00FFFF', '#008000', '#4169E1', '#FF4500', '#40E0D0', '#FF69B4',
|
||||||
|
'#DAA520', '#00BFFF'
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let color1;
|
||||||
|
let color2;
|
||||||
|
let color3;
|
||||||
let cWhite = "#FFFFFF";
|
let cWhite = "#FFFFFF";
|
||||||
let cBlack = "#000000";
|
let cBlack = "#000000";
|
||||||
let cGrey = "#424242";
|
let cGrey = "#424242";
|
||||||
|
|
@ -58,10 +76,77 @@ let convert24to16 = function(input)
|
||||||
return "0x"+RGB565.toString(16);
|
return "0x"+RGB565.toString(16);
|
||||||
};
|
};
|
||||||
|
|
||||||
let color1C = convert24to16(color1);//Converting colors to the correct format.
|
//Converting colors to the correct format.
|
||||||
let color2C = convert24to16(color2);
|
|
||||||
let color3C = convert24to16(color3);
|
|
||||||
|
|
||||||
|
let randomColors = function () {
|
||||||
|
|
||||||
|
if (settings.randomColors) {
|
||||||
|
do {
|
||||||
|
color1 = getRandomColor();
|
||||||
|
color2 = getRandomColor();
|
||||||
|
color3 = getRandomColor();
|
||||||
|
} while (!areColorsDistinct(color1, color2, color3));
|
||||||
|
|
||||||
|
} else {
|
||||||
|
color1 = settings.themeColor3BG;
|
||||||
|
color2 = settings.themeColor1BG;
|
||||||
|
color3 = settings.themeColor2BG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converting colors to the correct format.
|
||||||
|
color1C = convert24to16(color1);
|
||||||
|
color2C = convert24to16(color2);
|
||||||
|
color3C = convert24to16(color3);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to get a random color from the bg_code array.
|
||||||
|
let getRandomColor = function () {
|
||||||
|
return bg_code[Math.floor(Math.random() * bg_code.length)];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to check if three colors are distinct enough.
|
||||||
|
let areColorsDistinct = function (color1, color2, color3) {
|
||||||
|
return (
|
||||||
|
color1 !== color2 &&
|
||||||
|
color2 !== color3 &&
|
||||||
|
color1 !== color3 &&
|
||||||
|
hasSufficientContrast(color1, color2) &&
|
||||||
|
hasSufficientContrast(color2, color3) &&
|
||||||
|
hasSufficientContrast(color1, color3)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to calculate contrast between two colors.
|
||||||
|
let hasSufficientContrast = function (color1, color2) {
|
||||||
|
const contrastThreshold = 0.10; // Adjust this threshold based on your preference.
|
||||||
|
|
||||||
|
// Calculate the luminance values (for simplicity, assuming sRGB color space).
|
||||||
|
const luminance1 = getLuminance(color1);
|
||||||
|
const luminance2 = getLuminance(color2);
|
||||||
|
|
||||||
|
// Calculate the contrast ratio.
|
||||||
|
const contrastRatio = (Math.max(luminance1, luminance2) + 0.05) / (Math.min(luminance1, luminance2) + 0.05);
|
||||||
|
|
||||||
|
// Check if the contrast ratio meets the threshold.
|
||||||
|
return contrastRatio >= contrastThreshold;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to calculate luminance from a hex color.
|
||||||
|
let getLuminance = function (hexColor) {
|
||||||
|
const rgb = hexToRgb(hexColor);
|
||||||
|
return 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to convert hex color to RGB.
|
||||||
|
let hexToRgb = function (hex) {
|
||||||
|
const bigint = parseInt(hex.slice(1), 16);
|
||||||
|
const r = (bigint >> 16) & 255;
|
||||||
|
const g = (bigint >> 8) & 255;
|
||||||
|
const b = bigint & 255;
|
||||||
|
return { r, g, b };
|
||||||
|
};
|
||||||
|
|
||||||
|
randomColors();//Apply random colors if applied
|
||||||
/*
|
/*
|
||||||
* Requirements and globals
|
* Requirements and globals
|
||||||
*/
|
*/
|
||||||
|
|
@ -224,7 +309,7 @@ let drawData = function(key, y, c){
|
||||||
|
|
||||||
|
|
||||||
let _drawData = function(key, y, c){
|
let _drawData = function(key, y, c){
|
||||||
key = key.toUpperCase()
|
key = key.toUpperCase();
|
||||||
let text = key;
|
let text = key;
|
||||||
let value = "ERR";
|
let value = "ERR";
|
||||||
let should_print= true;
|
let should_print= true;
|
||||||
|
|
@ -271,7 +356,7 @@ let _drawData = function(key, y, c){
|
||||||
value = Math.round(data.altitude);
|
value = Math.round(data.altitude);
|
||||||
printRow(text, value, y, c);
|
printRow(text, value, y, c);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
} else if(key == "CORET"){
|
} else if(key == "CORET"){
|
||||||
value = locale.temp(parseInt(E.getTemperature()));
|
value = locale.temp(parseInt(E.getTemperature()));
|
||||||
|
|
@ -374,7 +459,7 @@ let drawPosition0 = function(){
|
||||||
drawHorizontalBgLine(color2, batStart, batX2, 171, 5);
|
drawHorizontalBgLine(color2, batStart, batX2, 171, 5);
|
||||||
drawHorizontalBgLine(cGrey, batX2, 172, 171, 5);
|
drawHorizontalBgLine(cGrey, batX2, 172, 171, 5);
|
||||||
for(let i=0; i+batStart<=172; i+=parseInt(batWidth/4)){
|
for(let i=0; i+batStart<=172; i+=parseInt(batWidth/4)){
|
||||||
drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8)
|
drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw Infos
|
// Draw Infos
|
||||||
|
|
@ -603,7 +688,7 @@ let getWeather = function(){
|
||||||
let speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934;
|
let speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934;
|
||||||
weather.wind = Math.round(wind[1] * speedFactor);
|
weather.wind = Math.round(wind[1] * speedFactor);
|
||||||
|
|
||||||
return weather
|
return weather;
|
||||||
|
|
||||||
} catch(ex) {
|
} catch(ex) {
|
||||||
// Return default
|
// Return default
|
||||||
|
|
@ -649,7 +734,7 @@ let getAlarmMinutes = function(){
|
||||||
let increaseAlarm = function(){
|
let increaseAlarm = function(){
|
||||||
try{
|
try{
|
||||||
let minutes = isAlarmEnabled() ? getAlarmMinutes() : 0;
|
let minutes = isAlarmEnabled() ? getAlarmMinutes() : 0;
|
||||||
let alarm = require('sched')
|
let alarm = require('sched');
|
||||||
alarm.setAlarm(TIMER_IDX, {
|
alarm.setAlarm(TIMER_IDX, {
|
||||||
timer : (minutes+5)*60*1000,
|
timer : (minutes+5)*60*1000,
|
||||||
});
|
});
|
||||||
|
|
@ -662,7 +747,7 @@ let decreaseAlarm = function(){
|
||||||
let minutes = getAlarmMinutes();
|
let minutes = getAlarmMinutes();
|
||||||
minutes -= 5;
|
minutes -= 5;
|
||||||
|
|
||||||
let alarm = require('sched')
|
let alarm = require('sched');
|
||||||
alarm.setAlarm(TIMER_IDX, undefined);
|
alarm.setAlarm(TIMER_IDX, undefined);
|
||||||
|
|
||||||
if(minutes > 0){
|
if(minutes > 0){
|
||||||
|
|
@ -773,7 +858,6 @@ Bangle.setUI({mode:"clock",remove:function() {
|
||||||
widget_utils.cleanup();
|
widget_utils.cleanup();
|
||||||
}});
|
}});
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
|
|
||||||
// Clear the screen once, at startup and draw clock
|
// Clear the screen once, at startup and draw clock
|
||||||
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
|
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
|
||||||
draw();
|
draw();
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
themeColor3BG: "#0094FF",
|
themeColor3BG: "#0094FF",
|
||||||
disableAlarms: false,
|
disableAlarms: false,
|
||||||
disableData: false,
|
disableData: false,
|
||||||
|
randomColors: false,
|
||||||
};
|
};
|
||||||
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
||||||
for (const key in saved_settings) {
|
for (const key in saved_settings) {
|
||||||
|
|
@ -28,9 +29,21 @@
|
||||||
|
|
||||||
var dataOptions = ["Steps", "Battery", "BattVolt", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"];
|
var dataOptions = ["Steps", "Battery", "BattVolt", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"];
|
||||||
var speedOptions = ["kph", "mph"];
|
var speedOptions = ["kph", "mph"];
|
||||||
var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White','Purple','Pink','Light Green','Dark Green'];
|
var color_options = [
|
||||||
var bg_code = ['#00ff00','#FF9900','#0094FF','#FF00DC','#ff0000','#0000ff','#ffef00','#FFFFFF','#FF00FF','#6C00FF','#99FF00','#556B2F'];
|
'Green', 'Orange', 'Cyan', 'Purple', 'Red', 'Blue', 'Yellow', 'White',
|
||||||
|
'Purple', 'Pink', 'Light Green', 'Brown', 'Turquoise', 'Magenta', 'Lime',
|
||||||
|
'Gold', 'Sky Blue', 'Rose', 'Lavender', 'Amber', 'Indigo', 'Teal',
|
||||||
|
'Crimson', 'Maroon', 'Firebrick', 'Dark Red', 'Aqua', 'Emerald', 'Royal Blue',
|
||||||
|
'Sunset Orange', 'Turquoise Blue', 'Hot Pink', 'Goldenrod', 'Deep Sky Blue'
|
||||||
|
];
|
||||||
|
|
||||||
|
var bg_code = [
|
||||||
|
'#00ff00', '#FF9900', '#0094FF', '#FF00DC', '#ff0000', '#0000ff', '#ffef00', '#FFFFFF',
|
||||||
|
'#FF00FF', '#6C00FF', '#99FF00', '#8B4513', '#40E0D0', '#FF00FF', '#00FF00', '#FFD700',
|
||||||
|
'#87CEEB', '#FF007F', '#E6E6FA', '#FFBF00', '#4B0082', '#008080', '#DC143C', '#800000',
|
||||||
|
'#B22222', '#8B0000', '#00FFFF', '#008000', '#4169E1', '#FF4500', '#40E0D0', '#FF69B4',
|
||||||
|
'#DAA520', '#00BFFF'
|
||||||
|
];
|
||||||
E.showMenu({
|
E.showMenu({
|
||||||
'': { 'title': 'LCARS Clock' },
|
'': { 'title': 'LCARS Clock' },
|
||||||
'< Back': back,
|
'< Back': back,
|
||||||
|
|
@ -80,7 +93,7 @@
|
||||||
},
|
},
|
||||||
'Theme Color 1': {
|
'Theme Color 1': {
|
||||||
value: 0 | bg_code.indexOf(settings.themeColor1BG),
|
value: 0 | bg_code.indexOf(settings.themeColor1BG),
|
||||||
min: 0, max: 11,
|
min: 0, max: 34,
|
||||||
format: v => color_options[v],
|
format: v => color_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.themeColor1BG = bg_code[v];
|
settings.themeColor1BG = bg_code[v];
|
||||||
|
|
@ -89,7 +102,7 @@
|
||||||
},
|
},
|
||||||
'Theme Color 2': {
|
'Theme Color 2': {
|
||||||
value: 0 | bg_code.indexOf(settings.themeColor2BG),
|
value: 0 | bg_code.indexOf(settings.themeColor2BG),
|
||||||
min: 0, max: 11,
|
min: 0, max: 34,
|
||||||
format: v => color_options[v],
|
format: v => color_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.themeColor2BG = bg_code[v];
|
settings.themeColor2BG = bg_code[v];
|
||||||
|
|
@ -98,7 +111,7 @@
|
||||||
},
|
},
|
||||||
'Theme Color 3': {
|
'Theme Color 3': {
|
||||||
value: 0 | bg_code.indexOf(settings.themeColor3BG),
|
value: 0 | bg_code.indexOf(settings.themeColor3BG),
|
||||||
min: 0, max: 11,
|
min: 0, max: 34,
|
||||||
format: v => color_options[v],
|
format: v => color_options[v],
|
||||||
onchange: v => {
|
onchange: v => {
|
||||||
settings.themeColor3BG = bg_code[v];
|
settings.themeColor3BG = bg_code[v];
|
||||||
|
|
@ -121,5 +134,13 @@
|
||||||
save();
|
save();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'Random colors on open': {
|
||||||
|
value: settings.randomColors,
|
||||||
|
format: () => (settings.randomColors ? 'Yes' : 'No'),
|
||||||
|
onchange: () => {
|
||||||
|
settings.randomColors = !settings.randomColors;
|
||||||
|
save();
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
"name": "LCARS Clock",
|
"name": "LCARS Clock",
|
||||||
"shortName":"LCARS",
|
"shortName":"LCARS",
|
||||||
"icon": "lcars.png",
|
"icon": "lcars.png",
|
||||||
"version":"0.29",
|
"version":"0.30",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"supports": ["BANGLEJS2"],
|
"supports": ["BANGLEJS2"],
|
||||||
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
"description": "Library Computer Access Retrieval System (LCARS) clock.",
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ var locales = {
|
||||||
distance: { "0": "yd", "1": "mi" },
|
distance: { "0": "yd", "1": "mi" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -90,7 +90,7 @@ var locales = {
|
||||||
distance: { 0: "ft", 1: "mi" },
|
distance: { 0: "ft", 1: "mi" },
|
||||||
temperature: "°F",
|
temperature: "°F",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d, %Y", 1: "%m/%d/%y" },
|
datePattern: { 0: "%b %d, %Y", 1: "%m/%d/%y" },
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -109,7 +109,7 @@ var locales = {
|
||||||
distance: { 0: "ft", 1: "mi" },
|
distance: { 0: "ft", 1: "mi" },
|
||||||
temperature: "°F",
|
temperature: "°F",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d, %Y", 1: "%Y-%m-%d" },
|
datePattern: { 0: "%b %d, %Y", 1: "%Y-%m-%d" },
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -128,7 +128,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%Y" }, // 28 Feb 2020" // "28/03/2020"(short)
|
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%Y" }, // 28 Feb 2020" // "28/03/2020"(short)
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -147,7 +147,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%Y" }, // 28 Feb 2020" // "28/03/2020"(short)
|
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%Y" }, // 28 Feb 2020" // "28/03/2020"(short)
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -165,7 +165,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "nm" },
|
distance: { "0": "m", "1": "nm" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -202,7 +202,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" },
|
datePattern: { 0: "%Y/%m/%d", 1: "%y/%m/%d" },
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -239,7 +239,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
datePattern: { 0: "%b %d %Y", 1: "%d/%m/%Y" }, // Feb 28 2020" // "01/03/2020"(short)
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -256,7 +256,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%Y-%m-%d" }, // Sunday, March 1, 2020 // 2012-12-20
|
datePattern: { 0: "%A, %B %d, %Y", "1": "%Y-%m-%d" }, // Sunday, March 1, 2020 // 2012-12-20
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -274,7 +274,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020
|
datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020
|
||||||
abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc",
|
abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc",
|
||||||
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
||||||
|
|
@ -292,7 +292,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "fm", 1: "em" },
|
ampm: { 0: "fm", 1: "em" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%b %d %Y", "1": "%Y-%m-%d" }, // feb 1 2020 // 2020-03-01
|
datePattern: { 0: "%b %d %Y", "1": "%Y-%m-%d" }, // feb 1 2020 // 2020-03-01
|
||||||
abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec",
|
abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec",
|
||||||
month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december",
|
month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december",
|
||||||
|
|
@ -310,7 +310,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01
|
datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -328,7 +328,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%y" }, // Sunday, 1 March 2020 // 1/3/20
|
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%y" }, // Sunday, 1 March 2020 // 1/3/20
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -346,7 +346,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%y" }, // Sunday, 1 March 2020 // 1/3/20
|
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%y" }, // Sunday, 1 March 2020 // 1/3/20
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -364,7 +364,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20
|
datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%y" }, // Sonntag, 1. März 2020 // 01.03.20
|
||||||
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
|
abmonth: "Jän,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez",
|
||||||
month: "Jänner,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
month: "Jänner,Februar,März,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember",
|
||||||
|
|
@ -383,7 +383,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020
|
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020
|
||||||
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec",
|
||||||
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
month: "January,February,March,April,May,June,July,August,September,October,November,December",
|
||||||
|
|
@ -401,7 +401,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %d de %B de %Y", "1": "%d/%m/%y" }, // domingo, 1 de marzo de 2020 // 01/03/20
|
datePattern: { 0: "%A, %d de %B de %Y", "1": "%d/%m/%y" }, // domingo, 1 de marzo de 2020 // 01/03/20
|
||||||
abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic",
|
abmonth: "ene,feb,mar,abr,may,jun,jul,ago,sept,oct,nov,dic",
|
||||||
month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre",
|
month: "enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre",
|
||||||
|
|
@ -420,7 +420,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
|
datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20
|
||||||
abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
|
abmonth: "anv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.",
|
||||||
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre",
|
||||||
|
|
@ -438,7 +438,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "ap", 1: "ip" },
|
ampm: { 0: "ap", 1: "ip" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, // 17.00.00 // 17.00
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, // 17.00.00 // 17.00
|
||||||
datePattern: { 0: "%A %d. %B %Y", "1": "%-d/%-m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020
|
datePattern: { 0: "%A %d. %B %Y", "1": "%-d/%-m/%Y" }, // sunnuntai 1. maaliskuuta 2020 // 1.3.2020
|
||||||
abmonth: "tammik,helmik,maalisk,huhtik,toukok,kesäk,heinäk,elok,syysk,lokak,marrask,jouluk",
|
abmonth: "tammik,helmik,maalisk,huhtik,toukok,kesäk,heinäk,elok,syysk,lokak,marrask,jouluk",
|
||||||
month: "tammikuuta,helmikuuta,maaliskuuta,huhtikuuta,toukokuuta,kesäkuuta,heinäkuuta,elokuuta,syyskuuta,lokakuuta,marraskuuta,joulukuuta",
|
month: "tammikuuta,helmikuuta,maaliskuuta,huhtikuuta,toukokuuta,kesäkuuta,heinäkuuta,elokuuta,syyskuuta,lokakuuta,marraskuuta,joulukuuta",
|
||||||
|
|
@ -492,7 +492,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM.%SS ", 1: "%HH:%MM" }, // 17:00.00 // 17:00
|
timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00
|
||||||
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
|
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
|
||||||
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
|
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
|
||||||
month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre",
|
month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre",
|
||||||
|
|
@ -510,7 +510,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM.%SS ", 1: "%HH:%MM" }, // 17:00.00 // 17:00
|
timePattern: { 0: "%HH:%MM.%SS", 1: "%HH:%MM" }, // 17:00.00 // 17:00
|
||||||
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
|
datePattern: { 0: "%d %b %Y", "1": "%d/%m/%Y" }, // 1 marzo 2020 // 01/03/2020
|
||||||
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
|
abmonth: "gen,feb,mar,apr,mag,giu,lug,ago,set,ott,nov,dic",
|
||||||
month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre",
|
month: "gennaio,febbraio,marzo,aprile,maggio,giugno,luglio,agosto,settembre,ottobre,novembre,dicembre",
|
||||||
|
|
@ -528,7 +528,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH.%MM.%SS ", 1: "%HH.%MM" }, // 17.00.00 // 17.00
|
timePattern: { 0: "%HH.%MM.%SS", 1: "%HH.%MM" }, // 17.00.00 // 17.00
|
||||||
datePattern: { 0: "%A, %d. %B %Y", "1": "%Y-%m-%d" }, // Sunntag, 1. Märze 2020 // 2020-03-01
|
datePattern: { 0: "%A, %d. %B %Y", "1": "%Y-%m-%d" }, // Sunntag, 1. Märze 2020 // 2020-03-01
|
||||||
abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr",
|
abmonth: "Jen,Hor,Mär,Abr,Mei,Brá,Hei,Öig,Her,Wím,Win,Chr",
|
||||||
month: "Jenner,Hornig,Märze,Abrille,Meije,Bráčet,Heiwet,Öigšte,Herbštmánet,Wímánet,Wintermánet,Chrištmánet",
|
month: "Jenner,Hornig,Märze,Abrille,Meije,Bráčet,Heiwet,Öigšte,Herbštmánet,Wímánet,Wintermánet,Chrištmánet",
|
||||||
|
|
@ -546,7 +546,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "öö", 1: "ös" },
|
ampm: { 0: "öö", 1: "ös" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %w %Y %A", 1: "%d/%m/%Y" }, // 1 Mart 2020 Pazar // "01/03/2020"
|
datePattern: { 0: "%d %w %Y %A", 1: "%d/%m/%Y" }, // 1 Mart 2020 Pazar // "01/03/2020"
|
||||||
abmonth: "Oca,Sub,Mar,Nis,May,Haz,Tem,Agu,Eyl,Eki,Kas,Ara",
|
abmonth: "Oca,Sub,Mar,Nis,May,Haz,Tem,Agu,Eyl,Eki,Kas,Ara",
|
||||||
month: "Ocak,Subat,Mart,Nisan,Mayis,Haziran,Temmuz,Agustos,Eylul,Ekim,Kasim,Aralik",
|
month: "Ocak,Subat,Mart,Nisan,Mayis,Haziran,Temmuz,Agustos,Eylul,Ekim,Kasim,Aralik",
|
||||||
|
|
@ -564,7 +564,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "de", 1: "du" },
|
ampm: { 0: "de", 1: "du" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%Y %b %d, %A", 1: "%Y.%m.%d" }, // 2020 Feb 28, Péntek" // "2020.03.01."(short)
|
datePattern: { 0: "%Y %b %d, %A", 1: "%Y.%m.%d" }, // 2020 Feb 28, Péntek" // "2020.03.01."(short)
|
||||||
abmonth: "Jan,Feb,Már,Ápr,Máj,Jún,Júl,Aug,Szep,Okt,Nov,Dec",
|
abmonth: "Jan,Feb,Már,Ápr,Máj,Jún,Júl,Aug,Szep,Okt,Nov,Dec",
|
||||||
month: "Január,Február,Március,Április,Május,Június,Július,Augusztus,Szeptember,Október,November,December",
|
month: "Január,Február,Március,Április,Május,Június,Július,Augusztus,Szeptember,Október,November,December",
|
||||||
|
|
@ -582,7 +582,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "", 1: "" },
|
ampm: { 0: "", 1: "" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020
|
datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020
|
||||||
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
|
abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.",
|
||||||
month: "genièr,febrièr,març,abril,mai,junh,julhet,agost,setembre,octòbre,novembre,decembre",
|
month: "genièr,febrièr,març,abril,mai,junh,julhet,agost,setembre,octòbre,novembre,decembre",
|
||||||
|
|
@ -600,7 +600,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%y" },
|
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%y" },
|
||||||
abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez",
|
abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez",
|
||||||
month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro",
|
month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro",
|
||||||
|
|
@ -618,7 +618,7 @@ var locales = {
|
||||||
distance: { "0": "m", "1": "km" },
|
distance: { "0": "m", "1": "km" },
|
||||||
temperature: '°C',
|
temperature: '°C',
|
||||||
ampm: { 0: "dop", 1: "odp" },
|
ampm: { 0: "dop", 1: "odp" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d. %b %Y", 1: "%d.%m.%Y" }, // "30. led 2020" // "30.01.2020"(short)
|
datePattern: { 0: "%d. %b %Y", 1: "%d.%m.%Y" }, // "30. led 2020" // "30.01.2020"(short)
|
||||||
abmonth: "led,úno,bře,dub,kvě,čvn,čvc,srp,zář,říj,lis,pro",
|
abmonth: "led,úno,bře,dub,kvě,čvn,čvc,srp,zář,říj,lis,pro",
|
||||||
month: "leden,únor,březen,duben,květen,červen,červenec,srpen,září,říjen,listopad,prosinec",
|
month: "leden,únor,březen,duben,květen,červen,červenec,srpen,září,říjen,listopad,prosinec",
|
||||||
|
|
@ -672,7 +672,7 @@ var locales = {
|
||||||
distance: { 0: "m", 1: "km" },
|
distance: { 0: "m", 1: "km" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: { 0: "am", 1: "pm" },
|
ampm: { 0: "am", 1: "pm" },
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%y" },
|
datePattern: { 0: "%d %b %Y", 1: "%d/%m/%y" },
|
||||||
abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez",
|
abmonth: "Jan,Fev,Mar,Abr,Mai,Jun,Jul,Ago,Set,Out,Nov,Dez",
|
||||||
month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro",
|
month: "Janeiro,Fevereiro,Março,Abril,Maio,Junho,Julho,Agosto,Setembro,Outubro,Novembro,Dezembro",
|
||||||
|
|
@ -764,7 +764,7 @@ var locales = {
|
||||||
distance: { 0: "מ׳", 1: "ק״מ" },
|
distance: { 0: "מ׳", 1: "ק״מ" },
|
||||||
temperature: "°C",
|
temperature: "°C",
|
||||||
ampm: {0:"am",1:"pm"},
|
ampm: {0:"am",1:"pm"},
|
||||||
timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" },
|
timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" },
|
||||||
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020
|
datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020
|
||||||
abmonth: "ינו,פבר,מרץ,אפר,מאי,יונ,יול,אוג,ספט,אוק,נוב,דצמ",
|
abmonth: "ינו,פבר,מרץ,אפר,מאי,יונ,יול,אוג,ספט,אוק,נוב,דצמ",
|
||||||
month: "ינואר,פברואר,מרץ,אפריל,מאי,יוני,יולי,אוגוסט,ספטמבר,אוקטובר,נובמבר,דצמבר",
|
month: "ינואר,פברואר,מרץ,אפריל,מאי,יוני,יולי,אוגוסט,ספטמבר,אוקטובר,נובמבר,דצמבר",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
# My Profile
|
||||||
|
|
||||||
|
Configure your personal profile. All settings are optional and are only stored on the watch.
|
||||||
|
|
||||||
|
## Available settings
|
||||||
|
|
||||||
|
| Setting | Description | Displayed in | Stored in | Default value | How to measure |
|
||||||
|
| ------------- | ------------------------------- | ------------------- | ------------ | ------------- | ----------------------------------------------------------------- |
|
||||||
|
| Birthday | Used to calculate age | year, month, day | 'YYYY-MM-DD' | 01.01.1970 | - |
|
||||||
|
| HR max | maximum heart rate | BPM | BPM | 60 | Use maximum value when exercising.<br/> If unsure set to 220-age. |
|
||||||
|
| HR min | minimum heart rate | BPM | BPM | 200 | Measure your heart rate after waking up |
|
||||||
|
| Height | Body height | local length unit | meter | 0 (=not set) | - |
|
||||||
|
| Stride length | distance traveled with one step | local length unit | meter | 0 (=not set) | Walk 10 steps and divide the travelled distance by 10 |
|
||||||
|
|
||||||
|
## Developer notes
|
||||||
|
|
||||||
|
- Feel free to add additional settings.
|
||||||
|
- For values without reasonable defaults never assume that a value is set. Always check the value before using it.
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,18 @@
|
||||||
|
{ "id": "myprofile",
|
||||||
|
"name": "My Profile",
|
||||||
|
"shortName":"My Profile",
|
||||||
|
"icon": "app.png",
|
||||||
|
"type": "settings",
|
||||||
|
"version":"0.01",
|
||||||
|
"description": "Configure your personal profile. All settings are optional and only stored on the watch.",
|
||||||
|
"readme": "README.md",
|
||||||
|
"tags": "tool,utility",
|
||||||
|
"supports": ["BANGLEJS", "BANGLEJS2"],
|
||||||
|
"storage": [
|
||||||
|
{"name":"myprofile.settings.js","url":"settings.js"}
|
||||||
|
],
|
||||||
|
"data": [
|
||||||
|
{"name":"myprofile.json"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,138 @@
|
||||||
|
(function(back) {
|
||||||
|
const FILE = "myprofile.json";
|
||||||
|
|
||||||
|
const myprofile = Object.assign({
|
||||||
|
minHrm: 60,
|
||||||
|
maxHrm: 200,
|
||||||
|
strideLength: 0, // 0 = not set
|
||||||
|
birthday: '1970-01-01',
|
||||||
|
height: 0, // 0 = not set
|
||||||
|
}, require('Storage').readJSON(FILE, true) || {});
|
||||||
|
|
||||||
|
function writeProfile() {
|
||||||
|
require('Storage').writeJSON(FILE, myprofile);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ageMenu = () => {
|
||||||
|
const date = new Date(myprofile.birthday);
|
||||||
|
|
||||||
|
E.showMenu({
|
||||||
|
"" : { "title" : /*LANG*/"Birthday" },
|
||||||
|
|
||||||
|
"< Back" : () => {
|
||||||
|
if (date != new Date(myprofile.birthday)) {
|
||||||
|
// Birthday changed
|
||||||
|
if (date > new Date()) {
|
||||||
|
E.showPrompt(/*LANG*/"Birthday must not be in future!", {
|
||||||
|
buttons : {"Ok":true},
|
||||||
|
}).then(() => ageMenu());
|
||||||
|
} else {
|
||||||
|
const age = (new Date()).getFullYear() - date.getFullYear();
|
||||||
|
const newMaxHRM = 220-age;
|
||||||
|
E.showPrompt(/*LANG*/`Set HR max to ${newMaxHRM} calculated from age?`).then(function(v) {
|
||||||
|
myprofile.birthday = date.getFullYear() + "-" + (date.getMonth() + 1).toString().padStart(2, '0') + "-" + date.getDate().toString().padStart(2, '0');
|
||||||
|
if (v) {
|
||||||
|
myprofile.maxHrm = newMaxHRM;
|
||||||
|
}
|
||||||
|
writeProfile();
|
||||||
|
mainMenu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mainMenu();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/"Day": {
|
||||||
|
value: date ? date.getDate() : null,
|
||||||
|
min: 1,
|
||||||
|
max: 31,
|
||||||
|
wrap: true,
|
||||||
|
onchange: v => {
|
||||||
|
date.setDate(v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*LANG*/"Month": {
|
||||||
|
value: date ? date.getMonth() + 1 : null,
|
||||||
|
format: v => require("date_utils").month(v),
|
||||||
|
onchange: v => {
|
||||||
|
date.setMonth((v+11)%12);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/*LANG*/"Year": {
|
||||||
|
value: date ? date.getFullYear() : null,
|
||||||
|
min: 1900,
|
||||||
|
max: (new Date()).getFullYear(),
|
||||||
|
onchange: v => {
|
||||||
|
date.setFullYear(v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const mainMenu = () => {
|
||||||
|
E.showMenu({
|
||||||
|
"" : { "title" : /*LANG*/"My Profile" },
|
||||||
|
|
||||||
|
"< Back" : () => back(),
|
||||||
|
|
||||||
|
/*LANG*/"Birthday" : () => ageMenu(),
|
||||||
|
|
||||||
|
/*LANG*/'Height': {
|
||||||
|
value: myprofile.height,
|
||||||
|
min: 0, max: 300,
|
||||||
|
step:0.01,
|
||||||
|
format: v => v ? require("locale").distance(v, 2) : '-',
|
||||||
|
onchange: v => {
|
||||||
|
if (v !== myprofile.height) {
|
||||||
|
// height changed
|
||||||
|
myprofile.height = v;
|
||||||
|
setTimeout(() => {
|
||||||
|
const newStrideLength = myprofile.height * 0.414;
|
||||||
|
E.showPrompt(/*LANG*/`Set Stride length to ${require("locale").distance(newStrideLength, 2)} calculated from height?`).then(function(v) {
|
||||||
|
if (v) {
|
||||||
|
myprofile.strideLength = newStrideLength;
|
||||||
|
}
|
||||||
|
writeProfile();
|
||||||
|
mainMenu();
|
||||||
|
});
|
||||||
|
}, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/'HR max': {
|
||||||
|
format: v => /*LANG*/`${v} BPM`,
|
||||||
|
value: myprofile.maxHrm,
|
||||||
|
min: 30, max: 220,
|
||||||
|
onchange: v => {
|
||||||
|
myprofile.maxHrm = v;
|
||||||
|
writeProfile();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/'HR min': {
|
||||||
|
format: v => /*LANG*/`${v} BPM`,
|
||||||
|
value: myprofile.minHrm,
|
||||||
|
min: 30, max: 220,
|
||||||
|
onchange: v => {
|
||||||
|
myprofile.minHrm = v;
|
||||||
|
writeProfile();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/*LANG*/"Stride length": {
|
||||||
|
value: myprofile.strideLength,
|
||||||
|
min:0.00,
|
||||||
|
step:0.01,
|
||||||
|
format: v => v ? require("locale").distance(v, 2) : '-',
|
||||||
|
onchange: v => {
|
||||||
|
myprofile.strideLength=v;
|
||||||
|
writeProfile();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mainMenu();
|
||||||
|
})
|
||||||
|
|
@ -31,3 +31,4 @@
|
||||||
0.24: Allow zooming by clicking the screen
|
0.24: Allow zooming by clicking the screen
|
||||||
0.25: Enable scaled image filtering on 2v19+ firmware
|
0.25: Enable scaled image filtering on 2v19+ firmware
|
||||||
0.26: Ensure that when redrawing, we always cancel any in-progress track draw
|
0.26: Ensure that when redrawing, we always cancel any in-progress track draw
|
||||||
|
0.27: Display message if no map is installed
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,12 @@ function showMap() {
|
||||||
}, btn: () => showMenu() });
|
}, btn: () => showMenu() });
|
||||||
}
|
}
|
||||||
|
|
||||||
showMap();
|
|
||||||
|
if (m.maps.length === 0) {
|
||||||
|
E.showPrompt(/*LANG*/'Please upload a map first.', {buttons : {/*LANG*/"Ok":true}}).then(v => load());
|
||||||
|
} else {
|
||||||
|
showMap();
|
||||||
|
}
|
||||||
|
|
||||||
// Write settings on exit via button
|
// Write settings on exit via button
|
||||||
setWatch(() => writeSettings(), BTN, { repeat: true, edge: "rising" });
|
setWatch(() => writeSettings(), BTN, { repeat: true, edge: "rising" });
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "openstmap",
|
"id": "openstmap",
|
||||||
"name": "OpenStreetMap",
|
"name": "OpenStreetMap",
|
||||||
"shortName": "OpenStMap",
|
"shortName": "OpenStMap",
|
||||||
"version": "0.26",
|
"version": "0.27",
|
||||||
"description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps",
|
"description": "Loads map tiles from OpenStreetMap onto your Bangle.js and displays a map of where you are. Once installed this also adds map functionality to `GPS Recorder` and `Recorder` apps",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,11 @@ m.maps = require("Storage").list(/openstmap\.\d+\.json/).map(f=>{
|
||||||
m.maps.sort((a,b) => b.scale-a.scale); // sort by scale so highest resolution is drawn last
|
m.maps.sort((a,b) => b.scale-a.scale); // sort by scale so highest resolution is drawn last
|
||||||
// we base our start position on the middle of the first map
|
// we base our start position on the middle of the first map
|
||||||
m.map = m.maps[0];
|
m.map = m.maps[0];
|
||||||
m.scale = m.map.scale; // current scale (based on first map)
|
if (m.map) {
|
||||||
m.lat = m.map.lat; // position of middle of screen
|
m.scale = m.map.scale; // current scale (based on first map)
|
||||||
m.lon = m.map.lon; // position of middle of screen
|
m.lat = m.map.lat; // position of middle of screen
|
||||||
|
m.lon = m.map.lon; // position of middle of screen
|
||||||
|
}
|
||||||
|
|
||||||
// return number of tiles drawn
|
// return number of tiles drawn
|
||||||
exports.draw = function() {
|
exports.draw = function() {
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,9 @@
|
||||||
0.06: Initial internal git(hub) release. Added icon and such.
|
0.06: Initial internal git(hub) release. Added icon and such.
|
||||||
0.07: Begin work on presentation parts.
|
0.07: Begin work on presentation parts.
|
||||||
0.08: Presentation parts!
|
0.08: Presentation parts!
|
||||||
|
0.09: Code cleanup and windows 11 support.
|
||||||
|
0.10: Bugfixes.
|
||||||
|
0.11: Fix mouse move getting stuck.
|
||||||
|
0.12: Added support for mouse dragging action (click then drag).
|
||||||
|
0.13: Removed mouse dragging (too buggy/unuseful).
|
||||||
|
0.14: Bugfix and add pointer mode. Also added default screen when no parts are there.
|
||||||
|
|
@ -1,2 +1,80 @@
|
||||||
# Presentor
|
# Presentor
|
||||||
Use your Bangle to present!
|
Use your Bangle to present!
|
||||||
|
This app basically turns your BangleJS watch into a presentor tool.
|
||||||
|
Very useful for presentations or when you are teaching a lesson.
|
||||||
|
|
||||||
|
### Features:
|
||||||
|
+ Control your (powerpoint) slides by swiping left and right.
|
||||||
|
+ See pre-programmed presentation notes by swiping up and down.
|
||||||
|
+ See if you are on time in your presentation.
|
||||||
|
+ Get notified if you go over-time for a certain subject.
|
||||||
|
+ Control cursor or spotlight in mouse mode (pressing the button).
|
||||||
|
|
||||||
|
### Usage:
|
||||||
|
Here is a step by step guide (thanks mu1)
|
||||||
|
1. If bluetooth connected to PC/laptop (check in bluetooth settings):
|
||||||
|
Select Bangle.js > Remove Device
|
||||||
|
|
||||||
|
2. On your smartphone, in "Gadgetbridge", close connection by long-pressing "Bangle.js"
|
||||||
|
|
||||||
|
3. Open banglejs.com/apps and select "Connect" (right upper corner)
|
||||||
|
|
||||||
|
4. Select Bangle.js in blue bar in pop-up window and select "Connect"
|
||||||
|
|
||||||
|
5. Search "Presentor" app and select diskette icon
|
||||||
|
|
||||||
|
6. Select "Clear" to start making new notes.
|
||||||
|
|
||||||
|
7. Fill the subjects, times in minutes (seconds optional) and Notes (optional)
|
||||||
|
The subject/times are on your watch displayed in a tall font, the notes in a very small font
|
||||||
|
Note: If you don't fill in any notes you can still save and the presentor will be for input only and not give any timing details.
|
||||||
|
|
||||||
|
8. Select "Save" and exit the pop-up window
|
||||||
|
|
||||||
|
9. Select "Disconnect" (right upper corner)
|
||||||
|
|
||||||
|
10. Open the Presentor app. This will start the correct HID service as well.
|
||||||
|
|
||||||
|
11. Open "Bluetooth & other devices" screen on PC/laptop and select "+" to add a device
|
||||||
|
|
||||||
|
12. Select "Bluetooth" and select Bangle.js
|
||||||
|
If "Try connecting your device again." is shown, switch PC/laptop bluetooth off and on again
|
||||||
|
|
||||||
|
13. Start your presentation.
|
||||||
|
- Swipe up to start timer for first subject
|
||||||
|
- Swipe down to pause
|
||||||
|
- Push button to switch between mouse mode and timer/presentation mode
|
||||||
|
|
||||||
|
14. Timer function
|
||||||
|
- Next subject: Swipe up
|
||||||
|
- Previous subject: Swipe down
|
||||||
|
- Pause timer: Swipe down to begin
|
||||||
|
|
||||||
|
15. Presentation function
|
||||||
|
- Next presentation slide: Swipe right or just touch
|
||||||
|
- Previous presentation slide: Swipe left
|
||||||
|
|
||||||
|
16. Mouse mode
|
||||||
|
- Swipe to move pointer over the presentation screen
|
||||||
|
- Tap to left click.
|
||||||
|
- Hold longer to right click.
|
||||||
|
|
||||||
|
17. Holding mode
|
||||||
|
In timer/presentation mode, hold one finger on your Bangle screen, point your arm foreward
|
||||||
|
- Mouse up/down on screen: Tilt your hand up/down
|
||||||
|
- Mouse left/right on screen: Rotate your hand counterclockwise/clockwise
|
||||||
|
|
||||||
|
18. Spotlight mode
|
||||||
|
- Dubble press button to go into presentor mode.
|
||||||
|
- Allows to move mouse but no clicking.
|
||||||
|
- Presses SHIFT+F10 on start (you can use app such as powertoys to set spotlight to this combo)
|
||||||
|
- Presses F10 at the end (will dis-engage spotlight for instance in powertoys)
|
||||||
|
|
||||||
|
19. End of presentation?
|
||||||
|
Switch bluetooth PC/laptop off or see step 1
|
||||||
|
|
||||||
|
20. Re-activate smartphone bluetooth (incl. Gadgetbridge)
|
||||||
|
|
||||||
|
### Creator
|
||||||
|
[7kasper](https://github.com/7kasper)
|
||||||
|
Issues or feature requests are welcome on my [Github](https://github.com/7kasper/BangleApps) or on the [Espruino Forums](https://forum.espruino.com/conversations/371443/)!
|
||||||
|
|
@ -1,80 +1,12 @@
|
||||||
// Presentor by 7kasper (Kasper Müller)
|
// Presentor by 7kasper (Kasper Müller)
|
||||||
// Version 3.0
|
// Version 0.14
|
||||||
|
|
||||||
const SpecialReport = new Uint8Array([
|
|
||||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
|
||||||
0x09, 0x02, // USAGE (Mouse)
|
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
|
||||||
0x85, 0x01, // REPORT_ID (1)
|
|
||||||
0x09, 0x01, // USAGE (Pointer)
|
|
||||||
0xa1, 0x00, // COLLECTION (Physical)
|
|
||||||
0x05, 0x09, // USAGE_PAGE (Button)
|
|
||||||
0x19, 0x01, // USAGE_MINIMUM (Button 1)
|
|
||||||
0x29, 0x05, // USAGE_MAXIMUM (Button 5)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
|
||||||
0x95, 0x05, // REPORT_COUNT (5)
|
|
||||||
0x75, 0x01, // REPORT_SIZE (1)
|
|
||||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
||||||
0x95, 0x01, // REPORT_COUNT (1)
|
|
||||||
0x75, 0x03, // REPORT_SIZE (3)
|
|
||||||
0x81, 0x03, // INPUT (Cnst,Var,Abs)
|
|
||||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
|
||||||
0x09, 0x30, // USAGE (X)
|
|
||||||
0x09, 0x31, // USAGE (Y)
|
|
||||||
0x09, 0x38, // USAGE (Wheel)
|
|
||||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
|
||||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x03, // REPORT_COUNT (3)
|
|
||||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
|
||||||
0x05, 0x0c, // USAGE_PAGE (Consumer Devices)
|
|
||||||
0x0a, 0x38, 0x02, // USAGE (AC Pan)
|
|
||||||
0x15, 0x81, // LOGICAL_MINIMUM (-127)
|
|
||||||
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x01, // REPORT_COUNT (1)
|
|
||||||
0x81, 0x06, // INPUT (Data,Var,Rel)
|
|
||||||
0xc0, // END_COLLECTION
|
|
||||||
0xc0, // END_COLLECTION
|
|
||||||
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
|
|
||||||
0x09, 0x06, // USAGE (Keyboard)
|
|
||||||
0xa1, 0x01, // COLLECTION (Application)
|
|
||||||
0x85, 0x02, // REPORT_ID (2)
|
|
||||||
0x05, 0x07, // USAGE_PAGE (Keyboard)
|
|
||||||
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
|
|
||||||
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x25, 0x01, // LOGICAL_MAXIMUM (1)
|
|
||||||
0x75, 0x01, // REPORT_SIZE (1)
|
|
||||||
0x95, 0x08, // REPORT_COUNT (8)
|
|
||||||
0x81, 0x02, // INPUT (Data,Var,Abs)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x95, 0x01, // REPORT_COUNT (1)
|
|
||||||
0x81, 0x01, // INPUT (Cnst,Ary,Abs)
|
|
||||||
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
|
|
||||||
0x29, 0x73, // USAGE_MAXIMUM (Keyboard F24)
|
|
||||||
0x15, 0x00, // LOGICAL_MINIMUM (0)
|
|
||||||
0x25, 0x73, // LOGICAL_MAXIMUM (115)
|
|
||||||
0x95, 0x05, // REPORT_COUNT (5)
|
|
||||||
0x75, 0x08, // REPORT_SIZE (8)
|
|
||||||
0x81, 0x00, // INPUT (Data,Ary,Abs)
|
|
||||||
0xc0 // END_COLLECTION
|
|
||||||
]);
|
|
||||||
|
|
||||||
const MouseButton = {
|
|
||||||
NONE : 0,
|
|
||||||
LEFT : 1,
|
|
||||||
RIGHT : 2,
|
|
||||||
MIDDLE : 4,
|
|
||||||
BACK : 8,
|
|
||||||
FORWARD: 16
|
|
||||||
};
|
|
||||||
|
|
||||||
const kb = require("ble_hid_keyboard");
|
|
||||||
|
|
||||||
|
// Imports
|
||||||
|
const bt = require("ble_hid_combo");
|
||||||
const Layout = require("Layout");
|
const Layout = require("Layout");
|
||||||
const Locale = require("locale");
|
const Locale = require("locale");
|
||||||
|
|
||||||
|
// App Layout
|
||||||
let mainLayout = new Layout({
|
let mainLayout = new Layout({
|
||||||
'type': 'v',
|
'type': 'v',
|
||||||
filly: 1,
|
filly: 1,
|
||||||
|
|
@ -153,18 +85,20 @@ let lasty = 0;
|
||||||
// Mouse states
|
// Mouse states
|
||||||
let holding = false;
|
let holding = false;
|
||||||
let trackPadMode = false;
|
let trackPadMode = false;
|
||||||
|
let focusMode = false;
|
||||||
|
|
||||||
// Timeout IDs.
|
// Timeout IDs.
|
||||||
let timeoutId = -1;
|
let timeoutId = -1;
|
||||||
let timeoutHolding = -1;
|
let timeoutHolding = -1;
|
||||||
let timeoutDraw = -1;
|
let timeoutDraw = -1;
|
||||||
|
let timeoutSendMouse = -1;
|
||||||
|
|
||||||
let homeRoll = 0;
|
let homeRoll = 0;
|
||||||
let homePitch = 0;
|
let homePitch = 0;
|
||||||
let mCal = 0;
|
let mCal = 0;
|
||||||
let mttl = 0;
|
let mttl = 0;
|
||||||
let cttl = 0;
|
let cttl = 0;
|
||||||
|
let bttl = 0;
|
||||||
|
|
||||||
// BT helper.
|
// BT helper.
|
||||||
let clearToSend = true;
|
let clearToSend = true;
|
||||||
|
|
@ -174,7 +108,7 @@ let ptimers = [];
|
||||||
|
|
||||||
function delay(t, v) {
|
function delay(t, v) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
setTimeout(resolve, t)
|
setTimeout(resolve, t);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -266,6 +200,11 @@ function drawMain() {
|
||||||
|
|
||||||
function doPPart(r) {
|
function doPPart(r) {
|
||||||
pparti += r;
|
pparti += r;
|
||||||
|
if (settings.pparts.length == 0) {
|
||||||
|
mainLayout.Subject.label = 'PRESENTOR';
|
||||||
|
mainLayout.Notes.label = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (pparti < 0) {
|
if (pparti < 0) {
|
||||||
pparti = -1;
|
pparti = -1;
|
||||||
mainLayout.Subject.label = 'PAUSED';
|
mainLayout.Subject.label = 'PAUSED';
|
||||||
|
|
@ -289,56 +228,34 @@ function doPPart(r) {
|
||||||
drawMainFrame();
|
drawMainFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
NRF.setServices(undefined, { hid : SpecialReport });
|
// Turn on Bluetooth as presentor.
|
||||||
// TODO: figure out how to detect HID.
|
NRF.setServices(undefined, { hid : bt.report });
|
||||||
NRF.on('HID', function() {
|
NRF.on('HID', function() {
|
||||||
HIDenabled = true;
|
if (!HIDenabled) {
|
||||||
|
Bangle.buzz(200);
|
||||||
|
HIDenabled = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
//
|
||||||
function moveMouse(x,y,b,wheel,hwheel,callback) {
|
NRF.setAdvertising([
|
||||||
if (!HIDenabled) return;
|
{}, // include original Advertising packet
|
||||||
if (!b) b = 0;
|
[ // second packet containing 'appearance'
|
||||||
if (!wheel) wheel = 0;
|
2, 1, 6, // standard Bluetooth flags
|
||||||
if (!hwheel) hwheel = 0;
|
3,3,0x12,0x18, // HID Service
|
||||||
NRF.sendHIDReport([1,b,x,y,wheel,hwheel,0,0], function() {
|
3,0x19,0xCA,0x03 // Appearance: Presentation Remote
|
||||||
if (callback) callback();
|
]
|
||||||
});
|
]);
|
||||||
}
|
|
||||||
|
|
||||||
// function getSign(x) {
|
// function getSign(x) {
|
||||||
// return ((x > 0) - (x < 0)) || +x;
|
// return ((x > 0) - (x < 0)) || +x;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
function scroll(wheel,hwheel,callback) {
|
|
||||||
moveMouse(0,0,0,wheel,hwheel,callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Single click a certain button (immidiatly release).
|
|
||||||
function clickMouse(b, callback) {
|
|
||||||
if (!HIDenabled) return;
|
|
||||||
NRF.sendHIDReport([1,b,0,0,0,0,0,0], function() {
|
|
||||||
NRF.sendHIDReport([1,0,0,0,0,0,0,0], function() {
|
|
||||||
if (callback) callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function pressKey(keyCode, modifiers, callback) {
|
|
||||||
if (!HIDenabled) return;
|
|
||||||
if (!modifiers) modifiers = 0;
|
|
||||||
NRF.sendHIDReport([2, modifiers,0,keyCode,0,0,0,0], function() {
|
|
||||||
NRF.sendHIDReport([2,0,0,0,0,0,0,0], function() {
|
|
||||||
if (callback) callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleAcc(acc) {
|
function handleAcc(acc) {
|
||||||
let rRoll = acc.y * -50;
|
let rRoll = acc.y * -50;
|
||||||
let rPitch = acc.x * -100;
|
let rPitch = acc.x * -100;
|
||||||
if (mCal > 10) {
|
if (mCal > 10) {
|
||||||
//console.log("x: " + (rRoll - homeRoll) + " y:" + (rPitch - homePitch));
|
//console.log("x: " + (rRoll - homeRoll) + " y:" + (rPitch - homePitch));
|
||||||
moveMouse(acc.y * -50 - homeRoll, acc.x * -100 - homePitch);
|
bt.moveMouse(acc.y * -50 - homeRoll, acc.x * -100 - homePitch);
|
||||||
} else {
|
} else {
|
||||||
//console.log("homeroll: " +homeRoll +"homepitch: " + homePitch);
|
//console.log("homeroll: " +homeRoll +"homepitch: " + homePitch);
|
||||||
homeRoll = rRoll * 0.7 + homeRoll * 0.3;
|
homeRoll = rRoll * 0.7 + homeRoll * 0.3;
|
||||||
|
|
@ -347,34 +264,37 @@ function handleAcc(acc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Bangle.on('lock', function(on) {
|
Bangle.on('lock', function(on) {
|
||||||
if (on && holding) {
|
if (on && (holding || trackPadMode)) {
|
||||||
Bangle.setLocked(false);
|
Bangle.setLocked(false);
|
||||||
Bangle.setLCDPower(1);
|
Bangle.setLCDPower(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function startHolding() {
|
function startHolding() {
|
||||||
pressKey(kb.KEY.F10);
|
bt.tapKey(bt.KEY.F10, bt.MODIFY.SHIFT);
|
||||||
holding = true;
|
holding = true;
|
||||||
|
focusMode = true;
|
||||||
Bangle.buzz();
|
Bangle.buzz();
|
||||||
E.showMessage('Holding');
|
E.showMessage('Holding');
|
||||||
Bangle.on('accel', handleAcc);
|
Bangle.on('accel', handleAcc);
|
||||||
Bangle.setLCDPower(1);
|
Bangle.setLCDPower(1);
|
||||||
}
|
}
|
||||||
function stopHolding() {
|
function stopHolding() {
|
||||||
clearTimeout(timeoutId);
|
|
||||||
if (holding) {
|
if (holding) {
|
||||||
pressKey(kb.KEY.F10);
|
bt.tapKey(bt.KEY.F10);
|
||||||
|
// bt.tapKey(bt.KEY.F10);
|
||||||
homePitch = 0;
|
homePitch = 0;
|
||||||
homeRoll = 0;
|
homeRoll = 0;
|
||||||
holding = false;
|
holding = false;
|
||||||
|
focusMode = false;
|
||||||
mCal = 0;
|
mCal = 0;
|
||||||
Bangle.removeListener('accel', handleAcc);
|
Bangle.removeListener('accel', handleAcc);
|
||||||
Bangle.buzz();
|
Bangle.buzz();
|
||||||
drawMain();
|
drawMain();
|
||||||
} else {
|
|
||||||
timeoutId = setTimeout(drawMain, 1000);
|
|
||||||
}
|
}
|
||||||
|
// else {
|
||||||
|
// timeoutId = setTimeout(drawMain, 1000);
|
||||||
|
// }
|
||||||
clearTimeout(timeoutHolding);
|
clearTimeout(timeoutHolding);
|
||||||
timeoutHolding = -1;
|
timeoutHolding = -1;
|
||||||
}
|
}
|
||||||
|
|
@ -395,24 +315,28 @@ Bangle.on('drag', function(e) {
|
||||||
//let qX = getSign(difX) * Math.pow(Math.abs(difX), 1.2);
|
//let qX = getSign(difX) * Math.pow(Math.abs(difX), 1.2);
|
||||||
//let qY = getSign(difY) * Math.pow(Math.abs(difY), 1.2);
|
//let qY = getSign(difY) * Math.pow(Math.abs(difY), 1.2);
|
||||||
let qX = difX + 0.02 * vX, qY = difY + 0.02 * vY;
|
let qX = difX + 0.02 * vX, qY = difY + 0.02 * vY;
|
||||||
moveMouse(qX, qY, 0, 0, 0, function() {
|
bt.moveMouse(qX, qY, 0, 0, 0, function() {
|
||||||
setTimeout(function() {clearToSend = true;}, 50);
|
timeoutSendMouse = setTimeout(function() {clearToSend = true; timeoutSendMouse = -1;}, 50);
|
||||||
});
|
});
|
||||||
lastx = e.x;
|
lastx = e.x;
|
||||||
lasty = e.y;
|
lasty = e.y;
|
||||||
mttl = getTime();
|
mttl = getTime();
|
||||||
console.log("Dx: " + (qX) + " Dy: " + (qY));
|
console.log("Dx: " + (qX) + " Dy: " + (qY));
|
||||||
|
} else if (timeoutSendMouse == -1) { // Can happen perhaps on single bluetooth failure.
|
||||||
|
timeoutSendMouse = setTimeout(function() {clearToSend = true; timeoutSendMouse = -1;}, 50);
|
||||||
}
|
}
|
||||||
if (!e.b) {
|
if (!e.b) {
|
||||||
// short press
|
if (!focusMode) {
|
||||||
if (getTime() - cttl < 0.2) {
|
// short press
|
||||||
clickMouse(MouseButton.LEFT);
|
if (getTime() - cttl < 0.2) {
|
||||||
console.log("click left");
|
bt.clickButton(bt.BUTTON.LEFT);
|
||||||
}
|
console.log("click left");
|
||||||
// longer press in center
|
}
|
||||||
else if (getTime() - cttl < 0.6 && e.x > g.getWidth()/4 && e.x < 3 * g.getWidth()/4 && e.y > g.getHeight() / 4 && e.y < 3 * g.getHeight() / 4) {
|
// longer press in center
|
||||||
clickMouse(MouseButton.RIGHT);
|
else if (getTime() - cttl < 0.6 && e.x > g.getWidth()/4 && e.x < 3 * g.getWidth()/4 && e.y > g.getHeight() / 4 && e.y < 3 * g.getHeight() / 4) {
|
||||||
console.log("click right");
|
bt.clickButton(bt.BUTTON.RIGHT);
|
||||||
|
console.log("click right");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cttl = 0;
|
cttl = 0;
|
||||||
lastx = 0;
|
lastx = 0;
|
||||||
|
|
@ -430,15 +354,17 @@ Bangle.on('drag', function(e) {
|
||||||
} else if(lastx > 40){
|
} else if(lastx > 40){
|
||||||
// E.showMessage('right');
|
// E.showMessage('right');
|
||||||
//kb.tap(kb.KEY.RIGHT, 0);
|
//kb.tap(kb.KEY.RIGHT, 0);
|
||||||
scroll(-1);
|
bt.scroll(-1);
|
||||||
} else if(lastx < -40){
|
} else if(lastx < -40){
|
||||||
// E.showMessage('left');
|
// E.showMessage('left');
|
||||||
//kb.tap(kb.KEY.LEFT, 0);
|
//kb.tap(kb.KEY.LEFT, 0);
|
||||||
scroll(1);
|
bt.scroll(1);
|
||||||
} else if(lastx==0 && lasty==0 && holding == false){
|
|
||||||
// E.showMessage('press');
|
|
||||||
clickMouse(MouseButton.LEFT);
|
|
||||||
}
|
}
|
||||||
|
// Todo re-implement? Seems bit buggy or unnecessary for now.
|
||||||
|
// else if(lastx==0 && lasty==0 && holding == false){
|
||||||
|
// // E.showMessage('press');
|
||||||
|
// bt.clickButton(bt.BUTTON.LEFT);
|
||||||
|
// }
|
||||||
stopHolding();
|
stopHolding();
|
||||||
lastx = 0;
|
lastx = 0;
|
||||||
lasty = 0;
|
lasty = 0;
|
||||||
|
|
@ -452,20 +378,37 @@ Bangle.on('drag', function(e) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function onBtn() {
|
function onBtn() {
|
||||||
if (trackPadMode) {
|
if (trackPadMode) {
|
||||||
trackPadMode = false;
|
if ((getTime() - bttl < 0.4 && !focusMode)) {
|
||||||
stopHolding();
|
E.showMessage('Pointer');
|
||||||
drawMain();
|
focusMode = true;
|
||||||
|
bt.tapKey(bt.KEY.F10, bt.MODIFY.SHIFT);
|
||||||
|
} else {
|
||||||
|
trackPadMode = false;
|
||||||
|
stopHolding();
|
||||||
|
drawMain();
|
||||||
|
if (focusMode) {
|
||||||
|
bt.tapKey(bt.KEY.F10);
|
||||||
|
focusMode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
stopHolding();
|
||||||
clearToSend = true;
|
clearToSend = true;
|
||||||
trackPadMode = true;
|
trackPadMode = true;
|
||||||
E.showMessage('Mouse');
|
E.showMessage('Mouse');
|
||||||
|
// Also skip drawing thingy for now.
|
||||||
|
if (timeoutDraw != -1) {
|
||||||
|
clearTimeout(timeoutDraw);
|
||||||
|
timeoutDraw = -1;
|
||||||
|
}
|
||||||
|
bttl = getTime();
|
||||||
}
|
}
|
||||||
Bangle.buzz();
|
Bangle.buzz();
|
||||||
}
|
}
|
||||||
setWatch(onBtn, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat: true});
|
setWatch(onBtn, (process.env.HWVERSION==2) ? BTN1 : BTN2, {repeat: true});
|
||||||
|
|
||||||
|
// Start App
|
||||||
loadSettings();
|
loadSettings();
|
||||||
drawMain();
|
drawMain();
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "presentor",
|
"id": "presentor",
|
||||||
"name": "Presentor",
|
"name": "Presentor",
|
||||||
"version": "0.08",
|
"version": "0.14",
|
||||||
"description": "Use your Bangle to present!",
|
"description": "Use your Bangle to present!",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
|
|
||||||
|
|
@ -43,3 +43,5 @@
|
||||||
0.34: Avoid prompting when creating a new file (#3081)
|
0.34: Avoid prompting when creating a new file (#3081)
|
||||||
0.35: Handle loading without a settings file (default record setting)
|
0.35: Handle loading without a settings file (default record setting)
|
||||||
0.36: When recording with 1 second periods, log time with one decimal.
|
0.36: When recording with 1 second periods, log time with one decimal.
|
||||||
|
0.37: 1 second periods + gps log => log when gps event is received, not with
|
||||||
|
setInterval.
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "recorder",
|
"id": "recorder",
|
||||||
"name": "Recorder",
|
"name": "Recorder",
|
||||||
"shortName": "Recorder",
|
"shortName": "Recorder",
|
||||||
"version": "0.36",
|
"version": "0.37",
|
||||||
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
"description": "Record GPS position, heart rate and more in the background, then download to your PC.",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
"tags": "tool,outdoors,gps,widget,clkinfo",
|
"tags": "tool,outdoors,gps,widget,clkinfo",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
let storageFile; // file for GPS track
|
let storageFile; // file for GPS track
|
||||||
let entriesWritten = 0;
|
let entriesWritten = 0;
|
||||||
let activeRecorders = [];
|
let activeRecorders = [];
|
||||||
let writeInterval;
|
let writeSetup;
|
||||||
|
|
||||||
let loadSettings = function() {
|
let loadSettings = function() {
|
||||||
var settings = require("Storage").readJSON("recorder.json",1)||{};
|
var settings = require("Storage").readJSON("recorder.json",1)||{};
|
||||||
|
|
@ -194,11 +194,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let writeOnGPS = function() {writeLog(settings.period);};
|
||||||
|
|
||||||
// Called by the GPS app to reload settings and decide what to do
|
// Called by the GPS app to reload settings and decide what to do
|
||||||
let reload = function() {
|
let reload = function() {
|
||||||
var settings = loadSettings();
|
var settings = loadSettings();
|
||||||
if (writeInterval) clearInterval(writeInterval);
|
if (typeof writeSetup === "number") clearInterval(writeSetup);
|
||||||
writeInterval = undefined;
|
writeSetup = undefined;
|
||||||
|
Bangle.removeListener('GPS', writeOnGPS);
|
||||||
|
|
||||||
activeRecorders.forEach(rec => rec.stop());
|
activeRecorders.forEach(rec => rec.stop());
|
||||||
activeRecorders = [];
|
activeRecorders = [];
|
||||||
|
|
@ -222,7 +225,12 @@
|
||||||
}
|
}
|
||||||
// start recording...
|
// start recording...
|
||||||
WIDGETS["recorder"].draw();
|
WIDGETS["recorder"].draw();
|
||||||
writeInterval = setInterval(writeLog, settings.period*1000, settings.period);
|
if (settings.period===1 && settings.record.includes("gps")) {
|
||||||
|
Bangle.on('GPS', writeOnGPS);
|
||||||
|
writeSetup = true;
|
||||||
|
} else {
|
||||||
|
writeSetup = setInterval(writeLog, settings.period*1000, settings.period);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
WIDGETS["recorder"].width = 0;
|
WIDGETS["recorder"].width = 0;
|
||||||
storageFile = undefined;
|
storageFile = undefined;
|
||||||
|
|
@ -230,7 +238,7 @@
|
||||||
}
|
}
|
||||||
// add the widget
|
// add the widget
|
||||||
WIDGETS["recorder"]={area:"tl",width:0,draw:function() {
|
WIDGETS["recorder"]={area:"tl",width:0,draw:function() {
|
||||||
if (!writeInterval) return;
|
if (!writeSetup) return;
|
||||||
g.reset().drawImage(atob("DRSBAAGAHgDwAwAAA8B/D/hvx38zzh4w8A+AbgMwGYDMDGBjAA=="),this.x+1,this.y+2);
|
g.reset().drawImage(atob("DRSBAAGAHgDwAwAAA8B/D/hvx38zzh4w8A+AbgMwGYDMDGBjAA=="),this.x+1,this.y+2);
|
||||||
activeRecorders.forEach((recorder,i)=>{
|
activeRecorders.forEach((recorder,i)=>{
|
||||||
recorder.draw(this.x+15+(i>>1)*12, this.y+(i&1)*12);
|
recorder.draw(this.x+15+(i>>1)*12, this.y+(i&1)*12);
|
||||||
|
|
@ -239,7 +247,7 @@
|
||||||
reload();
|
reload();
|
||||||
Bangle.drawWidgets(); // relayout all widgets
|
Bangle.drawWidgets(); // relayout all widgets
|
||||||
},isRecording:function() {
|
},isRecording:function() {
|
||||||
return !!writeInterval;
|
return !!writeSetup;
|
||||||
},setRecording:function(isOn, options) {
|
},setRecording:function(isOn, options) {
|
||||||
/* options = {
|
/* options = {
|
||||||
force : [optional] "append"/"new"/"overwrite" - don't ask, just do what's requested
|
force : [optional] "append"/"new"/"overwrite" - don't ask, just do what's requested
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ function readFile(input) {
|
||||||
const jCalData = ICAL.parse(icalText);
|
const jCalData = ICAL.parse(icalText);
|
||||||
const comp = new ICAL.Component(jCalData);
|
const comp = new ICAL.Component(jCalData);
|
||||||
const vtz = comp.getFirstSubcomponent('vtimezone');
|
const vtz = comp.getFirstSubcomponent('vtimezone');
|
||||||
const tz = new ICAL.Timezone(vtz);
|
const tz = vtz != null ? new ICAL.Timezone(vtz) : null;
|
||||||
|
|
||||||
// Fetch the VEVENT part
|
// Fetch the VEVENT part
|
||||||
comp.getAllSubcomponents('vevent').forEach(vevent => {
|
comp.getAllSubcomponents('vevent').forEach(vevent => {
|
||||||
|
|
@ -73,7 +73,9 @@ function getAlarmDefaults() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function eventToAlarm(event, tz, offsetMs) {
|
function eventToAlarm(event, tz, offsetMs) {
|
||||||
event.startDate.zone = tz;
|
if (tz != null) {
|
||||||
|
event.startDate.zone = tz;
|
||||||
|
}
|
||||||
const dateOrig = event.startDate.toJSDate();
|
const dateOrig = event.startDate.toJSDate();
|
||||||
const date = offsetMs ? new Date(dateOrig - offsetMs) : dateOrig;
|
const date = offsetMs ? new Date(dateOrig - offsetMs) : dateOrig;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,4 @@ when fastloading.
|
||||||
0.08: Issue newline before GB commands (solves issue with console.log and ignored commands)
|
0.08: Issue newline before GB commands (solves issue with console.log and ignored commands)
|
||||||
0.09: Don't send the gadgetbridge wake command twice. Once should do since we
|
0.09: Don't send the gadgetbridge wake command twice. Once should do since we
|
||||||
issue newline before GB commands.
|
issue newline before GB commands.
|
||||||
|
0.10: Some refactoring to shorten the code.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"", flags:["flag1", "flag2",...], categories:["category1","category2",...], mimetype:"", data:"", package:"", class:"", target:"", extra:{someKey:"someValueOrString"}}));
|
* Bluetooth.println(JSON.stringify({t:"intent", target:"", action:"", flags:["flag1", "flag2",...], categories:["category1","category2",...], package:"", class:"", mimetype:"", data:"", extra:{someKey:"someValueOrString", anotherKey:"anotherValueOrString",...}}));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let R;
|
let R;
|
||||||
|
|
@ -133,6 +133,17 @@ let backToGfx = function() {
|
||||||
The functions for interacting with Android and the Spotify app
|
The functions for interacting with Android and the Spotify app
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
let createCommand = function(o) {
|
||||||
|
return ()=>{
|
||||||
|
Bluetooth.println("");
|
||||||
|
Bluetooth.println(JSON.stringify(o));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
let assembleSearchString = function() {
|
||||||
|
return (artist=="" ? "":("artist:\""+artist+"\"")) + ((artist!="" && track!="") ? " ":"") + (track=="" ? "":("track:\""+track+"\"")) + (((artist!="" && album!="") || (track!="" && album!="")) ? " ":"") + (album=="" ? "":(" album:\""+album+"\""));
|
||||||
|
};
|
||||||
|
|
||||||
simpleSearch = "";
|
simpleSearch = "";
|
||||||
let simpleSearchTerm = function() { // input a simple search term without tags, overrides search with tags (artist and track)
|
let simpleSearchTerm = function() { // input a simple search term without tags, overrides search with tags (artist and track)
|
||||||
require("textinput").input({text:simpleSearch}).then(result => {simpleSearch = result;}).then(() => {E.showMenu(searchMenu);});
|
require("textinput").input({text:simpleSearch}).then(result => {simpleSearch = result;}).then(() => {E.showMenu(searchMenu);});
|
||||||
|
|
@ -153,97 +164,44 @@ let albumSearchTerm = function() { // input album to search for
|
||||||
require("textinput").input({text:album}).then(result => {album = result;}).then(() => {E.showMenu(searchMenu);});
|
require("textinput").input({text:album}).then(result => {album = result;}).then(() => {E.showMenu(searchMenu);});
|
||||||
};
|
};
|
||||||
|
|
||||||
let searchPlayWOTags = function() {//make a spotify search and play using entered terms
|
let searchPlayWOTags = createCommand({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:simpleSearch}, flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
searchString = simpleSearch;
|
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:searchString}, flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let searchPlayWTags = function() {//make a spotify search and play using entered terms
|
let searchPlayWTags = createCommand({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:assembleSearchString()}, flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
searchString = (artist=="" ? "":("artist:\""+artist+"\"")) + ((artist!="" && track!="") ? " ":"") + (track=="" ? "":("track:\""+track+"\"")) + (((artist!="" && album!="") || (track!="" && album!="")) ? " ":"") + (album=="" ? "":(" album:\""+album+"\""));
|
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:searchString}, flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let playVreden = function() {//Play the track "Vreden" by Sara Parkman via spotify uri-link
|
let playVreden = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:track:5QEFFJ5tAeRlVquCUNpAJY:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:track:5QEFFJ5tAeRlVquCUNpAJY:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let playVredenAlternate = function() {//Play the track "Vreden" by Sara Parkman via spotify uri-link
|
let playVredenAlternate = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:track:5QEFFJ5tAeRlVquCUNpAJY:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:track:5QEFFJ5tAeRlVquCUNpAJY:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let searchPlayVreden = function() {//Play the track "Vreden" by Sara Parkman via search and play
|
let searchPlayVreden = createCommand({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:'artist:"Sara Parkman" track:"Vreden"'}, flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:'artist:"Sara Parkman" track:"Vreden"'}, flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let openAlbum = function() {//Play EP "The Blue Room" by Coldplay
|
let openAlbum = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:album:3MVb2CWB36x7VwYo5sZmf2", target:"activity", flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:album:3MVb2CWB36x7VwYo5sZmf2", target:"activity", flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let searchPlayAlbum = function() {//Play EP "The Blue Room" by Coldplay via search and play
|
let searchPlayAlbum = createCommand({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:'album:"The blue room" artist:"Coldplay"', "android.intent.extra.focus":"vnd.android.cursor.item/album"}, flags:["FLAG_ACTIVITY_NEW_TASK"]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.media.action.MEDIA_PLAY_FROM_SEARCH", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", target:"activity", extra:{query:'album:"The blue room" artist:"Coldplay"', "android.intent.extra.focus":"vnd.android.cursor.item/album"}, flags:["FLAG_ACTIVITY_NEW_TASK"]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyWidget = function(action) {
|
let spotifyWidget = function(action) {
|
||||||
Bluetooth.println("");
|
Bluetooth.println("");
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:("com.spotify.mobile.android.ui.widget."+action), package:"com.spotify.music", target:"broadcastreceiver"}));
|
Bluetooth.println(JSON.stringify({t:"intent", action:("com.spotify.mobile.android.ui.widget."+action), package:"com.spotify.music", target:"broadcastreceiver"}));
|
||||||
};
|
};
|
||||||
|
|
||||||
let gadgetbridgeWake = function() {
|
let gadgetbridgeWake = createCommand({t:"intent", target:"activity", flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_CLEAR_TASK", "FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS", "FLAG_ACTIVITY_NO_ANIMATION"], package:"gadgetbridge", class:"nodomain.freeyourgadget.gadgetbridge.activities.WakeActivity"});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", target:"activity", flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_CLEAR_TASK", "FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS", "FLAG_ACTIVITY_NO_ANIMATION"], package:"gadgetbridge", class:"nodomain.freeyourgadget.gadgetbridge.activities.WakeActivity"}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDW = function() {
|
let spotifyPlaylistDW = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZEVXcRfaeEbxXIgb:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZEVXcRfaeEbxXIgb:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM1 = function() {
|
let spotifyPlaylistDM1 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E365VyzxE0mxF:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E365VyzxE0mxF:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM2 = function() {
|
let spotifyPlaylistDM2 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E38LZHLFnrM61:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E38LZHLFnrM61:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM3 = function() {
|
let spotifyPlaylistDM3 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E36RU87qzgBFP:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E36RU87qzgBFP:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM4 = function() {
|
let spotifyPlaylistDM4 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E396gGyCXEBFh:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E396gGyCXEBFh:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM5 = function() {
|
let spotifyPlaylistDM5 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E37a0Tt6CKJLP:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E37a0Tt6CKJLP:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDM6 = function() {
|
let spotifyPlaylistDM6 = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E36UIQLQK79od:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1E36UIQLQK79od:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistDD = function() {
|
let spotifyPlaylistDD = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1EfWFiI7QfIAKq:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZF1EfWFiI7QfIAKq:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
let spotifyPlaylistRR = function() {
|
let spotifyPlaylistRR = createCommand({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZEVXbs0XkE2V8sMO:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]});
|
||||||
Bluetooth.println("");
|
|
||||||
Bluetooth.println(JSON.stringify({t:"intent", action:"android.intent.action.VIEW", categories:["android.intent.category.DEFAULT"], package:"com.spotify.music", data:"spotify:user:spotify:playlist:37i9dQZEVXbs0XkE2V8sMO:play", target:"activity" , flags:["FLAG_ACTIVITY_NEW_TASK", "FLAG_ACTIVITY_NO_ANIMATION"/*, "FLAG_ACTIVITY_CLEAR_TOP", "FLAG_ACTIVITY_PREVIOUS_IS_TOP"*/]}));
|
|
||||||
};
|
|
||||||
|
|
||||||
// Spotify Remote Menu
|
// Spotify Remote Menu
|
||||||
let spotifyMenu = {
|
let spotifyMenu = {
|
||||||
|
|
@ -256,11 +214,14 @@ let spotifyMenu = {
|
||||||
"Exit Spotify Remote" : ()=>{load();}
|
"Exit Spotify Remote" : ()=>{load();}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let menuBackFunc = ()=>{
|
||||||
|
if (backToMenu) E.showMenu(spotifyMenu);
|
||||||
|
if (!backToMenu) backToGfx();
|
||||||
|
};
|
||||||
|
|
||||||
let controlMenu = {
|
let controlMenu = {
|
||||||
"" : { title : " Controls ",
|
"" : { title : " Controls ",
|
||||||
back: () => {if (backToMenu) E.showMenu(spotifyMenu);
|
back: menuBackFunc },
|
||||||
if (!backToMenu) backToGfx();} },
|
|
||||||
"Play" : ()=>{Bangle.musicControl("play");},
|
"Play" : ()=>{Bangle.musicControl("play");},
|
||||||
"Pause" : ()=>{Bangle.musicControl("pause");},
|
"Pause" : ()=>{Bangle.musicControl("pause");},
|
||||||
"Previous" : ()=>{spotifyWidget("PREVIOUS");},
|
"Previous" : ()=>{spotifyWidget("PREVIOUS");},
|
||||||
|
|
@ -271,32 +232,30 @@ let controlMenu = {
|
||||||
|
|
||||||
let searchMenu = {
|
let searchMenu = {
|
||||||
"" : { title : " Search ",
|
"" : { title : " Search ",
|
||||||
back: () => {if (backToMenu) E.showMenu(spotifyMenu);
|
back: menuBackFunc },
|
||||||
if (!backToMenu) backToGfx();} },
|
"Search term w/o tags" : simpleSearchTerm,
|
||||||
"Search term w/o tags" : ()=>{simpleSearchTerm();},
|
"Execute search and play w/o tags" : searchPlayWOTags,
|
||||||
"Execute search and play w/o tags" : ()=>{searchPlayWOTags();},
|
"Search term w tag \"artist\"" : artistSearchTerm,
|
||||||
"Search term w tag \"artist\"" : ()=>{artistSearchTerm();},
|
"Search term w tag \"track\"" : trackSearchTerm,
|
||||||
"Search term w tag \"track\"" : ()=>{trackSearchTerm();},
|
"Search term w tag \"album\"" : albumSearchTerm,
|
||||||
"Search term w tag \"album\"" : ()=>{albumSearchTerm();},
|
"Execute search and play with tags" : searchPlayWTags,
|
||||||
"Execute search and play with tags" : ()=>{searchPlayWTags();},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let savedMenu = {
|
let savedMenu = {
|
||||||
"" : { title : " Saved ",
|
"" : { title : " Saved ",
|
||||||
back: () => {if (backToMenu) E.showMenu(spotifyMenu);
|
back: menuBackFunc },
|
||||||
if (!backToMenu) backToGfx();} },
|
"Play Discover Weekly" : spotifyPlaylistDW,
|
||||||
"Play Discover Weekly" : ()=>{spotifyPlaylistDW();},
|
"Play Daily Mix 1" : spotifyPlaylistDM1,
|
||||||
"Play Daily Mix 1" : ()=>{spotifyPlaylistDM1();},
|
"Play Daily Mix 2" : spotifyPlaylistDM2,
|
||||||
"Play Daily Mix 2" : ()=>{spotifyPlaylistDM2();},
|
"Play Daily Mix 3" : spotifyPlaylistDM3,
|
||||||
"Play Daily Mix 3" : ()=>{spotifyPlaylistDM3();},
|
"Play Daily Mix 4" : spotifyPlaylistDM4,
|
||||||
"Play Daily Mix 4" : ()=>{spotifyPlaylistDM4();},
|
"Play Daily Mix 5" : spotifyPlaylistDM5,
|
||||||
"Play Daily Mix 5" : ()=>{spotifyPlaylistDM5();},
|
"Play Daily Mix 6" : spotifyPlaylistDM6,
|
||||||
"Play Daily Mix 6" : ()=>{spotifyPlaylistDM6();},
|
"Play Daily Drive" : spotifyPlaylistDD,
|
||||||
"Play Daily Drive" : ()=>{spotifyPlaylistDD();},
|
"Play Release Radar" : spotifyPlaylistRR,
|
||||||
"Play Release Radar" : ()=>{spotifyPlaylistRR();},
|
"Play \"Vreden\" by Sara Parkman via uri-link" : playVreden,
|
||||||
"Play \"Vreden\" by Sara Parkman via uri-link" : ()=>{playVreden();},
|
"Open \"The Blue Room\" EP (no autoplay)" : openAlbum,
|
||||||
"Open \"The Blue Room\" EP (no autoplay)" : ()=>{openAlbum();},
|
"Play \"The Blue Room\" EP via search&play" : searchPlayAlbum,
|
||||||
"Play \"The Blue Room\" EP via search&play" : ()=>{searchPlayAlbum();},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Bangle.loadWidgets();
|
Bangle.loadWidgets();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "spotrem",
|
"id": "spotrem",
|
||||||
"name": "Remote for Spotify",
|
"name": "Remote for Spotify",
|
||||||
"version": "0.09",
|
"version": "0.10",
|
||||||
"description": "Control spotify on your android device.",
|
"description": "Control spotify on your android device.",
|
||||||
"readme": "README.md",
|
"readme": "README.md",
|
||||||
"type": "app",
|
"type": "app",
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@
|
||||||
0.02: Checks for correct firmware; E.setDST(...) moved to boot.js
|
0.02: Checks for correct firmware; E.setDST(...) moved to boot.js
|
||||||
0.03: Convert Yes/No On/Off in settings to checkboxes
|
0.03: Convert Yes/No On/Off in settings to checkboxes
|
||||||
0.04: Give the boot file the highest priority to ensure it runs before sched (fix #2663)
|
0.04: Give the boot file the highest priority to ensure it runs before sched (fix #2663)
|
||||||
|
0.05: Tweaks to ensure Gadgetbridge can't overwrite timezone on 2v19.106 and later
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
(() => {
|
if (E.setDST) {
|
||||||
|
let dstSettings = require('Storage').readJSON('widdst.json',1)||{};
|
||||||
if (E.setDST) {
|
if (dstSettings.has_dst) {
|
||||||
var dstSettings = require('Storage').readJSON('widdst.json',1)||{};
|
E.setDST(60*dstSettings.dst_size, 60*dstSettings.tz, dstSettings.dst_start.dow_number, dstSettings.dst_start.dow,
|
||||||
if (dstSettings.has_dst) {
|
dstSettings.dst_start.month, dstSettings.dst_start.day_offset, 60*dstSettings.dst_start.at,
|
||||||
E.setDST(60*dstSettings.dst_size, 60*dstSettings.tz, dstSettings.dst_start.dow_number, dstSettings.dst_start.dow,
|
dstSettings.dst_end.dow_number, dstSettings.dst_end.dow, dstSettings.dst_end.month, dstSettings.dst_end.day_offset,
|
||||||
dstSettings.dst_start.month, dstSettings.dst_start.day_offset, 60*dstSettings.dst_start.at,
|
60*dstSettings.dst_end.at);
|
||||||
dstSettings.dst_end.dow_number, dstSettings.dst_end.dow, dstSettings.dst_end.month, dstSettings.dst_end.day_offset,
|
/* on 2v19.106 and later, E.setTimeZone overwrites E.setDST so we
|
||||||
60*dstSettings.dst_end.at);
|
manually disable E.setTimeZone here to stop Gadgetbridge resetting the timezone */
|
||||||
} else {
|
E.setTimeZone = function(){};
|
||||||
E.setDST(0,0,0,0,0,0,0,0,0,0,0,0);
|
} else {
|
||||||
}
|
E.setDST(0,0,0,0,0,0,0,0,0,0,0,0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
})()
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{ "id": "widdst",
|
{ "id": "widdst",
|
||||||
"name": "Daylight Saving",
|
"name": "Daylight Saving",
|
||||||
"version":"0.04",
|
"version":"0.05",
|
||||||
"description": "Widget to set daylight saving rules. Requires Espruino 2v15 or later - see the instructions below for more information.",
|
"description": "Widget to set daylight saving rules. Requires Espruino 2v15 or later - see the instructions below for more information.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
0.01: New App!
|
||||||
|
0.02: Read maximum HRM from myprofile
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"id": "widhrzone",
|
"id": "widhrzone",
|
||||||
"name": "Heart rate zone widget",
|
"name": "Heart rate zone widget",
|
||||||
"shortName": "HRzone widget",
|
"shortName": "HRzone widget",
|
||||||
"version": "0.01",
|
"version": "0.02",
|
||||||
"description": "Widget that displays the current out of five heart rate training zones 1. HEALTH (50-60% of max. HR, Recovery, grey), 2. FAT-B (60-70% of max. HR, burns fat, blue), 3. AROBIC (70-80% of max. HR, Endurance, green), 4. ANAROB (80-90% of max. HR, Speed, yellow), 5. MAX (90-100% of max. HR, red). Only visible when heart rate monitor is active and inside one of the zones. Requires to set the maximum heart rate in settings (if unsure set to 220-age).",
|
"description": "Widget that displays the current out of five heart rate training zones 1. HEALTH (50-60% of max. HR, Recovery, grey), 2. FAT-B (60-70% of max. HR, burns fat, blue), 3. AROBIC (70-80% of max. HR, Endurance, green), 4. ANAROB (80-90% of max. HR, Speed, yellow), 5. MAX (90-100% of max. HR, red). Only visible when heart rate monitor is active and inside one of the zones. Requires to set the maximum heart rate in settings (if unsure set to 220-age).",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
@ -10,8 +10,7 @@
|
||||||
"supports": ["BANGLEJS","BANGLEJS2"],
|
"supports": ["BANGLEJS","BANGLEJS2"],
|
||||||
"screenshots" : [ { "url":"screenshot.png" } ],
|
"screenshots" : [ { "url":"screenshot.png" } ],
|
||||||
"storage": [
|
"storage": [
|
||||||
{"name":"widhrzone.wid.js","url":"widget.js"},
|
{"name":"widhrzone.wid.js","url":"widget.js"}
|
||||||
{"name":"widhrzone.settings.js","url":"settings.js"}
|
|
||||||
],
|
],
|
||||||
"data": [{"name":"widhrzone.json"}]
|
"dependencies": {"myprofile":"app"}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
(function(back) {
|
|
||||||
const CONFIGFILE = "widhrzone.json";
|
|
||||||
// Load settings
|
|
||||||
const settings = Object.assign({
|
|
||||||
maxHrm: 200,
|
|
||||||
}, require("Storage").readJSON(CONFIGFILE,1) || {});
|
|
||||||
|
|
||||||
function writeSettings() {
|
|
||||||
require('Storage').writeJSON(CONFIGFILE, settings);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the menu
|
|
||||||
E.showMenu({
|
|
||||||
"" : { "title" : "HRzone widget" },
|
|
||||||
"< Back" : () => back(),
|
|
||||||
/*LANG*/'HR max': {
|
|
||||||
format: v => v,
|
|
||||||
value: settings.maxHrm,
|
|
||||||
min: 30, max: 220,
|
|
||||||
onchange: v => {
|
|
||||||
settings.maxHrm = v;
|
|
||||||
writeSettings();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
(() => {
|
(() => {
|
||||||
const config = Object.assign({
|
const myprofile = require("Storage").readJSON("myprofile.json",1)||{};
|
||||||
maxHrm: 200,
|
|
||||||
}, require("Storage").readJSON("widhrzone.json",1) || {});
|
|
||||||
|
|
||||||
require("FontTeletext5x9Ascii").add(Graphics);
|
require("FontTeletext5x9Ascii").add(Graphics);
|
||||||
|
|
||||||
const calczone = (bpm) => {
|
const calczone = (bpm) => {
|
||||||
if (bpm <= config.maxHrm*0.5) {
|
if (bpm <= myprofile.maxHrm*0.5) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if (bpm <= config.maxHrm*0.60) {
|
} else if (bpm <= myprofile.maxHrm*0.60) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (bpm <= config.maxHrm*0.70) {
|
} else if (bpm <= myprofile.maxHrm*0.70) {
|
||||||
return 2;
|
return 2;
|
||||||
} else if (bpm <= config.maxHrm*0.80) {
|
} else if (bpm <= myprofile.maxHrm*0.80) {
|
||||||
return 3;
|
return 3;
|
||||||
} else if (bpm <= config.maxHrm*0.90) {
|
} else if (bpm <= myprofile.maxHrm*0.90) {
|
||||||
return 4;
|
return 4;
|
||||||
} else { // > 0.9
|
} else { // > 0.9
|
||||||
return 5;
|
return 5;
|
||||||
|
|
|
||||||
|
|
@ -6,3 +6,4 @@
|
||||||
0.06: Darkmode, custom colours, and fix a bug with acting on mylocation changes
|
0.06: Darkmode, custom colours, and fix a bug with acting on mylocation changes
|
||||||
0.07: Use default Bangle formatter for booleans
|
0.07: Use default Bangle formatter for booleans
|
||||||
0.08: Better formula for the moon's phase
|
0.08: Better formula for the moon's phase
|
||||||
|
0.09: Fix variable declaration
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "widmp",
|
"id": "widmp",
|
||||||
"name": "Moon Phase",
|
"name": "Moon Phase",
|
||||||
"version": "0.08",
|
"version": "0.09",
|
||||||
"description": "Display the current moon phase in blueish (in light mode) or white (in dark mode) for both hemispheres. In the southern hemisphere the 'My Location' app is needed.",
|
"description": "Display the current moon phase in blueish (in light mode) or white (in dark mode) for both hemispheres. In the southern hemisphere the 'My Location' app is needed.",
|
||||||
"icon": "widget.png",
|
"icon": "widget.png",
|
||||||
"type": "widget",
|
"type": "widget",
|
||||||
|
|
|
||||||
|
|
@ -6,11 +6,11 @@
|
||||||
|
|
||||||
// https://github.com/deirdreobyrne/LunarPhase
|
// https://github.com/deirdreobyrne/LunarPhase
|
||||||
function moonPhase(sec) {
|
function moonPhase(sec) {
|
||||||
d = (4.847408287988257 + sec/406074.7465115577) % (2.0*Math.PI);
|
let d = (4.847408287988257 + sec/406074.7465115577) % (2.0*Math.PI);
|
||||||
m = (6.245333801867877 + sec/5022682.784840698) % (2.0*Math.PI);
|
let m = (6.245333801867877 + sec/5022682.784840698) % (2.0*Math.PI);
|
||||||
l = (4.456038755040014 + sec/378902.2499653011) % (2.0*Math.PI);
|
let l = (4.456038755040014 + sec/378902.2499653011) % (2.0*Math.PI);
|
||||||
t = d+1.089809730923715e-01 * Math.sin(l)-3.614132757006379e-02 * Math.sin(m)+2.228248661252023e-02 * Math.sin(d+d-l)+1.353592753655652e-02 * Math.sin(d+d)+4.238560208195022e-03 * Math.sin(l+l)+1.961408105275610e-03 * Math.sin(d);
|
let t = d+1.089809730923715e-01 * Math.sin(l)-3.614132757006379e-02 * Math.sin(m)+2.228248661252023e-02 * Math.sin(d+d-l)+1.353592753655652e-02 * Math.sin(d+d)+4.238560208195022e-03 * Math.sin(l+l)+1.961408105275610e-03 * Math.sin(d);
|
||||||
k = (1.0 - Math.cos(t))/2.0;
|
let k = (1.0 - Math.cos(t))/2.0;
|
||||||
if ((t >= Math.PI) && (t < 2.0*Math.PI)) {
|
if ((t >= Math.PI) && (t < 2.0*Math.PI)) {
|
||||||
k = -k;
|
k = -k;
|
||||||
}
|
}
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
function loadLocation() {
|
function loadLocation() {
|
||||||
// "mylocation.json" is created by the "My Location" app
|
// "mylocation.json" is created by the "My Location" app
|
||||||
location = require("Storage").readJSON("mylocation.json",1)||{"lat":50.1236,"lon":8.6553,"location":"Frankfurt"};
|
let location = require("Storage").readJSON("mylocation.json",1)||{"lat":50.1236,"lon":8.6553,"location":"Frankfurt"};
|
||||||
southernHemisphere = (location.lat < 0);
|
southernHemisphere = (location.lat < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,12 +63,13 @@
|
||||||
|
|
||||||
function draw() {
|
function draw() {
|
||||||
const CenterX = this.x + 12, CenterY = this.y + 12, Radius = 11;
|
const CenterX = this.x + 12, CenterY = this.y + 12, Radius = 11;
|
||||||
|
let leftFactor, rightFactor;
|
||||||
|
|
||||||
loadLocation();
|
loadLocation();
|
||||||
g.reset().setColor(g.theme.bg);
|
g.reset().setColor(g.theme.bg);
|
||||||
g.fillRect(CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius);
|
g.fillRect(CenterX - Radius, CenterY - Radius, CenterX + Radius, CenterY + Radius);
|
||||||
|
|
||||||
millis = (new Date()).getTime();
|
let millis = (new Date()).getTime();
|
||||||
if ((millis - lastCalculated) >= 7000000) { // if it's more than 7,000 sec since last calculation, re-calculate!
|
if ((millis - lastCalculated) >= 7000000) { // if it's more than 7,000 sec since last calculation, re-calculate!
|
||||||
phase = moonPhase(millis/1000);
|
phase = moonPhase(millis/1000);
|
||||||
lastCalculated = millis;
|
lastCalculated = millis;
|
||||||
|
|
|
||||||
|
|
@ -83,16 +83,16 @@
|
||||||
"Connect device\nto add to\nwhitelist": "Connecter le dispositif\nà ajouter à\nliste blanche",
|
"Connect device\nto add to\nwhitelist": "Connecter le dispositif\nà ajouter à\nliste blanche",
|
||||||
"LCD Timeout": "Temporisation de l'écran LCD",
|
"LCD Timeout": "Temporisation de l'écran LCD",
|
||||||
"LCD Brightness": "Luminosité de l'écran LCD",
|
"LCD Brightness": "Luminosité de l'écran LCD",
|
||||||
"Wake on BTN2": "Wake sur BTN2",
|
"Wake on BTN2": "Réveil sur BTN2",
|
||||||
"Wake on BTN3": "Wake sur BTN3",
|
"Wake on BTN3": "Réveil sur BTN3",
|
||||||
"Wake on FaceUp": "Réveillez-vous sur FaceUp",
|
"Wake on FaceUp": "Réveillez-vous sur FaceUp",
|
||||||
"Wake on Touch": "Réveil au toucher",
|
"Wake on Touch": "Réveil au toucher",
|
||||||
"Twist Threshold": "Seuil de torsion",
|
"Twist Threshold": "Seuil de rotation",
|
||||||
"Wake on Twist": "Réveil sur Twist",
|
"Wake on Twist": "Réveil sur rotation",
|
||||||
"Reset to Defaults": "Réinitialisation des valeurs par défaut",
|
"Reset to Defaults": "Réinitialisation des valeurs par défaut",
|
||||||
"Utilities": "Utilitaires",
|
"Utilities": "Utilitaires",
|
||||||
"Flattening battery - this can take hours.\nLong-press button to cancel": "Mise à plat de la batterie - cela peut prendre des heures.\nAppuyez longuement sur le bouton pour annuler",
|
"Flattening battery - this can take hours.\nLong-press button to cancel": "Décharger la batterie - cela peut prendre des heures.\nAppuyez longuement sur le bouton pour annuler",
|
||||||
"Flatten Battery": "Aplatir la batterie",
|
"Flatten Battery": "Décharger la batterie",
|
||||||
"Storage": "Stockage",
|
"Storage": "Stockage",
|
||||||
"Reset Settings": "Réinitialiser les paramètres",
|
"Reset Settings": "Réinitialiser les paramètres",
|
||||||
"Log": "Journal de bord",
|
"Log": "Journal de bord",
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
"Show": "Afficher",
|
"Show": "Afficher",
|
||||||
"Hide": "Cacher",
|
"Hide": "Cacher",
|
||||||
"Messages": "Messages",
|
"Messages": "Messages",
|
||||||
"BACK": "BACK",
|
"BACK": "RETOUR",
|
||||||
"Error in settings": "Erreur dans les paramètres",
|
"Error in settings": "Erreur dans les paramètres",
|
||||||
"Timer": "Minuterie",
|
"Timer": "Minuterie",
|
||||||
"On": "Sur",
|
"On": "Sur",
|
||||||
|
|
@ -155,7 +155,7 @@
|
||||||
"steps": "étapes",
|
"steps": "étapes",
|
||||||
"Settings": "Paramètres",
|
"Settings": "Paramètres",
|
||||||
"ALARM": "ALARME",
|
"ALARM": "ALARME",
|
||||||
"back": "dos",
|
"back": "retour",
|
||||||
"Yes": "Oui",
|
"Yes": "Oui",
|
||||||
"Steps": "Étapes",
|
"Steps": "Étapes",
|
||||||
"Year": "Année",
|
"Year": "Année",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue