Repository: facebook/react
File: packages/react-devtools-shared/src/backend/views/TraceUpdates/canvas.js (JavaScript)

Code before:
let canvas: HTMLCanvasElement | null = null;

function drawNative(nodeToData: Map<HostInstance, Data>, agent: Agent) {
  const nodesToDraw = [];
  iterateNodes(nodeToData, ({color, node}) => {
    nodesToDraw.push({node, color});
  });

  agent.emit('drawTraceUpdates', nodesToDraw);

  const mergedNodes = groupAndSortNodes(nodeToData);
  agent.emit('drawGroupedTraceUpdatesWithNames', mergedNodes);
}

function drawWeb(nodeToData: Map<HostInstance, Data>) {
  // if there are no nodes to draw, detach from top layer
  if (nodeToData.size === 0) {
    if (canvas !== null) {
      if (canvas.matches(':popover-open')) {
        // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
        // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
        canvas.hidePopover();
      }
    }
    return;
  }

  if (canvas === null) {
    initialize();
  } else {
    if (!canvas.matches(':popover-open')) {
      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
      canvas.showPopover();
    }
  }

  const dpr = window.devicePixelRatio || 1;
  const canvasFlow: HTMLCanvasElement = ((canvas: any): HTMLCanvasElement);
  canvasFlow.width = window.innerWidth * dpr;
  canvasFlow.height = window.innerHeight * dpr;
  canvasFlow.style.width = `${window.innerWidth}px`;
  canvasFlow.style.height = `${window.innerHeight}px`;

  const context = canvasFlow.getContext('2d');
  context.scale(dpr, dpr);

  context.clearRect(0, 0, canvasFlow.width / dpr, canvasFlow.height / dpr);

  const mergedNodes = groupAndSortNodes(nodeToData);


Review comment (suggestion):
I think this new code changes the behaviour of the `drawWeb` function.

Before this change, we would clear out canvas and draw nothing. Also, even if canvas was not initialized yet and `drawWeb` was called, we would initialize it as empty.

I think we should preserve the previous approach:
1. Remove `canvas.showPopover()` from `initialize`.
2. In the the end of `drawWeb` function call, add `canvas.showPopover` or `canvas.hidePopover` calls, based on `nodeToData.size` and popover state.

Something like this:
```
function drawWeb(nodeToData: Map<HostInstance, Data>) {
 <all code before your changes>
 ...
 
 if (nodeToData.size === 0 && canvas.matches(':popover-open')) {
   canvas.hidePopover();
 } else if (!canvas.matches(':popover-open') && nodeToData.size !== 0) {
   canvas.openPopover();
 }
 }
 ```


Code after:
let canvas: HTMLCanvasElement | null = null;

function drawNative(nodeToData: Map<HostInstance, Data>, agent: Agent) {
  const nodesToDraw = [];
  iterateNodes(nodeToData, ({color, node}) => {
    nodesToDraw.push({node, color});
  });

  agent.emit('drawTraceUpdates', nodesToDraw);

  const mergedNodes = groupAndSortNodes(nodeToData);
  agent.emit('drawGroupedTraceUpdatesWithNames', mergedNodes);
}

function drawWeb(nodeToData: Map<HostInstance, Data>) {
  if (canvas === null) {
    initialize();
  }

  const dpr = window.devicePixelRatio || 1;
  const canvasFlow: HTMLCanvasElement = ((canvas: any): HTMLCanvasElement);
  canvasFlow.width = window.innerWidth * dpr;
  canvasFlow.height = window.innerHeight * dpr;
  canvasFlow.style.width = `${window.innerWidth}px`;
  canvasFlow.style.height = `${window.innerHeight}px`;

  const context = canvasFlow.getContext('2d');
  context.scale(dpr, dpr);

  context.clearRect(0, 0, canvasFlow.width / dpr, canvasFlow.height / dpr);

  const mergedNodes = groupAndSortNodes(nodeToData);

  mergedNodes.forEach(group => {
    drawGroupBorders(context, group);
    drawGroupLabel(context, group);
  });

  if (canvas !== null) {
    if (nodeToData.size === 0 && canvas.matches(':popover-open')) {
      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
      canvas.hidePopover();
      return;
    }
    // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
    if (canvas.matches(':popover-open')) {
      // $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
      // $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
      canvas.hidePopover();
    }