Bug 1468343 - Part 1: Make graph to address infinity duration. r?pbro draft
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 26 Jun 2018 12:39:48 +0900
changeset 810559 005165435abfa6cf0324a2e3230f8d010f7e439f
parent 810529 ace6a059941b93ef35a15ae2fcccbb0a84abb341
child 810560 2a4b7f63505a9d6e997e7a5040283ed6facec000
child 810598 22aa40759a2b04fb877c3d96790c78adfe50c2ea
push id114035
push userbmo:dakatsuka@mozilla.com
push dateTue, 26 Jun 2018 05:17:45 +0000
reviewerspbro
bugs1468343
milestone63.0a1
Bug 1468343 - Part 1: Make graph to address infinity duration. r?pbro MozReview-Commit-ID: Cc5a55Qglpi
devtools/client/inspector/animation/components/graph/TimingPath.js
devtools/client/inspector/animation/utils/timescale.js
devtools/client/themes/animation.css
--- a/devtools/client/inspector/animation/components/graph/TimingPath.js
+++ b/devtools/client/inspector/animation/components/graph/TimingPath.js
@@ -39,16 +39,21 @@ class TimingPath extends PureComponent {
       // Move to forward the starting point for negative delay.
       iterationStart += negativeDelayCount;
       // Consume iteration count by negative delay.
       if (iterationCount !== Infinity) {
         iterationCount -= negativeDelayCount;
       }
     }
 
+    if (state.duration === Infinity) {
+      this.renderInfinityDuration(pathList, state, mainIterationStartTime, helper);
+      return pathList;
+    }
+
     // Append 1st section of iterations,
     // This section is only useful in cases where iterationStart has decimals.
     // e.g.
     // if { iterationStart: 0.25, iterations: 3 }, firstSectionCount is 0.75.
     const firstSectionCount = iterationStart % 1 === 0
                             ? 0
                             : Math.min(iterationCount, 1) - iterationStart % 1;
     if (firstSectionCount) {
@@ -283,16 +288,42 @@ class TimingPath extends PureComponent {
             d: helper.toPathString(segments),
           }
         )
       );
     }
   }
 
   /**
+   * Render infinity duration.
+   *
+   * @param {Array} pathList
+   *        Add rendered <path> elements to this array.
+   * @param {Object} state
+   *        State of animation.
+   * @param {Number} mainIterationStartTime
+   *        Starting time of main iteration.
+   * @param {SummaryGraphHelper} helper
+   *        Instance of SummaryGraphHelper.
+   */
+  renderInfinityDuration(pathList, state, mainIterationStartTime, helper) {
+    const startSegment = helper.getSegment(mainIterationStartTime);
+    const endSegment = { x: helper.totalDuration, y: startSegment.y };
+    const segments = [startSegment, endSegment];
+    pathList.push(
+      dom.path(
+        {
+          className: "animation-iteration-path infinity-duration",
+          d: helper.toPathString(segments),
+        }
+      )
+    );
+  }
+
+  /**
    * Render 'endDelay' part in animation and add a <path> element to given pathList.
    *
    * @param {Array} pathList
    *        Add rendered <path> element to this array.
    * @param {Object} state
    *        State of animation.
    * @param {Number} mainIterationStartTime
    *        Starting time of main iteration.
--- a/devtools/client/inspector/animation/utils/timescale.js
+++ b/devtools/client/inspector/animation/utils/timescale.js
@@ -35,20 +35,32 @@ class TimeScale {
         duration,
         endDelay = 0,
         iterationCount,
         playbackRate,
       } = animation.state;
 
       const toRate = v => v / playbackRate;
       const startTime = createdTime + toRate(Math.min(delay, 0));
-      const endTime = createdTime +
-                      toRate(delay +
-                             duration * (iterationCount || 1) +
-                             Math.max(endDelay, 0));
+      let endTime = 0;
+
+      if (duration === Infinity) {
+        // Set endTime so as to enable the scrubber with keeping the consinstency of UI
+        // even the duration was Infinity. In case of delay is longer than zero, handle
+        // the graph duration as double of the delay amount. In case of no delay, handle
+        // the duration as 1ms which is short enough so as to make the scrubber movable
+        // and the limited duration is prioritized.
+        endTime = createdTime + (delay > 0 ? delay * 2 : 1);
+      } else {
+        endTime = createdTime +
+                  toRate(delay +
+                         duration * (iterationCount || 1) +
+                         Math.max(endDelay, 0));
+      }
+
       minStartTime = Math.min(minStartTime, startTime);
       maxEndTime = Math.max(maxEndTime, endTime);
       animationsCurrentTime =
         Math.max(animationsCurrentTime, createdTime + toRate(currentTime));
     }
 
     this.minStartTime = minStartTime;
     this.maxEndTime = maxEndTime;
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -260,16 +260,21 @@ select.playback-rate-selector.devtools-b
   transform: scale(1, -1);
   vector-effect: non-scaling-stroke;
 }
 
 .animation-effect-timing-path path.infinity:nth-child(n+2) {
   opacity: 0.3;
 }
 
+.animation-computed-timing-path path.infinity-duration,
+.animation-effect-timing-path path.infinity-duration {
+  mask-image: linear-gradient(90deg, black, transparent);
+}
+
 .animation-negative-delay-path path,
 .animation-negative-end-delay-path path {
   fill: none;
   stroke: var(--theme-graphs-grey);
   stroke-dasharray: 2px 2px;
   transform: scale(1, -1);
   vector-effect: non-scaling-stroke;
 }