From c8da127f6ed936dd50168efc084aca281bb47310 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:07:24 +0300 Subject: [PATCH 01/85] Create settings button --- .../widgets/misc/AppBar/settings_button.dart | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart new file mode 100644 index 0000000..468fbad --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; + +class SettingsButton extends StatelessWidget { + const SettingsButton({super.key}); + + @override + Widget build(BuildContext context) { + return IconButton( + icon: Icon( + Icons.settings, + color: Colors.black, + ), + onPressed: (){ + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + backgroundColor: CustomColors.yellow.color, + builder:(context) { + return _buildBottomSheetMenu(context); + }, + ); + }, + ); + } + + Widget _buildBottomSheetMenu(BuildContext context){ + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), + ); + } +} \ No newline at end of file From 9f25be6377c8ee78dc7c29d98100f6b86e7813bf Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:07:48 +0300 Subject: [PATCH 02/85] Add settings button to the appbar --- .../widgets/misc/AppBar/appbar.dart | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart index bc2c03c..0a85c1b 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/AppBar/settings_button.dart'; class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ final String title; @@ -10,13 +11,15 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ return AppBar( backgroundColor: Colors.transparent, elevation: 0, - title: Center( - child: Text( - title, - style: const TextStyle( - fontWeight: FontWeight.bold - ), - ) + centerTitle: true, + actions: [ + SettingsButton() + ], + title: Text( + title, + style: const TextStyle( + fontWeight: FontWeight.bold + ), ), ); } From 9988f27623226f0f59682ac787ed5b74dfb2f023 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:18:54 +0300 Subject: [PATCH 03/85] Make SettingsButton animated --- .../widgets/misc/AppBar/settings_button.dart | 70 ++++++++++++++----- 1 file changed, 52 insertions(+), 18 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart index 468fbad..f63bc14 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -1,29 +1,63 @@ import 'package:flutter/material.dart'; import 'package:weathque/config/theme/custom_colors.dart'; -class SettingsButton extends StatelessWidget { +class SettingsButton extends StatefulWidget { const SettingsButton({super.key}); + @override + State createState() => _SettingsButtonState(); +} + +class _SettingsButtonState extends State with TickerProviderStateMixin { + late AnimationController _controller; + late Animation _animation; + + @override + void initState() { + _controller = AnimationController( + duration: const Duration(milliseconds: 500), + vsync: this, + ); + _animation = CurvedAnimation( + parent: _controller, + curve: Curves.easeOutSine + ); + + super.initState(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { - return IconButton( - icon: Icon( - Icons.settings, - color: Colors.black, + return RotationTransition( + turns: _animation, + child: IconButton( + icon: Icon( + Icons.settings, + color: Colors.black, + ), + onPressed: (){ + _controller.reset(); + _controller.forward(); + + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20.0), + ), + backgroundColor: CustomColors.yellow.color, + builder:(context) { + return _buildBottomSheetMenu(context); + }, + ); + }, ), - onPressed: (){ - showModalBottomSheet( - context: context, - isScrollControlled: true, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), - ), - backgroundColor: CustomColors.yellow.color, - builder:(context) { - return _buildBottomSheetMenu(context); - }, - ); - }, ); } From 7b87cefe51a00c792897314903f7d729ab107d12 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 13:20:27 +0300 Subject: [PATCH 04/85] Change border radius --- .../app/presentation/widgets/misc/AppBar/settings_button.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart index f63bc14..f535858 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -49,7 +49,7 @@ class _SettingsButtonState extends State with TickerProviderStat context: context, isScrollControlled: true, shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(20.0), + borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), ), backgroundColor: CustomColors.yellow.color, builder:(context) { From 891ebe1c2bacb01af65db73e09170119589c6f1f Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 18:16:18 +0300 Subject: [PATCH 05/85] Stylize TextField --- .../widgets/misc/AppBar/settings_button.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart index f535858..2d4a6b4 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -65,6 +65,36 @@ class _SettingsButtonState extends State with TickerProviderStat return Container( width: double.infinity, height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TextField( + cursorColor: Colors.black, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + hintText: "Enter a city", + labelText: "City", + labelStyle: TextStyle( + color: Colors.black + ), + suffixIcon: IconButton( + icon: Icon(Icons.search, color: Colors.black), + onPressed: (){}, + ) + ), + ) + ], + ), + ), ); } } \ No newline at end of file From 22489897a8e1715d71c19fb3c7c5b60a2e496495 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 18:33:26 +0300 Subject: [PATCH 06/85] Move showModalBottomSheet into separate file --- .../widgets/misc/AppBar/settings_button.dart | 51 ++---------------- .../misc/bottom_sheet/bottom_sheet.dart | 53 +++++++++++++++++++ 2 files changed, 56 insertions(+), 48 deletions(-) create mode 100644 lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart index 2d4a6b4..cd07557 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:weathque/config/theme/custom_colors.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart'; class SettingsButton extends StatefulWidget { const SettingsButton({super.key}); @@ -45,56 +45,11 @@ class _SettingsButtonState extends State with TickerProviderStat _controller.reset(); _controller.forward(); - showModalBottomSheet( - context: context, - isScrollControlled: true, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), - ), - backgroundColor: CustomColors.yellow.color, - builder:(context) { - return _buildBottomSheetMenu(context); - }, - ); + showCustomBottomSheet(context); }, ), ); } - Widget _buildBottomSheetMenu(BuildContext context){ - return Container( - width: double.infinity, - height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - TextField( - cursorColor: Colors.black, - decoration: InputDecoration( - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - hintText: "Enter a city", - labelText: "City", - labelStyle: TextStyle( - color: Colors.black - ), - suffixIcon: IconButton( - icon: Icon(Icons.search, color: Colors.black), - onPressed: (){}, - ) - ), - ) - ], - ), - ), - ); - } + } \ No newline at end of file diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart new file mode 100644 index 0000000..64299a3 --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -0,0 +1,53 @@ +import 'package:flutter/material.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; + +showCustomBottomSheet(BuildContext context){ + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), + ), + backgroundColor: CustomColors.yellow.color, + builder:(context) { + return _buildBottomSheetMenu(context); + }, + ); +} + +Widget _buildBottomSheetMenu(BuildContext context){ + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TextField( + cursorColor: Colors.black, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + hintText: "Enter a city", + labelText: "City", + labelStyle: TextStyle( + color: Colors.black + ), + suffixIcon: IconButton( + icon: Icon(Icons.search, color: Colors.black), + onPressed: (){}, + ) + ), + ) + ], + ), + ), + ); + } \ No newline at end of file From 596df84fcc43e83c8b5efa5d95c4f01273f03907 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 20:30:46 +0300 Subject: [PATCH 07/85] Make keyboard overlay the screen --- lib/features/app/presentation/pages/weather_page.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/app/presentation/pages/weather_page.dart b/lib/features/app/presentation/pages/weather_page.dart index a1ee9ae..f1acbd0 100644 --- a/lib/features/app/presentation/pages/weather_page.dart +++ b/lib/features/app/presentation/pages/weather_page.dart @@ -20,6 +20,7 @@ class WeatherPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( + resizeToAvoidBottomInset: false, backgroundColor: color, appBar: CustomAppBar(title: city), body: Row( From 84547a7cf829dc80d54d4314e0f4279b0a212787 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 18 Aug 2023 20:39:20 +0300 Subject: [PATCH 08/85] Change selectionHandle color --- lib/config/theme/app_themes.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/config/theme/app_themes.dart b/lib/config/theme/app_themes.dart index 6dcc44c..94cdb40 100644 --- a/lib/config/theme/app_themes.dart +++ b/lib/config/theme/app_themes.dart @@ -3,5 +3,8 @@ import 'package:flutter/material.dart'; ThemeData theme(){ return ThemeData( useMaterial3: true, + textSelectionTheme: TextSelectionThemeData( + selectionHandleColor: Colors.black + ) ); } \ No newline at end of file From 44f07bda120716d5ac418dd0fc9e6a4a38b2f616 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 15:27:07 +0300 Subject: [PATCH 09/85] Install fluttertoast package --- pubspec.lock | 13 +++++++++++++ pubspec.yaml | 1 + 2 files changed, 14 insertions(+) diff --git a/pubspec.lock b/pubspec.lock index 00fab57..0a6e172 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -267,6 +267,19 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + sha256: "474f7d506230897a3cd28c965ec21c5328ae5605fc9c400cd330e9e9d6ac175c" + url: "https://pub.dev" + source: hosted + version: "8.2.2" frontend_server_client: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 676bcc5..ae30f4d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: flutter_bloc: ^8.1.3 intl: ^0.18.1 flutter_carousel_slider: ^1.1.0 + fluttertoast: ^8.2.2 dev_dependencies: flutter_test: From 63b1c227b6f2092bc05c941207ba888db8b68d1a Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 17:06:18 +0300 Subject: [PATCH 10/85] Create custom toast --- .../widgets/misc/toast/custom_toast.dart | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 lib/features/app/presentation/widgets/misc/toast/custom_toast.dart diff --git a/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart new file mode 100644 index 0000000..dd0fa52 --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class CustomToast extends StatelessWidget { + final String text; + final bool isError; + + const CustomToast({super.key, required this.text, required this.isError}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(25.0), + color: isError ? Colors.redAccent : Colors.greenAccent, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(isError ? Icons.error_outline : Icons.check), + SizedBox( + width: 12.0, + ), + Text(text), + ], + ), + ); + } +} \ No newline at end of file From 8dc37a639420413e05c96fc10c0435a212dc72ff Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 17:06:28 +0300 Subject: [PATCH 11/85] Add toast builder --- lib/main.dart | 70 ++++++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b424282..0c4e659 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_carousel_slider/carousel_slider.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; @@ -33,41 +34,42 @@ class WeathqueApp extends StatelessWidget { ) ], child: MaterialApp( - theme: theme(), - // GetCurrentWeatherBloc - home: BlocBuilder( - builder: (_, currentWeatherState) { - if(currentWeatherState is GetCurrentWeatherLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(currentWeatherState is GetCurrentWeatherDone){ - return BlocBuilder( - builder: (_, forecastWeatherState) { - if(forecastWeatherState is GetWeatherForecastLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(forecastWeatherState is GetWeatherForecastDone){ - return CarouselSlider( - slideTransform: const CubeTransform(), - unlimitedMode: true, - children: [ - for (int i = 0; i < City.values.length; i++) - WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![City.values[i].string]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![City.values[i].string]!, - color: CustomColors.values[i].color, - city: City.values[i].string, - ), - ], - ); - } - return const SizedBox(); - }, - ); - } - return const SizedBox(); + builder: FToastBuilder(), + theme: theme(), + // GetCurrentWeatherBloc + home: BlocBuilder( + builder: (_, currentWeatherState) { + if(currentWeatherState is GetCurrentWeatherLoading){ + return LoadingPage(color: CustomColors.yellow.color); } - ) + if(currentWeatherState is GetCurrentWeatherDone){ + return BlocBuilder( + builder: (_, forecastWeatherState) { + if(forecastWeatherState is GetWeatherForecastLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(forecastWeatherState is GetWeatherForecastDone){ + return CarouselSlider( + slideTransform: const CubeTransform(), + unlimitedMode: true, + children: [ + for (int i = 0; i < City.values.length; i++) + WeatherPage( + weatherEntity: currentWeatherState.weatherEntity![City.values[i].string]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![City.values[i].string]!, + color: CustomColors.values[i].color, + city: City.values[i].string, + ), + ], + ); + } + return const SizedBox(); + }, + ); + } + return const SizedBox(); + } + ) ) ); } From 73b3132671ccccba796f6dbc830d4f9d482eb3c9 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 17:16:38 +0300 Subject: [PATCH 12/85] Add toast message --- .../misc/bottom_sheet/bottom_sheet.dart | 42 ++++++++++++++++++- .../widgets/misc/toast/custom_toast.dart | 6 ++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 64299a3..56529f3 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -1,5 +1,11 @@ import 'package:flutter/material.dart'; import 'package:weathque/config/theme/custom_colors.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:fluttertoast/fluttertoast.dart'; +import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; + +TextEditingController _cityController = TextEditingController(); showCustomBottomSheet(BuildContext context){ showModalBottomSheet( @@ -16,6 +22,9 @@ showCustomBottomSheet(BuildContext context){ } Widget _buildBottomSheetMenu(BuildContext context){ + FToast toastManager = FToast(); + toastManager.init(context); + return Container( width: double.infinity, height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), @@ -25,6 +34,10 @@ Widget _buildBottomSheetMenu(BuildContext context){ crossAxisAlignment: CrossAxisAlignment.center, children: [ TextField( + controller: _cityController, + onSubmitted: (value) { + print("Sibmitted"); + }, cursorColor: Colors.black, decoration: InputDecoration( enabledBorder: OutlineInputBorder( @@ -42,7 +55,34 @@ Widget _buildBottomSheetMenu(BuildContext context){ ), suffixIcon: IconButton( icon: Icon(Icons.search, color: Colors.black), - onPressed: (){}, + onPressed: () async { + String cityName = _cityController.text; + + try { + var response = await locator()(cityName: cityName); + } catch (_) { + CustomToast toast = CustomToast( + isError: true, + text: "This city cannot be found in the database", + ); + toastManager.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); + return; + } + + CustomToast toast = CustomToast( + isError: false, + text: "City was successfully saved", + ); + toastManager.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); + }, ) ), ) diff --git a/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart index dd0fa52..93da492 100644 --- a/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart +++ b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart @@ -19,9 +19,11 @@ class CustomToast extends StatelessWidget { children: [ Icon(isError ? Icons.error_outline : Icons.check), SizedBox( - width: 12.0, + width: 12.0, + ), + Expanded( + child: Text(text) ), - Text(text), ], ), ); From bd2898e7f5e50a0e6f27a73fb982478c42e15083 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 17:20:46 +0300 Subject: [PATCH 13/85] Mate text Flexible --- .../app/presentation/widgets/misc/toast/custom_toast.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart index 93da492..2a7c7d3 100644 --- a/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart +++ b/lib/features/app/presentation/widgets/misc/toast/custom_toast.dart @@ -21,7 +21,7 @@ class CustomToast extends StatelessWidget { SizedBox( width: 12.0, ), - Expanded( + Flexible( child: Text(text) ), ], From 6dca2761a8060c5f4482a9cc3c9d261147e0aa74 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 17:23:33 +0300 Subject: [PATCH 14/85] Make _onSubmit func --- .../misc/bottom_sheet/bottom_sheet.dart | 143 ++++++++++-------- 1 file changed, 77 insertions(+), 66 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 56529f3..b4ffe35 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -22,72 +22,83 @@ showCustomBottomSheet(BuildContext context){ } Widget _buildBottomSheetMenu(BuildContext context){ - FToast toastManager = FToast(); - toastManager.init(context); + FToast toastManager = FToast(); + toastManager.init(context); - return Container( - width: double.infinity, - height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), - child: Padding( - padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - TextField( - controller: _cityController, - onSubmitted: (value) { - print("Sibmitted"); - }, - cursorColor: Colors.black, - decoration: InputDecoration( - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - hintText: "Enter a city", - labelText: "City", - labelStyle: TextStyle( - color: Colors.black - ), - suffixIcon: IconButton( - icon: Icon(Icons.search, color: Colors.black), - onPressed: () async { - String cityName = _cityController.text; - - try { - var response = await locator()(cityName: cityName); - } catch (_) { - CustomToast toast = CustomToast( - isError: true, - text: "This city cannot be found in the database", - ); - toastManager.showToast( - child: toast, - gravity: ToastGravity.BOTTOM, - toastDuration: Duration(seconds: 2), - ); - return; - } - - CustomToast toast = CustomToast( - isError: false, - text: "City was successfully saved", - ); - toastManager.showToast( - child: toast, - gravity: ToastGravity.BOTTOM, - toastDuration: Duration(seconds: 2), - ); - }, - ) + return Container( + width: double.infinity, + height: MediaQuery.of(context).size.height - (kBottomNavigationBarHeight + kToolbarHeight), + child: Padding( + padding: EdgeInsets.symmetric(vertical: 30, horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + TextField( + controller: _cityController, + onSubmitted: (value) { + _onSubmit(toastManager); + }, + cursorColor: Colors.black, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) ), - ) - ], - ), + hintText: "Enter a city", + labelText: "City", + labelStyle: TextStyle( + color: Colors.black + ), + suffixIcon: IconButton( + icon: Icon(Icons.search, color: Colors.black), + onPressed: () { + _onSubmit(toastManager); + }, + ) + ), + ) + ], ), - ); - } \ No newline at end of file + ), + ); +} + +void _onSubmit(FToast toastManager) async { + String cityName = _cityController.text; + + try { + var response = await locator()(cityName: cityName); + } catch (_) { + _onError(toastManager); + return; + } + _onSuccess(toastManager); +} + +void _onError(FToast toastManager){ + CustomToast toast = CustomToast( + isError: true, + text: "This city cannot be found in the database", + ); + toastManager.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); +} + +void _onSuccess(FToast toastManager){ + CustomToast toast = CustomToast( + isError: false, + text: "City was successfully saved", + ); + toastManager.showToast( + child: toast, + gravity: ToastGravity.BOTTOM, + toastDuration: Duration(seconds: 2), + ); +} \ No newline at end of file From bbec716a0d07f70aa440bf077df35c81b5e694d6 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 18:30:16 +0300 Subject: [PATCH 15/85] Add shared preferences package --- pubspec.lock | 126 +++++++++++++++++++++++++++++++++++++++++++++++++-- pubspec.yaml | 1 + 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/pubspec.lock b/pubspec.lock index 0a6e172..eb6e360 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -217,14 +217,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + url: "https://pub.dev" + source: hosted + version: "2.1.0" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d" url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "6.1.4" fixnum: dependency: transitive description: @@ -440,6 +448,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: ba2b77f0c52a33db09fc8caf85b12df691bf28d983e84cf87ff6d693cfa007b3 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: bced5679c7df11190e1ddc35f3222c858f328fff85c3942e46e7f5589bf9eb84 + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: ee0e0d164516b90ae1f970bdf29f726f1aa730d7cfc449ecc74c495378b705da + url: "https://pub.dev" + source: hosted + version: "2.2.0" petitparser: dependency: transitive description: @@ -448,6 +480,22 @@ packages: url: "https://pub.dev" source: hosted version: "5.4.0" + platform: + dependency: transitive + description: + name: platform + sha256: "57c07bf82207aee366dfaa3867b3164e4f03a238a461a11b0e8a3a510d51203d" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "43798d895c929056255600343db8f049921cbec94d31ec87f1dc5c16c01935dd" + url: "https://pub.dev" + source: hosted + version: "2.1.5" pointycastle: dependency: transitive description: @@ -504,6 +552,62 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0+1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "0344316c947ffeb3a529eac929e1978fcd37c26be4e8468628bac399365a3ca1" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: fe8401ec5b6dcd739a0fe9588802069e608c3fdbfd3c3c93e546cf2f90438076 + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: d29753996d8eb8f7619a1f13df6ce65e34bc107bef6330739ed76f18b22310ef + url: "https://pub.dev" + source: hosted + version: "2.3.3" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "71d6806d1449b0a9d4e85e0c7a917771e672a3d5dc61149cc9fac871115018e1" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "23b052f17a25b90ff2b61aad4cc962154da76fb62848a9ce088efe30d7c50ab1" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: "7347b194fb0bbeb4058e6a4e87ee70350b6b2b90f8ac5f8bd5b3a01548f6d33a" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: f95e6a43162bce43c9c3405f3eb6f39e5b5d11f65fab19196cf8225e2777624d + url: "https://pub.dev" + source: hosted + version: "2.3.0" shelf: dependency: transitive description: @@ -645,6 +749,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.0" + win32: + dependency: transitive + description: + name: win32 + sha256: f2add6fa510d3ae152903412227bda57d0d5a8da61d2c39c1fb022c9429a41c0 + url: "https://pub.dev" + source: hosted + version: "5.0.6" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: f0c26453a2d47aa4c2570c6a033246a3fc62da2fe23c7ffdd0a7495086dc0247 + url: "https://pub.dev" + source: hosted + version: "1.0.2" xml: dependency: transitive description: @@ -663,4 +783,4 @@ packages: version: "3.1.2" sdks: dart: ">=3.0.0 <4.0.0" - flutter: ">=1.16.0" + flutter: ">=3.3.0" diff --git a/pubspec.yaml b/pubspec.yaml index ae30f4d..a52a3fb 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,7 @@ dependencies: intl: ^0.18.1 flutter_carousel_slider: ^1.1.0 fluttertoast: ^8.2.2 + shared_preferences: ^2.2.0 dev_dependencies: flutter_test: From 8fc9e5d17cc0ea304e01fa7618f7953be9e2cffb Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:50:04 +0300 Subject: [PATCH 16/85] Create storage in data layer --- .../app/data/data_sources/local/storage.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/features/app/data/data_sources/local/storage.dart diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart new file mode 100644 index 0000000..0560fa6 --- /dev/null +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -0,0 +1,27 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +abstract class Storage { + late SharedPreferences prefs; + Future saveCity(String cityName); +} + +class StorageImplementation implements Storage{ + late SharedPreferences prefs; + + StorageImplementation() { + print("Initializing prefs"); + _initPrefs(); + } + + Future _initPrefs() async { + prefs = await SharedPreferences.getInstance(); + print("Initialized prefs"); + } + + @override + Future saveCity(String cityName) async { + // P.S. This is just a template, I'm aware that it doesn't work as planned. + // Will fix it later + await prefs.setStringList('cities', [cityName]); + } +} \ No newline at end of file From 94f6aecefc753d87dd44fd7225e015a2cefb6fd0 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:50:35 +0300 Subject: [PATCH 17/85] Create storage repository --- .../storage_repository_implementation.dart | 13 +++++++++++++ .../app/domain/repository/storage_repository.dart | 3 +++ 2 files changed, 16 insertions(+) create mode 100644 lib/features/app/data/repository/storage_repository_implementation.dart create mode 100644 lib/features/app/domain/repository/storage_repository.dart diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart new file mode 100644 index 0000000..f7f8272 --- /dev/null +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -0,0 +1,13 @@ +import 'package:weathque/features/app/data/data_sources/local/storage.dart'; +import 'package:weathque/features/app/domain/repository/storage_repository.dart'; + +class StorageRepositoryImplementation implements StorageRepository{ + final Storage _storage; + + StorageRepositoryImplementation(this._storage); + + @override + Future saveCity(String cityName) async{ + await _storage.prefs.setStringList('cities', [cityName]); + } +} \ No newline at end of file diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart new file mode 100644 index 0000000..59a88f6 --- /dev/null +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -0,0 +1,3 @@ +abstract class StorageRepository{ + Future saveCity(String cityName); +} \ No newline at end of file From b54898220bc6a075aa69d83f353ce87fa4942b2b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:52:52 +0300 Subject: [PATCH 18/85] Create SaveCity usecase --- lib/core/usecases/usecase.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 2ade09f..5dde3c9 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -1,3 +1,7 @@ abstract class UseCase{ Future call({required String cityName}); +} + +abstract class SaveCityUseCase{ + Future call({required String cityName}); } \ No newline at end of file From 8435dbf581c1350043c7614c8785ca6485c3da08 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:53:48 +0300 Subject: [PATCH 19/85] Create implementation of SaveCity usecase --- lib/features/app/domain/usecases/save_city.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/features/app/domain/usecases/save_city.dart diff --git a/lib/features/app/domain/usecases/save_city.dart b/lib/features/app/domain/usecases/save_city.dart new file mode 100644 index 0000000..fd7513d --- /dev/null +++ b/lib/features/app/domain/usecases/save_city.dart @@ -0,0 +1,13 @@ +import 'package:weathque/core/usecases/usecase.dart'; +import 'package:weathque/features/app/domain/repository/storage_repository.dart'; + +class SaveCityUseCaseImplementation implements SaveCityUseCase{ + final StorageRepository _storage; + + SaveCityUseCaseImplementation(this._storage); + + @override + Future call({required String cityName}) { + return _storage.saveCity(cityName); + } +} \ No newline at end of file From 29624773c637a238cdf40d697445c22cf758fb76 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:54:03 +0300 Subject: [PATCH 20/85] Add all the stuff to the DI --- lib/core/dependency_injection.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/core/dependency_injection.dart b/lib/core/dependency_injection.dart index a5da8be..0d72824 100644 --- a/lib/core/dependency_injection.dart +++ b/lib/core/dependency_injection.dart @@ -1,12 +1,15 @@ import 'package:get_it/get_it.dart'; // ignore: depend_on_referenced_packages import 'package:dio/dio.dart'; +import 'package:weathque/features/app/data/data_sources/local/storage.dart'; import 'package:weathque/features/app/data/data_sources/remote/api_service.dart'; +import 'package:weathque/features/app/data/repository/storage_repository_implementation.dart'; import 'package:weathque/features/app/data/repository/weather_repository_implementation.dart'; import 'package:weathque/features/app/domain/entities/summary_builder.dart'; import 'package:weathque/features/app/domain/repository/weather_repository.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; +import 'package:weathque/features/app/domain/usecases/save_city.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; @@ -24,6 +27,9 @@ Future initializeDependencies() async { ForecastWeatherApiService(locator()) ); + // Storage + locator.registerSingleton(StorageImplementation()); + // Repo locator.registerSingleton( WeatherRepositoryImplementation(locator()) @@ -31,6 +37,9 @@ Future initializeDependencies() async { locator.registerSingleton( ForecastWeatherRepositoryImplementation(locator()) ); + locator.registerSingleton( + StorageRepositoryImplementation(locator()) + ); // Use cases locator.registerSingleton( @@ -39,6 +48,10 @@ Future initializeDependencies() async { locator.registerSingleton( GetWeatherForecastUseCase(locator()) ); + locator.registerSingleton( + SaveCityUseCaseImplementation(locator()) + ); + // Blocs locator.registerFactory( From a4dc805c1a0e635bea8939faf5ce058b6b3545b2 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:54:17 +0300 Subject: [PATCH 21/85] Make ensureInitialized --- lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/main.dart b/lib/main.dart index 0c4e659..e979394 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,7 @@ import 'package:weathque/features/app/presentation/pages/weather_page.dart'; import 'features/app/domain/entities/cities_enum.dart'; void main() { + WidgetsFlutterBinding.ensureInitialized(); initializeDependencies(); runApp(const WeathqueApp()); } From dd0ce8f332a735345428447baa6ac891f6ce9e69 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sat, 19 Aug 2023 19:54:42 +0300 Subject: [PATCH 22/85] Add example of city preservation --- .../presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index b4ffe35..5e6d096 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -91,7 +91,10 @@ void _onError(FToast toastManager){ ); } -void _onSuccess(FToast toastManager){ +Future _onSuccess(FToast toastManager) async { + // Example of city preservation + //locator()(cityName: *city name here*); + CustomToast toast = CustomToast( isError: false, text: "City was successfully saved", From 82fbad0588507ff12350e0aa3004c79698449321 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sun, 20 Aug 2023 23:45:42 +0300 Subject: [PATCH 23/85] Create getCities method in the Storage --- .../app/data/data_sources/local/storage.dart | 8 +++++ pubspec.lock | 30 ++++++++++++------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 0560fa6..07a85ff 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -3,6 +3,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class Storage { late SharedPreferences prefs; Future saveCity(String cityName); + List? getCities(); } class StorageImplementation implements Storage{ @@ -24,4 +25,11 @@ class StorageImplementation implements Storage{ // Will fix it later await prefs.setStringList('cities', [cityName]); } + + @override + List? getCities() { + final List? items = prefs.getStringList('cities'); + + return items; + } } \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock index eb6e360..562b0bc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -165,10 +165,10 @@ packages: dependency: transitive description: name: collection - sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" + sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 url: "https://pub.dev" source: hosted - version: "1.17.1" + version: "1.17.2" convert: dependency: transitive description: @@ -396,18 +396,18 @@ packages: dependency: transitive description: name: matcher - sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" + sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" url: "https://pub.dev" source: hosted - version: "0.12.15" + version: "0.12.16" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" url: "https://pub.dev" source: hosted - version: "0.2.0" + version: "0.5.0" meta: dependency: transitive description: @@ -649,10 +649,10 @@ packages: dependency: transitive description: name: source_span - sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" stack_trace: dependency: transitive description: @@ -697,10 +697,10 @@ packages: dependency: transitive description: name: test_api - sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb + sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" url: "https://pub.dev" source: hosted - version: "0.5.1" + version: "0.6.0" timing: dependency: transitive description: @@ -741,6 +741,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + url: "https://pub.dev" + source: hosted + version: "0.1.4-beta" web_socket_channel: dependency: transitive description: @@ -782,5 +790,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.0.0 <4.0.0" + dart: ">=3.1.0-185.0.dev <4.0.0" flutter: ">=3.3.0" From 6afa4aaae353f948a67d1ce23376561895fbb086 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sun, 20 Aug 2023 23:58:43 +0300 Subject: [PATCH 24/85] Add getCities methods in the repo --- .../data/repository/storage_repository_implementation.dart | 5 +++++ lib/features/app/domain/repository/storage_repository.dart | 1 + 2 files changed, 6 insertions(+) diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index f7f8272..e1233b2 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -10,4 +10,9 @@ class StorageRepositoryImplementation implements StorageRepository{ Future saveCity(String cityName) async{ await _storage.prefs.setStringList('cities', [cityName]); } + + @override + List? getCities() { + return _storage.getCities(); + } } \ No newline at end of file diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index 59a88f6..a4ca040 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,3 +1,4 @@ abstract class StorageRepository{ Future saveCity(String cityName); + List? getCities(); } \ No newline at end of file From 080cc439134b24964a73619bb6a9778b6c5e6ee6 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Sun, 20 Aug 2023 23:59:00 +0300 Subject: [PATCH 25/85] Create get cities usecase --- lib/core/usecases/usecase.dart | 4 ++++ lib/features/app/domain/usecases/get_cities.dart | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 lib/features/app/domain/usecases/get_cities.dart diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 5dde3c9..766bdaa 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -4,4 +4,8 @@ abstract class UseCase{ abstract class SaveCityUseCase{ Future call({required String cityName}); +} + +abstract class GetCitiesUseCase{ + List? call(); } \ No newline at end of file diff --git a/lib/features/app/domain/usecases/get_cities.dart b/lib/features/app/domain/usecases/get_cities.dart new file mode 100644 index 0000000..e0a097e --- /dev/null +++ b/lib/features/app/domain/usecases/get_cities.dart @@ -0,0 +1,13 @@ +import 'package:weathque/core/usecases/usecase.dart'; +import 'package:weathque/features/app/domain/repository/storage_repository.dart'; + +class GetCitiesUseCaseImplementation implements GetCitiesUseCase{ + final StorageRepository _storage; + + GetCitiesUseCaseImplementation(this._storage); + + @override + List? call() { + return _storage.getCities(); + } +} \ No newline at end of file From f6f6f2ad325e21de39a7ca06adff0dfd3159400b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 00:08:11 +0300 Subject: [PATCH 26/85] Fix save city logic --- .../app/data/repository/storage_repository_implementation.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index e1233b2..09b4915 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -8,7 +8,7 @@ class StorageRepositoryImplementation implements StorageRepository{ @override Future saveCity(String cityName) async{ - await _storage.prefs.setStringList('cities', [cityName]); + await _storage.saveCity(cityName); } @override From 1848a85ff8fd46697c936c6100e73502a11c92ee Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 00:08:32 +0300 Subject: [PATCH 27/85] Add Get Cities UseCase to the DI --- lib/core/dependency_injection.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core/dependency_injection.dart b/lib/core/dependency_injection.dart index 0d72824..ada89fd 100644 --- a/lib/core/dependency_injection.dart +++ b/lib/core/dependency_injection.dart @@ -7,6 +7,7 @@ import 'package:weathque/features/app/data/repository/storage_repository_impleme import 'package:weathque/features/app/data/repository/weather_repository_implementation.dart'; import 'package:weathque/features/app/domain/entities/summary_builder.dart'; import 'package:weathque/features/app/domain/repository/weather_repository.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; @@ -51,6 +52,9 @@ Future initializeDependencies() async { locator.registerSingleton( SaveCityUseCaseImplementation(locator()) ); + locator.registerSingleton( + GetCitiesUseCaseImplementation(locator()) + ); // Blocs From 611a5a6552ecea3addb31b25a6c078d69a45f8bd Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 00:09:00 +0300 Subject: [PATCH 28/85] Remove print statements --- lib/features/app/data/data_sources/local/storage.dart | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 07a85ff..15061f9 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -10,13 +10,11 @@ class StorageImplementation implements Storage{ late SharedPreferences prefs; StorageImplementation() { - print("Initializing prefs"); _initPrefs(); } Future _initPrefs() async { prefs = await SharedPreferences.getInstance(); - print("Initialized prefs"); } @override From 903744905baed043d96750056e21fbad3fb9976b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:20:02 +0300 Subject: [PATCH 29/85] Implement city preservation --- .../app/data/data_sources/local/storage.dart | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 15061f9..305f9b8 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -19,15 +19,18 @@ class StorageImplementation implements Storage{ @override Future saveCity(String cityName) async { - // P.S. This is just a template, I'm aware that it doesn't work as planned. - // Will fix it later - await prefs.setStringList('cities', [cityName]); + final List cities = getCities() ?? []; + + if(!cities.contains(cityName)){ + cities.add(cityName); + await prefs.setStringList('cities', cities); + } } @override List? getCities() { - final List? items = prefs.getStringList('cities'); + final List? cities = prefs.getStringList('cities'); - return items; + return cities; } } \ No newline at end of file From 1d9a74ab64d6f9a4f63d8f3e0aef7232bb426379 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:29:38 +0300 Subject: [PATCH 30/85] Return preservation result --- lib/core/usecases/usecase.dart | 2 +- lib/features/app/data/data_sources/local/storage.dart | 8 ++++++-- .../repository/storage_repository_implementation.dart | 4 ++-- .../app/domain/repository/storage_repository.dart | 2 +- lib/features/app/domain/usecases/save_city.dart | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 766bdaa..9cb4486 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -3,7 +3,7 @@ abstract class UseCase{ } abstract class SaveCityUseCase{ - Future call({required String cityName}); + Future call({required String cityName}); } abstract class GetCitiesUseCase{ diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 305f9b8..ca77f9b 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -2,7 +2,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class Storage { late SharedPreferences prefs; - Future saveCity(String cityName); + Future saveCity(String cityName); List? getCities(); } @@ -18,13 +18,17 @@ class StorageImplementation implements Storage{ } @override - Future saveCity(String cityName) async { + Future saveCity(String cityName) async { final List cities = getCities() ?? []; if(!cities.contains(cityName)){ cities.add(cityName); await prefs.setStringList('cities', cities); + + return true; } + + return false; } @override diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index 09b4915..f54dc2b 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -7,8 +7,8 @@ class StorageRepositoryImplementation implements StorageRepository{ StorageRepositoryImplementation(this._storage); @override - Future saveCity(String cityName) async{ - await _storage.saveCity(cityName); + Future saveCity(String cityName) async{ + return await _storage.saveCity(cityName); } @override diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index a4ca040..39dc1ae 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,4 +1,4 @@ abstract class StorageRepository{ - Future saveCity(String cityName); + Future saveCity(String cityName); List? getCities(); } \ No newline at end of file diff --git a/lib/features/app/domain/usecases/save_city.dart b/lib/features/app/domain/usecases/save_city.dart index fd7513d..7280144 100644 --- a/lib/features/app/domain/usecases/save_city.dart +++ b/lib/features/app/domain/usecases/save_city.dart @@ -7,7 +7,7 @@ class SaveCityUseCaseImplementation implements SaveCityUseCase{ SaveCityUseCaseImplementation(this._storage); @override - Future call({required String cityName}) { + Future call({required String cityName}) { return _storage.saveCity(cityName); } } \ No newline at end of file From bcc5c00ac714c7f4215f64b85e2043a5ba131ea5 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:39:13 +0300 Subject: [PATCH 31/85] Add error toast if city already saved --- .../misc/bottom_sheet/bottom_sheet.dart | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 5e6d096..4f6c50d 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; +import 'package:weathque/features/app/domain/usecases/save_city.dart'; import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; TextEditingController _cityController = TextEditingController(); @@ -92,13 +94,24 @@ void _onError(FToast toastManager){ } Future _onSuccess(FToast toastManager) async { + // Example of cities fetching + // print(locator()()); // Example of city preservation - //locator()(cityName: *city name here*); + + bool preservationResult = await locator()(cityName: _cityController.text); + late CustomToast toast; - CustomToast toast = CustomToast( - isError: false, - text: "City was successfully saved", - ); + if(preservationResult){ + toast = CustomToast( + isError: false, + text: "City was successfully saved", + ); + } else{ + toast = CustomToast( + isError: true, + text: "This city is already saved in the database", + ); + } toastManager.showToast( child: toast, gravity: ToastGravity.BOTTOM, From 3e506ac46d8018b4ae39c3526dd7b666cb71a484 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:45:16 +0300 Subject: [PATCH 32/85] Make getCities non-nullable --- lib/core/usecases/usecase.dart | 2 +- lib/features/app/data/data_sources/local/storage.dart | 8 ++++---- .../repository/storage_repository_implementation.dart | 2 +- .../app/domain/repository/storage_repository.dart | 2 +- lib/features/app/domain/usecases/get_cities.dart | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 9cb4486..6b4edd4 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -7,5 +7,5 @@ abstract class SaveCityUseCase{ } abstract class GetCitiesUseCase{ - List? call(); + List call(); } \ No newline at end of file diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index ca77f9b..eacc78b 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -3,7 +3,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class Storage { late SharedPreferences prefs; Future saveCity(String cityName); - List? getCities(); + List getCities(); } class StorageImplementation implements Storage{ @@ -19,7 +19,7 @@ class StorageImplementation implements Storage{ @override Future saveCity(String cityName) async { - final List cities = getCities() ?? []; + final List cities = getCities(); if(!cities.contains(cityName)){ cities.add(cityName); @@ -32,8 +32,8 @@ class StorageImplementation implements Storage{ } @override - List? getCities() { - final List? cities = prefs.getStringList('cities'); + List getCities() { + final List cities = prefs.getStringList('cities') ?? []; return cities; } diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index f54dc2b..178c816 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -12,7 +12,7 @@ class StorageRepositoryImplementation implements StorageRepository{ } @override - List? getCities() { + List getCities() { return _storage.getCities(); } } \ No newline at end of file diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index 39dc1ae..f51ad38 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,4 +1,4 @@ abstract class StorageRepository{ Future saveCity(String cityName); - List? getCities(); + List getCities(); } \ No newline at end of file diff --git a/lib/features/app/domain/usecases/get_cities.dart b/lib/features/app/domain/usecases/get_cities.dart index e0a097e..1aa2d31 100644 --- a/lib/features/app/domain/usecases/get_cities.dart +++ b/lib/features/app/domain/usecases/get_cities.dart @@ -7,7 +7,7 @@ class GetCitiesUseCaseImplementation implements GetCitiesUseCase{ GetCitiesUseCaseImplementation(this._storage); @override - List? call() { + List call() { return _storage.getCities(); } } \ No newline at end of file From 2be18f4587af1e5b7317ef262f1971dbfb2b19e4 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:41:43 +0300 Subject: [PATCH 33/85] Add city display --- .../widgets/misc/bottom_sheet/bottom_sheet.dart | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 4f6c50d..43e70d5 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -24,6 +24,7 @@ showCustomBottomSheet(BuildContext context){ } Widget _buildBottomSheetMenu(BuildContext context){ + List cities = locator()(); FToast toastManager = FToast(); toastManager.init(context); @@ -62,6 +63,14 @@ Widget _buildBottomSheetMenu(BuildContext context){ }, ) ), + ), + Expanded( + child: ListView.builder( //ListView.separated with separatorBuilder + itemCount: cities.length, + itemBuilder: (context, index) { + return Text(cities[index]); + }, + ), ) ], ), @@ -95,7 +104,7 @@ void _onError(FToast toastManager){ Future _onSuccess(FToast toastManager) async { // Example of cities fetching - // print(locator()()); + // print(); // Example of city preservation bool preservationResult = await locator()(cityName: _cityController.text); From fe35da58a185b0305bbee74f82a11ec547b789e2 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Mon, 21 Aug 2023 16:44:17 +0300 Subject: [PATCH 34/85] Add text capitalization --- .../app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 43e70d5..da6c493 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -41,6 +41,7 @@ Widget _buildBottomSheetMenu(BuildContext context){ onSubmitted: (value) { _onSubmit(toastManager); }, + textCapitalization: TextCapitalization.words, cursorColor: Colors.black, decoration: InputDecoration( enabledBorder: OutlineInputBorder( From 3bbe04fd27060f4233399fcb75795cef6982c7ae Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 18:47:19 +0300 Subject: [PATCH 35/85] Create dismissible city card --- .../misc/bottom_sheet/bottom_sheet.dart | 3 +- .../widgets/misc/bottom_sheet/city_card.dart | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index da6c493..f57b869 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -5,6 +5,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart'; import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; TextEditingController _cityController = TextEditingController(); @@ -69,7 +70,7 @@ Widget _buildBottomSheetMenu(BuildContext context){ child: ListView.builder( //ListView.separated with separatorBuilder itemCount: cities.length, itemBuilder: (context, index) { - return Text(cities[index]); + return CityCard(name: cities[index]); }, ), ) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart new file mode 100644 index 0000000..3250b61 --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; + +class CityCard extends StatelessWidget { + final String name; + + const CityCard({super.key, required this.name}); + + @override + Widget build(BuildContext context) { + return Dismissible( + key: Key(name), + onDismissed: (direction) { + //print("$name deleted"); + print(direction); + }, + child: Card( + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 15), + child: Text( + name, + style: TextStyle( + fontSize: 24, + ), + ) + ) + ), + ), + ); + } +} \ No newline at end of file From 788ab2bd8893a36143b0dafe938cd9e8f0147fbb Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:00:33 +0300 Subject: [PATCH 36/85] Add delete city in the repo --- lib/features/app/data/data_sources/local/storage.dart | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index eacc78b..2ec44f9 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -4,6 +4,7 @@ abstract class Storage { late SharedPreferences prefs; Future saveCity(String cityName); List getCities(); + void deleteCity(String cityName); } class StorageImplementation implements Storage{ @@ -37,4 +38,13 @@ class StorageImplementation implements Storage{ return cities; } + + @override + Future deleteCity(String cityName) async { + List cities = getCities(); + cities.remove(cityName); + + await prefs.remove('cities'); + await prefs.setStringList('cities', cities); + } } \ No newline at end of file From 7c165acaff083b95408d3e9fe15a32d85e2a3642 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:02:45 +0300 Subject: [PATCH 37/85] Add city removal in the repository --- lib/features/app/data/data_sources/local/storage.dart | 2 +- .../data/repository/storage_repository_implementation.dart | 5 +++++ lib/features/app/domain/repository/storage_repository.dart | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 2ec44f9..f9fad2f 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -4,7 +4,7 @@ abstract class Storage { late SharedPreferences prefs; Future saveCity(String cityName); List getCities(); - void deleteCity(String cityName); + Future deleteCity(String cityName); } class StorageImplementation implements Storage{ diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index 178c816..6c2757c 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -15,4 +15,9 @@ class StorageRepositoryImplementation implements StorageRepository{ List getCities() { return _storage.getCities(); } + + @override + Future deleteCity(String cityName) async { + await _storage.deleteCity(cityName); + } } \ No newline at end of file diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index f51ad38..663f6ee 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,4 +1,5 @@ abstract class StorageRepository{ Future saveCity(String cityName); List getCities(); + Future deleteCity(String cityName); } \ No newline at end of file From 225b3ecd0a1835c0b15ed67b41d740f80eee7509 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:08:34 +0300 Subject: [PATCH 38/85] Create use cases for city removal --- lib/core/usecases/usecase.dart | 4 ++++ lib/features/app/domain/usecases/delete_city.dart | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 lib/features/app/domain/usecases/delete_city.dart diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 6b4edd4..56cb9d1 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -8,4 +8,8 @@ abstract class SaveCityUseCase{ abstract class GetCitiesUseCase{ List call(); +} + +abstract class DeleteCityUseCase{ + Future call(String cityName); } \ No newline at end of file diff --git a/lib/features/app/domain/usecases/delete_city.dart b/lib/features/app/domain/usecases/delete_city.dart new file mode 100644 index 0000000..9706bac --- /dev/null +++ b/lib/features/app/domain/usecases/delete_city.dart @@ -0,0 +1,13 @@ +import 'package:weathque/core/usecases/usecase.dart'; +import 'package:weathque/features/app/domain/repository/storage_repository.dart'; + +class DeleteCityUseCaseImplementation implements DeleteCityUseCase{ + final StorageRepository _storage; + + DeleteCityUseCaseImplementation(this._storage); + + @override + Future call(String cityName) { + return _storage.deleteCity(cityName); + } +} From 9d3e1453353f0007f95c8f055fd85ae68563d1cf Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:08:49 +0300 Subject: [PATCH 39/85] Init city removal use case in the DI --- lib/core/dependency_injection.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/core/dependency_injection.dart b/lib/core/dependency_injection.dart index ada89fd..44f1b4d 100644 --- a/lib/core/dependency_injection.dart +++ b/lib/core/dependency_injection.dart @@ -7,6 +7,7 @@ import 'package:weathque/features/app/data/repository/storage_repository_impleme import 'package:weathque/features/app/data/repository/weather_repository_implementation.dart'; import 'package:weathque/features/app/domain/entities/summary_builder.dart'; import 'package:weathque/features/app/domain/repository/weather_repository.dart'; +import 'package:weathque/features/app/domain/usecases/delete_city.dart'; import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; @@ -55,6 +56,9 @@ Future initializeDependencies() async { locator.registerSingleton( GetCitiesUseCaseImplementation(locator()) ); + locator.registerSingleton( + DeleteCityUseCaseImplementation(locator()) + ); // Blocs From f149b9e82d45b68ef7259a400762a0b9d921ea51 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:10:00 +0300 Subject: [PATCH 40/85] Implement city removal --- .../widgets/misc/bottom_sheet/city_card.dart | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 3250b61..2ac99f4 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; -import 'package:weathque/config/theme/custom_colors.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/domain/usecases/delete_city.dart'; class CityCard extends StatelessWidget { final String name; @@ -7,12 +8,11 @@ class CityCard extends StatelessWidget { const CityCard({super.key, required this.name}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context) { return Dismissible( key: Key(name), - onDismissed: (direction) { - //print("$name deleted"); - print(direction); + onDismissed: (_) async { + await locator()(name); }, child: Card( child: Center( From e2501301c8a935252877f5501f34547db8c85e8c Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Tue, 22 Aug 2023 19:19:11 +0300 Subject: [PATCH 41/85] Add padding --- .../misc/bottom_sheet/bottom_sheet.dart | 14 +++++--- .../widgets/misc/bottom_sheet/city_card.dart | 34 +++++++++++-------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index f57b869..0678a72 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -67,11 +67,15 @@ Widget _buildBottomSheetMenu(BuildContext context){ ), ), Expanded( - child: ListView.builder( //ListView.separated with separatorBuilder - itemCount: cities.length, - itemBuilder: (context, index) { - return CityCard(name: cities[index]); - }, + child: Padding( + // Maybe I should replace it with symmetric + padding: const EdgeInsets.only(top: 10), + child: ListView.builder( + itemCount: cities.length, + itemBuilder: (context, index) { + return CityCard(name: cities[index]); + }, + ), ), ) ], diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 2ac99f4..79596ec 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/domain/usecases/delete_city.dart'; @@ -9,22 +10,25 @@ class CityCard extends StatelessWidget { @override Widget build(BuildContext context) { - return Dismissible( - key: Key(name), - onDismissed: (_) async { - await locator()(name); - }, - child: Card( - child: Center( - child: Padding( - padding: const EdgeInsets.symmetric(vertical: 15), - child: Text( - name, - style: TextStyle( - fontSize: 24, - ), + return Padding( + padding: const EdgeInsets.symmetric(vertical: 2.5), + child: Dismissible( + key: Key(name), + onDismissed: (_) async { + await locator()(name); + }, + child: Card( + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 15), + child: Text( + name, + style: TextStyle( + fontSize: 24, + ), + ) ) - ) + ), ), ), ); From 0337be30d948c0b771e03e9729dfa28cf68476d4 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:19:23 +0300 Subject: [PATCH 42/85] Create Cities Changed Cubit --- .../bloc/add_city/cities_changed_cubit.dart | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart diff --git a/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart b/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart new file mode 100644 index 0000000..c675e91 --- /dev/null +++ b/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart @@ -0,0 +1,12 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; + +class CitiesChangedCubit extends Cubit>{ + CitiesChangedCubit() : super(locator()()); + + void call(){ + print("cubit called ${locator()()}"); + emit(locator()()); + } +} \ No newline at end of file From bb74da443f541301d918b0bf1d28eee90030f0aa Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:19:36 +0300 Subject: [PATCH 43/85] Implement Cities Changed Cubit --- .../misc/bottom_sheet/bottom_sheet.dart | 45 ++++++++++--------- .../widgets/misc/bottom_sheet/city_card.dart | 3 ++ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 0678a72..ab4b3c1 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -1,10 +1,11 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:fluttertoast/fluttertoast.dart'; -import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart'; import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; @@ -25,7 +26,8 @@ showCustomBottomSheet(BuildContext context){ } Widget _buildBottomSheetMenu(BuildContext context){ - List cities = locator()(); + //List cities = locator()(); + //List cities = context.watch().state; FToast toastManager = FToast(); toastManager.init(context); @@ -40,7 +42,7 @@ Widget _buildBottomSheetMenu(BuildContext context){ TextField( controller: _cityController, onSubmitted: (value) { - _onSubmit(toastManager); + _onSubmit(toastManager, context); }, textCapitalization: TextCapitalization.words, cursorColor: Colors.black, @@ -61,21 +63,26 @@ Widget _buildBottomSheetMenu(BuildContext context){ suffixIcon: IconButton( icon: Icon(Icons.search, color: Colors.black), onPressed: () { - _onSubmit(toastManager); + _onSubmit(toastManager, context); }, ) ), ), Expanded( - child: Padding( - // Maybe I should replace it with symmetric - padding: const EdgeInsets.only(top: 10), - child: ListView.builder( - itemCount: cities.length, - itemBuilder: (context, index) { - return CityCard(name: cities[index]); - }, - ), + child: BlocBuilder>( + builder: (context, state) { + print("rebuilt $state"); + return Padding( + // Maybe I should replace it with symmetric + padding: const EdgeInsets.only(top: 10), + child: ListView.builder( + itemCount: state.length, + itemBuilder: (context, index) { + return CityCard(name: state[index]); + }, + ), + ); + }, ), ) ], @@ -84,7 +91,7 @@ Widget _buildBottomSheetMenu(BuildContext context){ ); } -void _onSubmit(FToast toastManager) async { +void _onSubmit(FToast toastManager, BuildContext context) async { String cityName = _cityController.text; try { @@ -93,7 +100,7 @@ void _onSubmit(FToast toastManager) async { _onError(toastManager); return; } - _onSuccess(toastManager); + _onSuccess(toastManager, context); } void _onError(FToast toastManager){ @@ -108,11 +115,7 @@ void _onError(FToast toastManager){ ); } -Future _onSuccess(FToast toastManager) async { - // Example of cities fetching - // print(); - // Example of city preservation - +Future _onSuccess(FToast toastManager, BuildContext context) async { bool preservationResult = await locator()(cityName: _cityController.text); late CustomToast toast; @@ -132,4 +135,6 @@ Future _onSuccess(FToast toastManager) async { gravity: ToastGravity.BOTTOM, toastDuration: Duration(seconds: 2), ); + + context.read()(); } \ No newline at end of file diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 79596ec..9adc7f7 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/domain/usecases/delete_city.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; class CityCard extends StatelessWidget { final String name; @@ -16,6 +18,7 @@ class CityCard extends StatelessWidget { key: Key(name), onDismissed: (_) async { await locator()(name); + context.read()(); }, child: Card( child: Center( From 0d610c08c7ddb689fcaaed3999687d700427610c Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:19:46 +0300 Subject: [PATCH 44/85] Add CitiesChangedCubit provider --- lib/main.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index e979394..a49d115 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart'; @@ -32,6 +33,9 @@ class WeathqueApp extends StatelessWidget { ), BlocProvider( create: (context) => locator()..add(const GetWeatherForecast()), + ), + BlocProvider( + create: (context) => locator(), ) ], child: MaterialApp( From b057d1ebde7c864419a2372ce73e107e04f31834 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:19:52 +0300 Subject: [PATCH 45/85] Add CitiesChangedCubit to the DI --- lib/core/dependency_injection.dart | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/core/dependency_injection.dart b/lib/core/dependency_injection.dart index 44f1b4d..58e275c 100644 --- a/lib/core/dependency_injection.dart +++ b/lib/core/dependency_injection.dart @@ -12,6 +12,7 @@ import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; @@ -69,6 +70,11 @@ Future initializeDependencies() async { () => GetWeatherForecastBloc(locator()) ); - //Entities + // Cubit + locator.registerFactory( + () => CitiesChangedCubit() + ); + + // Entities locator.registerSingleton(SummaryBuilder()); } \ No newline at end of file From 70f65289cb486f57c80c74d89163bace95c67eb0 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:25:43 +0300 Subject: [PATCH 46/85] Removi print statements --- .../app/presentation/bloc/add_city/cities_changed_cubit.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart b/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart index c675e91..5d673bb 100644 --- a/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart +++ b/lib/features/app/presentation/bloc/add_city/cities_changed_cubit.dart @@ -6,7 +6,6 @@ class CitiesChangedCubit extends Cubit>{ CitiesChangedCubit() : super(locator()()); void call(){ - print("cubit called ${locator()()}"); emit(locator()()); } } \ No newline at end of file From fc0633e7440bc324710223ed82b3608374d0f778 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 20:25:52 +0300 Subject: [PATCH 47/85] Remove print --- .../app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index ab4b3c1..2591901 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -71,7 +71,6 @@ Widget _buildBottomSheetMenu(BuildContext context){ Expanded( child: BlocBuilder>( builder: (context, state) { - print("rebuilt $state"); return Padding( // Maybe I should replace it with symmetric padding: const EdgeInsets.only(top: 10), From 6b0a4c51c966402fb09982ad1aa0886b221154f7 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 21:22:52 +0300 Subject: [PATCH 48/85] Add animation to CityCard --- .../widgets/misc/bottom_sheet/city_card.dart | 80 +++++++++++++++---- 1 file changed, 64 insertions(+), 16 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 9adc7f7..0c212b5 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -1,39 +1,87 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/domain/usecases/delete_city.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; +import 'package:weathque/features/app/presentation/widgets/animations/top_animation.dart'; -class CityCard extends StatelessWidget { +class CityCard extends StatefulWidget { final String name; + final int index; - const CityCard({super.key, required this.name}); + const CityCard({super.key, required this.name, required this.index}); @override - Widget build(BuildContext context) { - return Padding( - padding: const EdgeInsets.symmetric(vertical: 2.5), - child: Dismissible( - key: Key(name), - onDismissed: (_) async { - await locator()(name); - context.read()(); - }, - child: Card( + State createState() => _CityCardState(); +} + +class _CityCardState extends State { + bool isAnimated = false; + final Duration animationDuration = const Duration(milliseconds: 750); + final Curve animationCurve = Curves.easeOutSine; + final int animationStep = 200; + + @override + void initState() { + _animate(); + super.initState(); + } + + void _animate() async{ + await Future.delayed(Duration(milliseconds: (widget.index + 1) * animationStep)) + .then((value) => setState(() => isAnimated = true)); + } + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + SizedBox( child: Center( child: Padding( - padding: const EdgeInsets.symmetric(vertical: 15), + padding: const EdgeInsets.symmetric(vertical: 20), child: Text( - name, + widget.name, style: TextStyle( fontSize: 24, + color: Colors.transparent ), ) ) ), ), - ), + + TopAnimation( + curve: animationCurve, + duration: animationDuration, + animationField: isAnimated, + positionInitialValue: MediaQuery.of(context).size.height/11, + opacityInitialValue: 1, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 2.5), + child: Dismissible( + key: Key(widget.name), + onDismissed: (_) async { + await locator()(widget.name); + context.read()(); + }, + child: Card( + child: Center( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 15), + child: Text( + widget.name, + style: TextStyle( + fontSize: 24, + ), + ) + ) + ), + ), + ), + ), + ), + ], ); } } \ No newline at end of file From 58290a40494226a19f0526284ad8e0621bb82203 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 21:22:58 +0300 Subject: [PATCH 49/85] Implement animation --- .../presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 2591901..d150543 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -77,7 +77,7 @@ Widget _buildBottomSheetMenu(BuildContext context){ child: ListView.builder( itemCount: state.length, itemBuilder: (context, index) { - return CityCard(name: state[index]); + return CityCard(name: state[index], index: index); }, ), ); From 8cb54f75427f81f2f1b86ae05d42261d968d56be Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 21:47:32 +0300 Subject: [PATCH 50/85] Remove comments --- .../presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index d150543..46ba682 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -26,8 +26,6 @@ showCustomBottomSheet(BuildContext context){ } Widget _buildBottomSheetMenu(BuildContext context){ - //List cities = locator()(); - //List cities = context.watch().state; FToast toastManager = FToast(); toastManager.init(context); @@ -72,7 +70,6 @@ Widget _buildBottomSheetMenu(BuildContext context){ child: BlocBuilder>( builder: (context, state) { return Padding( - // Maybe I should replace it with symmetric padding: const EdgeInsets.only(top: 10), child: ListView.builder( itemCount: state.length, From b82f7b5a60859bd9232af7297681979cae14b11f Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:40:34 +0300 Subject: [PATCH 51/85] Add color preservation in the storage --- .../app/data/data_sources/local/storage.dart | 14 ++++++++++++-- .../storage_repository_implementation.dart | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index f9fad2f..4856c11 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -2,7 +2,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class Storage { late SharedPreferences prefs; - Future saveCity(String cityName); + Future saveCity(String cityName, String colorValue); List getCities(); Future deleteCity(String cityName); } @@ -19,12 +19,15 @@ class StorageImplementation implements Storage{ } @override - Future saveCity(String cityName) async { + Future saveCity(String cityName, String colorValue) async { final List cities = getCities(); + final List colors = getColors(); if(!cities.contains(cityName)){ cities.add(cityName); + colors.add(colorValue); await prefs.setStringList('cities', cities); + await prefs.setStringList('colors', colors); return true; } @@ -38,9 +41,16 @@ class StorageImplementation implements Storage{ return cities; } + + List getColors(){ + final List colors = prefs.getStringList('colors') ?? []; + + return colors; + } @override Future deleteCity(String cityName) async { + // TODO: Add color removal List cities = getCities(); cities.remove(cityName); diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index 6c2757c..d8af758 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -7,8 +7,8 @@ class StorageRepositoryImplementation implements StorageRepository{ StorageRepositoryImplementation(this._storage); @override - Future saveCity(String cityName) async{ - return await _storage.saveCity(cityName); + Future saveCity(String cityName, String colorValue) async{ + return await _storage.saveCity(cityName, colorValue); } @override From aa54d932bb868312e0b5abfd39d0bd434f38145f Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:41:45 +0300 Subject: [PATCH 52/85] Add color preservation in the repo --- lib/features/app/domain/repository/storage_repository.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index 663f6ee..0fec294 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,5 +1,5 @@ abstract class StorageRepository{ - Future saveCity(String cityName); + Future saveCity(String cityName, String colorValue); List getCities(); Future deleteCity(String cityName); } \ No newline at end of file From 8e9ec4507d726c59617de7144fc0a34b49e58493 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:41:59 +0300 Subject: [PATCH 53/85] Add color preservation in the use cases --- lib/core/usecases/usecase.dart | 2 +- lib/features/app/domain/usecases/save_city.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 56cb9d1..0214522 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -3,7 +3,7 @@ abstract class UseCase{ } abstract class SaveCityUseCase{ - Future call({required String cityName}); + Future call({required String cityName, required String colorValue}); } abstract class GetCitiesUseCase{ diff --git a/lib/features/app/domain/usecases/save_city.dart b/lib/features/app/domain/usecases/save_city.dart index 7280144..bcc25d0 100644 --- a/lib/features/app/domain/usecases/save_city.dart +++ b/lib/features/app/domain/usecases/save_city.dart @@ -7,7 +7,7 @@ class SaveCityUseCaseImplementation implements SaveCityUseCase{ SaveCityUseCaseImplementation(this._storage); @override - Future call({required String cityName}) { - return _storage.saveCity(cityName); + Future call({required String cityName, required String colorValue}) { + return _storage.saveCity(cityName, colorValue); } } \ No newline at end of file From 2368c5f93a76e09c2a728e7557267c183a1f51e4 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:42:10 +0300 Subject: [PATCH 54/85] Implement color preservation --- .../widgets/misc/bottom_sheet/bottom_sheet.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 46ba682..314f3e3 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:weathque/config/theme/custom_colors.dart'; @@ -112,7 +114,10 @@ void _onError(FToast toastManager){ } Future _onSuccess(FToast toastManager, BuildContext context) async { - bool preservationResult = await locator()(cityName: _cityController.text); + int randomIndex = Random().nextInt(CustomColors.values.length); + Color randomColor = CustomColors.values[randomIndex].color; + + bool preservationResult = await locator()(cityName: _cityController.text, colorValue: randomColor.value.toString()); late CustomToast toast; if(preservationResult){ From 72f4c200b44e3c24ca3a1c8b6c4da229815ac1b8 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:59:56 +0300 Subject: [PATCH 55/85] Add color removal --- lib/features/app/data/data_sources/local/storage.dart | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 4856c11..914bee1 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -50,11 +50,16 @@ class StorageImplementation implements Storage{ @override Future deleteCity(String cityName) async { - // TODO: Add color removal List cities = getCities(); + List colors = getColors(); + int colorIndex = cities.indexWhere((element) => element == cityName); + cities.remove(cityName); + colors.removeAt(colorIndex); await prefs.remove('cities'); + await prefs.remove('colors'); await prefs.setStringList('cities', cities); + await prefs.setStringList('colors', colors); } } \ No newline at end of file From 37e942bbcf4a59220a8e2c74d0cb4a318e961618 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:12:25 +0300 Subject: [PATCH 56/85] Add color preservation in the storage --- lib/features/app/data/data_sources/local/storage.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 914bee1..882f00b 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -4,6 +4,7 @@ abstract class Storage { late SharedPreferences prefs; Future saveCity(String cityName, String colorValue); List getCities(); + List getColors(); Future deleteCity(String cityName); } From 45a9397d03e18a34335b384bdc2db5665a53ce7f Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:13:00 +0300 Subject: [PATCH 57/85] Add color fetching in the repo --- .../data/repository/storage_repository_implementation.dart | 5 +++++ lib/features/app/domain/repository/storage_repository.dart | 1 + 2 files changed, 6 insertions(+) diff --git a/lib/features/app/data/repository/storage_repository_implementation.dart b/lib/features/app/data/repository/storage_repository_implementation.dart index d8af758..966208f 100644 --- a/lib/features/app/data/repository/storage_repository_implementation.dart +++ b/lib/features/app/data/repository/storage_repository_implementation.dart @@ -15,6 +15,11 @@ class StorageRepositoryImplementation implements StorageRepository{ List getCities() { return _storage.getCities(); } + + @override + List getColors() { + return _storage.getColors(); + } @override Future deleteCity(String cityName) async { diff --git a/lib/features/app/domain/repository/storage_repository.dart b/lib/features/app/domain/repository/storage_repository.dart index 0fec294..b9b356f 100644 --- a/lib/features/app/domain/repository/storage_repository.dart +++ b/lib/features/app/domain/repository/storage_repository.dart @@ -1,5 +1,6 @@ abstract class StorageRepository{ Future saveCity(String cityName, String colorValue); List getCities(); + List getColors(); Future deleteCity(String cityName); } \ No newline at end of file From ed94deee9f18a28e4270ab8f416c97272ba3687b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:13:11 +0300 Subject: [PATCH 58/85] Add color fetching use case --- lib/core/usecases/usecase.dart | 4 ++++ lib/features/app/domain/usecases/get_colors.dart | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 lib/features/app/domain/usecases/get_colors.dart diff --git a/lib/core/usecases/usecase.dart b/lib/core/usecases/usecase.dart index 0214522..fa4295c 100644 --- a/lib/core/usecases/usecase.dart +++ b/lib/core/usecases/usecase.dart @@ -10,6 +10,10 @@ abstract class GetCitiesUseCase{ List call(); } +abstract class GetColorsUseCase{ + List call(); +} + abstract class DeleteCityUseCase{ Future call(String cityName); } \ No newline at end of file diff --git a/lib/features/app/domain/usecases/get_colors.dart b/lib/features/app/domain/usecases/get_colors.dart new file mode 100644 index 0000000..fa5962e --- /dev/null +++ b/lib/features/app/domain/usecases/get_colors.dart @@ -0,0 +1,13 @@ +import 'package:weathque/core/usecases/usecase.dart'; +import 'package:weathque/features/app/domain/repository/storage_repository.dart'; + +class GetColorsUseCaseImplementation implements GetColorsUseCase{ + final StorageRepository _storage; + + GetColorsUseCaseImplementation(this._storage); + + @override + List call() { + return _storage.getColors(); + } +} \ No newline at end of file From 9486a9dbf1ec45317a7c8444bee622ab335f1944 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:13:19 +0300 Subject: [PATCH 59/85] Add color fetching in the DI --- lib/core/dependency_injection.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/core/dependency_injection.dart b/lib/core/dependency_injection.dart index 58e275c..9db3e6f 100644 --- a/lib/core/dependency_injection.dart +++ b/lib/core/dependency_injection.dart @@ -9,6 +9,7 @@ import 'package:weathque/features/app/domain/entities/summary_builder.dart'; import 'package:weathque/features/app/domain/repository/weather_repository.dart'; import 'package:weathque/features/app/domain/usecases/delete_city.dart'; import 'package:weathque/features/app/domain/usecases/get_cities.dart'; +import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; @@ -60,7 +61,9 @@ Future initializeDependencies() async { locator.registerSingleton( DeleteCityUseCaseImplementation(locator()) ); - + locator.registerSingleton( + GetColorsUseCaseImplementation(locator()) + ); // Blocs locator.registerFactory( From 1f6ef2773ae96d1c932816529010098a8e4e8635 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:02:46 +0300 Subject: [PATCH 60/85] Replace late init with nullable init --- .../app/data/data_sources/local/storage.dart | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 882f00b..6c6fa79 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -1,7 +1,7 @@ import 'package:shared_preferences/shared_preferences.dart'; abstract class Storage { - late SharedPreferences prefs; + SharedPreferences? prefs; Future saveCity(String cityName, String colorValue); List getCities(); List getColors(); @@ -9,9 +9,9 @@ abstract class Storage { } class StorageImplementation implements Storage{ - late SharedPreferences prefs; + SharedPreferences? prefs; - StorageImplementation() { + StorageImplementation(){ _initPrefs(); } @@ -19,6 +19,12 @@ class StorageImplementation implements Storage{ prefs = await SharedPreferences.getInstance(); } + Future ensurePrefsInitialized() async { + if (prefs == null) { + await _initPrefs(); + } + } + @override Future saveCity(String cityName, String colorValue) async { final List cities = getCities(); @@ -27,8 +33,8 @@ class StorageImplementation implements Storage{ if(!cities.contains(cityName)){ cities.add(cityName); colors.add(colorValue); - await prefs.setStringList('cities', cities); - await prefs.setStringList('colors', colors); + await prefs!.setStringList('cities', cities); + await prefs!.setStringList('colors', colors); return true; } @@ -38,13 +44,13 @@ class StorageImplementation implements Storage{ @override List getCities() { - final List cities = prefs.getStringList('cities') ?? []; + final List cities = prefs!.getStringList('cities') ?? []; return cities; } List getColors(){ - final List colors = prefs.getStringList('colors') ?? []; + final List colors = prefs!.getStringList('colors') ?? []; return colors; } @@ -58,9 +64,9 @@ class StorageImplementation implements Storage{ cities.remove(cityName); colors.removeAt(colorIndex); - await prefs.remove('cities'); - await prefs.remove('colors'); - await prefs.setStringList('cities', cities); - await prefs.setStringList('colors', colors); + await prefs!.remove('cities'); + await prefs!.remove('colors'); + await prefs!.setStringList('cities', cities); + await prefs!.setStringList('colors', colors); } } \ No newline at end of file From 65a655b569ddcef718e60641486bb3ab5dee0ad5 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:05:50 +0300 Subject: [PATCH 61/85] Make coordinated double --- lib/features/app/domain/entities/forecast_weather_entity.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/domain/entities/forecast_weather_entity.dart b/lib/features/app/domain/entities/forecast_weather_entity.dart index 81f13b2..15d164a 100644 --- a/lib/features/app/domain/entities/forecast_weather_entity.dart +++ b/lib/features/app/domain/entities/forecast_weather_entity.dart @@ -199,6 +199,6 @@ class Coord { Coord({required this.lat, required this.lon}); factory Coord.fromJson(Map json) { - return Coord(lat: json['lat'], lon: json['lon']); + return Coord(lat: json['lat'].toDouble(), lon: json['lon'].toDouble()); } } From c69a4d960601b5f089e43197ed2c6b943503d945 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:06:07 +0300 Subject: [PATCH 62/85] Refactor to use saved cities --- .../get_current_weather_bloc.dart | 12 ++++++++---- .../get_weather_forecast_bloc.dart | 9 +++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart index b57701e..ddc7311 100644 --- a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart +++ b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart @@ -1,6 +1,8 @@ import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:weathque/features/app/domain/entities/cities_enum.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/data/data_sources/local/storage.dart'; import 'package:weathque/features/app/domain/entities/weather_entity.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart'; @@ -13,13 +15,15 @@ class GetCurrentWeatherBloc extends Bloc emitter) async{ - List cities = City.values; + await locator().ensurePrefsInitialized(); + + List cities = locator()(); Map entities = {}; for (var city in cities) { - final dataState = await _getCurrentWeatherUseCase.call(cityName: city.string); + final dataState = await _getCurrentWeatherUseCase.call(cityName: city); - entities[city.string] = dataState; + entities[city] = dataState; } // ignore: invalid_use_of_visible_for_testing_member diff --git a/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart b/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart index 56d9955..8032d72 100644 --- a/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart +++ b/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart @@ -1,6 +1,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:weathque/features/app/domain/entities/cities_enum.dart'; +import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/domain/entities/forecast_weather_entity.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_weather_forecast.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_state.dart'; @@ -13,13 +14,13 @@ class GetWeatherForecastBloc extends Bloc emitter) async{ - List cities = City.values; + List cities = locator()(); Map entities = {}; for (var city in cities) { - final dataState = await _getWeatherForecastUseCase(cityName: city.string); + final dataState = await _getWeatherForecastUseCase(cityName: city); - entities[city.string] = dataState; + entities[city] = dataState; } // ignore: invalid_use_of_visible_for_testing_member From 85435b1083813ccfa2bbe5e221692398dda2f88b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:06:30 +0300 Subject: [PATCH 63/85] Fetch citites from shared prefs --- lib/main.dart | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a49d115..1675ed9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,8 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; +import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; @@ -15,7 +17,6 @@ import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get import 'package:weathque/features/app/presentation/pages/loading_page.dart'; import 'package:weathque/features/app/presentation/pages/weather_page.dart'; -import 'features/app/domain/entities/cities_enum.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); initializeDependencies(); @@ -54,16 +55,19 @@ class WeathqueApp extends StatelessWidget { return LoadingPage(color: CustomColors.yellow.color); } if(forecastWeatherState is GetWeatherForecastDone){ + List cities = locator()(); + List colors = locator()(); + return CarouselSlider( slideTransform: const CubeTransform(), unlimitedMode: true, children: [ - for (int i = 0; i < City.values.length; i++) + for (int i = 0; i < cities.length; i++) WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![City.values[i].string]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![City.values[i].string]!, - color: CustomColors.values[i].color, - city: City.values[i].string, + weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, + color: Color(int.parse(colors[i])), + city: cities[i], ), ], ); From 311c605165e6caf70938a732d5445bfe7beeab89 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:59:01 +0300 Subject: [PATCH 64/85] Add custom bottom sheet color --- lib/features/app/presentation/pages/loading_page.dart | 2 +- lib/features/app/presentation/pages/weather_page.dart | 2 +- .../app/presentation/widgets/misc/AppBar/appbar.dart | 5 +++-- .../presentation/widgets/misc/AppBar/settings_button.dart | 6 ++++-- .../widgets/misc/bottom_sheet/bottom_sheet.dart | 4 ++-- lib/main.dart | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/lib/features/app/presentation/pages/loading_page.dart b/lib/features/app/presentation/pages/loading_page.dart index 069aaf0..f395dca 100644 --- a/lib/features/app/presentation/pages/loading_page.dart +++ b/lib/features/app/presentation/pages/loading_page.dart @@ -10,7 +10,7 @@ class LoadingPage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( backgroundColor: color, - appBar: const CustomAppBar(title: "Loading"), + appBar: CustomAppBar(title: "Loading", bottomSheetColor: color), body: const Center( child: SizedBox( width: 100, diff --git a/lib/features/app/presentation/pages/weather_page.dart b/lib/features/app/presentation/pages/weather_page.dart index f1acbd0..204f8a3 100644 --- a/lib/features/app/presentation/pages/weather_page.dart +++ b/lib/features/app/presentation/pages/weather_page.dart @@ -22,7 +22,7 @@ class WeatherPage extends StatelessWidget { return Scaffold( resizeToAvoidBottomInset: false, backgroundColor: color, - appBar: CustomAppBar(title: city), + appBar: CustomAppBar(title: city, bottomSheetColor: color), body: Row( children: [ const Spacer(flex: 1,), diff --git a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart index 0a85c1b..6742745 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart @@ -3,8 +3,9 @@ import 'package:weathque/features/app/presentation/widgets/misc/AppBar/settings_ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ final String title; + final Color bottomSheetColor; - const CustomAppBar({required this.title, super.key}); + const CustomAppBar({required this.title, super.key, required this.bottomSheetColor}); @override Widget build(BuildContext context) { @@ -13,7 +14,7 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ elevation: 0, centerTitle: true, actions: [ - SettingsButton() + SettingsButton(bottomSheetColor: bottomSheetColor) ], title: Text( title, diff --git a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart index cd07557..e991928 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/settings_button.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart'; class SettingsButton extends StatefulWidget { - const SettingsButton({super.key}); + final Color bottomSheetColor; + + const SettingsButton({super.key, required this.bottomSheetColor}); @override State createState() => _SettingsButtonState(); @@ -45,7 +47,7 @@ class _SettingsButtonState extends State with TickerProviderStat _controller.reset(); _controller.forward(); - showCustomBottomSheet(context); + showCustomBottomSheet(context, widget.bottomSheetColor); }, ), ); diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 314f3e3..cd2c467 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -13,14 +13,14 @@ import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toa TextEditingController _cityController = TextEditingController(); -showCustomBottomSheet(BuildContext context){ +showCustomBottomSheet(BuildContext context, Color backgroundColor){ showModalBottomSheet( context: context, isScrollControlled: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)), ), - backgroundColor: CustomColors.yellow.color, + backgroundColor: backgroundColor, builder:(context) { return _buildBottomSheetMenu(context); }, diff --git a/lib/main.dart b/lib/main.dart index 1675ed9..c72d97e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -57,7 +57,7 @@ class WeathqueApp extends StatelessWidget { if(forecastWeatherState is GetWeatherForecastDone){ List cities = locator()(); List colors = locator()(); - + return CarouselSlider( slideTransform: const CubeTransform(), unlimitedMode: true, From 4d565b22e33a039d6050d3193c460c169b7a758c Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:09:50 +0300 Subject: [PATCH 65/85] Fill storage with default values in case it's empty --- .../app/data/data_sources/local/storage.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/features/app/data/data_sources/local/storage.dart b/lib/features/app/data/data_sources/local/storage.dart index 6c6fa79..999a887 100644 --- a/lib/features/app/data/data_sources/local/storage.dart +++ b/lib/features/app/data/data_sources/local/storage.dart @@ -17,6 +17,7 @@ class StorageImplementation implements Storage{ Future _initPrefs() async { prefs = await SharedPreferences.getInstance(); + await _fillEmptyStorage(); } Future ensurePrefsInitialized() async { @@ -25,6 +26,19 @@ class StorageImplementation implements Storage{ } } + Future _fillEmptyStorage() async{ + List defaultCities = ["Paris", "New York", "Sydney"]; + List defaultColors = ["4294959426", "4282566399", "4294927572"]; + + List cities = getCities(); + List colors = getColors(); + + if(cities.length == 0 || colors.length == 0){ + await prefs!.setStringList('cities', defaultCities); + await prefs!.setStringList('colors', defaultColors); + } + } + @override Future saveCity(String cityName, String colorValue) async { final List cities = getCities(); From ec35d96958438ab6eb9f660c5fb1548bfc27170b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:23:16 +0300 Subject: [PATCH 66/85] Update cities when user adds/deletes one --- lib/main.dart | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index c72d97e..2be90b8 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,7 +5,6 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; -import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; @@ -55,21 +54,25 @@ class WeathqueApp extends StatelessWidget { return LoadingPage(color: CustomColors.yellow.color); } if(forecastWeatherState is GetWeatherForecastDone){ - List cities = locator()(); - List colors = locator()(); - - return CarouselSlider( - slideTransform: const CubeTransform(), - unlimitedMode: true, - children: [ - for (int i = 0; i < cities.length; i++) - WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, - color: Color(int.parse(colors[i])), - city: cities[i], - ), - ], + return BlocBuilder>( + builder: (context, state) { + List cities = state; + List colors = locator()(); + + return CarouselSlider( + slideTransform: const CubeTransform(), + unlimitedMode: true, + children: [ + for (int i = 0; i < cities.length; i++) + WeatherPage( + weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, + color: Color(int.parse(colors[i])), + city: cities[i], + ), + ], + ); + }, ); } return const SizedBox(); From 7815e5b4a7d1453ec2f6ea552d9087dea17dbe63 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:34:34 +0300 Subject: [PATCH 67/85] Crear controller on success --- .../app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index cd2c467..8177a20 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -138,4 +138,5 @@ Future _onSuccess(FToast toastManager, BuildContext context) async { ); context.read()(); + _cityController.text = ""; } \ No newline at end of file From 979f4343e08176f4c927ca067b480c8962adde73 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:42:29 +0300 Subject: [PATCH 68/85] Fix null-check error when deleting a city --- .../get_current_weather_bloc.dart | 2 - lib/main.dart | 53 ++++++++++--------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart index ddc7311..fd189fc 100644 --- a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart +++ b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart @@ -15,8 +15,6 @@ class GetCurrentWeatherBloc extends Bloc emitter) async{ - await locator().ensurePrefsInitialized(); - List cities = locator()(); Map entities = {}; diff --git a/lib/main.dart b/lib/main.dart index 2be90b8..0f6f839 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,6 +5,7 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/data/data_sources/local/storage.dart'; import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; @@ -16,9 +17,10 @@ import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get import 'package:weathque/features/app/presentation/pages/loading_page.dart'; import 'package:weathque/features/app/presentation/pages/weather_page.dart'; -void main() { +void main() async{ WidgetsFlutterBinding.ensureInitialized(); initializeDependencies(); + await locator().ensurePrefsInitialized(); runApp(const WeathqueApp()); } @@ -41,22 +43,21 @@ class WeathqueApp extends StatelessWidget { child: MaterialApp( builder: FToastBuilder(), theme: theme(), - // GetCurrentWeatherBloc - home: BlocBuilder( - builder: (_, currentWeatherState) { - if(currentWeatherState is GetCurrentWeatherLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(currentWeatherState is GetCurrentWeatherDone){ - return BlocBuilder( - builder: (_, forecastWeatherState) { - if(forecastWeatherState is GetWeatherForecastLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(forecastWeatherState is GetWeatherForecastDone){ - return BlocBuilder>( - builder: (context, state) { - List cities = state; + home: BlocBuilder>( + builder: (_, cubitCities) { + return BlocBuilder( + builder: (_, currentWeatherState) { + if(currentWeatherState is GetCurrentWeatherLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(currentWeatherState is GetCurrentWeatherDone){ + return BlocBuilder( + builder: (_, forecastWeatherState) { + if(forecastWeatherState is GetWeatherForecastLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(forecastWeatherState is GetWeatherForecastDone){ + List cities = cubitCities; List colors = locator()(); return CarouselSlider( @@ -72,15 +73,15 @@ class WeathqueApp extends StatelessWidget { ), ], ); - }, - ); - } - return const SizedBox(); - }, - ); - } - return const SizedBox(); - } + } + return const SizedBox(); + }, + ); + } + return const SizedBox(); + } + ); + }, ) ) ); From 08f1321565cb314dcc552b166b98377abf56509a Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 18:49:07 +0300 Subject: [PATCH 69/85] Make last city non-dismissible --- .../widgets/misc/bottom_sheet/bottom_sheet.dart | 10 +++++++--- .../widgets/misc/bottom_sheet/city_card.dart | 6 +++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 8177a20..dde3156 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -70,13 +70,17 @@ Widget _buildBottomSheetMenu(BuildContext context){ ), Expanded( child: BlocBuilder>( - builder: (context, state) { + builder: (context, cubitCities) { return Padding( padding: const EdgeInsets.only(top: 10), child: ListView.builder( - itemCount: state.length, + itemCount: cubitCities.length, itemBuilder: (context, index) { - return CityCard(name: state[index], index: index); + if(cubitCities.length > 1){ + return CityCard(name: cubitCities[index], index: index, isLast: false); + } else{ + return CityCard(name: cubitCities[index], index: index, isLast: true); + } }, ), ); diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 0c212b5..0e05e40 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -8,8 +8,9 @@ import 'package:weathque/features/app/presentation/widgets/animations/top_animat class CityCard extends StatefulWidget { final String name; final int index; + final bool isLast; - const CityCard({super.key, required this.name, required this.index}); + const CityCard({super.key, required this.name, required this.index, required this.isLast}); @override State createState() => _CityCardState(); @@ -61,6 +62,9 @@ class _CityCardState extends State { padding: const EdgeInsets.symmetric(vertical: 2.5), child: Dismissible( key: Key(widget.name), + confirmDismiss: (direction) async { + return !widget.isLast; + }, onDismissed: (_) async { await locator()(widget.name); context.read()(); From 55c6a7afa62a523cab26727187f36f5dbdf4dd7e Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:24:53 +0300 Subject: [PATCH 70/85] Refresh cities list on adding --- .../get_current_weather_bloc.dart | 4 +- .../get_weather_forecast_bloc.dart | 5 +- .../misc/bottom_sheet/bottom_sheet.dart | 7 +- lib/main.dart | 75 +++++++++---------- 4 files changed, 49 insertions(+), 42 deletions(-) diff --git a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart index fd189fc..ecca2a2 100644 --- a/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart +++ b/lib/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart @@ -1,6 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:weathque/core/dependency_injection.dart'; -import 'package:weathque/features/app/data/data_sources/local/storage.dart'; import 'package:weathque/features/app/domain/entities/weather_entity.dart'; import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; @@ -15,6 +14,9 @@ class GetCurrentWeatherBloc extends Bloc emitter) async{ + // ignore: invalid_use_of_visible_for_testing_member + emit(const GetCurrentWeatherLoading()); + List cities = locator()(); Map entities = {}; diff --git a/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart b/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart index 8032d72..e9572d8 100644 --- a/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart +++ b/lib/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart @@ -14,11 +14,14 @@ class GetWeatherForecastBloc extends Bloc emitter) async{ + // ignore: invalid_use_of_visible_for_testing_member + emit(const GetWeatherForecastLoading()); + List cities = locator()(); Map entities = {}; for (var city in cities) { - final dataState = await _getWeatherForecastUseCase(cityName: city); + final dataState = await _getWeatherForecastUseCase.call(cityName: city); entities[city] = dataState; } diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index dde3156..9eef015 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -8,6 +8,10 @@ import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/features/app/domain/usecases/get_current_weather.dart'; import 'package:weathque/features/app/domain/usecases/save_city.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart'; import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; @@ -140,7 +144,8 @@ Future _onSuccess(FToast toastManager, BuildContext context) async { gravity: ToastGravity.BOTTOM, toastDuration: Duration(seconds: 2), ); - + BlocProvider.of(context).add(const GetCurrentWeather()); + BlocProvider.of(context).add(const GetWeatherForecast()); context.read()(); _cityController.text = ""; } \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index 0f6f839..e3c12e2 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/data/data_sources/local/storage.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; @@ -43,45 +44,41 @@ class WeathqueApp extends StatelessWidget { child: MaterialApp( builder: FToastBuilder(), theme: theme(), - home: BlocBuilder>( - builder: (_, cubitCities) { - return BlocBuilder( - builder: (_, currentWeatherState) { - if(currentWeatherState is GetCurrentWeatherLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(currentWeatherState is GetCurrentWeatherDone){ - return BlocBuilder( - builder: (_, forecastWeatherState) { - if(forecastWeatherState is GetWeatherForecastLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(forecastWeatherState is GetWeatherForecastDone){ - List cities = cubitCities; - List colors = locator()(); - - return CarouselSlider( - slideTransform: const CubeTransform(), - unlimitedMode: true, - children: [ - for (int i = 0; i < cities.length; i++) - WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, - color: Color(int.parse(colors[i])), - city: cities[i], - ), - ], - ); - } - return const SizedBox(); - }, - ); - } - return const SizedBox(); - } - ); - }, + home: BlocBuilder( + builder: (_, currentWeatherState) { + if(currentWeatherState is GetCurrentWeatherLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(currentWeatherState is GetCurrentWeatherDone){ + return BlocBuilder( + builder: (_, forecastWeatherState) { + if(forecastWeatherState is GetWeatherForecastLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(forecastWeatherState is GetWeatherForecastDone){ + List cities = locator()(); + List colors = locator()(); + + return CarouselSlider( + slideTransform: const CubeTransform(), + unlimitedMode: true, + children: [ + for (int i = 0; i < cities.length; i++) + WeatherPage( + weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, + color: Color(int.parse(colors[i])), + city: cities[i], + ), + ], + ); + } + return const SizedBox(); + }, + ); + } + return const SizedBox(); + } ) ) ); From 06880eedfdfe9d5d87dd735dc9fc878666208065 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Thu, 24 Aug 2023 22:31:23 +0300 Subject: [PATCH 71/85] Add CitiesChangedCubit to the main --- lib/main.dart | 74 +++++++++++++++++++++++++++------------------------ 1 file changed, 39 insertions(+), 35 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index e3c12e2..a5554ad 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -44,41 +44,45 @@ class WeathqueApp extends StatelessWidget { child: MaterialApp( builder: FToastBuilder(), theme: theme(), - home: BlocBuilder( - builder: (_, currentWeatherState) { - if(currentWeatherState is GetCurrentWeatherLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(currentWeatherState is GetCurrentWeatherDone){ - return BlocBuilder( - builder: (_, forecastWeatherState) { - if(forecastWeatherState is GetWeatherForecastLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(forecastWeatherState is GetWeatherForecastDone){ - List cities = locator()(); - List colors = locator()(); - - return CarouselSlider( - slideTransform: const CubeTransform(), - unlimitedMode: true, - children: [ - for (int i = 0; i < cities.length; i++) - WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, - color: Color(int.parse(colors[i])), - city: cities[i], - ), - ], - ); - } - return const SizedBox(); - }, - ); - } - return const SizedBox(); - } + home: BlocBuilder>( + builder: (_, cubitCities) { + return BlocBuilder( + builder: (_, currentWeatherState) { + if(currentWeatherState is GetCurrentWeatherLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(currentWeatherState is GetCurrentWeatherDone){ + return BlocBuilder( + builder: (_, forecastWeatherState) { + if(forecastWeatherState is GetWeatherForecastLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(forecastWeatherState is GetWeatherForecastDone){ + List cities = locator()(); + List colors = locator()(); + + return CarouselSlider( + slideTransform: const CubeTransform(), + unlimitedMode: true, + children: [ + for (int i = 0; i < cities.length; i++) + WeatherPage( + weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, + color: Color(int.parse(colors[i])), + city: cities[i], + ), + ], + ); + } + return const SizedBox(); + }, + ); + } + return const SizedBox(); + } + ); + }, ) ) ); From 88a7aecffe8ee6bacb0f4f34ba19675824dc44c8 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:53:30 +0300 Subject: [PATCH 72/85] Move forecast bloc into widget --- .../bloc/widgets/forecast_bloc_widget.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart diff --git a/lib/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart b/lib/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart new file mode 100644 index 0000000..bdd9681 --- /dev/null +++ b/lib/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_state.dart'; +import 'package:weathque/features/app/presentation/pages/loading_page.dart'; + +class ForecastBlocWidget extends StatelessWidget { + final Function(GetWeatherForecastState state) onSuccess; + + const ForecastBlocWidget({super.key, required this.onSuccess}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (_, forecastWeatherState) { + if(forecastWeatherState is GetWeatherForecastLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(forecastWeatherState is GetWeatherForecastDone){ + return onSuccess(forecastWeatherState); + } + return const SizedBox(); + }, + ); + } +} \ No newline at end of file From 9043d21a39d7d89826bc0ebae0498d5b8a7148e3 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:53:52 +0300 Subject: [PATCH 73/85] Move current weather bloc into widget --- .../widgets/current_weather_bloc_widget.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart diff --git a/lib/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart b/lib/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart new file mode 100644 index 0000000..a75f230 --- /dev/null +++ b/lib/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/config/theme/custom_colors.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart'; +import 'package:weathque/features/app/presentation/pages/loading_page.dart'; + +class CurrentWeatherForecastBloc extends StatelessWidget { + final Function(GetCurrentWeatherState state) onSuccess; + + const CurrentWeatherForecastBloc({super.key, required this.onSuccess}); + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (_, currentWeatherState) { + if(currentWeatherState is GetCurrentWeatherLoading){ + return LoadingPage(color: CustomColors.yellow.color); + } + if(currentWeatherState is GetCurrentWeatherDone){ + return onSuccess(currentWeatherState); + } + return const SizedBox(); + } + ); + } +} \ No newline at end of file From 1c0f4ecd356ce24081c3c3963b9cbf9141b76d91 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:54:01 +0300 Subject: [PATCH 74/85] Move cubit into widget --- .../bloc/widgets/cities_cubit_widget.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 lib/features/app/presentation/bloc/widgets/cities_cubit_widget.dart diff --git a/lib/features/app/presentation/bloc/widgets/cities_cubit_widget.dart b/lib/features/app/presentation/bloc/widgets/cities_cubit_widget.dart new file mode 100644 index 0000000..9afc607 --- /dev/null +++ b/lib/features/app/presentation/bloc/widgets/cities_cubit_widget.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; + +class CitiesCubitWidget extends StatelessWidget { + final Function(List state) onSuccess; + + const CitiesCubitWidget({super.key, required this.onSuccess}); + + @override + Widget build(BuildContext context) { + return BlocBuilder>( + builder: (_, cubitCities) { + return onSuccess(cubitCities); + }, + ); + } +} \ No newline at end of file From 18cc569430ce80d697644a3dc8f397cbbc4fbc0b Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:54:20 +0300 Subject: [PATCH 75/85] Move slider init into function --- .../functions/build_carousel_slider.dart | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 lib/features/app/presentation/functions/build_carousel_slider.dart diff --git a/lib/features/app/presentation/functions/build_carousel_slider.dart b/lib/features/app/presentation/functions/build_carousel_slider.dart new file mode 100644 index 0000000..362c4b5 --- /dev/null +++ b/lib/features/app/presentation/functions/build_carousel_slider.dart @@ -0,0 +1,27 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_carousel_slider/carousel_slider.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/domain/usecases/get_cities.dart'; +import 'package:weathque/features/app/domain/usecases/get_colors.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_state.dart'; +import 'package:weathque/features/app/presentation/pages/weather_page.dart'; + +Widget buildCarouselSlider(GetCurrentWeatherState currentWeatherState, GetWeatherForecastState forecastWeatherState){ + List cities = locator()(); + List colors = locator()(); + + return CarouselSlider( + slideTransform: const CubeTransform(), + unlimitedMode: true, + children: [ + for (int i = 0; i < cities.length; i++) + WeatherPage( + weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, + forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, + color: Color(int.parse(colors[i])), + city: cities[i], + ), + ], + ); +} \ No newline at end of file From aa83c64c3d79174e9d0362aaac29d730faee9412 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 17:54:29 +0300 Subject: [PATCH 76/85] Implement all the changes --- lib/main.dart | 61 +++++++++++++-------------------------------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index a5554ad..fb48ca7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,22 +1,18 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_carousel_slider/carousel_slider.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; -import 'package:weathque/config/theme/custom_colors.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/data/data_sources/local/storage.dart'; -import 'package:weathque/features/app/domain/usecases/get_cities.dart'; -import 'package:weathque/features/app/domain/usecases/get_colors.dart'; import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; -import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_state.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; -import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_state.dart'; -import 'package:weathque/features/app/presentation/pages/loading_page.dart'; -import 'package:weathque/features/app/presentation/pages/weather_page.dart'; +import 'package:weathque/features/app/presentation/bloc/widgets/cities_cubit_widget.dart'; +import 'package:weathque/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart'; +import 'package:weathque/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart'; +import 'features/app/presentation/functions/build_carousel_slider.dart'; void main() async{ WidgetsFlutterBinding.ensureInitialized(); @@ -44,47 +40,20 @@ class WeathqueApp extends StatelessWidget { child: MaterialApp( builder: FToastBuilder(), theme: theme(), - home: BlocBuilder>( - builder: (_, cubitCities) { - return BlocBuilder( - builder: (_, currentWeatherState) { - if(currentWeatherState is GetCurrentWeatherLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(currentWeatherState is GetCurrentWeatherDone){ - return BlocBuilder( - builder: (_, forecastWeatherState) { - if(forecastWeatherState is GetWeatherForecastLoading){ - return LoadingPage(color: CustomColors.yellow.color); - } - if(forecastWeatherState is GetWeatherForecastDone){ - List cities = locator()(); - List colors = locator()(); - - return CarouselSlider( - slideTransform: const CubeTransform(), - unlimitedMode: true, - children: [ - for (int i = 0; i < cities.length; i++) - WeatherPage( - weatherEntity: currentWeatherState.weatherEntity![cities[i]]!, - forecastWeatherEntity: forecastWeatherState.forecastWeatherEntity![cities[i]]!, - color: Color(int.parse(colors[i])), - city: cities[i], - ), - ], - ); - } - return const SizedBox(); - }, - ); - } - return const SizedBox(); - } + home: CitiesCubitWidget( + onSuccess: (state) { + return CurrentWeatherForecastBloc( + onSuccess: (currentWeatherState) { + return ForecastBlocWidget( + onSuccess: (forecastWeatherState) { + return buildCarouselSlider(currentWeatherState, forecastWeatherState); + }, + ); + }, ); }, ) ) ); } -} +} \ No newline at end of file From 56366c77cc00548b3541322a707ca2938b7e894d Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:04:27 +0300 Subject: [PATCH 77/85] Move MultiBlocProvider into separate windet --- .../bloc/blocs_provider_builder.dart | 31 +++++++++++++++++++ lib/main.dart | 23 +++----------- 2 files changed, 35 insertions(+), 19 deletions(-) create mode 100644 lib/features/app/presentation/bloc/blocs_provider_builder.dart diff --git a/lib/features/app/presentation/bloc/blocs_provider_builder.dart b/lib/features/app/presentation/bloc/blocs_provider_builder.dart new file mode 100644 index 0000000..b4c678c --- /dev/null +++ b/lib/features/app/presentation/bloc/blocs_provider_builder.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/core/dependency_injection.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; + +class BlocsProviderBuilder extends StatelessWidget { + final Widget child; + final BuildContext context; + final List providers = [ + BlocProvider( + create: (buildContext) => locator()..add(const GetCurrentWeather()) + ), + BlocProvider( + create: (buildContext) => locator()..add(const GetWeatherForecast()), + ), + BlocProvider( + create: (buildContext) => locator(), + ) + ]; + + BlocsProviderBuilder({super.key, required this.child, required this.context}); + + @override + Widget build(BuildContext context) { + return MultiBlocProvider(providers: providers, child: child); + } +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart index fb48ca7..8fe9224 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,14 +1,9 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:weathque/config/theme/app_themes.dart'; import 'package:weathque/core/dependency_injection.dart'; import 'package:weathque/features/app/data/data_sources/local/storage.dart'; -import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; -import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_bloc.dart'; -import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; -import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; -import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; +import 'package:weathque/features/app/presentation/bloc/blocs_provider_builder.dart'; import 'package:weathque/features/app/presentation/bloc/widgets/cities_cubit_widget.dart'; import 'package:weathque/features/app/presentation/bloc/widgets/current_weather_bloc_widget.dart'; import 'package:weathque/features/app/presentation/bloc/widgets/forecast_bloc_widget.dart'; @@ -25,18 +20,8 @@ class WeathqueApp extends StatelessWidget { const WeathqueApp({super.key}); @override Widget build(BuildContext context) { - return MultiBlocProvider( - providers: [ - BlocProvider( - create: (context) => locator()..add(const GetCurrentWeather()) - ), - BlocProvider( - create: (context) => locator()..add(const GetWeatherForecast()), - ), - BlocProvider( - create: (context) => locator(), - ) - ], + return BlocsProviderBuilder( + context: context, child: MaterialApp( builder: FToastBuilder(), theme: theme(), @@ -53,7 +38,7 @@ class WeathqueApp extends StatelessWidget { ); }, ) - ) + ), ); } } \ No newline at end of file From 62148e5d9135abe24448907b53859def52a48ca6 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:10:47 +0300 Subject: [PATCH 78/85] Change border radius --- .../app/presentation/widgets/misc/bottom_sheet/city_card.dart | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart index 0e05e40..0f9fce8 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart @@ -70,6 +70,9 @@ class _CityCardState extends State { context.read()(); }, child: Card( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(15.0)) + ), child: Center( child: Padding( padding: const EdgeInsets.symmetric(vertical: 15), From 05afebf2fb1c44dcedf4d841296651cb1d66ba61 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:17:52 +0300 Subject: [PATCH 79/85] Move city card --- .../widgets/misc/bottom_sheet/{ => widgets}/city_card.dart | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lib/features/app/presentation/widgets/misc/bottom_sheet/{ => widgets}/city_card.dart (100%) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/city_card.dart similarity index 100% rename from lib/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart rename to lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/city_card.dart From e3f39c5382a0492995a02db07718069fa27b2c61 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:18:10 +0300 Subject: [PATCH 80/85] Move text view into separate widget --- .../widgets/bottom_sheet_text_field.dart | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_text_field.dart diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_text_field.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_text_field.dart new file mode 100644 index 0000000..159110a --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_text_field.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; + +class BottomSheetTextField extends StatelessWidget { + final TextEditingController controller; + final FToast toastManager; + final Function(FToast toastManager, BuildContext context) onSubmit; + + const BottomSheetTextField({super.key, required this.controller, required this.toastManager, required this.onSubmit}); + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + onSubmitted: (value) { + onSubmit(toastManager, context); + }, + textCapitalization: TextCapitalization.words, + cursorColor: Colors.black, + decoration: InputDecoration( + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20.0)), + borderSide: BorderSide(color: Colors.black) + ), + hintText: "Enter a city", + labelText: "City", + labelStyle: TextStyle( + color: Colors.black + ), + suffixIcon: IconButton( + icon: Icon(Icons.search, color: Colors.black), + onPressed: () { + onSubmit(toastManager, context); + }, + ) + ), + ); + } +} \ No newline at end of file From aeae4f9a92e77989228a55d33152d34aedfc0132 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:18:19 +0300 Subject: [PATCH 81/85] Move list view into separate widget --- .../widgets/bottom_sheet_list_view.dart | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_list_view.dart diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_list_view.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_list_view.dart new file mode 100644 index 0000000..02d80d8 --- /dev/null +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_list_view.dart @@ -0,0 +1,31 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:weathque/features/app/presentation/bloc/add_city/cities_changed_cubit.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/widgets/city_card.dart'; + +class BottomSheetListView extends StatelessWidget { + const BottomSheetListView({super.key}); + + @override + Widget build(BuildContext context) { + return Expanded( + child: BlocBuilder>( + builder: (context, cubitCities) { + return Padding( + padding: const EdgeInsets.only(top: 10), + child: ListView.builder( + itemCount: cubitCities.length, + itemBuilder: (context, index) { + if(cubitCities.length > 1){ + return CityCard(name: cubitCities[index], index: index, isLast: false); + } else{ + return CityCard(name: cubitCities[index], index: index, isLast: true); + } + }, + ), + ); + }, + ), + ); + } +} \ No newline at end of file From 3d5db55804ae518dc21009ba2bb40fb0e1cda3b6 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 18:18:28 +0300 Subject: [PATCH 82/85] Implement changes --- .../misc/bottom_sheet/bottom_sheet.dart | 56 +++---------------- 1 file changed, 8 insertions(+), 48 deletions(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 9eef015..97dfb7f 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -12,7 +12,8 @@ import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_ import 'package:weathque/features/app/presentation/bloc/get_current_weather/get_current_weather_event.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_bloc.dart'; import 'package:weathque/features/app/presentation/bloc/get_weather_forecast/get_weather_forecast_event.dart'; -import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/city_card.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_list_view.dart'; +import 'package:weathque/features/app/presentation/widgets/misc/bottom_sheet/widgets/bottom_sheet_text_field.dart'; import 'package:weathque/features/app/presentation/widgets/misc/toast/custom_toast.dart'; TextEditingController _cityController = TextEditingController(); @@ -43,54 +44,13 @@ Widget _buildBottomSheetMenu(BuildContext context){ child: Column( crossAxisAlignment: CrossAxisAlignment.center, children: [ - TextField( - controller: _cityController, - onSubmitted: (value) { - _onSubmit(toastManager, context); - }, - textCapitalization: TextCapitalization.words, - cursorColor: Colors.black, - decoration: InputDecoration( - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20.0)), - borderSide: BorderSide(color: Colors.black) - ), - hintText: "Enter a city", - labelText: "City", - labelStyle: TextStyle( - color: Colors.black - ), - suffixIcon: IconButton( - icon: Icon(Icons.search, color: Colors.black), - onPressed: () { - _onSubmit(toastManager, context); - }, - ) - ), + BottomSheetTextField( + controller: _cityController, + toastManager: toastManager, + onSubmit: _onSubmit ), - Expanded( - child: BlocBuilder>( - builder: (context, cubitCities) { - return Padding( - padding: const EdgeInsets.only(top: 10), - child: ListView.builder( - itemCount: cubitCities.length, - itemBuilder: (context, index) { - if(cubitCities.length > 1){ - return CityCard(name: cubitCities[index], index: index, isLast: false); - } else{ - return CityCard(name: cubitCities[index], index: index, isLast: true); - } - }, - ), - ); - }, - ), - ) + + BottomSheetListView() ], ), ), From afcf6ed7b65a32fb7f63eb8e48624dcd6a11fdf9 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:06:12 +0300 Subject: [PATCH 83/85] Remove variable init --- .../presentation/widgets/misc/bottom_sheet/bottom_sheet.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart index 97dfb7f..9605ac4 100644 --- a/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart +++ b/lib/features/app/presentation/widgets/misc/bottom_sheet/bottom_sheet.dart @@ -61,7 +61,7 @@ void _onSubmit(FToast toastManager, BuildContext context) async { String cityName = _cityController.text; try { - var response = await locator()(cityName: cityName); + await locator()(cityName: cityName); } catch (_) { _onError(toastManager); return; From 4a0a296d185324cbd4543913bd672a60cacc0127 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 19:24:19 +0300 Subject: [PATCH 84/85] Change version number --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a52a3fb..7fec7aa 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.0+1 +version: 1.1.0+1 environment: sdk: '>=3.0.0 <4.0.0' From e4bc2e8cabfb3dbb3893a848643f1b006e8c1f51 Mon Sep 17 00:00:00 2001 From: tortamque <90132962+tortamque@users.noreply.github.com> Date: Fri, 25 Aug 2023 20:05:49 +0300 Subject: [PATCH 85/85] Change status bar icons color to black --- .../app/presentation/widgets/misc/AppBar/appbar.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart index 6742745..bb396e7 100644 --- a/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart +++ b/lib/features/app/presentation/widgets/misc/AppBar/appbar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:weathque/features/app/presentation/widgets/misc/AppBar/settings_button.dart'; class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ @@ -22,6 +23,11 @@ class CustomAppBar extends StatelessWidget implements PreferredSizeWidget{ fontWeight: FontWeight.bold ), ), + systemOverlayStyle: SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark, + statusBarBrightness: Brightness.dark, + ), ); }