Просмотр исходного кода

Show saving dialog based on whether there are inflight ops, and show a warning when leaving the page if there are

James Allen 12 лет назад
Родитель
Сommit
a12716ab6b

+ 35 - 2
services/web/public/coffee/editor/Document.coffee

@@ -10,6 +10,11 @@ define [
 				@openDocs[doc_id] = new Document(ide, doc_id)
 			return @openDocs[doc_id]
 
+		@hasUnsavedChanges: () ->
+			for doc_id, doc of (@openDocs or {})
+				return true if doc.hasBufferedOps()
+			return false
+
 		constructor: (@ide, @doc_id) ->
 			@connected = @ide.socket.socket.connected
 			@joined = false
@@ -25,8 +30,8 @@ define [
 
 		detachFromAce: () ->
 			@doc?.detachFromAce()
-			editorDoc = @ace.getSession().getDocument()
-			editorDoc.off "change", @_checkConsistency
+			editorDoc = @ace?.getSession().getDocument()
+			editorDoc?.off "change", @_checkConsistency
 
 		_checkConsistency: () ->
 			editorValue = @ace?.getValue()
@@ -40,6 +45,15 @@ define [
 		getType: () ->
 			@doc?.getType()
 
+		getInflightOp: () ->
+			@doc?.getInflightOp()
+
+		getPendingOp: () ->
+			@doc?.getPendingOp()
+
+		hasBufferedOps: () ->
+			@doc?.hasBufferedOps()
+
 		_bindToSocketEvents: () ->
 			@_onUpdateAppliedHandler = (update) => @_onUpdateApplied(update)
 			@ide.socket.on "otUpdateApplied", @_onUpdateAppliedHandler
@@ -84,6 +98,25 @@ define [
 			else
 				@_leaveDoc(callback)
 
+		pollSavedStatus: () ->
+			# returns false if doc has ops waiting to be acknowledged or
+			# sent that haven't changed since the last time we checked.
+			# Otherwise returns true.
+			inflightOp = @getInflightOp()
+			pendingOp = @getPendingOp()
+			if !inflightOp? and !pendingOp?
+				# there's nothing going on
+				saved = true
+			else if inflightOp == @oldInflightOp
+				saved = false
+			else if pendingOp?
+				saved = false
+			else
+				saved = true
+
+			@oldInflightOp = inflightOp
+			return saved
+
 		_cancelLeave: () ->
 			if @_leaveCallbacks?
 				delete @_leaveCallbacks

+ 3 - 5
services/web/public/coffee/editor/Editor.coffee

@@ -210,11 +210,6 @@ define [
 				callback null, @document
 
 		_bindToDocumentEvents: (document) ->
-			document.on "op:sent", () =>
-				@ide.savingAreaManager.saving()
-			document.on "op:acknowledged", () =>
-				@ide.savingAreaManager.saved()
-
 			document.on "remoteop", () =>
 				@undoManager.nextUpdateIsRemote = true
 
@@ -364,3 +359,6 @@ define [
 
 		disable: () ->
 			@enabled = false
+
+		hasUnsavedChanges: () ->
+			Document.hasUnsavedChanges()

+ 3 - 0
services/web/public/coffee/editor/ShareJsDoc.coffee

@@ -89,6 +89,9 @@ define [
 		hasBufferedOps: () ->
 			@_doc.inflightOp? or @_doc.pendingOp?
 
+		getInflightOp: () -> @_doc.inflightOp
+		getPendingOp: () -> @_doc.pendingOp
+
 		attachToAce: (ace) -> @_doc.attach_ace(ace)
 		detachFromAce: () -> @_doc.detach_ace?()
 	

+ 3 - 18
services/web/public/coffee/ide.coffee

@@ -11,6 +11,7 @@ define [
 	"ide/TabManager"
 	"ide/LayoutManager"
 	"ide/FileUploadManager"
+	"ide/SavingAreaManager"
 	"spelling/SpellingManager"
 	"search/SearchManager"
 	"models/Project"
@@ -45,6 +46,7 @@ define [
 	TabManager,
 	LayoutManager,
 	FileUploadManager,
+	SavingAreaManager,
 	SpellingManager,
 	SearchManager,
 	Project,
@@ -205,22 +207,5 @@ define [
 	ide.tourManager = new IdeTour ide
 	ide.debugManager = new DebugManager(ide)
 
-	ide.savingAreaManager =
-		$savingArea : $('#saving-area')
-		timeOut: undefined
-		saved:->
-			@clearTimeout()
-			$("#savingProblems").hide()
-		saving:->
-			return if @timeOut?
-			@clearTimeout()
-			@timeOut = setTimeout((=>
-				ga?('send', 'event', 'editor-interaction', 'notification-shown', "saving")
-				$("#savingProblems").show()
-			), 3000)
-
-		clearTimeout:->
-			if @timeOut?
-				clearTimeout @timeOut
-			delete @timeOut
+	ide.savingAreaManager = new SavingAreaManager(ide)
 

+ 30 - 0
services/web/public/coffee/ide/SavingAreaManager.coffee

@@ -0,0 +1,30 @@
+define [
+], () ->
+	class SavingAreaManager
+		$el: $('#saving-area')
+
+		constructor: (@ide) ->
+			@unsavedSeconds = 0
+			setInterval () =>
+				@pollSavedStatus()
+			, 1000
+
+			$(window).bind 'beforeunload', () =>
+				@warnAboutUnsavedChanges()
+
+		pollSavedStatus: () ->
+			saved = @ide.editor.document.pollSavedStatus()
+			if saved
+				@unsavedSeconds = 0
+			else
+				@unsavedSeconds += 1
+
+			if @unsavedSeconds >= 4
+				$("#savingProblems").text("Saving... (#{@unsavedSeconds} seconds of unsaved changes)")
+				$("#savingProblems").show()
+			else
+				$("#savingProblems").hide()
+
+		warnAboutUnsavedChanges: () ->
+			if @ide.editor.hasUnsavedChanges()
+				return "You have unsaved changes. If you leave now they will not be saved."