From e36f8dbfa6f127f9b8972dad2937d188b527e925 Mon Sep 17 00:00:00 2001 From: Shubh Kanodia Date: Sat, 28 Oct 2023 13:59:33 +0530 Subject: [PATCH 1/2] Spinkit_issue_fixed_added_fade --- lib/widgets/display_firestore_data.dart | 33 +++++++++++++++---------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/widgets/display_firestore_data.dart b/lib/widgets/display_firestore_data.dart index 4cdace1..c65f388 100644 --- a/lib/widgets/display_firestore_data.dart +++ b/lib/widgets/display_firestore_data.dart @@ -15,19 +15,26 @@ class DisplayFirestoreData extends StatelessWidget { return FutureBuilder>( future: firestoreService.fetchNewsItemsByCategory(category), builder: (context, snapshot) { - if (snapshot.connectionState == ConnectionState.waiting) { - return (const Center( - child: SpinKitDualRing( - color: Color(0xFF4169E1), - size: 30.0, - ), - )); - } else if (snapshot.data == null) { - return const Center(child: Text('An error occurred.')); - } else { - return ListViewBuilderByTab( - category: category, newsItems: snapshot.data!); - } + return AnimatedSwitcher( + duration: Duration(milliseconds: 650), + child: snapshot.connectionState == ConnectionState.waiting + ? Center( + // key: UniqueKey(), // Do not use rn, it will cause the widget to rebuild and will trigger a dirty rebuild- Shubh + child: SpinKitDualRing( + color: Color(0xFF4169E1), + size: 30.0, + ), + ) + : snapshot.hasError + ? Center( + // key: UniqueKey(), // Use UniqueKey for the error widget + child: Text('An error occurred: ${snapshot.error}'), + ) + : ListViewBuilderByTab( + category: category, + newsItems: snapshot.data ?? [], + ), + ); }, ); } From d922c03aaaefcf666fed490cd6575a2ce7b40259 Mon Sep 17 00:00:00 2001 From: Shubh Kanodia Date: Sat, 28 Oct 2023 17:02:19 +0530 Subject: [PATCH 2/2] Spinkit_fixed, minor UI, architecture changes --- lib/main.dart | 4 +- lib/screens/home_screen.dart | 148 ++++++++-------- lib/screens/splash_screen.dart | 2 +- lib/widgets/bottom_bar.dart | 57 ++++++ lib/widgets/display_firestore_data.dart | 26 +-- lib/widgets/list_view_builder_tab.dart | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 162 +++++++++++++++++- pubspec.yaml | 2 + test/widget_test.dart | 2 +- 10 files changed, 316 insertions(+), 91 deletions(-) create mode 100644 lib/widgets/bottom_bar.dart diff --git a/lib/main.dart b/lib/main.dart index c70faac..3a7e556 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,10 +7,12 @@ void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); // Initialize Firebase here - runApp(MyApp()); + runApp(const MyApp()); } class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override Widget build(BuildContext context) { return MaterialApp( diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index a9e5a11..6dc91ce 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -1,8 +1,12 @@ import 'package:flutter/material.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; +import 'package:google_fonts/google_fonts.dart'; import '/widgets/display_firestore_data.dart'; +import '/widgets/bottom_bar.dart'; class HomeScreen extends StatefulWidget { + const HomeScreen({super.key}); + @override _HomeScreenState createState() => _HomeScreenState(); } @@ -11,35 +15,16 @@ class _HomeScreenState extends State { PageController pageController = PageController(); int currentIndex = 0; - String _getMonth(int month) { - switch (month) { - case 1: - return 'January'; - case 2: - return 'February'; - case 3: - return 'March'; - case 4: - return 'April'; - case 5: - return 'May'; - case 6: - return 'June'; - case 7: - return 'July'; - case 8: - return 'August'; - case 9: - return 'September'; - case 10: - return 'October'; - case 11: - return 'November'; - case 12: - return 'December'; - default: - return 'Unknown'; - } + //Callback to handle when bottom bar is tapped - the below function is passed as a parameter to bottom_bar.dart + void onTabTapped(int index) { + setState(() { + currentIndex = index; + pageController.animateToPage( + index, + duration: const Duration(milliseconds: 20), + curve: Curves.ease, + ); + }); } @override @@ -47,17 +32,22 @@ class _HomeScreenState extends State { return Scaffold( appBar: AppBar( backgroundColor: const Color(0xffE2F9EE), - leadingWidth: 65, + leadingWidth: 100, leading: const Padding( - padding: EdgeInsets.only(left: 5.0), - child: Image(image: AssetImage('assets/logos/PesBuzzLogo.png')), + padding: EdgeInsets.only(left: 0), + child: Image( + image: AssetImage( + 'assets/logos/PesBuzzLogo.png', + )), ), - title: const Text( + title: Text( 'PES Buzz', - style: TextStyle( - color: Colors.black, - fontWeight: FontWeight.bold, - fontSize: 28, + style: GoogleFonts.poppins( + textStyle: const TextStyle( + color: Colors.black, + fontSize: 30, + fontWeight: FontWeight.bold, + ), ), ), actions: [ @@ -73,13 +63,16 @@ class _HomeScreenState extends State { body: Container( decoration: const BoxDecoration( gradient: LinearGradient( - begin: Alignment.topCenter, - end: Alignment.bottomCenter, - colors: [ - Color(0xffE2F9EE), - Color(0xffFBFBD4), - ], - ), + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [ + Color(0xffE2F9EE), + Color.fromARGB(255, 218, 229, 194), + ], + stops: [ + 0.25, + 1.0 + ]), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -103,7 +96,7 @@ class _HomeScreenState extends State { currentIndex = index; }); }, - children: [ + children: const [ DisplayFirestoreData(category: 'Trendy'), DisplayFirestoreData(category: 'Sports'), DisplayFirestoreData(category: 'Department'), @@ -113,39 +106,42 @@ class _HomeScreenState extends State { ], ), ), - bottomNavigationBar: BottomNavigationBar( - unselectedItemColor: Colors.blueGrey, - selectedItemColor: Colors.black, + //BottomBar is now under bottom_bar.dart in widgets folder + bottomNavigationBar: BottomBar( currentIndex: currentIndex, - onTap: (index) { - setState(() { - currentIndex = index; - pageController.animateToPage( - index, - duration: const Duration(milliseconds: 500), - curve: Curves.ease, - ); - }); - }, - items: const [ - BottomNavigationBarItem( - icon: Icon(Icons.trending_up), - label: 'Trendy', - ), - BottomNavigationBarItem( - icon: Icon(Icons.sports_soccer), - label: 'Sports', - ), - BottomNavigationBarItem( - icon: Icon(Icons.school), - label: 'Department', - ), - BottomNavigationBarItem( - icon: Icon(Icons.bookmark_outline), - label: 'Bookmarks', - ), - ], + onTabTapped: onTabTapped, ), ); } + + String _getMonth(int month) { + switch (month) { + case 1: + return 'January'; + case 2: + return 'February'; + case 3: + return 'March'; + case 4: + return 'April'; + case 5: + return 'May'; + case 6: + return 'June'; + case 7: + return 'July'; + case 8: + return 'August'; + case 9: + return 'September'; + case 10: + return 'October'; + case 11: + return 'November'; + case 12: + return 'December'; + default: + return 'Unknown'; + } + } } diff --git a/lib/screens/splash_screen.dart b/lib/screens/splash_screen.dart index 3992991..2b7dc97 100644 --- a/lib/screens/splash_screen.dart +++ b/lib/screens/splash_screen.dart @@ -21,7 +21,7 @@ class _SplashScreenState extends State { void _navigateToNextScreen() { Navigator.of(context).pushReplacement( PageRouteBuilder( - pageBuilder: (context, animation, secondaryAnimation) => HomeScreen(), + pageBuilder: (context, animation, secondaryAnimation) => const HomeScreen(), transitionsBuilder: (context, animation, secondaryAnimation, child) { const begin = Offset(1.0, 0.0); const end = Offset.zero; diff --git a/lib/widgets/bottom_bar.dart b/lib/widgets/bottom_bar.dart new file mode 100644 index 0000000..99b15e3 --- /dev/null +++ b/lib/widgets/bottom_bar.dart @@ -0,0 +1,57 @@ +import 'package:flutter/material.dart'; + +class BottomBar extends StatelessWidget { + final int currentIndex; + final Function(int) onTabTapped; + + const BottomBar( + {Key? key, required this.currentIndex, required this.onTabTapped}) + : super(key: key); + + @override + Widget build(BuildContext context) { + return BottomNavigationBar( + type: BottomNavigationBarType + .fixed, // Ensure the labels are always displayed + backgroundColor: Color.fromARGB(255, 34, 30, 30), + unselectedItemColor: Colors.blueGrey, + selectedItemColor: Colors.white, + currentIndex: currentIndex, + onTap: onTabTapped, + items: const [ + BottomNavigationBarItem( + icon: Padding( + padding: EdgeInsets.only(top: 10.0), + child: Icon(Icons.trending_up), + ), + label: 'Trendy', + ), + BottomNavigationBarItem( + icon: Padding( + padding: EdgeInsets.only(top: 10.0), + child: Icon(Icons.calendar_month_outlined), + ), + label: 'Events', + ), + BottomNavigationBarItem( + icon: Padding( + padding: EdgeInsets.only(top: 10.0), + child: Icon(Icons.school), + ), + label: 'Department', + ), + BottomNavigationBarItem( + icon: Padding( + padding: EdgeInsets.only(top: 10.0), + child: Icon(Icons.bookmark_outline), + ), + label: 'Bookmarks', + ), + ], + ); + } +} + + + +// Color.fromARGB(255, 34, 30, 30), \ No newline at end of file diff --git a/lib/widgets/display_firestore_data.dart b/lib/widgets/display_firestore_data.dart index c65f388..69ffdbe 100644 --- a/lib/widgets/display_firestore_data.dart +++ b/lib/widgets/display_firestore_data.dart @@ -4,34 +4,40 @@ import '/services/firestore_service.dart'; import '/widgets/list_view_builder_tab.dart'; import 'package:flutter_spinkit/flutter_spinkit.dart'; -class DisplayFirestoreData extends StatelessWidget { - final FirestoreService firestoreService = FirestoreService(); +class DisplayFirestoreData extends StatefulWidget { final String category; - DisplayFirestoreData({required this.category}); + const DisplayFirestoreData({super.key, required this.category}); + + @override + State createState() => _DisplayFirestoreDataState(); +} + +class _DisplayFirestoreDataState extends State { + final FirestoreService firestoreService = FirestoreService(); @override Widget build(BuildContext context) { return FutureBuilder>( - future: firestoreService.fetchNewsItemsByCategory(category), + future: firestoreService.fetchNewsItemsByCategory(widget.category), builder: (context, snapshot) { return AnimatedSwitcher( - duration: Duration(milliseconds: 650), + duration: const Duration(milliseconds: 300), child: snapshot.connectionState == ConnectionState.waiting ? Center( - // key: UniqueKey(), // Do not use rn, it will cause the widget to rebuild and will trigger a dirty rebuild- Shubh - child: SpinKitDualRing( - color: Color(0xFF4169E1), + key: UniqueKey(), // + child: const SpinKitDualRing( + color: Colors.black, size: 30.0, ), ) : snapshot.hasError ? Center( - // key: UniqueKey(), // Use UniqueKey for the error widget + key: UniqueKey(), // Use UniqueKey for the error widget child: Text('An error occurred: ${snapshot.error}'), ) : ListViewBuilderByTab( - category: category, + category: widget.category, newsItems: snapshot.data ?? [], ), ); diff --git a/lib/widgets/list_view_builder_tab.dart b/lib/widgets/list_view_builder_tab.dart index 9e4eec9..4bfc96a 100644 --- a/lib/widgets/list_view_builder_tab.dart +++ b/lib/widgets/list_view_builder_tab.dart @@ -6,7 +6,7 @@ class ListViewBuilderByTab extends StatelessWidget { final String category; final List newsItems; - ListViewBuilderByTab({required this.category, required this.newsItems}); + const ListViewBuilderByTab({super.key, required this.category, required this.newsItems}); @override Widget build(BuildContext context) { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 6d06bd4..8873098 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,9 +8,11 @@ import Foundation import cloud_firestore import firebase_core import path_provider_foundation +import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseFirestorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseFirestorePlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 8c02053..2640855 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -17,6 +17,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" async: dependency: transitive description: @@ -33,6 +41,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + sha256: f98972704692ba679db144261172a8e20feb145636c617af0eb4022132a6797f + url: "https://pub.dev" + source: hosted + version: "3.3.0" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + sha256: "56aa42a7a01e3c9db8456d9f3f999931f1e05535b5a424271e9a38cabf066613" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + sha256: "759b9a9f8f6ccbb66c185df805fac107f05730b1dab9c64626d1008cca532257" + url: "https://pub.dev" + source: hosted + version: "1.1.0" characters: dependency: transitive description: @@ -113,6 +145,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" firebase_core: dependency: "direct main" description: @@ -142,6 +182,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + sha256: "8207f27539deb83732fdda03e259349046a39a4c767269285f449ade355d54ba" + url: "https://pub.dev" + source: hosted + version: "3.3.1" flutter_lints: dependency: "direct dev" description: @@ -158,6 +206,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.2.0" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: bfc7cc3c75fe1282e8ce2e056d8fd1533f1a6848b65c379b4a5e7a9b623d3371 + url: "https://pub.dev" + source: hosted + version: "2.0.8" flutter_test: dependency: "direct dev" description: flutter @@ -240,6 +296,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.1" + octo_image: + dependency: transitive + description: + name: octo_image + sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d" + url: "https://pub.dev" + source: hosted + version: "2.0.0" path: dependency: transitive description: @@ -248,6 +312,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: transitive description: @@ -296,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" platform: dependency: transitive description: @@ -312,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.6" + rxdart: + dependency: transitive + description: + name: rxdart + sha256: "0c7c0cedd93788d996e33041ffecda924cc54389199cde4e6a34b440f50044cb" + url: "https://pub.dev" + source: hosted + version: "0.27.7" sky_engine: dependency: transitive description: flutter @@ -325,6 +413,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + sprintf: + dependency: transitive + description: + name: sprintf + sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + sqflite: + dependency: transitive + description: + name: sqflite + sha256: "591f1602816e9c31377d5f008c2d9ef7b8aca8941c3f89cc5fd9d84da0c38a9a" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "1b92f368f44b0dee2425bb861cfa17b6f6cf3961f762ff6f941d20b33355660a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" stack_trace: dependency: transitive description: @@ -349,6 +461,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60" + url: "https://pub.dev" + source: hosted + version: "3.1.0" term_glyph: dependency: transitive description: @@ -373,6 +493,38 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.2" + uuid: + dependency: transitive + description: + name: uuid + sha256: b715b8d3858b6fa9f68f87d20d98830283628014750c2b09b6f516c1da4af2a7 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "0f0c746dd2d6254a0057218ff980fc7f5670fd0fcf5e4db38a490d31eed4ad43" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "0edf6d630d1bfd5589114138ed8fada3234deacc37966bec033d3047c29248b7" + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: d24333727332d9bd20990f1483af4e09abdb9b1fc7c3db940b56ab5c42790c26 + url: "https://pub.dev" + source: hosted + version: "1.1.9+1" vector_math: dependency: transitive description: @@ -405,6 +557,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.3" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" sdks: dart: ">=3.1.3 <4.0.0" - flutter: ">=3.7.0" + flutter: ">=3.10.0" diff --git a/pubspec.yaml b/pubspec.yaml index bd9a9d0..807097f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,8 @@ dependencies: flutter_spinkit: ^5.2.0 another_flutter_splash_screen: ^1.2.0 font_awesome_flutter: ^10.6.0 + flutter_svg: ^2.0.8 + cached_network_image: ^3.3.0 dev_dependencies: flutter_test: diff --git a/test/widget_test.dart b/test/widget_test.dart index aad60af..664cd31 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -13,7 +13,7 @@ import 'package:pesbuzz/main.dart'; void main() { testWidgets('Counter increments smoke test', (WidgetTester tester) async { // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); + await tester.pumpWidget(const MyApp()); // Verify that our counter starts at 0. expect(find.text('0'), findsOneWidget);