diff --git a/lib/screens/timeline_screen.dart b/lib/screens/timeline_screen.dart index 7ffb656..4a11028 100644 --- a/lib/screens/timeline_screen.dart +++ b/lib/screens/timeline_screen.dart @@ -1,13 +1,125 @@ import 'package:flutter/material.dart'; -import 'package:share_location/widgets/timeline_scroll.dart'; +import 'package:provider/provider.dart'; +import 'package:share_location/extensions/date.dart'; +import 'package:share_location/models/timeline.dart'; +import 'package:share_location/utils/loadable.dart'; +import 'package:share_location/widgets/timeline_page.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; -class TimelineScreen extends StatelessWidget { +final supabase = Supabase.instance.client; + +class TimelineScreen extends StatefulWidget { static const ID = 'timeline'; - const TimelineScreen({Key? key}) : super(key: key); + final DateTime? date; + + const TimelineScreen({ + Key? key, + this.date, + }) : super(key: key); + + @override + State createState() => _TimelineScreenState(); +} + +class _TimelineScreenState extends State with Loadable { + final pageController = PageController(); + final timeline = TimelineModel(); + bool _ignorePageChanges = false; + + Future _goToPage(final int page) async { + _ignorePageChanges = true; + + await pageController.animateToPage( + page, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOutQuad, + ); + + _ignorePageChanges = false; + } + + @override + initState() { + super.initState(); + + timeline.initialize(); + + // Update page view + timeline.addListener(() async { + if (timeline.currentIndex != pageController.page) { + _goToPage(timeline.currentIndex); + } + }, ['currentIndex']); + + // Update page when initializing is done + timeline.addListener(() { + if (!mounted) { + return; + } + + setState(() {}); + + WidgetsBinding.instance.addPostFrameCallback((_) async { + final initialIndex = getIndexFromDate(); + + await _goToPage(initialIndex); + + timeline.setCurrentIndex(initialIndex); + }); + }, ['isInitializing']); + } + + @override + dispose() { + pageController.dispose(); + + super.dispose(); + } + + int getIndexFromDate() { + if (widget.date == null) { + return 0; + } + + return timeline.values.keys + .toList() + .indexWhere((date) => DateTime.parse(date).isSameDay(widget.date!)); + } @override Widget build(BuildContext context) { - return TimelineScroll(); + if (timeline.isInitializing) { + return const Center( + child: CircularProgressIndicator(), + ); + } + + return Scaffold( + body: ChangeNotifierProvider.value( + value: timeline, + child: PageView.builder( + controller: pageController, + scrollDirection: Axis.vertical, + itemCount: timeline.values.length, + onPageChanged: (newPage) { + if (_ignorePageChanges) { + return; + } + + if (timeline.currentIndex != newPage) { + // User manually changed page + timeline.setCurrentIndex(newPage); + + timeline.setMemoryIndex(0); + } + }, + itemBuilder: (_, index) => TimelinePage( + date: timeline.dateAtIndex(index), + memoryPack: timeline.atIndex(index), + ), + ), + ), + ); } } diff --git a/lib/widgets/calendar_month.dart b/lib/widgets/calendar_month.dart index f2aa685..9ded459 100644 --- a/lib/widgets/calendar_month.dart +++ b/lib/widgets/calendar_month.dart @@ -4,12 +4,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_calendar_widget/flutter_calendar_widget.dart'; import 'package:intl/intl.dart'; import 'package:share_location/constants/spacing.dart'; -import 'package:share_location/widgets/timeline_scroll.dart'; +import 'package:share_location/screens/timeline_screen.dart'; class MonthCalendarBuilder extends CalendarBuilder { @override Widget buildDayOfWeek(DateTime dateTime, String weekdayString) { - return SizedBox.shrink(); + return const SizedBox.shrink(); } @override @@ -123,10 +123,11 @@ class CalendarMonth extends StatelessWidget { startingDayOfWeek: DayOfWeek.mon, onDayPressed: (date) { Navigator.push( - context, - MaterialPageRoute( - builder: (context) => TimelineScroll(date: date), - )); + context, + MaterialPageRoute( + builder: (context) => TimelineScreen(date: date), + ), + ); }, style: const CalendarStyle( calenderMargin: EdgeInsets.symmetric(vertical: MEDIUM_SPACE), diff --git a/lib/widgets/timeline_scroll.dart b/lib/widgets/timeline_scroll.dart deleted file mode 100644 index 3d4ac16..0000000 --- a/lib/widgets/timeline_scroll.dart +++ /dev/null @@ -1,123 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; -import 'package:share_location/extensions/date.dart'; -import 'package:share_location/models/timeline.dart'; -import 'package:share_location/utils/loadable.dart'; -import 'package:share_location/widgets/timeline_page.dart'; -import 'package:supabase_flutter/supabase_flutter.dart'; - -final supabase = Supabase.instance.client; - -class TimelineScroll extends StatefulWidget { - final DateTime? date; - - TimelineScroll({ - Key? key, - this.date, - }) : super(key: key); - - @override - State createState() => _TimelineScrollState(); -} - -class _TimelineScrollState extends State with Loadable { - final pageController = PageController(); - final timeline = TimelineModel(); - bool _ignorePageChanges = false; - - Future _goToPage(final int page) async { - _ignorePageChanges = true; - - await pageController.animateToPage( - page, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOutQuad, - ); - - _ignorePageChanges = false; - } - - @override - initState() { - super.initState(); - - timeline.initialize(); - - // Update page view - timeline.addListener(() async { - if (timeline.currentIndex != pageController.page) { - _goToPage(timeline.currentIndex); - } - }, ['currentIndex']); - - // Update page when initializing is done - timeline.addListener(() { - if (!mounted) { - return; - } - - setState(() {}); - - WidgetsBinding.instance.addPostFrameCallback((_) async { - final initialIndex = getIndexFromDate(); - - await _goToPage(initialIndex); - - timeline.setCurrentIndex(initialIndex); - }); - }, ['isInitializing']); - } - - @override - dispose() { - pageController.dispose(); - - super.dispose(); - } - - int getIndexFromDate() { - if (widget.date == null) { - return 0; - } - - return timeline.values.keys - .toList() - .indexWhere((date) => DateTime.parse(date).isSameDay(widget.date!)); - } - - @override - Widget build(BuildContext context) { - if (timeline.isInitializing) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return Scaffold( - body: ChangeNotifierProvider.value( - value: timeline, - child: PageView.builder( - controller: pageController, - scrollDirection: Axis.vertical, - itemCount: timeline.values.length, - onPageChanged: (newPage) { - if (_ignorePageChanges) { - return; - } - - if (timeline.currentIndex != newPage) { - // User manually changed page - timeline.setCurrentIndex(newPage); - - timeline.setMemoryIndex(0); - } - }, - itemBuilder: (_, index) => TimelinePage( - date: timeline.dateAtIndex(index), - memoryPack: timeline.atIndex(index), - ), - ), - ), - ); - } -}