diff options
Diffstat (limited to 'lib/realtime.js')
-rw-r--r-- | lib/realtime.js | 167 |
1 files changed, 66 insertions, 101 deletions
diff --git a/lib/realtime.js b/lib/realtime.js index 0c68a256..ea3735a6 100644 --- a/lib/realtime.js +++ b/lib/realtime.js @@ -13,6 +13,7 @@ var moment = require('moment'); //core var config = require("./config.js"); var logger = require("./logger.js"); +var history = require("./history.js"); var models = require("./models"); //ot @@ -63,6 +64,7 @@ function secure(socket, next) { function emitCheck(note) { var out = { + title: note.title, updatetime: note.updatetime, lastchangeuser: note.lastchangeuser, lastchangeuserprofile: note.lastchangeuserprofile, @@ -148,7 +150,7 @@ function updateNote(note, callback) { function finishUpdateNote(note, _note, callback) { if (!note || !note.server) return callback(null, null); var body = note.server.document; - var title = models.Note.parseNoteTitle(body); + var title = note.title = models.Note.parseNoteTitle(body); title = LZString.compressToBase64(title); body = LZString.compressToBase64(body); var values = { @@ -312,6 +314,7 @@ function emitRefresh(socket) { if (!noteId || !notes[noteId]) return; var note = notes[noteId]; var out = { + title: note.title, docmaxlength: config.documentmaxlength, owner: note.owner, ownerprofile: note.ownerprofile, @@ -327,6 +330,15 @@ function emitRefresh(socket) { socket.emit('refresh', out); } +function isDuplicatedInSocketQueue(queue, socket) { + for (var i = 0; i < queue.length; i++) { + if (queue[i] && queue[i].id == socket.id) { + return true; + } + } + return false; +} + function clearSocketQueue(queue, socket) { for (var i = 0; i < queue.length; i++) { if (!queue[i] || queue[i].id == socket.id) { @@ -381,6 +393,12 @@ function finishConnection(socket, note, user) { note.server.setName(socket, user.name); note.server.setColor(socket, user.color); + // update user note history + setTimeout(function () { + var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id); + history.updateHistory(user.userid, noteId, note.server.document); + }, 0); + emitOnlineUsers(socket); emitRefresh(socket); @@ -459,6 +477,8 @@ function startConnection(socket) { notes[noteId] = { id: noteId, + alias: note.alias, + title: LZString.decompressFromBase64(note.title), owner: owner, ownerprofile: ownerprofile, permission: note.permission, @@ -509,17 +529,23 @@ function disconnect(socket) { var noteId = socket.noteId; var note = notes[noteId]; if (note) { + // delete user in users delete note.users[socket.id]; + // remove sockets in the note socks do { var index = note.socks.indexOf(socket); if (index != -1) { note.socks.splice(index, 1); } } while (index != -1); + // remove note in notes if no user inside if (Object.keys(note.users).length <= 0) { if (note.server.isDirty) { updateNote(note, function (err, _note) { if (err) return logger.error('disconnect note failed: ' + err); + // clear server before delete to avoid memory leaks + note.server.document = ""; + note.server.operations = []; delete note.server; delete notes[noteId]; if (config.debug) { @@ -640,108 +666,15 @@ function operationCallback(socket, operation) { return logger.error('operation callback failed: ' + err); }); } + // update user note history + setTimeout(function() { + var noteId = note.alias ? note.alias : LZString.compressToBase64(note.id); + history.updateHistory(userId, noteId, note.server.document); + }, 0); + } // save authorship - var index = 0; - var authorships = note.authorship; - var timestamp = Date.now(); - for (var i = 0; i < operation.length; i++) { - var op = operation[i]; - if (ot.TextOperation.isRetain(op)) { - index += op; - } else if (ot.TextOperation.isInsert(op)) { - var opStart = index; - var opEnd = index + op.length; - var inserted = false; - // authorship format: [userId, startPos, endPos, createdAt, updatedAt] - if (authorships.length <= 0) authorships.push([userId, opStart, opEnd, timestamp, timestamp]); - else { - for (var j = 0; j < authorships.length; j++) { - var authorship = authorships[j]; - if (!inserted) { - var nextAuthorship = authorships[j + 1] || -1; - if (nextAuthorship != -1 && nextAuthorship[1] >= opEnd || j >= authorships.length - 1) { - if (authorship[1] < opStart && authorship[2] > opStart) { - // divide - var postLength = authorship[2] - opStart; - authorship[2] = opStart; - authorship[4] = timestamp; - authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp]); - authorships.splice(j + 2, 0, [authorship[0], opEnd, opEnd + postLength, authorship[3], timestamp]); - j += 2; - inserted = true; - } else if (authorship[1] >= opStart) { - authorships.splice(j, 0, [userId, opStart, opEnd, timestamp, timestamp]); - j += 1; - inserted = true; - } else if (authorship[2] <= opStart) { - authorships.splice(j + 1, 0, [userId, opStart, opEnd, timestamp, timestamp]); - j += 1; - inserted = true; - } - } - } - if (authorship[1] >= opStart) { - authorship[1] += op.length; - authorship[2] += op.length; - } - } - } - index += op.length; - } else if (ot.TextOperation.isDelete(op)) { - var opStart = index; - var opEnd = index - op; - if (operation.length == 1) { - authorships = []; - } else if (authorships.length > 0) { - for (var j = 0; j < authorships.length; j++) { - var authorship = authorships[j]; - if (authorship[1] >= opStart && authorship[1] <= opEnd && authorship[2] >= opStart && authorship[2] <= opEnd) { - authorships.splice(j, 1); - j -= 1; - } else if (authorship[1] < opStart && authorship[1] < opEnd && authorship[2] > opStart && authorship[2] > opEnd) { - authorship[2] += op; - authorship[4] = timestamp; - } else if (authorship[2] >= opStart && authorship[2] <= opEnd) { - authorship[2] = opStart; - authorship[4] = timestamp; - } else if (authorship[1] >= opStart && authorship[1] <= opEnd) { - authorship[1] = opEnd; - authorship[4] = timestamp; - } - if (authorship[1] >= opEnd) { - authorship[1] += op; - authorship[2] += op; - } - } - } - index += op; - } - } - // merge - for (var j = 0; j < authorships.length; j++) { - var authorship = authorships[j]; - for (var k = j + 1; k < authorships.length; k++) { - var nextAuthorship = authorships[k]; - if (nextAuthorship && authorship[0] === nextAuthorship[0] && authorship[2] === nextAuthorship[1]) { - var minTimestamp = Math.min(authorship[3], nextAuthorship[3]); - var maxTimestamp = Math.max(authorship[3], nextAuthorship[3]); - authorships.splice(j, 1, [authorship[0], authorship[1], nextAuthorship[2], minTimestamp, maxTimestamp]); - authorships.splice(k, 1); - j -= 1; - break; - } - } - } - // clear - for (var j = 0; j < authorships.length; j++) { - var authorship = authorships[j]; - if (!authorship[0]) { - authorships.splice(j, 1); - j -= 1; - } - } - note.authorship = authorships; + note.authorship = models.Note.updateAuthorshipByOperation(operation, userId, note.authorship); } function connection(socket) { @@ -753,6 +686,8 @@ function connection(socket) { if (!noteId) { return failConnection(404, 'note id not found', socket); } + + if (isDuplicatedInSocketQueue(socket, connectionSocketQueue)) return; // store noteId in this socket session socket.noteId = noteId; @@ -864,6 +799,35 @@ function connection(socket) { } }); + // delete a note + socket.on('delete', function () { + //need login to do more actions + if (socket.request.user && socket.request.user.logged_in) { + var noteId = socket.noteId; + if (!noteId || !notes[noteId]) return; + var note = notes[noteId]; + //Only owner can delete note + if (note.owner && note.owner == socket.request.user.id) { + models.Note.destroy({ + where: { + id: noteId + } + }).then(function (count) { + if (!count) return; + for (var i = 0, l = note.socks.length; i < l; i++) { + var sock = note.socks[i]; + if (typeof sock !== 'undefined' && sock) { + sock.emit('delete'); + return sock.disconnect(true); + } + } + }).catch(function (err) { + return logger.error('delete note failed: ' + err); + }); + } + } + }); + //reveiced when user logout or changed socket.on('user changed', function () { logger.info('user changed'); @@ -929,6 +893,7 @@ function connection(socket) { //when a new client disconnect socket.on('disconnect', function () { + if (isDuplicatedInSocketQueue(socket, disconnectSocketQueue)) return; disconnectSocketQueue.push(socket); disconnect(socket); }); |