EditorManager.coffee 5.6 KB

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