render method

  1. @override
void render(
  1. Object view
)
override

Renders the view to the terminal.

view is the string representation of the current UI state, or a View object containing metadata.

Implementation

@override
void render(Object view) {
  _metrics.beginFrame();

  if (!_initialized) {
    initialize();
  }

  final String content = switch (view) {
    String s => s,
    View v => v.content,
    _ => view.toString(),
  };

  // A terminal resize reflows whatever is on screen, so the last rendered
  // frame no longer matches the terminal's actual content — a diff against
  // it would leave reflowed fragments in every skipped span. Clear and drop
  // the baseline so this frame paints in full. (Never rate-limit a resize:
  // the clear must be followed by its redraw in the same render.)
  final size = terminal.size;
  final resized = _lastSize != null && size != _lastSize;

  // Frame rate limiting using Stopwatch (immune to clock adjustments)
  if (!resized && _frameStopwatch.isRunning) {
    if (_frameStopwatch.elapsed < _options.frameTime) {
      // Skip this frame
      _metrics.endFrame(skipped: true);
      return;
    }
  }

  if (resized) {
    terminal.clearScreen();
    _lastView = null;
    _lastFrame = null;
  }

  // Skip if view hasn't changed
  if (content == _lastView) {
    _metrics.endFrame(skipped: true);
    return;
  }

  final output = _options.ansiCompress ? compressAnsi(content) : content;

  // A frame taller than the terminal cannot be diffed or drawn in full
  // without scrolling the screen, which would shift everything under the
  // diff's absolute row addressing. This is a transient mid-resize state
  // (the app has not rebuilt its view for the new size yet): draw it
  // clipped and keep the baseline invalid, so the first frame that fits
  // repaints in full.
  final parsedFrame = TerminalRenderFrame.parse(output);
  final oversize =
      _lineCount(content) > size.height ||
      parsedFrame.lines.any(
        (line) => renderedLineDisplayWidth(line) > size.width,
      );

  if (!terminal.supportsAnsi || _lastFrame == null || oversize) {
    _renderFullRedraw(output, clearBefore: oversize);
    _lastFrame = oversize ? null : TerminalRenderFrame.parse(output);
  } else {
    _renderDiffFrame(_lastFrame!, parsedFrame);
    _lastFrame = parsedFrame;
  }

  _lastView = oversize ? null : content;
  _lastSize = size;
  // Reset and start the stopwatch for next frame timing
  _frameStopwatch.reset();
  _frameStopwatch.start();
  _metrics.endFrame();
}