From a931b2e96982a1bbb63cdfc8711bead4242cbb48 Mon Sep 17 00:00:00 2001 From: Felipe Sales Date: Sun, 29 Jan 2023 08:29:54 -0300 Subject: [PATCH] feat: update all project to Flutter 3.7.0 --- analysis_options.yaml | 3 +- android/app/build.gradle | 4 +- android/app/src/main/AndroidManifest.xml | 1 + android/build.gradle | 4 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../bindings/application_bindings.dart | 10 +-- lib/application/movie_app.dart | 30 +++++++++ lib/application/ui/filmes_app_ui_config.dart | 24 +++---- .../ui/messages/messages_mixin.dart | 22 +++---- lib/application/ui/widgets/movie_card.dart | 4 +- lib/main.dart | 33 ++-------- lib/models/cast_model.dart | 22 +++---- lib/models/genre_model.dart | 22 +++---- lib/models/movie_detail_model.dart | 65 ++++++++++--------- lib/models/movie_model.dart | 27 ++++---- lib/modules/favorites/favorites_page.dart | 8 +-- lib/modules/home/home_controller.dart | 15 ++--- lib/modules/home/home_page.dart | 4 +- lib/modules/login/login_controller.dart | 13 ++-- lib/modules/login/login_page.dart | 2 +- .../movie_detail/movie_detail_controller.dart | 5 +- .../movie_detail/movie_detail_page.dart | 2 +- .../movie_detail_content/movie_cast.dart | 4 +- .../movie_detail_content.dart | 5 +- .../movie_detail_content_credits.dart | 8 ++- .../movie_detail_content_main_cast.dart | 12 ++-- ...e_detail_content_production_companies.dart | 5 +- .../movie_detail_content_title.dart | 6 +- .../widgets/movie_detail_header.dart | 4 +- lib/modules/movies/movies_controller.dart | 43 ++++++------ lib/modules/movies/movies_page.dart | 5 +- lib/modules/movies/widgets/filter_tag.dart | 11 ++-- .../movies/widgets/movies_filters.dart | 2 +- lib/modules/movies/widgets/movies_group.dart | 4 +- lib/modules/movies/widgets/movies_header.dart | 2 +- lib/modules/splash/splash_controller.dart | 4 +- lib/modules/splash/splash_module.dart | 2 +- lib/modules/splash/splash_page.dart | 2 +- .../genres/genres_repository_impl.dart | 15 +++-- .../movies/movies_repository_impl.dart | 27 ++++---- lib/services/genres/genres_service_impl.dart | 4 +- lib/services/login/login_service_impl.dart | 4 +- lib/services/movies/movies_service_impl.dart | 5 +- pubspec.lock | 2 +- pubspec.yaml | 1 + test/utils.dart | 17 +++++ test/widget_test.dart | 36 ++++------ 47 files changed, 282 insertions(+), 270 deletions(-) create mode 100644 lib/application/movie_app.dart create mode 100644 test/utils.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index f16eead..9a1d6f7 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,5 @@ include: package:flutter_lints/flutter.yaml linter: - rules: \ No newline at end of file + rules: + - sort_constructors_first \ No newline at end of file diff --git a/android/app/build.gradle b/android/app/build.gradle index e2c44f9..28e4176 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { - compileSdkVersion 30 + compileSdkVersion 33 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 @@ -45,7 +45,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "br.com.felipecastrosales.app_filmes" minSdkVersion 21 - targetSdkVersion 30 + targetSdkVersion flutter.targetSdkVersion versionCode flutterVersionCode.toInteger() versionName flutterVersionName } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 30ce0a7..f532178 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ android:icon="@mipmap/ic_launcher"> 'Filmes App'; static ThemeData get theme => ThemeData( - scaffoldBackgroundColor: Colors.white, - fontFamily: 'Metropolis', - appBarTheme: const AppBarTheme( - backgroundColor:Colors.white, - iconTheme: IconThemeData(color: Colors.black), - titleTextStyle: TextStyle( - color: Color(0xff222222), - fontSize: 18, - fontWeight: FontWeight.w500, - ), - ), - ); + scaffoldBackgroundColor: Colors.white, + fontFamily: 'Metropolis', + appBarTheme: const AppBarTheme( + backgroundColor: Colors.white, + iconTheme: IconThemeData(color: Colors.black), + titleTextStyle: TextStyle( + color: Color(0xff222222), + fontSize: 18, + fontWeight: FontWeight.w500, + ), + ), + ); } diff --git a/lib/application/ui/messages/messages_mixin.dart b/lib/application/ui/messages/messages_mixin.dart index ec7f137..7e896f3 100644 --- a/lib/application/ui/messages/messages_mixin.dart +++ b/lib/application/ui/messages/messages_mixin.dart @@ -11,7 +11,7 @@ mixin MessagesMixin on GetxController { Get.snackbar( model.title, model.message, - backgroundColor: model.type.color(), + backgroundColor: model.type.color(), ); } }, @@ -20,25 +20,25 @@ mixin MessagesMixin on GetxController { } class MessageModel { - final String title; - final String message; - final MessageType type; - - MessageModel({ + MessageModel.info({ required this.title, required this.message, - required this.type, - }); + }) : type = MessageType.info; MessageModel.error({ required this.title, required this.message, }) : type = MessageType.error; - MessageModel.info({ + MessageModel({ required this.title, required this.message, - }) : type = MessageType.info; + required this.type, + }); + + final String title; + final String message; + final MessageType type; } enum MessageType { @@ -47,7 +47,7 @@ enum MessageType { } extension MessageTypeExtension on MessageType { - Color color() { + Color color() { switch (this) { case MessageType.error: return Colors.red[600] ?? Colors.red; diff --git a/lib/application/ui/widgets/movie_card.dart b/lib/application/ui/widgets/movie_card.dart index abb060e..49b0210 100644 --- a/lib/application/ui/widgets/movie_card.dart +++ b/lib/application/ui/widgets/movie_card.dart @@ -9,10 +9,10 @@ import 'package:app_filmes/models/movie_model.dart'; class MovieCard extends StatelessWidget { MovieCard({ - Key? key, + super.key, required this.movie, required this.favoriteCallback, - }) : super(key: key); + }); final MovieModel movie; final dateFormat = DateFormat('dd/MM/y'); diff --git a/lib/main.dart b/lib/main.dart index f96f0bb..361411d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -2,40 +2,15 @@ import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_remote_config/firebase_remote_config.dart'; -import 'package:get/get.dart'; -import 'application/bindings/application_bindings.dart'; -import 'application/ui/filmes_app_ui_config.dart'; -import 'modules/home/home_module.dart'; -import 'modules/login/login_module.dart'; -import 'modules/movie_detail/movie_detail_module.dart'; -import 'modules/splash/splash_module.dart'; +import 'package:app_filmes/application/movie_app.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); - RemoteConfig.instance.fetchAndActivate(); + FirebaseRemoteConfig.instance.fetchAndActivate(); runApp( - // ignore: prefer_const_constructors - MyApp(), // it's not 'const' because void main is async + // ignore: prefer_const_constructors + MovieApp(), // it's not 'const' because void main is async ); } - -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return GetMaterialApp( - title: FilmesAppUiConfig.title, - debugShowCheckedModeBanner: false, - theme: FilmesAppUiConfig.theme, - initialBinding: ApplicationBindings(), - getPages: [ - ...SplashModule().routers, - ...LoginModule().routers, - ...HomeModule().routers, - ...MovieDetailModule().routers, - ], - ); - } -} diff --git a/lib/models/cast_model.dart b/lib/models/cast_model.dart index 75a646e..3d1a9a7 100644 --- a/lib/models/cast_model.dart +++ b/lib/models/cast_model.dart @@ -1,6 +1,17 @@ import 'dart:convert'; class CastModel { + factory CastModel.fromMap(Map map) { + return CastModel( + name: map['original_name'] ?? '', + image: 'https://image.tmdb.org/t/p/w200${map['profile_path']}', + character: map['character'] ?? '', + ); + } + + factory CastModel.fromJson(String source) => + CastModel.fromMap(json.decode(source)); + CastModel({ required this.name, required this.image, @@ -19,16 +30,5 @@ class CastModel { }; } - factory CastModel.fromMap(Map map) { - return CastModel( - name: map['original_name'] ?? '', - image: 'https://image.tmdb.org/t/p/w200${map['profile_path']}', - character: map['character'] ?? '', - ); - } - String toJson() => json.encode(toMap()); - - factory CastModel.fromJson(String source) => - CastModel.fromMap(json.decode(source)); } diff --git a/lib/models/genre_model.dart b/lib/models/genre_model.dart index ef33b06..e086023 100644 --- a/lib/models/genre_model.dart +++ b/lib/models/genre_model.dart @@ -1,13 +1,23 @@ import 'dart:convert'; class GenreModel { + factory GenreModel.fromMap(Map map) { + return GenreModel( + id: map['id'] ?? 0, + name: map['name'] ?? '', + ); + } + + factory GenreModel.fromJson(String source) => + GenreModel.fromMap(json.decode(source)); + GenreModel({ required this.id, required this.name, }); final int id; - final String name; + final String name; Map toMap() { return { @@ -16,15 +26,5 @@ class GenreModel { }; } - factory GenreModel.fromMap(Map map) { - return GenreModel( - id: map['id'] ?? 0, - name: map['name'] ?? '', - ); - } - String toJson() => json.encode(toMap()); - - factory GenreModel.fromJson(String source) => - GenreModel.fromMap(json.decode(source)); } diff --git a/lib/models/movie_detail_model.dart b/lib/models/movie_detail_model.dart index 048ce94..173ae15 100644 --- a/lib/models/movie_detail_model.dart +++ b/lib/models/movie_detail_model.dart @@ -4,16 +4,6 @@ import 'package:app_filmes/models/genre_model.dart'; import 'cast_model.dart'; class MovieDetailModel { - final String title; - final double stars; - final List genres; - final List urlImages; - final DateTime releaseDate; - final String overview; - final List productionCompanies; - final String originalLanguage; - final List cast; - MovieDetailModel({ required this.title, required this.stars, @@ -26,20 +16,6 @@ class MovieDetailModel { required this.cast, }); - Map toMap() { - return { - 'title': title, - 'vote_average': stars, - 'genres': genres.map((x) => x.toMap()).toList(), - 'urlImages': urlImages, - 'release_date': releaseDate.millisecondsSinceEpoch, - 'overview': overview, - 'production_companies': productionCompanies, - 'original_language': originalLanguage, - 'cast': cast.map((x) => x.toMap()).toList(), - }; - } - factory MovieDetailModel.fromMap(Map map) { var urlImagesPoster = map['images']['posters']; var urlImages = urlImagesPoster @@ -51,10 +27,12 @@ class MovieDetailModel { return MovieDetailModel( title: map['title'] ?? '', stars: map['vote_average'] ?? 0.0, - genres: List.from(map['genres']?.map( - (x) => GenreModel.fromMap(x), - ) ?? - const []), + genres: List.from( + map['genres']?.map( + (genre) => GenreModel.fromMap(genre), + ) ?? + const [], + ), urlImages: urlImages, releaseDate: DateTime.parse(map['release_date']), overview: map['overview'] ?? '', @@ -63,13 +41,38 @@ class MovieDetailModel { ).map((production) => production['name']).toList(), originalLanguage: map['original_language'] ?? '', cast: List.from( - map['credits']['cast']?.map((x) => CastModel.fromMap(x)) ?? const [], + map['credits']['cast']?.map((credit) => CastModel.fromMap(credit)) ?? + const [], ), ); } - String toJson() => json.encode(toMap()); - factory MovieDetailModel.fromJson(String source) => MovieDetailModel.fromMap(json.decode(source)); + + final String title; + final double stars; + final List genres; + final List urlImages; + final DateTime releaseDate; + final String overview; + final List productionCompanies; + final String originalLanguage; + final List cast; + + Map toMap() { + return { + 'title': title, + 'vote_average': stars, + 'genres': genres.map((genre) => genre.toMap()).toList(), + 'urlImages': urlImages, + 'release_date': releaseDate.millisecondsSinceEpoch, + 'overview': overview, + 'production_companies': productionCompanies, + 'original_language': originalLanguage, + 'cast': cast.map((item) => item.toMap()).toList(), + }; + } + + String toJson() => json.encode(toMap()); } diff --git a/lib/models/movie_model.dart b/lib/models/movie_model.dart index 46d5c16..492569e 100644 --- a/lib/models/movie_model.dart +++ b/lib/models/movie_model.dart @@ -1,6 +1,20 @@ import 'dart:convert'; class MovieModel { + factory MovieModel.fromMap(Map map) { + return MovieModel( + id: map['id'] ?? 0, + title: map['title'] ?? '', + releaseDate: map['release_date'] ?? '', + posterPath: map['poster_path'], + genres: List.from(map['genre_ids'] ?? const []), + favorite: map['favorite'] ?? false, + ); + } + + factory MovieModel.fromJson(String source) => + MovieModel.fromMap(json.decode(source)); + MovieModel({ required this.id, required this.title, @@ -28,21 +42,8 @@ class MovieModel { }; } - factory MovieModel.fromMap(Map map) { - return MovieModel( - id: map['id'] ?? 0, - title: map['title'] ?? '', - releaseDate: map['release_date'] ?? '', - posterPath: map['poster_path'], - genres: List.from(map['genre_ids'] ?? const []), - favorite: map['favorite'] ?? false, - ); - } - String toJson() => json.encode(toMap()); - factory MovieModel.fromJson(String source) => MovieModel.fromMap(json.decode(source)); - MovieModel copyWith({ int? id, String? title, diff --git a/lib/modules/favorites/favorites_page.dart b/lib/modules/favorites/favorites_page.dart index 801568f..cdebd30 100644 --- a/lib/modules/favorites/favorites_page.dart +++ b/lib/modules/favorites/favorites_page.dart @@ -6,7 +6,7 @@ import 'package:app_filmes/application/ui/widgets/movie_card.dart'; import 'favorites_controller.dart'; class FavoritesPage extends GetView { - const FavoritesPage({Key? key}) : super(key: key); + const FavoritesPage({super.key}); @override Widget build(BuildContext context) { @@ -23,10 +23,10 @@ class FavoritesPage extends GetView { alignment: WrapAlignment.spaceAround, children: controller.movies .map( - (m) => MovieCard( - movie: m, + (movie) => MovieCard( + movie: movie, favoriteCallback: () => - controller.removeFavorite(movie: m), + controller.removeFavorite(movie: movie), ), ) .toList(), diff --git a/lib/modules/home/home_controller.dart b/lib/modules/home/home_controller.dart index 0a88841..3aef706 100644 --- a/lib/modules/home/home_controller.dart +++ b/lib/modules/home/home_controller.dart @@ -3,16 +3,15 @@ import 'package:get/get.dart'; import 'package:app_filmes/services/login/login_service.dart'; class HomeController extends GetxController { - // ignore: constant_identifier_names - static const NAVIGATOR_KEY = 1; - // ignore: constant_identifier_names - static const INDEX_PAGE_EXIT = 2; - - final LoginService _loginService; HomeController({ required LoginService loginService, }) : _loginService = loginService; + static const navigatorKey = 1; + static const indexPageExit = 2; + + final LoginService _loginService; + final _pages = [ '/movies', '/favorites', @@ -24,12 +23,12 @@ class HomeController extends GetxController { void goToPage(int page) { _pageIndex(page); - if (page == INDEX_PAGE_EXIT) { + if (page == indexPageExit) { _loginService.logout(); } else { Get.offNamed( _pages[page], - id: NAVIGATOR_KEY, + id: navigatorKey, ); } } diff --git a/lib/modules/home/home_page.dart b/lib/modules/home/home_page.dart index d49fe18..1f7b2b0 100644 --- a/lib/modules/home/home_page.dart +++ b/lib/modules/home/home_page.dart @@ -11,7 +11,7 @@ import 'package:app_filmes/modules/movies/movies_page.dart'; import 'home_controller.dart'; class HomePage extends GetView { - const HomePage({Key? key}) : super(key: key); + const HomePage({super.key}); @override Widget build(BuildContext context) { @@ -40,7 +40,7 @@ class HomePage extends GetView { }), body: Navigator( initialRoute: '/movies', - key: Get.nestedKey(HomeController.NAVIGATOR_KEY), + key: Get.nestedKey(HomeController.navigatorKey), onGenerateRoute: (settings) { if (settings.name == '/movies') { return GetPageRoute( diff --git a/lib/modules/login/login_controller.dart b/lib/modules/login/login_controller.dart index f34f6f8..8647871 100644 --- a/lib/modules/login/login_controller.dart +++ b/lib/modules/login/login_controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:app_filmes/services/login/login_service.dart'; @@ -5,14 +6,14 @@ import 'package:app_filmes/application/ui/loader/loader_mixin.dart'; import 'package:app_filmes/application/ui/messages/messages_mixin.dart'; class LoginController extends GetxController with LoaderMixin, MessagesMixin { - final LoginService _loginService; - final loading = false.obs; - final message = Rxn(); - LoginController({ required LoginService loginService, }) : _loginService = loginService; + final LoginService _loginService; + final loading = false.obs; + final message = Rxn(); + @override void onInit() { super.onInit(); @@ -32,8 +33,8 @@ class LoginController extends GetxController with LoaderMixin, MessagesMixin { ), ); } catch (e, s) { - print(e); - print(s); + debugPrint(e.toString()); + debugPrint(s.toString()); loading(false); message( MessageModel.error( diff --git a/lib/modules/login/login_page.dart b/lib/modules/login/login_page.dart index 4122007..3f82081 100644 --- a/lib/modules/login/login_page.dart +++ b/lib/modules/login/login_page.dart @@ -6,7 +6,7 @@ import 'package:get/get.dart'; import 'login_controller.dart'; class LoginPage extends GetView { - const LoginPage({Key? key}) : super(key: key); + const LoginPage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/modules/movie_detail/movie_detail_controller.dart b/lib/modules/movie_detail/movie_detail_controller.dart index a39a155..3551885 100644 --- a/lib/modules/movie_detail/movie_detail_controller.dart +++ b/lib/modules/movie_detail/movie_detail_controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:app_filmes/application/ui/loader/loader_mixin.dart'; @@ -33,8 +34,8 @@ class MovieDetailController extends GetxController movie.value = movieDetailData; loading(false); } catch (e, s) { - print(e); - print(s); + debugPrint(e.toString()); + debugPrint(s.toString()); loading(false); MessageModel.error( title: 'Erro', diff --git a/lib/modules/movie_detail/movie_detail_page.dart b/lib/modules/movie_detail/movie_detail_page.dart index b039abc..3234e51 100644 --- a/lib/modules/movie_detail/movie_detail_page.dart +++ b/lib/modules/movie_detail/movie_detail_page.dart @@ -7,7 +7,7 @@ import 'widgets/movie_detail_content/movie_detail_content.dart'; import 'widgets/movie_detail_header.dart'; class MovieDetailPage extends GetView { - const MovieDetailPage({Key? key}) : super(key: key); + const MovieDetailPage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_cast.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_cast.dart index 1f4f885..e5cf1d0 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_cast.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_cast.dart @@ -5,9 +5,9 @@ import 'package:app_filmes/models/cast_model.dart'; class MovieCast extends StatelessWidget { const MovieCast({ - Key? key, + super.key, required this.cast, - }) : super(key: key); + }); final CastModel? cast; @override diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content.dart index f803fe4..b31c821 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content.dart @@ -8,9 +8,10 @@ import 'movie_detail_content_title.dart'; class MovieDetailContent extends StatelessWidget { const MovieDetailContent({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); + final MovieDetailModel? movie; @override diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_credits.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_credits.dart index 91a4f45..1a3b77f 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_credits.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_credits.dart @@ -4,9 +4,10 @@ import 'package:app_filmes/models/movie_detail_model.dart'; class MovieDetailContentCredits extends StatelessWidget { const MovieDetailContentCredits({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); + final MovieDetailModel? movie; @override @@ -18,7 +19,8 @@ class MovieDetailContentCredits extends StatelessWidget { child: Text( movie?.overview ?? '', style: const TextStyle( - fontSize: 14, height: 1.3, + fontSize: 14, + height: 1.3, ), ), ), diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_main_cast.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_main_cast.dart index 9aa6fee..164dd5b 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_main_cast.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_main_cast.dart @@ -8,9 +8,9 @@ import 'movie_cast.dart'; class MovieDetailContentMainCast extends StatelessWidget { MovieDetailContentMainCast({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); final MovieDetailModel? movie; final showPanel = false.obs; @@ -47,11 +47,7 @@ class MovieDetailContentMainCast extends StatelessWidget { child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: movie?.cast - .map( - (cast) => MovieCast( - cast: cast, - ), - ) + .map((cast) => MovieCast(cast: cast)) .toList() ?? const [], ), @@ -60,7 +56,7 @@ class MovieDetailContentMainCast extends StatelessWidget { ], ); }), - const SizedBox(height: 16), + const SizedBox(height: 16), ], ); } diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_production_companies.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_production_companies.dart index 253660e..ac503f1 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_production_companies.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_production_companies.dart @@ -4,9 +4,10 @@ import 'package:app_filmes/models/movie_detail_model.dart'; class MovieDetailContentProductionCompanies extends StatelessWidget { const MovieDetailContentProductionCompanies({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); + final MovieDetailModel? movie; @override diff --git a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_title.dart b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_title.dart index b521df2..a5fd5f2 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_title.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_content/movie_detail_content_title.dart @@ -7,10 +7,12 @@ import 'package:app_filmes/application/ui/theme_extension.dart'; class MovieDetailContentTitle extends StatelessWidget { const MovieDetailContentTitle({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); + final MovieDetailModel? movie; + @override Widget build(BuildContext context) { return Padding( diff --git a/lib/modules/movie_detail/widgets/movie_detail_header.dart b/lib/modules/movie_detail/widgets/movie_detail_header.dart index 3d33e15..f3679f6 100644 --- a/lib/modules/movie_detail/widgets/movie_detail_header.dart +++ b/lib/modules/movie_detail/widgets/movie_detail_header.dart @@ -7,9 +7,9 @@ import 'package:app_filmes/models/movie_detail_model.dart'; class MovieDetailHeader extends GetView { const MovieDetailHeader({ - Key? key, + super.key, required this.movie, - }) : super(key: key); + }); final MovieDetailModel? movie; diff --git a/lib/modules/movies/movies_controller.dart b/lib/modules/movies/movies_controller.dart index 0674465..0cce88b 100644 --- a/lib/modules/movies/movies_controller.dart +++ b/lib/modules/movies/movies_controller.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:app_filmes/application/auth/auth_service.dart'; @@ -8,6 +9,14 @@ import 'package:app_filmes/services/genres/genres_service.dart'; import 'package:app_filmes/services/movies/movies_service.dart'; class MoviesController extends GetxController with MessagesMixin { + MoviesController({ + required GenresService genresService, + required MoviesService moviesService, + required AuthService authService, + }) : _genresService = genresService, + _moviesService = moviesService, + _authService = authService; + final GenresService _genresService; final MoviesService _moviesService; final AuthService _authService; @@ -22,14 +31,6 @@ class MoviesController extends GetxController with MessagesMixin { var _topRatedMoviesOriginal = []; final genreSelected = Rxn(); - MoviesController({ - required GenresService genresService, - required MoviesService moviesService, - required AuthService authService, - }) : _genresService = genresService, - _moviesService = moviesService, - _authService = authService; - @override void onInit() { super.onInit(); @@ -44,8 +45,8 @@ class MoviesController extends GetxController with MessagesMixin { genres.assignAll(genresData); await getMovies(); } catch (e, s) { - print(e); - print(s); + debugPrint(e.toString()); + debugPrint(s.toString()); _message( MessageModel.error( title: 'Erro', @@ -61,11 +62,11 @@ class MoviesController extends GetxController with MessagesMixin { var topRatedMoviesData = await _moviesService.getTopRatedMovies(); final favorites = await getFavorites(); - popularMoviesData = popularMoviesData.map((m) { - if (favorites.containsKey(m.id)) { - return m.copyWith(favorite: true); + popularMoviesData = popularMoviesData.map((movie) { + if (favorites.containsKey(movie.id)) { + return movie.copyWith(favorite: true); } else { - return m.copyWith(favorite: false); + return movie.copyWith(favorite: false); } }).toList(); @@ -82,8 +83,8 @@ class MoviesController extends GetxController with MessagesMixin { topRatedMovies.assignAll(topRatedMoviesData); _topRatedMoviesOriginal = topRatedMoviesData; } catch (e, s) { - print(e); - print(s); + debugPrint(e.toString()); + debugPrint(s.toString()); _message( MessageModel.error( title: 'Erro', @@ -97,16 +98,12 @@ class MoviesController extends GetxController with MessagesMixin { if (title.isNotEmpty) { var newPopularMovies = _popularMoviesOriginal.where( (movie) { - return movie.title.toLowerCase().contains( - title.toLowerCase(), - ); + return movie.title.toLowerCase().contains(title.toLowerCase()); }, ); var newTopRatedMovies = _topRatedMoviesOriginal.where( (movie) { - return movie.title.toLowerCase().contains( - title.toLowerCase(), - ); + return movie.title.toLowerCase().contains(title.toLowerCase()); }, ); popularMovies.assignAll(newPopularMovies); @@ -157,7 +154,7 @@ class MoviesController extends GetxController with MessagesMixin { if (user != null) { final favorities = await _moviesService.getFavoritiesMovies(user.uid); return { - for (var fav in favorities) fav.id: fav, + for (var favorite in favorities) favorite.id: favorite, }; } return {}; diff --git a/lib/modules/movies/movies_page.dart b/lib/modules/movies/movies_page.dart index 3a84249..273b3bc 100644 --- a/lib/modules/movies/movies_page.dart +++ b/lib/modules/movies/movies_page.dart @@ -6,8 +6,9 @@ import 'movies_controller.dart'; import 'widgets/movies_filters.dart'; import 'widgets/movies_group.dart'; import 'widgets/movies_header.dart'; + class MoviesPage extends GetView { - const MoviesPage({Key? key}) : super(key: key); + const MoviesPage({super.key}); @override Widget build(BuildContext context) { @@ -29,4 +30,4 @@ class MoviesPage extends GetView { ), ); } -} \ No newline at end of file +} diff --git a/lib/modules/movies/widgets/filter_tag.dart b/lib/modules/movies/widgets/filter_tag.dart index ac1cf0f..8ffc4f4 100644 --- a/lib/modules/movies/widgets/filter_tag.dart +++ b/lib/modules/movies/widgets/filter_tag.dart @@ -4,16 +4,15 @@ import 'package:app_filmes/models/genre_model.dart'; import 'package:app_filmes/application/ui/theme_extension.dart'; class FilterTag extends StatelessWidget { - final GenreModel model; - final bool selected; - final VoidCallback onPressed; - const FilterTag({ - Key? key, + super.key, required this.model, this.selected = false, required this.onPressed, - }) : super(key: key); + }); + final GenreModel model; + final bool selected; + final VoidCallback onPressed; @override Widget build(BuildContext context) { diff --git a/lib/modules/movies/widgets/movies_filters.dart b/lib/modules/movies/widgets/movies_filters.dart index 883cb89..d6f93ae 100644 --- a/lib/modules/movies/widgets/movies_filters.dart +++ b/lib/modules/movies/widgets/movies_filters.dart @@ -6,7 +6,7 @@ import 'package:app_filmes/modules/movies/movies_controller.dart'; import 'filter_tag.dart'; class MoviesFilters extends GetView { - const MoviesFilters({Key? key}) : super(key: key); + const MoviesFilters({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/modules/movies/widgets/movies_group.dart b/lib/modules/movies/widgets/movies_group.dart index b944c01..930dc62 100644 --- a/lib/modules/movies/widgets/movies_group.dart +++ b/lib/modules/movies/widgets/movies_group.dart @@ -8,10 +8,10 @@ import 'package:app_filmes/modules/movies/movies_controller.dart'; class MoviesGroup extends GetView { const MoviesGroup({ - Key? key, + super.key, required this.title, required this.movies, - }) : super(key: key); + }); final String title; final List movies; diff --git a/lib/modules/movies/widgets/movies_header.dart b/lib/modules/movies/widgets/movies_header.dart index 622db6a..2d1c4ee 100644 --- a/lib/modules/movies/widgets/movies_header.dart +++ b/lib/modules/movies/widgets/movies_header.dart @@ -5,7 +5,7 @@ import 'package:get/get.dart'; import 'package:app_filmes/modules/movies/movies_controller.dart'; class MoviesHeader extends GetView { - const MoviesHeader({Key? key}) : super(key: key); + const MoviesHeader({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/modules/splash/splash_controller.dart b/lib/modules/splash/splash_controller.dart index 25ee00a..3d48f96 100644 --- a/lib/modules/splash/splash_controller.dart +++ b/lib/modules/splash/splash_controller.dart @@ -1,5 +1,3 @@ import 'package:get/get.dart'; -class SplashController extends GetxController { - -} +class SplashController extends GetxController {} diff --git a/lib/modules/splash/splash_module.dart b/lib/modules/splash/splash_module.dart index 7a4f351..94d2f23 100644 --- a/lib/modules/splash/splash_module.dart +++ b/lib/modules/splash/splash_module.dart @@ -5,7 +5,7 @@ import 'splash_bindings.dart'; import 'splash_page.dart'; class SplashModule implements Module { - @override + @override List routers = [ GetPage( name: '/', diff --git a/lib/modules/splash/splash_page.dart b/lib/modules/splash/splash_page.dart index a1b1272..09f2463 100644 --- a/lib/modules/splash/splash_page.dart +++ b/lib/modules/splash/splash_page.dart @@ -5,7 +5,7 @@ import 'package:get/get.dart'; import 'splash_controller.dart'; class SplashPage extends GetView { - const SplashPage({Key? key}) : super(key: key); + const SplashPage({super.key}); @override Widget build(BuildContext context) { diff --git a/lib/repositories/genres/genres_repository_impl.dart b/lib/repositories/genres/genres_repository_impl.dart index 8e3617e..f6027ee 100644 --- a/lib/repositories/genres/genres_repository_impl.dart +++ b/lib/repositories/genres/genres_repository_impl.dart @@ -1,38 +1,39 @@ +import 'package:flutter/material.dart'; + import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:app_filmes/application/rest_client/rest_client.dart'; import 'package:app_filmes/models/genre_model.dart'; + import 'genres_repository.dart'; class GenresRepositoryImpl implements GenresRepository { - final RestClient _restClient; - GenresRepositoryImpl({ required RestClient restClient, }) : _restClient = restClient; + final RestClient _restClient; + @override Future> getGenres() async { final result = await _restClient.get>( '/genre/movie/list', query: { - 'api_key': RemoteConfig.instance.getString('api_token'), + 'api_key': FirebaseRemoteConfig.instance.getString('api_token'), 'language': 'pt-br', }, decoder: (data) { final resultData = data['genres']; if (resultData != null) { return resultData - .map( - (genre) => GenreModel.fromMap(genre), - ) + .map((genre) => GenreModel.fromMap(genre)) .toList(); } return []; }, ); if (result.hasError) { - print('Status: ${result.statusText}'); + debugPrint('Status: ${result.statusText}'); throw Exception('Erro ao buscar Categorias'); } return result.body ?? []; diff --git a/lib/repositories/movies/movies_repository_impl.dart b/lib/repositories/movies/movies_repository_impl.dart index e6d208f..9da4284 100644 --- a/lib/repositories/movies/movies_repository_impl.dart +++ b/lib/repositories/movies/movies_repository_impl.dart @@ -4,6 +4,7 @@ import 'package:firebase_remote_config/firebase_remote_config.dart'; import 'package:app_filmes/application/rest_client/rest_client.dart'; import 'package:app_filmes/models/movie_detail_model.dart'; import 'package:app_filmes/models/movie_model.dart'; +import 'package:flutter/material.dart'; import 'movies_repository.dart'; class MoviesRepositoryImpl implements MoviesRepository { @@ -18,7 +19,7 @@ class MoviesRepositoryImpl implements MoviesRepository { final result = await _restClient.get>( '/movie/popular', query: { - 'api_key': RemoteConfig.instance.getString('api_token'), + 'api_key': FirebaseRemoteConfig.instance.getString('api_token'), 'language': 'pt-br', 'page': '1', }, @@ -26,9 +27,7 @@ class MoviesRepositoryImpl implements MoviesRepository { final results = data['results']; if (results != null) { return results - .map( - (date) => MovieModel.fromMap(date), - ) + .map((result) => MovieModel.fromMap(result)) .toList(); } return []; @@ -36,7 +35,7 @@ class MoviesRepositoryImpl implements MoviesRepository { ); if (result.hasError) { - print('Erro ao buscar popular movies [${result.statusText}]'); + debugPrint('Erro ao buscar popular movies [${result.statusText}]'); throw Exception('Erro ao buscar filmes populares'); } return result.body ?? []; @@ -47,7 +46,7 @@ class MoviesRepositoryImpl implements MoviesRepository { final result = await _restClient.get>( '/movie/top_rated', query: { - 'api_key': RemoteConfig.instance.getString('api_token'), + 'api_key': FirebaseRemoteConfig.instance.getString('api_token'), 'language': 'pt-br', 'page': '1', }, @@ -64,7 +63,7 @@ class MoviesRepositoryImpl implements MoviesRepository { }, ); if (result.hasError) { - print('Erro ao buscar top_rated movies ${result.statusText}'); + debugPrint('Erro ao buscar top_rated movies ${result.statusText}'); throw Exception('Erro ao buscar filmes tops'); } return result.body ?? []; @@ -75,7 +74,7 @@ class MoviesRepositoryImpl implements MoviesRepository { final result = await _restClient.get( '/movie/$id', query: { - 'api_key': RemoteConfig.instance.getString('api_token'), + 'api_key': FirebaseRemoteConfig.instance.getString('api_token'), 'language': 'pt-br', 'append_to_response': 'images,credits', 'include_image_language': 'en,pt-br', @@ -85,7 +84,7 @@ class MoviesRepositoryImpl implements MoviesRepository { }, ); if (result.hasError) { - print('Erro ao buscar detalhes dos movies ${result.statusText}'); + debugPrint('Erro ao buscar detalhes dos movies ${result.statusText}'); throw Exception('Erro ao buscar detalhes dos filmes'); } return result.body; @@ -99,9 +98,7 @@ class MoviesRepositoryImpl implements MoviesRepository { .doc(userId) .collection('movies'); if (movie.favorite) { - favoriteCollection.add( - movie.toMap(), - ); + favoriteCollection.add(movie.toMap()); } else { var favoriteData = await favoriteCollection .where('id', isEqualTo: movie.id) @@ -110,7 +107,7 @@ class MoviesRepositoryImpl implements MoviesRepository { favoriteData.docs.first.reference.delete(); } } catch (e) { - print('Erro ao favoritar um filme'); + debugPrint('Erro ao favoritar um filme'); rethrow; } } @@ -125,9 +122,7 @@ class MoviesRepositoryImpl implements MoviesRepository { final listFavorities = []; for (var movie in favoritiesMovies.docs) { listFavorities.add( - MovieModel.fromMap( - movie.data(), - ), + MovieModel.fromMap(movie.data()), ); } return listFavorities; diff --git a/lib/services/genres/genres_service_impl.dart b/lib/services/genres/genres_service_impl.dart index fb8e8fd..0976f80 100644 --- a/lib/services/genres/genres_service_impl.dart +++ b/lib/services/genres/genres_service_impl.dart @@ -3,12 +3,12 @@ import 'package:app_filmes/repositories/genres/genres_repository.dart'; import 'genres_service.dart'; class GenresServiceImpl implements GenresService { - final GenresRepository _genreRepository; - GenresServiceImpl({ required GenresRepository genreRepository, }) : _genreRepository = genreRepository; + final GenresRepository _genreRepository; + @override Future> getGenres() => _genreRepository.getGenres(); } diff --git a/lib/services/login/login_service_impl.dart b/lib/services/login/login_service_impl.dart index d937341..1152148 100644 --- a/lib/services/login/login_service_impl.dart +++ b/lib/services/login/login_service_impl.dart @@ -4,12 +4,12 @@ import 'package:app_filmes/repositories/login/login_repository.dart'; import 'login_service.dart'; class LoginServiceImpl implements LoginService { - final LoginRepository _loginRepository; - LoginServiceImpl({ required LoginRepository loginRepository, }) : _loginRepository = loginRepository; + final LoginRepository _loginRepository; + @override Future login() => _loginRepository.login(); diff --git a/lib/services/movies/movies_service_impl.dart b/lib/services/movies/movies_service_impl.dart index 6331816..6be69b2 100644 --- a/lib/services/movies/movies_service_impl.dart +++ b/lib/services/movies/movies_service_impl.dart @@ -25,10 +25,7 @@ class MoviesServiceImpl implements MoviesService { @override Future addOrRemoveFavorite(String userId, MovieModel movie) => - _moviesRepository.addOrRemoveFavorite( - userId, - movie, - ); + _moviesRepository.addOrRemoveFavorite(userId, movie); @override Future> getFavoritiesMovies(String userId) => diff --git a/pubspec.lock b/pubspec.lock index e23368b..0dd76d5 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -122,7 +122,7 @@ packages: source: hosted version: "2.4.1" firebase_core_platform_interface: - dependency: transitive + dependency: "direct main" description: name: firebase_core_platform_interface sha256: "5fab93f5b354648efa62e7cc829c90efb68c8796eecf87e0888cae2d5f3accd4" diff --git a/pubspec.yaml b/pubspec.yaml index 33af317..2d59f5e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -12,6 +12,7 @@ dependencies: cupertino_icons: ^1.0.5 firebase_auth: ^4.2.4 firebase_core: ^2.4.1 + firebase_core_platform_interface: ^4.5.2 firebase_remote_config: ^3.0.9 flutter: sdk: flutter diff --git a/test/utils.dart b/test/utils.dart new file mode 100644 index 0000000..8bec8ab --- /dev/null +++ b/test/utils.dart @@ -0,0 +1,17 @@ +import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +typedef Callback = void Function(MethodCall call); + +void setupFirebaseAuthMocks([Callback? customHandlers]) { + TestWidgetsFlutterBinding.ensureInitialized(); + + setupFirebaseCoreMocks(); +} + +Future neverEndingFuture() async { + while (true) { + await Future.delayed(const Duration(minutes: 5)); + } +} diff --git a/test/widget_test.dart b/test/widget_test.dart index d57ba96..62e45f8 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,30 +1,22 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; +import 'package:firebase_core/firebase_core.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:app_filmes/main.dart'; +import 'package:app_filmes/application/movie_app.dart'; -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); +import 'utils.dart'; - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); +void main() { + setupFirebaseAuthMocks(); - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); + setUpAll(() async { + await Firebase.initializeApp(); + }); - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); + testWidgets('Should renders MovieApp', (tester) async { + await tester.pumpWidget(const MovieApp()); + expect( + find.byType(MovieApp), + findsOneWidget, + ); }); }