forked from FOSS/BangleApps
commit
4ad848a767
|
@ -1 +1,2 @@
|
||||||
0.01: Initial upload
|
0.01: Initial upload
|
||||||
|
0.2: Added scrollable calendar and swipe gestures
|
||||||
|
|
|
@ -3,10 +3,14 @@
|
||||||
This is my "Hello World". I first made this watchface almost 10 years ago for my original Pebble and Pebble Time and I missed this so much, that I had to write it for the BangleJS2.
|
This is my "Hello World". I first made this watchface almost 10 years ago for my original Pebble and Pebble Time and I missed this so much, that I had to write it for the BangleJS2.
|
||||||
I know that it seems redundant because there already **is** a *time&cal*-app, but it didn't fit my style.
|
I know that it seems redundant because there already **is** a *time&cal*-app, but it didn't fit my style.
|
||||||
|
|
||||||
- locked screen with only one minimal update/minute
|
|Screenshot|description|
|
||||||
- 
|
|:--:|:-|
|
||||||
- unlocked screen (twist?) with seconds
|
||locked: triggers only one minimal update/min|
|
||||||
- 
|
||unlocked: smaller clock, but with seconds|
|
||||||
|
||swipe up for big calendar, (up down to scroll, left/right to exit)|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Configurable Features
|
## Configurable Features
|
||||||
- Number of calendar rows (weeks)
|
- Number of calendar rows (weeks)
|
||||||
|
@ -15,6 +19,14 @@ I know that it seems redundant because there already **is** a *time&cal*-app, bu
|
||||||
- First day of the week
|
- First day of the week
|
||||||
- Red Saturday
|
- Red Saturday
|
||||||
- Red Sunday
|
- Red Sunday
|
||||||
|
- Swipes (to disable all gestures)
|
||||||
|
- Swipes: music (swipe down)
|
||||||
|
- Spipes: messages (swipe right)
|
||||||
|
|
||||||
|
## Auto detects your message/music apps:
|
||||||
|
- swiping down will search your files for an app with the string "music" in its filename and launch it
|
||||||
|
- swiping right will search your files for an app with the string "message" in its filename and launch it.
|
||||||
|
- Configurable apps coming soon.
|
||||||
|
|
||||||
## Feedback
|
## Feedback
|
||||||
The clock works for me in a 24h/MondayFirst/WeekendFree environment but is not well-tested with other settings.
|
The clock works for me in a 24h/MondayFirst/WeekendFree environment but is not well-tested with other settings.
|
||||||
|
|
|
@ -7,15 +7,116 @@ var s = Object.assign({
|
||||||
FIRSTDAYOFFSET: 6, //First day of the week: 0-6: Sun, Sat, Fri, Thu, Wed, Tue, Mon
|
FIRSTDAYOFFSET: 6, //First day of the week: 0-6: Sun, Sat, Fri, Thu, Wed, Tue, Mon
|
||||||
REDSUN: true, // Use red color for sunday?
|
REDSUN: true, // Use red color for sunday?
|
||||||
REDSAT: true, // Use red color for saturday?
|
REDSAT: true, // Use red color for saturday?
|
||||||
|
DRAGENABLED: true,
|
||||||
|
DRAGMUSIC: true,
|
||||||
|
DRAGMESSAGES: true
|
||||||
}, require('Storage').readJSON("clockcal.json", true) || {});
|
}, require('Storage').readJSON("clockcal.json", true) || {});
|
||||||
|
|
||||||
const h = g.getHeight();
|
const h = g.getHeight();
|
||||||
const w = g.getWidth();
|
const w = g.getWidth();
|
||||||
const CELL_W = w / 7;
|
const CELL_W = w / 7;
|
||||||
|
const CELL2_W = w / 8;//full calendar
|
||||||
const CELL_H = 15;
|
const CELL_H = 15;
|
||||||
const CAL_Y = h - s.CAL_ROWS * CELL_H;
|
const CAL_Y = h - s.CAL_ROWS * CELL_H;
|
||||||
const DEBUG = false;
|
const DEBUG = false;
|
||||||
|
var state = "watch";
|
||||||
|
var monthOffset = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calendar features
|
||||||
|
*/
|
||||||
|
function drawFullCalendar(monthOffset) {
|
||||||
|
addMonths = function (_d, _am) {
|
||||||
|
var ay = 0, m = _d.getMonth(), y = _d.getFullYear();
|
||||||
|
while ((m + _am) > 11) { ay++; _am -= 12; }
|
||||||
|
while ((m + _am) < 0) { ay--; _am += 12; }
|
||||||
|
n = new Date(_d.getTime());
|
||||||
|
n.setMonth(m + _am);
|
||||||
|
n.setFullYear(y + ay);
|
||||||
|
return n;
|
||||||
|
};
|
||||||
|
monthOffset = (typeof monthOffset == "undefined") ? 0 : monthOffset;
|
||||||
|
state = "calendar";
|
||||||
|
var start = Date().getTime();
|
||||||
|
const months = ['Jan.', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec.'];
|
||||||
|
const monthclr = ['#0f0', '#f0f', '#00f', '#ff0', '#0ff', '#fff'];
|
||||||
|
if (typeof dayInterval !== "undefined") clearTimeout(dayInterval);
|
||||||
|
if (typeof secondInterval !== "undefined") clearTimeout(secondInterval);
|
||||||
|
if (typeof minuteInterval !== "undefined") clearTimeout(minuteInterval);
|
||||||
|
d = addMonths(Date(), monthOffset);
|
||||||
|
tdy = Date().getDate() + "." + Date().getMonth();
|
||||||
|
newmonth=false;
|
||||||
|
c_y = 0;
|
||||||
|
g.reset();
|
||||||
|
g.setBgColor(0);
|
||||||
|
g.clear();
|
||||||
|
var prevmonth = addMonths(d, -1)
|
||||||
|
const today = prevmonth.getDate();
|
||||||
|
var rD = new Date(prevmonth.getTime());
|
||||||
|
rD.setDate(rD.getDate() - (today - 1));
|
||||||
|
const dow = (s.FIRSTDAYOFFSET + rD.getDay()) % 7;
|
||||||
|
rD.setDate(rD.getDate() - dow);
|
||||||
|
var rDate = rD.getDate();
|
||||||
|
bottomrightY = c_y - 3;
|
||||||
|
clrsun=s.REDSUN?'#f00':'#fff';
|
||||||
|
clrsat=s.REDSUN?'#f00':'#fff';
|
||||||
|
var fg=[clrsun,'#fff','#fff','#fff','#fff','#fff',clrsat];
|
||||||
|
for (var y = 1; y <= 11; y++) {
|
||||||
|
bottomrightY += CELL_H;
|
||||||
|
bottomrightX = -2;
|
||||||
|
for (var x = 1; x <= 7; x++) {
|
||||||
|
bottomrightX += CELL2_W;
|
||||||
|
rMonth = rD.getMonth();
|
||||||
|
rDate = rD.getDate();
|
||||||
|
if (tdy == rDate + "." + rMonth) {
|
||||||
|
caldrawToday(rDate);
|
||||||
|
} else if (rDate == 1) {
|
||||||
|
caldrawFirst(rDate);
|
||||||
|
} else {
|
||||||
|
caldrawNormal(rDate,fg[rD.getDay()]);
|
||||||
|
}
|
||||||
|
if (newmonth && x == 7) {
|
||||||
|
caldrawMonth(rDate,monthclr[rMonth % 6],months[rMonth],rD);
|
||||||
|
}
|
||||||
|
rD.setDate(rDate + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete addMonths;
|
||||||
|
if (DEBUG) console.log("Calendar performance (ms):" + (Date().getTime() - start));
|
||||||
|
}
|
||||||
|
function caldrawMonth(rDate,c,m,rD) {
|
||||||
|
g.setColor(c);
|
||||||
|
g.setFont("Vector", 18);
|
||||||
|
g.setFontAlign(-1, 1, 1);
|
||||||
|
drawyear = ((rMonth % 11) == 0) ? String(rD.getFullYear()).substr(-2) : "";
|
||||||
|
g.drawString(m + drawyear, bottomrightX, bottomrightY - CELL_H, 1);
|
||||||
|
newmonth = false;
|
||||||
|
}
|
||||||
|
function caldrawToday(rDate) {
|
||||||
|
g.setFont("Vector", 16);
|
||||||
|
g.setFontAlign(1, 1);
|
||||||
|
g.setColor('#0f0');
|
||||||
|
g.fillRect(bottomrightX - CELL2_W + 1, bottomrightY - CELL_H - 1, bottomrightX, bottomrightY - 2);
|
||||||
|
g.setColor('#000');
|
||||||
|
g.drawString(rDate, bottomrightX, bottomrightY);
|
||||||
|
}
|
||||||
|
function caldrawFirst(rDate) {
|
||||||
|
g.flip();
|
||||||
|
g.setFont("Vector", 16);
|
||||||
|
g.setFontAlign(1, 1);
|
||||||
|
bottomrightY += 3;
|
||||||
|
newmonth = true;
|
||||||
|
g.setColor('#0ff');
|
||||||
|
g.fillRect(bottomrightX - CELL2_W + 1, bottomrightY - CELL_H - 1, bottomrightX, bottomrightY - 2);
|
||||||
|
g.setColor('#000');
|
||||||
|
g.drawString(rDate, bottomrightX, bottomrightY);
|
||||||
|
}
|
||||||
|
function caldrawNormal(rDate,c) {
|
||||||
|
g.setFont("Vector", 16);
|
||||||
|
g.setFontAlign(1, 1);
|
||||||
|
g.setColor(c);
|
||||||
|
g.drawString(rDate, bottomrightX, bottomrightY);//100
|
||||||
|
}
|
||||||
function drawMinutes() {
|
function drawMinutes() {
|
||||||
if (DEBUG) console.log("|-->minutes");
|
if (DEBUG) console.log("|-->minutes");
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
|
@ -52,8 +153,10 @@ function drawSeconds() {
|
||||||
if (!dimSeconds) secondInterval = setTimeout(drawSeconds, 1000);
|
if (!dimSeconds) secondInterval = setTimeout(drawSeconds, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function drawCalendar() {
|
function drawWatch() {
|
||||||
if (DEBUG) console.log("CALENDAR");
|
if (DEBUG) console.log("CALENDAR");
|
||||||
|
monthOffset = 0;
|
||||||
|
state = "watch";
|
||||||
var d = new Date();
|
var d = new Date();
|
||||||
g.reset();
|
g.reset();
|
||||||
g.setBgColor(0);
|
g.setBgColor(0);
|
||||||
|
@ -91,7 +194,7 @@ function drawCalendar() {
|
||||||
var nextday = (3600 * 24) - (d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds() + 1);
|
var nextday = (3600 * 24) - (d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds() + 1);
|
||||||
if (DEBUG) console.log("Next Day:" + (nextday / 3600));
|
if (DEBUG) console.log("Next Day:" + (nextday / 3600));
|
||||||
if (typeof dayInterval !== "undefined") clearTimeout(dayInterval);
|
if (typeof dayInterval !== "undefined") clearTimeout(dayInterval);
|
||||||
dayInterval = setTimeout(drawCalendar, nextday * 1000);
|
dayInterval = setTimeout(drawWatch, nextday * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
function BTevent() {
|
function BTevent() {
|
||||||
|
@ -103,17 +206,87 @@ function BTevent() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function input(dir) {
|
||||||
|
if (s.DRAGENABLED) {
|
||||||
|
Bangle.buzz(100,1);
|
||||||
|
console.log("swipe:"+dir);
|
||||||
|
switch (dir) {
|
||||||
|
case "r":
|
||||||
|
if (state == "calendar") {
|
||||||
|
drawWatch();
|
||||||
|
} else {
|
||||||
|
if (s.DRAGMUSIC) {
|
||||||
|
l=require("Storage").list(RegExp("music.*app"));
|
||||||
|
if (l.length > 0) {
|
||||||
|
load(l[0]);
|
||||||
|
} else Bangle.buzz(3000,1);//not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "l":
|
||||||
|
if (state == "calendar") {
|
||||||
|
drawWatch();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "d":
|
||||||
|
if (state == "calendar") {
|
||||||
|
monthOffset--;
|
||||||
|
drawFullCalendar(monthOffset);
|
||||||
|
} else {
|
||||||
|
if (s.DRAGMESSAGES) {
|
||||||
|
l=require("Storage").list(RegExp("message.*app"));
|
||||||
|
if (l.length > 0) {
|
||||||
|
load(l[0]);
|
||||||
|
} else Bangle.buzz(3000,1);//not found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "u":
|
||||||
|
if (state == "watch") {
|
||||||
|
state = "calendar";
|
||||||
|
drawFullCalendar(0);
|
||||||
|
} else if (state == "calendar") {
|
||||||
|
monthOffset++;
|
||||||
|
drawFullCalendar(monthOffset);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (state == "calendar") {
|
||||||
|
drawWatch();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let drag;
|
||||||
|
Bangle.on("drag", e => {
|
||||||
|
if (s.DRAGENABLED) {
|
||||||
|
if (!drag) {
|
||||||
|
drag = { x: e.x, y: e.y };
|
||||||
|
} else if (!e.b) {
|
||||||
|
const dx = e.x - drag.x, dy = e.y - drag.y;
|
||||||
|
var dir = "t";
|
||||||
|
if (Math.abs(dx) > Math.abs(dy) + 10) {
|
||||||
|
dir = (dx > 0) ? "r" : "l";
|
||||||
|
} else if (Math.abs(dy) > Math.abs(dx) + 10) {
|
||||||
|
dir = (dy > 0) ? "d" : "u";
|
||||||
|
}
|
||||||
|
drag = null;
|
||||||
|
input(dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
//register events
|
//register events
|
||||||
Bangle.on('lock', locked => {
|
Bangle.on('lock', locked => {
|
||||||
if (typeof secondInterval !== "undefined") clearTimeout(secondInterval);
|
if (typeof secondInterval !== "undefined") clearTimeout(secondInterval);
|
||||||
dimSeconds = locked; //dim seconds if lock=on
|
dimSeconds = locked; //dim seconds if lock=on
|
||||||
drawCalendar();
|
drawWatch();
|
||||||
});
|
});
|
||||||
NRF.on('connect', BTevent);
|
NRF.on('connect', BTevent);
|
||||||
NRF.on('disconnect', BTevent);
|
NRF.on('disconnect', BTevent);
|
||||||
|
|
||||||
|
|
||||||
dimSeconds = Bangle.isLocked();
|
dimSeconds = Bangle.isLocked();
|
||||||
drawCalendar();
|
drawWatch();
|
||||||
|
|
||||||
Bangle.setUI("clock");
|
Bangle.setUI("clock");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "clockcal",
|
"id": "clockcal",
|
||||||
"name": "Clock & Calendar",
|
"name": "Clock & Calendar",
|
||||||
"version": "0.01",
|
"version": "0.2",
|
||||||
"description": "Clock with Calendar",
|
"description": "Clock with Calendar",
|
||||||
"readme":"README.md",
|
"readme":"README.md",
|
||||||
"icon": "app.png",
|
"icon": "app.png",
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 5.7 KiB |
|
@ -8,6 +8,9 @@
|
||||||
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
||||||
REDSUN: true, // Use red color for sunday?
|
REDSUN: true, // Use red color for sunday?
|
||||||
REDSAT: true, // Use red color for saturday?
|
REDSAT: true, // Use red color for saturday?
|
||||||
|
DRAGENABLED: true, //Enable drag gestures (bigger calendar etc)
|
||||||
|
DRAGMUSIC: true, //Enable drag down for music (looks for "music*app")
|
||||||
|
DRAGMESSAGES: true //Enable drag right for messages (looks for "message*app")
|
||||||
}, require('Storage').readJSON(FILE, true) || {});
|
}, require('Storage').readJSON(FILE, true) || {});
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,6 +70,30 @@
|
||||||
writeSettings();
|
writeSettings();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'Swipes (big cal.)?': {
|
||||||
|
value: settings.DRAGENABLED,
|
||||||
|
format: v => v ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
settings.DRAGENABLED = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Swipes (music)?': {
|
||||||
|
value: settings.DRAGMUSIC,
|
||||||
|
format: v => v ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
settings.DRAGMUSIC = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Swipes (messg)?': {
|
||||||
|
value: settings.DRAGMESSAGES,
|
||||||
|
format: v => v ? "On" : "Off",
|
||||||
|
onchange: v => {
|
||||||
|
settings.DRAGMESSAGES = v;
|
||||||
|
writeSettings();
|
||||||
|
}
|
||||||
|
},
|
||||||
'Load deafauls?': {
|
'Load deafauls?': {
|
||||||
value: 0,
|
value: 0,
|
||||||
min: 0, max: 1,
|
min: 0, max: 1,
|
||||||
|
@ -80,13 +107,16 @@
|
||||||
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
FIRSTDAY: 6, //First day of the week: mo, tu, we, th, fr, sa, su
|
||||||
REDSUN: true, // Use red color for sunday?
|
REDSUN: true, // Use red color for sunday?
|
||||||
REDSAT: true, // Use red color for saturday?
|
REDSAT: true, // Use red color for saturday?
|
||||||
|
DRAGENABLED: true,
|
||||||
|
DRAGMUSIC: true,
|
||||||
|
DRAGMESSAGES: true
|
||||||
};
|
};
|
||||||
writeSettings();
|
writeSettings();
|
||||||
load()
|
load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
// Show the menu
|
// Show the menu
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
})
|
});
|
||||||
|
|
Loading…
Reference in New Issue