From 45b5eb7cac193478b97628dfe587ba93a78333b6 Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 16:08:28 +0200 Subject: [PATCH 1/6] add basic author colors to code app --- www/code/inner.js | 52 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/www/code/inner.js b/www/code/inner.js index 5b517c74c..e3e939a9a 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -300,6 +300,8 @@ define([ var previewPane = mkPreviewPane(editor, CodeMirror, framework, isPresentMode); var markdownTb = mkMarkdownTb(editor, framework); + var authormarksUpdate = []; + var $print = $('#cp-app-code-print'); var $content = $('#cp-app-code-preview-content'); mkPrintButton(framework, $content, $print); @@ -321,6 +323,23 @@ define([ } else { CodeMirror.configureTheme(common); } + + // get user color for author marks + var authorcolor = framework._.sfCommon.getMetadataMgr().getUserData().color; + var authorcolor_r = parseInt("0x" + authorcolor.slice(1,3)); + var authorcolor_g = parseInt("0x" + authorcolor.slice(3,5)); + var authorcolor_b = parseInt("0x" + authorcolor.slice(5,7)); + var authorcolor_min = Math.min(authorcolor_r, authorcolor_g, authorcolor_b); + + // set minimal brightness for author marks and calculate color + tarMinColorVal = 180; + if (authorcolor_min < tarMinColorVal) { + facColor = (255-tarMinColorVal)/(255-authorcolor_min); + authorcolor_r = Math.floor(255-facColor*(255-authorcolor_r)); + authorcolor_g = Math.floor(255-facColor*(255-authorcolor_g)); + authorcolor_b = Math.floor(255-facColor*(255-authorcolor_b)); + authorcolor = "#" + authorcolor_r.toString(16) + authorcolor_g.toString(16) + authorcolor_b.toString(16); + } //// @@ -329,6 +348,10 @@ define([ if (highlightMode && highlightMode !== CodeMirror.highlightMode) { CodeMirror.setMode(highlightMode, evModeChange.fire); } + + // author marks will be updated in onChange-Handler + authormarksUpdate = newContent.authormarks; + CodeMirror.contentUpdate(newContent); previewPane.draw(); }); @@ -338,6 +361,18 @@ define([ var content = CodeMirror.getContent(); content.highlightMode = CodeMirror.highlightMode; previewPane.draw(); + + // get author marks + authormarks = []; + editor.getAllMarks().forEach(function (mark) { + pos = mark.find(); + css = mark.css; + if (pos != undefined && css != undefined) { + authormarks.push({from: {line: pos.from.line, ch: pos.from.ch}, to: {line: pos.to.line, ch: pos.to.ch}, color: css.replace("background-color:", "").trim()}); + } + }); + content.authormarks = authormarks; + return content; }); @@ -401,11 +436,24 @@ define([ framework.setNormalizer(function (c) { return { content: c.content, - highlightMode: c.highlightMode + highlightMode: c.highlightMode, + authormarks: c.authormarks }; }); - editor.on('change', framework.localChange); + editor.on('change', function( cm, change ) { + if (change.origin == "+input" || change.origin == "paste") { + // add new author mark if text is added. marks from removed text are removed automatically + editor.markText({line: change.from.line, ch: change.from.ch}, {line: change.from.line + change.text.length-1, ch: change.from.ch + change.text[change.text.length-1].length}, {css: "background-color: " + authorcolor}); + } else if (change.origin == "setValue") { + // on remote update: remove all marks, add new marks + editor.getAllMarks().forEach(marker => marker.clear()); + authormarksUpdate.forEach(function (mark) { + editor.markText({line: mark.from.line, ch: mark.from.ch}, {line: mark.to.line, ch: mark.to.ch}, {css: "background-color: " + mark.color}); + }); + } + framework.localChange(); + }); framework.start(); From 8696ecc692e30ff3ffd9b7f0ef618debf7a4e4c2 Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 16:52:38 +0200 Subject: [PATCH 2/6] add 'remove authorcolors' button --- www/code/inner.js | 17 ++++++++++++++++- www/common/sframe-common-codemirror.js | 4 ++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/www/code/inner.js b/www/code/inner.js index e3e939a9a..545d954e4 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -300,6 +300,20 @@ define([ var previewPane = mkPreviewPane(editor, CodeMirror, framework, isPresentMode); var markdownTb = mkMarkdownTb(editor, framework); + var $removeAuthorColorsButton = framework._.sfCommon.createButton('removeauthorcolors', true, {icon: 'fa-paint-brush', title: 'Autorenfarben entfernen'}); + framework._.toolbar.$rightside.append($removeAuthorColorsButton); + $removeAuthorColorsButton.click(function() { + selfrom = editor.getCursor("from"); + selto = editor.getCursor("to"); + if (selfrom == selto) { + editor.getAllMarks().forEach(marker => marker.clear()); + } else { + editor.findMarks(selfrom, selto).forEach(marker => marker.clear()); + } + framework.localChange(); + }); + + var authormarksLocal = []; var authormarksUpdate = []; var $print = $('#cp-app-code-print'); @@ -352,7 +366,7 @@ define([ // author marks will be updated in onChange-Handler authormarksUpdate = newContent.authormarks; - CodeMirror.contentUpdate(newContent); + CodeMirror.contentUpdate(newContent, authormarksUpdate, authormarksLocal); previewPane.draw(); }); @@ -372,6 +386,7 @@ define([ } }); content.authormarks = authormarks; + authormarksLocal = authormarks.slice(); return content; }); diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index 5ae5a4246..bedaa9191 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -418,12 +418,12 @@ define([ - exp.contentUpdate = function (newContent) { + exp.contentUpdate = function (newContent, authormarksUpdate, authormarksLocal) { var oldDoc = canonicalize(editor.getValue()); var remoteDoc = newContent.content; // setValueAndCursor triggers onLocal, even if we don't make any change to the content // and it may revert other changes (metadata) - if (oldDoc === remoteDoc) { return; } + if (oldDoc === remoteDoc && authormarksUpdate == authormarksLocal) { return; } exp.setValueAndCursor(oldDoc, remoteDoc); }; From 5f7bc9fca5203c7035da96aea0f3a57bb068f202 Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 17:14:57 +0200 Subject: [PATCH 3/6] fix remove author color button when nothing is selected --- www/code/inner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/www/code/inner.js b/www/code/inner.js index 545d954e4..f155eee6a 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -305,7 +305,7 @@ define([ $removeAuthorColorsButton.click(function() { selfrom = editor.getCursor("from"); selto = editor.getCursor("to"); - if (selfrom == selto) { + if (!editor.somethingSelected() || selfrom == selto) { editor.getAllMarks().forEach(marker => marker.clear()); } else { editor.findMarks(selfrom, selto).forEach(marker => marker.clear()); From 79325b8cca475a84f99a3525e4ae44066c52d495 Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 19:07:12 +0200 Subject: [PATCH 4/6] bugfix authorcolors: wrong end position on multiline edit --- www/code/inner.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/www/code/inner.js b/www/code/inner.js index f155eee6a..79b625154 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -459,7 +459,12 @@ define([ editor.on('change', function( cm, change ) { if (change.origin == "+input" || change.origin == "paste") { // add new author mark if text is added. marks from removed text are removed automatically - editor.markText({line: change.from.line, ch: change.from.ch}, {line: change.from.line + change.text.length-1, ch: change.from.ch + change.text[change.text.length-1].length}, {css: "background-color: " + authorcolor}); + if (change.text.length > 1) { + to_ch = change.text[change.text.length-1].length; + } else { + to_ch = change.from.ch + change.text[change.text.length-1].length; + } + editor.markText({line: change.from.line, ch: change.from.ch}, {line: change.from.line + change.text.length-1, ch: to_ch}, {css: "background-color: " + authorcolor}); } else if (change.origin == "setValue") { // on remote update: remove all marks, add new marks editor.getAllMarks().forEach(marker => marker.clear()); From 56031a5c14463420056af3dd1c93b464ff63d3cd Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 20:30:55 +0200 Subject: [PATCH 5/6] authorcolor storage optimization, add undefined checks before access, code styling --- www/code/inner.js | 78 +++++++++++++++++++------- www/common/sframe-common-codemirror.js | 2 +- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/www/code/inner.js b/www/code/inner.js index 79b625154..f213b13a8 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -303,12 +303,16 @@ define([ var $removeAuthorColorsButton = framework._.sfCommon.createButton('removeauthorcolors', true, {icon: 'fa-paint-brush', title: 'Autorenfarben entfernen'}); framework._.toolbar.$rightside.append($removeAuthorColorsButton); $removeAuthorColorsButton.click(function() { - selfrom = editor.getCursor("from"); - selto = editor.getCursor("to"); - if (!editor.somethingSelected() || selfrom == selto) { - editor.getAllMarks().forEach(marker => marker.clear()); + var selfrom = editor.getCursor("from"); + var selto = editor.getCursor("to"); + if (!editor.somethingSelected() || selfrom === selto) { + editor.getAllMarks().forEach(function (marker) { + marker.clear(); + }); } else { - editor.findMarks(selfrom, selto).forEach(marker => marker.clear()); + editor.findMarks(selfrom, selto).forEach(function (marker) { + marker.clear(); + }); } framework.localChange(); }); @@ -346,9 +350,9 @@ define([ var authorcolor_min = Math.min(authorcolor_r, authorcolor_g, authorcolor_b); // set minimal brightness for author marks and calculate color - tarMinColorVal = 180; + var tarMinColorVal = 180; if (authorcolor_min < tarMinColorVal) { - facColor = (255-tarMinColorVal)/(255-authorcolor_min); + var facColor = (255-tarMinColorVal)/(255-authorcolor_min); authorcolor_r = Math.floor(255-facColor*(255-authorcolor_r)); authorcolor_g = Math.floor(255-facColor*(255-authorcolor_g)); authorcolor_b = Math.floor(255-facColor*(255-authorcolor_b)); @@ -377,12 +381,21 @@ define([ previewPane.draw(); // get author marks - authormarks = []; + var authormarks = []; editor.getAllMarks().forEach(function (mark) { - pos = mark.find(); - css = mark.css; - if (pos != undefined && css != undefined) { - authormarks.push({from: {line: pos.from.line, ch: pos.from.ch}, to: {line: pos.to.line, ch: pos.to.ch}, color: css.replace("background-color:", "").trim()}); + var pos = mark.find(); + var css = mark.css; + if (pos !== undefined && css !== undefined) { + var color = css.replace("background-color:", "").trim(); + if (pos.from.line === pos.to.line) { + if ((pos.from.ch + 1) === pos.to.ch) { + authormarks.push([pos.from.line, pos.from.ch, color]); + } else { + authormarks.push([pos.from.line, pos.from.ch, pos.to.ch, color]); + } + } else { + authormarks.push([pos.from.line, pos.from.ch, pos.to.line, pos.to.ch, color]); + } } }); content.authormarks = authormarks; @@ -457,19 +470,46 @@ define([ }); editor.on('change', function( cm, change ) { - if (change.origin == "+input" || change.origin == "paste") { + if (change.origin !== undefined && change.text !== undefined && (change.origin === "+input" || change.origin === "paste")) { // add new author mark if text is added. marks from removed text are removed automatically + var to_ch_add; if (change.text.length > 1) { - to_ch = change.text[change.text.length-1].length; + to_ch_add = change.text[change.text.length-1].length; } else { - to_ch = change.from.ch + change.text[change.text.length-1].length; + to_ch_add = change.from.ch + change.text[change.text.length-1].length; } - editor.markText({line: change.from.line, ch: change.from.ch}, {line: change.from.line + change.text.length-1, ch: to_ch}, {css: "background-color: " + authorcolor}); - } else if (change.origin == "setValue") { + editor.markText({line: change.from.line, ch: change.from.ch}, {line: change.from.line + change.text.length-1, ch: to_ch_add}, {css: "background-color: " + authorcolor}); + } else if (change.origin === "setValue") { // on remote update: remove all marks, add new marks - editor.getAllMarks().forEach(marker => marker.clear()); + editor.getAllMarks().forEach(function (marker) { + marker.clear(); + }); authormarksUpdate.forEach(function (mark) { - editor.markText({line: mark.from.line, ch: mark.from.ch}, {line: mark.to.line, ch: mark.to.ch}, {css: "background-color: " + mark.color}); + var from_line; + var to_line; + var from_ch; + var to_ch; + var mark_color; + if (mark.length === 3) { + from_line = mark[0]; + to_line = mark[0]; + from_ch = mark[1]; + to_ch = mark[1]+1; + mark_color = mark[2]; + } else if (mark.length === 4) { + from_line = mark[0]; + to_line = mark[0]; + from_ch = mark[1]; + to_ch = mark[2]; + mark_color = mark[3]; + } else if (mark.length === 5) { + from_line = mark[0]; + to_line = mark[2]; + from_ch = mark[1]; + to_ch = mark[3]; + mark_color = mark[4]; + } + editor.markText({line: from_line, ch: from_ch}, {line: to_line, ch: to_ch}, {css: "background-color: " + mark_color}); }); } framework.localChange(); diff --git a/www/common/sframe-common-codemirror.js b/www/common/sframe-common-codemirror.js index bedaa9191..2dc0db495 100644 --- a/www/common/sframe-common-codemirror.js +++ b/www/common/sframe-common-codemirror.js @@ -423,7 +423,7 @@ define([ var remoteDoc = newContent.content; // setValueAndCursor triggers onLocal, even if we don't make any change to the content // and it may revert other changes (metadata) - if (oldDoc === remoteDoc && authormarksUpdate == authormarksLocal) { return; } + if (oldDoc === remoteDoc && (authormarksUpdate === undefined || authormarksLocal === undefined || JSON.stringify(authormarksUpdate) === JSON.stringify(authormarksLocal))) { return; } exp.setValueAndCursor(oldDoc, remoteDoc); }; From 272c1007dbf07c2fd0f3e83d63df0bbdb283f950 Mon Sep 17 00:00:00 2001 From: stoppegp Date: Tue, 7 Apr 2020 20:49:36 +0200 Subject: [PATCH 6/6] authorcolor storage optimizations --- www/code/inner.js | 49 ++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 22 deletions(-) diff --git a/www/code/inner.js b/www/code/inner.js index f213b13a8..ae2fc5dd2 100644 --- a/www/code/inner.js +++ b/www/code/inner.js @@ -382,23 +382,29 @@ define([ // get author marks var authormarks = []; + var colorlist = []; editor.getAllMarks().forEach(function (mark) { var pos = mark.find(); var css = mark.css; if (pos !== undefined && css !== undefined) { var color = css.replace("background-color:", "").trim(); + var colorIndex = colorlist.indexOf(color); + if (colorIndex === -1) { + colorlist.push(color); + colorIndex = colorlist.length-1; + } if (pos.from.line === pos.to.line) { if ((pos.from.ch + 1) === pos.to.ch) { - authormarks.push([pos.from.line, pos.from.ch, color]); + authormarks.push([colorIndex, pos.from.line, pos.from.ch]); } else { - authormarks.push([pos.from.line, pos.from.ch, pos.to.ch, color]); + authormarks.push([colorIndex, pos.from.line, pos.from.ch, pos.to.ch]); } } else { - authormarks.push([pos.from.line, pos.from.ch, pos.to.line, pos.to.ch, color]); + authormarks.push([colorIndex, pos.from.line, pos.from.ch, pos.to.line, pos.to.ch]); } } }); - content.authormarks = authormarks; + content.authormarks = {marks: authormarks, colorlist: colorlist}; authormarksLocal = authormarks.slice(); return content; @@ -484,32 +490,31 @@ define([ editor.getAllMarks().forEach(function (marker) { marker.clear(); }); - authormarksUpdate.forEach(function (mark) { + authormarksUpdate.marks.forEach(function (mark) { var from_line; var to_line; var from_ch; var to_ch; - var mark_color; + var colorIndex = mark[0]; + if (authormarksUpdate.colorlist === undefined || (authormarksUpdate.colorlist.length < (colorIndex+1))) { return; } + var color = authormarksUpdate.colorlist[colorIndex]; if (mark.length === 3) { - from_line = mark[0]; - to_line = mark[0]; - from_ch = mark[1]; - to_ch = mark[1]+1; - mark_color = mark[2]; + from_line = mark[1]; + to_line = mark[1]; + from_ch = mark[2]; + to_ch = mark[2]+1; } else if (mark.length === 4) { - from_line = mark[0]; - to_line = mark[0]; - from_ch = mark[1]; - to_ch = mark[2]; - mark_color = mark[3]; - } else if (mark.length === 5) { - from_line = mark[0]; - to_line = mark[2]; - from_ch = mark[1]; + from_line = mark[1]; + to_line = mark[1]; + from_ch = mark[2]; to_ch = mark[3]; - mark_color = mark[4]; + } else if (mark.length === 5) { + from_line = mark[1]; + to_line = mark[3]; + from_ch = mark[2]; + to_ch = mark[4]; } - editor.markText({line: from_line, ch: from_ch}, {line: to_line, ch: to_ch}, {css: "background-color: " + mark_color}); + editor.markText({line: from_line, ch: from_ch}, {line: to_line, ch: to_ch}, {css: "background-color: " + color}); }); } framework.localChange();