Add a pad room when the messenger is active in a pad

pull/1/head
yflory 6 years ago
parent 9e27f111cb
commit d4dd58e7df

@ -67,7 +67,7 @@ define([
update: [],
friend: [],
unfriend: [],
ready: []
event: []
},
range_requests: {},
};
@ -189,6 +189,8 @@ define([
var friend = getFriendFromChannel(id);
if (!friend) { return void cb('NO_SUCH_FRIEND'); }
friend.lastKnownHash = hash;
} else if (channel.isPadChat) {
// Nothing to do
} else {
// TODO room
return void cb('NOT_IMPLEMENTED');
@ -200,6 +202,7 @@ define([
var checkFriendData = function (curve, data) {
if (curve === proxy.curvePublic) { return; }
var friend = getFriend(proxy, curve);
if (!friend) { return; }
var types = [];
Object.keys(data).forEach(function (k) {
if (friend[k] !== data[k]) {
@ -215,17 +218,21 @@ define([
// Id message allows us to map a netfluxId with a public curve key
var onIdMessage = function (msg, sender) {
var channel;
var isId = Object.keys(channels).some(function (chanId) {
if (channels[chanId].userList.indexOf(sender) !== -1) {
channel = channels[chanId];
return true;
}
});
var channel, parsed0;
if (!isId) { return; }
try {
parsed0 = JSON.parse(msg);
channel = channels[parsed0.channel];
if (!channel) { return; }
if (channel.userList.indexOf(sender) === -1) { return; }
} catch (e) {
console.log(msg);
console.error(e);
// Not an ID message
return;
}
var decryptedMsg = channel.encryptor.decrypt(msg);
var decryptedMsg = channel.encryptor.decrypt(parsed0.msg);
if (decryptedMsg === null) {
return void console.error("Failed to decrypt message");
@ -261,7 +268,11 @@ define([
var rMsg = [Types.mapIdAck, myData, channel.wc.myID];
var rMsgStr = JSON.stringify(rMsg);
var cryptMsg = channel.encryptor.encrypt(rMsgStr);
network.sendto(sender, cryptMsg);
var data = {
channel: channel.id,
msg: cryptMsg
};
network.sendto(sender, JSON.stringify(data));
};
var orderMessages = function (channel, new_messages /*, sig */) {
@ -295,15 +306,19 @@ define([
author: parsedMsg[1],
time: parsedMsg[2],
text: parsedMsg[3],
channel: channel.id
channel: channel.id,
name: parsedMsg[4] // Display name for multi-user rooms
// this makes debugging a whole lot easier
//curve: getCurveForChannel(channel.id),
};
channel.messages.push(res);
eachHandler('message', function (f) {
f(res);
});
if (!joining[channel.id]) {
// Channel is ready
eachHandler('message', function (f) {
f(res);
});
}
return true;
}
@ -414,7 +429,8 @@ define([
author: O.d[1],
time: O.d[2],
text: O.d[3],
channel: req.chanId
channel: req.chanId,
name: O.d[4]
};
});
@ -516,7 +532,7 @@ define([
var getChannelMessagesSince = function (chan, data, keys) {
console.log('Fetching [%s] messages since [%s]', chan.id, data.lastKnownHash || '');
var cfg = {
validateKey: keys.validateKey,
validateKey: keys ? keys.validateKey : undefined,
owners: [proxy.edPublic, data.edPublic],
lastKnownHash: data.lastKnownHash
};
@ -529,11 +545,12 @@ define([
var openChannel = function (data) {
var keys = data.keys;
var encryptor = Curve.createEncryptor(keys);
var encryptor = data.encryptor || Curve.createEncryptor(keys);
network.join(data.channel).then(function (chan) {
var channel = channels[data.channel] = {
id: data.channel,
isFriendChat: data.isFriendChat,
isPadChat: data.isPadChat,
sending: false,
encryptor: encryptor,
messages: [],
@ -556,7 +573,11 @@ define([
var msg = [Types.mapId, myData, chan.myID];
var msgStr = JSON.stringify(msg);
var cryptMsg = channel.encryptor.encrypt(msgStr);
network.sendto(peer, cryptMsg);
var data = {
channel: channel.id,
msg: cryptMsg
};
network.sendto(peer, JSON.stringify(data));
};
chan.members.forEach(function (peer) {
if (peer === Msg.hk) { return; }
@ -758,15 +779,16 @@ define([
// TODO send event chat ready
// Remove spinner in chatbox
ready = true;
eachHandler('ready', function (f) {
f();
eachHandler('event', function (f) {
f('READY');
});
});
};
init();
var getRooms = function (curvePublic, cb) {
if (curvePublic) {
var getRooms = function (data, cb) {
if (data && data.curvePublic) {
var curvePublic = data.curvePublic;
// We need to get data about a new friend's room
var friend = getFriend(proxy, curvePublic);
if (!friend) { return void cb({error: 'NO_SUCH_FRIEND'}); }
@ -777,7 +799,18 @@ define([
isFriendChat: true,
name: friend.displayName,
lastKnownHash: friend.lastKnownHash,
curvePublic: friend.curvePublic
curvePublic: friend.curvePublic,
messages: channel.messages
}]);
}
if (data && data.padChat) {
var pCChannel = getChannel(data.padChat);
if (!pCChannel) { return void cb({error: 'NO_SUCH_CHANNEL'}); }
return void cb([{
id: pCChannel.id,
isPadChat: true,
messages: pCChannel.messages
}]);
}
@ -798,7 +831,8 @@ define([
isFriendChat: r.isFriendChat,
name: name,
lastKnownHash: lastKnownHash,
curvePublic: curvePublic
curvePublic: curvePublic,
messages: r.messages
};
}).filter(function (x) { return x; });
cb(rooms);
@ -814,7 +848,30 @@ define([
} else {
// TODO room userlist in rooms...
// (this is the static userlist, not the netflux one)
}
cb([]);
}
};
var openPadChat = function (data, cb) {
var channel = data.channel;
var keys = data.secret && data.secret.keys;
var cryptKey = keys.viewKeyStr ? Crypto.b64AddSlashes(keys.viewKeyStr) : data.secret.key;
var encryptor = Crypto.createEncryptor(cryptKey);
var chanData = {
encryptor: encryptor,
channel: data.channel,
isPadChat: true,
//lastKnownHash: friend.lastKnownHash,
//owners: [proxy.edPublic, friend.edPublic],
//isFriendChat: true
};
openChannel(chanData);
joining[channel] = function () {
eachHandler('event', function (f) {
f('PADCHAT_READY', channel);
});
};
cb();
};
messenger.execCommand = function (obj, cb) {
@ -829,6 +886,9 @@ define([
if (cmd === 'GET_USERLIST') {
return void getUserList(data, cb);
}
if (cmd === 'OPEN_PAD_CHAT') {
return void openPadChat(data, cb);
}
};
Object.freeze(messenger);

@ -1372,10 +1372,10 @@ define([
removedByMe: removedByMe
});
});
messenger.on('ready', function () {
console.log('here');
messenger.on('event', function (ev, data) {
sendMessengerEvent('CHAT_EVENT', {
ev: 'READY'
ev: ev,
data: data
});
});
};

@ -322,6 +322,8 @@ define([
if (!readOnly) { onLocal(); }
evOnReady.fire(newPad);
common.openPadChat(onLocal);
UI.removeLoadingScreen(emitResize);
var privateDat = cpNfInner.metadataMgr.getPrivateData();

@ -776,11 +776,19 @@ define([
Cryptpad.messenger.setChannelHead(opt, cb);
});
sframeChan.on('Q_CHAT_OPENPADCHAT', function (data, cb) {
Cryptpad.messenger.execCommand({
cmd: 'OPEN_PAD_CHAT',
data: {
channel: data,
secret: secret
}
}, cb);
});
sframeChan.on('Q_CHAT_COMMAND', function (data, cb) {
Cryptpad.messenger.execCommand(data, cb);
});
Cryptpad.messenger.onEvent.reg(function (data) {
console.log(data);
sframeChan.event('EV_CHAT_EVENT', data);
});

@ -161,6 +161,19 @@ define([
});
};
// Chat
funcs.openPadChat = function (saveChanges) {
var md = JSON.parse(JSON.stringify(ctx.metadataMgr.getMetadata()));
var channel = md.chat || Hash.createChannelId();
if (!md.chat) {
md.chat = channel;
ctx.metadataMgr.updateMetadata(md);
setTimeout(saveChanges);
}
ctx.sframeChan.query('Q_CHAT_OPENPADCHAT', channel, function (err, obj) {
if (err || (obj && obj.error)) { console.error(err || (obj && obj.error)); }
});
};
// CodeMirror
funcs.initCodeMirrorApp = callWithCommon(CodeMirror.create);

@ -174,6 +174,7 @@ define({
// Chat
'EV_CHAT_EVENT': true,
'Q_CHAT_COMMAND': true,
'Q_CHAT_OPENPADCHAT': true,
// Put one or more entries to the localStore which will go in localStorage.
'EV_LOCALSTORE_PUT': true,

@ -24,13 +24,19 @@ define([
var initChannel = function (state, info) {
console.log('initializing channel for [%s]', info.id);
var h, t;
if (Array.isArray(info.messages) && info.messages.length) {
h = info.messages[info.messages.length -1].sig;
t = info.messages[0].sig;
}
state.channels[info.id] = {
messages: [],
messages: info.messages || [],
name: info.name,
isFriendChat: info.isFriendChat,
isPadChat: info.isPadChat,
curvePublic: info.curvePublic,
HEAD: info.lastKnownHash,
TAIL: null,
HEAD: h || info.lastKnownHash,
TAIL: t || null,
};
};
@ -114,7 +120,7 @@ define([
var markup = {};
markup.message = function (msg) {
var curvePublic = msg.author;
var name = contactsData[msg.author].displayName;
var name = msg.name || contactsData[msg.author].displayName;
return h('div.cp-app-contacts-message', {
title: msg.time? new Date(msg.time).toLocaleString(): '?',
'data-user': curvePublic,
@ -172,9 +178,13 @@ define([
return;
}
history.forEach(function (msg) {
history.forEach(function (msg, i) {
if (channel.exhausted) { return; }
if (msg.sig) {
if (i === 0 && history.length > 1 && msg.sig === channel.TAIL) {
// First message is usually the lastKnownHash, ignore it
return;
}
if (msg.sig === channel.TAIL) {
console.error('No more messages to fetch');
channel.exhausted = true;
@ -227,7 +237,7 @@ define([
var header = h('div.cp-app-contacts-header', [
avatar,
moreHistory,
removeHistory,
data.isFriendChat ? removeHistory: undefined,
]);
var messages = h('div.cp-app-contacts-messages');
var input = h('textarea', {
@ -242,18 +252,16 @@ define([
]);
var $avatar = $(avatar);
if (data.isFriendChat) {
var friend = contactsData[curvePublic];
if (friend.avatar && avatars[friend.avatar]) {
$avatar.append(avatars[friend.avatar]).append(rightCol);
} else {
common.displayAvatar($avatar, friend.avatar, friend.displayName, function ($img) {
if (friend.avatar && $img) {
avatars[friend.avatar] = $img[0].outerHTML;
}
$(rightCol).insertAfter($avatar);
});
}
var friend = contactsData[curvePublic] || {};
if (friend.avatar && avatars[friend.avatar]) {
$avatar.append(avatars[friend.avatar]).append(rightCol);
} else {
common.displayAvatar($avatar, friend.avatar, displayName, function ($img) {
if (friend.avatar && $img) {
avatars[friend.avatar] = $img[0].outerHTML;
}
$(rightCol).insertAfter($avatar);
});
}
var sending = false;
@ -368,7 +376,13 @@ define([
var $more = $chat.find('.cp-app-contacts-more-history');
$more.click();
}
return void $chat.show();
$chat.show();
if (channel.isPadChat) {
// Always scroll bottom for now in pad chat (no last known hash)
var $messagebox = $chat.find('.cp-app-contacts-messages');
$messagebox.scrollTop($messagebox.outerHeight());
}
return;
} else {
console.error("Chat is missing... Please reload the page and try again.");
}
@ -389,10 +403,14 @@ define([
var remove = h('span.cp-app-contacts-remove.fa.fa-user-times', {
title: Messages.contacts_remove
});
var leaveRoom = h('span.cp-app-contacts-remove.fa.fa-sign-out', {
title: 'Leave this room' // XXX
});
var status = h('span.cp-app-contacts-status');
var rightCol = h('span.cp-app-contacts-right-col', [
h('span.cp-app-contacts-name', [room.name]),
remove,
room.isFriendChat ? remove : leaveRoom,
]);
var friendData = room.isFriendChat ? userlist[0] : {};
@ -406,23 +424,20 @@ define([
$(remove).click(function (e) {
e.stopPropagation();
var channel = state.channels[id];
if (channel.isFriendChat) {
var curvePublic = channel.curvePublic;
var friend = contactsData[curvePublic] || friendData;
UI.confirm(Messages._getKey('contacts_confirmRemove', [
Util.fixHTML(friend.name)
]), function (yes) {
if (!yes) { return; }
removeFriend(curvePublic, function (e) {
if (e) { return void console.error(e); }
});
// TODO remove friend from userlist ui
// FIXME seems to trigger EJOINED from netflux-websocket (from server);
// (tried to join a channel in which you were already present)
}, undefined, true);
} else {
// TODO room remove room
}
if (!channel.isFriendChat) { return; }
var curvePublic = channel.curvePublic;
var friend = contactsData[curvePublic] || friendData;
UI.confirm(Messages._getKey('contacts_confirmRemove', [
Util.fixHTML(friend.name)
]), function (yes) {
if (!yes) { return; }
removeFriend(curvePublic, function (e) {
if (e) { return void console.error(e); }
});
// TODO remove friend from userlist ui
// FIXME seems to trigger EJOINED from netflux-websocket (from server);
// (tried to join a channel in which you were already present)
}, undefined, true);
});
if (friendData.avatar && avatars[friendData.avatar]) {
@ -457,6 +472,7 @@ define([
var channel = state.channels[chanId];
if (!channel) {
console.log(message);
console.error('expected channel [%s] to be open', chanId);
return;
}
@ -568,31 +584,40 @@ define([
execCommand('GET_USERLIST', {id: id}, function (e, list) {
if (e || list.error) { return void console.error(e || list.error); }
if (!Array.isArray(list) || !list.length) {
if (!room.isPadChat && (!Array.isArray(list) || !list.length)) {
return void console.error("Empty room!");
}
debug('userlist: ' + JSON.stringify(list));
// This is a friend, the userlist is only one user.
var friend = list[0];
contactsData[friend.curvePublic] = friend;
var friend = {};
if (room.isFriendChat) {
// This is a friend, the userlist is only one user.
friend = list[0];
contactsData[friend.curvePublic] = friend;
}
var chatbox = markup.chatbox(id, room, friend.curvePublic);
$(chatbox).hide();
$messages.append(chatbox);
var $messagebox = $(chatbox).find('.cp-app-contacts-messages');
room.messages.forEach(function (msg) {
var el_message = markup.message(msg);
$messagebox.append(el_message);
});
normalizeLabels($messagebox);
var roomEl = markup.room(id, room, list);
$userlist.append(roomEl);
updateStatus(id);
});
// TODO room group chat
};
messenger.on('friend', function (curvePublic) {
debug('new friend: ', curvePublic);
execCommand('GET_ROOMS', curvePublic, function (err, rooms) {
execCommand('GET_ROOMS', {curvePublic: curvePublic}, function (err, rooms) {
if (err) { return void console.error(err); }
debug('rooms: ' + JSON.stringify(rooms));
rooms.forEach(initializeRoom);
@ -636,16 +661,34 @@ define([
$container.removeClass('cp-app-contacts-initializing');
};
var onPadChatReady = function (data) {
execCommand('GET_ROOMS', {padChat: data}, function (err, rooms) {
if (err) { return void console.error(err); }
if (!Array.isArray(rooms) || rooms.length !== 1) {
return void console.error('Invalid pad chat');
}
var room = rooms[0];
room.name = 'XXX Pad chat';
rooms.forEach(initializeRoom);
});
$container.removeClass('cp-app-contacts-initializing');
};
// Initialize chat when outer is ready (all channels loaded)
// TODO: try again in outer if fail to load a channel
execCommand('IS_READY', null, function (err, yes) {
if (yes) { onMessengerReady(); }
});
sframeChan.on('EV_CHAT_EVENT', function (data) {
if (data.ev === 'READY') {
sframeChan.on('EV_CHAT_EVENT', function (obj) {
if (obj.ev === 'READY') {
onMessengerReady();
return;
}
if (obj.ev === 'PADCHAT_READY') {
onPadChatReady(obj.data);
return;
}
});
};

Loading…
Cancel
Save