Merge branch 'master' into sk-plans-tidy

This commit is contained in:
Shane Kilkelly
2016-10-26 13:47:26 +01:00
14 changed files with 806 additions and 509 deletions
@@ -143,7 +143,7 @@ module.exports = UserController =
type:'success'
text:'Your password has been changed'
else
logger.log user: user, "current password wrong"
logger.log user_id: user_id, "current password wrong"
res.send
message:
type:'error'
@@ -39,7 +39,7 @@ pathList = [
["#{jsPath}ide.js"]
["#{jsPath}main.js"]
["#{jsPath}libs.js"]
["#{jsPath}#{ace}/ace.js","#{jsPath}#{ace}/mode-latex.js", "#{jsPath}#{ace}/snippets/latex.js"]
["#{jsPath}#{ace}/ace.js","#{jsPath}#{ace}/mode-latex.js","#{jsPath}#{ace}/worker-latex.js","#{jsPath}#{ace}/snippets/latex.js"]
["#{jsPath}libs/#{pdfjs}/pdf.js"]
["#{jsPath}libs/#{pdfjs}/pdf.worker.js"]
["#{jsPath}libs/#{pdfjs}/compatibility.js"]
@@ -1,5 +1,7 @@
module.exports =
user: (user) ->
if !user?
return null
if !user._id?
user = {_id : user}
return {
@@ -10,6 +12,8 @@ module.exports =
}
project: (project) ->
if !project?
return null
if !project._id?
project = {_id: project}
return {
@@ -118,6 +118,9 @@ block requirejs
"ace/ext-searchbox": {
"deps": ["ace/ace"]
},
"ace/ext-modelist": {
"deps": ["ace/ace"]
},
"ace/ext-language_tools": {
"deps": ["ace/ace"]
}
@@ -35,7 +35,8 @@ div.full-size(
resize-on="layout:main:resize,layout:pdf:resize",
annotations="pdf.logEntryAnnotations[editor.open_doc_id]",
read-only="!permissions.write",
on-ctrl-enter="recompileViaKey"
file-name="editor.open_doc_name",
on-ctrl-enter="recompileViaKey",
syntax-validation="settings.syntaxValidation"
)
@@ -27,6 +27,7 @@ define [], () ->
@connected = false
@userIsInactive = false
@gracefullyReconnecting = false
@$scope.connection =
reconnecting: false
@@ -54,6 +55,7 @@ define [], () ->
@ide.socket.on "connect", () =>
sl_console.log "[socket.io connect] Connected"
@connected = true
@gracefullyReconnecting = false
@ide.pushEvent("connected")
@$scope.$apply () =>
@@ -81,7 +83,7 @@ define [], () ->
@$scope.$apply () =>
@$scope.connection.reconnecting = false
if !$scope.connection.forced_disconnect and !@userIsInactive
if !$scope.connection.forced_disconnect and !@userIsInactive and !@gracefullyReconnecting
@startAutoReconnectCountdown()
@ide.socket.on 'forceDisconnect', (message) =>
@@ -97,7 +99,11 @@ define [], () ->
setTimeout () ->
location.reload()
, 10 * 1000
@ide.socket.on "reconnectGracefully", () =>
sl_console.log "Reconnect gracefully"
@reconnectGracefully()
joinProject: () ->
sl_console.log "[joinProject] joining..."
@ide.socket.emit 'joinProject', {
@@ -180,3 +186,24 @@ define [], () ->
@$scope.$apply () =>
@$scope.connection.inactive_disconnect = true
RECONNECT_GRACEFULLY_RETRY_INTERVAL: 5000 # ms
MAX_RECONNECT_GRACEFULLY_INTERVAL: 60 * 5 * 1000 # 5 minutes
reconnectGracefully: () ->
@reconnectGracefullyStarted ?= new Date()
userIsInactive = (new Date() - @lastUserAction) > @RECONNECT_GRACEFULLY_RETRY_INTERVAL
maxIntervalReached = (new Date() - @reconnectGracefullyStarted) > @MAX_RECONNECT_GRACEFULLY_INTERVAL
if userIsInactive or maxIntervalReached
sl_console.log "[reconnectGracefully] User didn't do anything for last 5 seconds, reconnecting"
@_reconnectGracefullyNow()
else
sl_console.log "[reconnectGracefully] User is working, will try again in 5 seconds"
setTimeout () =>
@reconnectGracefully()
, @RECONNECT_GRACEFULLY_RETRY_INTERVAL
_reconnectGracefullyNow: () ->
@gracefullyReconnecting = true
@reconnectGracefullyStarted = null
# Clear cookie so we don't go to the same backend server
$.cookie("SERVERID", "", { expires: -1, path: "/" })
@reconnectImmediately()
@@ -8,6 +8,7 @@ define [
@$scope.editor = {
sharejs_doc: null
open_doc_id: null
open_doc_name: null
opening: true
}
@@ -59,6 +60,7 @@ define [
return
@$scope.editor.open_doc_id = doc.id
@$scope.editor.open_doc_name = doc.name
@ide.localStorage "doc.open_id.#{@$scope.project_id}", doc.id
@ide.fileTreeManager.selectEntity(doc)
@@ -2,14 +2,16 @@ define [
"base"
"ace/ace"
"ace/ext-searchbox"
"ace/ext-modelist"
"ide/editor/directives/aceEditor/undo/UndoManager"
"ide/editor/directives/aceEditor/auto-complete/AutoCompleteManager"
"ide/editor/directives/aceEditor/spell-check/SpellCheckManager"
"ide/editor/directives/aceEditor/highlights/HighlightsManager"
"ide/editor/directives/aceEditor/cursor-position/CursorPositionManager"
"ide/editor/directives/aceEditor/track-changes/TrackChangesManager"
], (App, Ace, SearchBox, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager, TrackChangesManager) ->
], (App, Ace, SearchBox, ModeList, UndoManager, AutoCompleteManager, SpellCheckManager, HighlightsManager, CursorPositionManager, TrackChangesManager) ->
EditSession = ace.require('ace/edit_session').EditSession
ModeList = ace.require('ace/ext/modelist')
# set the path for ace workers if using a CDN (from editor.jade)
if window.aceWorkerPath != ""
@@ -42,7 +44,8 @@ define [
text: "="
readOnly: "="
annotations: "="
navigateHighlights: "=",
navigateHighlights: "="
fileName: "="
onCtrlEnter: "="
syntaxValidation: "="
}
@@ -204,11 +207,6 @@ define [
editor.setOption("scrollPastEnd", true)
resetSession = () ->
session = editor.getSession()
session.setUseWrapMode(true)
session.setMode("ace/mode/latex")
updateCount = 0
onChange = () ->
updateCount++
@@ -221,9 +219,18 @@ define [
session = editor.getSession()
if session?
session.destroy()
editor.setSession(new EditSession(lines, "ace/mode/latex"))
resetSession()
# see if we can lookup a suitable mode from ace
# but fall back to text by default
try
mode = ModeList.getModeForPath(scope.fileName).mode
catch
mode = "ace/mode/text"
editor.setSession(new EditSession(lines, mode))
session = editor.getSession()
session.setUseWrapMode(true)
doc = session.getDocument()
doc.on "change", onChange
@@ -233,8 +233,16 @@ define [
start = aceDelta.start
if !start?
error = new Error("aceDelta had no start event.")
JSONstringifyWithCycles = (o) ->
seen = []
return JSON.stringify o, (k,v) ->
if (typeof v == 'object')
if ( !seen.indexOf(v) )
return '__cycle__'
seen.push(v);
return v
Raven?.captureException(error, {
aceDelta: JSON.stringify(aceDelta)
aceDelta: JSONstringifyWithCycles(aceDelta)
})
throw error
linesBefore = docLines.slice(0, start.row)
@@ -17,8 +17,13 @@ define [
# When we join the project:
# index all references files
# and don't broadcast to all clients
@inited = false
@$scope.$on 'project:joined', (e) =>
@indexAllReferences(false)
# We only need to grab the references when the editor first loads,
# not on every reconnect
if !@inited
@inited = true
@indexAllReferences(false)
setTimeout(
(self) ->
@@ -30,7 +30,7 @@ define [
$scope.$watch "settings.syntaxValidation", (syntaxValidation, oldSyntaxValidation) =>
if syntaxValidation != oldSyntaxValidation
settings.saveProjectSettings({syntaxValidation: syntaxValidation})
settings.saveSettings({syntaxValidation: syntaxValidation})
$scope.$watch "project.spellCheckLanguage", (language, oldLanguage) =>
return if @ignoreUpdates
+127 -118
View File
@@ -205,128 +205,137 @@ var LatexFoldMode = require("./folding/latex").FoldMode;
var Range = require("../range").Range;
var WorkerClient = require("ace/worker/worker_client").WorkerClient;
var createLatexWorker = function (session) {
var doc = session.getDocument();
var selection = session.getSelection();
var cursorAnchor = selection.lead;
var savedRange = {};
var suppressions = [];
var hints = [];
var changeHandler = null;
var worker = new WorkerClient(["ace"], "ace/mode/latex_worker", "LatexWorker");
worker.attachToDocument(doc);
doc.on("change", function () {
if(changeHandler) {
clearTimeout(changeHandler);
changeHandler = null;
}
});
selection.on("changeCursor", function () {
changeHandler = setTimeout(function () {
updateMarkers({cursorMoveOnly:true});
suppressions = [];
changeHandler = null;
}, 100);
});
var updateMarkers = function (options) {
if (!options) { options = {};};
var cursorMoveOnly = options.cursorMoveOnly;
var annotations = [];
var newRange = {};
var cursor = selection.getCursor();
suppressions = [];
for (var i = 0, len = hints.length; i<len; i++) {
var hint = hints[i];
var suppressedChanges = 0;
var hintRange = new Range(hint.start_row, hint.start_col, hint.end_row, hint.end_col);
var cursorInRange = hintRange.insideStart(cursor.row, cursor.column);
var cursorAtStart = hintRange.isStart(cursor.row, cursor.column);
var cursorAtEnd = hintRange.isEnd(cursor.row, cursor.column);
if (hint.suppressIfEditing && (cursorAtStart || cursorAtEnd)) {
suppressions.push(hintRange);
if (!hint.suppressed) { suppressedChanges++; };
hint.suppressed = true;
continue;
}
var isCascadeError = false;
for (var j = 0, suplen = suppressions.length; j < suplen; j++) {
var badRange = suppressions[j];
if (badRange.intersects(hintRange)) {
isCascadeError = true;
break;
}
}
if(isCascadeError) {
if (!hint.suppressed) { suppressedChanges++; };
hint.suppressed = true;
continue;
};
if (hint.suppressed) { suppressedChanges++; };
hint.suppressed = false;
annotations.push(hint);
if (hint.type === "info") {
continue;
};
var key = hintRange.toString() + (cursorInRange ? "+cursor" : "");
newRange[key] = {hint: hint, cursorInRange: cursorInRange, range: hintRange};
}
for (key in newRange) {
if (!savedRange[key]) { // doesn't exist in already displayed errors
var new_range = newRange[key].range;
cursorInRange = newRange[key].cursorInRange;
hint = newRange[key].hint;
var errorAtStart = (hint.row === hint.start_row && hint.column === hint.start_col);
var a = (cursorInRange && !errorAtStart) ? cursorAnchor : doc.createAnchor(new_range.start);
var b = (cursorInRange && errorAtStart) ? cursorAnchor : doc.createAnchor(new_range.end);
var range = new Range();
range.start = a;
range.end = b;
var cssClass = "ace_error-marker";
if (hint.type === "warning") { cssClass = "ace_highlight-marker"; };
range.id = session.addMarker(range, cssClass, "text");
savedRange[key] = range;
}
}
for (key in savedRange) {
if (!newRange[key]) { // no longer present in list of errors to display
range = savedRange[key];
if (range.start !== cursorAnchor) { range.start.detach(); }
if (range.end !== cursorAnchor) { range.end.detach(); }
session.removeMarker(range.id);
delete savedRange[key];
}
}
if (!cursorMoveOnly || suppressedChanges) {
session.setAnnotations(annotations);
};
};
worker.on("lint", function(results) {
hints = results.data;
if (hints.length > 100) {
hints = hints.slice(0, 100); // limit to 100 errors
};
updateMarkers();
});
worker.on("terminate", function() {
for (var key in savedRange) {
var range = savedRange[key];
range.start.detach();
range.end.detach();
session.removeMarker(range.id);
delete savedRange[key];
}
});
return worker;
};
var Mode = function() {
this.HighlightRules = LatexHighlightRules;
this.foldingRules = new LatexFoldMode();
this.createWorker = function(session) {
var doc = session.getDocument();
var selection = session.getSelection();
var savedRange = {};
var suppressions = [];
var hints = [];
var changeHandler = null;
var worker = new WorkerClient(["ace"], "ace/mode/latex_worker", "LatexWorker");
worker.attachToDocument(doc);
doc.on("change", function () {
if(changeHandler) {
clearTimeout(changeHandler);
changeHandler = null;
}
});
selection.on("changeCursor", function () {
if(suppressions.length > 0) {
changeHandler = setTimeout(function () {
updateMarkers();
suppressions = [];
changeHandler = null;
}, 100);
}
});
var updateMarkers = function () {
var annotations = [];
var newRange = {};
var cursor = selection.getCursor();
suppressions = [];
for (var i = 0; i<hints.length; i++) {
var data = hints[i];
var start_row = data.start_row;
var start_col = data.start_col;
var end_row = data.end_row;
var end_col = data.end_col;
if (data.suppressIfEditing &&
((cursor.row === start_row && cursor.column == start_col+1)
|| (cursor.row === end_row && (cursor.column+1) == end_col))) {
suppressions.push([start_row, start_col, end_row, end_col]);
continue;
}
var suppress = false;
for (var j = 0; j < suppressions.length; j++) {
var e=suppressions[j];
var fromRow=e[0], fromCol=e[1], toRow=e[2], toCol=e[3];
if (start_row == fromRow && start_col >= fromCol && start_row === toRow && start_col <= toCol) {
suppress = true;
break;
}
}
if(suppress) { continue; };
var key = "(" + start_row + "," + start_col + ")" + ":" + "(" + end_row + "," + end_col + ")";
newRange[key] = data;
annotations.push(data);
}
var newKeys = Object.keys(newRange);
var oldKeys = Object.keys(savedRange);
var changes = 0;
for (i = 0; i < newKeys.length; i++) {
key = newKeys[i];
if (!savedRange[key]) {
var new_range = newRange[key];
var a = doc.createAnchor(new_range.start_row, new_range.start_col);
var b = doc.createAnchor(new_range.end_row, new_range.end_col);
var range = new Range();
range.start = a;
range.end = b;
range.id = session.addMarker(range, "ace_error-marker", "text");
savedRange[key] = range;
changes++;
}
}
for (i = 0; i < oldKeys.length; i++) {
key = oldKeys[i];
if (!newRange[key]) {
range = savedRange[key];
range.start.detach();
range.end.detach();
session.removeMarker(range.id);
delete savedRange[key];
changes++;
}
}
if (changes>0) {
session.setAnnotations(annotations);
};
};
worker.on("lint", function(results) {
hints = results.data;
if (hints.length > 100) {
hints = hints.slice(0, 100); // limit to 100 errors
};
updateMarkers();
});
worker.on("terminate", function() {
var oldKeys = Object.keys(savedRange);
for (var i = 0; i < oldKeys.length; i++) {
var key = oldKeys[i];
var range = savedRange[key];
session.removeMarker(range.id);
delete savedRange[key];
}
});
return worker;
};
this.createWorker = createLatexWorker;
};
oop.inherits(Mode, TextMode);
File diff suppressed because it is too large Load Diff
@@ -200,6 +200,10 @@ ul.structured-list {
.select-item + span, .select-all + span {
display: inline-block;
padding-left: @line-height-computed * 1.5;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
vertical-align: top;
}
}
}