@@ -287,7 +287,7 @@ var editor = CodeMirror.fromTextArea(textit, {
287287 } ,
288288 autoCloseTags : true ,
289289 foldGutter : true ,
290- gutters : [ "CodeMirror-linenumbers" , "CodeMirror-foldgutter" ] ,
290+ gutters : [ "CodeMirror-linenumbers" , "authorship-gutters" , " CodeMirror-foldgutter"] ,
291291 extraKeys : defaultExtraKeys ,
292292 flattenSpans : true ,
293293 addModeClass : true ,
@@ -2127,6 +2127,9 @@ socket.on('version', function (data) {
21272127 }
21282128 }
21292129} ) ;
2130+ var authors = [ ] ;
2131+ var authorship = [ ] ;
2132+ var authorshipMarks = { } ;
21302133function updateLastInfo ( data ) {
21312134 //console.log(data);
21322135 if ( data . hasOwnProperty ( 'createtime' ) && createtime !== data . createtime ) {
@@ -2142,7 +2145,212 @@ function updateLastInfo(data) {
21422145 lastchangeuserprofile = data . lastchangeuserprofile ;
21432146 updateLastChangeUser ( ) ;
21442147 }
2148+ if ( data . hasOwnProperty ( 'authors' ) && authors !== data . authors ) {
2149+ authors = data . authors ;
2150+ }
2151+ if ( data . hasOwnProperty ( 'authorship' ) && authorship !== data . authorship ) {
2152+ authorship = data . authorship ;
2153+ updateAuthorship ( ) ;
2154+ }
2155+ }
2156+ var updateAuthorship = _ . throttle ( updateAuthorshipInner , 50 ) ;
2157+ function initMark ( ) {
2158+ return {
2159+ gutter : {
2160+ userid : null ,
2161+ timestamp : null
2162+ } ,
2163+ textmarkers : [ ]
2164+ } ;
21452165}
2166+ function initMarkAndCheckGutter ( mark , author , timestamp ) {
2167+ if ( ! mark ) mark = initMark ( ) ;
2168+ if ( ! mark . gutter . userid || mark . gutter . timestamp > timestamp ) {
2169+ mark . gutter . userid = author . userid ;
2170+ mark . gutter . timestamp = timestamp ;
2171+ }
2172+ return mark ;
2173+ }
2174+ var gutterStylePrefix = "border-left: 3px solid " ;
2175+ var gutterStylePostfix = "; height: " + defaultTextHeight + "px; margin-left: 3px;" ;
2176+ var textMarkderStylePrefix = "background-image: linear-gradient(to top, " ;
2177+ var textMarkderStylePostfix = " 1px, transparent 1px);" ;
2178+ var addStyleRule = ( function ( ) {
2179+ var added = { } ;
2180+ var styleElement = document . createElement ( 'style' ) ;
2181+ document . documentElement . getElementsByTagName ( 'head' ) [ 0 ] . appendChild ( styleElement ) ;
2182+ var styleSheet = styleElement . sheet ;
2183+
2184+ return function ( css ) {
2185+ if ( added [ css ] ) {
2186+ return ;
2187+ }
2188+ added [ css ] = true ;
2189+ styleSheet . insertRule ( css , ( styleSheet . cssRules || styleSheet . rules ) . length ) ;
2190+ } ;
2191+ } ( ) ) ;
2192+ function updateAuthorshipInner ( ) {
2193+ // ignore when ot not synced yet
2194+ if ( Object . keys ( cmClient . state ) . length > 0 ) return ;
2195+ var authorMarks = { } ;
2196+ for ( var i = 0 ; i < authorship . length ; i ++ ) {
2197+ var atom = authorship [ i ] ;
2198+ var author = authors [ atom [ 0 ] ] ;
2199+ if ( author ) {
2200+ var prePos = editor . posFromIndex ( atom [ 1 ] ) ;
2201+ var preLine = editor . getLine ( prePos . line ) ;
2202+ var postPos = editor . posFromIndex ( atom [ 2 ] ) ;
2203+ var postLine = editor . getLine ( postPos . line ) ;
2204+ if ( prePos . ch == 0 && postPos . ch == postLine . length ) {
2205+ for ( var j = prePos . line ; j <= postPos . line ; j ++ ) {
2206+ if ( editor . getLine ( j ) ) {
2207+ authorMarks [ j ] = initMarkAndCheckGutter ( authorMarks [ j ] , author , atom [ 3 ] ) ;
2208+ }
2209+ }
2210+ } else if ( postPos . line - prePos . line >= 1 ) {
2211+ var startLine = prePos . line ;
2212+ var endLine = postPos . line ;
2213+ if ( prePos . ch == preLine . length ) {
2214+ startLine ++ ;
2215+ } else if ( prePos . ch != 0 ) {
2216+ var mark = initMarkAndCheckGutter ( authorMarks [ prePos . line ] , author , atom [ 3 ] ) ;
2217+ var _postPos = {
2218+ line : prePos . line ,
2219+ ch : preLine . length
2220+ } ;
2221+ if ( JSON . stringify ( prePos ) != JSON . stringify ( _postPos ) ) {
2222+ mark . textmarkers . push ( {
2223+ userid : author . userid ,
2224+ pos : [ prePos , _postPos ]
2225+ } ) ;
2226+ startLine ++ ;
2227+ }
2228+ authorMarks [ prePos . line ] = mark ;
2229+ }
2230+ if ( postPos . ch == 0 ) {
2231+ endLine -- ;
2232+ } else if ( postPos . ch != postLine . length ) {
2233+ var mark = initMarkAndCheckGutter ( authorMarks [ postPos . line ] , author , atom [ 3 ] ) ;
2234+ var _prePos = {
2235+ line : postPos . line ,
2236+ ch : 0
2237+ } ;
2238+ if ( JSON . stringify ( _prePos ) != JSON . stringify ( postPos ) ) {
2239+ mark . textmarkers . push ( {
2240+ userid : author . userid ,
2241+ pos : [ _prePos , postPos ]
2242+ } ) ;
2243+ endLine -- ;
2244+ }
2245+ authorMarks [ postPos . line ] = mark ;
2246+ }
2247+ for ( var j = startLine ; j <= endLine ; j ++ ) {
2248+ if ( editor . getLine ( j ) ) {
2249+ authorMarks [ j ] = initMarkAndCheckGutter ( authorMarks [ j ] , author , atom [ 3 ] ) ;
2250+ }
2251+ }
2252+ } else {
2253+ var mark = initMarkAndCheckGutter ( authorMarks [ prePos . line ] , author , atom [ 3 ] ) ;
2254+ if ( JSON . stringify ( prePos ) != JSON . stringify ( postPos ) ) {
2255+ mark . textmarkers . push ( {
2256+ userid : author . userid ,
2257+ pos : [ prePos , postPos ]
2258+ } ) ;
2259+ }
2260+ authorMarks [ prePos . line ] = mark ;
2261+ }
2262+ }
2263+ }
2264+ var addTextMarkers = [ ] ;
2265+ editor . eachLine ( function ( line ) {
2266+ var lineNumber = editor . getLineNumber ( line ) ;
2267+ var currMark = authorMarks [ lineNumber ] ;
2268+ var author = currMark ? authors [ currMark . gutter . userid ] : null ;
2269+ if ( currMark && author ) {
2270+ var className = 'authorship-gutter-' + author . color . substr ( 1 ) ;
2271+ var gutters = editor . getLineHandle ( lineNumber ) . gutterMarkers ;
2272+ if ( ! gutters || ! gutters [ 'authorship-gutters' ] ||
2273+ ! gutters [ 'authorship-gutters' ] . className ||
2274+ ! gutters [ 'authorship-gutters' ] . className . indexOf ( className ) < 0 ) {
2275+ var styleString = gutterStylePrefix + author . color + gutterStylePostfix ;
2276+ var rule = "." + className + "{" + styleString + "}" ;
2277+ addStyleRule ( rule ) ;
2278+ var gutter = $ ( '<div>' , {
2279+ class : 'authorship-gutter ' + className ,
2280+ title : author . name
2281+ } ) ;
2282+ editor . setGutterMarker ( lineNumber , "authorship-gutters" , gutter [ 0 ] ) ;
2283+ }
2284+ } else {
2285+ editor . setGutterMarker ( lineNumber , "authorship-gutters" , null ) ;
2286+ }
2287+ if ( currMark && currMark . textmarkers . length > 0 ) {
2288+ for ( var i = 0 ; i < currMark . textmarkers . length ; i ++ ) {
2289+ var textMarker = currMark . textmarkers [ i ] ;
2290+ if ( textMarker . userid != currMark . gutter . userid ) {
2291+ addTextMarkers . push ( textMarker ) ;
2292+ }
2293+ }
2294+ }
2295+ } ) ;
2296+ var allTextMarks = editor . getAllMarks ( ) ;
2297+ for ( var i = 0 ; i < allTextMarks . length ; i ++ ) {
2298+ var _textMarker = allTextMarks [ i ] ;
2299+ var pos = _textMarker . find ( ) ;
2300+ var found = false ;
2301+ for ( var j = 0 ; j < addTextMarkers . length ; j ++ ) {
2302+ var textMarker = addTextMarkers [ j ] ;
2303+ var author = authors [ textMarker . userid ] ;
2304+ var className = 'authorship-inline-' + author . color . substr ( 1 ) ;
2305+ var obj = {
2306+ from : textMarker . pos [ 0 ] ,
2307+ to : textMarker . pos [ 1 ]
2308+ } ;
2309+ if ( JSON . stringify ( pos ) == JSON . stringify ( obj ) && _textMarker . className &&
2310+ _textMarker . className . indexOf ( className ) > - 1 ) {
2311+ addTextMarkers . splice ( j , 1 ) ;
2312+ j -- ;
2313+ found = true ;
2314+ break ;
2315+ }
2316+ }
2317+ if ( ! found && _textMarker . className && _textMarker . className . indexOf ( 'authorship-inline' ) > - 1 ) {
2318+ _textMarker . clear ( ) ;
2319+ }
2320+ }
2321+ for ( var i = 0 ; i < addTextMarkers . length ; i ++ ) {
2322+ var textMarker = addTextMarkers [ i ] ;
2323+ var author = authors [ textMarker . userid ] ;
2324+ var rgbcolor = hex2rgb ( author . color ) ;
2325+ var colorString = "rgba(" + rgbcolor . red + "," + rgbcolor . green + "," + rgbcolor . blue + ",0.7)" ;
2326+ var styleString = textMarkderStylePrefix + colorString + textMarkderStylePostfix ;
2327+ var className = 'authorship-inline-' + author . color . substr ( 1 ) ;
2328+ var rule = "." + className + "{" + styleString + "}" ;
2329+ addStyleRule ( rule ) ;
2330+ var _textMarker = editor . markText ( textMarker . pos [ 0 ] , textMarker . pos [ 1 ] , {
2331+ className : 'authorship-inline ' + className ,
2332+ title : author . name
2333+ } ) ;
2334+ }
2335+ authorshipMarks = authorMarks ;
2336+ }
2337+ editor . on ( 'update' , function ( ) {
2338+ $ ( '.authorship-gutter:not([data-original-title])' ) . tooltip ( {
2339+ container : '.CodeMirror-lines' ,
2340+ placement : 'right' ,
2341+ delay : { "show" : 500 , "hide" : 100 }
2342+ } ) ;
2343+ $ ( '.authorship-inline:not([data-original-title])' ) . tooltip ( {
2344+ container : '.CodeMirror-lines' ,
2345+ placement : 'bottom' ,
2346+ delay : { "show" : 500 , "hide" : 100 }
2347+ } ) ;
2348+ // clear tooltip which described element has been removed
2349+ $ ( '[id^="tooltip"]' ) . each ( function ( index , element ) {
2350+ $ele = $ ( element ) ;
2351+ if ( $ ( '[aria-describedby="' + $ele . attr ( 'id' ) + '"]' ) . length <= 0 ) $ele . remove ( ) ;
2352+ } ) ;
2353+ } ) ;
21462354socket . on ( 'check' , function ( data ) {
21472355 //console.log(data);
21482356 updateLastInfo ( data ) ;
0 commit comments