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

Merge pull request #4 from sharelatex/as-client-auto-compile

Client-side auto compile
Alasdair Smith 9 лет назад
Родитель
Сommit
66bed67270

+ 11 - 0
services/web/app/views/project/editor/pdf.pug

@@ -26,6 +26,17 @@ div.full-size.pdf(ng-controller="PdfController")
 			)
 				span.caret
 			ul.dropdown-menu.dropdown-menu-left
+				// Only show on beta program?
+				if user.betaProgram
+					li.dropdown-header #{translate("auto_compile")}
+					li
+						a(href, ng-click="autocompile_enabled = true")
+							i.fa.fa-fw(ng-class="{'fa-check': autocompile_enabled}")
+							|  #{translate('on')}
+					li
+						a(href, ng-click="autocompile_enabled = false")
+							i.fa.fa-fw(ng-class="{'fa-check': !autocompile_enabled}")
+							|  #{translate('off')}
 				li.dropdown-header #{translate("compile_mode")}
 				li
 					a(href, ng-click="draft = false")

+ 3 - 0
services/web/public/coffee/ide/editor/Document.coffee

@@ -309,6 +309,9 @@ define [
 				@ide.pushEvent "op:acknowledged",
 					doc_id: @doc_id
 					op: op
+				@ide.$scope.$emit "ide:opAcknowledged",
+					doc_id: @doc_id
+					op: op
 				@trigger "op:acknowledged"
 			@doc.on "op:timeout", (op) =>
 				@ide.pushEvent "op:timeout",

+ 15 - 0
services/web/public/coffee/ide/editor/directives/aceEditor.coffee

@@ -374,6 +374,21 @@ define [
 					if scope.eventsBridge?
 						session.on "changeScrollTop", onScroll
 
+					$rootScope.hasLintingError = false
+					session.on('changeAnnotation', () ->
+						# Both linter errors and compile logs are set as error annotations,
+						# however when the user types something, the compile logs are
+						# replaced with linter errors. When we check for lint errors before
+						# autocompile we are guaranteed to get linter errors
+						hasErrors = session
+							.getAnnotations()
+							.filter((annotation) -> annotation.type != 'info')
+							.length > 0
+
+						if ($rootScope.hasLintingError != hasErrors)
+							$rootScope.hasLintingError = hasErrors
+					)
+
 					setTimeout () ->
 						# Let any listeners init themselves
 						onScroll(editor.renderer.getScrollTop())

+ 42 - 1
services/web/public/coffee/ide/pdf/controllers/PdfController.coffee

@@ -5,8 +5,10 @@ define [
 	"libs/bib-log-parser"
 	"services/log-hints-feedback"
 ], (App, Ace, HumanReadableLogs, BibLogParser) ->
-	App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) ->
+	AUTO_COMPILE_TIMEOUT = 5000
+	OP_ACKNOWLEDGEMENT_TIMEOUT = 1100
 
+	App.controller "PdfController", ($scope, $http, ide, $modal, synctex, event_tracking, logHintsFeedback, localStorage) ->
 		# enable per-user containers by default
 		perUserCompile = true
 		autoCompile = true
@@ -73,6 +75,43 @@ define [
 			$scope.pdf.view = 'errors'
 			$scope.pdf.renderingError = true
 
+		autoCompileTimeout = null
+		triggerAutoCompile = () ->
+			return if autoCompileTimeout
+
+			timeSinceLastCompile = Date.now() - $scope.recompiledAt
+			# If time is non-monotonic, assume that the user's system clock has been
+			# changed and continue with recompile
+			isTimeNonMonotonic = timeSinceLastCompile < 0
+
+			if isTimeNonMonotonic || timeSinceLastCompile >= AUTO_COMPILE_TIMEOUT
+				if (!ide.$scope.hasLintingError)
+					$scope.recompile(isBackgroundAutoCompile: true)
+			else
+				# Extend remainder of timeout
+				autoCompileTimeout = setTimeout () ->
+					autoCompileTimeout = null
+					triggerAutoCompile()
+				, AUTO_COMPILE_TIMEOUT - timeSinceLastCompile
+
+		autoCompileListener = null
+		toggleAutoCompile = (enabling) ->
+			if enabling
+				autoCompileListener = ide.$scope.$on "ide:opAcknowledged", _.debounce(triggerAutoCompile, OP_ACKNOWLEDGEMENT_TIMEOUT)
+			else
+				autoCompileListener() if autoCompileListener
+				autoCompileListener = null
+
+		$scope.autocompile_enabled = localStorage("autocompile_enabled:#{$scope.project_id}") or false
+		$scope.$watch "autocompile_enabled", (newValue, oldValue) ->
+			if newValue? and oldValue != newValue
+				localStorage("autocompile_enabled:#{$scope.project_id}", newValue)
+				toggleAutoCompile(newValue)
+				event_tracking.sendMB "autocompile-setting-changed", newValue
+
+		if window.user?.betaProgram and $scope.autocompile_enabled
+			toggleAutoCompile(true)
+
 		# abort compile if syntax checks fail
 		$scope.stop_on_validation_error = localStorage("stop_on_validation_error:#{$scope.project_id}")
 		$scope.stop_on_validation_error ?= true # turn on for all users by default
@@ -401,6 +440,8 @@ define [
 					$scope.pdf.renderingError = false
 					$scope.pdf.error = true
 					$scope.pdf.view = 'errors'
+				.finally () ->
+					$scope.recompiledAt = Date.now()
 
 		# This needs to be public.
 		ide.$scope.recompile = $scope.recompile