From d3f990aecc695339c354bf8e1d6a2db938b82f8f Mon Sep 17 00:00:00 2001 From: Jonasz Bigda Date: Tue, 3 Nov 2020 19:22:08 +0100 Subject: [PATCH] settings --- lib/components/dishCard.dart | 25 ++- lib/components/homeScreen.dart | 381 +++++++++++++++++++++++++++------ lib/components/searchBar.dart | 10 +- lib/main.dart | 5 +- lib/settings.dart | 86 ++++++++ pubspec.lock | 119 +++++++++- pubspec.yaml | 1 + 7 files changed, 545 insertions(+), 82 deletions(-) create mode 100644 lib/settings.dart diff --git a/lib/components/dishCard.dart b/lib/components/dishCard.dart index 54e5c41..aab6b98 100644 --- a/lib/components/dishCard.dart +++ b/lib/components/dishCard.dart @@ -33,18 +33,29 @@ class DishCard extends StatelessWidget { ), Expanded( child: Row( - crossAxisAlignment: CrossAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - dish.name, - overflow: TextOverflow.ellipsis, - maxLines: 1, - style: TextStyle(color: Colors.orange[600], fontSize: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + dish.name, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle(color: Colors.orange[600], fontSize: 15), + ), + Text( + dish.weight, + overflow: TextOverflow.ellipsis, + maxLines: 1, + style: TextStyle(color: Colors.white, fontSize: 12), + ), + ], ), Text( '${dish.price} zł', - style: TextStyle(color: Colors.grey[300], fontSize: 14), + style: TextStyle(color: Colors.white, fontSize: 14), ), ], )), diff --git a/lib/components/homeScreen.dart b/lib/components/homeScreen.dart index 1c755b5..65d8661 100644 --- a/lib/components/homeScreen.dart +++ b/lib/components/homeScreen.dart @@ -1,19 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:geolocator/geolocator.dart'; import 'searchBar.dart'; +import '../settings.dart'; -class HomePage extends StatefulWidget { - HomePage({Key key}) : super(key: key); - - @override - _HomePageState createState() => _HomePageState(); -} - -class _HomePageState extends State { - void getLocation() async { - Position currentLocation = await Geolocator.getCurrentPosition(); - print(currentLocation); - } +class HomePage extends StatelessWidget { + final MenuiSettings settings = new MenuiSettings(); @override Widget build(BuildContext context) { @@ -37,7 +27,7 @@ class _HomePageState extends State { ), RaisedButton.icon( color: Colors.grey[850], - onPressed: getLocation, + onPressed: () {}, icon: Icon( Icons.my_location, color: Colors.orange, @@ -55,7 +45,7 @@ class _HomePageState extends State { ), floatingActionButton: FloatingActionButton( onPressed: () { - showSettings(); + showSettings(context); }, child: Icon( Icons.settings, @@ -66,63 +56,318 @@ class _HomePageState extends State { ); } - showSettings() { + // SHOW SETTINGS + + showSettings(BuildContext context) async { + FocusManager.instance.primaryFocus.unfocus(); + final String languageCode = await settings.getLanguage(); + final String language = settings.decodeLanguage(languageCode); + final int radius = await settings.getRadius(); + final bool recommendationsValue = await settings.getRecommendations(); + final recommendations = settings.decodeBool(recommendationsValue); + showModalBottomSheet( - backgroundColor: Colors.transparent, + backgroundColor: Colors.grey[850], + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(24), topRight: Radius.circular(24))), context: context, builder: (BuildContext context) { - return ClipRRect( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), topRight: Radius.circular(20)), - child: Container( - height: 260, - decoration: BoxDecoration(color: Colors.grey[850]), - child: ListView( - children: [ - ListTile( - title: Text( - 'Język', - style: TextStyle(color: Colors.grey), - ), - leading: Icon( - Icons.language, - color: Colors.orange, - ), - onTap: () {}), - ListTile( - title: Text( - 'Promień lokalizacji', - style: TextStyle(color: Colors.grey), - ), - leading: Icon( - Icons.location_searching_rounded, - color: Colors.orange, - ), - onTap: () {}), - ListTile( - title: Text( - 'Proponuj restauracje', - style: TextStyle(color: Colors.grey), - ), - leading: Icon( - Icons.restaurant, - color: Colors.orange, - ), - onTap: () {}), - ListTile( - title: Text( - 'O aplikacji', - style: TextStyle(color: Colors.grey), - ), - leading: Icon( - Icons.info, - color: Colors.grey, - ), - onTap: () {}), - ], - ), - ), + return ListView( + shrinkWrap: true, + physics: NeverScrollableScrollPhysics(), + children: [ + ListTile( + title: Text( + 'Język', + style: TextStyle(color: Colors.white), + ), + subtitle: Text( + language, + style: TextStyle(color: Colors.grey), + ), + leading: Icon( + Icons.language, + color: Colors.orange, + ), + onTap: () { + Navigator.pop(context); + showLanguageSelectionDialog(context); + }), + ListTile( + title: Text( + 'Promień lokalizacji', + style: TextStyle(color: Colors.white), + ), + subtitle: + Text('${radius}m', style: TextStyle(color: Colors.grey)), + leading: Icon( + Icons.location_searching_rounded, + color: Colors.orange, + ), + onTap: () { + Navigator.pop(context); + showRadiusSelectionDialog(context); + }), + ListTile( + title: Text( + 'Proponuj restauracje', + style: TextStyle(color: Colors.white), + ), + subtitle: Text(recommendations, + style: TextStyle(color: Colors.grey)), + leading: Icon( + Icons.notifications, + color: Colors.orange, + ), + onTap: () { + Navigator.pop(context); + showRecommendationsDialog(context); + }), + ListTile( + title: Text( + 'O aplikacji', + style: TextStyle(color: Colors.white), + ), + leading: Icon( + Icons.info, + color: Colors.grey, + ), + onTap: () { + Navigator.pop(context); + showAppInfoDialog(context); + }), + ], ); }); } + + // SELECT LANGUAGE + + void showLanguageSelectionDialog(BuildContext context) async { + final currentLanguage = await settings.getLanguage(); + showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + title: Text( + 'Język', + style: TextStyle(color: Colors.white, fontSize: 16), + textAlign: TextAlign.center, + ), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), + backgroundColor: Colors.grey[850], + children: [ + SimpleDialogOption( + onPressed: () { + settings.setLanguage('pl'); + Navigator.pop(context); + }, + child: Text( + 'Polski', + style: + TextStyle(color: getOptionColor(currentLanguage, 'pl')), + textAlign: TextAlign.center, + ), + ), + SimpleDialogOption( + onPressed: () { + settings.setLanguage('en'); + Navigator.pop(context); + }, + child: Text( + 'English', + style: + TextStyle(color: getOptionColor(currentLanguage, 'en')), + textAlign: TextAlign.center, + ), + ), + SimpleDialogOption( + onPressed: () { + settings.setLanguage('de'); + Navigator.pop(context); + }, + child: Text( + 'Deutsch', + style: + TextStyle(color: getOptionColor(currentLanguage, 'de')), + textAlign: TextAlign.center, + ), + ) + ], + ); + }); + } + + // SET SHOW RECOMMENDATIONS + + void showRecommendationsDialog(BuildContext context) async { + final showRecommendations = await settings.getRecommendations(); + showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + title: Text( + 'Polecaj restauracje w okolicy', + style: TextStyle(color: Colors.white, fontSize: 16), + textAlign: TextAlign.center, + ), + shape: + RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), + backgroundColor: Colors.grey[850], + children: [ + SimpleDialogOption( + onPressed: () { + settings.setRecommendations(true); + Navigator.pop(context); + }, + child: Text( + 'Tak', + style: TextStyle( + color: getOptionColor(showRecommendations, true)), + textAlign: TextAlign.center, + ), + ), + SimpleDialogOption( + onPressed: () { + settings.setRecommendations(false); + Navigator.pop(context); + }, + child: Text( + 'Nie', + style: TextStyle( + color: getOptionColor(showRecommendations, false)), + textAlign: TextAlign.center, + ), + ), + ], + ); + }); + } + + // SHOW APP INFO + + void showAppInfoDialog(BuildContext context) { + showDialog( + context: context, + builder: (BuildContext context) { + return SimpleDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(24)), + backgroundColor: Colors.grey[850], + children: [ + ListTile( + title: Text( + 'Wersja aplikacji', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white), + ), + subtitle: Text( + '0.0.1 (alpha)', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey), + )), + ListTile( + title: Text( + 'Wsparcie', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.white), + ), + subtitle: Text( + 'support@menui.pl', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey), + )), + Text( + 'Menui Sp. z o.o. - wszelkie prawa zastrzeżone.', + textAlign: TextAlign.center, + style: TextStyle(color: Colors.grey, fontSize: 12), + ) + ]); + }); + } + + // SELECT RADIUS + + void showRadiusSelectionDialog(BuildContext context) async { + final int currentRadius = await settings.getRadius(); + showDialog( + context: context, + builder: (BuildContext context) { + return RadiusSlider( + initialValue: currentRadius.toDouble(), + ); + }); + } + + Color getOptionColor(targetOption, thisOption) { + if (thisOption == targetOption) { + return Colors.orange; + } else { + return Colors.grey; + } + } +} + +class RadiusSlider extends StatefulWidget { + final double initialValue; + RadiusSlider({Key key, @required this.initialValue}) : super(key: key); + + @override + _RadiusSliderState createState() => + _RadiusSliderState(sliderValue: initialValue); +} + +class _RadiusSliderState extends State { + double sliderValue; + + _RadiusSliderState({this.sliderValue}); + + @override + Widget build(BuildContext context) { + return SimpleDialog( + title: Text( + 'Promień lokalizacji', + style: TextStyle(color: Colors.white, fontSize: 16), + textAlign: TextAlign.center, + ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)), + backgroundColor: Colors.grey[850], + children: [ + Slider( + value: sliderValue, + min: 300, + max: 3000, + divisions: 9, + label: formatDistance(sliderValue), + onChanged: (double value) { + setState(() { + sliderValue = value; + }); + }), + SimpleDialogOption( + onPressed: () async { + final MenuiSettings settings = new MenuiSettings(); + settings.setRadius(sliderValue.toInt()); + Navigator.pop(context); + }, + child: const Text( + 'Zapisz', + style: TextStyle(color: Colors.white), + textAlign: TextAlign.center, + ), + ), + ], + ); + } + + String formatDistance(double distance) { + if (distance > 1000) { + final double distanceInKM = distance / 1000; + return '${distanceInKM.toString()}km'; + } else { + return '${distance}m'; + } + } } diff --git a/lib/components/searchBar.dart b/lib/components/searchBar.dart index ba68988..bb602a7 100644 --- a/lib/components/searchBar.dart +++ b/lib/components/searchBar.dart @@ -15,6 +15,7 @@ class MenuiSearchBarState extends State { final LayerLink layerLink = LayerLink(); OverlayEntry _overlayEntry; final _controller = TextEditingController(); + String previousText = ''; var suggestions = []; bool suggestionsOpen = false; @@ -26,7 +27,8 @@ class MenuiSearchBarState extends State { } Future fetchAutocomplete() async { - if (_controller.text.isNotEmpty) { + if (_controller.text.isNotEmpty && _controller.text != previousText) { + previousText = _controller.text; final List results = await services.fetchAutocomplete(_controller.text); @@ -43,7 +45,6 @@ class MenuiSearchBarState extends State { } else if (results.isEmpty) { hideSuggestions(); } - print(suggestions); } else { hideSuggestions(); } @@ -76,6 +77,11 @@ class MenuiSearchBarState extends State { builder: (context) => GestureDetector( behavior: HitTestBehavior.translucent, onTap: () { + FocusScopeNode currentFocus = FocusScope.of(context); + print('12345'); + if (!currentFocus.hasPrimaryFocus) { + currentFocus.unfocus(); + } hideSuggestions(); }, child: Align( diff --git a/lib/main.dart b/lib/main.dart index 55509ae..19aa466 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -10,10 +10,7 @@ class App extends StatelessWidget { Widget build(BuildContext context) { return GestureDetector( onTap: () { - FocusScopeNode currentFocus = FocusScope.of(context); - if (!currentFocus.hasPrimaryFocus) { - currentFocus.focusedChild.unfocus(); - } + FocusManager.instance.primaryFocus.unfocus(); }, child: MaterialApp( title: 'Menui - food guide', diff --git a/lib/settings.dart b/lib/settings.dart new file mode 100644 index 0000000..07d959a --- /dev/null +++ b/lib/settings.dart @@ -0,0 +1,86 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class MenuiSettings { + // SET LANGUAGE + void setLanguage(String lang) async { + final settings = await SharedPreferences.getInstance(); + settings.setString('language', lang); + print('Language set to: $lang'); + } + + // GET LANGUAGE + Future getLanguage() async { + final settings = await SharedPreferences.getInstance(); + if (settings.containsKey('language')) { + final String language = settings.getString('language'); + return language; + } else { + settings.setString('language', 'pl'); + return 'pl'; + } + } + + // SET RADIUS + void setRadius(int radiusMeters) async { + final settings = await SharedPreferences.getInstance(); + settings.setInt('radius', radiusMeters); + print('Radius set to: $radiusMeters'); + } + + // GET RADIUS + Future getRadius() async { + final settings = await SharedPreferences.getInstance(); + if (settings.containsKey('radius')) { + final radius = settings.getInt('radius'); + return radius; + } else { + settings.setInt('radius', 600); + return 600; + } + } + + // SET RECOMMENDATIONS + void setRecommendations(bool recommend) async { + final settings = await SharedPreferences.getInstance(); + settings.setBool('recommendations', recommend); + print('Recommendations set to: $recommend'); + } + + // GET RECOMMENDATIONS + Future getRecommendations() async { + final settings = await SharedPreferences.getInstance(); + if (settings.containsKey('recommendations')) { + final recommend = settings.getBool('recommendations'); + return recommend; + } else { + settings.setBool('recommendations', false); + return false; + } + } + + // DECODE LANGUAGE + String decodeLanguage(String languageCode) { + String language; + switch (languageCode) { + case 'pl': + language = 'Polski'; + break; + case 'en': + language = 'English'; + break; + case 'de': + language = 'Deutsch'; + break; + } + return language; + } + + // DECODE BOOL + String decodeBool(bool value) { + if (value == true) { + return "Tak"; + } else { + return "Nie"; + } + } +} diff --git a/pubspec.lock b/pubspec.lock index ede8bc2..3404b71 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -57,6 +57,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.3" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "5.2.1" flutter: dependency: "direct main" description: flutter @@ -67,6 +81,11 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" geolocator: dependency: "direct main" description: @@ -95,6 +114,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "3.1.4" + intl: + dependency: transitive + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.16.1" matcher: dependency: transitive description: @@ -116,6 +142,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0-nullsafety.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+2" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.4+1" pedantic: dependency: transitive description: @@ -123,6 +170,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.9.2" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" plugin_platform_interface: dependency: transitive description: @@ -130,6 +184,55 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.3" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.13" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.12+2" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.2+2" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+10" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2+7" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.0.1+1" sky_engine: dependency: transitive description: flutter @@ -191,6 +294,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.1.0-nullsafety.3" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.2" sdks: dart: ">=2.10.0-110 <2.11.0" - flutter: ">=1.10.0" + flutter: ">=1.12.13+hotfix.5 <2.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9d5727f..a766548 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -25,6 +25,7 @@ dependencies: geolocator: ^6.1.0 flutter: sdk: flutter + shared_preferences: ^0.5.12 # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons.