@@ -564,7 +564,8 @@ var ui = {
564564 } ,
565565 modal : {
566566 snippetImportProjects : $ ( "#snippetImportModalProjects" ) ,
567- snippetImportSnippets : $ ( "#snippetImportModalSnippets" )
567+ snippetImportSnippets : $ ( "#snippetImportModalSnippets" ) ,
568+ revision : $ ( "#revisionModal" )
568569 }
569570} ;
570571
@@ -1382,6 +1383,149 @@ ui.toolbar.beta.pdf.attr("download", "").attr("href", noteurl + "/pdf");
13821383ui . toolbar . beta . slide . attr ( "href" , noteurl + "/slide" ) ;
13831384
13841385//modal actions
1386+ var revisions = [ ] ;
1387+ var revisionViewer = null ;
1388+ var revisionList = ui . modal . revision . find ( '.ui-revision-list' ) ;
1389+ var revision = null ;
1390+ var revisionTime = null ;
1391+ ui . modal . revision . on ( 'show.bs.modal' , function ( e ) {
1392+ $ . get ( noteurl + '/revision' )
1393+ . success ( function ( data ) {
1394+ parseRevisions ( JSON . parse ( data ) . revision ) ;
1395+ initRevisionViewer ( ) ;
1396+ } )
1397+ . error ( function ( err ) {
1398+
1399+ } )
1400+ . complete ( function ( ) {
1401+ //na
1402+ } ) ;
1403+ } ) ;
1404+ function checkRevisionViewer ( ) {
1405+ if ( revisionViewer ) {
1406+ var container = $ ( revisionViewer . display . wrapper ) . parent ( ) ;
1407+ $ ( revisionViewer . display . scroller ) . css ( 'height' , container . height ( ) + 'px' ) ;
1408+ revisionViewer . refresh ( ) ;
1409+ }
1410+ }
1411+ ui . modal . revision . on ( 'shown.bs.modal' , checkRevisionViewer ) ;
1412+ $ ( window ) . resize ( checkRevisionViewer ) ;
1413+ function parseRevisions ( _revisions ) {
1414+ if ( _revisions . length != revisions ) {
1415+ revisions = _revisions ;
1416+ var lastRevision = null ;
1417+ if ( revisionList . children ( ) . length > 0 ) {
1418+ lastRevision = revisionList . find ( '.active' ) . attr ( 'data-revision-time' ) ;
1419+ }
1420+ revisionList . html ( '' ) ;
1421+ for ( var i = 0 ; i < revisions . length ; i ++ ) {
1422+ var revision = revisions [ i ] ;
1423+ var item = $ ( '<a href="#" class="list-group-item"></a>' ) ;
1424+ item . attr ( 'data-revision-time' , revision . time ) ;
1425+ if ( lastRevision == revision . time ) item . addClass ( 'active' ) ;
1426+ var itemHeading = $ ( '<h5 class="list-group-item-heading"></h5>' ) ;
1427+ itemHeading . html ( '<i class="fa fa-clock-o"></i> ' + moment ( revision . time ) . format ( 'llll' ) ) ;
1428+ var itemText = $ ( '<p class="list-group-item-text"></p>' ) ;
1429+ itemText . html ( '<i class="fa fa-file-text"></i> Length: ' + revision . length ) ;
1430+ item . append ( itemHeading ) . append ( itemText ) ;
1431+ item . click ( function ( e ) {
1432+ var time = $ ( this ) . attr ( 'data-revision-time' ) ;
1433+ selectRevision ( time ) ;
1434+ } ) ;
1435+ revisionList . append ( item ) ;
1436+ }
1437+ if ( ! lastRevision ) {
1438+ selectRevision ( revisions [ 0 ] . time ) ;
1439+ }
1440+ }
1441+ }
1442+ function selectRevision ( time ) {
1443+ if ( time == revisionTime ) return ;
1444+ $ . get ( noteurl + '/revision/' + time )
1445+ . success ( function ( data ) {
1446+ revision = JSON . parse ( data ) ;
1447+ revisionTime = time ;
1448+ var lastScrollInfo = revisionViewer . getScrollInfo ( ) ;
1449+ revisionList . children ( ) . removeClass ( 'active' ) ;
1450+ revisionList . find ( '[data-revision-time="' + time + '"]' ) . addClass ( 'active' ) ;
1451+ var content = revision . content ;
1452+ revisionViewer . setValue ( content ) ;
1453+ revisionViewer . scrollTo ( null , lastScrollInfo . top ) ;
1454+ // mark the text which have been insert or delete
1455+ if ( revision . patch . length > 0 ) {
1456+ var bias = 0 ;
1457+ for ( j = 0 ; j < revision . patch . length ; j ++ ) {
1458+ var patch = revision . patch [ j ] ;
1459+ var currIndex = patch . start1 + bias ;
1460+ for ( var i = 0 ; i < patch . diffs . length ; i ++ ) {
1461+ var diff = patch . diffs [ i ] ;
1462+ // ignore if diff only contains line breaks
1463+ if ( ( diff [ 1 ] . match ( new RegExp ( "\n" , "g" ) ) || [ ] ) . length == diff [ 1 ] . length ) continue ;
1464+ switch ( diff [ 0 ] ) {
1465+ case 0 : // retain
1466+ currIndex += diff [ 1 ] . length ;
1467+ break ;
1468+ case 1 : // insert
1469+ var prePos = revisionViewer . posFromIndex ( currIndex ) ;
1470+ var postPos = revisionViewer . posFromIndex ( currIndex + diff [ 1 ] . length ) ;
1471+ revisionViewer . markText ( prePos , postPos , {
1472+ css : 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'
1473+ } ) ;
1474+ currIndex += diff [ 1 ] . length ;
1475+ break ;
1476+ case - 1 : // delete
1477+ var prePos = revisionViewer . posFromIndex ( currIndex ) ;
1478+ revisionViewer . replaceRange ( diff [ 1 ] , prePos ) ;
1479+ var postPos = revisionViewer . posFromIndex ( currIndex + diff [ 1 ] . length ) ;
1480+ revisionViewer . markText ( prePos , postPos , {
1481+ css : 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'
1482+ } ) ;
1483+ bias += diff [ 1 ] . length ;
1484+ currIndex += diff [ 1 ] . length ;
1485+ break ;
1486+ }
1487+ }
1488+ }
1489+ }
1490+ } )
1491+ . error ( function ( err ) {
1492+
1493+ } )
1494+ . complete ( function ( ) {
1495+ //na
1496+ } ) ;
1497+ }
1498+ function initRevisionViewer ( ) {
1499+ if ( revisionViewer ) return ;
1500+ var revisionViewerTextArea = document . getElementById ( "revisionViewer" ) ;
1501+ revisionViewer = CodeMirror . fromTextArea ( revisionViewerTextArea , {
1502+ mode : 'gfm' ,
1503+ viewportMargin : viewportMargin ,
1504+ lineNumbers : true ,
1505+ lineWrapping : true ,
1506+ showCursorWhenSelecting : true ,
1507+ inputStyle : "textarea" ,
1508+ gutters : [ "CodeMirror-linenumbers" ] ,
1509+ flattenSpans : true ,
1510+ addModeClass : true ,
1511+ readOnly : true ,
1512+ autoRefresh : true ,
1513+ scrollbarStyle : 'overlay'
1514+ } ) ;
1515+ }
1516+ $ ( '#revisionModalDownload' ) . click ( function ( ) {
1517+ if ( ! revision ) return ;
1518+ var filename = renderFilename ( ui . area . markdown ) + '_' + revisionTime + '.md' ;
1519+ var blob = new Blob ( [ revision . content ] , {
1520+ type : "text/markdown;charset=utf-8"
1521+ } ) ;
1522+ saveAs ( blob , filename ) ;
1523+ } ) ;
1524+ $ ( '#revisionModalRevert' ) . click ( function ( ) {
1525+ if ( ! revision ) return ;
1526+ editor . setValue ( revision . content ) ;
1527+ ui . modal . revision . modal ( 'hide' ) ;
1528+ } ) ;
13851529//snippet projects
13861530ui . modal . snippetImportProjects . change ( function ( ) {
13871531 var accesstoken = $ ( "#snippetImportModalAccessToken" ) . val ( ) ,
0 commit comments