DLynch has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/250904

Change subject: Add ve.Scheduler, use it to avoid conflict in ve.ui.Tool
......................................................................

Add ve.Scheduler, use it to avoid conflict in ve.ui.Tool

We have an occasional muddle of setTimeout calls which make it hard to
wait for a clean state sometimes. So, create a Scheduler utility that
handles waiting a reasonably efficient length of time before running
whatever action is required.

As a proof of concept, use it to avoid an issue that ve.Tool has with
attempting to perform certain actions while inspectors are open.

This is the bare-minimum implementation. In the future, we may want to
make it smarter so that it can track a setTimeout stack within the
action it performs, rather than just blindly polling a test function.

Bug: T117620
Bug: T76717
Change-Id: Ib1d6a702f73cd6c99fd524761115dfff27a3199d
---
M build/modules.json
M demos/ve/desktop.html
M demos/ve/mobile.html
M src/ui/ve.ui.Tool.js
A src/ve.Scheduler.js
M tests/index.html
6 files changed, 78 insertions(+), 2 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor 
refs/changes/04/250904/1

diff --git a/build/modules.json b/build/modules.json
index 7779105..971b7a2 100644
--- a/build/modules.json
+++ b/build/modules.json
@@ -209,6 +209,7 @@
                        "src/ve.LeafNode.js",
                        "src/ve.Document.js",
                        "src/ve.EventSequencer.js",
+                       "src/ve.Scheduler.js",
                        { "file": "src/ve.Filibuster.js", "debug": true },
                        "src/dm/ve.dm.js",
                        "src/dm/ve.dm.Model.js",
diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html
index 39f43a7..7cf4a79 100644
--- a/demos/ve/desktop.html
+++ b/demos/ve/desktop.html
@@ -170,6 +170,7 @@
                <script src="../../src/ve.LeafNode.js"></script>
                <script src="../../src/ve.Document.js"></script>
                <script src="../../src/ve.EventSequencer.js"></script>
+               <script src="../../src/ve.Scheduler.js"></script>
                <script src="../../src/ve.Filibuster.js"></script>
                <script src="../../src/dm/ve.dm.js"></script>
                <script src="../../src/dm/ve.dm.Model.js"></script>
diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html
index 8f40031..ccdab84 100644
--- a/demos/ve/mobile.html
+++ b/demos/ve/mobile.html
@@ -172,6 +172,7 @@
                <script src="../../src/ve.LeafNode.js"></script>
                <script src="../../src/ve.Document.js"></script>
                <script src="../../src/ve.EventSequencer.js"></script>
+               <script src="../../src/ve.Scheduler.js"></script>
                <script src="../../src/ve.Filibuster.js"></script>
                <script src="../../src/dm/ve.dm.js"></script>
                <script src="../../src/dm/ve.dm.Model.js"></script>
diff --git a/src/ui/ve.ui.Tool.js b/src/ui/ve.ui.Tool.js
index a3fe850..154113d 100644
--- a/src/ui/ve.ui.Tool.js
+++ b/src/ui/ve.ui.Tool.js
@@ -79,9 +79,22 @@
  * @inheritdoc
  */
 ve.ui.Tool.prototype.onSelect = function () {
-       var command = this.getCommand();
+       var command = this.getCommand(),
+               surface = this.toolbar.getSurface();
        if ( command instanceof ve.ui.Command ) {
-               command.execute( this.toolbar.getSurface() );
+               ve.scheduler.call(
+                       function () {
+                               if ( surface.context.inspector ) {
+                                       surface.context.inspector.close();
+                               }
+                       }, function () {
+                               // Make sure the inspector has left the 
context, at which point
+                               // all its cleanup should be done
+                               return !surface.context.inspector;
+                       }
+               ).then( function () {
+                       command.execute( surface );
+               } );
        }
        if ( this.constructor.static.deactivateOnSelect ) {
                this.setActive( false );
diff --git a/src/ve.Scheduler.js b/src/ve.Scheduler.js
new file mode 100644
index 0000000..7bd7875
--- /dev/null
+++ b/src/ve.Scheduler.js
@@ -0,0 +1,59 @@
+/*!
+ * VisualEditor Scheduler class.
+ *
+ * @copyright 2011-2015 VisualEditor Team and others; see 
http://ve.mit-license.org
+ */
+
+/**
+ * @class
+ *
+ * @constructor
+ */
+ve.Scheduler = function VeScheduler() {
+       // TODO: If we decide to start tracking setTimeout calls within 
actions, we'll
+       // need to keep state here.
+ };
+
+/* Inheritance */
+
+OO.initClass( ve.Scheduler );
+
+/* Methods */
+
+/**
+ * Perform an action and await a callback
+ *
+ * The signature of this function is designed to let you leave signals about 
your intent.
+ * You pass the action with side-effects in, and explain the conditions that 
must be met
+ * for further actions to be taken.
+ *
+ * @param {Function} immediateAction Action to take whose status we want to 
track
+ * @param {Function} completionTest Tests whether action is complete; ideally 
very cheap
+ * @param {number} [delayHint] Optional hint about how long to wait between 
tests
+ * @return {jQuery.Promise} Promise that resolves when the completionTest 
returns true.
+ *         Note that this _could_ already be resolved when it's returned, so 
there's no
+ *         guarantee that your `then` call on it will be delayed.
+ */
+ve.Scheduler.prototype.call = function ( immediateAction, completionTest, 
delayHint ) {
+       var deferred = $.Deferred(),
+               testThenAct = function () {
+                       if ( completionTest() ) {
+                               deferred.resolve();
+                               return;
+                       }
+                       setTimeout( testThenAct, delayHint || 0 );
+               };
+
+       // In the future, we may want to expand this to track whether other 
async calls
+       // were made within the action.
+       immediateAction();
+
+       // Spin up the test cycle
+       testThenAct();
+
+       return deferred.promise();
+};
+
+/* Initialization */
+
+ve.scheduler = new ve.Scheduler();
diff --git a/tests/index.html b/tests/index.html
index 3310e91..c419f2b 100644
--- a/tests/index.html
+++ b/tests/index.html
@@ -98,6 +98,7 @@
                <script src="../src/ve.LeafNode.js"></script>
                <script src="../src/ve.Document.js"></script>
                <script src="../src/ve.EventSequencer.js"></script>
+               <script src="../src/ve.Scheduler.js"></script>
                <script src="../src/dm/ve.dm.js"></script>
                <script src="../src/dm/ve.dm.Model.js"></script>
                <script src="../src/dm/ve.dm.ModelFactory.js"></script>

-- 
To view, visit https://gerrit.wikimedia.org/r/250904
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib1d6a702f73cd6c99fd524761115dfff27a3199d
Gerrit-PatchSet: 1
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: DLynch <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to