EditorManager.coffee 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. define [
  2. "ide/editor/Document"
  3. "ide/editor/directives/aceEditor"
  4. "ide/editor/controllers/SavingNotificationController"
  5. ], (Document) ->
  6. class EditorManager
  7. constructor: (@ide, @$scope) ->
  8. @$scope.editor = {
  9. sharejs_doc: null
  10. open_doc_id: null
  11. open_doc_name: null
  12. opening: true
  13. trackChanges: false
  14. wantTrackChanges: false
  15. }
  16. @$scope.$on "entity:selected", (event, entity) =>
  17. if (@$scope.ui.view != "history" and entity.type == "doc")
  18. @openDoc(entity)
  19. @$scope.$on "entity:deleted", (event, entity) =>
  20. if @$scope.editor.open_doc_id == entity.id
  21. return if !@$scope.project.rootDoc_id
  22. doc = @ide.fileTreeManager.findEntityById(@$scope.project.rootDoc_id)
  23. return if !doc?
  24. @openDoc(doc)
  25. initialized = false
  26. @$scope.$on "file-tree:initialized", () =>
  27. if !initialized
  28. initialized = true
  29. @autoOpenDoc()
  30. @$scope.$on "flush-changes", () =>
  31. Document.flushAll()
  32. @$scope.$watch "editor.wantTrackChanges", (value) =>
  33. return if !value?
  34. @_syncTrackChangesState(@$scope.editor.sharejs_doc)
  35. autoOpenDoc: () ->
  36. open_doc_id =
  37. @ide.localStorage("doc.open_id.#{@$scope.project_id}") or
  38. @$scope.project.rootDoc_id
  39. return if !open_doc_id?
  40. doc = @ide.fileTreeManager.findEntityById(open_doc_id)
  41. return if !doc?
  42. @openDoc(doc)
  43. openDocId: (doc_id, options = {}) ->
  44. doc = @ide.fileTreeManager.findEntityById(doc_id)
  45. return if !doc?
  46. @openDoc(doc, options)
  47. openDoc: (doc, options = {}) ->
  48. sl_console.log "[openDoc] Opening #{doc.id}"
  49. @$scope.ui.view = "editor"
  50. done = () =>
  51. if options.gotoLine?
  52. # allow Ace to display document before moving, delay until next tick
  53. # added delay to make this happen later that gotoStoredPosition in
  54. # CursorPositionManager
  55. setTimeout () =>
  56. @$scope.$broadcast "editor:gotoLine", options.gotoLine, options.gotoColumn
  57. , 0
  58. else if options.gotoOffset?
  59. setTimeout () =>
  60. @$scope.$broadcast "editor:gotoOffset", options.gotoOffset
  61. , 0
  62. if doc.id == @$scope.editor.open_doc_id and !options.forceReopen
  63. @$scope.$apply () =>
  64. done()
  65. return
  66. @$scope.editor.open_doc_id = doc.id
  67. @$scope.editor.open_doc_name = doc.name
  68. @ide.localStorage "doc.open_id.#{@$scope.project_id}", doc.id
  69. @ide.fileTreeManager.selectEntity(doc)
  70. @$scope.editor.opening = true
  71. @_openNewDocument doc, (error, sharejs_doc) =>
  72. if error?
  73. @ide.showGenericMessageModal(
  74. "Error opening document"
  75. "Sorry, something went wrong opening this document. Please try again."
  76. )
  77. return
  78. @_syncTrackChangesState(sharejs_doc)
  79. @$scope.$broadcast "doc:opened"
  80. @$scope.$apply () =>
  81. @$scope.editor.opening = false
  82. @$scope.editor.sharejs_doc = sharejs_doc
  83. done()
  84. _openNewDocument: (doc, callback = (error, sharejs_doc) ->) ->
  85. sl_console.log "[_openNewDocument] Opening..."
  86. current_sharejs_doc = @$scope.editor.sharejs_doc
  87. if current_sharejs_doc?
  88. sl_console.log "[_openNewDocument] Leaving existing open doc..."
  89. current_sharejs_doc.leaveAndCleanUp()
  90. @_unbindFromDocumentEvents(current_sharejs_doc)
  91. new_sharejs_doc = Document.getDocument @ide, doc.id
  92. new_sharejs_doc.join (error) =>
  93. return callback(error) if error?
  94. @_bindToDocumentEvents(doc, new_sharejs_doc)
  95. callback null, new_sharejs_doc
  96. _bindToDocumentEvents: (doc, sharejs_doc) ->
  97. sharejs_doc.on "error", (error, meta) =>
  98. if error?.message?
  99. message = error.message
  100. else if typeof error == "string"
  101. message = error
  102. else
  103. message = ""
  104. if message.match "maxDocLength"
  105. @ide.showGenericMessageModal(
  106. "Document Too Long"
  107. "Sorry, this file is too long to be edited manually. Please upload it directly."
  108. )
  109. else if message.match "too many comments or tracked changes"
  110. @ide.showGenericMessageModal(
  111. "Too many comments or tracked changes"
  112. "Sorry, this file has too many comments or tracked changes. Please try accepting or rejecting some existing changes, or resolving and deleting some comments."
  113. )
  114. else
  115. @ide.socket.disconnect()
  116. @ide.reportError(error, meta)
  117. @ide.showGenericMessageModal(
  118. "Out of sync"
  119. "Sorry, this file has gone out of sync and we need to do a full refresh. <br> <a href='/learn/Kb/Editor_out_of_sync_problems'>Please see this help guide for more information</a>"
  120. )
  121. @openDoc(doc, forceReopen: true)
  122. sharejs_doc.on "externalUpdate", (update) =>
  123. return if @_ignoreExternalUpdates
  124. @ide.showGenericMessageModal(
  125. "Document Updated Externally"
  126. "This document was just updated externally. Any recent changes you have made may have been overwritten. To see previous versions please look in the history."
  127. )
  128. _unbindFromDocumentEvents: (document) ->
  129. document.off()
  130. getCurrentDocValue: () ->
  131. @$scope.editor.sharejs_doc?.getSnapshot()
  132. getCurrentDocId: () ->
  133. @$scope.editor.open_doc_id
  134. startIgnoringExternalUpdates: () ->
  135. @_ignoreExternalUpdates = true
  136. stopIgnoringExternalUpdates: () ->
  137. @_ignoreExternalUpdates = false
  138. _syncTimeout: null
  139. _syncTrackChangesState: (doc) ->
  140. return if !doc?
  141. if @_syncTimeout?
  142. clearTimeout @_syncTimeout
  143. @_syncTimeout = null
  144. want = @$scope.editor.wantTrackChanges
  145. have = doc.getTrackingChanges()
  146. if want == have
  147. @$scope.editor.trackChanges = want
  148. return
  149. do tryToggle = () =>
  150. saved = !doc.getInflightOp()? and !doc.getPendingOp()?
  151. if saved
  152. doc.setTrackingChanges(want)
  153. @$scope.$apply () =>
  154. @$scope.editor.trackChanges = want
  155. else
  156. @_syncTimeout = setTimeout tryToggle, 100