Merge remote-tracking branch 'upstream/master'

pull/932/head
hughbarney 2021-11-23 13:22:30 +00:00
commit be3345d143
40 changed files with 18591 additions and 209 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

View File

@ -3649,7 +3649,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"}],
@ -4248,11 +4248,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" },
@ -4263,8 +4270,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",
@ -4296,7 +4303,7 @@
"name": "LCARS Clock",
"shortName":"LCARS",
"icon": "lcars.png",
"version":"0.02",
"version":"0.03",
"supports": ["BANGLEJS2"],
"description": "Library Computer Access Retrieval System (LCARS) clock.",
"type": "clock",
@ -4356,5 +4363,24 @@
{"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"}
]
}
]

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();
});

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

@ -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);

View File

@ -1,2 +1,3 @@
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.

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: 4.2 KiB

BIN
apps/lcars/bg_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
apps/lcars/icon_alarm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
apps/lcars/icon_compass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
apps/lcars/icon_gps.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
apps/lcars/icon_hrm.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
apps/lcars/icon_planet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -3,11 +3,42 @@
*/
const locale = require('locale');
var alarm = -1;
var hrmStr = "-"
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("AEcEiFBASFADpETps06YCcEYXnz15ASBBJzVp0wCdEYU8+fPASHAIJCAdQf6DpoUIkGCATCDWIBCDDzANJAGaDC6BB9QYWAQf804CD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/QbhA9Qf6D2oMEiFAQfoyB6ZBKQeYyBzVgQf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qf6Dnz1586D+AGaDNAGaD/Qf6D/Qf6D/Qf6D/Qf6D/Qf6D/Qc8Bg8euPv337ASHwDQNz588+YCC5AlCjR6CARCDN+/fvoCV6AbBj158+eAQV4EwUTPQQCIQZcB859SQdkPQCyDpvaAWQbmYIBUDQC6DQAC8eQC6DQAC8XQf6D/AASAYQdCAYQf6DHAESDeAESD/Qf6D/Qf6DK+2LtmXQfu8FEiDb8BB9QYRA9QYZB+Qf6D/AAccuPHIPwA/AH4A/AH4AHyVJkhB+zVp0yD/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/Qf6DlwCD/02QQf8kyVIkGChACeFAMo0WKAQOIC56/CQYQCi0kAgMv33794CUQYYChQYU9+/fvoCTviD/Qf6D/Qf6D/Qf6DLjSD/94="))
}
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 iconHrm = {
width : 50, height : 50, bpp : 3,
transparent : 1,
buffer : require("heatshrink").decompress(atob("kmSpIC/AX4CT+PHjlxARfBkmGjFhAR2REZwCC7AjPAQIjQ48dw0//4ANsOB49/CJv8JQNjEh32JQN3BY/5AwpKLkhKQ8+eBIhKK/jZBJR/+vPnJR/JkmTJR3xJQN5JRPypMkz5uByfJk5KI/zXCFQMev/nC4JKIkhrBn4pB/+Sp5KJfwnnOIqVHSQS5CFgaVIDQPHj4FBOIJNCSo/9EAI/CFIJNCSo/njiSC/KYDcBH6IgQAFcBHx44RGcBYAHcBIAHJRAAJJRAAJJSrdEARfYsOGjACOngjP48EyQdHx04BAtkyTnCAQYsCDoILGAQ2OnfvCJ2TIgNwCJuSpHj335CJnxNYvBChU48ZKC3378gRJp6SGiQ4JkaSBJQP7EwIOEyA"))
}
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="))
}
Graphics.prototype.setFontAntonioMedium = function(scale) {
@ -38,14 +69,32 @@ 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
for(var x=0; x<6; x++){
g.drawLine(115+x*10, 100, 115+x*10, 160);
}
for(var y=0; y<6; y++){
g.drawLine(110, 105+y*10, 170, 105+y*10);
}
// Draw symbol
var iconImg =
alarm >= 0 ? iconAlarm :
Bangle.isGPSOn() ? iconGps :
Bangle.isHRMOn() ? iconHrm :
Bangle.isCompassOn() ? iconCompass :
iconPlanet;
g.drawImage(iconImg, 115, 105);
// 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, 57, 57);
// Write date
g.setFontAlign(1,-1, 0);
@ -53,41 +102,32 @@ function draw(queue){
var dayName = locale.dow(currentDate, true).toUpperCase();
var day = currentDate.getDate();
g.drawString(day, 170, 30);
g.drawString(dayName, 170, 50);
g.drawString(day, 133, 37);
g.drawString(dayName, 133, 57);
// Alarm
// Alarm within symbol
if(alarm > 0){
g.setFontAlign(0,0,0);
g.drawString(alarm, 115+25, 105+25);
g.setFontAlign(-1,-1,0);
}
// HRM
g.setFontAlign(-1,-1,0);
g.drawString("TMR:", 30, 107);
var alrmText = alarm >= 0 ? "T-"+alarm : "OFF";
g.drawString(alrmText, 65, 107);
g.drawString("HRM:", 20, 104);
g.drawString(hrmStr, 60, 104);
// Draw steps
var steps = getSteps();
g.drawString("STEP:", 20, 124);
g.drawString(steps, 60, 124);
// Draw battery
var bat = E.getBattery();
var charging = Bangle.isCharging() ? "*" : "";
g.drawString("BAT:", 30, 127);
g.drawString(charging + bat+ "%", 65, 127);
g.drawString("BAT:", 20, 144);
g.drawString(charging + bat+ "%", 60, 144);
// Draw steps
var steps = getSteps();
g.drawString("STEP:", 30, 147);
g.drawString(steps, 65, 147);
// 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);
// Queue draw in one minute
if(queue){
@ -174,6 +214,14 @@ Bangle.on('swipe',function(dir) {
});
/*
* Measure heart rate
*/
Bangle.on('HRM', function(hrm) {
hrmStr = hrm.bpm;
});
/*
* Stop updates when LCD is off, restart when on
*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 24 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.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,6 @@
// check for alarms
(function() {
var alarms = require('Storage').readJSON('schoolCalendarAlarms.json',1)||[];
var time = new Date();
E.showPrompt("School Calendar Alarm Test");
})();

View File

@ -0,0 +1,420 @@
<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 = [//Monday:
{cn: "Biblical Theology", dow:1, sh: 8, sm: 10, eh:9, em: 5, r:"207", t:"Mr. Besaw"},
{cn: "English", dow:1, sh: 9, sm: 5, eh:10, em: 0, t:"Dr. Wong"},
{cn: "Break", dow:1, sh: 10, sm: 0, eh:10, em: 10, t:""},
{cn: "MS Robotics", dow:1, sh: 10, sm: 10, eh:11, em: 0, r:"211", t:"Mr. Broyles"}];//${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:*"
}
}

View File

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.base",
"compilerOptions": {
"rootDir": "src",
"outDir": "tsc"
},
"include": [
"src/**/*"
],
"references": [
{ "path": "../common" }
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -64,7 +64,9 @@
.icon.icon-favourite-active::before {
content: "\02665"; /* 0x2665 = solid heart; 0x2605 = solid star */
}
.icon.icon-interface {text-indent: 0px;font-size: 130%;vertical-align: -30%;} /*override spectre*/
.icon.icon-interface {text-indent: 0px;} /*override spectre*/
.icon.icon-interface::before {
content: "\01F5AB";
position: absolute; left: 50%; top: 70%;
transform: translate(-50%,-50%);
content: url("data:image/svg+xml,%3C%3Fxml version='1.0'%3F%3E%3Csvg fill='rgb(87, 85, 217)' xmlns='http://www.w3.org/2000/svg' viewBox='2 2 28 28' width='1.5em' height='1.5em'%3E%3Cpath d='M 6 4 C 4.895 4 4 4.895 4 6 L 4 24 C 4 25.105 4.895 26 6 26 L 24 26 C 25.105 26 26 25.105 26 24 L 26 8 L 22 4 L 20 4 L 20 10 C 20 10.552 19.552 11 19 11 L 10 11 C 9.448 11 9 10.552 9 10 L 9 4 L 6 4 z M 16 4 L 16 9 L 18 9 L 18 4 L 16 4 z M 10 16 L 20 16 C 21.105 16 22 16.895 22 18 L 22 24 L 8 24 L 8 18 C 8 16.895 8.895 16 10 16 z'/%3E%3C/svg%3E");
}