From 4b7d33896879baba1435281f814766a80fbeecb2 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Sun, 26 Mar 2023 21:04:58 -0600 Subject: Added popular movies screen and Firebase support --- .gitignore | 3 ++ android/app/build.gradle | 5 +- android/build.gradle | 1 + lib/firebase/email_auth.dart | 17 +++++++ lib/main.dart | 5 +- lib/models/popular.dart | 45 ++++++++++++++++++ lib/network/popular_api.dart | 19 ++++++++ lib/routes.dart | 2 + lib/screens/dashboard_screen.dart | 7 +++ lib/screens/popular_screen.dart | 55 ++++++++++++++++++++++ lib/widgets/popular_item.dart | 18 ++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 4 ++ pubspec.lock | 66 ++++++++++++++++++++++++++- pubspec.yaml | 3 ++ 14 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 lib/firebase/email_auth.dart create mode 100644 lib/models/popular.dart create mode 100644 lib/network/popular_api.dart create mode 100644 lib/screens/popular_screen.dart create mode 100644 lib/widgets/popular_item.dart diff --git a/.gitignore b/.gitignore index 24476c5..4c75159 100644 --- a/.gitignore +++ b/.gitignore @@ -42,3 +42,6 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# Firebase +/android/app/google-services.json diff --git a/android/app/build.gradle b/android/app/build.gradle index be0889c..0545ba2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -23,6 +23,7 @@ if (flutterVersionName == null) { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'com.google.gms.google-services' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { @@ -47,7 +48,7 @@ android { applicationId "com.example.pmsna1" // You can update the following values to match your application needs. // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. - minSdkVersion flutter.minSdkVersion + minSdkVersion 21 // flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName @@ -67,5 +68,7 @@ flutter { } dependencies { + implementation platform('com.google.firebase:firebase-bom:31.3.0') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" } diff --git a/android/build.gradle b/android/build.gradle index 58a8c74..144835c 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,6 +8,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:7.2.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "com.google.gms:google-services:4.3.15" } } diff --git a/lib/firebase/email_auth.dart b/lib/firebase/email_auth.dart new file mode 100644 index 0000000..70389ca --- /dev/null +++ b/lib/firebase/email_auth.dart @@ -0,0 +1,17 @@ +import 'package:firebase_auth/firebase_auth.dart'; + +class EmailAuth { + final FirebaseAuth _auth = FirebaseAuth.instance; + + Future createUserWithEmailAndPassword({ + required String email, + required String password, + }) async { + try { + UserCredential cred = await _auth.createUserWithEmailAndPassword( + email: email, + password: password, + ); + } catch (e) {} + } +} diff --git a/lib/main.dart b/lib/main.dart index 026019c..0b10f9b 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,4 @@ +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; import 'package:pmsna1/providers/flags_provider.dart'; import 'package:pmsna1/providers/theme_provider.dart'; @@ -5,7 +6,9 @@ import 'package:pmsna1/routes.dart'; import 'package:pmsna1/settings/themes.dart'; import 'package:provider/provider.dart'; -void main(List args) { +void main(List args) async { + WidgetsFlutterBinding.ensureInitialized(); + await Firebase.initializeApp(); return runApp(const MainContent()); } diff --git a/lib/models/popular.dart b/lib/models/popular.dart new file mode 100644 index 0000000..afe6858 --- /dev/null +++ b/lib/models/popular.dart @@ -0,0 +1,45 @@ +class Popular { + String? backdropPath; + int? id; + String? originalLanguage; + String? originalTitle; + String? overview; + double? popularity; + String? posterPath; + String? releaseDate; + String? title; + double? voteAverage; + int? voteCount; + + Popular({ + this.backdropPath, + this.id, + this.originalLanguage, + this.originalTitle, + this.overview, + this.popularity, + this.posterPath, + this.releaseDate, + this.title, + this.voteAverage, + this.voteCount, + }); + + factory Popular.fromMap(Map map) { + return Popular( + backdropPath: map['backdrop_path'], + id: map['id'], + originalLanguage: map['original_language'], + originalTitle: map['original_title'], + overview: map['overview'], + popularity: map['popularity'], + posterPath: map['poster_path'], + releaseDate: map['release_date'], + title: map['title'], + voteAverage: (map['vote_average'] is int) + ? (map['vote_average'] as int).toDouble() + : map['vote_average'], + voteCount: map['vote_count'], + ); + } +} diff --git a/lib/network/popular_api.dart b/lib/network/popular_api.dart new file mode 100644 index 0000000..4d2c033 --- /dev/null +++ b/lib/network/popular_api.dart @@ -0,0 +1,19 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:pmsna1/models/popular.dart'; + +class PopularApi { + String apiKey = '0cb894064f40656f3575e8ccae3d8d73'; + Uri get link => Uri.parse( + 'https://api.themoviedb.org/3/movie/popular?api_key=$apiKey&language=es-MX&page=1'); + + Future?> getAllPopular() async { + http.Response result = await http.get(link); + var list = jsonDecode(result.body)['results'] as List; + if (result.statusCode != 200) { + return null; + } + return list.map((popular) => Popular.fromMap(popular)).toList(); + } +} diff --git a/lib/routes.dart b/lib/routes.dart index 7510075..81bf833 100644 --- a/lib/routes.dart +++ b/lib/routes.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:pmsna1/screens/dashboard_screen.dart'; import 'package:pmsna1/screens/new_post_screen.dart'; import 'package:pmsna1/screens/onboarding_screen.dart'; +import 'package:pmsna1/screens/popular_screen.dart'; import 'screens/login_screen.dart'; import 'screens/register_screen.dart'; @@ -13,5 +14,6 @@ Map getApplicationRoutes() { '/onboard': (BuildContext context) => const OnboardingScreen(), '/dash': (BuildContext context) => const DashboardScreen(), '/new': (BuildContext context) => const NewPostScreen(), + '/popular': (BuildContext context) => const PopularScreen(), }; } diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart index 3f4ae21..9046878 100644 --- a/lib/screens/dashboard_screen.dart +++ b/lib/screens/dashboard_screen.dart @@ -37,6 +37,13 @@ class DashboardScreen extends StatelessWidget { onTap: () {}, ), const Divider(), + ListTile( + title: const Text('Películas populares'), + leading: const Icon(Icons.movie), + onTap: () { + Navigator.of(context).pushNamed('/popular'); + }, + ), ListTile( title: const Text('Tema'), trailing: SegmentedButton( diff --git a/lib/screens/popular_screen.dart b/lib/screens/popular_screen.dart new file mode 100644 index 0000000..07ca70e --- /dev/null +++ b/lib/screens/popular_screen.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:pmsna1/models/popular.dart'; +import 'package:pmsna1/network/popular_api.dart'; +import 'package:pmsna1/widgets/loading_modal_widget.dart'; +import 'package:pmsna1/widgets/popular_item.dart'; + +class PopularScreen extends StatefulWidget { + const PopularScreen({super.key}); + + @override + State createState() => _PopularScreenState(); +} + +class _PopularScreenState extends State { + PopularApi? popularApi; + + @override + void initState() { + super.initState(); + popularApi = PopularApi(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Películas populares')), + body: FutureBuilder( + future: popularApi!.getAllPopular(), + builder: (context, AsyncSnapshot?> snapshot) { + if (snapshot.hasData) { + return GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + childAspectRatio: .9, + mainAxisSpacing: 10, + crossAxisSpacing: 10, + ), + itemCount: snapshot.data != null ? snapshot.data!.length : 0, + itemBuilder: (context, index) { + return PopularItem(snapshot.data![index]); + }, + ); + } else if (snapshot.hasError) { + print(snapshot.error); + return const Center( + child: Text('Ocurrió un error'), + ); + } else { + return const LoadingModal(); + } + }, + ), + ); + } +} diff --git a/lib/widgets/popular_item.dart b/lib/widgets/popular_item.dart new file mode 100644 index 0000000..7e8cc2c --- /dev/null +++ b/lib/widgets/popular_item.dart @@ -0,0 +1,18 @@ +import 'package:flutter/material.dart'; +import 'package:pmsna1/models/popular.dart'; + +class PopularItem extends StatelessWidget { + final Popular popular; + + const PopularItem(this.popular, {super.key}); + + @override + Widget build(BuildContext context) { + return FadeInImage( + placeholder: const AssetImage('assets/loading.gif'), + image: NetworkImage( + 'https://image.tmdb.org/t/p/w500/${popular.posterPath!}', + ), + ); + } +} diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index eefcc6d..54b3ff1 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,11 +5,15 @@ import FlutterMacOS import Foundation +import firebase_auth +import firebase_core import path_provider_foundation import shared_preferences_foundation import sqflite func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseAuthPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAuthPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 773eaa6..ff25aa2 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "330d7fcbb72624f5b6d374af8b059b0ef4ba96ba5b8987f874964a1287eb617d" + url: "https://pub.dev" + source: hosted + version: "1.0.18" archive: dependency: transitive description: @@ -129,6 +137,54 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.4" + firebase_auth: + dependency: "direct main" + description: + name: firebase_auth + sha256: "94c229e296a5b9ee5c8cda918e0b320e3a0cc4f6a349cd410c427da347f2a244" + url: "https://pub.dev" + source: hosted + version: "4.3.0" + firebase_auth_platform_interface: + dependency: transitive + description: + name: firebase_auth_platform_interface + sha256: "1217d8aa313b49d58b489aa8879544563abc8793d9612ff20d8df193f202aedc" + url: "https://pub.dev" + source: hosted + version: "6.12.0" + firebase_auth_web: + dependency: transitive + description: + name: firebase_auth_web + sha256: bf7f1a87995a58b0f07dc617806dabd7ff25c64be7fa47b41ab1bb9a485b0062 + url: "https://pub.dev" + source: hosted + version: "5.2.10" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "75f747cafd7cbd6c00b908e3a7aa59fc31593d46ba8165d9ee8a79e69464a394" + url: "https://pub.dev" + source: hosted + version: "2.8.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "5615b30c36f55b2777d0533771deda7e5730e769e5d3cb7fda79e9bed86cfa55" + url: "https://pub.dev" + source: hosted + version: "4.5.3" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "0c1cf1f1022d2245ac117443bb95207952ca770281524d2908e323bc063fb8ff" + url: "https://pub.dev" + source: hosted + version: "2.2.2" flutter: dependency: "direct main" description: flutter @@ -169,7 +225,7 @@ packages: source: sdk version: "0.0.0" http: - dependency: transitive + dependency: "direct main" description: name: http sha256: "6aa2946395183537c8b880962d935877325d6a09a2867c3970c05c0fed6ac482" @@ -224,6 +280,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.6.3" + intl: + dependency: transitive + description: + name: intl + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" + source: hosted + version: "0.17.0" js: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index f31d24f..5698e57 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,6 +20,9 @@ dependencies: concentric_transition: ^1.0.3 lottie: ^2.2.0 shared_preferences: ^2.0.18 + http: ^0.13.5 + firebase_core: ^2.8.0 + firebase_auth: ^4.3.0 dev_dependencies: flutter_test: -- cgit v1.2.3