From 3f1fe463bfdafae67995f3de2fcc699115c3d881 Mon Sep 17 00:00:00 2001 From: Remy Moll Date: Mon, 18 Nov 2024 17:42:52 +0100 Subject: [PATCH] better help and onboarding --- ...otlin-compiler-17075128324497521906.salive | 0 frontend/lib/main.dart | 4 +- .../current_trip_loading_indicator.dart | 2 +- frontend/lib/modules/current_trip_panel.dart | 2 +- .../lib/modules/current_trip_save_button.dart | 76 +++++++++------- frontend/lib/modules/help_dialog.dart | 25 ++++++ frontend/lib/modules/landmark_card.dart | 1 - frontend/lib/modules/new_trip_button.dart | 4 +- frontend/lib/modules/onboarding_card.dart | 68 +++++++------- frontend/lib/modules/trips_saved_list.dart | 7 +- .../lib/{layout.dart => pages/base_page.dart} | 88 +++++++------------ frontend/lib/pages/current_trip.dart | 11 ++- frontend/lib/pages/new_trip_location.dart | 33 ++++--- frontend/lib/pages/new_trip_preferences.dart | 72 +++++++++------ frontend/lib/pages/onboarding.dart | 63 +++++++++++-- frontend/lib/pages/settings.dart | 52 ++++++----- frontend/lib/utils/get_first_page.dart | 27 ++++++ frontend/lib/utils/load_trips.dart | 3 - frontend/test/widget_test.dart | 30 ------- 19 files changed, 326 insertions(+), 242 deletions(-) create mode 100644 frontend/android/.kotlin/sessions/kotlin-compiler-17075128324497521906.salive create mode 100644 frontend/lib/modules/help_dialog.dart rename frontend/lib/{layout.dart => pages/base_page.dart} (61%) create mode 100644 frontend/lib/utils/get_first_page.dart delete mode 100644 frontend/test/widget_test.dart diff --git a/frontend/android/.kotlin/sessions/kotlin-compiler-17075128324497521906.salive b/frontend/android/.kotlin/sessions/kotlin-compiler-17075128324497521906.salive new file mode 100644 index 0000000..e69de29 diff --git a/frontend/lib/main.dart b/frontend/lib/main.dart index 77c7616..8e87dc3 100644 --- a/frontend/lib/main.dart +++ b/frontend/lib/main.dart @@ -1,6 +1,6 @@ +import 'package:anyway/utils/get_first_page.dart'; import 'package:flutter/material.dart'; import 'package:anyway/constants.dart'; -import 'package:anyway/layout.dart'; void main() => runApp(const App()); @@ -14,7 +14,7 @@ class App extends StatelessWidget { Widget build(BuildContext context) { return MaterialApp( title: APP_NAME, - home: BasePage(mainScreen: "map"), + home: getFirstPage(), theme: APP_THEME, scaffoldMessengerKey: rootScaffoldMessengerKey ); diff --git a/frontend/lib/modules/current_trip_loading_indicator.dart b/frontend/lib/modules/current_trip_loading_indicator.dart index 3072f72..1f81d60 100644 --- a/frontend/lib/modules/current_trip_loading_indicator.dart +++ b/frontend/lib/modules/current_trip_loading_indicator.dart @@ -73,4 +73,4 @@ class _CurrentTripLoadingIndicatorState extends State { const Padding(padding: EdgeInsets.only(top: 10)), - Center(child: saveButton(widget.trip)), + Center(child: saveButton(trip: widget.trip)), ], ); } diff --git a/frontend/lib/modules/current_trip_save_button.dart b/frontend/lib/modules/current_trip_save_button.dart index f4587cf..03ffe66 100644 --- a/frontend/lib/modules/current_trip_save_button.dart +++ b/frontend/lib/modules/current_trip_save_button.dart @@ -5,37 +5,51 @@ import 'package:auto_size_text/auto_size_text.dart'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; -Widget saveButton(Trip trip) => ElevatedButton( - onPressed: () async { - SharedPreferences prefs = await SharedPreferences.getInstance(); - trip.toPrefs(prefs); - rootScaffoldMessengerKey.currentState!.showSnackBar( - SnackBar( - content: Text('Trip saved'), - duration: Duration(seconds: 2), - dismissDirection: DismissDirection.horizontal + +class saveButton extends StatefulWidget { + Trip trip; + saveButton({super.key, required this.trip}); + + @override + State createState() => _saveButtonState(); +} + +class _saveButtonState extends State { + @override + Widget build(BuildContext context) { + return ElevatedButton( + onPressed: () async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + setState(() => widget.trip.toPrefs(prefs)); + rootScaffoldMessengerKey.currentState!.showSnackBar( + SnackBar( + content: Text('Trip saved'), + duration: Duration(seconds: 2), + dismissDirection: DismissDirection.horizontal + ) + ); + }, + child: SizedBox( + width: 100, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.save, + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 10, top: 5, bottom: 5, right: 5), + child: AutoSizeText( + 'Save trip', + maxLines: 2, + ), + ), + ), + ], + ), ) ); - }, - child: SizedBox( - width: 100, - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon( - Icons.save, - ), - Expanded( - child: Padding( - padding: EdgeInsets.only(left: 10, top: 5, bottom: 5, right: 5), - child: AutoSizeText( - 'Save trip', - maxLines: 2, - ), - ), - ), - ], - ), - ) -); + } +} diff --git a/frontend/lib/modules/help_dialog.dart b/frontend/lib/modules/help_dialog.dart new file mode 100644 index 0000000..75db7b0 --- /dev/null +++ b/frontend/lib/modules/help_dialog.dart @@ -0,0 +1,25 @@ + +import 'package:flutter/material.dart'; + +Future helpDialog(BuildContext context, String title, String content) { + return showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: Text(title), + content: Text(content), + actions: [ + TextButton( + style: TextButton.styleFrom( + textStyle: Theme.of(context).textTheme.labelLarge, + ), + child: const Text('Got it!'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ], + ); + }, + ); +} diff --git a/frontend/lib/modules/landmark_card.dart b/frontend/lib/modules/landmark_card.dart index 3ba17ef..8b2d824 100644 --- a/frontend/lib/modules/landmark_card.dart +++ b/frontend/lib/modules/landmark_card.dart @@ -17,7 +17,6 @@ class LandmarkCard extends StatefulWidget { class _LandmarkCardState extends State { @override Widget build(BuildContext context) { - ThemeData theme = Theme.of(context); return Container( height: 160, child: Card( diff --git a/frontend/lib/modules/new_trip_button.dart b/frontend/lib/modules/new_trip_button.dart index ebc1c5b..9dca910 100644 --- a/frontend/lib/modules/new_trip_button.dart +++ b/frontend/lib/modules/new_trip_button.dart @@ -1,5 +1,5 @@ -import 'package:anyway/layout.dart'; import 'package:anyway/main.dart'; +import 'package:anyway/pages/current_trip.dart'; import 'package:anyway/structs/preferences.dart'; import 'package:anyway/structs/trip.dart'; import 'package:anyway/utils/fetch_trip.dart'; @@ -57,7 +57,7 @@ class _NewTripButtonState extends State { fetchTrip(trip, widget.preferences); Navigator.of(context).push( MaterialPageRoute( - builder: (context) => BasePage(mainScreen: "map", trip: trip) + builder: (context) => TripPage(trip: trip) ) ); } diff --git a/frontend/lib/modules/onboarding_card.dart b/frontend/lib/modules/onboarding_card.dart index 4124754..05fc340 100644 --- a/frontend/lib/modules/onboarding_card.dart +++ b/frontend/lib/modules/onboarding_card.dart @@ -2,13 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; class OnboardingCard extends StatelessWidget { - int index; - String title; - String description; - String imagePath; + final String title; + final String description; + final String imagePath; - OnboardingCard({ - required this.index, + const OnboardingCard({ required this.title, required this.description, required this.imagePath, @@ -16,41 +14,35 @@ class OnboardingCard extends StatelessWidget { @override Widget build(BuildContext context) { - Color baseColor = Theme.of(context).colorScheme.secondary; - // have a different color for each card, incrementing the hue - Color currentColor = baseColor.withAlpha(baseColor.alpha - index * 30); - return Container( - color: currentColor, - alignment: Alignment.center, - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - title, - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: Colors.white, - ), + + return Padding( + padding: EdgeInsets.all(20), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + title, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Colors.white, ), - Padding(padding: EdgeInsets.only(top: 20)), - SvgPicture.asset( - imagePath, - height: 200, - ), - Padding(padding: EdgeInsets.only(top: 20)), - Text( - description, - style: TextStyle( - fontSize: 16, - ), + ), + Padding(padding: EdgeInsets.only(top: 20)), + SvgPicture.asset( + imagePath, + height: 200, + ), + Padding(padding: EdgeInsets.only(top: 20)), + Text( + description, + style: TextStyle( + fontSize: 16, ), + ), - ] - ), - ) + ] + ), ); } } \ No newline at end of file diff --git a/frontend/lib/modules/trips_saved_list.dart b/frontend/lib/modules/trips_saved_list.dart index 08fce0a..7f6f561 100644 --- a/frontend/lib/modules/trips_saved_list.dart +++ b/frontend/lib/modules/trips_saved_list.dart @@ -1,6 +1,6 @@ +import 'package:anyway/pages/current_trip.dart'; import 'package:flutter/material.dart'; -import 'package:anyway/layout.dart'; import 'package:anyway/structs/trip.dart'; @@ -16,7 +16,6 @@ class TripsOverview extends StatefulWidget { } class _TripsOverviewState extends State { - Widget listBuild (BuildContext context, AsyncSnapshot> snapshot) { List children; if (snapshot.hasData) { @@ -39,7 +38,7 @@ class _TripsOverviewState extends State { onTap: () { Navigator.of(context).push( MaterialPageRoute( - builder: (context) => BasePage(mainScreen: "map", trip: trip) + builder: (context) => TripPage(trip: trip) ) ); }, @@ -74,4 +73,4 @@ class _TripsOverviewState extends State { builder: listBuild, ); } -} \ No newline at end of file +} diff --git a/frontend/lib/layout.dart b/frontend/lib/pages/base_page.dart similarity index 61% rename from frontend/lib/layout.dart rename to frontend/lib/pages/base_page.dart index 3441f6b..0fd9434 100644 --- a/frontend/lib/layout.dart +++ b/frontend/lib/pages/base_page.dart @@ -1,3 +1,5 @@ +import 'package:anyway/modules/help_dialog.dart'; +import 'package:anyway/pages/current_trip.dart'; import 'package:anyway/pages/settings.dart'; import 'package:flutter/material.dart'; @@ -8,22 +10,24 @@ import 'package:anyway/modules/trips_saved_list.dart'; import 'package:anyway/utils/load_trips.dart'; import 'package:anyway/pages/new_trip_location.dart'; -import 'package:anyway/pages/current_trip.dart'; import 'package:anyway/pages/onboarding.dart'; -// BasePage is the scaffold that holds all other pages -// A side drawer is used to switch between pages +// BasePage is the scaffold that holds a child page and a side drawer +// The side drawer is the main way to switch between pages + class BasePage extends StatefulWidget { - final String mainScreen; - final Trip? trip; + final Widget mainScreen; + final Widget title; + final List helpTexts; const BasePage({ super.key, required this.mainScreen, - this.trip, + this.title = const Text(APP_NAME), + this.helpTexts = const [], }); @override @@ -34,53 +38,24 @@ class _BasePageState extends State { @override Widget build(BuildContext context) { - Widget currentView = const Text("loading..."); Future> trips = loadTrips(); - - - if (widget.mainScreen == "map") { - if (widget.trip != null) { - currentView = TripPage(trip: widget.trip!); - } else { - currentView = FutureBuilder( - future: trips, - builder: (context, snapshot) { - if (snapshot.hasData) { - List availableTrips = snapshot.data!; - if (availableTrips.isNotEmpty) { - return TripPage(trip: availableTrips[0]); - } else { - return Scaffold( - body: Center( - child: Text("Wow, so empty!"), - ), - floatingActionButton: FloatingActionButton.extended( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => const NewTripPage() - ) - ); - }, - label: Text("Plan a trip"), - ), - ); - } - } else { - return const Text("loading..."); - } - }, - ); - } - } else if (widget.mainScreen == "tutorial") { - currentView = OnboardingPage(); - } else if (widget.mainScreen == "settings") { - currentView = SettingsPage(); - } return Scaffold( - appBar: AppBar(title: Text(APP_NAME)), - body: Center(child: currentView), + appBar: AppBar( + title: widget.title, + actions: [ + IconButton( + icon: const Icon(Icons.help), + tooltip: 'Help', + onPressed: () { + if (widget.helpTexts.isNotEmpty) { + helpDialog(context, widget.helpTexts[0], widget.helpTexts[1]); + } + } + ), + ], + ), + body: Center(child: widget.mainScreen), drawer: Drawer( child: Column( children: [ @@ -104,7 +79,8 @@ class _BasePageState extends State { ListTile( title: const Text('Your Trips'), leading: const Icon(Icons.map), - selected: widget.mainScreen == "map", + // TODO: this is not working! + selected: widget.mainScreen is TripPage, onTap: () {}, trailing: ElevatedButton( onPressed: () { @@ -134,11 +110,12 @@ class _BasePageState extends State { ListTile( title: const Text('How to use'), leading: Icon(Icons.help), - selected: widget.mainScreen == "tutorial", + // TODO: this is not working! + selected: widget.mainScreen is OnboardingPage, onTap: () { Navigator.of(context).push( MaterialPageRoute( - builder: (context) => BasePage(mainScreen: "tutorial") + builder: (context) => OnboardingPage() ) ); }, @@ -148,11 +125,12 @@ class _BasePageState extends State { ListTile( title: const Text('Settings'), leading: const Icon(Icons.settings), - selected: widget.mainScreen == "settings", + // TODO: this is not working! + selected: widget.mainScreen is SettingsPage, onTap: () { Navigator.of(context).push( MaterialPageRoute( - builder: (context) => BasePage(mainScreen: "settings") + builder: (context) => SettingsPage() ) ); }, diff --git a/frontend/lib/pages/current_trip.dart b/frontend/lib/pages/current_trip.dart index 3fc1a71..7f59c3d 100644 --- a/frontend/lib/pages/current_trip.dart +++ b/frontend/lib/pages/current_trip.dart @@ -1,4 +1,5 @@ import 'package:anyway/constants.dart'; +import 'package:anyway/pages/base_page.dart'; import 'package:flutter/material.dart'; import 'package:sliding_up_panel/sliding_up_panel.dart'; @@ -31,7 +32,8 @@ class _TripPageState extends State { @override Widget build(BuildContext context) { - return SlidingUpPanel( + return BasePage( + mainScreen: SlidingUpPanel( // use panelBuilder instead of panel so that we can reuse the scrollcontroller for the listview panelBuilder: (scrollcontroller) => CurrentTripPanel(controller: scrollcontroller, trip: widget.trip), // using collapsed and panelBuilder seems to show both at the same time, so we include the greeter in the panelBuilder @@ -52,6 +54,13 @@ class _TripPageState extends State { color: Colors.black, ) ], + ), + title: FutureBuilder( + future: widget.trip.cityName, + builder: (context, snapshot) => Text( + 'Your trip to ${snapshot.hasData ? snapshot.data! : "..."}', + ) + ), ); } } diff --git a/frontend/lib/pages/new_trip_location.dart b/frontend/lib/pages/new_trip_location.dart index 7fb3b4b..2fba16f 100644 --- a/frontend/lib/pages/new_trip_location.dart +++ b/frontend/lib/pages/new_trip_location.dart @@ -1,5 +1,5 @@ -import 'package:anyway/modules/new_trip_button.dart'; import 'package:anyway/modules/new_trip_options_button.dart'; +import 'package:anyway/pages/base_page.dart'; import 'package:flutter/material.dart'; import "package:anyway/structs/trip.dart"; @@ -19,23 +19,28 @@ class _NewTripPageState extends State { final TextEditingController lonController = TextEditingController(); Trip trip = Trip(); + @override Widget build(BuildContext context) { // floating search bar and map as a background - return Scaffold( - appBar: AppBar( - title: const Text('New Trip'), + return BasePage( + mainScreen: Scaffold( + body: Stack( + children: [ + NewTripMap(trip), + Padding( + padding: EdgeInsets.all(15), + child: NewTripLocationSearch(trip), + ), + ], + ), + floatingActionButton: NewTripOptionsButton(trip: trip), ), - body: Stack( - children: [ - NewTripMap(trip), - Padding( - padding: EdgeInsets.all(15), - child: NewTripLocationSearch(trip), - ), - ], - ), - floatingActionButton: NewTripOptionsButton(trip: trip), + title: Text("New Trip"), + helpTexts: [ + "Setting the start location", + "To set the starting point, type a city name in the search bar. You can also navigate the map like you're used to and long press anywhere to set a starting point." + ], ); } } diff --git a/frontend/lib/pages/new_trip_preferences.dart b/frontend/lib/pages/new_trip_preferences.dart index 882cb53..15b7066 100644 --- a/frontend/lib/pages/new_trip_preferences.dart +++ b/frontend/lib/pages/new_trip_preferences.dart @@ -1,4 +1,5 @@ import 'package:anyway/modules/new_trip_button.dart'; +import 'package:anyway/pages/base_page.dart'; import 'package:anyway/structs/preferences.dart'; import 'package:anyway/structs/trip.dart'; import 'package:flutter/cupertino.dart'; @@ -19,41 +20,54 @@ class _NewTripPreferencesPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - body: ListView( - children: [ - // Center( - // child: CircleAvatar( - // radius: 100, - // child: Icon(Icons.person, size: 100), - // ) - // ), - Padding(padding: EdgeInsets.only(top: 30)), - Center( - child: FutureBuilder( - future: widget.trip.cityName, - builder: (context, snapshot) => Text( - 'Your trip to ${snapshot.hasData ? snapshot.data! : "..."}', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold) - ) - ) - ), + return BasePage( + mainScreen: Scaffold( + body: ListView( + children: [ + // Center( + // child: CircleAvatar( + // radius: 100, + // child: Icon(Icons.person, size: 100), + // ) + // ), + // Padding(padding: EdgeInsets.only(top: 30)), + // Center( + // child: FutureBuilder( + // future: widget.trip.cityName, + // builder: (context, snapshot) => Text( + // 'Your trip to ${snapshot.hasData ? snapshot.data! : "..."}', + // style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold) + // ) + // ) + // ), - Center( - child: Padding( - padding: EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 0), - child: Text('Tell us about your ideal trip.', style: TextStyle(fontSize: 18)) + Center( + child: Padding( + padding: EdgeInsets.only(left: 10, right: 10, top: 20, bottom: 0), + child: Text('Tell us about your ideal trip.', style: TextStyle(fontSize: 18)) + ), ), - ), - Divider(indent: 25, endIndent: 25, height: 50), + Divider(indent: 25, endIndent: 25, height: 50), - durationPicker(preferences.maxTime), + durationPicker(preferences.maxTime), - preferenceSliders([preferences.sightseeing, preferences.shopping, preferences.nature]), - ] + preferenceSliders([preferences.sightseeing, preferences.shopping, preferences.nature]), + ] + ), + floatingActionButton: NewTripButton(trip: widget.trip, preferences: preferences), ), - floatingActionButton: NewTripButton(trip: widget.trip, preferences: preferences), + + title: FutureBuilder( + future: widget.trip.cityName, + builder: (context, snapshot) => Text( + 'Your trip to ${snapshot.hasData ? snapshot.data! : "..."}', + ) + ), + helpTexts: [ + 'Trip preferences', + 'Set your preferences for this trip. These will be used to generate a custom itinerary.' + ], ); } diff --git a/frontend/lib/pages/onboarding.dart b/frontend/lib/pages/onboarding.dart index e23a016..0f5dc25 100644 --- a/frontend/lib/pages/onboarding.dart +++ b/frontend/lib/pages/onboarding.dart @@ -2,6 +2,26 @@ import 'package:anyway/modules/onboarding_card.dart'; import 'package:anyway/pages/new_trip_location.dart'; import 'package:flutter/material.dart'; + +const List onboardingCards = [ + OnboardingCard( + title: "Welcome to anyway!", + description: "Anyway helps you plan a city trip that suits your wishes.", + imagePath: "assets/city.svg" + ), + OnboardingCard( + title: "Find your way", + description: "Bored by churches? No problem! Hate shopping? No worries! Instead of suggesting the generic trips that bore you, anyway will try to give you recommendations that really suit you.", + imagePath: "assets/plan.svg" + ), + OnboardingCard( + title: "Change your mind", + description: "Feet get sore, the weather changes. Anyway understands that! Move or remove destinations, visit hidden gems along your journey, do your own thing. Anyway adapts to your spontaneous decisions.", + imagePath: "assets/cat.svg" + ), +]; + + class OnboardingPage extends StatefulWidget { const OnboardingPage({super.key}); @@ -13,24 +33,32 @@ class _OnboardingPageState extends State { @override Widget build(BuildContext context) { final PageController _controller = PageController(); + return Scaffold( body: Stack( children: [ + // horizontally scrollable list of pages PageView( - // horizontally scrollable list of pages controller: _controller, - children: [ - OnboardingCard(index: 1, title: "Welcome to anyway!", description: "Anyway helps you plan a city trip that suits your wishes.", imagePath: "assets/city.svg"), - OnboardingCard(index: 2, title: "Find your way", description: "Bored by churches? No problem! Hate shopping? No worries! More than showing you the typical 'must-sees' of a city, anyway will try to give you recommendations that really suit you.", imagePath: "assets/plan.svg"), - OnboardingCard(index: 3, title: "Change your mind", description: "Life happens when you're busy making plans. Anyway understands that! Move or remove destinations, visit hidden gems along your journey, do your own thing. Anyway adapts to your spontaneous decisions.", imagePath: "assets/cat.svg"), - ], + children: List.generate( + onboardingCards.length, + (index) { + Color currentColor = Colors.red.withAlpha(Colors.red.alpha - index * 30); + return Container( + color: currentColor, + alignment: Alignment.center, + child: onboardingCards[index], + ); + } + ) ), ], ), - floatingActionButton: FloatingActionButton( + + floatingActionButton: FloatingActionButton.extended( onPressed: () { - if (_controller.page == 2) { + if (_controller.page == onboardingCards.length - 1) { Navigator.of(context).push( MaterialPageRoute( builder: (context) => const NewTripPage() @@ -40,7 +68,24 @@ class _OnboardingPageState extends State { _controller.nextPage(duration: Duration(milliseconds: 500), curve: Curves.ease); } }, - child: Icon(Icons.arrow_forward), + label: ListenableBuilder( + listenable: _controller, + builder: (context, child) { + if (_controller.page == onboardingCards.length - 1) { + // icon and text side by side + return Row( + children: [ + const Text("Start planning!"), + Padding(padding: const EdgeInsets.only(right: 8.0)), + const Icon(Icons.map_outlined) + ], + ); + + } else { + return const Icon(Icons.arrow_forward); + } + } + ) ), ); } diff --git a/frontend/lib/pages/settings.dart b/frontend/lib/pages/settings.dart index d4c69a0..3d5aff6 100644 --- a/frontend/lib/pages/settings.dart +++ b/frontend/lib/pages/settings.dart @@ -1,5 +1,6 @@ import 'package:anyway/constants.dart'; import 'package:anyway/main.dart'; +import 'package:anyway/pages/base_page.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -16,30 +17,37 @@ class SettingsPage extends StatefulWidget { class _SettingsPageState extends State { @override Widget build(BuildContext context) { - return ListView( - padding: EdgeInsets.all(15), - children: [ - // First a round, centered image - Center( - child: CircleAvatar( - radius: 75, - child: Icon(Icons.settings, size: 100), - ) - ), - Center( - child: Text('Global settings', style: TextStyle(fontSize: 24)) - ), + return BasePage( + mainScreen: ListView( + padding: EdgeInsets.all(15), + children: [ + // First a round, centered image + Center( + child: CircleAvatar( + radius: 75, + child: Icon(Icons.settings, size: 100), + ) + ), + Center( + child: Text('Global settings', style: TextStyle(fontSize: 24)) + ), - Divider(indent: 25, endIndent: 25, height: 50), + Divider(indent: 25, endIndent: 25, height: 50), - darkMode(), - setLocationUsage(), - setDebugMode(), + darkMode(), + setLocationUsage(), + setDebugMode(), - Divider(indent: 25, endIndent: 25, height: 50), + Divider(indent: 25, endIndent: 25, height: 50), - privacyInfo(), - ] + privacyInfo(), + ] + ), + title: Text('Settings'), + helpTexts: [ + 'Settings', + 'Preferences set in this page are global and will affect the entire application.' + ], ); } @@ -169,7 +177,9 @@ class _SettingsPageState extends State { return Center( child: Column( children: [ - Text('Our privacy policy is available under:'), + Text('AnyWay does not collect or store any of the data that is submitted via the app. The location of your trip is not stored. The location feature is only used to show your current location on the map, it is not transmitted to our servers.', textAlign: TextAlign.center), + Padding(padding: EdgeInsets.only(top: 3)), + Text('Our full privacy policy is available under:', textAlign: TextAlign.center), TextButton.icon( icon: Icon(Icons.info), diff --git a/frontend/lib/utils/get_first_page.dart b/frontend/lib/utils/get_first_page.dart new file mode 100644 index 0000000..161e957 --- /dev/null +++ b/frontend/lib/utils/get_first_page.dart @@ -0,0 +1,27 @@ +import 'package:anyway/pages/current_trip.dart'; +import 'package:anyway/pages/onboarding.dart'; +import 'package:anyway/structs/trip.dart'; +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(); + } + } 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 cd4bdd7..e54e899 100644 --- a/frontend/lib/utils/load_trips.dart +++ b/frontend/lib/utils/load_trips.dart @@ -1,7 +1,4 @@ -import 'dart:collection'; - import 'package:anyway/structs/trip.dart'; -import 'package:anyway/structs/landmark.dart'; import 'package:shared_preferences/shared_preferences.dart'; Future> loadTrips() async { diff --git a/frontend/test/widget_test.dart b/frontend/test/widget_test.dart deleted file mode 100644 index cb3797b..0000000 --- a/frontend/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility in the flutter_test package. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -// import 'package:anyway/main.dart'; -import 'package:anyway/layout.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(BasePage(mainScreen: "map",)); - - // Verfiy that the title is displayed - expect(find.text('City Nav'), findsOneWidget); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -}