EditorManager.coffee 5.4 KB

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