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

feat: support different calendars #14

Closed
wants to merge 2 commits into from
Closed
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
8 changes: 5 additions & 3 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ packages:
time_machine:
dependency: "direct main"
description:
name: time_machine
url: "https://pub.dartlang.org"
source: hosted
path: "."
ref: "fix/localdate-today-calendar"
resolved-ref: c65f0a3b8e98d9966684d091f34d44aaad024c20
url: "https://github.com/JonasWanke/time_machine.git"
source: git
version: "0.9.12"
timetable:
dependency: "direct main"
Expand Down
5 changes: 4 additions & 1 deletion example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ dependencies:

timetable:
path: ../
time_machine: ^0.9.12
time_machine:
git:
url: https://github.com/JonasWanke/time_machine.git
ref: fix/localdate-today-calendar

flutter:
uses-material-design: true
Expand Down
4 changes: 2 additions & 2 deletions lib/src/content/current_time_indicator_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ class CurrentTimeIndicatorPainter<E extends Event> extends CustomPainter {
void paint(Canvas canvas, Size size) {
final dateWidth = size.width / controller.visibleRange.visibleDays;

final temporalOffset =
LocalDate.today().epochDay - controller.scrollControllers.page;
final temporalOffset = LocalDate.today(controller.calendar).epochDay -
controller.scrollControllers.page;
final left = temporalOffset * dateWidth;
final right = left + dateWidth;

Expand Down
20 changes: 9 additions & 11 deletions lib/src/content/date_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import 'package:time_machine/time_machine.dart' hide Offset;
import '../event.dart';
import '../theme.dart';
import '../timetable.dart';
import '../utils/utils.dart';

class DateEvents<E extends Event> extends StatelessWidget {
DateEvents({
Expand Down Expand Up @@ -145,16 +144,17 @@ class _DayEventsLayoutDelegate<E extends Event>
final positions = _EventPositions();

var currentGroup = <E>[];
var currentEnd = TimetableLocalDateTime.minIsoValue;
LocalDateTime currentEnd;
for (final event in events) {
if (event.start >= currentEnd) {
if (currentEnd != null || event.start >= currentEnd) {
_endGroup(positions, currentGroup, height);
currentGroup = [];
currentEnd = TimetableLocalDateTime.minIsoValue;
currentEnd = null;
}

currentGroup.add(event);
currentEnd = currentEnd.coerceAtLeast(_actualEnd(event, height));
final eventEnd = _actualEnd(event, height);
currentEnd = currentEnd?.coerceAtLeast(eventEnd) ?? eventEnd;
}
_endGroup(positions, currentGroup, height);

Expand All @@ -177,7 +177,7 @@ class _DayEventsLayoutDelegate<E extends Event>
for (final event in currentGroup) {
var minColumn = -1;
var minIndex = 1 << 31;
var minEnd = TimetableLocalDateTime.minIsoValue;
LocalDateTime minEnd;
var columnFound = false;
for (var columnIndex = 0; columnIndex < columns.length; columnIndex++) {
final column = columns[columnIndex];
Expand All @@ -193,12 +193,10 @@ class _DayEventsLayoutDelegate<E extends Event>
.map((e) => positions.eventPositions[e].index)
.max() ??
-1;
final previousEnd = column.fold(
TimetableLocalDateTime.maxIsoValue,
(max, e) => LocalDateTime.max(max, e.end),
);
final previousEnd = column.map((e) => e.end).max();
// Further at the top and hence wider
if (index < minIndex || (index == minIndex && previousEnd < minEnd)) {
if (index < minIndex ||
(index == minIndex && minEnd != null && previousEnd < minEnd)) {
minColumn = columnIndex;
minIndex = index;
minEnd = previousEnd;
Expand Down
32 changes: 26 additions & 6 deletions lib/src/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,18 @@ import 'visible_range.dart';
/// Controls a [Timetable] and manages its state.
class TimetableController<E extends Event> {
TimetableController({
CalendarSystem calendar,
@required this.eventProvider,
LocalDate initialDate,
this.initialTimeRange = const InitialTimeRange.zoom(1),
this.visibleRange = const VisibleRange.week(),
this.firstDayOfWeek = DayOfWeek.monday,
}) : assert(eventProvider != null),
initialDate = initialDate ?? LocalDate.today(),
}) : calendar = calendar ?? _defaultCalendar,
assert(eventProvider != null),
initialDate =
initialDate ?? LocalDate.today(calendar ?? _defaultCalendar),
assert(initialDate == null || initialDate.calendar == calendar ??
_defaultCalendar),
assert(initialTimeRange != null),
assert(firstDayOfWeek != null),
assert(visibleRange != null) {
Expand All @@ -31,19 +36,32 @@ class TimetableController<E extends Event> {
);

_dateListenable = scrollControllers.pageListenable
.map((page) => LocalDate.fromEpochDay(page.floor()));
.map((page) => LocalDate.fromEpochDay(page.floor(), calendar));
_currentlyVisibleDatesListenable = scrollControllers.pageListenable
.map((page) {
return DateInterval(
LocalDate.fromEpochDay(page.floor()),
LocalDate.fromEpochDay(page.ceil() + visibleRange.visibleDays - 1),
LocalDate.fromEpochDay(page.floor(), calendar),
LocalDate.fromEpochDay(
page.ceil() + visibleRange.visibleDays - 1,
calendar,
),
);
})
..addListener(
() => eventProvider.onVisibleDatesChanged(currentlyVisibleDates));
eventProvider.onVisibleDatesChanged(currentlyVisibleDates);
}

static final _defaultCalendar = CalendarSystem.iso;

/// The [CalendarSystem] used for all dates and times.
///
/// All [LocalDate]s and [LocalDateTime]s you pass to timetable must use this
/// calendar.
///
/// Defaults to [CalendarSystem.iso].
final CalendarSystem calendar;

/// The [EventProvider] used for populating [Timetable] with events.
final EventProvider<E> eventProvider;

Expand Down Expand Up @@ -89,7 +107,7 @@ class TimetableController<E extends Event> {
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 200),
}) =>
animateTo(LocalDate.today(), curve: curve, duration: duration);
animateTo(LocalDate.today(calendar), curve: curve, duration: duration);

/// Animates the given [date] into view.
///
Expand All @@ -99,6 +117,8 @@ class TimetableController<E extends Event> {
Curve curve = Curves.easeInOut,
Duration duration = const Duration(milliseconds: 200),
}) async {
assert(date.calendar == calendar);

await scrollControllers.animateTo(
visibleRange.getTargetPageForFocusDate(date, firstDayOfWeek),
curve: curve,
Expand Down
9 changes: 7 additions & 2 deletions lib/src/date_page_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'event.dart';
import 'scroll_physics.dart';

typedef DateWidgetBuilder = Widget Function(
BuildContext context, LocalDate date);
BuildContext context,
LocalDate date,
);

class DatePageView<E extends Event> extends StatefulWidget {
const DatePageView({
Expand Down Expand Up @@ -58,7 +60,10 @@ class _DatePageViewState extends State<DatePageView> {
delegate: SliverChildBuilderDelegate(
(context, index) => widget.builder(
context,
LocalDate.fromEpochDay(index + visibleDays ~/ 2),
LocalDate.fromEpochDay(
index + visibleDays ~/ 2,
widget.controller.calendar,
),
),
),
),
Expand Down
8 changes: 8 additions & 0 deletions lib/src/event.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ abstract class Event {
// End of the event; exclusive.
final LocalDateTime end;

CalendarSystem get calendar {
// TODO(JonasWanke): Check this in the constructor
assert(start.calendar == end.calendar);
return start.calendar;
}

bool get isAllDay => start.periodUntil(end).normalize().days >= 1;
bool get isPartDay => !isAllDay;

Expand All @@ -52,6 +58,8 @@ extension TimetableEvent on Event {
intersectsInterval(DateInterval(date, date));

bool intersectsInterval(DateInterval interval) {
assert(calendar == interval.calendar);

return start.calendarDate <= interval.end &&
endDateInclusive >= interval.start;
}
Expand Down
3 changes: 2 additions & 1 deletion lib/src/header/all_day_events.dart
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ class _EventsLayout<E extends Event> extends RenderBox

double _parallelEventCount() {
int parallelEventsFrom(int page) {
final startDate = LocalDate.fromEpochDay(page);
final startDate =
LocalDate.fromEpochDay(page, currentlyVisibleDates.calendar);
final interval = DateInterval(
startDate,
startDate + Period(days: visibleRange.visibleDays - 1),
Expand Down
4 changes: 3 additions & 1 deletion lib/src/header/date_header.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import 'date_indicator.dart';
import 'weekday_indicator.dart';

class DateHeader extends StatelessWidget {
const DateHeader(this.date, {Key key}) : super(key: key);
const DateHeader(this.date, {Key key})
: assert(date != null),
super(key: key);

final LocalDate date;

Expand Down
6 changes: 4 additions & 2 deletions lib/src/header/date_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import '../theme.dart';
import '../utils/utils.dart';

class DateIndicator extends StatelessWidget {
const DateIndicator(this.date, {Key key}) : super(key: key);
const DateIndicator(this.date, {Key key})
: assert(date != null),
super(key: key);

final LocalDate date;

Expand Down Expand Up @@ -44,7 +46,7 @@ class DateIndicator extends StatelessWidget {

static Set<MaterialState> statesFor(LocalDate date) {
return {
if (date < LocalDate.today()) MaterialState.disabled,
if (date < LocalDate.today(date.calendar)) MaterialState.disabled,
if (date.isToday) MaterialState.selected,
};
}
Expand Down
4 changes: 3 additions & 1 deletion lib/src/header/weekday_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import '../utils/utils.dart';
import 'date_indicator.dart';

class WeekdayIndicator extends StatelessWidget {
const WeekdayIndicator(this.date, {Key key}) : super(key: key);
const WeekdayIndicator(this.date, {Key key})
: assert(date != null),
super(key: key);

static final _pattern = LocalDatePattern.createWithCurrentCulture('ddd');

Expand Down
9 changes: 1 addition & 8 deletions lib/src/utils/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@ import 'package:flutter/foundation.dart';
import 'package:time_machine/time_machine.dart';

extension TimetableLocalDate on LocalDate {
bool get isToday => this == LocalDate.today();
bool get isToday => this == LocalDate.today(calendar);
}

final List<int> innerDateHours =
List.generate(TimeConstants.hoursPerDay - 1, (i) => i + 1);

extension TimetableLocalDateTime on LocalDateTime {
static LocalDateTime minIsoValue =
LocalDate.minIsoValue.at(LocalTime.minValue);
static LocalDateTime maxIsoValue =
LocalDate.maxIsoValue.at(LocalTime.maxValue);
}

extension TimetableDateInterval on DateInterval {
Iterable<LocalDate> get dates => Iterable.generate(length, start.addDays);
}
Expand Down
5 changes: 4 additions & 1 deletion lib/src/visible_range.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ abstract class VisibleRange {

/// Convenience method of [getTargetPageForFocus] taking a [LocalDate].
double getTargetPageForFocusDate(
LocalDate focusDate, DayOfWeek firstDayOfWeek) {
LocalDate focusDate,
DayOfWeek firstDayOfWeek,
) {
assert(focusDate != null);

return getTargetPageForFocus(focusDate.epochDay.toDouble(), firstDayOfWeek);
}

Expand Down
5 changes: 4 additions & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ dependencies:
meta: ^1.1.8
pedantic: ^1.8.0+1
rxdart: ^0.24.0
time_machine: ^0.9.12
time_machine:
git:
url: https://github.com/JonasWanke/time_machine.git
ref: fix/localdate-today-calendar

dev_dependencies:
flutter_test:
Expand Down