Merge pull request #2950 from nxdefiant/master

Calendar: Edit holidays on device in settings
pull/2954/head
Gordon Williams 2023-08-07 10:24:04 +01:00 committed by GitHub
commit 34cb33f75f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 168 additions and 35 deletions

View File

@ -14,3 +14,4 @@
0.13: Switch to swipe left/right for month and up/down for year selection
Display events for current month on touch
0.14: Add support for holidays
0.15: Edit holidays on device in settings

View File

@ -75,11 +75,32 @@ function getDowLbls(locale) {
}
function sameDay(d1, d2) {
"jit";
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
}
function drawEvent(ev, curDay, x1, y1, x2, y2) {
"ram";
switch(ev.type) {
case "e": // alarm/event
const hour = 0|ev.date.getHours() + 0|ev.date.getMinutes()/60.0;
const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
const height = (y2-2) - (y1+2); // height of a cell
const sliceHeight = height/eventsPerDay;
const ystart = (y1+2) + slice*sliceHeight;
g.setColor(bgEvent).fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
break;
case "h": // holiday
g.setColor(bgColorWeekend).fillRect(x1+1, y1+1, x2-1, y2-1);
break;
case "o": // other
g.setColor(bgOtherEvent).fillRect(x1+1, y1+1, x2-1, y2-1);
break;
}
}
function drawCalendar(date) {
g.setBgColor(bgColor);
g.clearRect(0, 0, maxX, maxY);
@ -118,7 +139,6 @@ function drawCalendar(date) {
true
);
g.setFont("6x8", fontSize);
let dowLbls = getDowLbls(require('locale').name);
dowLbls.forEach((lbl, i) => {
g.drawString(lbl, i * colW + colW / 2, headerH + rowH / 2);
@ -172,6 +192,7 @@ function drawCalendar(date) {
const eventsThisMonth = events.filter(ev => ev.date > weekBeforeMonth && ev.date < week2AfterMonth);
eventsThisMonth.sort((a,b) => a.date - b.date);
let i = 0;
g.setFont("8x12", fontSize);
for (y = 0; y < rowN - 1; y++) {
for (x = 0; x < colN; x++) {
i++;
@ -188,22 +209,7 @@ function drawCalendar(date) {
// Display events for this day
eventsThisMonth.forEach((ev, idx) => {
if (sameDay(ev.date, curDay)) {
switch(ev.type) {
case "e": // alarm/event
const hour = ev.date.getHours() + ev.date.getMinutes()/60.0;
const slice = hour/24*(eventsPerDay-1); // slice 0 for 0:00 up to eventsPerDay for 23:59
const height = (y2-2) - (y1+2); // height of a cell
const sliceHeight = height/eventsPerDay;
const ystart = (y1+2) + slice*sliceHeight;
g.setColor(bgEvent).fillRect(x1+1, ystart, x2-2, ystart+sliceHeight);
break;
case "h": // holiday
g.setColor(bgColorWeekend).fillRect(x1+1, y1+1, x2-1, y2-1);
break;
case "o": // other
g.setColor(bgOtherEvent).fillRect(x1+1, y1+1, x2-1, y2-1);
break;
}
drawEvent(ev, curDay, x1, y1, x2, y2);
eventsThisMonth.splice(idx, 1); // this event is no longer needed
}
@ -221,17 +227,15 @@ function drawCalendar(date) {
);
}
require("Font8x12").add(Graphics);
g.setFont("8x12", fontSize);
g.setColor(day < 50 ? fgOtherMonth : fgSameMonth);
g.drawString(
(day > 50 ? day - 50 : day).toString(),
x * colW + colW / 2,
headerH + rowH + y * rowH + rowH / 2
);
}
}
}
} // end for (x = 0; x < colN; x++)
} // end for (y = 0; y < rowN - 1; y++)
} // end function drawCalendar
function setUI() {
Bangle.setUI({
@ -279,6 +283,7 @@ function setUI() {
});
}
require("Font8x12").add(Graphics);
drawCalendar(date);
setUI();
// No space for widgets!

View File

@ -1,7 +1,7 @@
{
"id": "calendar",
"name": "Calendar",
"version": "0.14",
"version": "0.15",
"description": "Simple calendar",
"icon": "calendar.png",
"screenshots": [{"url":"screenshot_calendar.png"}],

View File

@ -1,5 +1,6 @@
(function (back) {
var FILE = "calendar.json";
const HOLIDAY_FILE = "calendar.days.json";
var settings = require('Storage').readJSON(FILE, true) || {};
if (settings.ndColors === undefined)
if (process.env.HWVERSION == 2) {
@ -7,21 +8,147 @@
} 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() {
require('Storage').writeJSON(FILE, settings);
}
E.showMenu({
"": { "title": "Calendar" },
"< Back": () => back(),
'B2 Colors': {
value: settings.ndColors,
onchange: v => {
settings.ndColors = v;
writeSettings();
}
},
});
})
function writeHolidays() {
holidays.sort((a,b) => new Date(a.date) - new Date(b.date));
require('Storage').writeJSON(HOLIDAY_FILE, holidays);
}
function formatDate(d) {
return d.getFullYear() + "-" + (d.getMonth() + 1).toString().padStart(2, '0') + "-" + d.getDate().toString().padStart(2, '0');
}
const editdate = (i) => {
const holiday = holidays[i];
const date = new Date(holiday.date);
const dateStr = require("locale").date(date, 1);
const menu = {
"": { "title" : holiday.name},
"< Back": () => {
writeHolidays();
editdates();
},
/*LANG*/"Day": {
value: date ? date.getDate() : null,
min: 1,
max: 31,
wrap: true,
onchange: v => {
date.setDate(v);
holiday.date = formatDate(date);
}
},
/*LANG*/"Month": {
value: date ? date.getMonth() + 1 : null,
format: v => require("date_utils").month(v),
onchange: v => {
date.setMonth((v+11)%12);
holiday.date = formatDate(date);
}
},
/*LANG*/"Year": {
value: date ? date.getFullYear() : null,
min: 1900,
max: 2100,
onchange: v => {
date.setFullYear(v);
holiday.date = formatDate(date);
}
},
/*LANG*/"Name": () => {
require("textinput").input({text:holiday.name}).then(result => {
holiday.name = result;
editdate(i);
});
},
/*LANG*/"Type": {
value: function() {
switch(holiday.type) {
case 'h': return 0;
case 'o': return 1;
}
return 0;
}(),
min: 0, max: 1,
format: v => [/*LANG*/"Holiday", /*LANG*/"Other"][v],
onchange: v => {
holiday.type = function() {
switch(v) {
case 0: return 'h';
case 1: return 'o';
}
}();
}
},
/*LANG*/"Repeat": {
value: !!holiday.repeat,
format: v => v ? /*LANG*/"Yearly" : /*LANG*/"Never",
onchange: v => {
holiday.repeat = v ? 'y' : undefined;
}
},
/*LANG*/"Delete": () => E.showPrompt(/*LANG*/"Delete" + " " + menu[""].title + "?").then(function(v) {
if (v) {
holidays.splice(i, 1);
writeHolidays();
editdates();
} else {
editday(i);
}
}
),
};
try {
require("textinput");
} catch(e) {
// textinput not installed
delete menu[/*LANG*/"Name"];
}
E.showMenu(menu);
};
const editdates = () => {
const menu = holidays.map((holiday,i) => {
const date = new Date(holiday.date);
const dateStr = require("locale").date(date, 1);
return {
title: dateStr + ' ' + holiday.name,
onchange: v => setTimeout(() => editdate(i), 10),
};
});
menu[''] = { 'title': 'Holidays' };
menu['< Back'] = ()=>settingsmenu();
E.showMenu(menu);
};
const settingsmenu = () => {
E.showMenu({
"": { "title": "Calendar" },
"< Back": () => back(),
'B2 Colors': {
value: settings.ndColors,
onchange: v => {
settings.ndColors = v;
writeSettings();
}
},
/*LANG*/"Edit Holidays": () => editdates(),
/*LANG*/"Add Holiday": () => {
holidays.push({
"date":formatDate(new Date()),
"name":/*LANG*/"New",
"type":'h',
});
editdate(holidays.length-1);
},
});
};
settingsmenu();
})