Add support of showing authorship in editor and adjust related styles
This commit is contained in:
parent
d5549c6a84
commit
a14e7953b5
4 changed files with 218 additions and 3 deletions
|
@ -65,7 +65,9 @@ function emitCheck(note) {
|
||||||
var out = {
|
var out = {
|
||||||
updatetime: note.updatetime,
|
updatetime: note.updatetime,
|
||||||
lastchangeuser: note.lastchangeuser,
|
lastchangeuser: note.lastchangeuser,
|
||||||
lastchangeuserprofile: note.lastchangeuserprofile
|
lastchangeuserprofile: note.lastchangeuserprofile,
|
||||||
|
authors: note.authors,
|
||||||
|
authorship: note.authorship
|
||||||
};
|
};
|
||||||
realtime.io.to(note.id).emit('check', out);
|
realtime.io.to(note.id).emit('check', out);
|
||||||
}
|
}
|
||||||
|
@ -314,6 +316,8 @@ function emitRefresh(socket) {
|
||||||
ownerprofile: note.ownerprofile,
|
ownerprofile: note.ownerprofile,
|
||||||
lastchangeuser: note.lastchangeuser,
|
lastchangeuser: note.lastchangeuser,
|
||||||
lastchangeuserprofile: note.lastchangeuserprofile,
|
lastchangeuserprofile: note.lastchangeuserprofile,
|
||||||
|
authors: note.authors,
|
||||||
|
authorship: note.authorship,
|
||||||
permission: note.permission,
|
permission: note.permission,
|
||||||
createtime: note.createtime,
|
createtime: note.createtime,
|
||||||
updatetime: note.updatetime
|
updatetime: note.updatetime
|
||||||
|
|
|
@ -49,6 +49,9 @@ body {
|
||||||
min-width: 1.5em;
|
min-width: 1.5em;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
.CodeMirror-gutter.authorship-gutters {
|
||||||
|
width: 8px;
|
||||||
|
}
|
||||||
.CodeMirror-matchingtag {
|
.CodeMirror-matchingtag {
|
||||||
background: rgba(255, 255, 255, .1);
|
background: rgba(255, 255, 255, .1);
|
||||||
line-height: 1em;
|
line-height: 1em;
|
||||||
|
|
|
@ -287,7 +287,7 @@ var editor = CodeMirror.fromTextArea(textit, {
|
||||||
},
|
},
|
||||||
autoCloseTags: true,
|
autoCloseTags: true,
|
||||||
foldGutter: true,
|
foldGutter: true,
|
||||||
gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
|
gutters: ["CodeMirror-linenumbers", "authorship-gutters", "CodeMirror-foldgutter"],
|
||||||
extraKeys: defaultExtraKeys,
|
extraKeys: defaultExtraKeys,
|
||||||
flattenSpans: true,
|
flattenSpans: true,
|
||||||
addModeClass: true,
|
addModeClass: true,
|
||||||
|
@ -2127,6 +2127,9 @@ socket.on('version', function (data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
var authors = [];
|
||||||
|
var authorship = [];
|
||||||
|
var authorshipMarks = {};
|
||||||
function updateLastInfo(data) {
|
function updateLastInfo(data) {
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
if (data.hasOwnProperty('createtime') && createtime !== data.createtime) {
|
if (data.hasOwnProperty('createtime') && createtime !== data.createtime) {
|
||||||
|
@ -2142,7 +2145,212 @@ function updateLastInfo(data) {
|
||||||
lastchangeuserprofile = data.lastchangeuserprofile;
|
lastchangeuserprofile = data.lastchangeuserprofile;
|
||||||
updateLastChangeUser();
|
updateLastChangeUser();
|
||||||
}
|
}
|
||||||
|
if (data.hasOwnProperty('authors') && authors !== data.authors) {
|
||||||
|
authors = data.authors;
|
||||||
|
}
|
||||||
|
if (data.hasOwnProperty('authorship') && authorship !== data.authorship) {
|
||||||
|
authorship = data.authorship;
|
||||||
|
updateAuthorship();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
var updateAuthorship = _.throttle(updateAuthorshipInner, 50);
|
||||||
|
function initMark() {
|
||||||
|
return {
|
||||||
|
gutter: {
|
||||||
|
userid: null,
|
||||||
|
timestamp: null
|
||||||
|
},
|
||||||
|
textmarkers: []
|
||||||
|
};
|
||||||
|
}
|
||||||
|
function initMarkAndCheckGutter(mark, author, timestamp) {
|
||||||
|
if (!mark) mark = initMark();
|
||||||
|
if (!mark.gutter.userid || mark.gutter.timestamp > timestamp) {
|
||||||
|
mark.gutter.userid = author.userid;
|
||||||
|
mark.gutter.timestamp = timestamp;
|
||||||
|
}
|
||||||
|
return mark;
|
||||||
|
}
|
||||||
|
var gutterStylePrefix = "border-left: 3px solid ";
|
||||||
|
var gutterStylePostfix = "; height: " + defaultTextHeight + "px; margin-left: 3px;";
|
||||||
|
var textMarkderStylePrefix = "background-image: linear-gradient(to top, ";
|
||||||
|
var textMarkderStylePostfix = " 1px, transparent 1px);";
|
||||||
|
var addStyleRule = (function () {
|
||||||
|
var added = {};
|
||||||
|
var styleElement = document.createElement('style');
|
||||||
|
document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
|
||||||
|
var styleSheet = styleElement.sheet;
|
||||||
|
|
||||||
|
return function (css) {
|
||||||
|
if (added[css]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
added[css] = true;
|
||||||
|
styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length);
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
function updateAuthorshipInner() {
|
||||||
|
// ignore when ot not synced yet
|
||||||
|
if (Object.keys(cmClient.state).length > 0) return;
|
||||||
|
var authorMarks = {};
|
||||||
|
for (var i = 0; i < authorship.length; i++) {
|
||||||
|
var atom = authorship[i];
|
||||||
|
var author = authors[atom[0]];
|
||||||
|
if (author) {
|
||||||
|
var prePos = editor.posFromIndex(atom[1]);
|
||||||
|
var preLine = editor.getLine(prePos.line);
|
||||||
|
var postPos = editor.posFromIndex(atom[2]);
|
||||||
|
var postLine = editor.getLine(postPos.line);
|
||||||
|
if (prePos.ch == 0 && postPos.ch == postLine.length) {
|
||||||
|
for (var j = prePos.line; j <= postPos.line; j++) {
|
||||||
|
if (editor.getLine(j)) {
|
||||||
|
authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (postPos.line - prePos.line >= 1) {
|
||||||
|
var startLine = prePos.line;
|
||||||
|
var endLine = postPos.line;
|
||||||
|
if (prePos.ch == preLine.length) {
|
||||||
|
startLine++;
|
||||||
|
} else if (prePos.ch != 0) {
|
||||||
|
var mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3]);
|
||||||
|
var _postPos = {
|
||||||
|
line: prePos.line,
|
||||||
|
ch: preLine.length
|
||||||
|
};
|
||||||
|
if (JSON.stringify(prePos) != JSON.stringify(_postPos)) {
|
||||||
|
mark.textmarkers.push({
|
||||||
|
userid: author.userid,
|
||||||
|
pos: [prePos, _postPos]
|
||||||
|
});
|
||||||
|
startLine++;
|
||||||
|
}
|
||||||
|
authorMarks[prePos.line] = mark;
|
||||||
|
}
|
||||||
|
if (postPos.ch == 0) {
|
||||||
|
endLine--;
|
||||||
|
} else if (postPos.ch != postLine.length) {
|
||||||
|
var mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3]);
|
||||||
|
var _prePos = {
|
||||||
|
line: postPos.line,
|
||||||
|
ch: 0
|
||||||
|
};
|
||||||
|
if (JSON.stringify(_prePos) != JSON.stringify(postPos)) {
|
||||||
|
mark.textmarkers.push({
|
||||||
|
userid: author.userid,
|
||||||
|
pos: [_prePos, postPos]
|
||||||
|
});
|
||||||
|
endLine--;
|
||||||
|
}
|
||||||
|
authorMarks[postPos.line] = mark;
|
||||||
|
}
|
||||||
|
for (var j = startLine; j <= endLine; j++) {
|
||||||
|
if (editor.getLine(j)) {
|
||||||
|
authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3]);
|
||||||
|
if (JSON.stringify(prePos) != JSON.stringify(postPos)) {
|
||||||
|
mark.textmarkers.push({
|
||||||
|
userid: author.userid,
|
||||||
|
pos: [prePos, postPos]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
authorMarks[prePos.line] = mark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var addTextMarkers = [];
|
||||||
|
editor.eachLine(function (line) {
|
||||||
|
var lineNumber = editor.getLineNumber(line);
|
||||||
|
var currMark = authorMarks[lineNumber];
|
||||||
|
var author = currMark ? authors[currMark.gutter.userid] : null;
|
||||||
|
if (currMark && author) {
|
||||||
|
var className = 'authorship-gutter-' + author.color.substr(1);
|
||||||
|
var gutters = editor.getLineHandle(lineNumber).gutterMarkers;
|
||||||
|
if (!gutters || !gutters['authorship-gutters'] ||
|
||||||
|
!gutters['authorship-gutters'].className ||
|
||||||
|
!gutters['authorship-gutters'].className.indexOf(className) < 0) {
|
||||||
|
var styleString = gutterStylePrefix + author.color + gutterStylePostfix;
|
||||||
|
var rule = "." + className + "{" + styleString + "}";
|
||||||
|
addStyleRule(rule);
|
||||||
|
var gutter = $('<div>', {
|
||||||
|
class: 'authorship-gutter ' + className,
|
||||||
|
title: author.name
|
||||||
|
});
|
||||||
|
editor.setGutterMarker(lineNumber, "authorship-gutters", gutter[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
editor.setGutterMarker(lineNumber, "authorship-gutters", null);
|
||||||
|
}
|
||||||
|
if (currMark && currMark.textmarkers.length > 0) {
|
||||||
|
for (var i = 0; i < currMark.textmarkers.length; i++) {
|
||||||
|
var textMarker = currMark.textmarkers[i];
|
||||||
|
if (textMarker.userid != currMark.gutter.userid) {
|
||||||
|
addTextMarkers.push(textMarker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var allTextMarks = editor.getAllMarks();
|
||||||
|
for (var i = 0; i < allTextMarks.length; i++) {
|
||||||
|
var _textMarker = allTextMarks[i];
|
||||||
|
var pos = _textMarker.find();
|
||||||
|
var found = false;
|
||||||
|
for (var j = 0; j < addTextMarkers.length; j++) {
|
||||||
|
var textMarker = addTextMarkers[j];
|
||||||
|
var author = authors[textMarker.userid];
|
||||||
|
var className = 'authorship-inline-' + author.color.substr(1);
|
||||||
|
var obj = {
|
||||||
|
from: textMarker.pos[0],
|
||||||
|
to: textMarker.pos[1]
|
||||||
|
};
|
||||||
|
if (JSON.stringify(pos) == JSON.stringify(obj) && _textMarker.className &&
|
||||||
|
_textMarker.className.indexOf(className) > -1) {
|
||||||
|
addTextMarkers.splice(j, 1);
|
||||||
|
j--;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && _textMarker.className && _textMarker.className.indexOf('authorship-inline') > -1) {
|
||||||
|
_textMarker.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < addTextMarkers.length; i++) {
|
||||||
|
var textMarker = addTextMarkers[i];
|
||||||
|
var author = authors[textMarker.userid];
|
||||||
|
var rgbcolor = hex2rgb(author.color);
|
||||||
|
var colorString = "rgba(" + rgbcolor.red + "," + rgbcolor.green + "," + rgbcolor.blue + ",0.7)";
|
||||||
|
var styleString = textMarkderStylePrefix + colorString + textMarkderStylePostfix;
|
||||||
|
var className = 'authorship-inline-' + author.color.substr(1);
|
||||||
|
var rule = "." + className + "{" + styleString + "}";
|
||||||
|
addStyleRule(rule);
|
||||||
|
var _textMarker = editor.markText(textMarker.pos[0], textMarker.pos[1], {
|
||||||
|
className: 'authorship-inline ' + className,
|
||||||
|
title: author.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
authorshipMarks = authorMarks;
|
||||||
|
}
|
||||||
|
editor.on('update', function () {
|
||||||
|
$('.authorship-gutter:not([data-original-title])').tooltip({
|
||||||
|
container: '.CodeMirror-lines',
|
||||||
|
placement: 'right',
|
||||||
|
delay: { "show": 500, "hide": 100 }
|
||||||
|
});
|
||||||
|
$('.authorship-inline:not([data-original-title])').tooltip({
|
||||||
|
container: '.CodeMirror-lines',
|
||||||
|
placement: 'bottom',
|
||||||
|
delay: { "show": 500, "hide": 100 }
|
||||||
|
});
|
||||||
|
// clear tooltip which described element has been removed
|
||||||
|
$('[id^="tooltip"]').each(function (index, element) {
|
||||||
|
$ele = $(element);
|
||||||
|
if ($('[aria-describedby="' + $ele.attr('id') + '"]').length <= 0) $ele.remove();
|
||||||
|
});
|
||||||
|
});
|
||||||
socket.on('check', function (data) {
|
socket.on('check', function (data) {
|
||||||
//console.log(data);
|
//console.log(data);
|
||||||
updateLastInfo(data);
|
updateLastInfo(data);
|
||||||
|
|
|
@ -4,4 +4,4 @@
|
||||||
* @link https://github.com/NextStepWebs/codemirror-spell-checker
|
* @link https://github.com/NextStepWebs/codemirror-spell-checker
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){border-bottom:1px dashed rgba(255,0,0,.8)}
|
.CodeMirror .cm-spell-error:not(.cm-url):not(.cm-comment):not(.cm-tag):not(.cm-word){border-bottom:2px dotted rgba(255,0,0,.8)}
|
Loading…
Add table
Reference in a new issue