diff --git a/extension.json b/extension.json index 1873711e..ce792bc1 100644 --- a/extension.json +++ b/extension.json @@ -432,6 +432,10 @@ "WikiEditorRealtimePreviewDebounce": { "description": "Debounce time in milliseconds for the Realtime Preview feature.", "value": 2500 + }, + "WikiEditorRealtimeDisableDuration": { + "description": "Average number of milliseconds after which to automatically disable Realtime Preview.", + "value": 10000 } }, "manifest_version": 2 diff --git a/includes/Hooks.php b/includes/Hooks.php index a0b8b886..0a786204 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -358,6 +358,7 @@ class Hooks implements 'magicWords' => self::getMagicWords(), 'signature' => self::getSignatureMessage( $context ), 'realtimeDebounce' => $config->get( 'WikiEditorRealtimePreviewDebounce' ), + 'realtimeDisableDuration' => $config->get( 'WikiEditorRealtimeDisableDuration' ), ]; } diff --git a/modules/realtimepreview/RealtimePreview.js b/modules/realtimepreview/RealtimePreview.js index 09aabbb3..8a881cd7 100644 --- a/modules/realtimepreview/RealtimePreview.js +++ b/modules/realtimepreview/RealtimePreview.js @@ -26,6 +26,8 @@ function RealtimePreview() { // Used to ensure we wait for a response before making new requests. this.isPreviewing = false; this.previewPending = false; + // Used to average response times and automatically disable realtime preview if it's very slow. + this.responseTimes = []; } /** @@ -131,6 +133,30 @@ RealtimePreview.prototype.showError = function ( $msg ) { this.errorLayout.toggle( true ); }; +/** + * @private + * @param {number} time + */ +RealtimePreview.prototype.checkResponseTimes = function ( time ) { + this.responseTimes.push( Date.now() - time ); + if ( this.responseTimes.length < 3 ) { + return; + } + + var totalResponseTime = this.responseTimes.reduce( function ( a, b ) { + return a + b; + }, 0 ); + + if ( ( totalResponseTime / this.responseTimes.length ) > this.configData.realtimeDisableDuration ) { + // TODO: switch to the 'manual preview' workflow once designs/behaviour is finalized. + this.showError( + $( '
' ).text( '[PLACEHOLDER] Realtime preview is too slow' ) + ); + } + + this.responseTimes.shift(); +}; + /** * @private */ @@ -147,6 +173,8 @@ RealtimePreview.prototype.doRealtimePreview = function () { var loadingSelectors = this.pagePreview.getLoadingSelectors(); loadingSelectors.push( '.ext-WikiEditor-realtimepreview-preview' ); this.errorLayout.toggle( false ); + var time = Date.now(); + this.pagePreview.doPreview( { $previewNode: this.$previewNode, $spinnerNode: false, @@ -157,6 +185,7 @@ RealtimePreview.prototype.doRealtimePreview = function () { }.bind( this ) ).always( function () { this.twoPaneLayout.getPane2().removeClass( 'ext-WikiEditor-twopanes-loading' ); this.isPreviewing = false; + this.checkResponseTimes( time ); if ( this.previewPending ) { this.previewPending = false;