Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 36 additions & 13 deletions src/components/timeline/TrackPowerGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// @flow

import * as React from 'react';
import { InView } from 'react-intersection-observer';
import { withSize } from 'firefox-profiler/components/shared/WithSize';
import explicitConnect from 'firefox-profiler/utils/connect';
import { bisectionRight } from 'firefox-profiler/utils/bisect';
Expand Down Expand Up @@ -57,7 +58,10 @@ type CanvasProps = {|
*/
class TrackPowerCanvas extends React.PureComponent<CanvasProps> {
_canvas: null | HTMLCanvasElement = null;
_requestedAnimationFrame: boolean = false;
_canvasState: {| renderScheduled: boolean, inView: boolean |} = {
renderScheduled: false,
inView: false,
};

drawCanvas(canvas: HTMLCanvasElement): void {
const {
Expand Down Expand Up @@ -174,28 +178,47 @@ class TrackPowerCanvas extends React.PureComponent<CanvasProps> {
}
}

_scheduleDraw() {
if (!this._requestedAnimationFrame) {
this._requestedAnimationFrame = true;
window.requestAnimationFrame(() => {
this._requestedAnimationFrame = false;
const canvas = this._canvas;
if (canvas) {
this.drawCanvas(canvas);
}
});
_renderCanvas() {
if (!this._canvasState.inView) {
// Canvas is not in the view. Schedule the render for a later intersection
// observer callback.
this._canvasState.renderScheduled = true;
return;
}

// Canvas is in the view. Render the canvas and reset the schedule state.
this._canvasState.renderScheduled = false;

const canvas = this._canvas;
if (canvas) {
this.drawCanvas(canvas);
}
}

_takeCanvasRef = (canvas: HTMLCanvasElement | null) => {
this._canvas = canvas;
};

_observerCallback = (inView: boolean, _entry: IntersectionObserverEntry) => {
this._canvasState.inView = inView;
if (!this._canvasState.renderScheduled) {
// Skip if render is not scheduled.
return;
}

this._renderCanvas();
};

render() {
this._scheduleDraw();
this._renderCanvas();

return (
<canvas className="timelineTrackPowerCanvas" ref={this._takeCanvasRef} />
<InView onChange={this._observerCallback}>
<canvas
className="timelineTrackPowerCanvas"
ref={this._takeCanvasRef}
/>
</InView>
);
}
}
Expand Down
7 changes: 4 additions & 3 deletions src/selectors/profile.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,14 @@ export const getCounterSelectors = (index: CounterIndex): CounterSelectors => {
* type of the function.
*/
function _createCounterSelectors(counterIndex: CounterIndex) {
const getCounter: Selector<Counter> = (state) =>
const getCounter: Selector<Counter> = createSelector(getProfile, (profile) =>
processCounter(
ensureExists(
getProfile(state).counters,
profile.counters,
'Attempting to get a counter by index, but no counters exist.'
)[counterIndex]
);
)
);

const getDescription: Selector<string> = (state) =>
getCounter(state).description;
Expand Down
12 changes: 7 additions & 5 deletions src/test/components/__snapshots__/TrackPower.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,13 @@ exports[`TrackPower matches the component snapshot 1`] = `
<div
class="timelineTrackPowerGraph"
>
<canvas
class="timelineTrackPowerCanvas"
height="25"
width="80"
/>
<div>
<canvas
class="timelineTrackPowerCanvas"
height="25"
width="80"
/>
</div>
<div
class="timelineEmptyThreadIndicator"
/>
Expand Down
37 changes: 37 additions & 0 deletions src/utils/react.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// @flow

// This file contains some functions that might be interesting when debugging
// react code.

// This function keeps track of the props of a React component and logs the
// changes between two calls. This is best used in render() or
// componentDidUpdate() like this:
// import { logPropChanges } from 'firefox-profiler/utils/react';
// ...
// render() {
// logPropChanges(this);
// }
export function logPropChanges(component: any) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice, this will come in handy in the future!

if (!component.__DEBUG__oldProps) {
component.__DEBUG__oldProps = component.props;
return;
}

for (const [prop, value] of Object.entries(component.props)) {
const oldValue = component.__DEBUG__oldProps[prop];
if (oldValue !== value) {
console.log(
`prop "${prop}" changed: old value is`,
oldValue,
', new value is',
value
);
}
}

component.__DEBUG__oldProps = component.props;
}