From a14e7953b5a2196eda001229d44ebb2e9c18fe7c Mon Sep 17 00:00:00 2001 From: Wu Cheng-Han Date: Sat, 30 Jul 2016 11:28:24 +0800 Subject: Add support of showing authorship in editor and adjust related styles --- public/js/index.js | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 209 insertions(+), 1 deletion(-) (limited to 'public/js') diff --git a/public/js/index.js b/public/js/index.js index 6a1c6e76..ac45d220 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -287,7 +287,7 @@ var editor = CodeMirror.fromTextArea(textit, { }, autoCloseTags: true, foldGutter: true, - gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"], + gutters: ["CodeMirror-linenumbers", "authorship-gutters", "CodeMirror-foldgutter"], extraKeys: defaultExtraKeys, flattenSpans: true, addModeClass: true, @@ -2127,6 +2127,9 @@ socket.on('version', function (data) { } } }); +var authors = []; +var authorship = []; +var authorshipMarks = {}; function updateLastInfo(data) { //console.log(data); if (data.hasOwnProperty('createtime') && createtime !== data.createtime) { @@ -2142,7 +2145,212 @@ function updateLastInfo(data) { lastchangeuserprofile = data.lastchangeuserprofile; 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 = $('