Bug 1454392 - Part 2: Apply createdTime to summary graph so as keeping proper graph. r?pbro
MozReview-Commit-ID: 4udVcj2Zy5C
--- a/devtools/client/inspector/animation/components/graph/DelaySign.js
+++ b/devtools/client/inspector/animation/components/graph/DelaySign.js
@@ -17,26 +17,31 @@ class DelaySign extends PureComponent {
}
render() {
const {
animation,
timeScale,
} = this.props;
const {
+ createdTime,
+ delay,
fill,
playbackRate,
- previousStartTime = 0,
} = animation.state;
- const delay = animation.state.delay / playbackRate;
- const startTime =
- previousStartTime - timeScale.minStartTime + (delay < 0 ? delay : 0);
+ const toRate = v => v / playbackRate;
+ // If createdTime is not defined (which happens when connected to server older
+ // than FF62), use previousStartTime instead. See bug 1454392
+ const baseTime = typeof createdTime === "undefined"
+ ? (animation.state.previousStartTime || 0)
+ : createdTime;
+ const startTime = baseTime + toRate(Math.min(delay, 0)) - timeScale.minStartTime;
const offset = startTime / timeScale.getDuration() * 100;
- const width = Math.abs(delay) / timeScale.getDuration() * 100;
+ const width = Math.abs(toRate(delay)) / timeScale.getDuration() * 100;
return dom.div(
{
className: "animation-delay-sign" +
(delay < 0 ? " negative" : "") +
(fill === "both" || fill === "backwards" ? " fill" : ""),
style: {
width: `${ width }%`,
--- a/devtools/client/inspector/animation/components/graph/EndDelaySign.js
+++ b/devtools/client/inspector/animation/components/graph/EndDelaySign.js
@@ -17,30 +17,35 @@ class EndDelaySign extends PureComponent
}
render() {
const {
animation,
timeScale,
} = this.props;
const {
+ createdTime,
delay,
duration,
+ endDelay,
fill,
iterationCount,
playbackRate,
- previousStartTime = 0,
} = animation.state;
- const endDelay = animation.state.endDelay / playbackRate;
- const startTime = previousStartTime - timeScale.minStartTime;
- const endTime =
- (duration * iterationCount + delay) / playbackRate + (endDelay < 0 ? endDelay : 0);
+ const toRate = v => v / playbackRate;
+ // If createdTime is not defined (which happens when connected to server older
+ // than FF62), use previousStartTime instead. See bug 1454392
+ const baseTime = typeof createdTime === "undefined"
+ ? (animation.state.previousStartTime || 0)
+ : createdTime;
+ const startTime = baseTime - timeScale.minStartTime;
+ const endTime = toRate(delay + duration * iterationCount + Math.min(endDelay, 0));
const offset = (startTime + endTime) / timeScale.getDuration() * 100;
- const width = Math.abs(endDelay) / timeScale.getDuration() * 100;
+ const width = Math.abs(toRate(endDelay)) / timeScale.getDuration() * 100;
return dom.div(
{
className: "animation-end-delay-sign" +
(endDelay < 0 ? " negative" : "") +
(fill === "both" || fill === "forwards" ? " fill" : ""),
style: {
width: `${ width }%`,
--- a/devtools/client/inspector/animation/components/graph/SummaryGraphPath.js
+++ b/devtools/client/inspector/animation/components/graph/SummaryGraphPath.js
@@ -116,20 +116,16 @@ class SummaryGraphPath extends Component
});
}).map(keyframes => {
return keyframes.map(keyframe => {
return { easing: keyframe.easing, offset: keyframe.offset };
});
});
}
- getTotalDuration(animation, timeScale) {
- return animation.state.playbackRate * timeScale.getDuration();
- }
-
/**
* Return true if given keyframes have same length, offset and easing.
*
* @param {Array} keyframes1
* @param {Array} keyframes2
* @return {Boolean} true: equals
*/
isOffsetAndEasingKeyframesEqual(keyframes1, keyframes2) {
@@ -167,17 +163,17 @@ class SummaryGraphPath extends Component
// in the meantime.
console.error(e);
return;
}
const keyframesList = this.getOffsetAndEasingOnlyKeyframes(animatedPropertyMap);
const thisEl = ReactDOM.findDOMNode(this);
- const totalDuration = this.getTotalDuration(animation, timeScale);
+ const totalDuration = timeScale.getDuration() * animation.state.playbackRate;
const durationPerPixel = totalDuration / thisEl.parentNode.clientWidth;
this.setState(
{
durationPerPixel,
isStateUpdating: false,
keyframesList
}
@@ -194,20 +190,29 @@ class SummaryGraphPath extends Component
}
const {
animation,
simulateAnimation,
timeScale,
} = this.props;
- const totalDuration = this.getTotalDuration(animation, timeScale);
- const { playbackRate, previousStartTime = 0 } = animation.state;
+ const { createdTime, playbackRate } = animation.state;
+
+ // If createdTime is not defined (which happens when connected to server older
+ // than FF62), use previousStartTime instead. See bug 1454392
+ const baseTime = typeof createdTime === "undefined"
+ ? (animation.state.previousStartTime || 0)
+ : createdTime;
+ // Absorb the playbackRate in viewBox of SVG and offset of child path elements
+ // in order to each graph path components can draw without considering to the
+ // playbackRate.
+ const offset = baseTime * playbackRate;
const startTime = timeScale.minStartTime * playbackRate;
- const offset = previousStartTime * playbackRate;
+ const totalDuration = timeScale.getDuration() * playbackRate;
const opacity = Math.max(1 / keyframesList.length, MIN_KEYFRAMES_EASING_OPACITY);
return dom.svg(
{
className: "animation-summary-graph-path",
preserveAspectRatio: "none",
viewBox: `${ startTime } -${ DEFAULT_GRAPH_HEIGHT } `
+ `${ totalDuration } ${ DEFAULT_GRAPH_HEIGHT }`,
--- a/devtools/client/inspector/animation/utils/timescale.js
+++ b/devtools/client/inspector/animation/utils/timescale.js
@@ -10,71 +10,96 @@ const { getFormatStr } = require("./l10n
// TIME_FORMAT_MAX_DURATION_IN_MS, the text which expresses time is in milliseconds,
// and seconds otherwise. Use in formatTime function.
const TIME_FORMAT_MAX_DURATION_IN_MS = 4000;
/**
* TimeScale object holds the total duration, start time and end time information for all
* animations which should be displayed, and is used to calculate the displayed area for
* each animation.
- *
- * For the helper to know how to convert, it needs to know all the animations.
- * Whenever a new animation is added to the panel, addAnimation(state) should be
- * called.
*/
class TimeScale {
constructor(animations) {
+ if (!animations.every(animation => animation.state.createdTime)) {
+ // Backward compatibility for createdTime.
+ return this._initializeWithoutCreatedTime(animations);
+ }
+
this.minStartTime = Infinity;
this.maxEndTime = 0;
this.documentCurrentTime = 0;
for (const animation of animations) {
- this.addAnimation(animation.state);
+ const {
+ createdTime,
+ delay,
+ documentCurrentTime,
+ 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));
+ this.minStartTime = Math.min(this.minStartTime, startTime);
+ this.maxEndTime = Math.max(this.maxEndTime, endTime);
+ this.documentCurrentTime = Math.max(this.documentCurrentTime, documentCurrentTime);
}
}
/**
- * Add a new animation to time scale.
+ * Same as the constructor but doesn't use the animation's createdTime property
+ * which has only been added in FF62, for backward compatbility reasons.
*
- * @param {Object} state
- * A PlayerFront.state object.
+ * @param {Array} animations
*/
- addAnimation(state) {
- let {
- delay,
- documentCurrentTime,
- duration,
- endDelay = 0,
- iterationCount,
- playbackRate,
- previousStartTime = 0,
- } = state;
+ _initializeWithoutCreatedTime(animations) {
+ this.minStartTime = Infinity;
+ this.maxEndTime = 0;
+ this.documentCurrentTime = 0;
+
+ for (const animation of animations) {
+ const {
+ delay,
+ documentCurrentTime,
+ duration,
+ endDelay = 0,
+ iterationCount,
+ playbackRate,
+ previousStartTime = 0,
+ } = animation.state;
- const toRate = v => v / playbackRate;
- const minZero = v => Math.max(v, 0);
- const rateRelativeDuration =
- toRate(duration * (!iterationCount ? 1 : iterationCount));
- // Negative-delayed animations have their startTimes set such that we would
- // be displaying the delay outside the time window if we didn't take it into
- // account here.
- const relevantDelay = delay < 0 ? toRate(delay) : 0;
- const startTime = toRate(minZero(delay)) +
- rateRelativeDuration +
- endDelay;
- this.minStartTime = Math.min(
- this.minStartTime,
- previousStartTime +
- relevantDelay +
- Math.min(startTime, 0)
- );
- const length = toRate(delay) + rateRelativeDuration + toRate(minZero(endDelay));
- const endTime = previousStartTime + length;
- this.maxEndTime = Math.max(this.maxEndTime, endTime);
+ const toRate = v => v / playbackRate;
+ const minZero = v => Math.max(v, 0);
+ const rateRelativeDuration =
+ toRate(duration * (!iterationCount ? 1 : iterationCount));
+ // Negative-delayed animations have their startTimes set such that we would
+ // be displaying the delay outside the time window if we didn't take it into
+ // account here.
+ const relevantDelay = delay < 0 ? toRate(delay) : 0;
+ const startTime = toRate(minZero(delay)) +
+ rateRelativeDuration +
+ endDelay;
+ this.minStartTime = Math.min(
+ this.minStartTime,
+ previousStartTime +
+ relevantDelay +
+ Math.min(startTime, 0)
+ );
+ const length = toRate(delay) + rateRelativeDuration + toRate(minZero(endDelay));
+ const endTime = previousStartTime + length;
+ this.maxEndTime = Math.max(this.maxEndTime, endTime);
- this.documentCurrentTime = Math.max(this.documentCurrentTime, documentCurrentTime);
+ this.documentCurrentTime = Math.max(this.documentCurrentTime, documentCurrentTime);
+ }
}
/**
* Convert a distance in % to a time, in the current time scale.
*
* @param {Number} distance
* @return {Number}
*/