mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-13 22:54:42 -04:00
Add support of saving authors and authorship
This commit is contained in:
parent
44fd0a617b
commit
2f117a22cd
6 changed files with 240 additions and 3 deletions
156
lib/realtime.js
156
lib/realtime.js
|
@ -151,6 +151,7 @@ function finishUpdateNote(note, _note, callback) {
|
|||
var values = {
|
||||
title: title,
|
||||
content: body,
|
||||
authorship: LZString.compressToBase64(JSON.stringify(note.authorship)),
|
||||
lastchangeuserId: note.lastchangeuser,
|
||||
lastchangeAt: Date.now()
|
||||
};
|
||||
|
@ -404,6 +405,13 @@ function startConnection(socket) {
|
|||
}, {
|
||||
model: models.User,
|
||||
as: "lastchangeuser"
|
||||
}, {
|
||||
model: models.Author,
|
||||
as: "authors",
|
||||
include: [{
|
||||
model: models.User,
|
||||
as: "user"
|
||||
}]
|
||||
}];
|
||||
|
||||
models.Note.findOne({
|
||||
|
@ -424,7 +432,19 @@ function startConnection(socket) {
|
|||
var body = LZString.decompressFromBase64(note.content);
|
||||
var createtime = note.createdAt;
|
||||
var updatetime = note.lastchangeAt;
|
||||
var server = new ot.EditorSocketIOServer(body, [], noteId, ifMayEdit);
|
||||
var server = new ot.EditorSocketIOServer(body, [], noteId, ifMayEdit, operationCallback);
|
||||
|
||||
var authors = {};
|
||||
for (var i = 0; i < note.authors.length; i++) {
|
||||
var author = note.authors[i];
|
||||
var profile = models.User.parseProfile(author.user.profile);
|
||||
authors[author.userId] = {
|
||||
userid: author.userId,
|
||||
color: author.color,
|
||||
photo: profile.photo,
|
||||
name: profile.name
|
||||
};
|
||||
}
|
||||
|
||||
notes[noteId] = {
|
||||
id: noteId,
|
||||
|
@ -437,7 +457,9 @@ function startConnection(socket) {
|
|||
users: {},
|
||||
createtime: moment(createtime).valueOf(),
|
||||
updatetime: moment(updatetime).valueOf(),
|
||||
server: server
|
||||
server: server,
|
||||
authors: authors,
|
||||
authorship: note.authorship ? JSON.parse(LZString.decompressFromBase64(note.authorship)) : []
|
||||
};
|
||||
|
||||
return finishConnection(socket, notes[noteId], users[socket.id]);
|
||||
|
@ -581,6 +603,136 @@ function ifMayEdit(socket, callback) {
|
|||
return callback(mayEdit);
|
||||
}
|
||||
|
||||
function operationCallback(socket, operation) {
|
||||
var noteId = socket.noteId;
|
||||
if (!noteId || !notes[noteId]) return;
|
||||
var note = notes[noteId];
|
||||
var userId = null;
|
||||
// save authors
|
||||
if (socket.request.user && socket.request.user.logged_in) {
|
||||
var socketId = socket.id;
|
||||
var user = users[socketId];
|
||||
userId = socket.request.user.id;
|
||||
if (!note.authors[userId]) {
|
||||
models.Author.create({
|
||||
noteId: noteId,
|
||||
userId: userId,
|
||||
color: users[socketId].color
|
||||
}).then(function (author) {
|
||||
note.authors[author.userId] = {
|
||||
userid: author.userId,
|
||||
color: author.color,
|
||||
photo: user.photo,
|
||||
name: user.name
|
||||
};
|
||||
}).catch(function (err) {
|
||||
return logger.error('operation callback failed: ' + err);
|
||||
});
|
||||
}
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
||||
function connection(socket) {
|
||||
if (config.maintenance) return;
|
||||
parseNoteIdFromSocket(socket, function (err, noteId) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue