mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-14 11:05:41 +05:00
Add basic reminders
This commit is contained in:
parent
68b94fee41
commit
5ec4e39413
@ -459,6 +459,25 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
Messages.reminder_minutes = "<b>{0}</b> will start in {1} minutes!"; // XXX
|
||||
Messages.reminder_hour = "<b>{0}</b> will start in 1 hour!"; // XXX
|
||||
handlers['REMINDER'] = function (common, data) {
|
||||
var content = data.content;
|
||||
var msg = content.msg.content;
|
||||
var now = +new Date();
|
||||
var start = msg.start;
|
||||
content.getFormatText = function () {
|
||||
if ((start - now) > 600000) {
|
||||
return Messages._getKey('reminder_hour', [Util.fixHTML(msg.title)]);
|
||||
}
|
||||
var minutes = Math.round((start - now) / 60000);
|
||||
return Messages._getKey('reminder_minutes', [Util.fixHTML(msg.title), minutes]);
|
||||
};
|
||||
if (!content.archived) {
|
||||
content.dismissHandler = defaultDismiss(common, data);
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: don't forget to fixHTML everything returned by "getFormatText"
|
||||
|
||||
return {
|
||||
|
||||
@ -12,60 +12,6 @@ define([
|
||||
], function (Util, Hash, Constants, Realtime, Cache, Messages, nThen, Listmap, Crypto, ChainPad) {
|
||||
var Calendar = {};
|
||||
|
||||
|
||||
/* TODO
|
||||
* Calendar
|
||||
{
|
||||
href,
|
||||
roHref,
|
||||
channel, (pinning)
|
||||
title, (when created from the UI, own calendar has no title)
|
||||
color
|
||||
}
|
||||
|
||||
|
||||
* Own drive
|
||||
{
|
||||
calendars: {
|
||||
uid: calendar,
|
||||
uid: calendar
|
||||
}
|
||||
}
|
||||
|
||||
* Team drive
|
||||
{
|
||||
calendars: {
|
||||
uid: calendar,
|
||||
uid: calendar
|
||||
}
|
||||
}
|
||||
|
||||
* Calendars are listmap
|
||||
{
|
||||
content: {},
|
||||
metadata: {
|
||||
title: "pewpewpew"
|
||||
}
|
||||
}
|
||||
|
||||
ctx.calendars[channel] = {
|
||||
lm: lm,
|
||||
proxy: lm.proxy?
|
||||
stores: [teamId, teamId, 1]
|
||||
}
|
||||
|
||||
* calendar app can subscribe to this module
|
||||
* when a listmap changes, push an update for this calendar to subscribed tabs
|
||||
* Ability to open a calendar not stored in the stores but from its URL directly
|
||||
* No "userlist" visible in the UI
|
||||
* No framework
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
var getStore = function (ctx, id) {
|
||||
if (!id || id === 1) {
|
||||
return ctx.store;
|
||||
@ -109,6 +55,15 @@ ctx.calendars[channel] = {
|
||||
}, ctx.clients);
|
||||
};
|
||||
|
||||
var clearReminders = function (ctx, id) {
|
||||
var calendar = ctx.calendars[id];
|
||||
if (!calendar || !calendar.reminders) { return; }
|
||||
// Clear existing reminders
|
||||
Object.keys(calendar.reminders).forEach(function (uid) {
|
||||
if (!Array.isArray(calendar.reminders[uid])) { return; }
|
||||
calendar.reminders[uid].forEach(function (to) { clearTimeout(to); });
|
||||
});
|
||||
};
|
||||
var closeCalendar = function (ctx, id) {
|
||||
var ctxCal = ctx.calendars[id];
|
||||
if (!ctxCal) { return; }
|
||||
@ -116,6 +71,7 @@ ctx.calendars[channel] = {
|
||||
// If the calendar doesn't exist in any other team, stop it and delete it from ctx
|
||||
if (!ctxCal.stores.length) {
|
||||
ctxCal.lm.stop();
|
||||
clearReminders(ctx, id);
|
||||
delete ctx.calendars[id];
|
||||
}
|
||||
};
|
||||
@ -133,12 +89,83 @@ ctx.calendars[channel] = {
|
||||
if (cal.title !== data.title) { cal.title = data.title; }
|
||||
});
|
||||
};
|
||||
|
||||
var updateEventReminders = function (ctx, reminders, ev) {
|
||||
var now = +new Date();
|
||||
var time10 = now + (600 * 1000); // 10 minutes from now
|
||||
var time60 = now + (3600 * 1000); // 1 hour from now
|
||||
var uid = ev.id;
|
||||
|
||||
// Clear reminders for this event
|
||||
if (Array.isArray(reminders[uid])) {
|
||||
reminders[uid].forEach(function (to) { clearTimeout(to); });
|
||||
}
|
||||
reminders[uid] = [];
|
||||
|
||||
// No reminder for past events
|
||||
if (ev.start <= now) {
|
||||
delete reminders[uid];
|
||||
return;
|
||||
}
|
||||
|
||||
var send = function () {
|
||||
console.error(ev);
|
||||
ctx.store.mailbox.showMessage('reminders', {
|
||||
msg: {
|
||||
ctime: +new Date(),
|
||||
type: "REMINDER",
|
||||
content: ev
|
||||
},
|
||||
hash: 'REMINDER|'+uid
|
||||
}, null, function () {
|
||||
});
|
||||
};
|
||||
var sendNotif = function () { ctx.Store.onReadyEvt.reg(send); };
|
||||
|
||||
if (ev.start <= time10) {
|
||||
sendNotif();
|
||||
return;
|
||||
}
|
||||
|
||||
// It starts in more than 10 minutes: prepare the 10 minutes notification
|
||||
reminders[uid].push(setTimeout(function () {
|
||||
sendNotif();
|
||||
}, (ev.start - time10)));
|
||||
|
||||
if (ev.start <= time60) { return; }
|
||||
|
||||
// It starts in more than 1 hour: prepare the 1 hour notification
|
||||
reminders[uid].push(setTimeout(function () {
|
||||
sendNotif();
|
||||
}, (ev.start - time60)));
|
||||
};
|
||||
var addReminders = function (ctx, id, ev) {
|
||||
var calendar = ctx.calendars[id];
|
||||
if (!calendar || !calendar.reminders) { return; }
|
||||
if (calendar.stores.length === 1 && calendar.stores[0] === 0) { return; }
|
||||
|
||||
updateEventReminders(ctx, calendar.reminders, ev);
|
||||
};
|
||||
var addInitialReminders = function (ctx, id) {
|
||||
var calendar = ctx.calendars[id];
|
||||
if (!calendar || !calendar.reminders) { return; }
|
||||
if (Object.keys(calendar.reminders).length) { return; } // Already initialized
|
||||
|
||||
// No reminders for calendars not stored
|
||||
if (calendar.stores.length === 1 && calendar.stores[0] === 0) { return; }
|
||||
|
||||
// Re-add all reminders
|
||||
var content = Util.find(calendar, ['proxy', 'content']);
|
||||
if (!content) { return; }
|
||||
Object.keys(content).forEach(function (uid) {
|
||||
updateEventReminders(ctx, calendar.reminders, content[uid]);
|
||||
});
|
||||
};
|
||||
var openChannel = function (ctx, cfg, _cb) {
|
||||
var cb = Util.once(Util.mkAsync(_cb || function () {}));
|
||||
var teamId = cfg.storeId;
|
||||
var data = cfg.data;
|
||||
var channel = data.channel;
|
||||
console.error(cfg);
|
||||
if (!channel) { return; }
|
||||
|
||||
var c = ctx.calendars[channel];
|
||||
@ -193,6 +220,7 @@ ctx.calendars[channel] = {
|
||||
readOnly: !data.href,
|
||||
stores: [teamId],
|
||||
roStores: data.href ? [] : [teamId],
|
||||
reminders: {},
|
||||
hashes: {}
|
||||
};
|
||||
|
||||
@ -232,6 +260,7 @@ ctx.calendars[channel] = {
|
||||
if (c.lm) { c.lm.stop(); }
|
||||
c.stores = [];
|
||||
sendUpdate(ctx, c);
|
||||
clearReminders(ctx, channel);
|
||||
delete ctx.calendars[channel];
|
||||
};
|
||||
|
||||
@ -290,6 +319,7 @@ ctx.calendars[channel] = {
|
||||
c.cacheready = true;
|
||||
setTimeout(update);
|
||||
if (cb) { cb(null, lm.proxy); }
|
||||
addInitialReminders(ctx, channel);
|
||||
}).on('ready', function (info) {
|
||||
var md = info.metadata;
|
||||
c.owners = md.owners || [];
|
||||
@ -306,9 +336,25 @@ ctx.calendars[channel] = {
|
||||
}
|
||||
setTimeout(update);
|
||||
if (cb) { cb(null, lm.proxy); }
|
||||
addInitialReminders(ctx, channel);
|
||||
}).on('change', [], function () {
|
||||
if (!c.ready) { return; }
|
||||
setTimeout(update);
|
||||
}).on('change', ['content'], function (o, n, p) {
|
||||
if (p.length === 2 && n && !o) { // New event
|
||||
addReminders(ctx, channel, n);
|
||||
}
|
||||
if (p.length === 2 && !n && o) { // Deleted event
|
||||
addReminders(ctx, channel, {
|
||||
id: p[1],
|
||||
start: 0
|
||||
});
|
||||
}
|
||||
if (p.length === 3 && n && o && p[2] === 'start') { // Update event start
|
||||
setTimeout(function () {
|
||||
addReminders(ctx, channel, proxy.content[p[1]]);
|
||||
});
|
||||
}
|
||||
}).on('change', ['metadata'], function () {
|
||||
// if title or color have changed, update our local values
|
||||
var md = proxy.metadata;
|
||||
@ -627,6 +673,7 @@ ctx.calendars[channel] = {
|
||||
c.proxy.content = c.proxy.content || {};
|
||||
c.proxy.content[data.id] = data;
|
||||
Realtime.whenRealtimeSyncs(c.lm.realtime, function () {
|
||||
addReminders(ctx, id, data);
|
||||
sendUpdate(ctx, c);
|
||||
cb();
|
||||
});
|
||||
@ -655,6 +702,7 @@ ctx.calendars[channel] = {
|
||||
ev[key] = changes[key];
|
||||
});
|
||||
|
||||
|
||||
// Move to a different calendar?
|
||||
if (changes.calendarId && newC) {
|
||||
newC.proxy.content[data.ev.id] = Util.clone(ev);
|
||||
@ -664,7 +712,10 @@ ctx.calendars[channel] = {
|
||||
nThen(function (waitFor) {
|
||||
Realtime.whenRealtimeSyncs(c.lm.realtime, waitFor());
|
||||
if (newC) { Realtime.whenRealtimeSyncs(newC.lm.realtime, waitFor()); }
|
||||
}).nThen(cb);
|
||||
}).nThen(function () {
|
||||
if (changes.start) { addReminders(ctx, id, ev); }
|
||||
cb();
|
||||
});
|
||||
};
|
||||
var deleteEvent = function (ctx, data, cId, cb) {
|
||||
var id = data.calendarId;
|
||||
@ -672,7 +723,12 @@ ctx.calendars[channel] = {
|
||||
if (!c) { return void cb({error: "ENOENT"}); }
|
||||
c.proxy.content = c.proxy.content || {};
|
||||
delete c.proxy.content[data.id];
|
||||
Realtime.whenRealtimeSyncs(c.lm.realtime, cb);
|
||||
Realtime.whenRealtimeSyncs(c.lm.realtime, function () {
|
||||
addReminders(ctx, id, {
|
||||
id: data.id,
|
||||
start: 0
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var removeClient = function (ctx, cId) {
|
||||
@ -693,7 +749,7 @@ ctx.calendars[channel] = {
|
||||
emit: emit,
|
||||
onReady: Util.mkEvent(true),
|
||||
calendars: {},
|
||||
clients: [],
|
||||
clients: []
|
||||
};
|
||||
|
||||
initializeCalendars(ctx, waitFor(function (err) {
|
||||
|
||||
@ -174,6 +174,18 @@ proxy.mailboxes = {
|
||||
var dismiss = function (ctx, data, cId, cb) {
|
||||
var type = data.type;
|
||||
var hash = data.hash;
|
||||
|
||||
// Reminder messages don't persist
|
||||
if (/^REMINDER\|/.test(hash)) {
|
||||
cb();
|
||||
delete ctx.boxes.reminders.content[hash];
|
||||
hideMessage(ctx, type, hash, ctx.clients.filter(function (clientId) {
|
||||
return clientId !== cId;
|
||||
}));
|
||||
return;
|
||||
};
|
||||
|
||||
|
||||
var box = ctx.boxes[type];
|
||||
if (!box) { return void cb({error: 'NOT_LOADED'}); }
|
||||
var m = box.data || {};
|
||||
@ -548,6 +560,10 @@ proxy.mailboxes = {
|
||||
initializeHistory(ctx);
|
||||
}
|
||||
|
||||
ctx.boxes.reminders = {
|
||||
content: {}
|
||||
};
|
||||
|
||||
Object.keys(mailboxes).forEach(function (key) {
|
||||
if (TYPES.indexOf(key) === -1) { return; }
|
||||
var m = mailboxes[key];
|
||||
@ -588,6 +604,15 @@ proxy.mailboxes = {
|
||||
});
|
||||
};
|
||||
|
||||
mailbox.showMessage = function (type, msg, cId, cb) {
|
||||
if (type === "reminders" && msg) {
|
||||
ctx.boxes.reminders.content[msg.hash] = msg.msg;
|
||||
// Hide existing messages for this event
|
||||
hideMessage(ctx, type, msg.hash, ctx.clients);
|
||||
}
|
||||
showMessage(ctx, type, msg, cId, cb);
|
||||
};
|
||||
|
||||
mailbox.open = function (key, m, cb, team, opts) {
|
||||
if (TYPES.indexOf(key) === -1 && !team) { return; }
|
||||
openChannel(ctx, key, m, cb, opts);
|
||||
|
||||
@ -65,6 +65,8 @@ define([
|
||||
if (/^LOCAL\|/.test(data.content.hash)) {
|
||||
$(avatar).addClass('preview');
|
||||
}
|
||||
} else if (data.type === 'reminders') {
|
||||
avatar = h('i.fa.fa-calendar.cp-broadcast.preview');
|
||||
} else if (userData && typeof(userData) === "object" && userData.profile) {
|
||||
avatar = h('span.cp-avatar');
|
||||
Common.displayAvatar($(avatar), userData.avatar, userData.displayName || userData.name);
|
||||
@ -117,7 +119,7 @@ define([
|
||||
|
||||
// Call the onMessage handlers
|
||||
var isNotification = function (type) {
|
||||
return type === "notifications" || /^team-/.test(type) || type === "broadcast";
|
||||
return type === "notifications" || /^team-/.test(type) || type === "broadcast" || type === "reminders";
|
||||
};
|
||||
var pushMessage = function (data, handler) {
|
||||
var todo = function (f) {
|
||||
|
||||
@ -1148,7 +1148,7 @@ MessengerUI, Messages) {
|
||||
$button.addClass('fa-bell');
|
||||
};
|
||||
|
||||
Common.mailbox.subscribe(['notifications', 'team', 'broadcast'], {
|
||||
Common.mailbox.subscribe(['notifications', 'team', 'broadcast', 'reminders'], {
|
||||
onMessage: function (data, el) {
|
||||
if (el) {
|
||||
$(div).prepend(el);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user