diff --git a/services/web/app/views/project/editor/pdf.pug b/services/web/app/views/project/editor/pdf.pug index 960d4bf2c9..db4a0e9dd3 100644 --- a/services/web/app/views/project/editor/pdf.pug +++ b/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") diff --git a/services/web/public/coffee/ide/editor/Document.coffee b/services/web/public/coffee/ide/editor/Document.coffee index d1aa883734..229e791c67 100644 --- a/services/web/public/coffee/ide/editor/Document.coffee +++ b/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", diff --git a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee b/services/web/public/coffee/ide/editor/directives/aceEditor.coffee index 1cb527fc40..40ae0bb06f 100644 --- a/services/web/public/coffee/ide/editor/directives/aceEditor.coffee +++ b/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()) diff --git a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee b/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee index d06d5822a4..68a6649ef7 100644 --- a/services/web/public/coffee/ide/pdf/controllers/PdfController.coffee +++ b/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