mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-11 17:06:43 -05:00
Get basic cursor updating going on
This commit is contained in:
parent
703a4faa0e
commit
c14774bedd
7 changed files with 143 additions and 4 deletions
|
@ -142,9 +142,11 @@ block content
|
||||||
font-size="settings.fontSize",
|
font-size="settings.fontSize",
|
||||||
auto-complete="settings.autoComplete",
|
auto-complete="settings.autoComplete",
|
||||||
spell-check-language="project.spellCheckLanguage",
|
spell-check-language="project.spellCheckLanguage",
|
||||||
|
annotations="onlineUserCursorAnnotations[editor.open_doc_id]"
|
||||||
show-print-margin="false",
|
show-print-margin="false",
|
||||||
sharejs-doc="editor.sharejs_doc",
|
sharejs-doc="editor.sharejs_doc",
|
||||||
last-updated="editor.last_updated"
|
last-updated="editor.last_updated",
|
||||||
|
cursor-position="editor.cursorPosition"
|
||||||
)
|
)
|
||||||
|
|
||||||
//- #loadingScreen
|
//- #loadingScreen
|
||||||
|
|
|
@ -4,6 +4,7 @@ define [
|
||||||
"ide/connection/ConnectionManager"
|
"ide/connection/ConnectionManager"
|
||||||
"ide/editor/EditorManager"
|
"ide/editor/EditorManager"
|
||||||
"ide/settings/SettingsManager"
|
"ide/settings/SettingsManager"
|
||||||
|
"ide/online-users/OnlineUsersManager"
|
||||||
"ide/directives/layout"
|
"ide/directives/layout"
|
||||||
"ide/services/ide"
|
"ide/services/ide"
|
||||||
"directives/focus"
|
"directives/focus"
|
||||||
|
@ -15,6 +16,7 @@ define [
|
||||||
ConnectionManager
|
ConnectionManager
|
||||||
EditorManager
|
EditorManager
|
||||||
SettingsManager
|
SettingsManager
|
||||||
|
OnlineUsersManager
|
||||||
) ->
|
) ->
|
||||||
App.controller "IdeController", ["$scope", "$timeout", "ide", ($scope, $timeout, ide) ->
|
App.controller "IdeController", ["$scope", "$timeout", "ide", ($scope, $timeout, ide) ->
|
||||||
# Don't freak out if we're already in an apply callback
|
# Don't freak out if we're already in an apply callback
|
||||||
|
@ -43,6 +45,7 @@ define [
|
||||||
ide.fileTreeManager = new FileTreeManager(ide, $scope)
|
ide.fileTreeManager = new FileTreeManager(ide, $scope)
|
||||||
ide.editorManager = new EditorManager(ide, $scope)
|
ide.editorManager = new EditorManager(ide, $scope)
|
||||||
ide.settingsManager = new SettingsManager(ide, $scope)
|
ide.settingsManager = new SettingsManager(ide, $scope)
|
||||||
|
ide.onlineUsersManager = new OnlineUsersManager(ide, $scope)
|
||||||
]
|
]
|
||||||
|
|
||||||
angular.bootstrap(document.body, ["SharelatexApp"])
|
angular.bootstrap(document.body, ["SharelatexApp"])
|
|
@ -9,6 +9,7 @@ define [
|
||||||
last_updated: null
|
last_updated: null
|
||||||
open_doc_id: null
|
open_doc_id: null
|
||||||
opening: true
|
opening: true
|
||||||
|
cursorPosition: null
|
||||||
}
|
}
|
||||||
|
|
||||||
@$scope.$on "entity:selected", (event, entity) =>
|
@$scope.$on "entity:selected", (event, entity) =>
|
||||||
|
@ -32,8 +33,8 @@ define [
|
||||||
|
|
||||||
openDoc: (doc, options = {}) ->
|
openDoc: (doc, options = {}) ->
|
||||||
console.log "Trying to open doc", doc.id
|
console.log "Trying to open doc", doc.id
|
||||||
return if doc.id == @$scope.open_doc_id and !options.forceReopen
|
return if doc.id == @$scope.editor.open_doc_id and !options.forceReopen
|
||||||
@$scope.open_doc_id = doc.id
|
@$scope.editor.open_doc_id = doc.id
|
||||||
console.log "Actually opening doc", doc.id
|
console.log "Actually opening doc", doc.id
|
||||||
|
|
||||||
$.localStorage "doc.open_id.#{@$scope.project_id}", doc.id
|
$.localStorage "doc.open_id.#{@$scope.project_id}", doc.id
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
define [
|
||||||
|
"ace/range"
|
||||||
|
], () ->
|
||||||
|
Range = require("ace/range").Range
|
||||||
|
|
||||||
|
class AnnotationsManager
|
||||||
|
constructor: (@$scope, @editor) ->
|
||||||
|
@markerIds = []
|
||||||
|
|
||||||
|
@$scope.$watch "annotations", (value) =>
|
||||||
|
if value?
|
||||||
|
@redrawAnnotations()
|
||||||
|
|
||||||
|
redrawAnnotations: () ->
|
||||||
|
console.log "REDRAWING ANNOTATIONS"
|
||||||
|
for marker_id in @markerIds
|
||||||
|
@editor.getSession().removeMarker(marker_id)
|
||||||
|
@markerIds = []
|
||||||
|
|
||||||
|
for annotation in @$scope.annotations or []
|
||||||
|
do (annotation) =>
|
||||||
|
console.log "DRAWING ANNOTATION", annotation
|
||||||
|
@markerIds.push @editor.getSession().addMarker new Range(
|
||||||
|
annotation.cursor.row, annotation.cursor.column,
|
||||||
|
annotation.cursor.row, annotation.cursor.column + 1
|
||||||
|
), "remote-cursor", (html, range, left, top, config) ->
|
||||||
|
div = """
|
||||||
|
<div
|
||||||
|
class='remote-cursor custom ace_start'
|
||||||
|
style='height: #{config.lineHeight}px; top:#{top}px; left:#{left}px;'
|
||||||
|
>
|
||||||
|
<div class="nubbin" style="bottom: #{config.lineHeight - 2}px"></div>
|
||||||
|
<div class="name" style="display: none; bottom: #{config.lineHeight - 2}px">#{$('<div/>').text(annotation.text).html()}</div>
|
||||||
|
</div>
|
||||||
|
"""
|
||||||
|
html.push div
|
||||||
|
, true
|
|
@ -4,11 +4,12 @@ define [
|
||||||
"ide/editor/undo/UndoManager"
|
"ide/editor/undo/UndoManager"
|
||||||
"ide/editor/auto-complete/AutoCompleteManager"
|
"ide/editor/auto-complete/AutoCompleteManager"
|
||||||
"ide/editor/spell-check/SpellCheckManager"
|
"ide/editor/spell-check/SpellCheckManager"
|
||||||
|
"ide/editor/annotations/AnnotationsManager"
|
||||||
"ace/keyboard/vim"
|
"ace/keyboard/vim"
|
||||||
"ace/keyboard/emacs"
|
"ace/keyboard/emacs"
|
||||||
"ace/mode/latex"
|
"ace/mode/latex"
|
||||||
"ace/edit_session"
|
"ace/edit_session"
|
||||||
], (App, Ace, UndoManager, AutoCompleteManager, SpellCheckManager) ->
|
], (App, Ace, UndoManager, AutoCompleteManager, SpellCheckManager, AnnotationsManager) ->
|
||||||
LatexMode = require("ace/mode/latex").Mode
|
LatexMode = require("ace/mode/latex").Mode
|
||||||
EditSession = require('ace/edit_session').EditSession
|
EditSession = require('ace/edit_session').EditSession
|
||||||
|
|
||||||
|
@ -23,13 +24,25 @@ define [
|
||||||
sharejsDoc: "="
|
sharejsDoc: "="
|
||||||
lastUpdated: "="
|
lastUpdated: "="
|
||||||
spellCheckLanguage: "="
|
spellCheckLanguage: "="
|
||||||
|
cursorPosition: "="
|
||||||
|
annotations: "="
|
||||||
}
|
}
|
||||||
link: (scope, element, attrs) ->
|
link: (scope, element, attrs) ->
|
||||||
|
# Don't freak out if we're already in an apply callback
|
||||||
|
scope.$originalApply = scope.$apply
|
||||||
|
scope.$apply = (fn = () ->) ->
|
||||||
|
phase = @$root.$$phase
|
||||||
|
if (phase == '$apply' || phase == '$digest')
|
||||||
|
fn()
|
||||||
|
else
|
||||||
|
@$originalApply(fn);
|
||||||
|
|
||||||
editor = Ace.edit(element.find(".ace-editor-body")[0])
|
editor = Ace.edit(element.find(".ace-editor-body")[0])
|
||||||
|
|
||||||
autoCompleteManager = new AutoCompleteManager(scope, editor)
|
autoCompleteManager = new AutoCompleteManager(scope, editor)
|
||||||
spellCheckManager = new SpellCheckManager(scope, editor, element)
|
spellCheckManager = new SpellCheckManager(scope, editor, element)
|
||||||
undoManager = new UndoManager(scope, editor)
|
undoManager = new UndoManager(scope, editor)
|
||||||
|
annotationsManagaer = new AnnotationsManager(scope, editor)
|
||||||
|
|
||||||
# Prevert Ctrl|Cmd-S from triggering save dialog
|
# Prevert Ctrl|Cmd-S from triggering save dialog
|
||||||
editor.commands.addCommand
|
editor.commands.addCommand
|
||||||
|
@ -41,6 +54,11 @@ define [
|
||||||
editor.commands.removeCommand "showSettingsMenu"
|
editor.commands.removeCommand "showSettingsMenu"
|
||||||
editor.commands.removeCommand "foldall"
|
editor.commands.removeCommand "foldall"
|
||||||
|
|
||||||
|
editor.on "changeSelection", () ->
|
||||||
|
cursor = editor.getCursorPosition()
|
||||||
|
scope.$apply () ->
|
||||||
|
scope.cursorPosition = cursor
|
||||||
|
|
||||||
scope.$watch "theme", (value) ->
|
scope.$watch "theme", (value) ->
|
||||||
editor.setTheme("ace/theme/#{value}")
|
editor.setTheme("ace/theme/#{value}")
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
define [], () ->
|
||||||
|
class OnlineUsersManager
|
||||||
|
constructor: (@ide, @$scope) ->
|
||||||
|
@$scope.onlineUsers = {}
|
||||||
|
@$scope.onlineUserCursorAnnotations = {}
|
||||||
|
|
||||||
|
@$scope.$watch "editor.cursorPosition", (position) =>
|
||||||
|
console.log "CURSOR POSITION UPDATE", position
|
||||||
|
if position?
|
||||||
|
@sendCursorPositionUpdate()
|
||||||
|
|
||||||
|
@ide.socket.on "clientTracking.clientUpdated", (client) =>
|
||||||
|
console.log "REMOTE CURSOR POSITION UPDATE", client
|
||||||
|
if client.id != @ide.socket.socket.sessionid # Check it's not me!
|
||||||
|
@$scope.$apply () =>
|
||||||
|
@$scope.onlineUsers[client.id] = client
|
||||||
|
@updateCursorHighlights()
|
||||||
|
|
||||||
|
@ide.socket.on "clientTracking.clientDisconnected", (client_id) =>
|
||||||
|
@$scope.$apply () =>
|
||||||
|
delete @$scope.onlineUsers[client_id]
|
||||||
|
@updateCursorHighlights()
|
||||||
|
|
||||||
|
updateCursorHighlights: () ->
|
||||||
|
console.log "UPDATING CURSOR HIGHLIGHTS"
|
||||||
|
@$scope.onlineUserCursorAnnotations = {}
|
||||||
|
for client_id, client of @$scope.onlineUsers
|
||||||
|
doc_id = client.doc_id
|
||||||
|
@$scope.onlineUserCursorAnnotations[doc_id] ||= []
|
||||||
|
@$scope.onlineUserCursorAnnotations[doc_id].push {
|
||||||
|
text: client.name
|
||||||
|
cursor:
|
||||||
|
row: client.row
|
||||||
|
column: client.column
|
||||||
|
}
|
||||||
|
|
||||||
|
UPDATE_INTERVAL: 500
|
||||||
|
sendCursorPositionUpdate: () ->
|
||||||
|
if !@cursorUpdateTimeout?
|
||||||
|
console.log "CREATING DELAYED UPDATED"
|
||||||
|
@cursorUpdateTimeout = setTimeout ()=>
|
||||||
|
position = @$scope.editor.cursorPosition
|
||||||
|
doc_id = @$scope.editor.open_doc_id
|
||||||
|
|
||||||
|
@ide.socket.emit "clientTracking.updatePosition", {
|
||||||
|
row: position.row
|
||||||
|
column: position.column
|
||||||
|
doc_id: doc_id
|
||||||
|
}
|
||||||
|
|
||||||
|
delete @cursorUpdateTimeout
|
||||||
|
, @UPDATE_INTERVAL
|
||||||
|
else
|
||||||
|
console.log "NOT UPDATING"
|
||||||
|
|
||||||
|
|
|
@ -193,6 +193,28 @@
|
||||||
background-repeat: repeat-x;
|
background-repeat: repeat-x;
|
||||||
background-position: bottom left;
|
background-position: bottom left;
|
||||||
}
|
}
|
||||||
|
@cursor-color: rgb(14, 158, 0);
|
||||||
|
.remote-cursor {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
border-left: 2px solid @cursor-color;
|
||||||
|
.name {
|
||||||
|
font-size: 0.8em;
|
||||||
|
background-color: @cursor-color;
|
||||||
|
color: white;
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 3px 3px 3px 0;
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
}
|
||||||
|
.nubbin {
|
||||||
|
height: 6px;
|
||||||
|
width: 6px;
|
||||||
|
background-color: @cursor-color;
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.ui-layout-resizer {
|
.ui-layout-resizer {
|
||||||
|
|
Loading…
Reference in a new issue