overleaf/services/web/public/coffee/editor/Document.coffee
2014-02-12 10:23:40 +00:00

159 lines
4.2 KiB
CoffeeScript

define [
"editor/ShareJsDoc"
"libs/backbone"
], (ShareJsDoc) ->
class Document
@getDocument: (ide, doc_id) ->
@openDocs ||= {}
if !@openDocs[doc_id]?
@openDocs[doc_id] = new Document(ide, doc_id)
return @openDocs[doc_id]
constructor: (@ide, @doc_id) ->
@connected = @ide.socket.socket.connected
@joined = false
@wantToBeJoined = false
@_bindToEditorEvents()
@_bindToSocketEvents()
attachToAce: (ace) ->
@doc?.attachToAce(ace)
detachFromAce: () ->
@doc?.detachFromAce()
getSnapshot: () ->
@doc?.getSnapshot()
getType: () ->
@doc?.getType()
_bindToSocketEvents: () ->
@_onUpdateAppliedHandler = (update) => @_onUpdateApplied(update)
@ide.socket.on "otUpdateApplied", @_onUpdateAppliedHandler
@_onErrorHandler = (error, update) => @_onError(error, update)
@ide.socket.on "otUpdateError", @_onErrorHandler
@_onDisconnectHandler = (error) => @_onDisconnect(error)
@ide.socket.on "disconnect", @_onDisconnectHandler
_bindToEditorEvents: () ->
@_onReconnectHandler = (update) => @_onReconnect(update)
@ide.on "afterJoinProject", @_onReconnectHandler
unBindFromSocketEvents: () ->
@ide.socket.removeListener "otUpdateApplied", @_onUpdateAppliedHandler
@ide.socket.removeListener "otUpdateError", @_onUpdateErrorHandler
@ide.socket.removeListener "disconnect", @_onDisconnectHandler
unBindFromEditorEvents: () ->
@ide.off "afterJoinProject", @_onReconnectHandler
leaveAndCleanUp: () ->
@leave (error) =>
@_cleanUp()
join: (callback = (error) ->) ->
@wantToBeJoined = true
@_cancelLeave()
if @connected
return @_joinDoc callback
else
@_joinCallbacks ||= []
@_joinCallbacks.push callback
leave: (callback = (error) ->) ->
@wantToBeJoined = false
@_cancelJoin()
if (@doc? and @doc.hasBufferedOps())
@_leaveCallbacks ||= []
@_leaveCallbacks.push callback
else if !@connected
callback()
else
@_leaveDoc(callback)
_cancelLeave: () ->
if @_leaveCallbacks?
delete @_leaveCallbacks
_cancelJoin: () ->
if @_joinCallbacks?
delete @_joinCallbacks
_onUpdateApplied: (update) ->
if update?.doc == @doc_id and @doc?
@doc.processUpdateFromServer update
if !@wantToBeJoined
@leave()
_onDisconnect: () ->
@connected = false
@joined = false
@doc?.updateConnectionState "disconnected"
_onReconnect: () ->
@connected = true
if @wantToBeJoined or @doc?.hasBufferedOps()
@_joinDoc (error) =>
return @_onError(error) if error?
@doc.updateConnectionState "ok"
@doc.flushPendingOps()
@_callJoinCallbacks()
_callJoinCallbacks: () ->
for callback in @_joinCallbacks or []
callback()
delete @_joinCallbacks
_joinDoc: (callback = (error) ->) ->
if @doc?
@ide.socket.emit 'joinDoc', @doc_id, @doc.getVersion(), (error, docLines, version, updates) =>
return callback(error) if error?
@joined = true
@doc.catchUp( updates )
callback()
else
@ide.socket.emit 'joinDoc', @doc_id, (error, docLines, version) =>
return callback(error) if error?
@joined = true
@doc = new ShareJsDoc @doc_id, docLines, version, @ide.socket
@_bindToShareJsDocEvents()
callback()
_leaveDoc: (callback = (error) ->) ->
@ide.socket.emit 'leaveDoc', @doc_id, (error) =>
return callback(error) if error?
@joined = false
for callback in @_leaveCallbacks or []
callback(error)
delete @_leaveCallbacks
callback(error)
_cleanUp: () ->
delete Document.openDocs[@doc_id]
@unBindFromEditorEvents()
@unBindFromSocketEvents()
_bindToShareJsDocEvents: () ->
@doc.on "error", (error) => @_onError error
@doc.on "externalUpdate", () => @trigger "externalUpdate"
@doc.on "remoteop", () => @trigger "remoteop"
@doc.on "op:sent", () => @trigger "op:sent"
@doc.on "op:acknowledged", () => @trigger "op:acknowledged"
_onError: (error) ->
console.error "ShareJS error", error
heap?.track "shareJsError", { error: (error.message or error), transport: ide.socket.socket.transport.name }
@ide.socket.disconnect()
@doc?.clearInflightAndPendingOps()
@_cleanUp()
@trigger "error", error
_.extend(Document::, Backbone.Events)
return Document