Merge branch 'espruino:master' into scaledlauncher

master
t0m1o1 2021-11-25 01:46:21 +00:00 committed by GitHub
commit b0a2507977
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
124 changed files with 18965 additions and 300 deletions

View File

@ -1,2 +1,4 @@
apps/animclk/V29.LBM.js
apps/banglerun/rollup.config.js
apps/schoolCalendar/fullcalendar/main.js
apps/authentiwatch/qr_packed.js

136
apps.json
View File

@ -32,7 +32,7 @@
{
"id": "messages",
"name": "Messages",
"version": "0.03",
"version": "0.05",
"description": "App to display notifications from iOS and Gadgetbridge",
"icon": "app.png",
"type": "app",
@ -45,12 +45,14 @@
{"name":"messages.wid.js","url":"widget.js"},
{"name":"messages","url":"lib.js"}
],
"data": [{"name":"messages.json"}],
"sortorder": -9
},
{
"id": "android",
"name": "Android Integration",
"version": "0.01",
"shortName": "Android",
"version": "0.03",
"description": "(BETA) App to display notifications from Gadgetbridge on Android. This will eventually replace the Gadgetbridge widget.",
"icon": "app.png",
"tags": "tool,system,messages,notifications",
@ -61,12 +63,12 @@
{"name":"android.img","url":"app-icon.js","evaluate":true},
{"name":"android.boot.js","url":"boot.js"}
],
"sortorder": -9
"sortorder": -8
},
{
"id": "ios",
"name": "iOS Integration",
"version": "0.01",
"version": "0.03",
"description": "(BETA) App to display notifications from iOS devices",
"icon": "app.png",
"tags": "tool,system,ios,apple,messages,notifications",
@ -77,7 +79,7 @@
{"name":"ios.img","url":"app-icon.js","evaluate":true},
{"name":"ios.boot.js","url":"boot.js"}
],
"sortorder": -9
"sortorder": -8
},
{
"id": "health",
@ -141,6 +143,7 @@
"icon": "app.png",
"tags": "tool,system",
"supports": ["BANGLEJS","BANGLEJS2"],
"screenshots": [{"url":"bangle1-about-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"about.app.js","url":"app-bangle1.js","supports": ["BANGLEJS"]},
@ -216,7 +219,7 @@
"id": "welcome",
"name": "Welcome",
"shortName": "Welcome",
"version": "0.13",
"version": "0.14",
"description": "Appears at first boot and explains how to use Bangle.js",
"icon": "app.png",
"screenshots": [{"url":"screenshot_welcome.png"}],
@ -242,6 +245,7 @@
"tags": "start,welcome",
"supports": ["BANGLEJS"],
"custom": "custom.html",
"screenshots": [{"url":"bangle1-customized-welcome-screenshot.png"}],
"storage": [
{"name":"mywelcome.boot.js","url":"boot.js"},
{"name":"mywelcome.app.js","url":"app.js"},
@ -278,6 +282,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-morphing-clock-screenshot.png"}],
"storage": [
{"name":"mclock.app.js","url":"clock-morphing.js"},
{"name":"mclock.img","url":"clock-morphing-icon.js","evaluate":true}
@ -292,6 +297,7 @@
"icon": "app.png",
"tags": "",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-moon-phase-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"moonphase.app.js","url":"app.js"},
@ -422,6 +428,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-sweep-clock-screenshot.png"}],
"storage": [
{"name":"sweepclock.app.js","url":"sweepclock.js"},
{"name":"sweepclock.img","url":"sweepclock-icon.js","evaluate":true}
@ -472,6 +479,7 @@
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"impwclock.app.js","url":"clock-impword.js"},
@ -555,6 +563,7 @@
"supports" : ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle2-cube-scramble-screenshot.png"},{"url":"bangle1-cube-scramble-screenshot.png"}],
"storage": [
{"name":"cubescramble.app.js","url":"cube-scramble.js"},
{"name":"cubescramble.img","url":"cube-scramble-icon.js","evaluate":true}
@ -658,7 +667,7 @@
{
"id": "gpsrec",
"name": "GPS Recorder",
"version": "0.24",
"version": "0.25",
"description": "Application that allows you to record a GPS track. Can run in background",
"icon": "app.png",
"tags": "tool,outdoors,gps,widget",
@ -745,7 +754,7 @@
"description": "Show currently installed apps, free space, and allow their deletion from the watch",
"icon": "files.png",
"tags": "tool,system,files",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS","BANGLEJS2"],
"storage": [
{"name":"files.app.js","url":"files.js"},
{"name":"files.img","url":"files-icon.js","evaluate":true}
@ -779,6 +788,7 @@
"tags": "battery",
"supports": ["BANGLEJS", "BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-charge-animation-screenshot.png"},{"url":"bangle-charge-animation-screenshot.png"}],
"storage": [
{"name":"chargeanim.app.js","url":"app.js"},
{"name":"chargeanim.boot.js","url":"boot.js"},
@ -984,6 +994,7 @@
"readme": "README.md",
"interface": "interface.html",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-stopwatch-screenshot.png"}],
"storage": [
{"name":"swatch.app.js","url":"stopwatch.js"},
{"name":"swatch.img","url":"stopwatch-icon.js","evaluate":true}
@ -1185,6 +1196,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-vibrate-clock-screenshot.png"}],
"storage": [
{"name":"vibrclock.app.js","url":"app.js"},
{"name":"vibrclock.img","url":"app-icon.js","evaluate":true}
@ -1200,6 +1212,7 @@
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-simple-v-clock-screenshot.png"}],
"storage": [
{"name":"svclock.app.js","url":"vclock-simple.js"},
{"name":"svclock.img","url":"vclock-simple-icon.js","evaluate":true}
@ -1215,6 +1228,7 @@
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-dev-clock-screenshot.png"},{"url":"bangle1-dev-clock-screenshot.png"}],
"storage": [
{"name":"dclock.app.js","url":"clock-dev.js"},
{"name":"dclock.img","url":"clock-dev-icon.js","evaluate":true}
@ -1246,6 +1260,7 @@
"tags": "party,parrot,lol",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-party-parrot-screenshot.png"}],
"storage": [
{"name":"pparrot.app.js","url":"party-parrot.js"},
{"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true}
@ -1261,6 +1276,7 @@
"tags": "rings,hypnosis,psychadelic",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-hypno-rings-screenshot.png"}],
"storage": [
{"name":"hrings.app.js","url":"hypno-rings.js"},
{"name":"hrings.img","url":"hypno-rings-icon.js","evaluate":true}
@ -1328,6 +1344,7 @@
"icon": "show-color.png",
"type": "app",
"tags": "tool",
"screenshots": [{"url":"bangle1-view-color-screenshot.png"}],
"supports": ["BANGLEJS"],
"allow_emulator": true,
"storage": [
@ -1343,6 +1360,7 @@
"icon": "clock-mixed.png",
"type": "clock",
"tags": "clock",
"screenshots": [{"url":"bangle1-mixed-clock-screenshot.png"}],
"supports": ["BANGLEJS"],
"allow_emulator": true,
"storage": [
@ -1360,6 +1378,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-binary-clock-screenshot.png"}],
"storage": [
{"name":"bclock.app.js","url":"clock-binary.js"},
{"name":"bclock.img","url":"clock-binary-icon.js","evaluate":true}
@ -1373,6 +1392,7 @@
"icon": "clock-tris.png",
"tags": "game",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-clock-tris-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"clotris.app.js","url":"clock-tris.js"},
@ -1432,6 +1452,7 @@
"tags": "pomodoro,cooking,tools",
"supports": ["BANGLEJS", "BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-pomodoro-screenshot.png"}],
"storage": [
{"name":"pomodo.app.js","url":"pomodoro.js"},
{"name":"pomodo.img","url":"pomodoro-icon.js","evaluate":true}
@ -1448,6 +1469,7 @@
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-large-digit-blob-clock-screenshot.png"},{"url":"bangle1-large-digit-blob-clock-screenshot.png"}],
"storage": [
{"name":"blobclk.app.js","url":"clock-blob.js"},
{"name":"blobclk.img","url":"clock-blob-icon.js","evaluate":true}
@ -1507,6 +1529,7 @@
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"berlin-clock-screenshot.png"}],
"storage": [
{"name":"berlinc.app.js","url":"berlin-clock.js"},
{"name":"berlinc.img","url":"berlin-clock-icon.js","evaluate":true}
@ -1521,6 +1544,7 @@
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-center-clock-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"ctrclk.app.js","url":"app.js"},
@ -1535,6 +1559,7 @@
"icon": "app.png",
"type": "app",
"tags": "",
"screenshots": [{"url":"bangle1-demo-loop-screenshot1.png"},{"url":"bangle1-demo-loop-screenshot2.png"},{"url":"bangle1-demo-loop-screenshot3.png"},{"url":"bangle1-demo-loop-screenshot4.png"}],
"supports": ["BANGLEJS"],
"allow_emulator": true,
"storage": [
@ -1567,6 +1592,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-pipboy-themed-clock-screenshot.png"}],
"storage": [
{"name":"pipboy.app.js","url":"app.js"},
{"name":"pipboy.img","url":"app-icon.js","evaluate":true}
@ -1613,6 +1639,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}],
"storage": [
{"name":"wohrm.app.js","url":"app.js"},
{"name":"wohrm.img","url":"app-icon.js","evaluate":true}
@ -1657,6 +1684,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": false,
"screenshots": [{"url":"bangle1-mario-clock-screenshot.png"}],
"storage": [
{"name":"marioclock.app.js","url":"marioclock-app.js"},
{"name":"marioclock.img","url":"marioclock-icon.js","evaluate":true}
@ -1695,13 +1723,13 @@
{
"id": "barclock",
"name": "Bar Clock",
"version": "0.08",
"version": "0.09",
"description": "A simple digital clock showing seconds as a bar",
"icon": "clock-bar.png",
"screenshots": [{"url":"screenshot.png"},{"url":"screenshot_pm.png"}],
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS","BANGLEJS2"],
"readme": "README.md",
"allow_emulator": true,
"storage": [
@ -1719,6 +1747,7 @@
"tags": "clock",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle2-dot-clcok-screenshot.png"},{"url":"bangle1-dot-clock-screenshot.png"}],
"storage": [
{"name":"dotclock.app.js","url":"clock-dot.js"},
{"name":"dotclock.img","url":"clock-dot-icon.js","evaluate":true}
@ -1828,6 +1857,7 @@
"tags": "game,fun",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-rpg-dice-screenshot.png"}],
"storage": [
{"name":"rpgdice.app.js","url":"app.js"},
{"name":"rpgdice.img","url":"app-icon.js","evaluate":true}
@ -1856,6 +1886,7 @@
"tags": "clock,minion",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-minion-clock-screenshot.png"}],
"storage": [
{"name":"minionclk.app.js","url":"app.js"},
{"name":"minionclk.img","url":"app-icon.js","evaluate":true}
@ -1933,7 +1964,7 @@
"icon": "custom.png",
"type": "bootloader",
"tags": "tool,system",
"supports": ["BANGLEJS"],
"supports": ["BANGLEJS","BANGLEJS2"],
"custom": "custom.html",
"storage": [
{"name":"custom"}
@ -1948,6 +1979,7 @@
"icon": "app.png",
"tags": "stopwatch,chrono,timer,chronometer",
"supports": ["BANGLEJS","BANGLEJS2"],
"screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"devstopwatch.app.js","url":"app.js"},
@ -1981,6 +2013,7 @@
"tags": "app,learn,visual",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-NATO-alphabet-screenshot.png"},{"url":"bangle1-NATO-alphabet-screenshot2.png"}],
"storage": [
{"name":"nato.app.js","url":"nato.js"},
{"name":"nato.img","url":"nato-icon.js","evaluate":true}
@ -1997,6 +2030,7 @@
"tags": "numerals,clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-numerals-screenshot.png"}],
"storage": [
{"name":"numerals.app.js","url":"numerals.app.js"},
{"name":"numerals.img","url":"numerals-icon.js","evaluate":true},
@ -2123,13 +2157,14 @@
{
"id": "metronome",
"name": "Metronome",
"version": "0.06",
"version": "0.07",
"readme": "README.md",
"description": "Makes the watch blinking and vibrating with a given rate",
"icon": "metronome_icon.png",
"tags": "tool",
"supports": ["BANGLEJS"],
"readme": "README.md",
"supports": ["BANGLEJS","BANGLEJS2"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-metronome-screenshot.png"}],
"storage": [
{"name":"metronome.app.js","url":"metronome.js"},
{"name":"metronome.img","url":"metronome-icon.js","evaluate":true},
@ -2145,6 +2180,7 @@
"icon": "blackjack.png",
"tags": "game",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-black-jack-game-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"blackjack.app.js","url":"blackjack.app.js"},
@ -2178,6 +2214,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-SWL-clock-screenshot.png"}],
"storage": [
{"name":"swlclk.app.js","url":"app.js"},
{"name":"swlclk.img","url":"app-icon.js","evaluate":true}
@ -2255,6 +2292,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-pong-screenshot.png"}],
"storage": [
{"name":"pong.app.js","url":"app.js"},
{"name":"pong.img","url":"app-icon.js","evaluate":true}
@ -2317,6 +2355,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-large-clock-screenshot.png"}],
"storage": [
{"name":"largeclock.app.js","url":"largeclock.js"},
{"name":"largeclock.img","url":"largeclock-icon.js","evaluate":true},
@ -2368,6 +2407,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-timer-screenshot.png"}],
"storage": [
{"name":"simpletimer.app.js","url":"app.js"},
{"name":".tfnames","url":"gesture-tfnames.js","evaluate":true},
@ -2384,6 +2424,7 @@
"icon": "beebclock.png",
"type": "clock",
"tags": "clock",
"screenshots": [{"url":"bangle1-beeb-clock-screenshot.png"}],
"supports": ["BANGLEJS"],
"allow_emulator": true,
"storage": [
@ -2417,6 +2458,7 @@
"tags": "tools,health",
"supports": ["BANGLEJS"],
"readme": "README.md",
"screenshots": [{"url":"bangle1-get-up-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"getup.app.js","url":"app.js"},
@ -2495,6 +2537,7 @@
"version": "0.01",
"description": "La palla predice il futuro",
"icon": "app.png",
"screenshots": [{"url":"bangle1-magic-8-ball-italiano-screenshot.png"}],
"tags": "game",
"supports": ["BANGLEJS"],
"allow_emulator": true,
@ -2608,6 +2651,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-vertical-watch-face-screenshot.png"}],
"storage": [
{"name":"verticalface.app.js","url":"app.js"},
{"name":"verticalface.img","url":"app-icon.js","evaluate":true}
@ -2635,6 +2679,7 @@
"icon": "life.png",
"tags": "game",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-game-of-life-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"life.app.js","url":"life.min.js"},
@ -2682,6 +2727,7 @@
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-mixed-clock-2-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"miclock2.app.js","url":"clock-mixed.js"},
@ -2817,6 +2863,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-CPR-assist-screenshot.png"}],
"storage": [
{"name":"cprassist.app.js","url":"cprassist.js"},
{"name":"cprassist.img","url":"cprassist-icon.js","evaluate":true},
@ -2860,6 +2907,7 @@
"icon": "counter_icon.png",
"tags": "tool",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-counter-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"counter.app.js","url":"counter.js"},
@ -3239,6 +3287,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"readme": "README.md",
"screenshots": [{"url":"bangle1-lazy-clock-screenshot.png"}],
"allow_emulator": true,
"storage": [
{"name":"lazyclock.app.js","url":"lazyclock-app.js"},
@ -3340,6 +3389,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-slow-mo-clock-screenshot.png"}],
"storage": [
{"name":"slomoclock.app.js","url":"app.js"},
{"name":"slomoclock.img","url":"app-icon.js","evaluate":true},
@ -3654,7 +3704,7 @@
"id": "gbmusic",
"name": "Gadgetbridge Music Controls",
"shortName": "Music Controls",
"version": "0.06",
"version": "0.07",
"description": "Control the music on your Gadgetbridge-connected phone",
"icon": "icon.png",
"screenshots": [{"url":"screenshot_v1.png"},{"url":"screenshot_v2.png"}],
@ -3679,6 +3729,7 @@
"icon": "battleship-icon.png",
"tags": "game",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-battle-ship-screenshot.png"}],
"readme": "README.md",
"allow_emulator": true,
"storage": [
@ -3882,6 +3933,7 @@
"type": "clock",
"tags": "clock",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"bangle1-mystic-clock-screenshot.png"}],
"readme": "README.md",
"allow_emulator": true,
"storage": [
@ -3898,6 +3950,7 @@
"icon": "hcclock-icon.png",
"type": "clock",
"tags": "clock",
"screenshots": [{"url":"bangle1-high-contrast-clock-screenshot.png"}],
"supports": ["BANGLEJS"],
"allow_emulator": true,
"storage": [
@ -3979,6 +4032,7 @@
"tags": "clock",
"supports": ["BANGLEJS"],
"allow_emulator": true,
"screenshots": [{"url":"bangle1-vector-clock-screenshot.png"}],
"storage": [
{"name":"vectorclock.app.js","url":"app.js"},
{"name":"vectorclock.img","url":"app-icon.js","evaluate":true}
@ -4008,6 +4062,7 @@
"supports": ["BANGLEJS"],
"readme": "README.md",
"allow_emulator": true,
"screenshots": [{"url":"bangle1-choozi-screenshot1.png"},{"url":"bangle1-choozi-screenshot2.png"}],
"storage": [
{"name":"choozi.app.js","url":"app.js"},
{"name":"choozi.img","url":"app-icon.js","evaluate":true}
@ -4245,11 +4300,18 @@
"id": "emojuino",
"name": "Emojuino",
"shortName": "Emojuino",
"version": "0.01",
"version": "0.02",
"description": "Emojis & Espruino: broadcast Unicode emojis via Bluetooth Low Energy.",
"icon": "emojuino.png",
"screenshots": [
{ "url": "screenshot-tx.png" },
{ "url": "screenshot-swipe.png" },
{ "url": "screenshot-welcome.png" }
],
"type": "app",
"tags": "emoji",
"supports" : [ "BANGLEJS2" ],
"allow_emulator": true,
"readme": "README.md",
"storage": [
{ "name": "emojuino.app.js", "url": "emojuino.js" },
@ -4260,8 +4322,8 @@
"id": "cliclockJS2Enhanced",
"name": "Commandline-Clock JS2 Enhanced",
"shortName": "CLI-Clock JS2",
"version": "0.1",
"description": "Simple CLI-Styled Clock with enhancements. Modes that are hard to use and unneded are removed (BPM, battery info, memory ect) credit to hughbarney for the original code and design",
"version": "0.02",
"description": "Simple CLI-Styled Clock with enhancements. Modes that are hard to use and unneded are removed (BPM, battery info, memory ect) credit to hughbarney for the original code and design. Also added HID media controlls, just swipe on the clock face to controll the media! Gadgetbride support coming soon(hopefully) Thanks to t0m1o1 for media controls!",
"icon": "app.png",
"screenshots": [{"url":"screengrab.png"}],
"type": "clock",
@ -4293,7 +4355,7 @@
"name": "LCARS Clock",
"shortName":"LCARS",
"icon": "lcars.png",
"version":"0.02",
"version":"0.05",
"supports": ["BANGLEJS2"],
"description": "Library Computer Access Retrieval System (LCARS) clock.",
"type": "clock",
@ -4316,8 +4378,10 @@
"description": "Famous binary watch",
"tags": "clock",
"type": "clock",
"storage": [
"storage": [
{"name":"binwatch.app.js","url":"app.js"},
{"name":"binwatch.bg176.img","url":"Background176_center.img"},
{"name":"binwatch.bg240.img","url":"Background240_center.img"},
{"name":"binwatch.img","url":"app-icon.js","evaluate":true}
]
},
@ -4353,5 +4417,37 @@
{"name":"authentiwatch.img","url":"app-icon.js","evaluate":true}
],
"data": [{"name":"authentiwatch.json"}]
},
{ "id": "schoolCalendar",
"name": "School Calendar",
"shortName":"SCalendar",
"icon": "CalenderLogo.png",
"version": "0.01",
"description": "A simple calendar that you can see your upcoming events that you create in the customizer. Keep in note that your events reapeat weekly.(Beta)",
"tags": "tool",
"readme":"README.md",
"custom":"custom.html",
"supports": ["BANGLEJS"],
"screenshots": [{"url":"screenshot_basic.png"},{"url":"screenshot_info.png"}],
"storage": [
{"name":"schoolCalendar.app.js"},
{"name":"schoolCalendar.img","url":"app-icon.js","evaluate":true}
],
"data": [
{"name":"app.json"}
]
},
{ "id": "timecal",
"name": "TimeCal",
"shortName":"TimeCal",
"icon": "icon.png",
"version":"0.01",
"description": "TimeCal shows the Time along with a 3 week calendar",
"tags": "clock",
"type": "clock",
"supports":["BANGLEJS2"],
"storage": [
{"name":"timecal.app.js","url":"timecal.app.js"}
]
}
]

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -1 +1,4 @@
0.01: New App!
0.02: Remove messages on disconnect
Fix music control
0.03: Handling of message actions (ok/clear)

View File

@ -12,7 +12,7 @@
/* TODO: Call handling, fitness */
var HANDLERS = {
// {t:"notify",id:int, src,title,subject,body,sender,tel:string} add
"notify" : function() { event.t="add";require("messages").pushMessage(event); },
"notify" : function() { Object.assign(event,{t:"add",positive:true, negative:true});require("messages").pushMessage(event); },
// {t:"notify~",id:int, title:string} // modified
"notify~" : function() { event.t="modify";require("messages").pushMessage(event); },
// {t:"notify-",id:int} // remove
@ -33,7 +33,16 @@
// {t:"musicinfo", artist,album,track,dur,c(track count),n(track num}
"musicinfo" : function() {
require("messages").pushMessage(Object.assign(event, {t:"modify",id:"music",title:"Music"}));
}
},
// {"t":"call","cmd":"incoming/end","name":"Bob","number":"12421312"})
"call" : function() {
Object.assign(event, {
t:event.cmd=="incoming"?"add":"remove",
id:"call", src:"Phone",
positive:true, negative:true,
title:event.name||"Call", body:"Incoming call\n"+event.number});
require("messages").pushMessage(event);
},
};
var h = HANDLERS[event.t];
if (h) h(); else console.log("GB Unknown",event);
@ -42,6 +51,7 @@
// Battery monitor
function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); }
NRF.on("connect", () => setTimeout(sendBattery, 2000));
NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect
setInterval(sendBattery, 10*60*1000);
// Health tracking
Bangle.on('health', health=>{
@ -50,6 +60,12 @@
// Music control
Bangle.musicControl = cmd => {
// play/pause/next/previous/volumeup/volumedown
gbSend({ t: "music", m:cmd });
}
gbSend({ t: "music", n:cmd });
};
// Message response
Bangle.messageResponse = (msg,response) => {
if (msg.id=="call") return gbSend({ t: "call", n:response?"ACCEPT":"REJECT" });
if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS" });
// error/warn here?
};
})();

View File

@ -5,4 +5,5 @@
0.05: Clock does not start if app Languages is not installed
0.06: Improve accuracy
0.07: Update to use Bangle.setUI instead of setWatch
0.08: Use theme colors, Layout library
0.08: Use theme colors, Layout library
0.09: Fix time/date disappearing after fullscreen notification

View File

@ -24,7 +24,7 @@ function renderBar(l) {
return;
}
const width = this.fraction*l.w;
g.fillRect(l.x, l.y, width-1, l.y+l.height-1);
g.fillRect(l.x, l.y, l.x+width-1, l.y+l.height-1);
}
const Layout = require("Layout");
@ -78,7 +78,7 @@ function dateText(date) {
return `${dayName} ${dayMonth}`;
}
draw = function draw() {
draw = function draw(force) {
if (!Bangle.isLCDOn()) {return;} // no drawing, also no new update scheduled
const date = new Date();
layout.time.label = timeText(date);
@ -86,6 +86,10 @@ draw = function draw() {
layout.date.label = dateText(date);
const SECONDS_PER_MINUTE = 60;
layout.bar.fraction = date.getSeconds()/SECONDS_PER_MINUTE;
if (force) {
Bangle.drawWidgets();
layout.forgetLazyState();
}
layout.render();
// schedule update at start of next second
const millis = date.getMilliseconds();
@ -96,7 +100,7 @@ draw = function draw() {
Bangle.setUI("clock");
Bangle.on("lcdPower", function(on) {
if (on) {
draw();
draw(true);
}
});
g.reset().clear();

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -1,3 +1,4 @@
0.01: start of development
0.02: first running version for BangleJs2
0.03: corrected icon, added screen shot, extended description
0.04: corrected format of background image (raw binary)

View File

@ -12,7 +12,6 @@
require("Font7x11Numeric7Seg").add(Graphics);
require("Font5x7Numeric7Seg").add(Graphics);
/* constants and definitions */
/* Bangle 2: 176 x 176 */
@ -63,7 +62,7 @@ const V2_BAT_SIZE_Y = 2;
const V2_SCREEN_SIZE_X = 176;
const V2_SCREEN_SIZE_Y = 176;
const V2_BACKGROUND_IMAGE = "Background176_center.png";
const V2_BACKGROUND_IMAGE = "binwatch.bg176.img";
const V2_BG_COLOR = 0;
const V2_FG_COLOR = 1;
@ -91,7 +90,7 @@ const V1_BAT_SIZE_X = 3;
const V1_BAT_SIZE_Y = 5;
const V1_SCREEN_SIZE_X = 240;
const V1_SCREEN_SIZE_Y = 240;
const V1_BACKGROUND_IMAGE = "Background240_center.png";
const V1_BACKGROUND_IMAGE = "binwatch.bg240.img";
const V1_BG_COLOR = 1;
const V1_FG_COLOR = 0;
@ -293,7 +292,7 @@ function setRuntimeValues(resolution) {
bat_size_x = V1_BAT_SIZE_X;
bat_size_y = V1_BAT_SIZE_Y;
setWatch(toggleDateTime, BTN1, { repeat : true, edge: "falling"});
setWatch(toggleDateTime, BTN1, { repeat : true, edge: "falling"});
} else {
x_step = V2_X_STEP;
@ -362,8 +361,7 @@ function draw() {
updateVTime();
g.clear();
g.drawImages([{image:cgimg},
{image:require("Storage").read(backgroundImage)},
// { x:bt_x, y:bt_y, rotate: 0, image:require("Storage").read("bt-icon.png")},
{image:require("Storage").read(backgroundImage)}
]);
drawBT(g, NRF.getSecurityStatus().connected);
// Bangle.drawWidgets();

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -0,0 +1,2 @@
0.01: Submitted to App Loader
0.02: Removed unneded code, added HID controlls thanks to t0m1o1 for his code :p

View File

@ -4,24 +4,96 @@ var fontsizeTime = g.getWidth()>200 ? 4 : 4;
var fontheight = 10*fontsize;
var fontheightTime = 10*fontsizeTime;
var locale = require("locale");
var marginTop = 40;
var marginTop = 25;
var flag = false;
var hrtOn = false;
var hrtStr = "Hrt: ??? bpm";
var storage = require('Storage');
const NONE_MODE = "none";
const ID_MODE = "id";
const VER_MODE = "ver";
const BATT_MODE = "batt";
const MEM_MODE = "mem";
const STEPS_MODE = "step";
const HRT_MODE = "hrt";
const NONE_FN_MODE = "no_fn";
const HRT_FN_MODE = "fn_hrt";
const settings = storage.readJSON('setting.json',1) || { HID: false };
var sendHid, next, prev, toggle, up, down, profile;
var lasty = 0;
var lastx = 0;
if (settings.HID=="kbmedia") {
profile = 'Music';
sendHid = function (code, cb) {
try {
NRF.sendHIDReport([1,code], () => {
NRF.sendHIDReport([1,0], () => {
if (cb) cb();
});
});
} catch(e) {
print(e);
}
};
next = function (cb) { sendHid(0x01, cb); };
prev = function (cb) { sendHid(0x02, cb); };
toggle = function (cb) { sendHid(0x10, cb); };
up = function (cb) {sendHid(0x40, cb); };
down = function (cb) { sendHid(0x80, cb); };
} else {
E.showPrompt("Enable HID?",{title:"HID disabled"}).then(function(enable) {
if (enable) {
settings.HID = "kbmedia";
require("Storage").write('setting.json', settings);
setTimeout(load, 1000, "hidmsicswipe.app.js");
} else setTimeout(load, 1000);
});
}
if (next) {
setWatch(function(e) {
var len = e.time - e.lastTime;
E.showMessage('lock');
setTimeout(drawApp, 1000);
Bangle.setLocked(true);
}, BTN1, { edge:"falling",repeat:true,debounce:50});
Bangle.on('drag', function(e) {
if(!e.b){
console.log(lasty);
console.log(lastx);
if(lasty > 40){
writeLine('Down', 3);
// setTimeout(drawApp, 1000);
// Bluetooth.println(JSON.stringify({t:"music", n:"volumedown"}));
down(() => {});
}
else if(lasty < -40){
writeLine('Up', 3);
// setTimeout(drawApp, 1000);
//Bluetooth.println(JSON.stringify({t:"music", n:"volumeup"}));
up(() => {});
} else if(lastx < -40){
writeLine('Prev', 3);
// setTimeout(drawApp, 1000);
// Bluetooth.println(JSON.stringify({t:"music", n:"previous"}));
prev(() => {});
} else if(lastx > 40){
writeLine('Next', 3);
// setTimeout(drawApp, 1000);
// Bluetooth.println(JSON.stringify({t:"music", n:"next"}));
next(() => {});
} else if(lastx==0 && lasty==0){
writeLine('play/pause', 3);
//setTimeout(drawApp, 1000);
// Bluetooth.println(JSON.stringify({t:"music", n:"play"}));
toggle(() => {});
}
lastx = 0;
lasty = 0;
}
else{
lastx = lastx + e.dx;
lasty = lasty + e.dy;
}
});
}
let infoMode = NONE_MODE;
let functionMode = NONE_FN_MODE;
let textCol = g.theme.dark ? "#0f0" : "#080";
@ -33,13 +105,12 @@ function drawAll(){
function updateRest(now){
writeLine(locale.dow(now),1);
writeLine(locale.date(now,1),2);
drawInfo(5);
}
function updateTime(){
if (!Bangle.isLCDOn()) return;
let now = new Date();
writeLine(locale.time(now,1),0);
writeLine(flag?" ":"_",3);
writeLine(flag?" ":"_ ",3);
flag = !flag;
if(now.getMinutes() == 0)
updateRest(now);
@ -65,142 +136,13 @@ function writeLine(str,line){
var y = marginTop+(line-1)*fontheight+fontheightTime;
g.setFont("6x8",fontsize);
g.setColor(textCol).setFontAlign(-1,-1);
g.clearRect(0,y,((str.length+1)*20),y+fontheight-1);
g.clearRect(0,y,((str.length+10)*40),y+fontheightTime-1);
writeLineStart(line);
g.drawString(str,25,y);
}
}
function drawInfo(line) {
let val;
let str = "";
let col = textCol; // green
//console.log("drawInfo(), infoMode=" + infoMode + " funcMode=" + functionMode);
switch(functionMode) {
case NONE_FN_MODE:
break;
case HRT_FN_MODE:
col = g.theme.dark ? "#0ff": "#088"; // cyan
str = "HRM: " + (hrtOn ? "ON" : "OFF");
drawModeLine(line,str,col);
return;
}
switch(infoMode) {
case NONE_MODE:
col = g.theme.bg;
str = "";
break;
case HRT_MODE:
str = hrtStr;
break;
case STEPS_MODE:
str = "Steps: " + stepsWidget().getSteps();
break;
case ID_MODE:
val = NRF.getAddress().split(":");
str = "Id: " + val[4] + val[5];
break;
case VER_MODE:
str = "Fw: " + process.env.VERSION;
break;
case MEM_MODE:
val = process.memory();
str = "Memory: " + Math.round(val.usage*100/val.total) + "%";
break;
case BATT_MODE:
default:
str = "Battery: " + E.getBattery() + "%";
}
drawModeLine(line,str,col);
}
function drawModeLine(line, str, col) {
g.setColor(col);
var y = marginTop+line*fontheight;
g.fillRect(0, y, 239, y+fontheight-1);
g.setColor(g.theme.bg).setFontAlign(0, 0);
g.drawString(str, g.getWidth()/2, y+fontheight/2);
}
function changeInfoMode() {
switch(functionMode) {
case NONE_FN_MODE:
break;
case HRT_FN_MODE:
hrtOn = !hrtOn;
Bangle.buzz();
Bangle.setHRMPower(hrtOn ? 1 : 0);
if (hrtOn) infoMode = HRT_MODE;
return;
}
switch(infoMode) {
case NONE_MODE:
if (stepsWidget() !== undefined)
infoMode = hrtOn ? HRT_MODE : STEPS_MODE;
else
infoMode = VER_MODE;
break;
case HRT_MODE:
if (stepsWidget() !== undefined)
infoMode = STEPS_MODE;
else
infoMode = VER_MODE;
break;
case STEPS_MODE:
infoMode = ID_MODE;
break;
case ID_MODE:
infoMode = VER_MODE;
break;
case VER_MODE:
infoMode = BATT_MODE;
break;
case BATT_MODE:
infoMode = MEM_MODE;
break;
case MEM_MODE:
default:
infoMode = NONE_MODE;
}
}
function changeFunctionMode() {
//console.log("changeFunctionMode()");
switch(functionMode) {
case NONE_FN_MODE:
functionMode = HRT_FN_MODE;
break;
case HRT_FN_MODE:
default:
functionMode = NONE_FN_MODE;
}
//console.log(functionMode);
}
function stepsWidget() {
if (WIDGETS.activepedom !== undefined) {
return WIDGETS.activepedom;
} else if (WIDGETS.wpedom !== undefined) {
return WIDGETS.wpedom;
}
return undefined;
}
Bangle.on('HRM', function(hrm) {
if(hrm.confidence > 90){
hrtStr = "Hrt: " + hrm.bpm + " bpm";
} else {
hrtStr = "Hrt: ??? bpm";
}
});
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
@ -211,6 +153,5 @@ Bangle.on('lcdPower',function(on) {
var click = setInterval(updateTime, 1000);
// Show launcher when button pressed
Bangle.setUI("clockupdown", btn=>{
if (btn<0) changeInfoMode();
drawAll();
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1 +1,2 @@
0.01: New App!
0.02: Upgraded text to images, added welcome screen and subtitles.

View File

@ -4,29 +4,48 @@
*/
// Emojis are integer pairs with the form [ image, Unicode code point ]
// Emoji images are 96px x 96px, 4bpp (https://www.espruino.com/Image+Converter)
// and adapted from Font Awesome 5
const GRIN = "sFgwkBiIATDwoaUFi4ynQZ4uuGDzlTF1wwaFyowYFy4wWiAvZgIutGCgubSKRecMCQudMCBeeMCAufMBxegMBwuhMBheiMBgujMBRekMBQvvF0qQIL0xgIF94unSA4vuR1CQGF94upSAovuR1SQEF94urSAY/PCBivQF5z/DEBQ+DEB5ePCJYOEMBgNNF8MBHpogNHwqBNF/4vsEAovOX7TviBhYgFD5Q/EEJoANEAY/OLxgAQPx5edAH4A/AH4A/AH4A/AEUQF1sBF/4v/F/4vviILJBRQANEZYLJHQIMKFpYABQhIiKC4QaMIhBHLF6AAVEhRQIF8ZuCF5B6GACYjMF9ZrOF8jAiKRgvvSEJROBo5gYEBw+IMCwfPB5BgWDxBPHCCBeVJxBgdJqIvJMCQcTCRAwRFxJ8KChQwODKwVJGBouKbZgXLDBQVLPBoZLDYxDMLxocQACLXOMBwARFxxgfLx5gfFyBgdLyIwcFyaRbFygwZFywwXFzAwVFzQwTFzgwRFzwxOFsIyKDSg";
const MEH = "sFgwkBiIATDwoaUFi4ynQZ4uuGDzlTF1wwaFyowYFy4wWiAvZgIutGCgubSKRecMCQudMCBeeMCAufMBxegMBwuhMBheiMBgujMBRekMBQvvF0qQIL0xgIF94unSA4vuR1CQGF94upSAovuR1SQEF94urSAY/PCBivQF5z/DEBQ+DEB5ePCJYOEMBgNNF8MBHpogNHwqBNF/4vsEAovOX7TviBhYgFD5Q/EEJoANEAY/OLxgAQPx5edAH4A/AH4A/AH4A/AEUQF1sBF/4v/F/4vviIvtiIv/F9qeBACDgNB5ouSECAOLFyaBMKAYvrByQvgSBS/fD4jAfXxwQMADxAQF8iQLADjeGF96QoFwxgnLw4vwSEwuIMEpeJMEouKMEZeLMEYuMMEJeNMEIuOMD5ePMD4uQMDpeRGDguTSLYuUGDIuWGC4uYGCouaGCYucGCIueGJwthGRQaUA";
const FROWN = "sFgwkBiIATDwoaUFi4ynQZ4uuGDzlTF1wwaFyowYFy4wWiAvZgIutGCgubSKRecMCQudMCBeeMCAufMBxegMBwuhMBheiMBgujMBRekMBQvvF0qQIL0xgIF94unSA4vuR1CQGF94upSAovuR1SQEF94urSAY/PCBivQF5z/DEBQ+DEB5ePCJYOEMBgNNF8MBHpogNHwqBNF/4vsEAovOX7TviBhYgFD5Q/EEJoANEAY/OLxgAQPx5edAH4A/AH4A/AH4A/AEUQF1sBF/4v/F/4vUgMRAAQZWFqwxWCgIuZGCYvSFxIcUFzYdTOZyNKSKQdCCJwuNMB5NDLzZOPIKAviCJguPJxpNEF94RLRyBONIKAvHNRQvRCKAMUJpIvOZxx9WAEbSTADReHF+CQmFxBglLxJglFxRgjLxZgjFxhghLxpghFxxgfLx5gfFyBgdLyIwcFyaRbFygwZFywwXFzAwVFzQwTFzgwRFzwxOFsIyKDSg";
const THUMBS_UP = "sFgwkBiIAaiAiBDzYAQKYZQcLyAwsF4qSpcoxgoF4xgnRwwvxSEwvvFw4vwYEwv/F/4AOiAv/R1Av/F/6+PgIv/RzwvjLxQvkFxTujLxYvjFxaOiLxgvvR1wviR3gviR3YviFxg6iF7AwVRxowhFzUAgIvuMCSObF6YucSCJedF6IudSARQIHQheeAAIgKGAYufF+CbMF/4v/WYQv/F/6yPF/6OeF9wgNL/4v/F/4vhEQIv/R/4v/F/7ueF/4v/Xx4v/F/4v/F/4v/F/4v/F7ogOF/6OSEAgHCiAvrAwQHHRz4v/F/4v/F58QF8cBE4wPDGLYvHB5aTaKwQvUMS4vYGCx8QF5AwULwgvWYiZJQIAowXDowvYGJyqRFx4bKDRQA==";
const THUMBS_DOWN = "sFgwkBiIAbiAoGEroAHLZgttMcK9RXEZgmFyZgHDZA/JFyogFDZQwHFqovXLiyQHB5wtaF6gubF/4v/F/4vwgIv/F7wgPF/6QTF/4v/F/4v/F/4v/F/4AdF/4v/YCIv/F/4v9EQIv/R/4v/F/7ueL+gFBiMQF8oiBE4wHHF/6QQF/4v/YigvugInBiAvrM5QvvM4gvqMFgvDMD0BF55gegJPKgIvEMDoeLF4pgdJ5QuGF7gjHABaQbFyRgbFygvZFyqQOEixgYF8RgMgIv/SH5gPYH6QfF8aQvMBgvjMBaQjMBYvkMBQv/SEAv/F/7APF/6QfF/4v/F/0BF8sQF/4vnF0rAJF9yOmSBAunF4xeoSAouqMAYTQA==";
const HEART = "sFgwkBiIA/AH4A/AH4AogAADC1EQC4gaQCo8BIqYwRCyxdJDJoVLMJYuMGBIVNGBQYNDI5FOO5IXODI4WWI6BgGCywYTDIYVVO6gvXSAoYTDIQVTMAgYTDIJFUMAgYUACyOXAC7XWF7YurSAYvuR1iQCF/4v/F54utAH4A/AH4A/AH4A/AGMQF1sBF/4v/F58RF9sRF/4vgYFi+BMFouCF+CQqRwYvwSFQuEMFJeFMFIuGME5eHME4uIMEpeJMEouKMEZeLMEYuMMEJeNMEIuOMD5ePMD4uQMDpeRMDouSMDZeTMDYuUMDJeVMDIuWMC5eXMC4uYMCpeZMCouaMCZebMCYucMCJedF+CQQFzxgPFz5gPF8JgMXr5gPF0RgLL0ZgLF0hgJL0pgJF0xgHL05gHF1BgFL1JgFF1QwDF1gA/AH4A/AH4AJA=";
const TX = "k8XwkBiIAYEYogLHBAUIiBNKGxooKEggvJCYYHDKxAMFAoRrOCRAsHCYqbNHQibLKAauOLBCJHQw6JMQBIJBRJDWJThK5JJJi5KbpaJKFBaKEE5ybGHRhcOACEQA";
// Emojis are pairs with the form [ Image String, Unicode code point ]
// For code points see https://unicode.org/emoji/charts/emoji-list.html
const EMOJIS = [
[ ':)', 0x1f642 ], // Slightly smiling
[ ':|', 0x1f610 ], // Neutral
[ ':(', 0x1f641 ], // Slightly frowning
[ '+1', 0x1f44d ], // Thumbs up
[ '-1', 0x1f44e ], // Thumbs down
[ '<3', 0x02764 ], // Heart
[ GRIN, 0x1f642 ], // Slightly smiling
[ MEH, 0x1f610 ], // Neutral
[ FROWN, 0x1f641 ], // Slightly frowning
[ THUMBS_UP, 0x1f44d ], // Thumbs up
[ THUMBS_DOWN, 0x1f44e ], // Thumbs down
[ HEART, 0x02764 ], // Heart
];
const EMOJI_TRANSMISSION_MILLISECONDS = 5000;
const BLINK_PERIOD_MILLISECONDS = 500;
const TRANSMIT_BUZZ_MILLISECONDS = 200;
const CYCLE_BUZZ_MILLISECONDS = 50;
const WELCOME_MESSAGE = 'Emojuino:\r\n\r\n< Swipe >\r\nto select\r\n\r\nTap\r\nto transmit';
// Non-user-configurable constants
const IMAGE_INDEX = 0;
const CODE_POINT_INDEX = 1;
const EMOJI_PX = 96;
const EMOJI_X = (g.getWidth() - EMOJI_PX) / 2;
const EMOJI_Y = (g.getHeight() - EMOJI_PX) / 2;
const TX_X = 68;
const TX_Y = 12;
const FONT_SIZE = 24;
const BTN_WATCH_OPTIONS = { repeat: true, debounce: 20, edge: "falling" };
const UNICODE_CODE_POINT_ELIDED_UUID = [ 0x49, 0x6f, 0x49, 0x44, 0x55,
0x54, 0x46, 0x2d, 0x33, 0x32 ];
// Global variables
let emojiIndex = 0;
let isToggleOn = false;
@ -72,6 +91,7 @@ function transmitEmoji(image, codePoint, duration) {
require('ble_eddystone_uid').advertise(UNICODE_CODE_POINT_ELIDED_UUID,
instance);
isTransmitting = true;
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX], true);
let displayIntervalId = setInterval(toggleImage, BLINK_PERIOD_MILLISECONDS,
image);
@ -85,14 +105,14 @@ function terminateEmoji(displayIntervalId) {
NRF.setAdvertising({ });
isTransmitting = false;
clearInterval(displayIntervalId);
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX], false);
}
// Toggle the display between image/off
function toggleImage(image) {
if(isToggleOn) {
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX], true);
}
else {
g.clear();
@ -102,9 +122,15 @@ function toggleImage(image) {
// Draw the given emoji
function drawImage(image) {
function drawImage(image, isTx) {
g.clear();
g.drawString(image, g.getWidth() / 2, g.getHeight() / 2);
g.drawImage(require("heatshrink").decompress(atob(image)), EMOJI_X, EMOJI_Y);
if(isTx) {
g.drawImage(require("heatshrink").decompress(atob(TX)), TX_X, TX_Y);
}
else {
g.drawString("< Swipe >", g.getWidth() / 2, g.getHeight() - FONT_SIZE);
}
g.flip();
}
@ -131,15 +157,15 @@ function handleDrag(event) {
// Special function to handle display switch on
Bangle.on('lcdPower', (on) => {
if(on) {
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX], false);
}
});
// On start: display the first emoji and handle drag and touch events
g.clear();
g.setFont('Vector', 80);
g.setFont('Vector', FONT_SIZE);
g.setFontAlign(0, 0);
drawImage(EMOJIS[emojiIndex][IMAGE_INDEX]);
g.drawString(WELCOME_MESSAGE, g.getWidth() / 2, g.getHeight() / 2);
Bangle.on('touch', handleTouch);
Bangle.on('drag', handleDrag);

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1 +1 @@
require("heatshrink").decompress(atob("mEwghC/AEkIxAABwUiAAwKBC6+AC6ERiIXDGBAXPGA8JzIAByQXKGA4XUA4eDmYAGJwQXVxEizAXPIgIXDwWZC6uIxIwCC6eIGAQX/C9i/FC5mCCw0yC5wAMC/4Xnx//ABf4C/Xzdw8zn4XkL/5f/L+oUDI6YX3AB4XeAH4AdA=="))
require("heatshrink").decompress(atob("mEw4cA///7c0AYMXlm3gf42s1yvb5xT/ABdJkmStu27YCCtMkCKOACJdm7YRCyARQyQRLBwIRDoARTgVLtu3K4tJl4RQkvpCJdbtwRBkm5CKGZCKGTCKGSsgR/R4gRHpIMBCInaCJIIBARAR/CJtPB5FLCI1KEhMSCLN//4AE/QRbI/5H/CI4PCGpwRXp4RIpZFDCIQiJAQIRWAH4AGA"))

View File

@ -4,3 +4,4 @@
0.04: Setting to disable touch controls, minor bugfix
0.05: Setting to disable double/triple press control, remove touch controls setting, reduce fadeout flicker
0.06: Bangle.js 2 support
0.07: Fix "previous" button image

View File

@ -303,7 +303,7 @@ function drawControls() {
l.up.col = cc("volumeup" in tCommand);
l.down.col = cc("volumedown" in tCommand);
}
l.prev.icon = (stat==="play") ? "pause" : "prev";
l.prev.icon = (stat==="play") ? "pause" : "previous";
l.prev.col = cc("prev" in tCommand || "pause" in tCommand);
l.next.icon = (stat==="play") ? "next" : "play";
l.next.col = cc("next" in tCommand || "play" in tCommand);

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -26,3 +26,4 @@
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
0.25: Fix issue where if Bangle.js 2 got a GPS fix but no reported time, errors could be caused by the widget (fix #935)

View File

@ -26,6 +26,7 @@
fixToggle = !fixToggle;
WIDGETS["gpsrec"].draw();
if (hasFix) {
if (fix.time===undefined) fix.time = new Date(); // Bangle.js 2 can provide a fix before time it seems
var period = fix.time.getTime() - lastFixTime;
if (period+500 > settings.period*1000) { // round up
lastFixTime = fix.time.getTime();

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -1 +1,3 @@
0.01: New App!
0.02: Remove messages on disconnect
0.03: Handling of message actions (ok/clear)

View File

@ -95,7 +95,14 @@ E.on('AMS',a=>{
Bangle.musicControl = cmd => {
// play, pause, playpause, next, prev, volup, voldown, repeat, shuffle, skipforward, skipback, like, dislike, bookmark
NRF.amsCommand(cmd);
}
};
// Message response
Bangle.messageResponse = (msg,response) => {
if (isFinite(msg.id)) return NRF.sendANCSAction(msg.id, response);//true/false
// error/warn here?
};
// remove all messages on disconnect
NRF.on("disconnect", () => require("messages").clearAll());
/*
// For testing...

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,2 +1,5 @@
0.01: Launch app
0.01: Launch app.
0.02: Swipe left/right to set an alarm.
0.03: New design with different icons if gps, hrm or compass is on.
0.04: Inluded LCARS Logo.
0.05: Additional icons for (1) charging and (2) bat < 30%.

View File

@ -11,6 +11,9 @@ the [Pedometer widget](https://banglejs.com/apps/#pedometer%20widget).
* Shows the number of daily steps
* Swipe left/right to activate an alarm
## Icons
<div>Icons made by <a href="https://www.flaticon.com/authors/smashicons" title="Smashicons">Smashicons</a>, <a href="https://www.freepik.com" title="Freepik">Freepik</a> from <a href="https://www.flaticon.com/" title="Flaticon">www.flaticon.com</a></div>
## Creator
Made by [David Peer](https://github.com/peerdavid)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

BIN
apps/lcars/bg_large.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
apps/lcars/bg_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -3,11 +3,48 @@
*/
const locale = require('locale');
var alarm = -1;
var hrmValue = "-";
var img = {
var backgroundImage = {
width : 176, height : 151, bpp : 3,
transparent : 0,
buffer : require("heatshrink").decompress(atob("gF58+eAR14IN1fvv374CN7yD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/AH4A/AH4A/AB1z588+YCN+RBuj158+eARyD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf4AUhyD/gEDQaHz4BCuQaNAIN0PQaHIIN0BQaF5IN0AQaHPkBBug6DQ8iEvQaE8yBBuhyDPAQNAINsBQaACBkhCuQaACpVo0cQaACo4CFGjyD/AAMPQf4ACQf4ADgiD+AH4A/AH8J02atICIwEAgPnz15AR3gEgM27dt2wCTF4IABgYROgN9+/fAR14ILsaQBKDakwjKF5oABKZ6DwgxTPQeEmQf5cPQeMBLhyDxgJTRQd0JKaKDuhKD/gENQf6D/F4VNQf8AKaKDvKBYnBAGZQKzBB1QZOwIGqDJsBA2QZJA3QZGYIPCDH4CD/0xA4QY+wIPKDGwCD/tpB6Qf6DHthA5QY1oIPSD/QY9gQf/bIPaD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/AF8JQYgCdsEHnnz54CJgIdLwEAhqDEATtggPnz15ARHkgIdLIIKAgQcCAgQcAA/gAA=="))
transparent : 2,
buffer : require("heatshrink").decompress(atob("AAdx48cATojCufPnnzASocCyVJkgCdyAkCh158+eASsAgMHQDyDggKAeQcKAgQYodZgRoFpAkCAG0QJQtwIPMSQYtAIPLOGQfSADAQRA5Qf6D6g/gQf8H/iD/n//wCD9gP/Qf5BBQf5BC+CD9h5BB/yD8jl/IIPx46D6g4/BQYU//+AQe8B/6DD//Hj/x4CD2v/4AQJBC4ED/4IBQegvBPQJBERgSD1j/wgB9BAASACn/gQepECIIaACg/8QeY1DQYjCD/+AQeUHQZSPDwUIkACDQdT7DIJEfQYIAxg44DIJHwIOU/fwYAERgUDIOUBPQhBE/hB1QZRBFjlx44CDuBBpg4CCHwdxIIcfIIPnz15AQeAQdT+CIIXgZwJBDHAM8+fPAQbOqQY0AIIkcAQKDxg44BIIX4RgX/GoICCQeR3BIIXARIfwJoSDyfYI4B//+BAaABn/gAoKDxfYNx459BJQnx/4FCQeUAv7EBIIv//AFCQeUAgPH/lwAwUHQYPAQe0An6EBAAfj/wMDQeZ9B/jIC//HgCJDQe3gAYICCgF+Qe8B/4IGIIiD0nAHGhyD3ABqD0ABiD/Qf4ADjiD/gEnQYuQQf6D7gaDFzxB5gFzQYnz4JB5hyDFATfkEwUN23btoCVgEBQYoCcIIRhZDYMJQf4ABjiD/AH4A/AH4AGiFx48cATokCufPnnzASocCyVJkgCdyAkCj158+eASsAgKAfQcEJQDyDhNA8QoMEAQIqCACweEASkCNAtIHbIAfdI1wIPMSQYtAQf6D7QAYCCIHKD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/AH4A/AH4A/AH4Asjlx44CDsBB57dt2wCDQfWevPnAQaD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf4Akjlx44CDQfQA/AH4A/AH4A/ABM8+fPAQfwIPPnz15AQeAQf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf4AZjiD/gEHQYuQQf6D7gaDFzxB5gFzQYnz48cuICZEwQdZgECQYoCb8hBChMkyVJASsAgPHQYgCcQboABQf4ABfzACIQbg="))
}
var iconPlanet = {
width : 50, height : 50, bpp : 3,
transparent : 5,
buffer : require("heatshrink").decompress(atob("23btoCD6PHjlx9oLGAQuGiVJkmSpIRK2lxEYQCDCJOGjEhEYNBwUI5drEw/xEYwCB8oRGDoMhwmSsAFBkGM237NZICGj15OgnaDoOGI4cgwUa5dv332EwdHEZACB8+evYRCtAdBEAQpDscs3379+9HAW8EZPHz158+WSQQjFwUYsMs2QjBEwPrSRZuCJQN5TAJuCEYkhwUS5cvJQRxCNxZKDOIXgJQkh0mYtMk2XLJQXv1u0EZSVDOIWsJQsSpMkyVJljgB9gmB7YjLOgtq4BKEsIjCAQNLlgCBt+9EZwCCj8sJQpxB00aJoYCB5cBEZ4CB+RKFJoeGjAjCoOGzBKaAQeGJQQFBwJKSsAjIcweSBwRKRjojKOgYFCxZKRtAaBjHrlm4FJUN3hKQi3ShAjB2XLAQQmI7dHJR97tsh9gjEAQLpHlu2+PnExvF23an3794mF2BKFm3btsevImMjwRB23v3wmB3xNF5BuDCIPb8+eEwOeExIRCtojCJo5uEEwRxBEwRuJHAdI+YmCTYlgJQIREtrjCEwLdHCIiYBhF7OgnJSQgmFjhxCOgiSDAQvSX4QmB90IkQRIX4gmCEZICDvwmCBY3QA"))
}
var iconGps = {
width : 50, height : 50, bpp : 3,
transparent : 2,
buffer : require("heatshrink").decompress(atob("pMkyQCFpH0BAwCJv/6CJ8l589CJ0kyf//wIDpVEChM8+/fBAdZ8QRIp++///0gIBlMkxI4IuZKB+/SKAPHzpKJ/YkB//pKAP2BYeXhIFDx88+fPvqYBnibEkmUAofv34lC/RQBBYdcmPCXIYjBEwPfvnzJoILBQoUlHAUuJQYmCDodw48cuBKGTA0WEYIEBJQ6YEQwMMuImBJQyYEkmZFAVkyVSJQ6YCyUcmPDjgmBTAJKETAlJiS4ETANPJQpxCJQtxTALgBEwnfvohBI4NZkmWpNlcAgAD/wzBEYaYCy8cJQiYEyIjCTAWS3wlGTAVIEwkerJKFTAkmOIclToK8GAAIPBIgImCufHyxxG59pEIS8DvfypMr968HEwOHEwfx8+cEYkpCIeSoiYByVf/uSkmTEQP7ZIiYDnl5AQNwBYgCGyOn38k2+2pIRKyVeuPPj1x4ccCJVKSgP/5cJA4NSExMps+cSoMMKAIVCCg7SBpd7TANZkmUHBMevPnjlwcwXCCJFEzYDBA4WWKIIRHpEw4+eNwUxEwKYIkVJk1IyIKFHA+DR4VcJQYCBJRBoCkxHBAgNkyyYKkmXEYaYMAQMSEYKYNAQOHEwnSfBYjBAgVaCJdJJSMkTAK8KYQyVKAQ4jBNxiYEcBCYJXIkgA="))
}
var iconCompass = {
width : 50, height : 50, bpp : 3,
transparent : 2,
buffer : require("heatshrink").decompress(atob("pMkyQCDl//AAPSBYwCFv4RCAAOkCJNLCAgACCJm2rNn34FB+g1Jvny5cs2XPn///QRI9uWEYP2rNly5NHNYN82YjB/4mC5YmBOgkl//9y1bsuW/4CB/Nlz//9I4D3/8I4M8EAICB55NCL4g/BIgRKBAQtnL4lf+QdCI4YCD2Y4DSQPZtojHsuerI4Dv/flnzEZB3CHAJuB8ojIAQY4CNwJHI2XHTAY4B/4gJrGBAoSqBpf2EZMQmRxEv/5Nw9YyVCAoO+rf/0v/Nw/PjFB4ZxCn/+y7dBJQyNBkAIDz/6/7dBJQsYsMEhgsE//+7IjFsTYBwAIE/4ABEYs8uPEiFyF4gRBXIImEBAPSpAjDtuX//9+YmERgMcuODBAU9+xKCr68Ev4lBNwm//IJCnhxDDQPx4xuFJQhBDDQXwTwpKBSos8//HjlwYQyVG34aB2zCG//1Nw6SFAQTgD/JuD+wjFrbgCr/yMQI+B/lxEY08UgPpl4jCNwP+I4wCBUgOk3/8DoXxI44CBn/0yREDzx0EAQlndANJv4gJAQf3/VJkq8CJoZuGXIPpkg4BOIZuI5/9CII4BEZAmDNwIRBHAJxDNxH+CII4CSQW+NALgBtomBt5uCHAbjB2ZoCAQPyJQP/NwIRCkm//4gBIgP/SQn/CImSYALjDviSDQAYUDL4ImEEYYRGL4X/76PCI4P/SQYCFl4MBAAgRJEwYRPOgZrHpMgA"))
}
var iconAlarm = {
width : 50, height : 50, bpp : 3,
transparent : 1,
buffer : require("heatshrink").decompress(atob("kmSpICEp//BAwCJn/+CJ8k//5CKAABCJs8uPH//x48EI5YjCAARNKEYUcv//jgFBExEnEYoAC+QmHIgIgC/gpCuPBCI2fIgU4AQXjA4P8CIuTEYZKBAolwHApXBEAWP//jxwpBAALaFDoYCIiQmDDIP4EAT+CEwnJEwYjLAQLaFEYomDKALmDNwoCIOIZuD8AkFgCYDHAQjMAQTdDNwOAEg0Dx0/cYeREZtxQYOTHgJuHOIvkXJy8DNwIACJQ8Ah4NDAAfxEZARHOIIkHg4jQAQb1CQ4KVJgEOnDIBSoIjNAQPBcAaVJcAKVBcDGOcD7OBMQM48BuH8f//JKCnhKNggRBkmfTQJxBEwhuD/gRCyVHJRlyCIVJXgYmB8ZQBAoIKBXIQmCOIt/NxAUCOIImCIgIpCBAJuDAQZEE/huIAQWTDgImBTYQGC8gRFcYpKFCI8kDwQAFCJBfBEAX/+IjBiQRIEw4jJAQc8v//NYwCIOgJrIJpA1OcwbaFAQWQA="))
}
var iconCharging = {
width : 50, height : 50, bpp : 3,
transparent : 5,
buffer : require("heatshrink").decompress(atob("23btugAwUBtoICARG0h048eODQYCJ6P/AAUCCJfbo4SDxYRLtEcuPHjlwgoRJ7RnIloUHoYjDAQfAExEAwUIkACEkSAIEYwCBhZKH6EIJI0CJRFHEY0BJRWBSgf//0AJRYSE4BKLj4SE8BKLv4RD/hK/JS2AXY0gXwRKG4cMmACCJQMAg8csEFJQsBAwfasEAm379u0gFbcBfHzgFBz1xMQZKBjY/D0E2+BOChu26yVEEYdww+cgAFCg+cgIfB6RKF4HbgEIkGChEAthfCJQ0eEAIjBBAMxk6GCJQtgtyVBwRKBAQMbHAJKGXIIFCgACBhl54qVG2E+EAJKBJoWAm0WJQ6SCXgdxFgMLJQvYjeAEAUwFIUitEtJQ14NwUHgEwKYZKGwOwNYX7XgWCg3CJQ5rB4MevPnAoPDJRJrCgEG/ECAoNsJRUwoEesIIBiJKI3CVDti/CJRKVDiJHBSo0YsOGjED8AjBcAcIgdhcAXAPIUAcAYIBcA4dBAQUG8BrBgBuCgOwcBEeXIK2BBAIFBgRqBGoYAChq8CcYUE4FbUYOACQsHzgjDgwFBCIImBAQsDtwYD7cAloRI22B86YBw5QBgoRJ7dAgYEDCJaeBJoMcsARMAQNoJIIRE6A"))
}
var iconNoBattery = {
width : 50, height : 50, bpp : 3,
transparent : 2,
buffer : require("heatshrink").decompress(atob("pMkyQCoycMmHDhgLEqVECg1Bw0YsOGBAdKpMSEwwjCmHCBAYDBHA4jCjFpBAUpkmJJR0lkmRL49Fy1ZsuWBAWkyQRGxcs2XLAQe0ymSNw9t23bAQnSyVICI1IEYoCBqSAIkwjF7dupMiQA5KH/KSIJQ+5SRBKH2fkSRBKH8iSHJRHPSRBKIH4PSCJBKFn1JhYRIJQqSBkdtJRscSQLgBJRliAwONcAJKM9MkyAFBJRm/AwM2AoJKMUgNCFIJKM7A8BOgRKMmVJg8MJRqSBAwMGJRqSBzVpJRu5kmTpMhJRmz8mQ2emJRqABm3cyK/BJRWPSQUauRKMSQVmpFbJRdSpMLOIODX4JKJpVJkYgB+gCBJRQDBEAQCDJREpkmNEAQCDJQ8lkmQEYpKJ0mScAIjEJRGUyVEcAJKNSQLgBJRqSBiVIJRqSBkTgBJRoDBAIJKNSQOJAoJKN0mRAoJKOyQFCSp4CikAA="))
}
Graphics.prototype.setFontAntonioMedium = function(scale) {
@ -38,56 +75,67 @@ function draw(queue){
g.clearRect(0, 24, g.getWidth(), g.getHeight());
// Draw background image
g.drawImage(img, 0, 24);
g.drawImage(backgroundImage, 0, 24);
// Draw raster
// g.drawLine(112, 100, 112, 165);
for(var x=1; x<7; x++){
g.drawLine(110+x*10, 100, 110+x*10, 160);
}
for(var y=0; y<6; y++){
g.drawLine(113, 105+y*10, 175, 105+y*10);
}
// Draw symbol
var bat = E.getBattery();
var iconImg =
alarm >= 0 ? iconAlarm :
Bangle.isCharging() ? iconCharging :
bat < 30 ? iconNoBattery :
Bangle.isGPSOn() ? iconGps :
Bangle.isCompassOn() ? iconCompass :
iconPlanet;
g.drawImage(iconImg, 120, 107);
// Alarm within symbol
g.setFontAntonioMedium();
if(alarm > 0){
g.setFontAlign(0,0,0);
g.drawString(alarm, 120+25, 107+25);
g.setFontAlign(-1,-1,0);
}
// Write time
var currentDate = new Date();
var timeStr = locale.time(currentDate,1);
g.setFontAlign(0,0,0);
g.setFontAntonioLarge();
g.drawString(timeStr, 100, 50);
g.drawString(timeStr, 60, 55);
// Write date
g.setFontAlign(1,-1, 0);
g.setFontAlign(-1,-1, 0);
g.setFontAntonioMedium();
var dayName = locale.dow(currentDate, true).toUpperCase();
var day = currentDate.getDate();
g.drawString(day, 170, 30);
g.drawString(dayName, 170, 50);
g.drawString(day, 100, 35);
g.drawString(dayName, 100, 55);
// Alarm
// HRM
g.setFontAlign(-1,-1,0);
g.drawString("TMR:", 30, 107);
var alrmText = alarm >= 0 ? "T-"+alarm : "OFF";
g.drawString(alrmText, 65, 107);
// Draw battery
var bat = E.getBattery();
var charging = Bangle.isCharging() ? "*" : "";
g.drawString("BAT:", 30, 127);
g.drawString(charging + bat+ "%", 65, 127);
g.drawString("HRM:", 28, 102);
g.drawString(hrmValue, 63, 102);
// Draw steps
var steps = getSteps();
g.drawString("STEP:", 30, 147);
g.drawString(steps, 65, 147);
g.drawString("STEP:", 28, 122);
g.drawString(steps, 63, 122);
// GPS
var gpsText = Bangle.isGPSOn() ? "ON" : "OFF";
g.drawString("GPS:", 115, 107);
g.drawString(gpsText, 149, 107);
// HRM
var gpsText = Bangle.isHRMOn() ? "ON" : "OFF";
g.drawString("HRM:", 115, 127);
g.drawString(gpsText, 149, 127);
// CMP
var compassText = Bangle.isCompassOn() ? "ON" : "OFF";
g.drawString("CMP:", 115, 147);
g.drawString(compassText, 149, 147);
// Draw battery
g.drawString("BAT:", 28, 142);
g.drawString(bat+ "%", 63, 142);
// Queue draw in one minute
if(queue){
@ -113,6 +161,13 @@ function stepsWidget() {
return undefined;
}
/*
* HRM
*/
Bangle.on('HRM',function(hrm) {
hrmValue = hrm.bpm;
});
/*
* Handle alarm
*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@ -1,3 +1,5 @@
0.01: New App!
0.02: Add 'messages' library
0.03: Fixes for Bangle.js 1
0.04: Add require("messages").clearAll()
0.05: Handling of message actions (ok/clear)

View File

@ -16,7 +16,8 @@
{"t":"add","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"}
// maps
{"t":"add","id":1,"src":"Maps","title":"0 yd - High St","body":"Campton - 11:48 ETA","img":"GhqBAAAMAAAHgAAD8AAB/gAA/8AAf/gAP/8AH//gD/98B//Pg/4B8f8Afv+PP//n3/f5//j+f/wfn/4D5/8Aef+AD//AAf/gAD/wAAf4AAD8AAAeAAADAAA="}
// call
{"t":"add","id":"call","src":"Phone","name":"Bob","number":"12421312",positive:true,negative:true}
*/
var Layout = require("Layout");
@ -55,9 +56,16 @@ function saveMessages() {
function getBackImage() {
return atob("FhYBAAAAEAAAwAAHAAA//wH//wf//g///BwB+DAB4EAHwAAPAAA8AADwAAPAAB4AAHgAB+AH/wA/+AD/wAH8AA==");
}
function getPosImage() {
return atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA==");
}
function getNegImage() {
return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA=");
}
function getMessageImage(msg) {
if (msg.img) return atob(msg.img);
var s = (msg.src||"").toLowerCase();
if (s=="Phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA=");
if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA==");
if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA=");
if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA==");
@ -154,6 +162,28 @@ function showMessage(msgid) {
if (g.setFont(titleFont).stringWidth(title) > w)
title = g.wrapString(title, w).join("\n");
}
var buttons = [
{type:"btn", src:getBackImage(), cb:()=>checkMessages(true)}, // back
msg.new?{type:"btn", src:atob("HRiBAD///8D///wj///Fj//8bj//x3z//Hvx/8/fx/j+/x+Ad/B4AL8Rh+HxwH+PHwf+cf5/+x/n/PH/P8cf+cx5/84HwAB4fgAD5/AAD/8AAD/wAAD/AAAD8A=="), cb:()=>{
msg.new = false; // read mail
saveMessages();
checkMessages();
}}:{}
];
if (msg.positive) {
buttons.push({type:"btn", src:getPosImage(), cb:()=>{
msg.new = false; saveMessages();
Bangle.messageResponse(msg,true);
checkMessages();
}});
}
if (msg.negative) {
buttons.push({type:"btn", src:getNegImage(), cb:()=>{
msg.new = false; saveMessages();
Bangle.messageResponse(msg,true);
checkMessages();
}});
}
layout = new Layout({ type:"v", c: [
{type:"h", fillx:1, bgCol:colBg, c: [
{ type:"img", src:getMessageImage(msg), pad:2 },
@ -163,14 +193,7 @@ function showMessage(msgid) {
]},
]},
{type:"txt", font:fontMedium, label:msg.body||"", wrap:true, fillx:1, filly:1, pad:2 },
{type:"h",fillx:1, c: [
{type:"btn", src:getBackImage(), cb:()=>checkMessages(true)}, // back
msg.new?{type:"btn", src:atob("HRiBAD///8D///wj///Fj//8bj//x3z//Hvx/8/fx/j+/x+Ad/B4AL8Rh+HxwH+PHwf+cf5/+x/n/PH/P8cf+cx5/84HwAB4fgAD5/AAD/8AAD/wAAD/AAAD8A=="), cb:()=>{
msg.new = false; // read mail
saveMessages();
checkMessages();
}}:{}
]}
{type:"h",fillx:1, c: buttons}
]});
g.clearRect(Bangle.appRect);
layout.render();
@ -178,12 +201,15 @@ function showMessage(msgid) {
function checkMessages(forceShowMenu) {
// If no messages, just show 'no messages' and return
if (!MESSAGES.length)
return E.showPrompt("No Messages",{
if (!MESSAGES.length) {
if (forceShowMenu) return E.showPrompt("No Messages",{
title:"Messages",
img:require("heatshrink").decompress(atob("kkk4UBrkc/4AC/tEqtACQkBqtUDg0VqAIGgoZFDYQIIM1sD1QAD4AIBhnqA4WrmAIBhc6BAWs8AIBhXOBAWz0AIC2YIC5wID1gkB1c6BAYFBEQPqBAYXBEQOqBAnDAIQaEnkAngaEEAPDFgo+IKA5iIOhCGIAFb7RqAIGgtUBA0VqobFgNVA")),
buttons : {"Ok":1}
}).then(() => { load() });
load();
return;
}
// we have >0 messages
// If we have a new message, show it
if (!forceShowMenu) {
@ -194,7 +220,7 @@ function checkMessages(forceShowMenu) {
// Otherwise show a menu
E.showScroller({
h : 48,
c : MESSAGES.length+1,
c : Math.min(MESSAGES.length+1,3), // workaround for 2v10.219 firmware (min 3 not needed for 2v11)
draw : function(idx, r) {"ram"
var msg = MESSAGES[idx-1];
if (msg && msg.new) g.setBgColor(colBg);
@ -235,4 +261,4 @@ function checkMessages(forceShowMenu) {
g.clear();
Bangle.loadWidgets();
Bangle.drawWidgets();
checkMessages();
checkMessages(true); // force showing a menu

View File

@ -28,10 +28,25 @@ exports.pushMessage = function(event) {
// otherwise load after a delay, to ensure we have all the messages
if (exports.messageTimeout) clearTimeout(exports.messageTimeout);
exports.messageTimeout = setTimeout(function() {
exports.messageTimeout = undefined;
exports.messageTimeout = undefined;
// if we're in a clock or it's important, go straight to messages app
if (Bangle.CLOCK || event.important) return load("messages.app.js");
if (!global.WIDGETS || !WIDGETS.messages) return Bangle.buzz(); // no widgets - just buzz to let someone know
WIDGETS.messages.newMessage();
WIDGETS.messages.show();
}, 500);
}
exports.clearAll = function(event) {
var messages, inApp = "undefined"!=typeof MESSAGES;
if (inApp) {
MESSAGES = [];
messages = MESSAGES; // we're in an app that has already loaded messages
} else // no app - empty messages
messages = [];
// Save all messages
require("Storage").writeJSON("messages.json",messages);
// update app if in app
if (inApp) return onMessagesModified();
// if we have a widget, update it
if (global.WIDGETS && WIDGETS.messages)
WIDGETS.messages.hide();
}

View File

@ -10,11 +10,15 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() {
Bangle.buzz(); // buzz every 4 seconds
}
setTimeout(()=>WIDGETS["messages"].draw(), 1000);
},newMessage:function() {
},show:function() {
WIDGETS["messages"].t=Date.now(); // first time
WIDGETS["messages"].l=Date.now()-10000; // last buzz
if (WIDGETS["messages"].c!==undefined) return; // already called
WIDGETS["messages"].width=64;
Bangle.drawWidgets();
Bangle.setLCDPower(1);// turns screen on
},hide:function() {
delete WIDGETS["messages"].t;
delete WIDGETS["messages"].l;
WIDGETS["messages"].width=0;
Bangle.drawWidgets();
}};

View File

@ -4,3 +4,4 @@
0.04: App shows instructions, Widgets remain visible, color changed
0.05: Buzz intensity and beats per bar can be changed via settings-app
0.06: Correct string position
0.07: Add support for Bangle.sjs2

View File

@ -4,11 +4,12 @@ This metronome makes your watch blink and vibrate with a given rate.
## Usage
* Tap the screen at least three times. The app calculates the mean rate of your tapping. This rate is displayed in bmp while the text blinks and the watch softly vibrates with every beat.
* Use `BTN1` to increase the bmp value by one.
* Use `BTN3` to decrease the bmp value by one.
* Tap the screen at least three times. The app calculates the mean rate of your tapping. This rate is displayed in bpm while the text blinks and the watch softly vibrates with every beat.
* Use `BTN1` to increase the bpm value by one.
* Use `BTN3` to decrease the bpm value by one.
* You can change the bpm value any time by tapping the screen or using `BTN1` and `BTN3`.
* Intensity of buzzing and the beats per bar (default 4) can be changed with the settings-app. The first beat per bar will be marked in red.
* On Bangle.js 2 tapping the center of the screen initiates bpm. in- or decreasing bpm can by 1 can be done by tapping left or right site of the screen.
## Attributions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -3,10 +3,9 @@ var cindex=0; // index to iterate through colous
var bpm=60; // ininital bpm value
var time_diffs = [1000, 1000, 1000]; //array to calculate mean bpm
var tindex=0; //index to iterate through time_diffs
Bangle.setLCDTimeout(undefined); //do not deaktivate display while running this app
// set background colour
g.setTheme({bg:"#000"});
Bangle.setLCDTimeout(undefined); //do not deactivate display while running this app
const storage = require("Storage");
const SETTINGS_FILE = 'metronome.settings.json';
@ -15,7 +14,7 @@ function setting(key) {
//define default settings
const DEFAULTS = {
'beatsperbar': 4,
'buzzintens': 0.75,
'buzzintens': 1.0,
};
if (!settings) { loadSettings(); }
return (key in settings) ? settings[key] : DEFAULTS[key];
@ -40,6 +39,10 @@ function changecolor() {
7: { value: 0xFFFF, name: "White" },
};
g.setColor(colors[cindex].value);
if ((process.env.HWVERSION==2 )) {
g.drawLine(39,0,39,g.getWidth()/3);
g.drawLine(136,0,136,g.getWidth()/3);
}
if (cindex == setting('beatsperbar')-1) {
cindex = 0;
}
@ -50,43 +53,73 @@ function changecolor() {
}
function updateScreen() {
g.reset().clearRect(0, 50, 250, 150);
g.reset().clearRect(0, 50, 250, 120);
changecolor();
try {
Bangle.buzz(50, setting('buzzintens'));
} catch(err) {
}
g.setFont("Vector",40).setFontAlign(0,0);
g.drawString(Math.floor(bpm)+"bpm", g.getWidth()/2, 100);
g.drawString(Math.floor(bpm)+"bpm", g.getWidth()/2, g.getWidth()/2);
}
Bangle.on('touch', function(button) {
// setting bpm by tapping the screen. Uses the mean time difference between several tappings.
if (tindex < time_diffs.length) {
if (Date.now()-tStart < 5000) {
time_diffs[tindex] = Date.now()-tStart;
}
} else {
tindex=0;
time_diffs[tindex] = Date.now()-tStart;
}
tindex += 1;
mean_time = 0.0;
for(count = 0; count < time_diffs.length; count++) {
mean_time += time_diffs[count];
}
time_diff = mean_time/count;
//Write user instructuins to screen
function printInstructions() {
g.clear(1).setFont("4x6");
g.setColor(-1); //set color to white
g.drawString('Drum the beat on the center\nof the screen to set tempo.', 30, g.getWidth()/3*2+15);
if(process.env.HWVERSION==1) {
g.drawString('Use BTN1 to increase, and\nBTN3 to decrease bpm value by 1.', 30, g.getWidth()/3*2+30);
}
else {
g.drawString('Touch left part of the screen\nto decrease, or the right site\nto increase bpm value by 1.', 30, g.getWidth()/3*2+30);
}
}
tStart = Date.now();
clearInterval(time_diff);
bpm = (60 * 1000/(time_diff));
updateScreen();
clearInterval(interval);
interval = setInterval(updateScreen, 60000 / bpm);
return bpm;
Bangle.on('touch', function(zone, e) {
// setting bpm by tapping the screen. Uses the mean time difference between several tappings.
if ((process.env.HWVERSION==2 && e.x > 39 && e.x < 136) || process.env.HWVERSION==1){
if (tindex < time_diffs.length) {
if (Date.now()-tStart < 5000) {
time_diffs[tindex] = Date.now()-tStart;
}
} else {
tindex=0;
time_diffs[tindex] = Date.now()-tStart;
}
tindex += 1;
mean_time = 0.0;
for (count = 0; count < time_diffs.length; count++) {
mean_time += time_diffs[count];
}
time_diff = mean_time/count;
tStart = Date.now();
clearInterval(time_diff);
bpm = (60 * 1000/(time_diff));
updateScreen();
clearInterval(interval);
interval = setInterval(updateScreen, 60000 / bpm);
return bpm;
}
else if (e.x < 39) {
if (bpm > 1) {
bpm -= 1;
clearInterval(interval);
interval = setInterval(updateScreen, 60000 / bpm);
}
}
else if (e.x > 136) {
if (bpm > 1) {
bpm += 1;
clearInterval(interval);
interval = setInterval(updateScreen, 60000 / bpm);
}}
});
// enable bpm finetuning via buttons.
// enable bpm finetuning
if ((process.env.HWVERSION==1)) {
setWatch(() => {
bpm += 1;
clearInterval(interval);
@ -101,10 +134,10 @@ setWatch(() => {
}
}, BTN3, {repeat:true});
}
interval = setInterval(updateScreen, 60000 / bpm);
printInstructions();
g.clear(1).setFont("6x8");
g.drawString('Touch the screen to set tempo.\nUse BTN1 to increase, and\nBTN3 to decrease bpm value by 1.', 25, 200);
Bangle.loadWidgets();
Bangle.drawWidgets();

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@ -34,14 +34,12 @@ function getApp() {
var ir = require("heatshrink").decompress(atob("jk0ggGDhvdAAXQCYwMEBxAMFAAIaH6c/+c9DgwMC/8zDg4aC/4YCHIwNB7/zHAwNCAgM/DQwqDAYIaHBonT/oNMFBAND74NNBhApEBrQAKBrrrGWpANZHBT7FBpYqIFAYcJBgkA5oMF7gNFFQwoFDgwMHHIoMIAAPM5gMKBrk0oANLmcwBu0zBrMDBv4AFN5gA/ADYA="));
var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/+c3DgwMC/8yDg4aC/4YCHIwNBv/zHAwNCAgM/DQwqDAYIaHBolz+4NMFBANDv8nBpgMIFIgNaABQNddYy1IBrI4KfYoNLFRAoDDhIMEgHnBgt+BooqGFAoqGBg4OFBhAODBhQNcmUgBpczmAN2mYNZgYN/AApvMAH4Ab"));
var igift = require("heatshrink").decompress(atob("q1QxH+ADOi0QbZ5nMHDQAbKgIACKa4ACKnJWVKghW0KgxWTKgxWyKhBWRKhBWwKhRWPKhRWuKhhWNKhhWtKpxWKKhys8KxBU8Ky5U+KypU/KyhU/KyhU/KynGKn5WTKn5WUKmHCADpJJE7uYABZUfKuuYKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/AAv+Kv5VT/wADyIAaKpIlbABZSEKv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/Kv5V/ADNtKv6rdKzZVwKhAABy5V/Khw"));
var W=240,H=240;
var blns = [];
function updateFlake(f) {
f.im = [ir,ig,ib][Math.round(Math.random()*100)%3];
f.s = 0.4+Math.random()*0.5;
}
for (var i=0;i<6;i++) {
var f = {
y:Math.random()*H,x:(0.5+(i<3?i:i+5))*W/11,
@ -51,7 +49,6 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/
updateFlake(f);
blns.push(f);
}
function draw() {
blns.forEach(f=>{
f.y-=f.v;f.r+=f.t;
@ -71,7 +68,6 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/
g.drawString(${JSON.stringify(line4)},x,y+=10);
g.flip();
}
g.clear();
setInterval(draw,50);
})()`;
@ -79,7 +75,6 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/
return `(function() {
var isnow = require("heatshrink").decompress(atob("jEagQWTgfAAocf+gFDh4FDiARBggVB3AFBl3Agf8jfkn/AgX/v/9/+Agfv/2//YrBgfwh4wCgfghYFJCIYdFFIw1EIIpNFL44FFOIoAP"));
var itree = require("heatshrink").decompress(atob("mtWxH+ADHHDTI0aGuXH5vNGmhqvTYIzBGtoxF6fTG4g4oGgQyBAAZssGoI0Ga1g1FGdo01ZgIAEGmHHNoLSuAAN/rdb0YFBGlgCBGYIABA4YArGYY1CGn4znAAM6GeVd5PQ5Iyurc/vQ0oGZFAn+d4XC3d5GddiGYIEBy+7zoEBGlFhoEcsQ9GT08+oFk1mkGdaVBMgNArnJ6/KzswGs/J6GlrlbqtbvPC5PCy8wGohniMIPJvIpCqmX3e7vI0BqhqlMIY0DqhtBqoEBa0xgBMIIoEqoABGQwzfsIhBv4qHABM50vQGjg1CGaN66DoBGt1ioGd5LoBGjo1PGYNhvLoCa7wnBqgvGA4YzCAgN5GUAsCqoDBmAHCAYU/wPQ0oSDGcBiDqkwAYcxoFd5PX6GdGjrIIqtUAAc3jk5vPC4fCy5pef5I2BTQMcnAHBy+7y95T0oADnFk1ekBpI2aGRUin7NGAA9hsIzVsIgHTAKZBZoPJ5LNDGhBpXGolcwOsrtcA4TNB3bNDGb/+sVin9AoGe6HX5InEvN/TkP+5XQwM/sRsBzqWB4QuKGjvC6HQ4QdDvKWBZYMwmAuHmFUCYNbqibX3fD5O7qolEZQQ0FBwgKDqgJBGiphEDwNUEgJbBFIQqCAgYOCB4IzCnE6GyhYFGoQnDABYzGAAQ1UAAo2NBoQSBnOB0t/Gjo2EABIPCoGe6HX4QzTGRIAEqtVF4QEBBQc4oE4y/J5PCvIxeABk/oADBvO73eXTyAyZMwM/Awd5vIOFGslAr2Av4PLNcU/jmA6HX5I1KasFcn8dTIOd5PJ4SZGGiNhAAIyNn0ckU+ZYe7AAJpJEYJnNGZk+n9kw9cBAcwGoN5aZg1JJJQABm8/oEjoDKC5ALCrUwqh/NrvQ6HDGp04n9doEdoE/sQJBZQZhCqgABGZk6zw0K/1dnVAoNAFwOlCYL1FubJBy4GCGh1AnOX4XC3YzHFYOeCgdV5PQ5OdD4rKBqqYNGYlbv+X3edGY3CGgKMDAAO7JAJgDAClcr2BEYgADaIZ0DL4uXGbDuB6HX5I1GsP+sNhOgWXIhBmWd4Od5PK4TwFGIJoBAYI2BAD0/jlcQoO7AAJaEGQQADGr0/sjNEvOdAoZmDGgw2ZsVAkeAZpQACGZI2VsU/kVGn1bZoPJZogpGGhA4GfRYwBoGC1mlBQbNFFoo0JNxAGCEod/wM6oFAn9iv/J6/Kzo1Ey9/MZQAKCg4GCFgTDEvPCSwI0BC5I0RN4ocEYYPQ5OdHgeXSwTFKGaJyKFYPC3f+MIdbpzFLAD4zB/1OqtbqtOGgYArGAIADGl9UAAI0wGQN5GoQ0vvIABGoI0uGYQABqo0zNOg0uaQY0/GllOGn40//w="));
var W=g.getWidth(),H=g.getHeight();
var flakes = [];
for (var i=0;i<10;i++) {
@ -94,7 +89,6 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/
f.v = f.s * (1+Math.random());
flakes.push(f);
}
function draw() {
flakes.forEach(f=>{
f.y+=f.v;f.r+=f.t;
@ -111,7 +105,6 @@ var ig = require("heatshrink").decompress(atob("jk0ggGDg93AAVwCYwMEBxAMFAAIaHuc/
g.drawString(${JSON.stringify(line4)},x,y+=10);
g.flip();
}
g.clear();
setInterval(draw,50);
})();

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
0.01: App is created with gradient background.

View File

@ -0,0 +1,27 @@
# School Calendar
School Calendar is a calendar that you can see your upcoming classes or schedule.
## Usage:
Enter your calendar events on the customizer then upload. (all day events are not supported yet)
Once uploaded on the watch when in the table mode you can use BTN1 and BTN3 to scroll up and down on the list. (The red rectangle indicates your current position on the table and your yellow rectangle indicates your current schedule item or your next schedule item.)
If you press BTN2 it will go into detail mode, and you can see additional information about your schedule item. Also, in this mode you can scroll up and down with BTN1 and BTN3 to move around in the table. To exit detail mode press BTN2 again.
## Screenshots:
![screenshot (5)](https://user-images.githubusercontent.com/89286474/142801592-485aa0b0-c417-44c8-8097-befa81d2599c.png)
![screenshot (6)](https://user-images.githubusercontent.com/89286474/142801595-47f73c63-501a-4221-baba-84dd97b65bf9.png)
## Updates Coming Soon:
- [ ] Notifications
- [ ] All Day Events
- [ ] Improved Rendering Screen
- [ ] Better Graphics
- [ ] Scrolling Table
- [ ] Bangle.js V2 Compatibility
- [ ] Full Calendar (Calendar that does not have repeating weekly events.)
## Creator
Ronin0000

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwyBC/AH4A/AH4A/AH4A/AH4A/AH4A80s0AIIh/L/5f/EP4ATscsAIo9DBY4BVEJZf/L/5fRznzAIJfdEJZfpymyAJmSBpwPLBZRfqIYYBwL9OMuIBzL9VRAMRTDCJhfymBpkL+GEmABzL9UQAJelinOrPWzQDBymSCpe96+c6YnNL9N794tBAYoFD5152u21t1AoP332MuIPDVIJxB88c///AoODD4gFBLoYJBL9YBT888M4IHDNYPvvoDDznzD5pfq54BT737L4QHCVYQFCL4XTD5pfpueuAKOtqpRBxlRB5JfDEJpfqxwBIG4OOwkw/4AC+++xlxC5ZfBymyDoYlHAIJf0AImEiBbB0s0MIOtuoTJL4glML9NrtoBTLoJTBBpJfCyQfNL9VNAKZfB88cBpJfED5hfslgzEAoT3BxlxBYd795RB2uWC4tjAoQNBC4olFCIZfpFoIBJe4JJB+++AYe964XLL4YPLAIJfqhgBNueuAIJnBCp4BPL9Na9YBBsQBCAoY3BA4YBRC4INPL9oBS5YXWDoxfqJIIByL9NS1QBzL9WKAIgzBAooHFAMBfpMJABqLtYA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4ALA"))

View File

@ -0,0 +1,416 @@
<html>
<head>
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100%;
}
#controls {
padding: 10px;
margin: 10px;
border: 1px solid black;
position:absolute;
right:0px;bottom:0px;
background-color: rgb(255, 255, 255);
z-index: 100;
}
</style>
<link href='fullcalendar/main.css' rel='stylesheet' />
<link rel="stylesheet" href="../../css/spectre.min.css">
</head>
<body>
<div>
<p>Create your events on the week shown. Keep in note that your events repeat weekly.</p>
<p>One you have created your events, Click <button id="upload" class="btn btn-primary">Upload</button>.</p>
<p>All day events are not supported. A feature that lets you get the calendar from your watch will be added in a future update.</p>
</div>
<script src='fullcalendar/main.js'></script>
<script src="../../core/lib/customize.js"></script>
<script>
var calendar;
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
calendar = new FullCalendar.Calendar(calendarEl, {
initialView: 'timeGridWeek',
headerToolbar: {
left: '',
center: 'title',
right: 'timeGridWeek,listWeek'
},
navLinks: true, // can click day/week names to navigate views
editable: true,
selectable: true,
selectMirror: true,
nowIndicator: true,
editable: true,
height: 600,
initialDate: '2018-06-03', // will be parsed as local
select: function(arg) {
var title = prompt('Event Title:');
if (title) {
calendar.addEvent({
title: title,
start: arg.start,
end: arg.end,
allDay: arg.allDay
})
}
calendar.unselect()
},
eventClick: function(arg) {
if (confirm('Are you sure you want to delete this event?')) {
arg.event.remove()
}
},
});
calendar.render();
});
// When the 'upload' button is clicked...
document.getElementById("upload").addEventListener("click", function () {
//Cacultate data:
var calendarEvents = calendar.getEvents();
let schedule = []
//--------------------
for(i=0;i<calendarEvents.length;i++){
var calendarEntry = {}
calendarEntry['cn'] = calendarEvents[i].title;
calendarEntry['dow'] = calendarEvents[i].start.getDate()-3;
calendarEntry['sh'] = calendarEvents[i].start.getHours();
calendarEntry['sm'] = calendarEvents[i].start.getMinutes();
calendarEntry['eh'] = calendarEvents[i].end.getHours();
calendarEntry['em'] = calendarEvents[i].end.getMinutes();
schedule.push(calendarEntry)
}
// build the app's text using a templated String
var app = `
require("Font8x12").add(Graphics);
require("Font7x11Numeric7Seg", 2).add(Graphics);
var file = require("Storage").open("calendarItems.csv","w");
let nIntervId;
function redrawScreen() {
layout.render(layout.background);
layout.render(layout.buttons);
draw();
}
function updateDay(ffunction,day){
if(ffunction == 1){
switch (day) {
case 0:
return "Sunday";
case 1:
day = "Monday";
break;
case 2:
day = "Tuesday";
break;
case 3:
day = "Wednesday";
break;
case 4:
day = "Thursday";
break;
case 5:
day = "Friday";
break;
case 6:
day = "Saturday";
}
return day;
}else if(ffunction == 2){
switch (day) {
case 0:
return "Sun";
case 1:
day = "Mon";
break;
case 2:
day = "Tue";
break;
case 3:
day = "Wed";
break;
case 4:
day = "Thu";
break;
case 5:
day = "Fri";
break;
case 6:
day = "Sat";
}
return day;
}else if(ffunction == 3){
switch (day) {
case 0:
return "S";
case 1:
day = "M";
break;
case 2:
day = "T";
break;
case 3:
day = "W";
break;
case 4:
day = "R";
break;
case 5:
day = "F";
break;
case 6:
day = "S";
}
return day;
}
}
function getScheduleTable() {
let schedule = ${JSON.stringify(schedule)};
logDebug(JSON.stringify(schedule));
return schedule;
}
function findNextScheduleIndex() {
var schedule = getScheduleTable();
var currentDate = new Date();
var minuteOfWeek = (currentDate.getDay()*3600)+(currentDate.getHours()*60)+currentDate.getMinutes();
//var minuteOfWeek = (4*3600)+(16*60)+0;
var currentPosition;
for(currentPosition = 0;currentPosition < schedule.length; currentPosition++){
var scheduleItemStartMinuteOfWeek = schedule[currentPosition].dow*3600 + schedule[currentPosition].eh*60+schedule[currentPosition].em;
if(scheduleItemStartMinuteOfWeek > minuteOfWeek) {
return currentPosition;
}
}
return 0;
}
function getUpArrow() {return require("heatshrink").decompress(atob("hkOyANKmv9AIIjRCoYZRlvdAI8U3YVK3oBJC4Mc7YVRC4sc7gVCzoBNC4oZDGowXGR58lvoBFC9FcAIoXongBFC58dngBFC6EcAIoPHA"));}
function getDownArrow() {return require("heatshrink").decompress(atob("hkOyALImv9AIojPmvdAIoXPlvdAIoXQ3oBFC9GdAIoXnkt9AIoPPAI8U3cc7cc7gBBDIVcAJYXFGYwXOLpU8AI4XBO5sdjgBFR54ZFBpIA=="));}
function getMenuIcon() {return require("heatshrink").decompress(atob("iEQyBC/AEU+rwBEn02js17st3stvklrkljkc/cc3cUzYBBD5AdUD4oA/P/4A/P/4A/ADoA=="));}
function getDotIcon() {return require("heatshrink").decompress(atob("iEQyBC/AA0t3oBBA4ndAIIPGA4gAFkt9lt9AYIHEzoBBBIwRED41cks8AYIJGA44RGP8xtGP44RJBYh1CAIIHHBJJ/KroBBPoqBFB4YRDAA8dngHHBJKdq3oBDBI4RNP4l9AIYHHBJJBJks8AIIHTAH4ABA="));}
var currentPositionTable = 0;
var numberOfItemsShown = 8;
//Table Positions:
var rectStart = 45;
var rectEnd = 65;
var rectStartX = 10;
var rectEndX = 210;
//Scences:
LIST = 1;
INFORMATION = 2;
currentStage = LIST;
function splitter(str, l){
var strs = [];
while(str.length > l){
var pos = str.substring(0, l).lastIndexOf(' ');
pos = pos <= 0 ? l : pos;
strs.push(str.substring(0, pos));
var i = str.indexOf(' ', pos)+1;
if(i < pos || i > pos+l)
i = pos;
str = str.substring(i);
}
strs.push(str);
return strs;
}
function updateMinutesToCurrentTime(currentMinuteFunction) {
if (currentMinuteFunction<10){
currentMinuteUpdatedFunction = "0"+currentMinuteFunction;
}else{
currentMinuteUpdatedFunction = currentMinuteFunction;
}
return currentMinuteUpdatedFunction;
}
function renderBackground(l) {
g.clearRect(0,0,240,20);
g.drawImage(getBackgroundImage(),110,130,{scale:9,rotate:0});
}
function renderTable(l) {
var foundNumber = findNextScheduleIndex();
var yellowIndex = 3;
if (foundNumber < 3) { yellowIndex = foundNumber; }
for(var x = 0;x<=numberOfItemsShown;x++){
g.setColor(255,255,255);
g.drawRect(rectStartX,rectStart+(x*20),rectEndX,rectEnd+(20*x));
}
g.setColor(255,205,0);
g.drawRect(rectStartX,rectStart+(yellowIndex*20),rectEndX,rectEnd+(20*yellowIndex));
g.setColor(255,0,0);
g.drawRect(rectStartX,rectStart+(currentPositionTable*20),rectEndX,rectEnd+(20*currentPositionTable));
}
function renderTableText(l) {
var foundSchedule = getScheduleTable();
var foundNumber = findNextScheduleIndex();
var startNumber = foundNumber - 2;
if (startNumber < 0) { startNumber = 0; }
var endNumber = startNumber + 8 - (foundNumber - startNumber);
if (endNumber > foundSchedule.length-1) { endNumber = foundSchedule.length-1; }
var scheduleHourUpdated;
var scheduleMinuteUpdated;
for(var currentNumber = startNumber; currentNumber<=endNumber; currentNumber++){
scheduleMinuteUpdatedStart = updateMinutesToCurrentTime(foundSchedule[currentNumber].sm);
scheduleHourUpdatedStart = foundSchedule[currentNumber].sh;
scheduleMinuteUpdatedEnd = updateMinutesToCurrentTime(foundSchedule[currentNumber].em);
scheduleHourUpdatedEnd = foundSchedule[currentNumber].eh;
scheduleDecriptionUpdated = foundSchedule[currentNumber].cn.substring(0, 20);
if(foundSchedule[currentNumber].cn.length >= 15){
scheduleDecriptionUpdated = foundSchedule[currentNumber].cn.substring(0, 20)+"...";
}
schduleDay = updateDay(3,foundSchedule[currentNumber].dow);
g.setFont("8x12");
g.drawString(scheduleHourUpdatedStart+":"+scheduleMinuteUpdatedStart+"-"+scheduleHourUpdatedEnd+":"+scheduleMinuteUpdatedEnd+" "+schduleDay+" "+scheduleDecriptionUpdated,13,50+(currentNumber*20));
}
}
function buttonsF(l){
if(currentStage == LIST){
g.drawImage(getDotIcon(),223.5,115);
}else{
g.drawImage(getMenuIcon(),223.5,115);
}
g.drawImage(getUpArrow(),225,30);
g.drawImage(getDownArrow(),225,215);
}
function draw() {
var currentDate = new Date();
var currentDayOfWeek = currentDate.getDay();
var currentHour = currentDate.getHours();
var currentMinute = currentDate.getMinutes();
var currentMinuteUpdated = updateMinutesToCurrentTime(currentMinute);
if (layout) {
if(currentStage == LIST){
layout.time.label = currentHour+":"+currentMinuteUpdated;
layout.time.x = 147;
layout.time.y = 10;
layout.render(layout.table);
layout.render(layout.tableText);
logDebug("Rendered"+currentPositionTable);
}else{
layout.time.label = currentHour+":"+currentMinuteUpdated;
layout.time.x = 147;
layout.time.y = 10;
layout.render(layout.info);
logDebug("Rendered"+currentPositionTable);
}
g.clearRect(150,0,220,35);
layout.render(layout.time);
}
}
function RedRectDown() {
if(currentPositionTable > 0){
currentPositionTable -= 1;
if(currentStage == INFORMATION){
redrawScreen();
}else{
draw();
}
}
}
function RedRectUp() {
if(currentPositionTable < numberOfItemsShown){
currentPositionTable += 1;
if(currentStage == INFORMATION){
redrawScreen();
}else{
draw();
}
}
}
function renderMiniBackground(l){
for(var i = 233;i<=240;i++){
g.drawImage(getBackgroundImage(),i,123,{scale:10,rotate:0});
}
}
function renderLoading(l){
g.setFont("8x12");
g.drawString("Loading...",240/2-20,240/2-20);
}
function renderInformation(l){
var foundNumber = findNextScheduleIndex();
var foundSchedule = getScheduleTable();
var startNumber = foundNumber - 2;
if (startNumber < 0) { startNumber = 0; }
if ((startNumber+currentPositionTable) <= foundSchedule.length-1) {
scheduleMinuteUpdatedStart = updateMinutesToCurrentTime(foundSchedule[foundNumber].sm);
scheduleHourUpdatedStart = foundSchedule[foundNumber].sh;
scheduleMinuteUpdatedEnd = updateMinutesToCurrentTime(foundSchedule[foundNumber].em);
scheduleHourUpdatedEnd = foundSchedule[foundNumber].eh;
scheduleDay = updateDay(1,foundSchedule[(startNumber+currentPositionTable)].dow);
g.setColor(255,255,255);
g.setFont("8x12",2);
var splitClassNames = splitter(foundSchedule[(startNumber+currentPositionTable)].cn, 15);
var currentY = 5;
for (var j=0; j < splitClassNames.length; j++) {
g.drawString(splitClassNames[j],13,currentY+50);
currentY = currentY + 25;
}
g.setFont("8x12");
g.drawString(schduleDay,13,currentY+50);
g.drawString(scheduleHourUpdatedStart+":"+scheduleMinuteUpdatedStart+"-"+scheduleHourUpdatedEnd+":"+scheduleMinuteUpdatedEnd,13,currentY+15+50);
}
}
var Layout = require("Layout");
var layout = new Layout(
{type:"h", c: [
{type:"custom", render:renderTableText, id:"tableText"},
{type:"custom", render:buttonsF, id:"buttons"},
{type:"custom", render:renderBackground, id:"background"},
{type:"custom", render:renderTable, id:"table"},
{type:"custom", render:renderMiniBackground, id:"miniBackground"},
{type:"custom", render:renderLoading, id:"loading"},
{type:"custom", render:renderInformation, id:"info"},
{type:"txt", font:"7x11Numeric7Seg:2", label:"00:00", id:"time"},
]},
{type:"v", c:[
]},
{btns:[
{label:"", cb: RedRectUp()},
{label:"", cb: l=>print("Two")},
{label:"", cb: RedRectDown()}
]});
function getBackgroundImage() {return require("heatshrink").decompress(atob("j0ZyEKIf4A4gIB6gQB6gYB6ggB6goB6gwB6g4B6hAABAYIBHBZIVLAK8IhIBXgAThhQB6hYB6hgB6hoB6hwB6h4B6iAB6iIB6iQBHiAJOB54XSiYB6igB6ioB6iwB6i4B5A="));}
function logDebug(message) {console.log(message);}
function changeScene(){
layout.render(layout.buttons);
if(currentStage == INFORMATION){
currentStage = LIST;
nIntervId = setInterval(redrawScreen, 100000);
}else if(currentStage == LIST){
currentStage = INFORMATION;
clearInterval();
}
layout.render(layout.background);
layout.render(layout.buttons);
draw();
}
// timeout used to update every minute
var drawTimeout;
setInterval(draw, 15000);
setWatch(RedRectUp, BTN3, { repeat:true, edge:'rising', debounce : 50 });
setWatch(RedRectDown, BTN1, { repeat:true, edge:'rising', debounce : 50 });
setWatch(changeScene, BTN2, { repeat:true, edge:'rising', debounce : 50 });
layout.update();
layout.render(layout.loading);
layout.render(layout.background);
layout.render(layout.buttons);
draw();
file.write(JSON.stringify(schedule));
`;
// send finished app (in addition to contents of app.json)
sendCustomizedApp({
storage: [
{ name: "schoolCalendar.app.js", url: "app.js", content: app },
]
});
});
</script>
<div id='calendar'></div>
</body>
</html>

View File

@ -0,0 +1,22 @@
MIT License
Copyright (c) 2021 Adam Shaw
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,8 @@
# FullCalendar Interaction Plugin
Provides functionality for event drag-n-drop, resizing, dateClick, and selectable actions
[View the docs &raquo;](https://fullcalendar.io/docs/editable)
This package was created from the [FullCalendar monorepo &raquo;](https://github.com/fullcalendar/fullcalendar)

View File

@ -0,0 +1,32 @@
{
"name": "@fullcalendar/interaction",
"version": "5.9.0",
"title": "FullCalendar Interaction Plugin",
"description": "Provides functionality for event drag-n-drop, resizing, dateClick, and selectable actions",
"docs": "https://fullcalendar.io/docs/editable",
"dependencies": {
"@fullcalendar/common": "workspace:~5.9.0",
"tslib": "^2.1.0"
},
"main": "main.cjs.js",
"module": "main.js",
"types": "main.d.ts",
"jsdelivr": "main.global.min.js",
"browserGlobal": "FullCalendarInteraction",
"homepage": "https://fullcalendar.io/",
"bugs": "https://fullcalendar.io/reporting-bugs",
"repository": {
"type": "git",
"url": "https://github.com/fullcalendar/fullcalendar.git",
"homepage": "https://github.com/fullcalendar/fullcalendar"
},
"license": "MIT",
"author": {
"name": "Adam Shaw",
"email": "arshaw@arshaw.com",
"url": "http://arshaw.com/"
},
"devDependencies": {
"@fullcalendar/core-preact": "workspace:*"
}
}

Some files were not shown because too many files have changed in this diff Show More