diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 8e87dc3..5f3dc49 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,10 +1,12 @@ import 'package:anyway/utils/get_first_page.dart'; +import 'package:anyway/utils/load_trips.dart'; import 'package:flutter/material.dart'; import 'package:anyway/constants.dart'; void main() => runApp(const App()); final GlobalKey rootScaffoldMessengerKey = GlobalKey(); +final SavedTrips savedTrips = SavedTrips(); class App extends StatelessWidget { const App({super.key}); diff --git a/frontend/lib/modules/current_trip_save_button.dart b/frontend/lib/modules/current_trip_save_button.dart index 03ffe66..0b8e773 100644 --- a/frontend/lib/modules/current_trip_save_button.dart +++ b/frontend/lib/modules/current_trip_save_button.dart @@ -3,7 +3,6 @@ import 'package:anyway/main.dart'; import 'package:anyway/structs/trip.dart'; import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; -import 'package:shared_preferences/shared_preferences.dart'; class saveButton extends StatefulWidget { @@ -19,8 +18,9 @@ class _saveButtonState extends State { Widget build(BuildContext context) { return ElevatedButton( onPressed: () async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - setState(() => widget.trip.toPrefs(prefs)); + savedTrips.addTrip(widget.trip); + // SharedPreferences prefs = await SharedPreferences.getInstance(); + // setState(() => widget.trip.toPrefs(prefs)); rootScaffoldMessengerKey.currentState!.showSnackBar( SnackBar( content: Text('Trip saved'), diff --git a/frontend/lib/modules/trips_saved_list.dart b/frontend/lib/modules/trips_saved_list.dart index 7f6f561..fd53ada 100644 --- a/frontend/lib/modules/trips_saved_list.dart +++ b/frontend/lib/modules/trips_saved_list.dart @@ -1,11 +1,12 @@ import 'package:anyway/pages/current_trip.dart'; +import 'package:anyway/utils/load_trips.dart'; import 'package:flutter/material.dart'; import 'package:anyway/structs/trip.dart'; class TripsOverview extends StatefulWidget { - final Future> trips; + final SavedTrips trips; const TripsOverview({ super.key, required this.trips, @@ -16,49 +17,34 @@ class TripsOverview extends StatefulWidget { } class _TripsOverviewState extends State { - Widget listBuild (BuildContext context, AsyncSnapshot> snapshot) { + Widget listBuild (BuildContext context, SavedTrips trips) { List children; - if (snapshot.hasData) { - children = List.generate(snapshot.data!.length, (index) { - Trip trip = snapshot.data![index]; - return ListTile( - title: FutureBuilder( - future: trip.cityName, - builder: (BuildContext context, AsyncSnapshot snapshot) { - if (snapshot.hasData) { - return Text("Trip to ${snapshot.data}"); - } else if (snapshot.hasError) { - return Text("Error: ${snapshot.error}"); - } else { - return const Text("Trip to ..."); - } - }, - ), - leading: Icon(Icons.pin_drop), - onTap: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => TripPage(trip: trip) - ) - ); + List items = trips.trips; + children = List.generate(items.length, (index) { + Trip trip = items[index]; + return ListTile( + title: FutureBuilder( + future: trip.cityName, + builder: (BuildContext context, AsyncSnapshot snapshot) { + if (snapshot.hasData) { + return Text("Trip to ${snapshot.data}"); + } else if (snapshot.hasError) { + return Text("Error: ${snapshot.error}"); + } else { + return const Text("Trip to ..."); + } }, - ); - }); - } else if (snapshot.hasError) { - children = [ - const Icon( - Icons.error_outline, - color: Colors.red, - size: 60, ), - Padding( - padding: const EdgeInsets.only(top: 16), - child: Text('Error: ${snapshot.error}'), - ), - ]; - } else { - children = [Center(child: CircularProgressIndicator())]; - } + leading: Icon(Icons.pin_drop), + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => TripPage(trip: trip) + ) + ); + }, + ); + }); return ListView( children: children, @@ -68,9 +54,11 @@ class _TripsOverviewState extends State { @override Widget build(BuildContext context) { - return FutureBuilder( - future: widget.trips, - builder: listBuild, + return ListenableBuilder( + listenable: widget.trips, + builder: (BuildContext context, Widget? child) { + return listBuild(context, widget.trips); + } ); } } diff --git a/frontend/lib/pages/base_page.dart b/frontend/lib/pages/base_page.dart index 0fd9434..ce36f1f 100644 --- a/frontend/lib/pages/base_page.dart +++ b/frontend/lib/pages/base_page.dart @@ -1,3 +1,4 @@ +import 'package:anyway/main.dart'; import 'package:anyway/modules/help_dialog.dart'; import 'package:anyway/pages/current_trip.dart'; import 'package:anyway/pages/settings.dart'; @@ -38,7 +39,8 @@ class _BasePageState extends State { @override Widget build(BuildContext context) { - Future> trips = loadTrips(); + savedTrips.loadTrips(); + return Scaffold( appBar: AppBar( @@ -98,11 +100,11 @@ class _BasePageState extends State { // through the options in the drawer if there isn't enough vertical // space to fit everything. Expanded( - child: TripsOverview(trips: trips), + child: TripsOverview(trips: savedTrips), ), ElevatedButton( onPressed: () async { - removeAllTripsFromPrefs(); + savedTrips.clearTrips(); }, child: const Text('Clear trips'), ), diff --git a/frontend/lib/pages/onboarding.dart b/frontend/lib/pages/onboarding.dart index ff335e8..3692cb8 100644 --- a/frontend/lib/pages/onboarding.dart +++ b/frontend/lib/pages/onboarding.dart @@ -1,3 +1,6 @@ +import 'dart:ui'; + +import 'package:anyway/constants.dart'; import 'package:anyway/modules/onboarding_card.dart'; import 'package:anyway/pages/new_trip_location.dart'; import 'package:flutter/material.dart'; @@ -33,32 +36,51 @@ class OnboardingPage extends StatefulWidget { } class _OnboardingPageState extends State { + final PageController _controller = PageController(); + @override Widget build(BuildContext context) { - final PageController _controller = PageController(); - return Scaffold( body: Stack( children: [ - Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [Colors.red, Colors.blue], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), - ), - child: PageView( - controller: _controller, - children: List.generate( - onboardingCards.length, - (index) { - return Container( - alignment: Alignment.center, - child: onboardingCards[index], - ); - } - ), + AnimatedBuilder( + animation: _controller, + builder: (context, child) { + return Stack( + children: [ + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: APP_GRADIENT.colors, + stops: [ + (_controller.hasClients ? _controller.page ?? _controller.initialPage : _controller.initialPage) / onboardingCards.length, + (_controller.hasClients ? _controller.page ?? _controller.initialPage + 1 : _controller.initialPage + 1) / onboardingCards.length, + ], + ), + ), + ), + BackdropFilter( + filter: ImageFilter.blur(sigmaX: 100, sigmaY: 100), + child: Container( + color: Colors.black.withOpacity(0), + ), + ), + ], + ); + }, + ), + PageView( + controller: _controller, + children: List.generate( + onboardingCards.length, + (index) { + return Container( + alignment: Alignment.center, + child: onboardingCards[index], + ); + } ), ), ], @@ -75,10 +97,10 @@ class _OnboardingPageState extends State { _controller.nextPage(duration: Duration(milliseconds: 500), curve: Curves.ease); } }, - label: ListenableBuilder( - listenable: _controller, + label: AnimatedBuilder( + animation: _controller, builder: (context, child) { - if (_controller.page == onboardingCards.length - 1) { + if ((_controller.page ?? _controller.initialPage) == onboardingCards.length - 1) { return Row( children: [ const Text("Start planning!"), diff --git a/frontend/lib/structs/trip.dart b/frontend/lib/structs/trip.dart index 296ba25..44e12c3 100644 --- a/frontend/lib/structs/trip.dart +++ b/frontend/lib/structs/trip.dart @@ -113,10 +113,3 @@ LinkedList readLandmarks(SharedPreferences prefs, String? firstUUID) { } return landmarks; } - - - -void removeAllTripsFromPrefs () async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - prefs.clear(); -} diff --git a/frontend/lib/utils/get_first_page.dart b/frontend/lib/utils/get_first_page.dart index 161e957..e2dffd2 100644 --- a/frontend/lib/utils/get_first_page.dart +++ b/frontend/lib/utils/get_first_page.dart @@ -5,23 +5,37 @@ import 'package:anyway/utils/load_trips.dart'; import 'package:flutter/material.dart'; Widget getFirstPage() { - Future> trips = loadTrips(); - // test if there are any active trips - // if there are, return the trip list - // if there are not, return the onboarding page - return FutureBuilder( - future: trips, - builder: (context, snapshot) { - if (snapshot.hasData) { - List availableTrips = snapshot.data!; - if (availableTrips.isNotEmpty) { - return TripPage(trip: availableTrips[0]); - } else { - return OnboardingPage(); - } + SavedTrips trips = SavedTrips(); + trips.loadTrips(); + + return ListenableBuilder( + listenable: trips, + builder: (BuildContext context, Widget? child) { + List items = trips.trips; + if (items.isNotEmpty) { + return TripPage(trip: items[0]); } else { - return CircularProgressIndicator(); + return OnboardingPage(); } } ); + // Future> trips = loadTrips(); + // // test if there are any active trips + // // if there are, return the trip list + // // if there are not, return the onboarding page + // return FutureBuilder( + // future: trips, + // builder: (context, snapshot) { + // if (snapshot.hasData) { + // List availableTrips = snapshot.data!; + // if (availableTrips.isNotEmpty) { + // return TripPage(trip: availableTrips[0]); + // } else { + // return OnboardingPage(); + // } + // } else { + // return CircularProgressIndicator(); + // } + // } + // ); } \ No newline at end of file diff --git a/frontend/lib/utils/load_trips.dart b/frontend/lib/utils/load_trips.dart index e54e899..dbf7aa7 100644 --- a/frontend/lib/utils/load_trips.dart +++ b/frontend/lib/utils/load_trips.dart @@ -1,16 +1,39 @@ import 'package:anyway/structs/trip.dart'; import 'package:shared_preferences/shared_preferences.dart'; -Future> loadTrips() async { - SharedPreferences prefs = await SharedPreferences.getInstance(); +import 'package:flutter/foundation.dart'; - List trips = []; - Set keys = prefs.getKeys(); - for (String key in keys) { - if (key.startsWith('trip_')) { - String uuid = key.replaceFirst('trip_', ''); - trips.add(Trip.fromPrefs(prefs, uuid)); +class SavedTrips extends ChangeNotifier { + List _trips = []; + + List get trips => _trips; + + void loadTrips() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + + List trips = []; + Set keys = prefs.getKeys(); + for (String key in keys) { + if (key.startsWith('trip_')) { + String uuid = key.replaceFirst('trip_', ''); + trips.add(Trip.fromPrefs(prefs, uuid)); + } } + _trips = trips; + notifyListeners(); + } + + void addTrip(Trip trip) async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + trip.toPrefs(prefs); + _trips.add(trip); + notifyListeners(); + } + + void clearTrips () async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + prefs.clear(); + _trips = []; + notifyListeners(); } - return trips; }