EditorManager.coffee 5.7 KB

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