Skip to content

Frontend framework

This is the canonical working note for the Flutter benchmark viewer.

Use it to understand the current architecture, the implementation facts that should stay true, and the near-term scope before making structural changes.

Working architecture

The current ownership split is:

  • BenchmarkPage — owns benchmark loading, page UI, and loading/error/success state
  • ViewportController — owns persistent viewport state and operations such as panBy(...) and zoomAt(...)
  • InteractiveCanvas — handles device-specific input and translates it into viewport updates
  • BenchmarkPainter — renders scene data using the current viewport state

Behavioral boundaries that should remain clear:

  • BenchmarkPage should not absorb low-level input handling or render math
  • ViewportController should not care which input device triggered an update
  • InteractiveCanvas should handle desktop wheel and middle-mouse behavior plus touch gesture adaptation
  • BenchmarkPainter should stay free of mutable interaction state and asset loading

Implementation notes:

  • desktop input should use Listener for wheel signals and button-specific pointer behavior
  • touch input should use GestureDetector.onScale*
  • painter work should prefer one canvas transform over repeated per-object transform math

Useful shape reminder:

BenchmarkPage
  -> Scaffold
    -> InteractiveCanvas
         -> CustomPaint
              -> BenchmarkPainter

This shape keeps loading, interaction, and drawing responsibilities separate enough to evolve one area without reworking the others.

Next steps remaining

See Draw optimisations for next steps to optimise drawing performance

Benchmark findings

See Benchmark findings for measured behavior, likely bottlenecks, and performance-oriented next steps. Keep detailed measurement notes there instead of duplicating them here.