2020-02-12 10:48:14 +00:00
|
|
|
Bangle.loadWidgets();
|
|
|
|
Bangle.drawWidgets();
|
|
|
|
|
2023-09-18 21:38:17 +00:00
|
|
|
const settings = Object.assign({
|
|
|
|
showConfirm : true,
|
|
|
|
showAutoSnooze : true,
|
|
|
|
showHidden : true
|
|
|
|
}, require('Storage').readJSON('alarm.json',1)||{});
|
2022-05-12 20:59:03 +00:00
|
|
|
// 0 = Sunday (default), 1 = Monday
|
|
|
|
const firstDayOfWeek = (require("Storage").readJSON("setting.json", true) || {}).firstDayOfWeek || 0;
|
2023-03-16 17:39:46 +00:00
|
|
|
const WORKDAYS = 62;
|
2022-05-12 20:59:03 +00:00
|
|
|
const WEEKEND = firstDayOfWeek ? 192 : 65;
|
|
|
|
const EVERY_DAY = firstDayOfWeek ? 254 : 127;
|
2023-01-09 04:04:13 +00:00
|
|
|
const INTERVALS = ["day", "week", "month", "year"];
|
|
|
|
const INTERVAL_LABELS = [/*LANG*/"Day", /*LANG*/"Week", /*LANG*/"Month", /*LANG*/"Year"];
|
2022-05-12 20:59:03 +00:00
|
|
|
|
|
|
|
const iconAlarmOn = "\0" + atob("GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAP/wAf/4A/n8A/n8B/n+B/n+B/n+B/n+B/h+B/4+A/+8A//8Af/4AP/wAH/gAB+AAAAAAAAAA==");
|
|
|
|
const iconAlarmOff = "\0" + (g.theme.dark
|
|
|
|
? atob("GBjBAP////8AAAAAAAAGAGAOAHAcfjg5/5wD/8AH/+AP5/AP5/Af5/gf5/gf5wAf5gAf4Hgf+f4P+bYP8wMH84cD84cB8wMAebYAAf4AAHg=")
|
|
|
|
: atob("GBjBAP//AAAAAAAAAAAGAGAOAHAcfjg5/5wD/8AH/+AP5/AP5/Af5/gf5/gf5wAf5gAf4Hgf+f4P+bYP8wMH84cD84cB8wMAebYAAf4AAHg="));
|
|
|
|
|
|
|
|
const iconTimerOn = "\0" + (g.theme.dark
|
|
|
|
? atob("GBjBAP////8AAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5wAAwwABgYABgYABgYAH/+AH/+AAAAAAAAAAAAA=")
|
|
|
|
: atob("GBjBAP//AAAAAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5wAAwwABgYABgYABgYAH/+AH/+AAAAAAAAAAAAA="));
|
|
|
|
const iconTimerOff = "\0" + (g.theme.dark
|
|
|
|
? atob("GBjBAP////8AAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5HgAwf4BgbYBgwMBg4cH84cH8wMAAbYAAf4AAHg=")
|
|
|
|
: atob("GBjBAP//AAAAAAAAAAAAAAAH/+AH/+ABgYABgYABgYAA/wAA/wAAfgAAPAAAPAAAfgAA5HgAwf4BgbYBgwMBg4cH84cH8wMAAbYAAf4AAHg="));
|
|
|
|
|
2022-04-04 15:58:17 +00:00
|
|
|
// An array of alarm objects (see sched/README.md)
|
2022-05-03 19:34:03 +00:00
|
|
|
var alarms = require("sched").getAlarms();
|
2024-03-22 19:35:06 +00:00
|
|
|
// Fix possible wrap around in existing alarms #3281, broken alarms still needs to be saved to get fixed
|
|
|
|
alarms.forEach(e => e.t %= 86400000); // This can probably be removed in the future when we are sure there are no more broken alarms
|
2022-05-03 19:34:03 +00:00
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
function handleFirstDayOfWeek(dow) {
|
|
|
|
if (firstDayOfWeek == 1) {
|
|
|
|
if ((dow & 1) == 1) {
|
|
|
|
// In the scheduler API Sunday is 1.
|
|
|
|
// Here the week starts on Monday and Sunday is ON so
|
|
|
|
// when I read the dow I need to move Sunday to 128...
|
|
|
|
dow += 127;
|
|
|
|
} else if ((dow & 128) == 128) {
|
|
|
|
// ... and then when I write the dow I need to move Sunday back to 1.
|
|
|
|
dow -= 127;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return dow;
|
2022-03-31 12:48:45 +00:00
|
|
|
}
|
|
|
|
|
2022-05-25 21:13:37 +00:00
|
|
|
// Check the first day of week and update the dow field accordingly (alarms only!)
|
|
|
|
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
2020-02-12 10:48:14 +00:00
|
|
|
|
2023-01-31 18:04:06 +00:00
|
|
|
function getLabel(e) {
|
2024-04-29 02:59:53 +00:00
|
|
|
const dateStr = getDateText(e.date);
|
2023-01-31 18:04:06 +00:00
|
|
|
return (e.timer
|
|
|
|
? require("time_utils").formatDuration(e.timer)
|
2023-03-07 11:37:35 +00:00
|
|
|
: (dateStr ? `${dateStr}${e.rp?"*":""} ${require("time_utils").formatTime(e.t)}` : require("time_utils").formatTime(e.t) + (e.rp ? ` ${decodeRepeat(e)}` : ""))
|
2023-03-07 11:23:13 +00:00
|
|
|
) + (e.msg ? ` ${e.msg}` : "");
|
2023-01-31 18:04:06 +00:00
|
|
|
}
|
|
|
|
|
2024-04-29 02:59:53 +00:00
|
|
|
function getDateText(d) {
|
|
|
|
return d && (settings.menuDateFormat === "mmdd" ? d.substring(d.startsWith(new Date().getFullYear()) ? 5 : 0) : require("locale").date(new Date(d), 1));
|
|
|
|
}
|
|
|
|
|
2023-03-16 17:39:46 +00:00
|
|
|
function trimLabel(label, maxLength) {
|
2023-06-08 03:13:06 +00:00
|
|
|
if(settings.showOverflow) return label;
|
2023-03-16 17:39:46 +00:00
|
|
|
return (label.length > maxLength
|
|
|
|
? label.substring(0,maxLength-3) + "..."
|
|
|
|
: label.substring(0,maxLength));
|
|
|
|
}
|
|
|
|
|
2023-06-08 03:13:06 +00:00
|
|
|
function formatAlarmProperty(msg) {
|
|
|
|
if(settings.showOverflow) return msg;
|
2023-03-18 03:46:23 +00:00
|
|
|
if (msg == null) {
|
|
|
|
return msg;
|
|
|
|
} else if (msg.length > 7) {
|
|
|
|
return msg.substring(0,6)+"...";
|
|
|
|
} else {
|
|
|
|
return msg.substring(0,7);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-29 02:59:53 +00:00
|
|
|
function showMainMenu(scroll, group, scrollback) {
|
2020-02-12 10:48:14 +00:00
|
|
|
const menu = {
|
2023-11-24 19:54:45 +00:00
|
|
|
"": { "title": group || /*LANG*/"Alarms & Timers", scroll: scroll },
|
2024-04-29 02:59:53 +00:00
|
|
|
"< Back": () => group ? showMainMenu(scrollback) : load(),
|
2023-11-15 02:28:59 +00:00
|
|
|
/*LANG*/"New...": () => showNewMenu(group)
|
2020-02-12 10:48:14 +00:00
|
|
|
};
|
2023-11-15 02:28:59 +00:00
|
|
|
const getGroups = settings.showGroup && !group;
|
|
|
|
const groups = getGroups ? {} : undefined;
|
|
|
|
var showAlarm;
|
2024-10-06 23:38:45 +00:00
|
|
|
const getIcon = (e)=>{return e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff);};
|
2022-05-12 20:59:03 +00:00
|
|
|
|
|
|
|
alarms.forEach((e, index) => {
|
2023-11-28 03:27:13 +00:00
|
|
|
showAlarm = !settings.showGroup || (group ? e.group === group : !e.group);
|
2023-11-15 02:28:59 +00:00
|
|
|
if(showAlarm) {
|
2024-10-06 23:38:45 +00:00
|
|
|
const label = trimLabel(getLabel(e),40);
|
|
|
|
menu[label] = {
|
|
|
|
value: e.on,
|
|
|
|
onchange: (v, touch) => {
|
|
|
|
if (touch && (2==touch.type || 145<touch.x)) { // Long touch or touched icon.
|
|
|
|
e.on = v;
|
|
|
|
saveAndReload();
|
|
|
|
} else {
|
|
|
|
setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index, undefined, scroller?scroller.scroll:undefined, group);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
format: v=>getIcon(e)
|
2023-11-15 02:28:59 +00:00
|
|
|
};
|
|
|
|
} else if (getGroups) {
|
|
|
|
groups[e.group] = undefined;
|
|
|
|
}
|
2020-02-12 10:48:14 +00:00
|
|
|
});
|
2022-04-25 13:23:18 +00:00
|
|
|
|
2023-11-15 02:28:59 +00:00
|
|
|
if (!group) {
|
2024-10-07 18:43:04 +00:00
|
|
|
Object.keys(groups).sort().forEach(g => menu[g] = () => showMainMenu(null, g, scroller?scroller.scroll:undefined));
|
2023-11-15 02:28:59 +00:00
|
|
|
menu[/*LANG*/"Advanced"] = () => showAdvancedMenu();
|
|
|
|
}
|
2022-04-25 13:23:18 +00:00
|
|
|
|
2023-11-15 03:04:47 +00:00
|
|
|
var scroller = E.showMenu(menu).scroller;
|
2020-02-12 10:48:14 +00:00
|
|
|
}
|
|
|
|
|
2023-11-15 02:28:59 +00:00
|
|
|
function showNewMenu(group) {
|
|
|
|
const newMenu = {
|
2022-05-12 20:59:03 +00:00
|
|
|
"": { "title": /*LANG*/"New..." },
|
2023-11-15 02:28:59 +00:00
|
|
|
"< Back": () => showMainMenu(group),
|
|
|
|
/*LANG*/"Alarm": () => showEditAlarmMenu(undefined, undefined, false, null, group),
|
2022-12-20 00:18:08 +00:00
|
|
|
/*LANG*/"Timer": () => showEditTimerMenu(undefined, undefined),
|
2023-11-15 02:28:59 +00:00
|
|
|
/*LANG*/"Event": () => showEditAlarmMenu(undefined, undefined, true, null, group)
|
|
|
|
};
|
|
|
|
|
|
|
|
if (group) delete newMenu[/*LANG*/"Timer"];
|
|
|
|
E.showMenu(newMenu);
|
2022-03-31 12:48:45 +00:00
|
|
|
}
|
|
|
|
|
2023-11-15 03:04:47 +00:00
|
|
|
function showEditAlarmMenu(selectedAlarm, alarmIndex, withDate, scroll, group) {
|
2022-05-12 20:59:03 +00:00
|
|
|
var isNew = alarmIndex === undefined;
|
|
|
|
|
|
|
|
var alarm = require("sched").newDefaultAlarm();
|
2023-11-15 02:28:59 +00:00
|
|
|
if (isNew && group) alarm.group = group;
|
2023-11-15 20:35:37 +00:00
|
|
|
if (withDate || (selectedAlarm && selectedAlarm.date)) {
|
2023-10-14 07:23:49 +00:00
|
|
|
alarm.del = require("sched").getSettings().defaultDeleteExpiredTimers;
|
|
|
|
}
|
2022-05-12 20:59:03 +00:00
|
|
|
alarm.dow = handleFirstDayOfWeek(alarm.dow);
|
|
|
|
|
|
|
|
if (selectedAlarm) {
|
|
|
|
Object.assign(alarm, selectedAlarm);
|
|
|
|
}
|
2022-05-03 19:34:03 +00:00
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
var time = require("time_utils").decodeTime(alarm.t);
|
2022-12-20 00:18:08 +00:00
|
|
|
if (withDate && !alarm.date) alarm.date = new Date().toLocalISOString().slice(0,10);
|
|
|
|
var date = alarm.date ? new Date(alarm.date) : undefined;
|
|
|
|
var title = date ? (isNew ? /*LANG*/"New Event" : /*LANG*/"Edit Event") : (isNew ? /*LANG*/"New Alarm" : /*LANG*/"Edit Alarm");
|
|
|
|
var keyboard = "textinput";
|
|
|
|
try {keyboard = require(keyboard);} catch(e) {keyboard = null;}
|
2024-04-29 02:59:53 +00:00
|
|
|
var datetimeinput;
|
|
|
|
try {datetimeinput = require("datetimeinput");} catch(e) {datetimeinput = null;}
|
2022-03-31 12:48:45 +00:00
|
|
|
|
2020-02-12 10:48:14 +00:00
|
|
|
const menu = {
|
2022-12-20 00:18:08 +00:00
|
|
|
"": { "title": title },
|
2022-05-12 20:59:03 +00:00
|
|
|
"< Back": () => {
|
2022-12-20 00:18:08 +00:00
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, date);
|
2022-05-28 20:16:23 +00:00
|
|
|
saveAndReload();
|
2023-11-15 03:04:47 +00:00
|
|
|
showMainMenu(scroll, group);
|
2024-04-29 02:59:53 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (alarm.date && datetimeinput) {
|
|
|
|
menu[`${getDateText(date.toLocalISOString().slice(0,10))} ${require("time_utils").formatTime(time)}`] = {
|
|
|
|
value: date,
|
|
|
|
format: v => "",
|
|
|
|
onchange: v => {
|
|
|
|
setTimeout(() => {
|
|
|
|
var datetime = new Date(v.getTime());
|
|
|
|
datetime.setHours(time.h, time.m);
|
|
|
|
datetimeinput.input({datetime}).then(result => {
|
|
|
|
time.h = result.getHours();
|
|
|
|
time.m = result.getMinutes();
|
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, result, true);
|
|
|
|
setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate, scroll, group);
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
Object.assign(menu, {
|
|
|
|
/*LANG*/"Hour": {
|
|
|
|
value: time.h,
|
|
|
|
format: v => ("0" + v).substr(-2),
|
|
|
|
min: 0,
|
|
|
|
max: 23,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => time.h = v
|
|
|
|
},
|
|
|
|
/*LANG*/"Minute": {
|
|
|
|
value: time.m,
|
|
|
|
format: v => ("0" + v).substr(-2),
|
|
|
|
min: 0,
|
|
|
|
max: 59,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => time.m = v
|
|
|
|
},
|
|
|
|
/*LANG*/"Day": {
|
|
|
|
value: date ? date.getDate() : null,
|
|
|
|
min: 1,
|
|
|
|
max: 31,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => date.setDate(v)
|
|
|
|
},
|
|
|
|
/*LANG*/"Month": {
|
|
|
|
value: date ? date.getMonth() + 1 : null,
|
|
|
|
format: v => require("date_utils").month(v),
|
|
|
|
onchange: v => date.setMonth((v+11)%12)
|
|
|
|
},
|
|
|
|
/*LANG*/"Year": {
|
|
|
|
value: date ? date.getFullYear() : null,
|
|
|
|
min: new Date().getFullYear(),
|
|
|
|
max: 2100,
|
|
|
|
onchange: v => date.setFullYear(v)
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Object.assign(menu, {
|
2022-12-20 00:18:08 +00:00
|
|
|
/*LANG*/"Message": {
|
|
|
|
value: alarm.msg,
|
2023-06-08 03:13:06 +00:00
|
|
|
format: formatAlarmProperty,
|
2022-12-20 00:18:08 +00:00
|
|
|
onchange: () => {
|
|
|
|
setTimeout(() => {
|
|
|
|
keyboard.input({text:alarm.msg}).then(result => {
|
|
|
|
alarm.msg = result;
|
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, date, true);
|
2023-11-15 02:28:59 +00:00
|
|
|
setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate, scroll, group);
|
2022-12-20 00:18:08 +00:00
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
},
|
2023-06-08 03:13:06 +00:00
|
|
|
/*LANG*/"Group": {
|
|
|
|
value: alarm.group,
|
|
|
|
format: formatAlarmProperty,
|
|
|
|
onchange: () => {
|
|
|
|
setTimeout(() => {
|
|
|
|
keyboard.input({text:alarm.group}).then(result => {
|
|
|
|
alarm.group = result;
|
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, date, true);
|
2023-11-15 02:28:59 +00:00
|
|
|
setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate, scroll, group);
|
2023-06-08 03:13:06 +00:00
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
},
|
2022-05-12 20:59:03 +00:00
|
|
|
/*LANG*/"Enabled": {
|
|
|
|
value: alarm.on,
|
|
|
|
onchange: v => alarm.on = v
|
2022-03-31 12:48:45 +00:00
|
|
|
},
|
2022-05-12 20:59:03 +00:00
|
|
|
/*LANG*/"Repeat": {
|
2023-01-09 04:04:13 +00:00
|
|
|
value: decodeRepeat(alarm),
|
|
|
|
onchange: () => setTimeout(showEditRepeatMenu, 100, alarm.rp, date || alarm.dow, (repeat, dow) => {
|
2023-10-14 07:23:49 +00:00
|
|
|
if (repeat) {
|
|
|
|
alarm.del = false; // do not auto delete a repeated alarm
|
|
|
|
}
|
2022-05-20 16:21:32 +00:00
|
|
|
alarm.rp = repeat;
|
2022-05-12 20:59:03 +00:00
|
|
|
alarm.dow = dow;
|
2022-12-20 00:18:08 +00:00
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, date, true);
|
2023-11-15 02:28:59 +00:00
|
|
|
setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate, scroll, group);
|
2022-04-21 09:15:49 +00:00
|
|
|
})
|
2020-06-01 17:12:14 +00:00
|
|
|
},
|
2022-05-12 20:59:03 +00:00
|
|
|
/*LANG*/"Vibrate": require("buzz_menu").pattern(alarm.vibrate, v => alarm.vibrate = v),
|
|
|
|
/*LANG*/"Auto Snooze": {
|
|
|
|
value: alarm.as,
|
|
|
|
onchange: v => alarm.as = v
|
|
|
|
},
|
2023-10-14 07:23:49 +00:00
|
|
|
/*LANG*/"Delete After Expiration": {
|
|
|
|
value: alarm.del,
|
|
|
|
onchange: v => alarm.del = v
|
|
|
|
},
|
2022-07-08 16:25:36 +00:00
|
|
|
/*LANG*/"Hidden": {
|
|
|
|
value: alarm.hidden || false,
|
|
|
|
onchange: v => alarm.hidden = v
|
|
|
|
},
|
2023-11-15 03:04:47 +00:00
|
|
|
/*LANG*/"Cancel": () => showMainMenu(scroll, group),
|
2022-12-01 09:10:00 +00:00
|
|
|
/*LANG*/"Confirm": () => {
|
2023-07-30 00:20:36 +00:00
|
|
|
prepareAlarmForSave(alarm, alarmIndex, time, date);
|
2022-12-01 09:03:23 +00:00
|
|
|
saveAndReload();
|
2023-11-15 03:04:47 +00:00
|
|
|
showMainMenu(scroll, group);
|
2022-12-01 09:29:00 +00:00
|
|
|
}
|
2024-04-29 02:59:53 +00:00
|
|
|
});
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
if (!keyboard) delete menu[/*LANG*/"Message"];
|
2023-06-08 03:13:06 +00:00
|
|
|
if (!keyboard || !settings.showGroup) delete menu[/*LANG*/"Group"];
|
2023-09-18 21:38:17 +00:00
|
|
|
if (!settings.showConfirm) delete menu[/*LANG*/"Confirm"];
|
|
|
|
if (!settings.showAutoSnooze) delete menu[/*LANG*/"Auto Snooze"];
|
|
|
|
if (!settings.showHidden) delete menu[/*LANG*/"Hidden"];
|
2023-01-09 04:04:13 +00:00
|
|
|
if (!alarm.date) {
|
2022-12-20 00:18:08 +00:00
|
|
|
delete menu[/*LANG*/"Day"];
|
|
|
|
delete menu[/*LANG*/"Month"];
|
|
|
|
delete menu[/*LANG*/"Year"];
|
2023-10-14 07:23:49 +00:00
|
|
|
delete menu[/*LANG*/"Delete After Expiration"];
|
2022-12-20 00:18:08 +00:00
|
|
|
}
|
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
if (!isNew) {
|
|
|
|
menu[/*LANG*/"Delete"] = () => {
|
2023-01-31 18:04:06 +00:00
|
|
|
E.showPrompt(getLabel(alarm) + "\n" + /*LANG*/"Are you sure?", { title: /*LANG*/"Delete Alarm" }).then((confirm) => {
|
2022-05-12 20:59:03 +00:00
|
|
|
if (confirm) {
|
|
|
|
alarms.splice(alarmIndex, 1);
|
|
|
|
saveAndReload();
|
2023-11-15 03:04:47 +00:00
|
|
|
showMainMenu(scroll, group);
|
2022-05-12 20:59:03 +00:00
|
|
|
} else {
|
|
|
|
alarm.t = require("time_utils").encodeTime(time);
|
2023-11-15 02:28:59 +00:00
|
|
|
setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex, withDate, scroll, group);
|
2022-05-12 20:59:03 +00:00
|
|
|
}
|
|
|
|
});
|
2020-02-12 10:48:14 +00:00
|
|
|
};
|
|
|
|
}
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
E.showMenu(menu);
|
2020-02-12 10:48:14 +00:00
|
|
|
}
|
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
function prepareAlarmForSave(alarm, alarmIndex, time, date, temp) {
|
2022-05-12 20:59:03 +00:00
|
|
|
alarm.t = require("time_utils").encodeTime(time);
|
|
|
|
alarm.last = alarm.t < require("time_utils").getCurrentTimeMillis() ? new Date().getDate() : 0;
|
2022-12-20 00:18:08 +00:00
|
|
|
if(date) alarm.date = date.toLocalISOString().slice(0,10);
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
if(!temp) {
|
|
|
|
if (alarmIndex === undefined) {
|
|
|
|
alarms.push(alarm);
|
|
|
|
} else {
|
|
|
|
alarms[alarmIndex] = alarm;
|
|
|
|
}
|
2022-04-25 13:24:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
function saveAndReload() {
|
2022-05-25 21:13:37 +00:00
|
|
|
// Before saving revert the dow to the standard format (alarms only!)
|
|
|
|
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
2022-05-12 20:59:03 +00:00
|
|
|
|
|
|
|
require("sched").setAlarms(alarms);
|
|
|
|
require("sched").reload();
|
|
|
|
|
|
|
|
// Fix after save
|
2022-05-25 21:13:37 +00:00
|
|
|
alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow));
|
2022-05-12 20:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 04:04:13 +00:00
|
|
|
function decodeRepeat(alarm) {
|
2022-05-12 20:59:03 +00:00
|
|
|
return alarm.rp
|
2023-01-09 04:04:13 +00:00
|
|
|
? (alarm.date
|
|
|
|
? `${alarm.rp.num}*${INTERVAL_LABELS[INTERVALS.indexOf(alarm.rp.interval)]}`
|
|
|
|
: require("date_utils")
|
|
|
|
.dows(firstDayOfWeek, 2)
|
|
|
|
.map((day, index) => alarm.dow & (1 << (index + firstDayOfWeek)) ? day : "_")
|
|
|
|
.join("")
|
|
|
|
.toLowerCase())
|
2023-03-16 17:39:46 +00:00
|
|
|
: /*LANG*/"Once";
|
2022-05-12 20:59:03 +00:00
|
|
|
}
|
|
|
|
|
2023-01-09 04:04:13 +00:00
|
|
|
function showEditRepeatMenu(repeat, day, dowChangeCallback) {
|
|
|
|
var dow;
|
2022-03-31 12:48:45 +00:00
|
|
|
|
2021-10-06 08:47:37 +00:00
|
|
|
const menu = {
|
2022-05-12 20:59:03 +00:00
|
|
|
"": { "title": /*LANG*/"Repeat Alarm" },
|
2022-05-20 16:21:32 +00:00
|
|
|
"< Back": () => dowChangeCallback(repeat, dow),
|
2023-01-09 04:04:13 +00:00
|
|
|
/*LANG*/"Only Once": () => dowChangeCallback(false, EVERY_DAY)
|
2022-05-20 16:21:32 +00:00
|
|
|
// The alarm will fire once. Internally it will be saved
|
|
|
|
// as "fire every days" BUT the repeat flag is false so
|
|
|
|
// we avoid messing up with the scheduler.
|
2022-05-12 20:59:03 +00:00
|
|
|
};
|
|
|
|
|
2023-01-09 04:04:13 +00:00
|
|
|
let restOfMenu;
|
|
|
|
if (typeof day === "number") {
|
|
|
|
dow = day;
|
|
|
|
var originalDow = dow;
|
|
|
|
var isCustom = repeat && dow != WORKDAYS && dow != WEEKEND && dow != EVERY_DAY;
|
|
|
|
|
|
|
|
restOfMenu = {
|
|
|
|
/*LANG*/"Workdays": {
|
|
|
|
value: repeat && dow == WORKDAYS,
|
|
|
|
onchange: () => dowChangeCallback(true, WORKDAYS)
|
|
|
|
},
|
|
|
|
/*LANG*/"Weekends": {
|
|
|
|
value: repeat && dow == WEEKEND,
|
|
|
|
onchange: () => dowChangeCallback(true, WEEKEND)
|
|
|
|
},
|
|
|
|
/*LANG*/"Every Day": {
|
|
|
|
value: repeat && dow == EVERY_DAY,
|
|
|
|
onchange: () => dowChangeCallback(true, EVERY_DAY)
|
|
|
|
},
|
|
|
|
/*LANG*/"Custom": {
|
|
|
|
value: isCustom ? decodeRepeat({ rp: true, dow: dow }) : false,
|
2023-10-14 07:25:39 +00:00
|
|
|
onchange: () => setTimeout(showCustomDaysMenu, 10, dow, dowChangeCallback, repeat, originalDow)
|
2023-01-09 04:04:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
} else {
|
2023-03-09 20:13:10 +00:00
|
|
|
// var date = day; // eventually: detect day of date and configure a repeat e.g. 3rd Monday of Month
|
2023-01-09 04:04:13 +00:00
|
|
|
dow = EVERY_DAY;
|
2023-10-14 07:25:39 +00:00
|
|
|
const repeatObj = repeat || {interval: "month", num: 1};
|
2023-01-09 04:04:13 +00:00
|
|
|
|
|
|
|
restOfMenu = {
|
|
|
|
/*LANG*/"Every": {
|
2023-10-14 07:25:39 +00:00
|
|
|
value: repeatObj.num,
|
2023-01-09 04:04:13 +00:00
|
|
|
min: 1,
|
2023-10-14 07:25:39 +00:00
|
|
|
onchange: v => {
|
|
|
|
repeat = repeatObj;
|
|
|
|
repeat.num = v;
|
|
|
|
}
|
2023-01-09 04:04:13 +00:00
|
|
|
},
|
|
|
|
/*LANG*/"Interval": {
|
2023-10-14 07:25:39 +00:00
|
|
|
value: INTERVALS.indexOf(repeatObj.interval),
|
2023-01-09 04:04:13 +00:00
|
|
|
format: v => INTERVAL_LABELS[v],
|
|
|
|
min: 0,
|
|
|
|
max: INTERVALS.length - 1,
|
2023-10-14 07:25:39 +00:00
|
|
|
onchange: v => {
|
|
|
|
repeat = repeatObj;
|
|
|
|
repeat.interval = INTERVALS[v];
|
|
|
|
}
|
2023-01-09 04:04:13 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
Object.assign(menu, restOfMenu);
|
2022-05-12 20:59:03 +00:00
|
|
|
E.showMenu(menu);
|
|
|
|
}
|
|
|
|
|
2022-05-20 16:21:32 +00:00
|
|
|
function showCustomDaysMenu(dow, dowChangeCallback, originalRepeat, originalDow) {
|
2022-05-12 20:59:03 +00:00
|
|
|
const menu = {
|
|
|
|
"": { "title": /*LANG*/"Custom Days" },
|
2022-05-20 20:26:36 +00:00
|
|
|
"< Back": () => {
|
|
|
|
// If the user unchecks all the days then we assume repeat = once
|
|
|
|
// and we force the dow to every day.
|
|
|
|
var repeat = dow > 0;
|
2023-03-16 17:39:46 +00:00
|
|
|
dowChangeCallback(repeat, repeat ? dow : EVERY_DAY);
|
2022-05-20 20:26:36 +00:00
|
|
|
}
|
2021-10-06 08:47:37 +00:00
|
|
|
};
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
require("date_utils").dows(firstDayOfWeek).forEach((day, i) => {
|
|
|
|
menu[day] = {
|
|
|
|
value: !!(dow & (1 << (i + firstDayOfWeek))),
|
|
|
|
onchange: v => v ? (dow |= 1 << (i + firstDayOfWeek)) : (dow &= ~(1 << (i + firstDayOfWeek)))
|
|
|
|
};
|
|
|
|
});
|
|
|
|
|
2023-03-16 17:39:46 +00:00
|
|
|
menu[/*LANG*/"Cancel"] = () => setTimeout(showEditRepeatMenu, 10, originalRepeat, originalDow, dowChangeCallback);
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
E.showMenu(menu);
|
|
|
|
}
|
|
|
|
|
|
|
|
function showEditTimerMenu(selectedTimer, timerIndex) {
|
|
|
|
var isNew = timerIndex === undefined;
|
|
|
|
|
|
|
|
var timer = require("sched").newDefaultTimer();
|
|
|
|
|
|
|
|
if (selectedTimer) {
|
|
|
|
Object.assign(timer, selectedTimer);
|
|
|
|
}
|
|
|
|
|
|
|
|
var time = require("time_utils").decodeTime(timer.timer);
|
2022-12-20 00:18:08 +00:00
|
|
|
var keyboard = "textinput";
|
|
|
|
try {keyboard = require(keyboard);} catch(e) {keyboard = null;}
|
2022-05-12 20:59:03 +00:00
|
|
|
|
|
|
|
const menu = {
|
|
|
|
"": { "title": isNew ? /*LANG*/"New Timer" : /*LANG*/"Edit Timer" },
|
|
|
|
"< Back": () => {
|
2022-05-28 20:16:23 +00:00
|
|
|
prepareTimerForSave(timer, timerIndex, time);
|
|
|
|
saveAndReload();
|
2021-10-06 08:47:37 +00:00
|
|
|
showMainMenu();
|
2022-05-12 20:59:03 +00:00
|
|
|
},
|
|
|
|
/*LANG*/"Hours": {
|
|
|
|
value: time.h,
|
|
|
|
min: 0,
|
|
|
|
max: 23,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => time.h = v
|
|
|
|
},
|
|
|
|
/*LANG*/"Minutes": {
|
|
|
|
value: time.m,
|
|
|
|
min: 0,
|
|
|
|
max: 59,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => time.m = v
|
|
|
|
},
|
2022-06-02 15:54:16 +00:00
|
|
|
/*LANG*/"Seconds": {
|
|
|
|
value: time.s,
|
|
|
|
min: 0,
|
|
|
|
max: 59,
|
|
|
|
step: 1,
|
|
|
|
wrap: true,
|
|
|
|
onchange: v => time.s = v
|
|
|
|
},
|
2022-12-20 00:18:08 +00:00
|
|
|
/*LANG*/"Message": {
|
|
|
|
value: timer.msg,
|
2023-06-08 03:13:06 +00:00
|
|
|
format: formatAlarmProperty,
|
2022-12-20 00:18:08 +00:00
|
|
|
onchange: () => {
|
|
|
|
setTimeout(() => {
|
|
|
|
keyboard.input({text:timer.msg}).then(result => {
|
|
|
|
timer.msg = result;
|
|
|
|
prepareTimerForSave(timer, timerIndex, time, true);
|
|
|
|
setTimeout(showEditTimerMenu, 10, timer, timerIndex);
|
|
|
|
});
|
|
|
|
}, 100);
|
|
|
|
}
|
|
|
|
},
|
2022-05-12 20:59:03 +00:00
|
|
|
/*LANG*/"Enabled": {
|
|
|
|
value: timer.on,
|
|
|
|
onchange: v => timer.on = v
|
|
|
|
},
|
2022-06-16 20:04:40 +00:00
|
|
|
/*LANG*/"Delete After Expiration": {
|
|
|
|
value: timer.del,
|
|
|
|
onchange: v => timer.del = v
|
|
|
|
},
|
2022-07-08 16:25:36 +00:00
|
|
|
/*LANG*/"Hidden": {
|
|
|
|
value: timer.hidden || false,
|
|
|
|
onchange: v => timer.hidden = v
|
|
|
|
},
|
2022-06-07 19:56:14 +00:00
|
|
|
/*LANG*/"Vibrate": require("buzz_menu").pattern(timer.vibrate, v => timer.vibrate = v),
|
2022-12-01 09:29:00 +00:00
|
|
|
/*LANG*/"Cancel": () => showMainMenu(),
|
|
|
|
/*LANG*/"Confirm": () => {
|
|
|
|
prepareTimerForSave(timer, timerIndex, time);
|
|
|
|
saveAndReload();
|
|
|
|
showMainMenu();
|
|
|
|
}
|
2022-05-12 20:59:03 +00:00
|
|
|
};
|
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
if (!keyboard) delete menu[/*LANG*/"Message"];
|
2023-09-19 07:27:11 +00:00
|
|
|
if (!settings.showConfirm) delete menu[/*LANG*/"Confirm"];
|
|
|
|
if (!settings.showHidden) delete menu[/*LANG*/"Hidden"];
|
2022-05-12 20:59:03 +00:00
|
|
|
if (!isNew) {
|
|
|
|
menu[/*LANG*/"Delete"] = () => {
|
2023-01-31 18:04:06 +00:00
|
|
|
E.showPrompt(getLabel(timer) + "\n" + /*LANG*/"Are you sure?", { title: /*LANG*/"Delete Timer" }).then((confirm) => {
|
2022-05-12 20:59:03 +00:00
|
|
|
if (confirm) {
|
|
|
|
alarms.splice(timerIndex, 1);
|
|
|
|
saveAndReload();
|
|
|
|
showMainMenu();
|
|
|
|
} else {
|
|
|
|
timer.timer = require("time_utils").encodeTime(time);
|
2023-03-16 17:39:46 +00:00
|
|
|
setTimeout(showEditTimerMenu, 10, timer, timerIndex);
|
2022-05-12 20:59:03 +00:00
|
|
|
}
|
|
|
|
});
|
2021-10-06 08:47:37 +00:00
|
|
|
};
|
|
|
|
}
|
2022-05-12 20:59:03 +00:00
|
|
|
|
|
|
|
E.showMenu(menu);
|
2021-10-06 08:47:37 +00:00
|
|
|
}
|
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
function prepareTimerForSave(timer, timerIndex, time, temp) {
|
2022-05-12 20:59:03 +00:00
|
|
|
timer.timer = require("time_utils").encodeTime(time);
|
2024-03-22 19:35:06 +00:00
|
|
|
timer.t = (require("time_utils").getCurrentTimeMillis() + timer.timer) % 86400000;
|
2022-05-12 20:59:03 +00:00
|
|
|
timer.last = 0;
|
2022-04-25 13:24:05 +00:00
|
|
|
|
2022-12-20 00:18:08 +00:00
|
|
|
if (!temp) {
|
|
|
|
if (timerIndex === undefined) {
|
|
|
|
alarms.push(timer);
|
|
|
|
} else {
|
|
|
|
alarms[timerIndex] = timer;
|
|
|
|
}
|
2022-04-25 13:24:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-12 20:59:03 +00:00
|
|
|
function showAdvancedMenu() {
|
|
|
|
E.showMenu({
|
|
|
|
"": { "title": /*LANG*/"Advanced" },
|
|
|
|
"< Back": () => showMainMenu(),
|
|
|
|
/*LANG*/"Scheduler Settings": () => eval(require("Storage").read("sched.settings.js"))(() => showAdvancedMenu()),
|
|
|
|
/*LANG*/"Enable All": () => enableAll(true),
|
|
|
|
/*LANG*/"Disable All": () => enableAll(false),
|
|
|
|
/*LANG*/"Delete All": () => deleteAll()
|
|
|
|
});
|
2022-05-03 19:34:03 +00:00
|
|
|
}
|
|
|
|
|
2022-04-25 13:23:18 +00:00
|
|
|
function enableAll(on) {
|
2022-05-12 20:59:03 +00:00
|
|
|
if (alarms.filter(e => e.on == !on).length == 0) {
|
2022-05-20 20:41:26 +00:00
|
|
|
E.showAlert(
|
|
|
|
on ? /*LANG*/"Nothing to Enable" : /*LANG*/"Nothing to Disable",
|
|
|
|
on ? /*LANG*/"Enable All" : /*LANG*/"Disable All"
|
|
|
|
).then(() => showAdvancedMenu());
|
2022-05-12 20:59:03 +00:00
|
|
|
} else {
|
2022-05-20 20:08:59 +00:00
|
|
|
E.showPrompt(/*LANG*/"Are you sure?", { title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All" }).then((confirm) => {
|
2022-05-12 20:59:03 +00:00
|
|
|
if (confirm) {
|
2022-05-28 20:16:23 +00:00
|
|
|
alarms.forEach((alarm, i) => {
|
|
|
|
alarm.on = on;
|
|
|
|
if (on) {
|
|
|
|
if (alarm.timer) {
|
2023-03-16 17:39:46 +00:00
|
|
|
prepareTimerForSave(alarm, i, require("time_utils").decodeTime(alarm.timer));
|
2022-05-28 20:16:23 +00:00
|
|
|
} else {
|
2023-03-16 17:39:46 +00:00
|
|
|
prepareAlarmForSave(alarm, i, require("time_utils").decodeTime(alarm.t));
|
2022-05-28 20:16:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2022-05-12 20:59:03 +00:00
|
|
|
saveAndReload();
|
|
|
|
showMainMenu();
|
|
|
|
} else {
|
|
|
|
showAdvancedMenu();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2022-04-25 13:23:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function deleteAll() {
|
2022-05-12 20:59:03 +00:00
|
|
|
if (alarms.length == 0) {
|
2022-05-20 20:41:26 +00:00
|
|
|
E.showAlert(/*LANG*/"Nothing to delete", /*LANG*/"Delete All").then(() => showAdvancedMenu());
|
2022-05-12 20:59:03 +00:00
|
|
|
} else {
|
|
|
|
E.showPrompt(/*LANG*/"Are you sure?", {
|
|
|
|
title: /*LANG*/"Delete All"
|
|
|
|
}).then((confirm) => {
|
|
|
|
if (confirm) {
|
|
|
|
alarms = [];
|
|
|
|
saveAndReload();
|
|
|
|
showMainMenu();
|
|
|
|
} else {
|
|
|
|
showAdvancedMenu();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2022-04-25 13:23:18 +00:00
|
|
|
}
|
|
|
|
|
2020-02-28 15:34:31 +00:00
|
|
|
showMainMenu();
|