Merge remote-tracking branch 'upstream/master'
commit
cd7e0292c4
43
apps.json
43
apps.json
|
|
@ -500,9 +500,9 @@
|
|||
{ "id": "speedo",
|
||||
"name": "Speedo",
|
||||
"icon": "speedo.png",
|
||||
"version":"0.04",
|
||||
"version":"0.05",
|
||||
"description": "Show the current speed according to the GPS",
|
||||
"tags": "tool,outdoors,gps",
|
||||
"tags": "tool,outdoors,gps,b2",
|
||||
"storage": [
|
||||
{"name":"speedo.app.js","url":"speedo.js"},
|
||||
{"name":"speedo.img","url":"speedo-icon.js","evaluate":true}
|
||||
|
|
@ -511,7 +511,7 @@
|
|||
{ "id": "gpsrec",
|
||||
"name": "GPS Recorder",
|
||||
"icon": "app.png",
|
||||
"version":"0.23",
|
||||
"version":"0.24",
|
||||
"interface": "interface.html",
|
||||
"description": "Application that allows you to record a GPS track. Can run in background",
|
||||
"tags": "tool,outdoors,gps,widget",
|
||||
|
|
@ -687,7 +687,7 @@
|
|||
{ "id": "widbt",
|
||||
"name": "Bluetooth Widget",
|
||||
"icon": "widget.png",
|
||||
"version":"0.05",
|
||||
"version":"0.06",
|
||||
"description": "Show the current Bluetooth connection status in the top right of the clock",
|
||||
"tags": "widget,bluetooth,b2",
|
||||
"type":"widget",
|
||||
|
|
@ -1316,7 +1316,7 @@
|
|||
{ "id": "widid",
|
||||
"name": "Bluetooth ID Widget",
|
||||
"icon": "widget.png",
|
||||
"version":"0.02",
|
||||
"version":"0.03",
|
||||
"description": "Display the last two tuple of your Bangle.js MAC address in the widget section. This is useful for figuring out which Bangle.js to connect to if you have more than one Bangle.js!",
|
||||
"tags": "widget,address,mac",
|
||||
"type":"widget",
|
||||
|
|
@ -3533,7 +3533,7 @@
|
|||
"name": "Wave Clock",
|
||||
"icon": "app.png",
|
||||
"version":"0.02",
|
||||
"description": "A clock using a wave image by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: This requires a bugfix for #2049 on Bangle.js 1**",
|
||||
"description": "A clock using a wave image by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: This requires firmware 2v11 or later Bangle.js 1**",
|
||||
"tags":"clock,b2",
|
||||
"type":"clock",
|
||||
"allow_emulator":true,
|
||||
|
|
@ -3541,5 +3541,36 @@
|
|||
{"name":"waveclk.app.js","url":"app.js"},
|
||||
{"name":"waveclk.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "floralclk",
|
||||
"name": "Floral Clock",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"description": "A clock with a flower background by [Lillith May](https://www.instagram.com/_lilustrations_/). **Note: This requires firmware 2v11 or later Bangle.js 1**",
|
||||
"tags":"clock,b2",
|
||||
"type":"clock",
|
||||
"allow_emulator":true,
|
||||
"storage": [
|
||||
{"name":"floralclk.app.js","url":"app.js"},
|
||||
{"name":"floralclk.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{ "id": "score",
|
||||
"name": "Score Tracker",
|
||||
"icon": "score.app.png",
|
||||
"version":"0.01",
|
||||
"description": "Score Tracker for sports that use plain numbers (e.g. Badminton, Volleyball, Soccer, Table Tennis, ...). Also supports tennis scoring.",
|
||||
"readme": "README.md",
|
||||
"tags": "b2",
|
||||
"type": "app",
|
||||
"storage": [
|
||||
{"name":"score.app.js","url":"score.app.js"},
|
||||
{"name":"score.settings.js","url":"score.settings.js"},
|
||||
{"name":"score.presets.json","url":"score.presets.json"},
|
||||
{"name":"score.img","url":"score.app-icon.js","evaluate":true}
|
||||
],
|
||||
"data": [
|
||||
{"name":"score.json"}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -11,4 +11,4 @@
|
|||
0.11: Respect Quiet Mode
|
||||
0.12: Fix widget for bangle 2, now uses theme
|
||||
Widgets now shown on Alarm screen
|
||||
Alarm widget state now updates when setting/resetting an alarm
|
||||
0.13: Alarm widget state now updates when setting/resetting an alarm
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwhE+sVin0/tVjsdim84sdro1GAQNrAAlHAYVqABk/FINosc/AoNpF4cTGoMTnIhBo1qEgIvFABJACoAvEFwJaDGoNjnFpn5eCik/DYQwBAAQwOFIMUDYKBBLwQwBnwoBBAM3GIIEBhs5E4RLBPYqMKFwU4AAM+nwCBF4SJCAwMxXII2BnBeDJogAGNQIAFBIJMBRIYvCLQK+Bow7BhsNCINjm45BXwZgHF5ITBigoBF4NpQoIwBLwLJBn8Oh0NBoU4F4J6CF4RiKR47iCtIrBiaGBEgdknMOnBABiYKBtNkKoaUIdo5hCQoKvBYgKGBGAIJBMANjhqfBHgLQBNgKcBEpAxBBA9HHoiwBF4S3BcoM4Nwdim83sVEGAINBMQIfBEASYGLII4ECISFBnEyFgKHBGwRsDHYKfBaQOGrifCXw4qBNgIEBXoQHBCQZXBnArCAQNpnBWBFwUTBINiwGkwFcsbzDEwJcFG4pcCAAMUik/EIKJBn6JBMYNpnzABsY0BwGeAAN6wLnCEQQACF4ztCF4UUJ4QNDGAKTCtMTnASBHwOezAwCveIP4ReEeQzNDFwgvDDQU/oDlDJYVkF4e8z2Hx2Px2IAAKKEGo1qnAuBtLYBBwRJCAoIuCbgVqxAsCAQWB1mBwN6AANWmSwBJwRcCDIIuDnxAGAYU5HQmPF4W84QBBvWlGoOY4TIBmMxnJGCYYc5ik+coNjn8UhsUiqRDGQQUBQQJUBz3CzAxBYYYADvWGsTZBDoNHcQUTXgU+n1pB4LmBFQSUCAoNkw4uCF4QBBF4QFBAAIFBF4IjBoBMCn84nwtCMAIABm8TnLREXYd7KQSLBzoBDAQJlBBQN5w1osU/VAQuBnCLBGQNpGYM4R4LRCAATTBRgJcCy4kBz3I5HO5HHy4JBYwRfBcYIfBoE4m5YCho0BA4M4FwzzCxCMBEIO73guB5wAC5BgBSoWAF4KQBsdkKoKNChoACik4nIuHF4i0BdQOdF4XNAQK8Cz2lqzjCnCIBFwTnBS4IrBTQQuBdoLuCBAWOdoOYWgRfC5ovDy4vDriDCAAS8CFQYADdQgvCowvDSAK0CF4SPC4QwCvVcmUymMxFwSUBFwQoDFQToBAoIsBBoSQBMASRBy6QDXwIJCSIWAFwjzDWowAKGYOHwIhBYIOezooC3YuBF4d6GAK/BYAVkF6CUExBiBYQQCBFQIvCzAvCAYM3LoUTLwIeDF5pBDSQRgCLQYDBZQZrBz1cw9iiZeCWoQvWeYQuBfIIxCLwd6w1inEULyQvFtYvFEwOB0uBz4zCX4QuBnDsCDortNCQNHL4mYFwN7ZAOIfgN6AANcsc+m6NBDoRgQFwNGo5FBx2HKoZeBHYNqsg7BqtVsS8BRoReCL6AgBSYQ1CwJWBveHZYlkmMxLwM4h05sgADPwRRCF5ouDMIKKCxwPDsk4mM4XgMTXwLvBikOYYQvOBoQOBoE/JA4DBn8UFwNim8NF4QABhsNnIvQUgVAnMOVoQ4CAANqscUidiRoMNm4zBAAQHBF6CLDO4JIBGAVHXgYiBn1jn0NGYVoAAIvBIwYvOBgM/hyxBAAQXBHYU5RANjscTLwNjLgIuBny+FF5xeBhtcPYU+DYJeDRog0CCIYSBoAvRGAMUmOHJgcbF4QuBFIUNmIBBeYItCIIRNBd54ABisUVgNED4QJBn69Dm4uBh0OnIsBoArCFBoPDHgNqoAvBL4YvCb4JeBnxiCslkDogvRNQVGGALrBVobwBfAMNXoMTigsHDINHAAIvJGIdGn9ro4FBscNMANpF4LoBm4DChq1BFAJDBDobmMMIgvDA4UULwKHBMoLlBG4MynBeBCYQfFF56MBoAbDMAKzBnETm7oBGoM4hxeCQoJfCcJC/KAgIvFMAMNAASNBsQ1BLwVqFwIeELppCBF4dq"))
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
function getImg() {
|
||||
return require("heatshrink").decompress(atob("2F0gdt23bAX4C/AWvYppB+2kAgM2IPuwgRB/2ESpJB/IIMmzYUN6EJIN1IgECChuAa9u0IIUApoUMgVAINsCoMkwBBMKYRBs0kAgMkyBBGwDOEIIUmDoqbOAS0EySDBII1sgMAIJmgLgJBithBLpMkYpmBkmBIMckyTFByQLFsBBGgRBGxJBlgmQIIOTBYtiII0AgDFEtkJkmAJQoCdgGSFAILGgRBD7QOBIIMAibUFyBBj22SpJxEtsG7cSIIfQH4QACBAMAiBBn7ZBFsEAghLBIIXAAgJBDhuBkgOCyBcFIMDFEYQRBHwDIBAQIDBIIcAIMsEAobCCII0ggA9BHQJBEyUAjZBx7TCCQYRBDtu0yVIgZBizdJgGbYpQRB2mAoBEBhuBIIlJIMWggEBkBBDsA+Bydt0gUEwFJ0wFB2CDowDrBIIltWwJBGQYIaESQZBBjZBhghBCEwmJIJGCIJNJrZBhEoMAkhBDtiDDklsgEApukIIjFCIIVATwhBggjsBkhBBOIcktEEwEN0j7EIIw+fAQWkyEIIINggEbsBBEsEkwCLBiZBJgBBi2matuEwS7BgdiII2QhMgagZBCyFIIMoCCwGAgJBJyRBG2kAgMwBgMGIM41BZANJghBGgGbC4nAhu2TQMmIMugiBBDgBBDtkAyEIIIxEDgI4coBfI2D7BgETBAUCIIKPBgBBByR3k23aUQJrH2mQBYIIDsFIIIL+BpEAwEBmxBmO4ZBEiUAgwIDYQMAAoPQoEEKAJBlfYQLHyQyIpu26VAkgOBcBBBcegJBIwVAQYgCChJBq7ZBBgVtgEbBYnApBBHgJBBgEkyEBSQ9sghBetEAiYLE7EJgAUGoLRBgMkgFJEY9AgGbILVIkECZA/aIJO0iCGBEZMAILiABgEJII8BkDOFTAM0yEJEZJZBkhBbtuAIITFE2kAIJMgwENIJSkBILmkIIQ4E0GSgEkgQOBYokEwFNUhEE6RBekiwBkAIEIINIIILUBR4cBgkAEBFAgmCILtpkh6CIIsSIILSBgCGBBYMAggFDAQqhBwBBBQDJBDyFJkwLE2mSNwJBBZARBCkkDIOe2d4JBBgIvBIIcgZYYCFCIUAEAzFYMROgyBBFgMgiQgKIIMEzZBatskyZBJ2BBCwS5DkEQgIgI0hBBgEbILZlDEBESIIMCIIcAyVAXJG0gAUBahKGWEAOkEYvCoEAgYICpEEyT7J2ECoJBg0mDIgI4DIJFAgmQgEGDo+AyTmBYrxBBwQjBXgYCB6FIeQkBkGAwBBHtkEydtkBBf2mSU4ImBBYfaIIObIIe0wmSII9gkgRBAQRBeiRBBEY1JgDyDhO28mSoAdGgMkHbgCGYoRBHkEDAoVNIIVBoEAJofYhKeGATvApEEBY1hkkABAlEbAWSgBNC4BTBgENIMPQpMmBY1AgmAQAIIBwA+BSwJBBwARBgAHBwBBjhJBG7EAIIIvBzdsgBBFyFN2kCIMvadgLOGBAOQgOwidgAwJBEyVN0ESgLFBSoYCfgJBHeoJBBgECsA+CIIqGBgAOBH0ACCsEgzZBHiAyBgFiHwIPBRoMEyFIgGABoMTfa8AgxBKkkbYo0AiUAHAJBFyUEwFAAQMAkx3X4CkBBxNoghoFKwJBBGoOSYoRBDRoUkQC4CCE4MAiEBmxBIwQIE7SAB7BBByBBDtLFBIAMBbowCERh5iBoAhBCg9BgBBFIgdIXINshIdBIgIgCagLpKgBNKAQWwEYRBBggOF6AuByFNDQ9JkEAtq9BIIpNBIJTZCIKGAgEbBwnSFwUJDQ9pIIW0IIggBpEGGRNBkmTIKACBpBBF4QKBiUBDREkIILjCDocCoE2IMEDBwnABQMCoIsIkmAAoMEyQwBDoJWBIJUBIJts5KnFgRBFhMgNxWkIIQaBgMECQMQTBJBQoA+DdIcNIIkAAANIOwIQBzYdD2mSQYcE6ATBwAdEGQ8kiZBLgQ+CVwJBCMonYFgPYhYYDCAJBGwmQg3bsBBM6QjBIJfYN4STB0jpBgTpH7VbAwhBD2xBCSoIXBoEEgFt0wyH0GSU4VNIJUSIItJiVBIIu0ywbGkxuDKAQKCGQQABa4gCBtjWBoEAyRuHQZZJBCIukGYNJk36BgVkGQm0AoXagMgIIUbIJdAL4aDJVYLFDTA0t3/SIIP+AQIqBIIkAgYFB6EJgAlBII9tkmQIIUAIJPaIIYCCpETCItptu3+RBDkgMBLAJxCgECAoOAhBBDYoyVBHwMAiDFK7dghJBFMQ1rAYKACIITaB2QOCtAtBAoMApB0BIIIyJoDIBWAwCFxJBMpdt03/IImaIIImCsEEyFN2kCWwVISgS2HoDCJWYMkTYOxIIlAIIvardt0nf5JBF2xBDDIMN2BBCiUJWxJBMpEEIJDmF7QDB0mf9MnIIXfII9NwESZQMSWw/aBAPSoBNJ7YoBII2Qgj3BCIfWAYMkyf5IIQCBFQPJCINoQYWAiEBGRPAgEENoIOI2nahJBC2AkBMYMAG4JBGv+kIILFCn/yIIlsF4MNgGQhJxHAQOApMgagJBIwEAhMgfwO0QAS7CIIv27f//2Sv8k7VJ33SpJBDtpBBhEAwENIJOCV4MCSROEwEJgD+CJAMmIIWSIIubv//6V9a4W2AQRBDwmQWwOARwJBLiUBBxEETwMABY5BG22bpO//1NkiABIgU27JrC0DgCgQ+HAQXCDIMQIJOAyQeBBY1AVoJBF7dJk//5M3/5BI2AiBfAJBKLYWQIJOgIJD3BGIIID2hBCkn//M///pII+0gEBkETIJQfBkGQhoOIDocbIJwJCzf/IIP5m/+IIu2wDpBEYrvIwBBJDoIuBL4pBM71tIIQCB/+27MmDQXAhEAzZBMwhBLiQuBL4vYhMgyVNYo03/VJYoR+BIQP5QYZBCHxQCCgmABZO0iVBghfF7TOBII9//3SpMm/6TCpO/IItIghBMthBL2AlBkgLGoIxBTYZBD+hLBHwQCCm3ZIIeAoEGIJ0CIJYaKIIm2AYNpHYNt0hBKgVAkxBMtEkgVICJGEyAaKXYM2aIQJBHYVvkmTI4VJ2xBD2kCgE2yQyJAQNgkEAoEABYmkyZBBwRBLZAKeCIIl/IIP/ZYJRB5JBC2ESgE0yTILoJBBpEANYQLBghBCwZBQyxBCyd9IIX/SYO2IIsBKQNIIJUBkDFBgEbBAVsgmSpkEIKPS7a/Byf9GYNN//+ppBE0GQIJvahMAIISDDIIVIkkDIJpQCIINtIIP5GYNJm//BgPJC4WAyEAFIRBJ7BBBAAMEBYgXBoBBPa4JBEzZBDknf9pBEgmAIJvQIIOaToPQgARCwESIIMTIJYOBTYdbtukz5BEBgQpBVQRBDgEmQAwIB4FIQAcACQMbcAKMBkgFBIJVIEwlLtu0IIoMCIIwABgM2EYvABQOAIIewEANIPoXTOgJBStIDC9JBCBgWyBQVokhBDhIjGwEBkEAaIexIIUDCIVgIJnadg0tIoQgBBIYEDMoJACboYCEJQIOBoBbCIIVJg5BY0oDBXoQJDyYECgMkgQjKwBBBgRBHghZBjZfBLhBBK2gSHDoi2BIJfAIIc2IIoCCR4MkzVJGoo4DbIILG6QGF7BrCIIcTIJZ3BIIm5II0AkkQgEEDo+gIIILG7VJAwitDIJ/aGYMSgJBCbYJBEkBBBgVIgAdHgjZCBY1pkgDBgmQFIYHBhLsBIJXbtBBEsDMBIIkkIIMSIJFsCASPI22SoBsBhILEIJyqBIIdCHYObtukIItAGo9sQYSPIVoJBBgQLFIII+KIIq7BgRBGYoRpBgzFKIJVILI5BQyUAG4MSIJTsFAQeAWwIsJ6RBIhDaJIIuQgMkwBBGpEDsEkVQx3FIJSDJUhJBNydtkiDBiZBBiZBgA"));
|
||||
}
|
||||
var IMAGEWIDTH = 176;
|
||||
var IMAGEHEIGHT = 109;
|
||||
|
||||
|
||||
Graphics.prototype.setFontDancingScript = function() {
|
||||
// Actual height 44 (44 - 1)
|
||||
var widths = atob("DBIhFB4bGRoeFhweDQ==");
|
||||
var font = atob("AAAAAAAAAAAAAAMAAAAAAAHgAAAAAAD4AAAAAAA+AAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAD8AAAAAAD+AAAAAAD/AAAAAAD/gAAAAAH/gAAAAAH/wAAAAAH/gAAAAAP/gAAAAAP/gAAAAAf/AAAAAAf/AAAAAA/+AAAAAA/+AAAAAB/+AAAAAB/8AAAAAB/8AAAAAA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8AAAAAf//4AAAAf///AAAAf///4AAAf////AAAf/8Af4AAP/gAA/AAP/AAADwAH+AAAAcAD+AAAAHAA+AAAABwAfAAAAAcAPAAAAAHADgAAAABwB4AAAAA8AcAAAAAOAHAAAAAHgBgAAAAHwAYAAAAD4AGAAAAD+ABwAAAD/AAcAAAD/gAHgAAH/wAA+AAP/wAAH+H//4AAB////4AAAP///4AAAA///4AAAAD//gAAAAAD8AAAAAAAAAAAGAAAAAAABwAAAAAAAcAAAAAAAHAAAAAAABwAAAAAAAcAAGAAAAPAADwAAA/wAA4AAB/8AAeAAP//AAPAD//7wAHwf//w8AB////gPAA///+ABwAf//4AAcAP/+AAADAH/wAAAAQB8AAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAB8AAAAAAAfAAAAAAAGwAAAAAABsAAAAAAAfAAAAAAAHwAAP4AAB4AAP/AAAeAAH/wAAHAAD/+AAD4AB+AgAB+AA8AAAA/gAOAAAAf8AHAAAAPvABwAAAPzwAYAAAH4eAGAAAH8HgBgAAD+B8AcAAD/AfAHAAH/AHwB4AH/gB8AP4//gAfAD///wAHwAf//wAB8AB//gAAeAAP/gAAHAAAAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAP+AAAAAAH/wAAAAAB/+AAAAAAcfgAAAAAEB8AB/AAAAPAA/4AAABwAf+AAAAcAP/gAAAHADwQAAABwAwABAAAcAcAAYAAHAHAAOAADwBgAHwAB4AYAD+AB+AHAB/4B/ABwB+///wAeB/P//4AH//h//8AA//4P/+AAH/4B/+AAA/8AH/AAAH8AAEAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAA4AAAAAAAeAAAAAAAPAAAAAAAHwAAAAAAD8AAAAAAB/AAAAAAA/wAAAAAAe8AAAAAAPPAAAAAAHjwAAAAADw8AAAAAB4PAAwAAA8DwP+AAAeA///wAAPAP//8AAHh////AAH3////wAD////AAAB///wAAAA//88AAAAf/gPAAAAf8ADgAAAHgAA4AAAAAAAMAAAAAAAAAfwAAAAAAP+AAAAAAH/wAAAAAB/+AAAAAA8PgAAAAwEA8AAAH8AAHAAAP/AABwAA//gAAcAD/4YAAHAH/gGAABwB/ABgAAcAfgAYAAPAD4AHAADwA+ABwAB4APgAeAB+AD4AH4B/AA+AA///wAPgAP//4AD4AB//8AB+AAP/+AAfgAB//AAHwAAH/AAB8AAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAf/4AAAAA///gAAAB///+AAAB////wAAB////+AAA//+B/gAA//8AD8AAf+OAAPAAP8HAABwAH8BgAAcAD8A4AAHAB+AOAABwAeADgAAcAPAA4AAHADgAOAADwBwADgAA8AcAA8AA+AGAAPgAfgBgAD+A/wAYAAf//4AGAAH//8ABwAA//+AAfgAH//AAD4AAf/AAAcAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAHAA/AAAABwB/wAwAA8B/8AeAAPB//AHwADx//gB8AA9//wAfAAP/4IAHwAD/wAAB8AB/wAAAPAB/gAAADwB/wAAAA8A/8AAAAPA/PAAAADw/DwAAAA8/A8AAAAP/AOAAAAD/ADgAAAB/gAwAAAAAAAAAAAAAAAAABAAAAAAAH/AAAAAAD/4AAAAAB//AAAAAA//4AAOAAfA+AAf8APgHwAP/wHgA8AH/+DwAHAD//48ABwA///eAAcAeAf/AAHAHAB/gABwBwAP4AA8AYAB/AAPAGAAf4AHgBgAP/AD4AcAHv8B8AHgD5///AA8H8H//gAP/+A//wAB/+AH/4AAP/AAf8AAA/AAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAAAAP/gAAeAAP/+AAPgAH//wAD8AD//+AAPAB///gAAwAfwD8AAMAPwAfAADADwADwAAwB4AAeAAcAcAAHgAHAHAAA4ADgBwAAOAB4AcAADAB8AHAAAwA/ABwAAcA/gAeAAGB/wAHwADh/4AA+AB//8AAP+D//8AAB////+AAAP///+AAAB///+AAAAP//8AAAAAf/4AAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAA4AAAAAAAeAAAAADAHgAAAAB4BwAAAAAeAIAAAAAHgAAAAAABwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
|
||||
var scale = 1; // size multiplier for this font
|
||||
g.setFontCustom(font, 46, widths, 50+(scale<<8)+(1<<16));
|
||||
}
|
||||
|
||||
// timeout used to update every minute
|
||||
var drawTimeout;
|
||||
|
||||
// schedule a draw for the next minute
|
||||
function queueDraw() {
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = setTimeout(function() {
|
||||
drawTimeout = undefined;
|
||||
draw();
|
||||
}, 60000 - (Date.now() % 60000));
|
||||
}
|
||||
|
||||
function draw() {
|
||||
var x = g.getWidth()/2;
|
||||
var y = 50;
|
||||
g.reset().clearRect(0,24,g.getWidth(),g.getHeight()-IMAGEHEIGHT);
|
||||
if (g.getWidth() == IMAGEWIDTH)
|
||||
g.drawImage(getImg(),0,g.getHeight()-IMAGEHEIGHT);
|
||||
else {
|
||||
let scale = g.getWidth()/IMAGEWIDTH;
|
||||
y *= scale;
|
||||
g.drawImage(getImg(),0,g.getHeight()-IMAGEHEIGHT*scale,{scale:scale});
|
||||
}
|
||||
|
||||
var date = new Date();
|
||||
var dateStr = require("locale").date(date);
|
||||
// draw time
|
||||
g.setFont("DancingScript").setFontAlign(0,0).setColor("#f00");
|
||||
g.drawString(date.getHours(), x,y);
|
||||
y += 43;
|
||||
g.drawString(date.getMinutes().toString().padStart(2,0), x,y);
|
||||
// draw date
|
||||
y += 22;
|
||||
g.setFontAlign(0,0).setFont("6x8");
|
||||
var p = g.getWidth()-60;
|
||||
g.clearRect(p,y-4,g.getWidth()-p,y+3); // clear the background
|
||||
g.drawString(dateStr,x,y);
|
||||
// queue draw in one minute
|
||||
queueDraw();
|
||||
}
|
||||
|
||||
// Stop updates when LCD is off, restart when on
|
||||
Bangle.on('lcdPower',on=>{
|
||||
if (on) {
|
||||
draw(); // draw immediately, queue redraw
|
||||
} else { // stop draw timer
|
||||
if (drawTimeout) clearTimeout(drawTimeout);
|
||||
drawTimeout = undefined;
|
||||
}
|
||||
});
|
||||
// set background colour
|
||||
g.setTheme({bg:"#0ff"});
|
||||
// Clear the screen once, at startup
|
||||
g.clear();
|
||||
// draw immediately at first, queue update
|
||||
draw();
|
||||
// Show launcher when middle button pressed
|
||||
Bangle.setUI("clock");
|
||||
// Load widgets
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.9 KiB |
|
|
@ -25,3 +25,4 @@
|
|||
0.21: Fix issue where a period of 1s recorded every 2s, 5s every 6s, and so on
|
||||
0.22: Ensure Bangle.setGPSPower uses 'gpsrec' as a tag
|
||||
0.23: Fix issue where tracks wouldn't record when running from OpenStMap if a period hadn't been set up first
|
||||
0.24: Better support for Bangle.js 2, avoid widget area for Graphs, smooth graphs more
|
||||
|
|
|
|||
|
|
@ -102,7 +102,8 @@ function getTrackInfo(fn) {
|
|||
var lfactor = Math.cos(minLat*Math.PI/180);
|
||||
var ylen = (maxLat-minLat);
|
||||
var xlen = (maxLong-minLong)* lfactor;
|
||||
var scale = xlen>ylen ? 200/xlen : 200/ylen;
|
||||
var screenSize = g.getHeight()-48; // 24 for widgets, plus a border
|
||||
var scale = xlen>ylen ? screenSize/xlen : screenSize/ylen;
|
||||
return {
|
||||
fn : fn,
|
||||
filename : filename,
|
||||
|
|
@ -110,6 +111,7 @@ function getTrackInfo(fn) {
|
|||
records : nl,
|
||||
minLat : minLat, maxLat : maxLat,
|
||||
minLong : minLong, maxLong : maxLong,
|
||||
lat : (minLat+maxLat)/2, lon : (minLong+maxLong)/2,
|
||||
lfactor : lfactor,
|
||||
scale : scale,
|
||||
duration : Math.round(duration/1000)
|
||||
|
|
@ -180,16 +182,18 @@ function plotTrack(info) {
|
|||
getMapXY = osm.latLonToXY.bind(osm);
|
||||
} else {
|
||||
getMapXY = function(lat, lon) { "ram"
|
||||
var ix = 30 + Math.round((long - info.minLong)*info.lfactor*info.scale);
|
||||
var iy = 210 - Math.round((lat - info.minLat)*info.scale);
|
||||
return {x:ix, y:iy};
|
||||
return {x:cx + Math.round((long - info.lon)*info.lfactor*info.scale),
|
||||
y:cy + Math.round((info.lat - lat)*info.scale)};
|
||||
}
|
||||
}
|
||||
|
||||
E.showMenu(); // remove menu
|
||||
E.showMessage("Drawing...","GPS Track "+info.fn);
|
||||
g.flip(); // on buffered screens, draw a not saying we're busy
|
||||
g.clear(1);
|
||||
var s = require("Storage");
|
||||
var cx = g.getWidth()/2;
|
||||
var cy = g.getHeight()/2;
|
||||
var cy = 24 + (g.getHeight()-24)/2;
|
||||
g.setColor(1,0.5,0.5);
|
||||
g.setFont("Vector",16);
|
||||
g.drawString("Track"+info.fn.toString()+" - Loading",10,220);
|
||||
|
|
@ -203,8 +207,8 @@ function plotTrack(info) {
|
|||
g.drawString("N",2,40);
|
||||
g.setColor(1,1,1);
|
||||
} else {
|
||||
osm.lat = (info.minLat+info.maxLat)/2;
|
||||
osm.lon = (info.minLong+info.maxLong)/2;
|
||||
osm.lat = info.lat;
|
||||
osm.lon = info.lon;
|
||||
osm.draw();
|
||||
g.setColor(0, 0, 0);
|
||||
}
|
||||
|
|
@ -251,7 +255,8 @@ function plotTrack(info) {
|
|||
g.drawString("Back",230,200);
|
||||
setWatch(function() {
|
||||
viewTrack(info.fn, info);
|
||||
}, BTN3);
|
||||
}, global.BTN3||BTN1);
|
||||
Bangle.drawWidgets();
|
||||
g.flip();
|
||||
}
|
||||
|
||||
|
|
@ -260,8 +265,8 @@ function plotGraph(info, style) {
|
|||
E.showMenu(); // remove menu
|
||||
E.showMessage("Calculating...","GPS Track "+info.fn);
|
||||
var filename = getFN(info.fn);
|
||||
var infn = new Float32Array(200);
|
||||
var infc = new Uint16Array(200);
|
||||
var infn = new Float32Array(80);
|
||||
var infc = new Uint16Array(80);
|
||||
var title;
|
||||
var lt = 0; // last time
|
||||
var tn = 0; // count for each time period
|
||||
|
|
@ -278,7 +283,7 @@ function plotGraph(info, style) {
|
|||
title = "Altitude (m)";
|
||||
while(l!==undefined) {
|
||||
++nl;c=l.split(",");
|
||||
i = Math.round(200*(c[0]/1000 - strt)/dur);
|
||||
i = Math.round(80*(c[0]/1000 - strt)/dur);
|
||||
infn[i]+=+c[3];
|
||||
infc[i]++;
|
||||
l = f.readLine(f);
|
||||
|
|
@ -289,7 +294,7 @@ function plotGraph(info, style) {
|
|||
var t,dx,dy,d,lt = c[0]/1000;
|
||||
while(l!==undefined) {
|
||||
++nl;c=l.split(",");
|
||||
i = Math.round(200*(c[0]/1000 - strt)/dur);
|
||||
i = Math.round(80*(c[0]/1000 - strt)/dur);
|
||||
t = c[0]/1000;
|
||||
p = Bangle.project({lat:c[1],lon:c[2]});
|
||||
dx = p.x-lp.x;
|
||||
|
|
@ -320,9 +325,9 @@ function plotGraph(info, style) {
|
|||
// draw
|
||||
g.clear(1).setFont("6x8",1);
|
||||
var r = require("graph").drawLine(g, infn, {
|
||||
x:4,y:0,
|
||||
x:4,y:24,
|
||||
width: g.getWidth()-24,
|
||||
height: g.getHeight()-8,
|
||||
height: g.getHeight()-(24+8),
|
||||
axes : true,
|
||||
gridy : grid,
|
||||
gridx : 50,
|
||||
|
|
@ -334,7 +339,7 @@ function plotGraph(info, style) {
|
|||
g.drawString("Back",230,200);
|
||||
setWatch(function() {
|
||||
viewTrack(info.fn, info);
|
||||
}, BTN3);
|
||||
}, global.BTN3||BTN1);
|
||||
g.flip();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ function redraw() {
|
|||
m.draw();
|
||||
drawMarker();
|
||||
if (WIDGETS["gpsrec"] && WIDGETS["gpsrec"].plotTrack) {
|
||||
g.flip(); // force immediate draw on double-buffered screens - track will update later
|
||||
g.setColor(0.75,0.2,0);
|
||||
WIDGETS["gpsrec"].plotTrack(m);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
0.01: New App!
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
This app will allow you to keep scores for most kinds of sports.
|
||||
|
||||
# Keybinds
|
||||
To correct a falsely awarded point simply open and close the menu within .5 seconds. This will put the app into correction mode (indicated by the `R`).
|
||||
In this mode any score increments will be decrements. To move back a set, reduce both players scores to 0, then decrement one of the scores once again.
|
||||
|
||||
## Bangle.js 1
|
||||
| Keybinding | Description |
|
||||
|---------------------|------------------------------|
|
||||
| `BTN1` | Increment left player score |
|
||||
| `BTN3` | Increment right player score |
|
||||
| `BTN2` | Menu |
|
||||
| touch on left side | Scroll up |
|
||||
| touch on right side | Scroll down |
|
||||
|
||||
## Bangle.js 2
|
||||
| Keybinding | Description |
|
||||
|-------------------------------------|------------------------------|
|
||||
| `BTN1` | Menu |
|
||||
| touch on left side of divider line | Increment left player score |
|
||||
| touch on right side of divider line | Increment right player score |
|
||||
|
||||
# Settings
|
||||
| Setting | Description |
|
||||
|------------------------------------|------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `Presets` | Enable a preset for one of the configured sports |
|
||||
| `Sets to win` | How many sets a player has to win before the match is won (Maximum sets: this*2-1) |
|
||||
| `Sets per page` | How many sets should be shown in the app. Further sets will be available by scrolling (ignored if higher than `Sets to win`) |
|
||||
| `Score to win` | What score ends a given set |
|
||||
| `2-point lead` | Does winning a set require a two-point lead |
|
||||
| `Maximum score?` | Should there be a maximum score, at which point the two-point lead rule falls away |
|
||||
| `Maximum score` | At which score should the two-point lead rule fall away (ignored if lower than Sets to win) |
|
||||
| `Tennis scoring` | If enabled, each point in a set will require a full tennis game |
|
||||
| `TB sets?` | Should sets that have reached `(maxScore-1):(maxScore-1)` be decided with a tiebreak |
|
||||
| All other options starting with TB | Equivalent to option with same name but applied to tiebreaks |
|
||||
|
||||
The settings can be changed both from within the app by simply pressing `BTN2` (`BTN1` on Bangle.js 2) or in the `App Settings` in the `Settings` app.
|
||||
|
||||
If changes are made to the settings from within the app, a new match will automatically be initialized upon exiting the settings.
|
||||
|
||||
By default the settings will reflect Badminton rules.
|
||||
|
||||
## Tennis Scoring
|
||||
While tennis scoring is available, correcting in this mode will reset to the beginning of the current game.
|
||||
Resetting at the beginning of the current game will reset to the beginning of the previous game, leaving the user to fast-forward to the correct score once again.
|
||||
|
||||
This might get changed at some point.
|
||||
|
|
@ -0,0 +1 @@
|
|||
require("heatshrink").decompress(atob("mEwxH+AH4A/AH4A/AE2IxAKSCigv/F/4vS44ABB4IECAAoKECgM7AAIJBAgQAFBQguJF6HHEhAvKGAwvy4wPB4wuGBQwdCmgJBmguGBQwvJ0ulF5AKFEgeCwQvIBQqPJ4wuHBQ4lEFw4KHF5IAQFJAALF+vNACYv/F/4v053P64vPxPXAAOJF6vP6wbCF52zCQQAB2YvTDIgvOLoWzMJQvOL6JeCss7spgIF5nPMQgvNCAQEBr4FEd6YvVAowv/F/4v4d9WzCANlndlAgOzF82JFQWJGgWJF8xgDAAReGF8RhDLo4vRABQiHABgv/F/4v/F4owTCgIuZAH4A/AH4A/ADgA=="))
|
||||
|
|
@ -0,0 +1,478 @@
|
|||
require('Font5x9Numeric7Seg').add(Graphics);
|
||||
require('Font7x11Numeric7Seg').add(Graphics);
|
||||
require('FontTeletext5x9Ascii').add(Graphics);
|
||||
|
||||
let settingsMenu = eval(require('Storage').read('score.settings.js'));
|
||||
let settings = settingsMenu(null, null, true);
|
||||
|
||||
let tennisScores = ['00','15','30','40','DC','AD'];
|
||||
|
||||
let scores = null;
|
||||
let tScores = null;
|
||||
let cSet = null;
|
||||
|
||||
let firstShownSet = null;
|
||||
|
||||
let settingsMenuOpened = null;
|
||||
let correctionMode = false;
|
||||
|
||||
let w = g.getWidth();
|
||||
let h = g.getHeight();
|
||||
|
||||
let isBangle1 = process.env.BOARD === 'BANGLEJS';
|
||||
|
||||
function getXCoord(func) {
|
||||
let offset = 40;
|
||||
return func(w-offset)+offset;
|
||||
}
|
||||
|
||||
function getSecondsTime() {
|
||||
return Math.floor(getTime() * 1000);
|
||||
}
|
||||
|
||||
function setupDisplay() {
|
||||
// make sure LCD on Bangle.js 1 stays on
|
||||
if (isBangle1) {
|
||||
if (settings.keepDisplayOn) {
|
||||
Bangle.setLCDTimeout(0);
|
||||
Bangle.setLCDPower(true);
|
||||
} else {
|
||||
Bangle.setLCDTimeout(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setupInputWatchers(init) {
|
||||
Bangle.setUI('updown', v => {
|
||||
if (v) {
|
||||
if (isBangle1) {
|
||||
let i = settings.mirrorScoreButtons ? v : v * -1;
|
||||
handleInput(Math.floor((i+2)/2));
|
||||
} else {
|
||||
handleInput(Math.floor((v+2)/2)+3);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (init) {
|
||||
setWatch(() => handleInput(2), isBangle1 ? BTN2 : BTN, { repeat: true });
|
||||
Bangle.on('touch', (b, e) => {
|
||||
if (isBangle1) {
|
||||
if (b === 1) {
|
||||
handleInput(3);
|
||||
} else {
|
||||
handleInput(4);
|
||||
}
|
||||
} else {
|
||||
if (e.x < getXCoord(w => w/2)) {
|
||||
handleInput(0);
|
||||
} else {
|
||||
handleInput(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setupMatch() {
|
||||
scores = [];
|
||||
for (let s = 0; s < sets(); s++) {
|
||||
scores.push([0,0,null,0,0]);
|
||||
}
|
||||
scores.push([0,0,null,0,0]);
|
||||
|
||||
if (settings.enableTennisScoring) {
|
||||
tScores = [0,0];
|
||||
} else {
|
||||
tScores = null;
|
||||
}
|
||||
|
||||
scores[0][2] = getSecondsTime();
|
||||
|
||||
cSet = 0;
|
||||
setFirstShownSet();
|
||||
|
||||
correctionMode = false;
|
||||
}
|
||||
|
||||
function showSettingsMenu() {
|
||||
settingsMenuOpened = getSecondsTime();
|
||||
l = null;
|
||||
settingsMenu(function (s, reset) {
|
||||
E.showMenu();
|
||||
|
||||
settings = s;
|
||||
|
||||
if (reset) {
|
||||
setupMatch();
|
||||
} else if (getSecondsTime() - settingsMenuOpened < 500 || correctionMode) {
|
||||
correctionMode = !correctionMode;
|
||||
}
|
||||
|
||||
settingsMenuOpened = null;
|
||||
|
||||
draw();
|
||||
|
||||
setupDisplay();
|
||||
setupInputWatchers();
|
||||
}, function (msg) {
|
||||
switch (msg) {
|
||||
case 'end_set':
|
||||
updateCurrentSet(1);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function maxScore() {
|
||||
return Math.max(settings.maxScore, settings.winScore);
|
||||
}
|
||||
|
||||
function tiebreakMaxScore() {
|
||||
return Math.max(settings.maxScoreTiebreakMaxScore, settings.maxScoreTiebreakWinScore);
|
||||
}
|
||||
|
||||
function setsPerPage() {
|
||||
return Math.min(settings.setsPerPage, sets());
|
||||
}
|
||||
|
||||
function sets() {
|
||||
return settings.winSets * 2 - 1;
|
||||
}
|
||||
|
||||
function currentSet() {
|
||||
return matchEnded() ? cSet - 1 : cSet;
|
||||
}
|
||||
|
||||
function shouldTiebreak() {
|
||||
return settings.enableMaxScoreTiebreak &&
|
||||
scores[cSet][0] + scores[cSet][1] === (maxScore() - 1) * 2;
|
||||
}
|
||||
|
||||
function formatNumber(num, length) {
|
||||
return num.toString().padStart(length ? length : 2,"0");
|
||||
}
|
||||
|
||||
function formatDuration(duration) {
|
||||
let durS = Math.floor(duration / 1000);
|
||||
let durM = Math.floor(durS / 60);
|
||||
let durH = Math.floor(durM / 60);
|
||||
durS = durS - durM * 60;
|
||||
durM = durM - durH * 60;
|
||||
|
||||
durS = formatNumber(durS);
|
||||
durM = formatNumber(durM);
|
||||
durH = formatNumber(durH);
|
||||
|
||||
let dur = null;
|
||||
if (durH > 0) {
|
||||
dur = durH + ':' + durM;
|
||||
} else {
|
||||
dur = durM + ':' + durS;
|
||||
}
|
||||
|
||||
return dur;
|
||||
}
|
||||
|
||||
function tiebreakWon(set, player) {
|
||||
let pScore = scores[set][3+player];
|
||||
let p2Score = scores[set][3+~~!player];
|
||||
|
||||
let winScoreReached = pScore >= settings.maxScoreTiebreakWinScore;
|
||||
let isTwoAhead = !settings.maxScoreTiebreakEnableTwoAhead || pScore - p2Score >= 2;
|
||||
let reachedMaxScore = settings.maxScoreTiebreakEnableMaxScore && pScore >= tiebreakMaxScore();
|
||||
|
||||
return reachedMaxScore || (winScoreReached && isTwoAhead);
|
||||
}
|
||||
|
||||
function setWon(set, player) {
|
||||
let pScore = scores[set][player];
|
||||
let p2Score = scores[set][~~!player];
|
||||
|
||||
let winScoreReached = pScore >= settings.winScore;
|
||||
let isTwoAhead = !settings.enableTwoAhead || pScore - p2Score >= 2;
|
||||
let tiebreakW = tiebreakWon(set, player);
|
||||
let reachedMaxScore = settings.enableMaxScore && pScore >= maxScore();
|
||||
let manuallyEndedWon = cSet > set ? pScore > p2Score : false;
|
||||
|
||||
return (
|
||||
(settings.enableMaxScoreTiebreak ? tiebreakW : reachedMaxScore) ||
|
||||
(winScoreReached && isTwoAhead) ||
|
||||
manuallyEndedWon
|
||||
);
|
||||
}
|
||||
|
||||
function setEnded(set) {
|
||||
return setWon(set, 0) || setWon(set, 1);
|
||||
}
|
||||
|
||||
function setsWon(player) {
|
||||
return Array(sets()).fill(0).map((_, s) => ~~setWon(s, player)).reduce((a,v) => a+v, 0);
|
||||
}
|
||||
|
||||
function matchWon(player) {
|
||||
return setsWon(player) >= settings.winSets;
|
||||
}
|
||||
|
||||
function matchEnded() {
|
||||
return (matchWon(0) || matchWon(1)) && cSet > (setsWon(0) + setsWon(1) - 1);
|
||||
}
|
||||
|
||||
function matchScore(player) {
|
||||
return scores.reduce((acc, val) => acc += val[player], 0);
|
||||
}
|
||||
|
||||
function setFirstShownSet() {
|
||||
firstShownSet = Math.max(0, currentSet() - setsPerPage() + 1);
|
||||
}
|
||||
|
||||
function updateCurrentSet(val) {
|
||||
if (val > 0) {
|
||||
cSet++;
|
||||
} else if (val < 0) {
|
||||
cSet--;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
setFirstShownSet();
|
||||
|
||||
if (val > 0) {
|
||||
scores[cSet][2] = getSecondsTime();
|
||||
|
||||
if (matchEnded()) {
|
||||
firstShownSet = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function score(player) {
|
||||
if (!matchEnded()) {
|
||||
setFirstShownSet();
|
||||
}
|
||||
|
||||
if (correctionMode) {
|
||||
if (
|
||||
scores[cSet][0] === 0 && scores[cSet][1] === 0 &&
|
||||
scores[cSet][3] === 0 && scores[cSet][4] === 0 &&
|
||||
cSet > 0
|
||||
) {
|
||||
updateCurrentSet(-1);
|
||||
}
|
||||
|
||||
if (scores[cSet][3] > 0 || scores[cSet][4] > 0) {
|
||||
if (scores[cSet][3+player] > 0) {
|
||||
scores[cSet][3+player]--;
|
||||
}
|
||||
} else if (scores[cSet][player] > 0) {
|
||||
if (
|
||||
!settings.enableTennisScoring ||
|
||||
(tScores[player] === 0 && tScores[~~!player] === 0)
|
||||
) {
|
||||
scores[cSet][player]--;
|
||||
} else {
|
||||
tScores[player] = 0;
|
||||
tScores[~~!player] = 0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (matchEnded()) return;
|
||||
|
||||
if (shouldTiebreak()) {
|
||||
scores[cSet][3+player]++;
|
||||
} else if (settings.enableTennisScoring) {
|
||||
if (tScores[player] === 4 && tScores[~~!player] === 5) { // DC : AD
|
||||
tScores[~~!player]--;
|
||||
} else if (tScores[player] === 2 && tScores[~~!player] === 3) { // 30 : 40
|
||||
tScores[0] = 4;
|
||||
tScores[1] = 4;
|
||||
} else if (tScores[player] === 3 || tScores[player] === 5) { // 40 / AD
|
||||
tScores[0] = 0;
|
||||
tScores[1] = 0;
|
||||
scores[cSet][player]++;
|
||||
} else {
|
||||
tScores[player]++;
|
||||
}
|
||||
} else {
|
||||
scores[cSet][player]++;
|
||||
}
|
||||
|
||||
if (setEnded(cSet) && cSet < sets()) {
|
||||
if (shouldTiebreak()) {
|
||||
scores[cSet][player]++;
|
||||
}
|
||||
updateCurrentSet(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleInput(button) {
|
||||
if (settingsMenuOpened) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (button) {
|
||||
case 0:
|
||||
case 1:
|
||||
score(button);
|
||||
break;
|
||||
case 2:
|
||||
showSettingsMenu();
|
||||
return;
|
||||
case 3:
|
||||
case 4:
|
||||
let hLimit = currentSet() - setsPerPage() + 1;
|
||||
let lLimit = 0;
|
||||
let val = (button * 2 - 7);
|
||||
firstShownSet += val;
|
||||
if (firstShownSet > hLimit) firstShownSet = hLimit;
|
||||
if (firstShownSet < lLimit) firstShownSet = lLimit;
|
||||
break;
|
||||
}
|
||||
|
||||
draw();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
g.setFontAlign(0,0);
|
||||
g.clear();
|
||||
|
||||
for (let p = 0; p < 2; p++) {
|
||||
if (matchWon(p)) {
|
||||
g.setFontAlign(0,0);
|
||||
g.setFont('Teletext5x9Ascii',2);
|
||||
g.drawString(
|
||||
"WINNER",
|
||||
getXCoord(w => p === 0 ? w/4 : w/4*3),
|
||||
15
|
||||
);
|
||||
} else if (matchEnded()) {
|
||||
g.setFontAlign(1,0);
|
||||
|
||||
g.setFont('Teletext5x9Ascii',1);
|
||||
g.drawString(
|
||||
(currentSet()+1) + ' set' + (currentSet() > 0 ? 's' : ''),
|
||||
40,
|
||||
8
|
||||
);
|
||||
|
||||
let dur1 = formatDuration(scores[cSet][2] - scores[0][2]);
|
||||
g.setFont('5x9Numeric7Seg',1);
|
||||
g.drawString(
|
||||
dur1,
|
||||
40,
|
||||
18
|
||||
);
|
||||
}
|
||||
|
||||
g.setFontAlign(p === 0 ? -1 : 1,1);
|
||||
g.setFont('5x9Numeric7Seg',2);
|
||||
g.drawString(
|
||||
setsWon(p),
|
||||
getXCoord(w => p === 0 ? 5 : w-3),
|
||||
h-5
|
||||
);
|
||||
|
||||
if (!settings.enableTennisScoring) {
|
||||
g.setFontAlign(p === 0 ? 1 : -1,1);
|
||||
g.setFont('7x11Numeric7Seg',2);
|
||||
g.drawString(
|
||||
formatNumber(matchScore(p), 3),
|
||||
getXCoord(w => p === 0 ? w/2 - 3 : w/2 + 6),
|
||||
h-5
|
||||
);
|
||||
}
|
||||
}
|
||||
g.setFontAlign(0,0);
|
||||
|
||||
if (correctionMode) {
|
||||
g.setFont('Teletext5x9Ascii',2);
|
||||
g.drawString(
|
||||
"R",
|
||||
getXCoord(w => w/2),
|
||||
h-10
|
||||
);
|
||||
}
|
||||
|
||||
let lastShownSet = Math.min(
|
||||
sets(),
|
||||
currentSet() + 1,
|
||||
firstShownSet+setsPerPage()
|
||||
);
|
||||
let setsOnCurrentPage = Math.min(
|
||||
sets(),
|
||||
setsPerPage()
|
||||
);
|
||||
for (let set = firstShownSet; set < lastShownSet; set++) {
|
||||
if (set < 0) continue;
|
||||
|
||||
let y = (h-15)/(setsOnCurrentPage+1)*(set-firstShownSet+1)+5;
|
||||
|
||||
g.setFontAlign(-1,0);
|
||||
g.setFont('7x11Numeric7Seg',1);
|
||||
g.drawString(set+1, 5, y-10);
|
||||
if (scores[set+1][2] != null) {
|
||||
let dur2 = formatDuration(scores[set+1][2] - scores[set][2]);
|
||||
g.drawString(dur2, 5, y+10);
|
||||
}
|
||||
|
||||
for (let p = 0; p < 2; p++) {
|
||||
if (!setWon(set, p === 0 ? 1 : 0) || matchEnded()) {
|
||||
let bigNumX = getXCoord(w => p === 0 ? w/4-12 : w/4*3+15);
|
||||
let smallNumX = getXCoord(w => p === 0 ? w/2-2 : w/2+3);
|
||||
|
||||
if (settings.enableTennisScoring && set === cSet && !shouldTiebreak()) {
|
||||
g.setFontAlign(0,0);
|
||||
g.setFont('7x11Numeric7Seg',3);
|
||||
g.drawString(
|
||||
formatNumber(tennisScores[tScores[p]]),
|
||||
bigNumX,
|
||||
y
|
||||
);
|
||||
} else if (shouldTiebreak() && set === cSet) {
|
||||
g.setFontAlign(0,0);
|
||||
g.setFont('7x11Numeric7Seg',3);
|
||||
g.drawString(
|
||||
formatNumber(scores[set][3+p], 3),
|
||||
bigNumX,
|
||||
y
|
||||
);
|
||||
} else {
|
||||
g.setFontAlign(0,0);
|
||||
g.setFont('7x11Numeric7Seg',3);
|
||||
g.drawString(
|
||||
formatNumber(scores[set][p]),
|
||||
bigNumX,
|
||||
y
|
||||
);
|
||||
}
|
||||
|
||||
if ((shouldTiebreak() || settings.enableTennisScoring) && set === cSet) {
|
||||
g.setFontAlign(p === 0 ? 1 : -1,0);
|
||||
g.setFont('7x11Numeric7Seg',1);
|
||||
g.drawString(
|
||||
formatNumber(scores[set][p]),
|
||||
smallNumX,
|
||||
y
|
||||
);
|
||||
} else if ((scores[set][3] !== 0 || scores[set][4] !== 0) && set !== cSet) {
|
||||
g.setFontAlign(p === 0 ? 1 : -1,0);
|
||||
g.setFont('7x11Numeric7Seg',1);
|
||||
g.drawString(
|
||||
formatNumber(scores[set][3+p], 3),
|
||||
smallNumX,
|
||||
y
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draw separator
|
||||
g.drawLine(getXCoord(w => w/2), 20, getXCoord(w => w/2), h-25);
|
||||
|
||||
g.flip();
|
||||
}
|
||||
|
||||
setupDisplay();
|
||||
setupInputWatchers(true);
|
||||
setupMatch();
|
||||
draw();
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 897 B |
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"Badminton": {
|
||||
"winScore": 21,
|
||||
"enableTwoAhead": true,
|
||||
"enableMaxScore": true,
|
||||
"maxScore": 30
|
||||
},
|
||||
"Tennis": {
|
||||
"winScore": 6,
|
||||
"enableTwoAhead": true,
|
||||
"enableMaxScore": true,
|
||||
"maxScore": 7,
|
||||
"enableMaxScoreTiebreak": true,
|
||||
"maxScoreTiebreakWinScore": 7,
|
||||
"maxScoreTiebreakEnableTwoAhead": true,
|
||||
"maxScoreTiebreakEnableMaxScore": false,
|
||||
"enableTennisScoring": true
|
||||
},
|
||||
"Soccer": {
|
||||
"winSets": 1,
|
||||
"winScore": 9999,
|
||||
"enableTwoAhead": false,
|
||||
"enableMaxScore": false
|
||||
},
|
||||
"Table Tennis": {
|
||||
"winScore": 11,
|
||||
"enableTwoAhead": true,
|
||||
"enableMaxScore": false
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
(function () {
|
||||
return (function (back, inApp, ret) {
|
||||
const isBangle1 = process.env.BOARD === 'BANGLEJS'
|
||||
|
||||
function fillSettingsWithDefaults(settings) {
|
||||
if (isBangle1) {
|
||||
if (settings.mirrorScoreButtons == null) {
|
||||
settings.mirrorScoreButtons = false;
|
||||
}
|
||||
if (settings.keepDisplayOn == null) {
|
||||
settings.keepDisplayOn = true;
|
||||
}
|
||||
}
|
||||
if (settings.winSets == null) {
|
||||
settings.winSets = 2;
|
||||
}
|
||||
if (settings.setsPerPage == null) {
|
||||
settings.setsPerPage = 5;
|
||||
}
|
||||
if (settings.winScore == null) {
|
||||
settings.winScore = 21;
|
||||
}
|
||||
if (settings.enableTwoAhead == null) {
|
||||
settings.enableTwoAhead = true;
|
||||
}
|
||||
if (settings.enableMaxScore == null) {
|
||||
settings.enableMaxScore = true;
|
||||
}
|
||||
if (settings.maxScore == null) {
|
||||
settings.maxScore = 30;
|
||||
}
|
||||
if (settings.enableTennisScoring == null) {
|
||||
settings.enableTennisScoring = false;
|
||||
}
|
||||
|
||||
if (settings.enableMaxScoreTiebreak == null) {
|
||||
settings.enableMaxScoreTiebreak = false;
|
||||
}
|
||||
if (settings.maxScoreTiebreakWinScore == null) {
|
||||
settings.maxScoreTiebreakWinScore = 6;
|
||||
}
|
||||
if (settings.maxScoreTiebreakEnableTwoAhead == null) {
|
||||
settings.maxScoreTiebreakEnableTwoAhead = true;
|
||||
}
|
||||
if (settings.maxScoreTiebreakEnableMaxScore == null) {
|
||||
settings.maxScoreTiebreakEnableMaxScore = false;
|
||||
}
|
||||
if (settings.maxScoreTiebreakMaxScore == null) {
|
||||
settings.maxScoreTiebreakMaxScore = 15;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
const fileName = 'score.json';
|
||||
let settings = require('Storage').readJSON(fileName, 1) || {};
|
||||
const offon = ['No', 'Yes'];
|
||||
|
||||
let presetsFileName = 'score.presets.json';
|
||||
let presets = require('Storage').readJSON(presetsFileName);
|
||||
let presetNames = Object.keys(presets);
|
||||
|
||||
let changed = false;
|
||||
|
||||
function save(settings) {
|
||||
require('Storage').writeJSON(fileName, settings);
|
||||
}
|
||||
|
||||
function setAndSave(key, value, notChanged) {
|
||||
if (!notChanged) {
|
||||
changed = true;
|
||||
}
|
||||
settings[key] = value;
|
||||
if (key === 'winScore' && settings.maxScore < value) {
|
||||
settings.maxScore = value;
|
||||
}
|
||||
save(settings);
|
||||
}
|
||||
|
||||
settings = fillSettingsWithDefaults(settings);
|
||||
|
||||
if (ret) {
|
||||
return settings;
|
||||
}
|
||||
|
||||
const presetMenu = function (appMenuBack) {
|
||||
let ret = function (changed) { E.showMenu(appMenu(appMenuBack, changed ? 2 : null)); };
|
||||
let m = {
|
||||
'': {'title': 'Score Presets'},
|
||||
'< Back': ret,
|
||||
};
|
||||
for (let i = 0; i < presetNames.length; i++) {
|
||||
m[presetNames[i]] = (function (i) {
|
||||
return function() {
|
||||
changed = true;
|
||||
let mirrorScoreButtons = settings.mirrorScoreButtons;
|
||||
let keepDisplayOn = settings.keepDisplayOn;
|
||||
|
||||
settings = fillSettingsWithDefaults(presets[presetNames[i]]);
|
||||
|
||||
settings.mirrorScoreButtons = mirrorScoreButtons;
|
||||
settings.keepDisplayOn = keepDisplayOn;
|
||||
save(settings);
|
||||
ret(true);
|
||||
};
|
||||
})(i);
|
||||
}
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
const appMenu = function (back, selected) {
|
||||
let m = {};
|
||||
|
||||
m[''] = {'title': 'Score Settings'};
|
||||
if (selected != null) {
|
||||
m[''].selected = selected;
|
||||
}
|
||||
m['< Back'] = function () { back(settings, changed); };
|
||||
m['Presets'] = function () { E.showMenu(presetMenu(back)); };
|
||||
if (isBangle1) {
|
||||
m['Mirror Buttons'] = {
|
||||
value: settings.mirrorScoreButtons,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('mirrorScoreButtons', m, true),
|
||||
};
|
||||
m['Keep display on'] = {
|
||||
value: settings.keepDisplayOn,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('keepDisplayOn', m, true),
|
||||
}
|
||||
}
|
||||
m['Sets to win'] = {
|
||||
value: settings.winSets,
|
||||
min:1,
|
||||
onchange: m => setAndSave('winSets', m),
|
||||
};
|
||||
m['Sets per page'] = {
|
||||
value: settings.setsPerPage,
|
||||
min:1,
|
||||
max:5,
|
||||
onchange: m => setAndSave('setsPerPage', m),
|
||||
};
|
||||
m['Score to win'] = {
|
||||
value: settings.winScore,
|
||||
min:1,
|
||||
max: 999,
|
||||
onchange: m => setAndSave('winScore', m),
|
||||
};
|
||||
m['2-point lead'] = {
|
||||
value: settings.enableTwoAhead,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('enableTwoAhead', m),
|
||||
};
|
||||
m['Maximum score?'] = {
|
||||
value: settings.enableMaxScore,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('enableMaxScore', m),
|
||||
};
|
||||
m['Maximum score'] = {
|
||||
value: settings.maxScore,
|
||||
min: 1,
|
||||
max: 999,
|
||||
onchange: m => setAndSave('maxScore', m),
|
||||
};
|
||||
m['Tennis scoring'] = {
|
||||
value: settings.enableTennisScoring,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('enableTennisScoring', m),
|
||||
};
|
||||
m['TB sets?'] = {
|
||||
value: settings.enableMaxScoreTiebreak,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('enableMaxScoreTiebreak', m),
|
||||
};
|
||||
m['TB Score to win'] = {
|
||||
value: settings.maxScoreTiebreakWinScore,
|
||||
onchange: m => setAndSave('maxScoreTiebreakWinScore', m),
|
||||
};
|
||||
m['TB 2-point lead'] = {
|
||||
value: settings.maxScoreTiebreakEnableTwoAhead,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('maxScoreTiebreakEnableTwoAhead', m),
|
||||
};
|
||||
m['TB max score?'] = {
|
||||
value: settings.maxScoreTiebreakEnableMaxScore,
|
||||
format: m => offon[~~m],
|
||||
onchange: m => setAndSave('maxScoreTiebreakEnableMaxScore', m),
|
||||
};
|
||||
m['TB max score'] = {
|
||||
value: settings.maxScoreTiebreakMaxScore,
|
||||
onchange: m => setAndSave('maxScoreTiebreakMaxScore', m),
|
||||
};
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
const inAppMenu = function () {
|
||||
let m = {
|
||||
'': {'title': 'Score Menu'},
|
||||
'< Back': function () { back(settings, changed); },
|
||||
'Reset match': function () { back(settings, true); },
|
||||
'End current set': function () { inApp('end_set'); back(settings, changed); },
|
||||
'Configuration': function () { E.showMenu(appMenu(function () {
|
||||
E.showMenu(inAppMenu());
|
||||
})); },
|
||||
};
|
||||
|
||||
return m;
|
||||
};
|
||||
|
||||
if (inApp != null) {
|
||||
E.showMenu(inAppMenu());
|
||||
} else {
|
||||
E.showMenu(appMenu(back));
|
||||
}
|
||||
|
||||
});
|
||||
})();
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
var DateFormatter = require("slidingtext.dtfmt.js");
|
||||
|
||||
const germanNumberStr = [ ["ZERO",""], // 0
|
||||
const germanNumberStr = [ ["NULL",""], // 0
|
||||
["EINS",""], // 1
|
||||
["ZWEI",""], //2
|
||||
["DREI",''], //3
|
||||
["VIER",''], //4
|
||||
["FÜNF",''], //5
|
||||
["SECHS",''], //6
|
||||
["SEIBEN",''], //7
|
||||
["SIEBEN",''], //7
|
||||
["ACHT",''], //8
|
||||
["NUEN",''], // 9,
|
||||
["NEUN",''], // 9,
|
||||
["ZEHN",''], // 10
|
||||
["ELF",''], // 11,
|
||||
["ZWÖLF",''], // 12
|
||||
|
|
@ -22,7 +22,7 @@ const germanNumberStr = [ ["ZERO",""], // 0
|
|||
["NEUN",'ZEHN'], // 19
|
||||
];
|
||||
|
||||
const germanTensStr = ["ZERO",//0
|
||||
const germanTensStr = ["NULL",//0
|
||||
"ZEHN",//10
|
||||
"ZWANZIG",//20
|
||||
"DREIßIG",//30
|
||||
|
|
@ -38,7 +38,7 @@ const germanUnit = ["",//0
|
|||
"VIERUND", //4
|
||||
"FÜNFUND", //5
|
||||
"SECHSUND", //6
|
||||
"SEIBENUND", //7
|
||||
"SIEBENUND", //7
|
||||
"ACHTUND", //8
|
||||
"NEUNUND" //9
|
||||
]
|
||||
|
|
@ -91,4 +91,4 @@ class GermanDateFormatter extends DateFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = GermanDateFormatter;
|
||||
module.exports = GermanDateFormatter;
|
||||
|
|
|
|||
|
|
@ -3,3 +3,4 @@
|
|||
0.03: Use offscreen buffer (not doublebuffer)
|
||||
Use 'locale' to get internationalised speed
|
||||
0.04: Start GPS after loading app, just in case widgets affect it (#449)
|
||||
0.05: Use Layout lib for Bangle.js 2 compatibility
|
||||
|
|
|
|||
|
|
@ -1,33 +1,61 @@
|
|||
var buf = Graphics.createArrayBuffer(240,120,1,{msb:true});
|
||||
var lastFix = {fix:0,satellites:0};
|
||||
var Layout = require("Layout");
|
||||
var layout;
|
||||
|
||||
var lastFix = {fix:-1,satellites:0};
|
||||
|
||||
function speedoImage() {
|
||||
return require("heatshrink").decompress(atob("kkdxH+ABteAAwWOECImZDQ2CAQglUD4us2fX68ymQDB1omFESWtDgIACEYYACrolPBwddmWIEZWsmVWJYgiLwXX2YcB1gdDq+BAodWGIWsEhQiDRAWBmQdEAAhGBroFC1ojMC4etERIlDAggkHNIgAWSYYjFVwNWGwgAP5KkBEYoFC1ihBagwAL5W72vKJAxpExCiDABnQ4W12vD6AHBEYxnT4YhB3ghCSIhqDe4SIP3giBM4LfFEYpiMDoQhC3fDCA7+DfBwiCAARmFAAmtEYlYagMywISHEQhEId4UyEYleqwABEZBHERQwABroZBq5rR6BGLNZKzMAAPKRZKzJr2tfaAAKxD7CfgRsD1g1GAAwME2YGDwQjFNgOzwMyCwuCwIAEBg0yHoKODEYmCcYNWCwutAAuzBgg4BCwJGEEgj7JV5r7BIwgjEWrDVCEQYkCWgYAWNYIjF/z8awQfD"));
|
||||
}
|
||||
|
||||
function onGPS(fix) {
|
||||
if (lastFix.fix != fix.fix) {
|
||||
// if fix is different, change the layout
|
||||
if (fix.fix) {
|
||||
layout = new Layout( {
|
||||
type:"v", c: [
|
||||
{type:"txt", font:"6x8:2", label:"Speed" },
|
||||
{type:"h", c: [
|
||||
{type:"img", src:speedoImage, pad:4 },
|
||||
{type:"txt", font:"35%", label:"--", fillx:true, id:"speed" },
|
||||
]},
|
||||
{type:"txt", font:"6x8", label:"--", id:"units" },
|
||||
{type:"h", c: [
|
||||
{type:"txt", font:"10%", label:fix.satellites, pad:2, id:"sat" },
|
||||
{type:"txt", font:"6x8", pad:3, label:"Satellites" }
|
||||
]},
|
||||
]},[],{lazy:true});
|
||||
} else {
|
||||
layout = new Layout( {
|
||||
type:"v", c: [
|
||||
{type:"txt", font:"6x8:2", label:"Speed" },
|
||||
{type:"img", src:speedoImage, pad:4 },
|
||||
{type:"txt", font:"6x8", label:"Waiting for GPS" },
|
||||
{type:"h", c: [
|
||||
{type:"txt", font:"10%", label:fix.satellites, pad:2, id:"sat" },
|
||||
{type:"txt", font:"6x8", pad:3, label:"Satellites" }
|
||||
]},
|
||||
]},[],{lazy:true});
|
||||
}
|
||||
g.clearRect(0,24,g.getWidth(),g.getHeight());
|
||||
layout.render();
|
||||
}
|
||||
lastFix = fix;
|
||||
buf.clear();
|
||||
buf.setFontAlign(0,0);
|
||||
buf.setFont("6x8");
|
||||
buf.drawString(fix.satellites+" satellites",120,6);
|
||||
if (fix.fix) {
|
||||
|
||||
if (fix.fix && isFinite(fix.speed)) {
|
||||
var speed = require("locale").speed(fix.speed);
|
||||
var m = speed.match(/([0-9,\.]+)(.*)/); // regex splits numbers from units
|
||||
var txt = (fix.speed<20) ? fix.speed.toFixed(1) : Math.round(fix.speed);
|
||||
var value = m[1], units = m[2];
|
||||
var s = 80;
|
||||
buf.setFontVector(s);
|
||||
buf.drawString(value,120,10+s/2);
|
||||
buf.setFont("6x8",2);
|
||||
buf.drawString(units,120,s+26);
|
||||
} else {
|
||||
buf.setFont("6x8",2);
|
||||
buf.drawString("Waiting for GPS",120,56);
|
||||
layout.speed.label = m[1];
|
||||
layout.units.label = m[2];
|
||||
}
|
||||
g.reset();
|
||||
g.drawImage({width:buf.getWidth(),height:buf.getHeight(),bpp:1,buffer:buf.buffer},0,70);
|
||||
g.flip();
|
||||
layout.sat.label = fix.satellites;
|
||||
layout.render();
|
||||
}
|
||||
g.clear();
|
||||
onGPS(lastFix);
|
||||
onGPS({fix:0,satellites:0});
|
||||
// onGPS({fix:1,satellites:3,speed:200}); // testing
|
||||
Bangle.loadWidgets();
|
||||
Bangle.drawWidgets();
|
||||
|
||||
Bangle.on('GPS', onGPS);
|
||||
Bangle.setGPSPower(1);
|
||||
Bangle.setGPSPower(1, "app");
|
||||
|
|
|
|||
|
|
@ -2,3 +2,4 @@
|
|||
0.03: Ensure redrawing works with variable size widget system
|
||||
0.04: Fix automatic update of Bluetooth connection status
|
||||
0.05: Make Bluetooth widget thinner, and when on a bright theme use light grey for disabled color
|
||||
0.06: Tweaking colors for dark/light themes and low bpp screens
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
function draw() {
|
||||
g.reset();
|
||||
if (NRF.getSecurityStatus().connected)
|
||||
g.setColor("#07f");
|
||||
g.setColor((g.getBPP()>8) ? "#07f" : (g.theme.dark ? "#0ff" : "#00f"));
|
||||
else
|
||||
g.setColor(g.theme.bg ? "#AAA" : "#555");
|
||||
g.setColor(g.theme.dark ? "#666" : "#999");
|
||||
g.drawImage(atob("CxQBBgDgFgJgR4jZMawfAcA4D4NYybEYIwTAsBwDAA=="),2+this.x,2+this.y);
|
||||
}
|
||||
function changed() {
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
0.01: New Widget!
|
||||
0.02: Tweaks for variable size widget system
|
||||
0.03: Tweaking colors for dark/light themes
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
/* jshint esversion: 6 */
|
||||
(() => {
|
||||
function draw() {
|
||||
var id = NRF.getAddress().substr().substr(12).split(":");
|
||||
g.reset().setColor(0, 0.49, 1).setFont("6x8", 1);
|
||||
g.reset().setColor(g.theme.dark ? "#0ff" : "#00f").setFont("6x8", 1);
|
||||
g.drawString(id[0], this.x+2, this.y+4, true);
|
||||
g.drawString(id[1], this.x+2, this.y+14, true);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,6 @@
|
|||
<p id="requireHTTPS" class="hidden">
|
||||
<b>STOP!</b> This page <b>must</b> be served over HTTPS. Please <a>reload this page via HTTPS</a>.
|
||||
</p>
|
||||
<div class="toast toast-success flex-centered" id="bangle2ks">
|
||||
<img src="data:image/png;base64,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" />
|
||||
Bangle.js 2 is now on KickStarter! <a href="https://www.kickstarter.com/projects/gfw/banglejs-2-the-open-smart-watch" target="_blank">Check it out here</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue