From ca927367bb23e1e6242f9578b55c327e875ae427 Mon Sep 17 00:00:00 2001 From: MAYANK Date: Wed, 19 Jun 2024 11:25:41 +0530 Subject: [PATCH] Solved Intermittent Gap in Timeline Display Causing Missing Hour #381 --- lib/src/components/_internal_components.dart | 79 ++++++------ lib/src/day_view/_internal_day_view_page.dart | 25 ++-- lib/src/day_view/day_view.dart | 117 +++++++++--------- 3 files changed, 120 insertions(+), 101 deletions(-) diff --git a/lib/src/components/_internal_components.dart b/lib/src/components/_internal_components.dart index 129e84c1..0b258b5c 100644 --- a/lib/src/components/_internal_components.dart +++ b/lib/src/components/_internal_components.dart @@ -91,7 +91,7 @@ class _LiveTimeIndicatorState extends State { final currentMinute = _currentTime.minute.appendLeadingZero(); final currentPeriod = _currentTime.period.name; final timeString = widget.liveTimeIndicatorSettings.timeStringBuilder - ?.call(DateTime.now()) ?? + ?.call(DateTime.now()) ?? '$currentHour:$currentMinute $currentPeriod'; /// remove startHour minute from [_currentTime.getTotalMinutes] @@ -121,10 +121,10 @@ class _LiveTimeIndicatorState extends State { showBullet: widget.liveTimeIndicatorSettings.showBullet, showTime: widget.liveTimeIndicatorSettings.showTime, showTimeBackgroundView: - widget.liveTimeIndicatorSettings.showTimeBackgroundView, + widget.liveTimeIndicatorSettings.showTimeBackgroundView, bulletRadius: widget.liveTimeIndicatorSettings.bulletRadius, timeBackgroundViewWidth: - widget.liveTimeIndicatorSettings.timeBackgroundViewWidth, + widget.liveTimeIndicatorSettings.timeBackgroundViewWidth, ), ); } @@ -167,6 +167,9 @@ class TimeLine extends StatefulWidget { /// This field will be used to set end hour for day and week view final int endHour; + /// This field will be optional if set true then the current timeline hour will be visible else default + final bool currentHourVisibility; + /// Time line to display time at left side of day or week view. const TimeLine({ Key? key, @@ -178,6 +181,7 @@ class TimeLine extends StatefulWidget { required this.startHour, this.showHalfHours = false, this.showQuarterHours = false, + this.currentHourVisibility = false, required this.liveTimeIndicatorSettings, this.endHour = Constants.hoursADay, }) : super(key: key); @@ -228,49 +232,53 @@ class _TimeLineState extends State { children: [ for (int i = widget.startHour + 1; i < widget.endHour; i++) _timelinePositioned( - topPosition: widget.hourHeight * (i - widget.startHour) - - widget.timeLineOffset, - bottomPosition: widget.height - - (widget.hourHeight * (i - widget.startHour + 1)) + - widget.timeLineOffset, - hour: i, - ), - if (widget.showHalfHours) - for (int i = widget.startHour; i < widget.endHour; i++) - _timelinePositioned( topPosition: widget.hourHeight * (i - widget.startHour) - - widget.timeLineOffset + - widget._halfHourHeight, + widget.timeLineOffset, bottomPosition: widget.height - (widget.hourHeight * (i - widget.startHour + 1)) + widget.timeLineOffset, hour: i, - minutes: 30, + visibility: widget.currentHourVisibility + ), + if (widget.showHalfHours) + for (int i = widget.startHour; i < widget.endHour; i++) + _timelinePositioned( + topPosition: widget.hourHeight * (i - widget.startHour) - + widget.timeLineOffset + + widget._halfHourHeight, + bottomPosition: widget.height - + (widget.hourHeight * (i - widget.startHour + 1)) + + widget.timeLineOffset, + hour: i, + minutes: 30, + visibility: widget.currentHourVisibility ), if (widget.showQuarterHours) for (int i = 0; i < widget.endHour; i++) ...[ /// this is for 15 minutes _timelinePositioned( - topPosition: widget.hourHeight * i - - widget.timeLineOffset + - widget.hourHeight * 0.25, - bottomPosition: widget.height - - (widget.hourHeight * (i + 1)) + - widget.timeLineOffset, - hour: i, - minutes: 15, + topPosition: widget.hourHeight * i - + widget.timeLineOffset + + widget.hourHeight * 0.25, + bottomPosition: widget.height - + (widget.hourHeight * (i + 1)) + + widget.timeLineOffset, + hour: i, + minutes: 15, + visibility: widget.currentHourVisibility ), /// this is for 45 minutes _timelinePositioned( - topPosition: widget.hourHeight * i - - widget.timeLineOffset + - widget.hourHeight * 0.75, - bottomPosition: widget.height - - (widget.hourHeight * (i + 1)) + - widget.timeLineOffset, - hour: i, - minutes: 45, + topPosition: widget.hourHeight * i - + widget.timeLineOffset + + widget.hourHeight * 0.75, + bottomPosition: widget.height - + (widget.hourHeight * (i + 1)) + + widget.timeLineOffset, + hour: i, + minutes: 45, + visibility: widget.currentHourVisibility ), ], ], @@ -285,13 +293,14 @@ class _TimeLineState extends State { required double topPosition, required double bottomPosition, required int hour, + bool visibility = false, int minutes = 0, }) { return Visibility( - visible: !((_currentTime.minute >= 45 && _currentTime.hour == hour - 1) || - (_currentTime.minute <= 15 && _currentTime.hour == hour)) || + visible: visibility == false ? !((_currentTime.minute >= 45 && _currentTime.hour == hour - 1) || + (_currentTime.minute <= 15 && _currentTime.hour == hour)) || !(widget.liveTimeIndicatorSettings.showTime || - widget.liveTimeIndicatorSettings.showTimeBackgroundView), + widget.liveTimeIndicatorSettings.showTimeBackgroundView) : true, child: Positioned( top: topPosition, left: 0, diff --git a/lib/src/day_view/_internal_day_view_page.dart b/lib/src/day_view/_internal_day_view_page.dart index d46be383..2a1ea7c9 100644 --- a/lib/src/day_view/_internal_day_view_page.dart +++ b/lib/src/day_view/_internal_day_view_page.dart @@ -133,6 +133,9 @@ class InternalDayViewPage extends StatefulWidget { /// Flag to keep scrollOffset of pages on page change final bool keepScrollOffset; + /// Flag to keep the visibility of the current hour to be optional + final bool currentHourVisibility; + /// Defines a single day page. const InternalDayViewPage({ Key? key, @@ -173,6 +176,7 @@ class InternalDayViewPage extends StatefulWidget { required this.emulateVerticalOffsetBy, required this.onTileDoubleTap, this.keepScrollOffset = false, + this.currentHourVisibility = false }) : super(key: key); @override @@ -215,9 +219,9 @@ class _InternalDayViewPageState fullDayEventList.isEmpty ? SizedBox.shrink() : widget.fullDayEventBuilder( - widget.controller.getFullDayEvent(widget.date), - widget.date, - ), + widget.controller.getFullDayEvent(widget.date), + widget.date, + ), Expanded( child: SingleChildScrollView( controller: widget.keepScrollOffset @@ -241,7 +245,7 @@ class _InternalDayViewPageState lineStyle: widget.hourIndicatorSettings.lineStyle, dashWidth: widget.hourIndicatorSettings.dashWidth, dashSpaceWidth: - widget.hourIndicatorSettings.dashSpaceWidth, + widget.hourIndicatorSettings.dashSpaceWidth, emulateVerticalOffsetBy: widget.emulateVerticalOffsetBy, startHour: widget.startHour, endHour: widget.endHour, @@ -259,7 +263,7 @@ class _InternalDayViewPageState lineStyle: widget.halfHourIndicatorSettings.lineStyle, dashWidth: widget.halfHourIndicatorSettings.dashWidth, dashSpaceWidth: - widget.halfHourIndicatorSettings.dashSpaceWidth, + widget.halfHourIndicatorSettings.dashSpaceWidth, startHour: widget.startHour, endHour: widget.endHour, ), @@ -270,14 +274,14 @@ class _InternalDayViewPageState painter: QuarterHourLinePainter( lineColor: widget.quarterHourIndicatorSettings.color, lineHeight: - widget.quarterHourIndicatorSettings.height, + widget.quarterHourIndicatorSettings.height, offset: widget.timeLineWidth + widget.quarterHourIndicatorSettings.offset, minuteHeight: widget.heightPerMinute, lineStyle: - widget.quarterHourIndicatorSettings.lineStyle, + widget.quarterHourIndicatorSettings.lineStyle, dashWidth: - widget.quarterHourIndicatorSettings.dashWidth, + widget.quarterHourIndicatorSettings.dashWidth, dashSpaceWidth: widget .quarterHourIndicatorSettings.dashSpaceWidth, ), @@ -325,14 +329,15 @@ class _InternalDayViewPageState showQuarterHours: widget.showQuarterHours, key: ValueKey(widget.heightPerMinute), liveTimeIndicatorSettings: - widget.liveTimeIndicatorSettings, + widget.liveTimeIndicatorSettings, + currentHourVisibility: widget.currentHourVisibility, ), if (widget.showLiveLine && widget.liveTimeIndicatorSettings.height > 0) IgnorePointer( child: LiveTimeIndicator( liveTimeIndicatorSettings: - widget.liveTimeIndicatorSettings, + widget.liveTimeIndicatorSettings, width: widget.width, height: widget.height, heightPerMinute: widget.heightPerMinute, diff --git a/lib/src/day_view/day_view.dart b/lib/src/day_view/day_view.dart index 163b8937..654bda9a 100644 --- a/lib/src/day_view/day_view.dart +++ b/lib/src/day_view/day_view.dart @@ -229,6 +229,9 @@ class DayView extends StatefulWidget { /// Flag to keep scrollOffset of pages on page change final bool keepScrollOffset; + /// Flag to keep the visibility of the current hour to be optional + final bool currentHourVisibility; + /// Main widget for day view. const DayView({ Key? key, @@ -279,28 +282,29 @@ class DayView extends StatefulWidget { this.onEventDoubleTap, this.endHour = Constants.hoursADay, this.keepScrollOffset = false, + this.currentHourVisibility = false }) : assert(!(onHeaderTitleTap != null && dayTitleBuilder != null), - "can't use [onHeaderTitleTap] & [dayTitleBuilder] simultaneously"), + "can't use [onHeaderTitleTap] & [dayTitleBuilder] simultaneously"), assert(timeLineOffset >= 0, - "timeLineOffset must be greater than or equal to 0"), + "timeLineOffset must be greater than or equal to 0"), assert(width == null || width > 0, - "Calendar width must be greater than 0."), + "Calendar width must be greater than 0."), assert(timeLineWidth == null || timeLineWidth > 0, - "Time line width must be greater than 0."), + "Time line width must be greater than 0."), assert( - heightPerMinute > 0, "Height per minute must be greater than 0."), + heightPerMinute > 0, "Height per minute must be greater than 0."), assert( - dayDetectorBuilder == null || onDateLongPress == null, - """If you use [dayPressDetectorBuilder] + dayDetectorBuilder == null || onDateLongPress == null, + """If you use [dayPressDetectorBuilder] do not provide [onDateLongPress]""", ), assert( - startHour <= 0 || startHour != endHour, - "startHour must be greater than 0 or startHour should not equal to endHour", + startHour <= 0 || startHour != endHour, + "startHour must be greater than 0 or startHour should not equal to endHour", ), assert( - endHour <= Constants.hoursADay || endHour < startHour, - "End hour must be less than 24 or startHour must be less than endHour", + endHour <= Constants.hoursADay || endHour < startHour, + "End hour must be less than 24 or startHour must be less than endHour", ), super(key: key); @@ -384,11 +388,11 @@ class DayViewState extends State> { _controller = newController; _controller! - // Removes existing callback. + // Removes existing callback. ..removeListener(_reloadCallback) - // Reloads the view if there is any change in controller or - // user adds new events. + // Reloads the view if there is any change in controller or + // user adds new events. ..addListener(_reloadCallback); } } @@ -465,7 +469,7 @@ class DayViewState extends State> { _hourHeight.toString() + date.toString()), width: _width, liveTimeIndicatorSettings: - _liveTimeIndicatorSettings, + _liveTimeIndicatorSettings, timeLineBuilder: _timeLineBuilder, dayDetectorBuilder: _dayDetectorBuilder, eventTileBuilder: _eventTileBuilder, @@ -494,17 +498,18 @@ class DayViewState extends State> { showHalfHours: widget.showHalfHours, showQuarterHours: widget.showQuarterHours, halfHourIndicatorSettings: - _halfHourIndicatorSettings, + _halfHourIndicatorSettings, startHour: widget.startHour, endHour: widget.endHour, quarterHourIndicatorSettings: - _quarterHourIndicatorSettings, + _quarterHourIndicatorSettings, emulateVerticalOffsetBy: - widget.emulateVerticalOffsetBy, + widget.emulateVerticalOffsetBy, lastScrollOffset: _lastScrollOffset, dayViewScrollController: _scrollController, scrollListener: _scrollPageListener, keepScrollOffset: widget.keepScrollOffset, + currentHourVisibility: widget.currentHourVisibility, ), ); }, @@ -551,7 +556,7 @@ class DayViewState extends State> { ); assert(_liveTimeIndicatorSettings.height < _hourHeight, - "liveTimeIndicator height must be less than minuteHeight * 60"); + "liveTimeIndicator height must be less than minuteHeight * 60"); _hourIndicatorSettings = widget.hourIndicatorSettings ?? HourIndicatorSettings( @@ -561,7 +566,7 @@ class DayViewState extends State> { ); assert(_hourIndicatorSettings.height < _hourHeight, - "hourIndicator height must be less than minuteHeight * 60"); + "hourIndicator height must be less than minuteHeight * 60"); _halfHourIndicatorSettings = widget.halfHourIndicatorSettings ?? HourIndicatorSettings( @@ -571,7 +576,7 @@ class DayViewState extends State> { ); assert(_halfHourIndicatorSettings.height < _hourHeight, - "halfHourIndicator height must be less than minuteHeight * 60"); + "halfHourIndicator height must be less than minuteHeight * 60"); _quarterHourIndicatorSettings = widget.quarterHourIndicatorSettings ?? HourIndicatorSettings( @@ -581,7 +586,7 @@ class DayViewState extends State> { ); assert(_quarterHourIndicatorSettings.height < _hourHeight, - "quarterHourIndicator height must be less than minuteHeight * 60"); + "quarterHourIndicator height must be less than minuteHeight * 60"); } void _calculateHeights() { @@ -624,9 +629,9 @@ class DayViewState extends State> { _maxDate = (widget.maxDay ?? CalendarConstants.maxDate).withoutTime; assert( - !_maxDate.isBefore(_minDate), - "Minimum date should be less than maximum date.\n" - "Provided minimum date: $_minDate, maximum date: $_maxDate", + !_maxDate.isBefore(_minDate), + "Minimum date should be less than maximum date.\n" + "Provided minimum date: $_minDate, maximum date: $_maxDate", ); _totalDays = _maxDate.getDayDifference(_minDate) + 1; @@ -663,12 +668,12 @@ class DayViewState extends State> { /// [widget.eventTileBuilder] is null /// Widget _defaultEventTileBuilder( - DateTime date, - List> events, - Rect boundary, - DateTime startDuration, - DateTime endDuration, - ) => + DateTime date, + List> events, + Rect boundary, + DateTime startDuration, + DateTime endDuration, + ) => DefaultEventTile( date: date, events: events, @@ -706,7 +711,7 @@ class DayViewState extends State> { } Widget _defaultFullDayEventBuilder( - List> events, DateTime date) => + List> events, DateTime date) => FullDayEventView( events: events, date: date, @@ -716,19 +721,19 @@ class DayViewState extends State> { ); HourLinePainter _defaultHourLinePainter( - Color lineColor, - double lineHeight, - double offset, - double minuteHeight, - bool showVerticalLine, - double verticalLineOffset, - LineStyle lineStyle, - double dashWidth, - double dashSpaceWidth, - double emulateVerticalOffsetBy, - int startHour, - int endHour, - ) { + Color lineColor, + double lineHeight, + double offset, + double minuteHeight, + bool showVerticalLine, + double verticalLineOffset, + LineStyle lineStyle, + double dashWidth, + double dashSpaceWidth, + double emulateVerticalOffsetBy, + int startHour, + int endHour, + ) { return HourLinePainter( lineColor: lineColor, lineHeight: lineHeight, @@ -772,9 +777,9 @@ class DayViewState extends State> { /// /// void nextPage({Duration? duration, Curve? curve}) => _pageController.nextPage( - duration: duration ?? widget.pageTransitionDuration, - curve: curve ?? widget.pageTransitionCurve, - ); + duration: duration ?? widget.pageTransitionDuration, + curve: curve ?? widget.pageTransitionCurve, + ); /// Animate to previous page /// @@ -879,10 +884,10 @@ class DayViewState extends State> { /// Animate to specific offset in a day view using the start duration Future animateToDuration( - Duration startDuration, { - Duration duration = const Duration(milliseconds: 200), - Curve curve = Curves.linear, - }) async { + Duration startDuration, { + Duration duration = const Duration(milliseconds: 200), + Curve curve = Curves.linear, + }) async { final offSetForSingleMinute = _height / 24 / 60; final startDurationInMinutes = startDuration.inMinutes; @@ -899,10 +904,10 @@ class DayViewState extends State> { /// Animate to specific scroll controller offset void animateTo( - double offset, { - Duration duration = const Duration(milliseconds: 200), - Curve curve = Curves.linear, - }) { + double offset, { + Duration duration = const Duration(milliseconds: 200), + Curve curve = Curves.linear, + }) { _scrollController.animateTo( offset, duration: duration,