Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fixed Time Zone Support for NowIndicator #174

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:time/time.dart';
import 'package:timetable/timetable.dart';
// import 'package:timezone/data/latest.dart' as tz;

// ignore: unused_import
import 'positioning_demo.dart';
import 'utils.dart';

Future<void> main() async {
initDebugOverlay();
// Please ensure the time zone database is initialized
// when you need to display current time indicator with specific time zone.
//
// More information: [https://pub.dev/packages/timezone]
// tz.initializeTimeZones();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also like to provide an API like DateTimeTimetable.initializeTimeZones() to make it easier to use.

runApp(const ExampleApp(child: TimetableExample()));
}

Expand Down Expand Up @@ -49,6 +55,7 @@ class _TimetableExampleState extends State<TimetableExample>
// maxDuration: 10.hours,
// initialRange: TimeRange(8.hours, 20.hours),
maxRange: TimeRange(0.hours, 24.hours),
// tzIdentifier: 'Europe/Berlin',
);

final _draggedEvents = <BasicEvent>[];
Expand Down
28 changes: 18 additions & 10 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -82,26 +82,26 @@ packages:
dependency: transitive
description:
name: characters
sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev"
source: hosted
version: "1.3.0"
version: "1.4.0"
clock:
dependency: transitive
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
url: "https://pub.dev"
source: hosted
version: "1.1.1"
version: "1.1.2"
collection:
dependency: "direct main"
description:
name: collection
sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
url: "https://pub.dev"
source: hosted
version: "1.19.0"
version: "1.19.1"
color:
dependency: transitive
description:
Expand Down Expand Up @@ -386,10 +386,10 @@ packages:
dependency: transitive
description:
name: meta
sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev"
source: hosted
version: "1.15.0"
version: "1.16.0"
oxidized:
dependency: transitive
description:
Expand Down Expand Up @@ -426,10 +426,10 @@ packages:
dependency: transitive
description:
name: path
sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
url: "https://pub.dev"
source: hosted
version: "1.9.0"
version: "1.9.1"
petitparser:
dependency: transitive
description:
Expand Down Expand Up @@ -604,6 +604,14 @@ packages:
relative: true
source: path
version: "1.0.0-alpha.15"
timezone:
dependency: "direct main"
description:
name: timezone
sha256: ffc9d5f4d1193534ef051f9254063fa53d588609418c84299956c3db9383587d
url: "https://pub.dev"
source: hosted
version: "0.10.0"
todo:
dependency: transitive
description:
Expand Down
2 changes: 2 additions & 0 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ dependencies:
time: ^2.1.4
timetable:
path: ../
# Optional: it is only required for displaying current time indicator with specific time zone
timezone: ^0.10.0

dev_dependencies:
supernova:
Expand Down
34 changes: 24 additions & 10 deletions lib/src/components/now_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/material.dart';
import '../config.dart';
import '../date/controller.dart';
import '../theme.dart';
import '../time/controller.dart';
import '../utils.dart';

/// A widget that displays an indicator at the current date and time.
Expand Down Expand Up @@ -36,7 +37,8 @@ class NowIndicator extends StatelessWidget {
Widget build(BuildContext context) {
return CustomPaint(
foregroundPainter: _NowIndicatorPainter(
controller: DefaultDateController.of(context)!,
dateController: DefaultDateController.of(context)!,
timeController: DefaultTimeController.of(context)!,
style: style ?? TimetableTheme.orDefaultOf(context).nowIndicatorStyle,
devicePixelRatio: context.mediaQuery.devicePixelRatio,
),
Expand Down Expand Up @@ -287,28 +289,36 @@ class TriangleNowIndicatorShape extends NowIndicatorShape {

class _NowIndicatorPainter extends CustomPainter {
factory _NowIndicatorPainter({
required DateController controller,
required DateController dateController,
required TimeController timeController,
required NowIndicatorStyle style,
required double devicePixelRatio,
}) =>
_NowIndicatorPainter._(
controller: controller,
dateController: dateController,
timeController: timeController,
style: style,
devicePixelRatio: devicePixelRatio,
repaintNotifier: ValueNotifier(DateTimeTimetable.now()),
repaintNotifier: ValueNotifier(
timeController.useTimeZone
? DateTimeTimetable.nowAt(timeController.tzIdentifier!)
: DateTimeTimetable.now(),
),
);
_NowIndicatorPainter._({
required this.controller,
required this.dateController,
required this.timeController,
required this.style,
required this.devicePixelRatio,
required ValueNotifier<DateTime> repaintNotifier,
}) : _paint = Paint()
..color = style.lineColor
..strokeWidth = style.lineWidth,
_repaintNotifier = repaintNotifier,
super(repaint: Listenable.merge([controller, repaintNotifier]));
super(repaint: Listenable.merge([dateController, repaintNotifier]));

final DateController controller;
final DateController dateController;
final TimeController timeController;
final Paint _paint;
final NowIndicatorStyle style;
final double devicePixelRatio;
Expand All @@ -318,9 +328,11 @@ class _NowIndicatorPainter extends CustomPainter {
unawaited(_repaint?.cancel());
_repaint = null;

final pageValue = controller.value;
final pageValue = dateController.value;
final dateWidth = size.width / pageValue.visibleDayCount;
final now = DateTimeTimetable.now();
final now = timeController.useTimeZone
? DateTimeTimetable.nowAt(timeController.tzIdentifier!)
: DateTimeTimetable.now();
final temporalXOffset =
now.copyWith(isUtc: true).atStartOfDay.page - pageValue.page;
final left = temporalXOffset * dateWidth;
Expand All @@ -346,7 +358,9 @@ class _NowIndicatorPainter extends CustomPainter {
() {
// [ChangeNotifier.notifyListeners] is protected, so we use a
// [ValueNotifier] and always set a different time.
_repaintNotifier.value = DateTimeTimetable.now();
_repaintNotifier.value = timeController.useTimeZone
? DateTimeTimetable.nowAt(timeController.tzIdentifier!)
: DateTimeTimetable.now();
},
),
);
Expand Down
13 changes: 13 additions & 0 deletions lib/src/time/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class TimeController extends ValueNotifier<TimeRange> {
Duration? maxDuration,
TimeRange? initialRange,
TimeRange? maxRange,
this.tzIdentifier,
this.minDayHeight,
}) : assert(!minDuration.isNegative),
assert(minDuration <= maxPossibleDuration),
Expand All @@ -36,6 +37,7 @@ class TimeController extends ValueNotifier<TimeRange> {
maxRange == null ||
maxDuration <= maxRange.duration,
),
assert(tzIdentifier == null || tzIdentifier.isNotEmpty),
maxRange = maxRange ?? TimeRange.fullDay,
assert(minDayHeight == null || minDayHeight > 0),
assert(minDayHeight == null || minDayHeight.isFinite),
Expand Down Expand Up @@ -85,11 +87,22 @@ class TimeController extends ValueNotifier<TimeRange> {
Duration get actualMaxDuration =>
maxDuration.coerceAtMost(maxDurationFromMinDayHeightOrDefault);

/// Whether the specified time zone is used when displaying current time.
bool get useTimeZone => tzIdentifier != null;

static const maxPossibleDuration = Duration(days: 1);

/// The maximum range that can be revealed when zooming out.
final TimeRange maxRange;

/// The time zone identifier that be used when displaying current time.
/// If null, the system time zone is used.
///
/// Note: Ensure timezone database is initialized before use
///
/// More information: [https://pub.dev/packages/timezone#initialization]
final String? tzIdentifier;

@override
set value(TimeRange value) {
assert(_isValidRange(value));
Expand Down
2 changes: 1 addition & 1 deletion lib/src/time/zoom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ class _RenderVerticalOverflowBox extends RenderShiftedBox {
class _ScaleGestureRecognizer extends OneSequenceGestureRecognizer {
_ScaleGestureRecognizer({
super.debugOwner,
// ignore: unused_element
// ignore: unused_element_parameter
this.dragStartBehavior = DragStartBehavior.down,
});

Expand Down
7 changes: 7 additions & 0 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'package:dart_date/dart_date.dart' show Interval;
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart' hide Interval;
import 'package:timezone/timezone.dart';

import 'week.dart';

Expand Down Expand Up @@ -88,6 +89,12 @@ extension DateTimeTimetable on DateTime {
return date;
}

static DateTime nowAt(String timezone) {
final date = TZDateTime.now(getLocation(timezone)).copyWith(isUtc: true);
assert(date.debugCheckIsValidTimetableDateTime());
return date;
}

static DateTime today() {
final date = DateTimeTimetable.now().atStartOfDay;
assert(date.debugCheckIsValidTimetableDate());
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ dependencies:
flutter_layout_grid: ^2.0.0
intl: '>=0.17.0 <0.21.0'
meta: ^1.3.0
timezone: ^0.10.0

dev_dependencies:
flutter_test:
Expand Down