Mailbox and notifications prototype
This commit is contained in:
parent
3feb310fc4
commit
ce2d0d5b83
@ -625,6 +625,13 @@ define([
|
|||||||
|
|
||||||
// Set the display name (username) in the proxy
|
// Set the display name (username) in the proxy
|
||||||
Store.setDisplayName = function (clientId, value, cb) {
|
Store.setDisplayName = function (clientId, value, cb) {
|
||||||
|
if (store.mailbox) {
|
||||||
|
// XXX test mailbox, should be removed in prod
|
||||||
|
store.mailbox.post('notifications', 'NAME_CHANGED', {
|
||||||
|
old: store.proxy[Constants.displayNameKey],
|
||||||
|
new: value
|
||||||
|
});
|
||||||
|
}
|
||||||
store.proxy[Constants.displayNameKey] = value;
|
store.proxy[Constants.displayNameKey] = value;
|
||||||
broadcast([clientId], "UPDATE_METADATA");
|
broadcast([clientId], "UPDATE_METADATA");
|
||||||
if (store.messenger) { store.messenger.updateMyData(); }
|
if (store.messenger) { store.messenger.updateMyData(); }
|
||||||
@ -950,6 +957,7 @@ define([
|
|||||||
// Mailbox
|
// Mailbox
|
||||||
Store.mailbox = {
|
Store.mailbox = {
|
||||||
execCommand: function (clientId, data, cb) {
|
execCommand: function (clientId, data, cb) {
|
||||||
|
if (!store.loggedIn) { return void cb(); }
|
||||||
if (!store.mailbox) { return void cb ({error: 'Mailbox is disabled'}); }
|
if (!store.mailbox) { return void cb ({error: 'Mailbox is disabled'}); }
|
||||||
store.mailbox.execCommand(clientId, data, cb);
|
store.mailbox.execCommand(clientId, data, cb);
|
||||||
}
|
}
|
||||||
@ -1092,6 +1100,7 @@ define([
|
|||||||
channel.queue.forEach(function (data) {
|
channel.queue.forEach(function (data) {
|
||||||
channel.sendMessage(data.message, clientId);
|
channel.sendMessage(data.message, clientId);
|
||||||
});
|
});
|
||||||
|
channel.queue = [];
|
||||||
channel.bcast("PAD_CONNECT", {
|
channel.bcast("PAD_CONNECT", {
|
||||||
myID: wc.myID,
|
myID: wc.myID,
|
||||||
id: wc.id,
|
id: wc.id,
|
||||||
@ -1310,13 +1319,15 @@ define([
|
|||||||
if (messengerIdx !== -1) {
|
if (messengerIdx !== -1) {
|
||||||
messengerEventClients.splice(messengerIdx, 1);
|
messengerEventClients.splice(messengerIdx, 1);
|
||||||
}
|
}
|
||||||
// TODO mailbox events
|
|
||||||
try {
|
try {
|
||||||
store.cursor.removeClient(clientId);
|
store.cursor.removeClient(clientId);
|
||||||
} catch (e) { console.error(e); }
|
} catch (e) { console.error(e); }
|
||||||
try {
|
try {
|
||||||
store.onlyoffice.removeClient(clientId);
|
store.onlyoffice.removeClient(clientId);
|
||||||
} catch (e) { console.error(e); }
|
} catch (e) { console.error(e); }
|
||||||
|
try {
|
||||||
|
store.mailbox.removeClient(clientId);
|
||||||
|
} catch (e) { console.error(e); }
|
||||||
|
|
||||||
Object.keys(Store.channels).forEach(function (chanId) {
|
Object.keys(Store.channels).forEach(function (chanId) {
|
||||||
var chanIdx = Store.channels[chanId].clients.indexOf(clientId);
|
var chanIdx = Store.channels[chanId].clients.indexOf(clientId);
|
||||||
@ -1413,6 +1424,9 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
var loadMailbox = function (waitFor) {
|
var loadMailbox = function (waitFor) {
|
||||||
|
if (!store.loggedIn || !store.proxy.edPublic) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
store.mailbox = Mailbox.init(store, waitFor, function (ev, data, clients) {
|
store.mailbox = Mailbox.init(store, waitFor, function (ev, data, clients) {
|
||||||
clients.forEach(function (cId) {
|
clients.forEach(function (cId) {
|
||||||
postMessage(cId, 'MAILBOX_EVENT', {
|
postMessage(cId, 'MAILBOX_EVENT', {
|
||||||
|
|||||||
@ -1,30 +1,242 @@
|
|||||||
define([
|
define([
|
||||||
'/common/common-util.js',
|
'/common/common-util.js',
|
||||||
'/common/common-constants.js',
|
'/common/common-constants.js',
|
||||||
|
'/common/common-realtime.js',
|
||||||
'/customize/messages.js',
|
'/customize/messages.js',
|
||||||
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
'/bower_components/chainpad-netflux/chainpad-netflux.js',
|
||||||
'/bower_components/chainpad-crypto/crypto.js',
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
], function (Util, Constants, Messages, CpNetflux, Crypto) {
|
], function (Util, Constants, Realtime, Messages, CpNetflux, Crypto) {
|
||||||
var Mailbox = {};
|
var Mailbox = {};
|
||||||
|
|
||||||
|
var TYPES = [
|
||||||
|
'notifications'
|
||||||
|
];
|
||||||
|
var BLOCKING_TYPES = [
|
||||||
|
];
|
||||||
|
|
||||||
|
/*
|
||||||
|
proxy.mailboxes = {
|
||||||
|
friends: {
|
||||||
|
keys: '',
|
||||||
|
channel: '',
|
||||||
|
hash: '',
|
||||||
|
lastKnownHash: '',
|
||||||
|
viewed: []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
var isMessageNew = function (hash, m) {
|
||||||
|
return (m.viewed || []).indexOf(hash) === -1 && hash !== m.lastKnownHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
var showMessage = function (ctx, type, msg, cId) {
|
||||||
|
ctx.emit('MESSAGE', {
|
||||||
|
type: type,
|
||||||
|
content: msg
|
||||||
|
}, cId ? [cId] : ctx.clients);
|
||||||
|
};
|
||||||
|
|
||||||
|
var openChannel = function (ctx, type, m, onReady) {
|
||||||
|
var box = ctx.boxes[type] = {
|
||||||
|
queue: [],
|
||||||
|
history: [],
|
||||||
|
sendMessage: function (msg) { // To send a message to our box
|
||||||
|
try {
|
||||||
|
msg = JSON.stringify(msg);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
box.queue.push(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
// XXX
|
||||||
|
if (!Crypto.Mailbox) {
|
||||||
|
return void console.error("chainpad-crypto is outdated and doesn't support mailboxes.");
|
||||||
|
}
|
||||||
|
var crypto = Crypto.Mailbox.createEncryptor();
|
||||||
|
*/
|
||||||
|
var crypto = {
|
||||||
|
encrypt: function (x) { return x; },
|
||||||
|
decrypt: function (x) { return x; }
|
||||||
|
};
|
||||||
|
var cfg = {
|
||||||
|
network: ctx.store.network,
|
||||||
|
channel: m.channel, // TODO
|
||||||
|
noChainPad: true,
|
||||||
|
crypto: crypto,
|
||||||
|
owners: [ctx.store.proxy.edPublic],
|
||||||
|
lastKnownHash: m.lastKnownHash
|
||||||
|
};
|
||||||
|
cfg.onConnect = function (wc, sendMessage) {
|
||||||
|
// Send a message to our box?
|
||||||
|
box.sendMessage = function (msg) {
|
||||||
|
try {
|
||||||
|
msg = JSON.stringify(msg);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
sendMessage(msg, function (err, hash) {
|
||||||
|
if (m.viewed.indexOf(hash) === -1) {
|
||||||
|
m.viewed.push(hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
box.queue.forEach(function (msg) {
|
||||||
|
box.sendMessage(msg);
|
||||||
|
});
|
||||||
|
box.queue = [];
|
||||||
|
};
|
||||||
|
cfg.onMessage = function (msg, user, vKey, isCpi, hash) {
|
||||||
|
// TODO
|
||||||
|
try {
|
||||||
|
msg = JSON.parse(msg);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
if (isMessageNew(hash, m)) {
|
||||||
|
// Message should be displayed
|
||||||
|
var message = {
|
||||||
|
msg: msg,
|
||||||
|
hash: hash
|
||||||
|
};
|
||||||
|
box.history.push(message);
|
||||||
|
showMessage(ctx, type, message);
|
||||||
|
} else {
|
||||||
|
// Message has already been viewer by the user
|
||||||
|
if (history.length === 0) {
|
||||||
|
m.lastKnownHash = hash;
|
||||||
|
}
|
||||||
|
console.log(hash + ' is not new');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cfg.onReady = function () {
|
||||||
|
onReady();
|
||||||
|
};
|
||||||
|
CpNetflux.start(cfg);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Send a message to someone else
|
||||||
|
var sendTo = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Mark a message as read
|
||||||
|
var dismiss = function (ctx, data, cId, cb) {
|
||||||
|
var type = data.type;
|
||||||
|
var hash = data.hash;
|
||||||
|
var m = Util.find(ctx, ['store', 'proxy', 'mailboxes', type]);
|
||||||
|
if (!m) { return void cb({error: 'NOT_FOUND'}); }
|
||||||
|
var box = ctx.boxes[type];
|
||||||
|
if (!box) { return void cb({error: 'NOT_LOADED'}); }
|
||||||
|
|
||||||
|
// If the hash in in our history, get the index from the history:
|
||||||
|
// - if the index is 0, we can change our lastKnownHash
|
||||||
|
// - otherwise, just push to view
|
||||||
|
var idx;
|
||||||
|
if (box.history.some(function (el, i) {
|
||||||
|
if (hash === el.hash) {
|
||||||
|
idx = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
})) {
|
||||||
|
if (idx === 0) {
|
||||||
|
m.lastKnownHash = hash;
|
||||||
|
} else if (m.viewed.indexOf(hash) === -1) {
|
||||||
|
m.viewed.push(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the "viewed" array to see if we're able to bump lastKnownhash more
|
||||||
|
var sliceIdx;
|
||||||
|
box.history.some(function (el, i) {
|
||||||
|
var isViewed = m.viewed.indexOf(el.hash);
|
||||||
|
if (isViewed !== -1) {
|
||||||
|
sliceIdx = i + 1;
|
||||||
|
m.viewed.splice(isViewed, 1);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (sliceIdx) {
|
||||||
|
box.history = box.history.slice(sliceIdx);
|
||||||
|
}
|
||||||
|
|
||||||
|
Realtime.whenRealtimeSyncs(ctx.store.realtime, function () {
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var subscribe = function (ctx, data, cId, cb) {
|
||||||
|
// Get existing notifications
|
||||||
|
Object.keys(ctx.boxes).forEach(function (type) {
|
||||||
|
ctx.boxes[type].history.forEach(function (obj) {
|
||||||
|
showMessage(ctx, type, obj, cId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
// Subscribe to new notifications
|
||||||
|
var idx = ctx.clients.indexOf(cId);
|
||||||
|
if (idx === -1) {
|
||||||
|
ctx.clients.push(cId);
|
||||||
|
}
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeClient = function (ctx, cId) {
|
||||||
|
var idx = ctx.clients.indexOf(cId);
|
||||||
|
ctx.clients.splice(idx, 1);
|
||||||
|
};
|
||||||
|
|
||||||
Mailbox.init = function (store, waitFor, emit) {
|
Mailbox.init = function (store, waitFor, emit) {
|
||||||
var mailbox = {};
|
var mailbox = {};
|
||||||
var ctx = {
|
var ctx = {
|
||||||
store: store,
|
store: store,
|
||||||
emit: emit,
|
emit: emit,
|
||||||
|
clients: [],
|
||||||
|
boxes: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
var mailboxes = store.proxy.mailboxes || {};
|
||||||
|
Object.keys(mailboxes).forEach(function (key) {
|
||||||
|
if (TYPES.indexOf(key) === -1) { return; }
|
||||||
|
var m = mailboxes[key];
|
||||||
|
|
||||||
|
if (BLOCKING_TYPES.indexOf(key) === -1) {
|
||||||
|
openChannel(ctx, key, m, function () {
|
||||||
|
console.log(key + ' mailbox is ready');
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
openChannel(ctx, key, m, waitFor(function () {
|
||||||
|
console.log(key + ' mailbox is ready');
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// XXX test function used to populate a mailbox, should be removed in prod
|
||||||
|
mailbox.post = function (box, type, content) {
|
||||||
|
var b = ctx.boxes[box];
|
||||||
|
if (!b) { return; }
|
||||||
|
b.sendMessage({
|
||||||
|
type: type,
|
||||||
|
content: content,
|
||||||
|
sender: store.proxy.curvePublic
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
mailbox.removeClient = function (clientId) {
|
mailbox.removeClient = function (clientId) {
|
||||||
// TODO
|
removeClient(ctx, clientId);
|
||||||
//removeClient(ctx, clientId);
|
|
||||||
};
|
|
||||||
mailbox.leavePad = function (padChan) {
|
|
||||||
// TODO
|
|
||||||
//leaveChannel(ctx, padChan);
|
|
||||||
};
|
};
|
||||||
mailbox.execCommand = function (clientId, obj, cb) {
|
mailbox.execCommand = function (clientId, obj, cb) {
|
||||||
var cmd = obj.cmd;
|
var cmd = obj.cmd;
|
||||||
var data = obj.data;
|
var data = obj.data;
|
||||||
|
if (cmd === 'SUBSCRIBE') {
|
||||||
|
return void subscribe(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
|
if (cmd === 'DISMISS') {
|
||||||
|
return void dismiss(ctx, data, clientId, cb);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return mailbox;
|
return mailbox;
|
||||||
|
|||||||
127
www/common/sframe-common-mailbox.js
Normal file
127
www/common/sframe-common-mailbox.js
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
define([
|
||||||
|
'jquery',
|
||||||
|
'/common/common-util.js',
|
||||||
|
'/common/common-interface.js',
|
||||||
|
'/common/common-ui-elements.js',
|
||||||
|
'/customize/messages.js'
|
||||||
|
], function ($, Util, UI, UIElements, Messages) {
|
||||||
|
var Mailbox = {};
|
||||||
|
|
||||||
|
Mailbox.create = function (Common) {
|
||||||
|
var mailbox = {};
|
||||||
|
var metadataMgr = Common.getMetadataMgr();
|
||||||
|
var sframeChan = Common.getSframeChannel();
|
||||||
|
|
||||||
|
var execCommand = function (cmd, data, cb) {
|
||||||
|
sframeChan.query('Q_MAILBOX_COMMAND', {
|
||||||
|
cmd: cmd,
|
||||||
|
data: data
|
||||||
|
}, function (err, obj) {
|
||||||
|
if (err) { return void cb({error: err}); }
|
||||||
|
cb(obj);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var history = {};
|
||||||
|
|
||||||
|
var removeFromHistory = function (type, hash) {
|
||||||
|
history[type] = history[type].filter(function (obj) {
|
||||||
|
return obj.hash !== hash;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mailbox.dismiss = function (type, hash, cb) {
|
||||||
|
execCommand('DISMISS', {
|
||||||
|
hash: hash,
|
||||||
|
type: type
|
||||||
|
}, function (obj) {
|
||||||
|
if (obj && obj.error) { return void cb(obj.error); }
|
||||||
|
removeFromHistory(type, hash);
|
||||||
|
cb();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
mailbox.sendTo = function (user, type, content) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// UI
|
||||||
|
|
||||||
|
var onViewedHandlers = [];
|
||||||
|
var onMessageHandlers = [];
|
||||||
|
|
||||||
|
// Call the onMessage handlers
|
||||||
|
var pushMessage = function (data) {
|
||||||
|
onMessageHandlers.forEach(function (f) {
|
||||||
|
try {
|
||||||
|
f(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get all existing notifications + the new ones when they come
|
||||||
|
mailbox.subscribe = function (cfg) {
|
||||||
|
if (typeof(cfg.onViewed) === "function") {
|
||||||
|
onViewedHandlers.push(cfg.onViewed);
|
||||||
|
}
|
||||||
|
if (typeof(cfg.onMessage) === "function") {
|
||||||
|
onMessageHandlers.push(cfg.onMessage);
|
||||||
|
}
|
||||||
|
Object.keys(history).forEach(function (type) {
|
||||||
|
history[type].forEach(function (data) {
|
||||||
|
pushMessage({
|
||||||
|
type: type,
|
||||||
|
content: data
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var onViewed = function (data) {
|
||||||
|
// data = { type: 'type', hash: 'hash' }
|
||||||
|
onViewedHandlers.forEach(function (f) {
|
||||||
|
try {
|
||||||
|
f(data);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
removeFromHistory(data.type, data.hash);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onMessage = function (data) {
|
||||||
|
// data = { type: 'type', content: {msg: 'msg', hash: 'hash'} }
|
||||||
|
console.log(data.content);
|
||||||
|
pushMessage(data);
|
||||||
|
if (!history[data.type]) { history[data.type] = []; }
|
||||||
|
history[data.type].push(data.content);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// CHANNEL WITH WORKER
|
||||||
|
|
||||||
|
sframeChan.on('EV_MAILBOX_EVENT', function (obj) {
|
||||||
|
// obj = { ev: 'type', data: obj }
|
||||||
|
var ev = obj.ev;
|
||||||
|
var data = obj.data;
|
||||||
|
if (ev === 'MESSAGE') {
|
||||||
|
return void onMessage(data);
|
||||||
|
}
|
||||||
|
if (ev === 'VIEWED') {
|
||||||
|
return void onViewed(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
execCommand('SUBSCRIBE', null, function () {
|
||||||
|
console.log('subscribed');
|
||||||
|
});
|
||||||
|
|
||||||
|
return mailbox;
|
||||||
|
};
|
||||||
|
|
||||||
|
return Mailbox;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -877,6 +877,13 @@ define([
|
|||||||
Cryptpad.cursor.execCommand(data, cb);
|
Cryptpad.cursor.execCommand(data, cb);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cryptpad.mailbox.onEvent.reg(function (data) {
|
||||||
|
sframeChan.event('EV_MAILBOX_EVENT', data);
|
||||||
|
});
|
||||||
|
sframeChan.on('Q_MAILBOX_COMMAND', function (data, cb) {
|
||||||
|
Cryptpad.mailbox.execCommand(data, cb);
|
||||||
|
});
|
||||||
|
|
||||||
Cryptpad.onTimeoutEvent.reg(function () {
|
Cryptpad.onTimeoutEvent.reg(function () {
|
||||||
sframeChan.event('EV_WORKER_TIMEOUT');
|
sframeChan.event('EV_WORKER_TIMEOUT');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -10,6 +10,7 @@ define([
|
|||||||
'/common/sframe-common-file.js',
|
'/common/sframe-common-file.js',
|
||||||
'/common/sframe-common-codemirror.js',
|
'/common/sframe-common-codemirror.js',
|
||||||
'/common/sframe-common-cursor.js',
|
'/common/sframe-common-cursor.js',
|
||||||
|
'/common/sframe-common-mailbox.js',
|
||||||
'/common/metadata-manager.js',
|
'/common/metadata-manager.js',
|
||||||
|
|
||||||
'/customize/application_config.js',
|
'/customize/application_config.js',
|
||||||
@ -33,6 +34,7 @@ define([
|
|||||||
File,
|
File,
|
||||||
CodeMirror,
|
CodeMirror,
|
||||||
Cursor,
|
Cursor,
|
||||||
|
Mailbox,
|
||||||
MetadataMgr,
|
MetadataMgr,
|
||||||
AppConfig,
|
AppConfig,
|
||||||
CommonRealtime,
|
CommonRealtime,
|
||||||
@ -630,6 +632,8 @@ define([
|
|||||||
|
|
||||||
ctx.sframeChan.ready();
|
ctx.sframeChan.ready();
|
||||||
cb(funcs);
|
cb(funcs);
|
||||||
|
|
||||||
|
Mailbox.create(funcs);
|
||||||
});
|
});
|
||||||
} };
|
} };
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user