diff --git a/lib/ui/screens/timeline/widgets/_event_popups.dart b/lib/ui/screens/timeline/widgets/_event_popups.dart index e0ef74be..56731057 100644 --- a/lib/ui/screens/timeline/widgets/_event_popups.dart +++ b/lib/ui/screens/timeline/widgets/_event_popups.dart @@ -50,7 +50,7 @@ class _EventPopupsState extends State<_EventPopups> { key: ValueKey(_eventToShow?.year), child: IntrinsicHeight( child: SizedBox( - width: 600, + width: $styles.sizes.maxContentWidth3, child: Padding( padding: EdgeInsets.all($styles.insets.md), child: TimelineEventCard( diff --git a/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart b/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart index 13627b16..a7fde53f 100644 --- a/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart +++ b/lib/ui/screens/timeline/widgets/_scrolling_viewport.dart @@ -24,6 +24,7 @@ class _ScalingViewportState extends State<_ScrollingViewport> { late final _ScrollingViewportController controller = _ScrollingViewportController(this); static const double _minTimelineSize = 100; final _currentEventMarker = ValueNotifier(null); + @override void initState() { super.initState(); @@ -44,50 +45,41 @@ class _ScalingViewportState extends State<_ScrollingViewport> { @override Widget build(BuildContext context) { - return LayoutBuilder(builder: (_, constraints) { - // cache constraints, so they can be used to maintain the selected year while zooming - controller._constraints = constraints; - double vtPadding = constraints.maxHeight / 2; - double size = controller.calculateContentHeight(); - return GestureDetector( - // Handle pinch to zoom - onScaleUpdate: controller._handleScaleUpdate, - onScaleStart: controller._handleScaleStart, - behavior: HitTestBehavior.translucent, - // Fade in entire view when first shown - child: Animate( - effects: const [FadeEffect()], - child: Stack( + return GestureDetector( + // Handle pinch to zoom + onScaleUpdate: controller._handleScaleUpdate, + onScaleStart: controller._handleScaleStart, + behavior: HitTestBehavior.translucent, + // Fade in entire view when first shown + child: Stack( + children: [ + Column( children: [ - Column( - children: [ - /// Main scrolling area, holds the year markers, and the [WondersTimelineBuilder] - Expanded( - child: _buildScrollingArea(vtPadding, size, context, constraints), - ), - Gap($styles.insets.xs), - - /// Era Text (classical, modern etc) - _buildAnimatedEraText(context), - Gap($styles.insets.xs), - ], + /// Main scrolling area, holds the year markers, and the [WondersTimelineBuilder] + Expanded( + child: _buildScrollingArea(context), ), + Gap($styles.insets.xs), - /// Dashed line with a year that changes as we scroll - IgnorePointer( - ignoringSemantics: false, - child: AnimatedBuilder( - animation: controller.scroller, - builder: (_, __) { - return _DashedDividerWithYear(controller.calculateYearFromScrollPos()); - }, - ), - ), + /// Era Text (classical, modern etc) + _buildAnimatedEraText(context), + Gap($styles.insets.xs), ], + ).animate().fadeIn(), + + /// Dashed line with a year that changes as we scroll + IgnorePointer( + ignoringSemantics: false, + child: AnimatedBuilder( + animation: controller.scroller, + builder: (_, __) { + return _DashedDividerWithYear(controller.calculateYearFromScrollPos()); + }, + ), ), - ), - ); - }); + ], + ), + ); } AnimatedBuilder _buildAnimatedEraText(BuildContext context) { @@ -107,7 +99,7 @@ class _ScalingViewportState extends State<_ScrollingViewport> { }); } - Widget _buildScrollingArea(double vtPadding, double size, BuildContext context, BoxConstraints constraints) { + Widget _buildScrollingArea(BuildContext context) { // Builds a TimelineSection, and passes it the currently selected yr based on scroll position. // Rebuilds when timeline is scrolled. Widget buildTimelineSection(WonderData data) { @@ -124,59 +116,72 @@ class _ScalingViewportState extends State<_ScrollingViewport> { ); } - return Stack( - children: [ - SingleChildScrollView( - controller: controller.scroller, - padding: EdgeInsets.symmetric(vertical: vtPadding), - // A stack inside a SizedBox which sets its overall height - child: SizedBox( - height: size, - width: double.infinity, - child: Stack( - children: [ - /// Year Markers - _YearMarkers(), + return LayoutBuilder( + builder: (_, constraints) { + // cache constraints, so they can be used to maintain the selected year while zooming + controller._constraints = constraints; + double vtPadding = constraints.maxHeight / 2; + double size = controller.calculateContentHeight(); + final contentSize = min($styles.sizes.maxContentWidth2, constraints.maxWidth); + return Stack( + children: [ + SingleChildScrollView( + controller: controller.scroller, + padding: EdgeInsets.symmetric(vertical: vtPadding), + // A stack inside a SizedBox which sets its overall height + child: Center( + child: SizedBox( + height: size, + width: contentSize, + child: Stack( + children: [ + /// Year Markers + _YearMarkers(), - /// individual timeline sections - Positioned.fill( - left: 100, - right: $styles.insets.sm, - child: FocusTraversalGroup( - child: WondersTimelineBuilder( - axis: Axis.vertical, - crossAxisGap: max(6, (constraints.maxWidth - (120 * 3)) / 2), - minSize: _minTimelineSize, - timelineBuilder: (_, data, __) => buildTimelineSection(data)), + /// individual timeline sections + Positioned.fill( + left: 100, + right: $styles.insets.sm, + child: FocusTraversalGroup( + //child: Placeholder(), + child: WondersTimelineBuilder( + axis: Axis.vertical, + crossAxisGap: max(6, (contentSize - (120 * 3)) / 2), + minSize: _minTimelineSize, + timelineBuilder: (_, data, __) => buildTimelineSection(data), + ), + ), + ), + + /// Event Markers, rebuilds on scroll + AnimatedBuilder( + animation: controller.scroller, + builder: (_, __) => _EventMarkers( + controller.calculateYearFromScrollPos(), + onEventChanged: _handleEventMarkerChanged, + ), + ), + ], ), ), - - /// Event Markers, rebuilds on scroll - AnimatedBuilder( - animation: controller.scroller, - builder: (_, __) => _EventMarkers( - controller.calculateYearFromScrollPos(), - onEventChanged: _handleEventMarkerChanged, - ), - ), - ], + ), ), - ), - ), - /// Top and bottom gradients for visual style - ListOverscollGradient(), - BottomCenter( - child: ListOverscollGradient(bottomUp: true), - ), + /// Top and bottom gradients for visual style + ListOverscollGradient(), + BottomCenter( + child: ListOverscollGradient(bottomUp: true), + ), - /// Event Popups, rebuilds when [_currentEventMarker] changes - ValueListenableBuilder( - valueListenable: _currentEventMarker, - builder: (_, data, __) { - return _EventPopups(currentEvent: data); - }) - ], + /// Event Popups, rebuilds when [_currentEventMarker] changes + ValueListenableBuilder( + valueListenable: _currentEventMarker, + builder: (_, data, __) { + return _EventPopups(currentEvent: data); + }) + ], + ); + }, ); } }