The heartbeat monitor display logic was extracted from lib/screens/zigzag_gap_line.dart into a standalone Flutter package at packages/flutter_ecg_monitor/.
Total lines deleted: ~450
-
_StaticBackgroundPainterclass (lines 38-114)- Static ECG-paper grid background
- Now:
EcgGridPainterin package
-
Heartbeat-specific static members in
_GapLinePainter:_heartbeatLUT+_precomputeHeartbeat()— PQRST waveform lookup table_trailBuffer— ring buffer for trail storage_distanceToPaintLUT— pre-baked distance-to-paint-index mapping_corePaints,_glowPaints— pre-built paint lists_lastCursorX,_lastIntCursorX— cursor tracking state
-
_drawHeartbeatMonitor()method (~260 lines)- Entire heartbeat rendering logic
- Now:
EcgTrailPainter.paint()in package
-
Unused imports:
dart:typed_data(only used by deleted heartbeat code)
-
Removed constructor parameters:
tipColorfrom_GapLinePainter(only used by heartbeat)
New package structure:
packages/flutter_ecg_monitor/
├── lib/
│ ├── flutter_ecg_monitor.dart — barrel export
│ └── src/
│ ├── ecg_monitor_config.dart — all tunable params
│ ├── ecg_monitor.dart — EcgMonitor widget
│ ├── ecg_grid_painter.dart — static grid (was _StaticBackgroundPainter)
│ └── ecg_trail_painter.dart — trail + cursor (was _drawHeartbeatMonitor)
├── example/lib/main.dart — demo app
├── pubspec.yaml
├── README.md
└── ARCHITECTURE.md — optimization techniques documentation
// build() method created _GapLinePainter which called _drawHeartbeatMonitor()
return Stack([
RepaintBoundary(child: CustomPaint(painter: _StaticBackgroundPainter(...))),
CustomPaint(painter: _GapLinePainter(...)), // calls _drawHeartbeatMonitor
]);@override
Widget build(BuildContext context) {
// Short-circuit for heartbeat style
if (widget.style == GapVisualizationStyle.heartbeatMonitor) {
return EcgMonitor(
height: widget.height,
config: EcgMonitorConfig(
heartRateBPM: 27.0,
beatDurationSeconds: 0.8,
cursorSpeedPixelsPerSecond: 40.0,
color: widget.color ?? CalendarGridTheme.subtleGrid(context),
),
);
}
// Other styles still use _GapLinePainter
return SizedBox(
child: AnimatedBuilder(
builder: (context, child) => CustomPaint(painter: _GapLinePainter(...)),
),
);
}The case GapVisualizationStyle.heartbeatMonitor: in _GapLinePainter.paint() is now unreachable (the build method returns early), but left as a comment for clarity.
- Reusability —
EcgMonitorcan be used in any Flutter app, not just where_when - Separation of concerns — Gap visualization styles vs ECG rendering are now independent
- Cleaner codebase — Removed ~450 lines from zigzag_gap_line.dart
- Better documentation — Package has dedicated README + ARCHITECTURE.md
- Independent versioning — Package can be published to pub.dev separately
- Testability — Package can have its own unit/widget tests
lib/screens/zigzag_gap_line.dart— removed heartbeat code, added package import + short-circuitpubspec.yaml— addedflutter_ecg_monitor: path: packages/flutter_ecg_monitor
Run flutter pub get to resolve the package dependency. The heartbeat monitor style should work identically to before the migration.