Merge pull request #3051 from nxdefiant/calendar

Calendar: Add menu to jump to settings
master
Gordon Williams 2023-10-20 09:03:13 +01:00 committed by GitHub
commit 6b3cc136e3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 166 additions and 89 deletions

View File

@ -15,3 +15,5 @@
Display events for current month on touch
0.14: Add support for holidays
0.15: Edit holidays on device in settings
0.16: Add menu to fast open settings to edit holidays
Display Widgets in menus

View File

@ -1,6 +1,6 @@
# Calendar
Basic calendar
Monthly calendar, displays holidays uploaded from the web interface and scheduled events.
## Usage
@ -14,4 +14,4 @@ Basic calendar
## Settings
- B2 Colors: use non-dithering colors (default, recommended for Bangle 2) or the original color scheme.
B2 Colors: use non-dithering colors (default, recommended for Bangle 2) or the original color scheme.

View File

@ -1,3 +1,4 @@
{
const maxX = g.getWidth();
const maxY = g.getHeight();
const fontSize = g.getWidth() > 200 ? 2 : 1;
@ -17,71 +18,85 @@ const red = "#d41706";
const blue = "#0000ff";
const yellow = "#ffff00";
const cyan = "#00ffff";
let bgColor = color4;
let bgColorMonth = color1;
let bgColorDow = color2;
let bgColorWeekend = color3;
let fgOtherMonth = gray1;
let fgSameMonth = white;
let bgEvent = blue;
let bgOtherEvent = "#ff8800";
let bgColor;
let bgColorMonth;
let bgColorDow;
let bgColorWeekend;
let fgOtherMonth;
let fgSameMonth;
let bgEvent;
let bgOtherEvent;
const eventsPerDay=6; // how much different events per day we can display
const date = new Date();
const timeutils = require("time_utils");
let settings = require('Storage').readJSON("calendar.json", true) || {};
let startOnSun = ((require("Storage").readJSON("setting.json", true) || {}).firstDayOfWeek || 0) === 0;
// all alarms that run on a specific date
const events = (require("Storage").readJSON("sched.json",1) || []).filter(a => a.on && a.date).map(a => {
const date = new Date(a.date);
const time = timeutils.decodeTime(a.t);
date.setHours(time.h);
date.setMinutes(time.m);
date.setSeconds(time.s);
return {date: date, msg: a.msg, type: "e"};
});
// add holidays & other events
(require("Storage").readJSON("calendar.days.json",1) || []).forEach(d => {
const date = new Date(d.date);
const o = {date: date, msg: d.name, type: d.type};
if (d.repeat) {
o.repeat = d.repeat;
}
events.push(o);
});
if (settings.ndColors === undefined) {
settings.ndColors = !g.theme.dark;
}
if (settings.ndColors === true) {
bgColor = white;
bgColorMonth = blue;
bgColorDow = black;
bgColorWeekend = yellow;
fgOtherMonth = blue;
fgSameMonth = black;
bgEvent = color2;
bgOtherEvent = cyan;
}
function getDowLbls(locale) {
let days = startOnSun ? [0, 1, 2, 3, 4, 5, 6] : [1, 2, 3, 4, 5, 6, 0];
let events;
const dowLbls = function() {
const locale = require('locale').name;
const days = startOnSun ? [0, 1, 2, 3, 4, 5, 6] : [1, 2, 3, 4, 5, 6, 0];
const d = new Date();
return days.map(i => {
d.setDate(d.getDate() + (i + 7 - d.getDay()) % 7);
return require("locale").dow(d, 1);
});
}
}();
function sameDay(d1, d2) {
const loadEvents = () => {
// all alarms that run on a specific date
events = (require("Storage").readJSON("sched.json",1) || []).filter(a => a.on && a.date).map(a => {
const date = new Date(a.date);
const time = timeutils.decodeTime(a.t);
date.setHours(time.h);
date.setMinutes(time.m);
date.setSeconds(time.s);
return {date: date, msg: a.msg, type: "e"};
});
// add holidays & other events
(require("Storage").readJSON("calendar.days.json",1) || []).forEach(d => {
const date = new Date(d.date);
const o = {date: date, msg: d.name, type: d.type};
if (d.repeat) {
o.repeat = d.repeat;
}
events.push(o);
});
};
const loadSettings = () => {
let settings = require('Storage').readJSON("calendar.json", true) || {};
if (settings.ndColors === undefined) {
settings.ndColors = !g.theme.dark;
}
if (settings.ndColors === true) {
bgColor = white;
bgColorMonth = blue;
bgColorDow = black;
bgColorWeekend = yellow;
fgOtherMonth = blue;
fgSameMonth = black;
bgEvent = color2;
bgOtherEvent = cyan;
} else {
bgColor = color4;
bgColorMonth = color1;
bgColorDow = color2;
bgColorWeekend = color3;
fgOtherMonth = gray1;
fgSameMonth = white;
bgEvent = blue;
bgOtherEvent = "#ff8800";
}
};
const sameDay = function(d1, d2) {
"jit";
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}
};
function drawEvent(ev, curDay, x1, y1, x2, y2) {
const drawEvent = function(ev, curDay, x1, y1, x2, y2) {
"ram";
switch(ev.type) {
case "e": // alarm/event
@ -99,9 +114,33 @@ function drawEvent(ev, curDay, x1, y1, x2, y2) {
g.setColor(bgOtherEvent).fillRect(x1+1, y1+1, x2-1, y2-1);
break;
}
}
};
function drawCalendar(date) {
const calcDays = (month, monthMaxDayMap, dowNorm) => {
"jit";
const maxDay = colN * (rowN - 1) + 1;
const days = [];
let nextMonthDay = 1;
let thisMonthDay = 51;
const month2 = month;
let prevMonthDay = monthMaxDayMap[month > 0 ? month - 1 : 11] - dowNorm + 1;
for (let i = 0; i < maxDay; i++) {
if (i < dowNorm) {
days.push(prevMonthDay);
prevMonthDay++;
} else if (thisMonthDay <= monthMaxDayMap[month] + 50) {
days.push(thisMonthDay);
thisMonthDay++;
} else {
days.push(nextMonthDay);
nextMonthDay++;
}
}
return days;
};
const drawCalendar = function(date) {
g.setBgColor(bgColor);
g.clearRect(0, 0, maxX, maxY);
g.setBgColor(bgColorMonth);
@ -139,7 +178,6 @@ function drawCalendar(date) {
true
);
let dowLbls = getDowLbls(require('locale').name);
dowLbls.forEach((lbl, i) => {
g.drawString(lbl, i * colW + colW / 2, headerH + rowH / 2);
});
@ -163,23 +201,7 @@ function drawCalendar(date) {
11: 31
};
let days = [];
let nextMonthDay = 1;
let thisMonthDay = 51;
let prevMonthDay = monthMaxDayMap[month > 0 ? month - 1 : 11] - dowNorm + 1;
for (let i = 0; i < colN * (rowN - 1) + 1; i++) {
if (i < dowNorm) {
days.push(prevMonthDay);
prevMonthDay++;
} else if (thisMonthDay <= monthMaxDayMap[month] + 50) {
days.push(thisMonthDay);
thisMonthDay++;
} else {
days.push(nextMonthDay);
nextMonthDay++;
}
}
const days = calcDays(month, monthMaxDayMap, dowNorm);
const weekBeforeMonth = new Date(date.getTime());
weekBeforeMonth.setDate(weekBeforeMonth.getDate() - 7);
const week2AfterMonth = new Date(date.getFullYear(), date.getMonth()+1, 0);
@ -189,8 +211,15 @@ function drawCalendar(date) {
ev.date.setFullYear(ev.date.getMonth() < 6 ? week2AfterMonth.getFullYear() : weekBeforeMonth.getFullYear());
}
});
const eventsThisMonth = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth);
eventsThisMonth.sort((a,b) => a.date - b.date);
const eventsThisMonthPerDay = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth).reduce((acc, ev) => {
const day = ev.date.getDate();
if (!acc[day]) {
acc[day] = [];
}
acc[day].push(ev);
return acc;
}, []);
let i = 0;
g.setFont("8x12", fontSize);
for (y = 0; y < rowN - 1; y++) {
@ -205,13 +234,13 @@ function drawCalendar(date) {
const x2 = x * colW + colW;
const y2 = y * rowH + headerH + rowH + rowH;
if (eventsThisMonth.length > 0) {
const eventsThisDay = eventsThisMonthPerDay[curDay.getDate()];
if (eventsThisDay && eventsThisDay.length > 0) {
// Display events for this day
eventsThisMonth.forEach((ev, idx) => {
eventsThisDay.forEach((ev, idx) => {
if (sameDay(ev.date, curDay)) {
drawEvent(ev, curDay, x1, y1, x2, y2);
eventsThisMonth.splice(idx, 1); // this event is no longer needed
eventsThisDay.splice(idx, 1); // this event is no longer needed
}
});
}
@ -235,9 +264,44 @@ function drawCalendar(date) {
);
} // end for (x = 0; x < colN; x++)
} // end for (y = 0; y < rowN - 1; y++)
} // end function drawCalendar
}; // end function drawCalendar
const showMenu = function() {
const menu = {
"" : {
title : "Calendar",
remove: () => {
require("widget_utils").show();
}
},
"< Back": () => {
require("widget_utils").hide();
E.showMenu();
setUI();
},
/*LANG*/"Exit": () => load(),
/*LANG*/"Settings": () => {
const appSettings = eval(require('Storage').read('calendar.settings.js'));
appSettings(() => {
loadSettings();
loadEvents();
showMenu();
});
},
};
if (require("Storage").read("alarm.app.js")) {
menu[/*LANG*/"Launch Alarms"] = () => {
load("alarm.app.js");
};
}
require("widget_utils").show();
E.showMenu(menu);
};
const setUI = function() {
require("widget_utils").hide(); // No space for widgets!
drawCalendar(date);
function setUI() {
Bangle.setUI({
mode : "custom",
swipe: (dirLR, dirUD) => {
@ -261,7 +325,14 @@ function setUI() {
drawCalendar(date);
}
},
btn: (n) => n === (process.env.HWVERSION === 2 ? 1 : 3) && load(),
btn: (n) => {
if (process.env.HWVERSION === 2 || n === 2) {
showMenu();
} else if (n === 3) {
// directly exit only on Bangle.js 1
load();
}
},
touch: (n,e) => {
events.sort((a,b) => a.date - b.date);
const menu = events.filter(ev => ev.date.getFullYear() === date.getFullYear() && ev.date.getMonth() === date.getMonth()).map(e => {
@ -274,16 +345,19 @@ function setUI() {
}
menu[""] = { title: require("locale").month(date) + " " + date.getFullYear() };
menu["< Back"] = () => {
require("widget_utils").hide();
E.showMenu();
drawCalendar(date);
setUI();
};
require("widget_utils").show();
E.showMenu(menu);
}
});
}
};
loadSettings();
loadEvents();
Bangle.loadWidgets();
require("Font8x12").add(Graphics);
drawCalendar(date);
setUI();
// No space for widgets!
}

View File

@ -1,8 +1,8 @@
{
"id": "calendar",
"name": "Calendar",
"version": "0.15",
"description": "Simple calendar",
"version": "0.16",
"description": "Monthly calendar, displays holidays uploaded from the web interface and scheduled events.",
"icon": "calendar.png",
"screenshots": [{"url":"screenshot_calendar.png"}],
"tags": "calendar,tool",

View File

@ -1,13 +1,14 @@
(function (back) {
var FILE = "calendar.json";
const FILE = "calendar.json";
const HOLIDAY_FILE = "calendar.days.json";
var settings = require('Storage').readJSON(FILE, 1) || {};
if (settings.ndColors === undefined)
const settings = require('Storage').readJSON(FILE, true) || {};
if (settings.ndColors === undefined) {
if (process.env.HWVERSION == 2) {
settings.ndColors = true;
} else {
settings.ndColors = false;
}
}
const holidays = (require("Storage").readJSON(HOLIDAY_FILE,1)||[]).sort((a,b) => new Date(a.date) - new Date(b.date)) || [];
function writeSettings() {