├── .gitignore
├── README.md
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── ic_launcher_icon-playstore.png
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── ruben
│ │ │ │ └── fun_box
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable
│ │ │ ├── icon_splash.png
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ ├── ic_launcher_icon.xml
│ │ │ └── ic_launcher_icon_round.xml
│ │ │ ├── mipmap-hdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_icon.png
│ │ │ ├── ic_launcher_icon_foreground.png
│ │ │ └── ic_launcher_icon_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_icon.png
│ │ │ ├── ic_launcher_icon_foreground.png
│ │ │ └── ic_launcher_icon_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_icon.png
│ │ │ ├── ic_launcher_icon_foreground.png
│ │ │ └── ic_launcher_icon_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_icon.png
│ │ │ ├── ic_launcher_icon_foreground.png
│ │ │ └── ic_launcher_icon_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ ├── ic_launcher.png
│ │ │ ├── ic_launcher_icon.png
│ │ │ ├── ic_launcher_icon_foreground.png
│ │ │ └── ic_launcher_icon_round.png
│ │ │ └── values
│ │ │ ├── ic_launcher_icon_background.xml
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── fun_box_android.iml
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── settings.gradle
└── settings_aar.gradle
├── data
├── .gitignore
├── .metadata
├── README.md
├── data.iml
├── data_android.iml
├── lib
│ ├── di
│ │ ├── di.config.dart
│ │ └── di.dart
│ └── repository
│ │ ├── cast_repository_impl.dart
│ │ ├── config_repository_impl.dart
│ │ ├── details_repository_impl.dart
│ │ ├── filter_repository_impl.dart
│ │ ├── movies_repository_impl.dart
│ │ ├── person_repository_impl.dart
│ │ ├── search_repository_impl.dart
│ │ ├── shows_repository_impl.dart
│ │ ├── trending_repository_impl.dart
│ │ └── video_repository_impl.dart
└── pubspec.yaml
├── domain
├── .gitignore
├── .metadata
├── README.md
├── domain.iml
├── domain_android.iml
├── lib
│ ├── di
│ │ ├── di.config.dart
│ │ └── di.dart
│ ├── model
│ │ ├── cast_record.dart
│ │ ├── config_record.dart
│ │ ├── movie_details_record.dart
│ │ ├── movie_show_genres_record.dart
│ │ ├── movies_shows_record.dart
│ │ ├── person_credits_record.dart
│ │ ├── person_info_record.dart
│ │ ├── show_details_record.dart
│ │ ├── trailer_record.dart
│ │ └── trending_people_record.dart
│ ├── repository
│ │ ├── cast_repository.dart
│ │ ├── config_repository.dart
│ │ ├── details_repository.dart
│ │ ├── filter_repository.dart
│ │ ├── movies_repository.dart
│ │ ├── person_repository.dart
│ │ ├── search_repository.dart
│ │ ├── shows_repository.dart
│ │ ├── trending_repository.dart
│ │ └── video_repository.dart
│ └── usecase
│ │ ├── cast
│ │ ├── movie_cast_use_case.dart
│ │ └── show_cast_use_case.dart
│ │ ├── details
│ │ ├── movie_details_use_case.dart
│ │ └── show_details_use_case.dart
│ │ ├── filter
│ │ ├── movie_filter_use_case.dart
│ │ └── show_filter_use_case.dart
│ │ ├── get_config_use_case.dart
│ │ ├── movies
│ │ ├── current_playing_movies_use_case.dart
│ │ ├── latest_movies_use_case.dart
│ │ ├── movies_by_genres_use_case.dart
│ │ ├── popular_movies_use_case.dart
│ │ ├── top_rated_movies_use_case.dart
│ │ └── upcoming_movies_use_case.dart
│ │ ├── person
│ │ ├── person_credits_use_case.dart
│ │ └── person_info_use_case.dart
│ │ ├── search_movies_shows_use_case.dart
│ │ ├── shows
│ │ ├── airing_today_shows_use_case.dart
│ │ ├── current_playing_shows_use_case.dart
│ │ ├── latest_shows_use_case.dart
│ │ ├── popular_shows_use_case.dart
│ │ ├── shows_by_genres_use_case.dart
│ │ └── top_rated_shows_use_case.dart
│ │ ├── trending
│ │ ├── trending_movies_use_case.dart
│ │ ├── trending_people_use_case.dart
│ │ └── trending_shows_use_case.dart
│ │ └── video
│ │ ├── movie_trailer_use_case.dart
│ │ └── show_trailer_use_case.dart
└── pubspec.yaml
├── fonts
├── ironclad.ttf
└── metropolis.otf
├── fun_box.iml
├── images
└── error_image.png
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
└── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ ├── AppIcon.appiconset
│ │ ├── Contents.json
│ │ ├── Icon-App-1024x1024@1x.png
│ │ ├── Icon-App-20x20@1x.png
│ │ ├── Icon-App-20x20@2x.png
│ │ ├── Icon-App-20x20@3x.png
│ │ ├── Icon-App-29x29@1x.png
│ │ ├── Icon-App-29x29@2x.png
│ │ ├── Icon-App-29x29@3x.png
│ │ ├── Icon-App-40x40@1x.png
│ │ ├── Icon-App-40x40@2x.png
│ │ ├── Icon-App-40x40@3x.png
│ │ ├── Icon-App-60x60@2x.png
│ │ ├── Icon-App-60x60@3x.png
│ │ ├── Icon-App-76x76@1x.png
│ │ ├── Icon-App-76x76@2x.png
│ │ └── Icon-App-83.5x83.5@2x.png
│ └── LaunchImage.imageset
│ │ ├── Contents.json
│ │ ├── LaunchImage.png
│ │ ├── LaunchImage@2x.png
│ │ ├── LaunchImage@3x.png
│ │ └── README.md
│ ├── Base.lproj
│ ├── LaunchScreen.storyboard
│ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
├── lib
├── bloc
│ ├── all
│ │ ├── trending_bloc.dart
│ │ ├── trending_event.dart
│ │ └── trending_state.dart
│ ├── cast
│ │ ├── movie_show_cast_bloc.dart
│ │ ├── movie_show_cast_event.dart
│ │ └── movie_show_cast_state.dart
│ ├── details
│ │ ├── movie_show_details_bloc.dart
│ │ ├── movie_show_details_event.dart
│ │ └── movie_show_details_state.dart
│ ├── filter
│ │ ├── movies_shows_filter_bloc.dart
│ │ ├── movies_shows_filter_event.dart
│ │ └── movies_shows_filter_state.dart
│ ├── movieshow
│ │ ├── movies_shows_bloc.dart
│ │ ├── movies_shows_event.dart
│ │ └── movies_shows_state.dart
│ ├── person
│ │ ├── person_details_bloc.dart
│ │ ├── person_details_event.dart
│ │ └── person_details_state.dart
│ ├── search
│ │ ├── movies_shows_search_bloc.dart
│ │ ├── movies_shows_search_event.dart
│ │ └── movies_shows_search_state.dart
│ └── video
│ │ ├── movie_show_trailer_bloc.dart
│ │ ├── movie_show_trailer_event.dart
│ │ └── movie_show_trailer_state.dart
├── config
│ ├── configurations.dart
│ └── default_config.dart
├── di
│ ├── di.config.dart
│ └── di.dart
├── main.dart
├── presentation
│ ├── common
│ │ ├── common_display_tiles.dart
│ │ ├── common_error_ui.dart
│ │ ├── common_people_tiles.dart
│ │ ├── common_search_bar.dart
│ │ └── common_widgets.dart
│ ├── details
│ │ ├── movie_show_details.dart
│ │ └── widgets
│ │ │ ├── movie_show_cast.dart
│ │ │ └── movie_show_info.dart
│ ├── filter
│ │ ├── filters.dart
│ │ └── movies_shows_filters.dart
│ ├── home
│ │ ├── home.dart
│ │ └── widgets
│ │ │ ├── trending_movies.dart
│ │ │ ├── trending_people.dart
│ │ │ └── trending_shows.dart
│ ├── movieshow
│ │ ├── movies_shows.dart
│ │ └── widgets
│ │ │ ├── currently_playing.dart
│ │ │ └── most_popular.dart
│ ├── person
│ │ ├── person_details.dart
│ │ └── widgets
│ │ │ ├── person_credits.dart
│ │ │ └── person_info.dart
│ ├── search
│ │ └── search.dart
│ ├── ui_constants.dart
│ └── video
│ │ ├── movie_show_trailer.dart
│ │ └── video_player.dart
└── utils
│ ├── app_constants.dart
│ ├── app_navigator_observer.dart
│ └── app_utility.dart
├── pubspec.yaml
├── remote
├── .gitignore
├── .metadata
├── README.md
├── lib
│ ├── datasource
│ │ ├── movies_shows_data_source.dart
│ │ └── movies_shows_data_source_impl.dart
│ ├── di
│ │ ├── di.config.dart
│ │ └── di.dart
│ ├── http_client.dart
│ ├── model
│ │ ├── cast_request.dart
│ │ ├── details_request.dart
│ │ ├── genres_request.dart
│ │ ├── movies_shows_genre_request.dart
│ │ ├── movies_shows_request.dart
│ │ ├── page_request.dart
│ │ ├── person_credits_request.dart
│ │ ├── person_info_request.dart
│ │ ├── search_request.dart
│ │ ├── trailer_request.dart
│ │ └── trending_request.dart
│ └── util
│ │ ├── api_constants.dart
│ │ └── http_util.dart
├── pubspec.yaml
├── remote.iml
└── remote_android.iml
└── screenshots
├── home.jpg
├── movie_show_details.jpg
├── movie_show_filters.jpg
├── movie_show_search.jpg
├── movies.jpg
├── person_details.jpg
├── tv_show_details.jpg
└── tv_shows.jpg
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://www.dartlang.org/guides/libraries/private-files
2 |
3 | # Files and directories created by pub
4 | .dart_tool/
5 | .packages
6 | build/
7 | # If you're building an application, you may want to check-in your pubspec.lock
8 | pubspec.lock
9 |
10 | # Directory created by dartdoc
11 | # If you don't generate documentation locally you can remove this line.
12 | doc/api/
13 |
14 | # Avoid committing generated Javascript files:
15 | *.dart.js
16 | *.info.json # Produced by the --dump-info flag.
17 | *.js # When generated by dart2js. Don't specify *.js if your
18 | # project includes source files written in JavaScript.
19 | *.js_
20 | *.js.deps
21 | *.js.map
22 | .flutter-plugins
23 | .flutter-plugins-dependencies
24 | .idea
25 | .DS_Store
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | #Fun Box
2 |
3 | Movies and Tv shows finder.
4 |
5 | - Multi-module MVVM Clean Architecture
6 | - Bloc Pattern
7 | - GetIt and Injectable for dependency injection
8 | - The Movie DB for movies and TV shows. [TheMovieDB](https://developers.themoviedb.org)
9 |
10 | ## Libraries Used
11 | - [Bloc](https://pub.dev/packages/flutter_bloc)
12 | - [GetIt](https://pub.dev/packages/get_it)
13 | - [Injectable](https://pub.dev/packages/injectable)
14 | - [YouTubePlayer](https://pub.dev/packages/youtube_player_flutter)
15 | - [Http](https://pub.dev/packages/http)
16 |
17 | ## App Screens
18 |
19 | - Home Screen
20 |
21 | 
22 |
23 | - Movies Sceen
24 |
25 | 
26 |
27 | - TV Shows Screen
28 |
29 | 
30 |
31 | - Movies Details
32 |
33 | 
34 |
35 | - TV Shows Details
36 |
37 | 
38 |
39 | - Cast Details
40 |
41 | 
42 |
43 | - Search movies & shows
44 |
45 | 
46 |
47 | - Filter movies & shows
48 |
49 | 
50 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 |
--------------------------------------------------------------------------------
/android/app/build.gradle:
--------------------------------------------------------------------------------
1 | def localProperties = new Properties()
2 | def localPropertiesFile = rootProject.file('local.properties')
3 | if (localPropertiesFile.exists()) {
4 | localPropertiesFile.withReader('UTF-8') { reader ->
5 | localProperties.load(reader)
6 | }
7 | }
8 |
9 | def flutterRoot = localProperties.getProperty('flutter.sdk')
10 | if (flutterRoot == null) {
11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12 | }
13 |
14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15 | if (flutterVersionCode == null) {
16 | flutterVersionCode = '1'
17 | }
18 |
19 | def flutterVersionName = localProperties.getProperty('flutter.versionName')
20 | if (flutterVersionName == null) {
21 | flutterVersionName = '1.0'
22 | }
23 |
24 | apply plugin: 'com.android.application'
25 | apply plugin: 'kotlin-android'
26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 |
28 | android {
29 | compileSdkVersion 29
30 |
31 | sourceSets {
32 | main.java.srcDirs += 'src/main/kotlin'
33 | }
34 |
35 | lintOptions {
36 | disable 'InvalidPackage'
37 | }
38 |
39 | defaultConfig {
40 | applicationId "com.ruben.funbox"
41 | minSdkVersion 19
42 | targetSdkVersion 30
43 | versionCode flutterVersionCode.toInteger()
44 | versionName flutterVersionName
45 | }
46 |
47 | buildTypes {
48 | release {
49 | // TODO: Add your own signing config for the release build.
50 | // Signing with the debug keys for now, so `flutter run --release` works.
51 | signingConfig signingConfigs.debug
52 | }
53 | }
54 | }
55 |
56 | flutter {
57 | source '../..'
58 | }
59 |
60 | dependencies {
61 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
62 | }
63 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
8 |
12 |
19 |
23 |
27 |
32 |
36 |
37 |
38 |
39 |
40 |
41 |
43 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/android/app/src/main/ic_launcher_icon-playstore.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/ic_launcher_icon-playstore.png
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/ruben/fun_box/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.ruben.fun_box
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/icon_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/drawable/icon_splash.png
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_icon.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_icon_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-hdpi/ic_launcher_icon_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-mdpi/ic_launcher_icon_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xhdpi/ic_launcher_icon_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_icon_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon_foreground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon_foreground.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_icon_round.png
--------------------------------------------------------------------------------
/android/app/src/main/res/values/ic_launcher_icon_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFFFFF
4 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.4.32'
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.1.3'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/android/fun_box_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 | android.enableR8=true
5 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
7 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/android/settings_aar.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/data/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | .idea/
8 | .vagrant/
9 | .sconsign.dblite
10 | .svn/
11 |
12 | *.swp
13 | profile
14 |
15 | DerivedData/
16 |
17 | .generated/
18 |
19 | *.pbxuser
20 | *.mode1v3
21 | *.mode2v3
22 | *.perspectivev3
23 |
24 | !default.pbxuser
25 | !default.mode1v3
26 | !default.mode2v3
27 | !default.perspectivev3
28 |
29 | xcuserdata
30 |
31 | *.moved-aside
32 |
33 | *.pyc
34 | *sync/
35 | Icon?
36 | .tags*
37 |
38 | build/
39 | .android/
40 | .ios/
41 | .flutter-plugins
42 | .flutter-plugins-dependencies
43 |
44 | # Symbolication related
45 | app.*.symbols
46 |
47 | # Obfuscation related
48 | app.*.map.json
49 |
--------------------------------------------------------------------------------
/data/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
8 | channel: stable
9 |
10 | project_type: module
11 |
--------------------------------------------------------------------------------
/data/README.md:
--------------------------------------------------------------------------------
1 | # data
2 |
3 | A new flutter module project.
4 |
5 | ## Getting Started
6 |
7 | For help getting started with Flutter, view our online
8 | [documentation](https://flutter.dev/).
9 |
10 | For instructions integrating Flutter modules to your existing applications,
11 | see the [add-to-app documentation](https://flutter.dev/docs/development/add-to-app).
12 |
--------------------------------------------------------------------------------
/data/data.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/data/data_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/data/lib/di/di.config.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | // **************************************************************************
4 | // InjectableConfigGenerator
5 | // **************************************************************************
6 |
7 | import 'package:domain/repository/cast_repository.dart' as _i3;
8 | import 'package:domain/repository/config_repository.dart' as _i6;
9 | import 'package:domain/repository/details_repository.dart' as _i8;
10 | import 'package:domain/repository/filter_repository.dart' as _i10;
11 | import 'package:domain/repository/movies_repository.dart' as _i12;
12 | import 'package:domain/repository/person_repository.dart' as _i14;
13 | import 'package:domain/repository/search_repository.dart' as _i16;
14 | import 'package:domain/repository/shows_repository.dart' as _i18;
15 | import 'package:domain/repository/trending_repository.dart' as _i20;
16 | import 'package:domain/repository/video_repository.dart' as _i22;
17 | import 'package:get_it/get_it.dart' as _i1;
18 | import 'package:injectable/injectable.dart' as _i2;
19 | import 'package:remote/datasource/movies_shows_data_source.dart' as _i5;
20 |
21 | import '../repository/cast_repository_impl.dart' as _i4;
22 | import '../repository/config_repository_impl.dart' as _i7;
23 | import '../repository/details_repository_impl.dart' as _i9;
24 | import '../repository/filter_repository_impl.dart' as _i11;
25 | import '../repository/movies_repository_impl.dart' as _i13;
26 | import '../repository/person_repository_impl.dart' as _i15;
27 | import '../repository/search_repository_impl.dart' as _i17;
28 | import '../repository/shows_repository_impl.dart' as _i19;
29 | import '../repository/trending_repository_impl.dart' as _i21;
30 | import '../repository/video_repository_impl.dart'
31 | as _i23; // ignore_for_file: unnecessary_lambdas
32 |
33 | // ignore_for_file: lines_longer_than_80_chars
34 | /// initializes the registration of provided dependencies inside of [GetIt]
35 | _i1.GetIt $initDataGetIt(_i1.GetIt get,
36 | {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
37 | final gh = _i2.GetItHelper(get, environment, environmentFilter);
38 | gh.singleton<_i3.CastRepository>(
39 | _i4.CastRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
40 | gh.singleton<_i6.ConfigRepository>(
41 | _i7.ConfigRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
42 | gh.singleton<_i8.DetailsRepository>(
43 | _i9.DetailsRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
44 | gh.singleton<_i10.FilterRepository>(
45 | _i11.FilterRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
46 | gh.singleton<_i12.MoviesRepository>(
47 | _i13.MoviesRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
48 | gh.singleton<_i14.PersonRepository>(
49 | _i15.PersonRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
50 | gh.singleton<_i16.SearchRepository>(
51 | _i17.SearchRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
52 | gh.singleton<_i18.ShowsRepository>(
53 | _i19.ShowsRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
54 | gh.singleton<_i20.TrendingRepository>(
55 | _i21.TrendingRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
56 | gh.singleton<_i22.VideoRepository>(
57 | _i23.VideoRepositoryImpl(get<_i5.MoviesShowsDataSource>()));
58 | return get;
59 | }
60 |
--------------------------------------------------------------------------------
/data/lib/di/di.dart:
--------------------------------------------------------------------------------
1 | import 'package:data/di/di.config.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @InjectableInit(
5 | initializerName: r'$initDataGetIt'
6 | )
7 | Future configureDataInjection(final getIt) async => $initDataGetIt(getIt);
--------------------------------------------------------------------------------
/data/lib/repository/cast_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/cast_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/cast_request.dart';
5 |
6 | @Singleton(as: CastRepository)
7 | class CastRepositoryImpl extends CastRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | CastRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future getMovieCast(String type, double id) {
14 | return moviesShowsDataSource.getCast(CastRequest(type, id));
15 | }
16 |
17 | @override
18 | Future getShowCast(String type, double id) {
19 | return moviesShowsDataSource.getCast(CastRequest(type, id));
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/data/lib/repository/config_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/config_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 |
5 | @Singleton(as: ConfigRepository)
6 | class ConfigRepositoryImpl extends ConfigRepository {
7 | final MoviesShowsDataSource moviesShowsDataSource;
8 |
9 | ConfigRepositoryImpl(this.moviesShowsDataSource);
10 |
11 | @override
12 | Future getConfig() {
13 | return moviesShowsDataSource.getConfig();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/data/lib/repository/details_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/details_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/details_request.dart';
5 |
6 | @Singleton(as: DetailsRepository)
7 | class DetailsRepositoryImpl extends DetailsRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | DetailsRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future getMovieDetails(String type, double id) {
14 | return moviesShowsDataSource.getDetails(DetailsRequest(type: type, id: id));
15 | }
16 |
17 | @override
18 | Future getShowDetails(String type, double id) {
19 | return moviesShowsDataSource.getDetails(DetailsRequest(type: type, id: id));
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/data/lib/repository/filter_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/filter_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/genres_request.dart';
5 |
6 | @Singleton(as: FilterRepository)
7 | class FilterRepositoryImpl extends FilterRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | FilterRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future getGenres(String type) {
14 | return moviesShowsDataSource.getGenres(GenresRequest(type: type));
15 | }
16 |
17 | }
--------------------------------------------------------------------------------
/data/lib/repository/movies_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/movies_shows_genre_request.dart';
5 | import 'package:remote/model/movies_shows_request.dart';
6 | import 'package:remote/model/page_request.dart';
7 |
8 | @Singleton(as: MoviesRepository)
9 | class MoviesRepositoryImpl extends MoviesRepository {
10 | final MoviesShowsDataSource moviesShowsDataSource;
11 |
12 | MoviesRepositoryImpl(this.moviesShowsDataSource);
13 |
14 | @override
15 | Future getCurrentPlayingMovies(int page) {
16 | return moviesShowsDataSource
17 | .getCurrentPlayingMovies(PageRequest(page: page));
18 | }
19 |
20 | @override
21 | Future getPopularMovies(String type, int page) {
22 | return moviesShowsDataSource
23 | .getPopularMoviesShows(MoviesShowsRequest(type: type, page: page));
24 | }
25 |
26 | @override
27 | Future getLatestMovies(String type, int page) {
28 | return moviesShowsDataSource
29 | .getLatestMoviesShows(MoviesShowsRequest(type: type, page: page));
30 | }
31 |
32 | @override
33 | Future getTopRatedMovies(String type, int page) {
34 | return moviesShowsDataSource
35 | .getTopRatedMoviesShows(MoviesShowsRequest(type: type, page: page));
36 | }
37 |
38 | @override
39 | Future getUpcomingMovies(int page) {
40 | return moviesShowsDataSource.getUpcomingMovies(PageRequest(page: page));
41 | }
42 |
43 | @override
44 | Future getMoviesByGenre(String type, int genreId, int page) {
45 | return moviesShowsDataSource.getMoviesShowsByGenre(
46 | MoviesShowsGenreRequest(type: type, genreId: genreId, page: page));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/data/lib/repository/person_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/person_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/person_credits_request.dart';
5 | import 'package:remote/model/person_info_request.dart';
6 |
7 | @Singleton(as: PersonRepository)
8 | class PersonRepositoryImpl extends PersonRepository {
9 | final MoviesShowsDataSource moviesShowsDataSource;
10 |
11 | PersonRepositoryImpl(this.moviesShowsDataSource);
12 |
13 | @override
14 | Future getPersonCredits(double id) {
15 | return moviesShowsDataSource.getPersonCredits(PersonCreditsRequest(id: id));
16 | }
17 |
18 | @override
19 | Future getPersonInfo(double id) {
20 | return moviesShowsDataSource.getPersonInfo(PersonInfoRequest(id: id));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/data/lib/repository/search_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/search_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/search_request.dart';
5 |
6 | @Singleton(as: SearchRepository)
7 | class SearchRepositoryImpl extends SearchRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | SearchRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future searchMoviesShows(String searchTerm) {
14 | return moviesShowsDataSource
15 | .searchMoviesShows(SearchRequest(searchTerm: searchTerm));
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/data/lib/repository/shows_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/movies_shows_genre_request.dart';
5 | import 'package:remote/model/movies_shows_request.dart';
6 | import 'package:remote/model/page_request.dart';
7 |
8 | @Singleton(as: ShowsRepository)
9 | class ShowsRepositoryImpl extends ShowsRepository {
10 | final MoviesShowsDataSource moviesShowsDataSource;
11 |
12 | ShowsRepositoryImpl(this.moviesShowsDataSource);
13 |
14 | @override
15 | Future getCurrentPlayingShows(int page) {
16 | return moviesShowsDataSource
17 | .getCurrentPlayingShows(PageRequest(page: page));
18 | }
19 |
20 | @override
21 | Future getPopularShows(String type, int page) {
22 | return moviesShowsDataSource
23 | .getPopularMoviesShows(MoviesShowsRequest(type: type, page: page));
24 | }
25 |
26 | @override
27 | Future getLatestShows(String type, int page) {
28 | return moviesShowsDataSource
29 | .getLatestMoviesShows(MoviesShowsRequest(type: type, page: page));
30 | }
31 |
32 | @override
33 | Future getTopRatedShows(String type, int page) {
34 | return moviesShowsDataSource
35 | .getTopRatedMoviesShows(MoviesShowsRequest(type: type, page: page));
36 | }
37 |
38 | @override
39 | Future getAiringTodayShows(int page) {
40 | return moviesShowsDataSource.getAiringTodayShows(PageRequest(page: page));
41 | }
42 |
43 | @override
44 | Future getShowsByGenre(String type, int genreId, int page) {
45 | return moviesShowsDataSource.getMoviesShowsByGenre(
46 | MoviesShowsGenreRequest(type: type, genreId: genreId, page: page));
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/data/lib/repository/trending_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/trending_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/trending_request.dart';
5 |
6 | @Singleton(as: TrendingRepository)
7 | class TrendingRepositoryImpl implements TrendingRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | TrendingRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future getTrendingMovies(String type) {
14 | return moviesShowsDataSource
15 | .getTrending(TrendingRequest(type: type));
16 | }
17 |
18 | @override
19 | Future getTrendingShows(String type) {
20 | return moviesShowsDataSource
21 | .getTrending(TrendingRequest(type: type));
22 | }
23 |
24 | @override
25 | Future getTrendingPeople(String type) {
26 | return moviesShowsDataSource
27 | .getTrendingPeople(TrendingRequest(type: type));
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/data/lib/repository/video_repository_impl.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/video_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 | import 'package:remote/datasource/movies_shows_data_source.dart';
4 | import 'package:remote/model/trailer_request.dart';
5 |
6 | @Singleton(as: VideoRepository)
7 | class VideoRepositoryImpl extends VideoRepository {
8 | final MoviesShowsDataSource moviesShowsDataSource;
9 |
10 | VideoRepositoryImpl(this.moviesShowsDataSource);
11 |
12 | @override
13 | Future getMovieTrailer(String type, double id) {
14 | return moviesShowsDataSource.getTrailer(TrailerRequest(type, id));
15 | }
16 |
17 | @override
18 | Future getShowTrailer(String type, double id) {
19 | return moviesShowsDataSource.getTrailer(TrailerRequest(type, id));
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/data/pubspec.yaml:
--------------------------------------------------------------------------------
1 | publish_to: none
2 | name: data
3 | description: A new flutter module project.
4 |
5 | # The following defines the version and build number for your application.
6 | # A version number is three numbers separated by dots, like 1.2.43
7 | # followed by an optional build number separated by a +.
8 | # Both the version and the builder number may be overridden in flutter
9 | # build by specifying --build-name and --build-number, respectively.
10 | # In Android, build-name is used as versionName while build-number used as versionCode.
11 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
12 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
13 | # Read more about iOS versioning at
14 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
15 | #
16 | # This version is used _only_ for the Runner app, which is used if you just do
17 | # a `flutter run` or a `flutter make-host-app-editable`. It has no impact
18 | # on any other native host app that you embed your Flutter project into.
19 | version: 1.0.0+1
20 |
21 | environment:
22 | sdk: ">=2.12.0 <3.0.0"
23 |
24 | dependencies:
25 | flutter:
26 | sdk: flutter
27 |
28 | # The following adds the Cupertino Icons font to your application.
29 | # Use with the CupertinoIcons class for iOS style icons.
30 | cupertino_icons: ^1.0.0
31 | injectable: ^1.2.2
32 | get_it: ^6.0.0
33 |
34 | domain:
35 | path: ../domain
36 |
37 | remote:
38 | path: ../remote
39 |
40 | dev_dependencies:
41 | flutter_test:
42 | sdk: flutter
43 | injectable_generator: 1.2.2
44 | build_runner: 1.12.2
45 |
46 | # For information on the generic Dart part of this file, see the
47 | # following page: https://dart.dev/tools/pub/pubspec
48 |
49 | flutter:
50 | # The following line ensures that the Material Icons font is
51 | # included with your application, so that you can use the icons in
52 | # the material Icons class.
53 | uses-material-design: true
54 |
55 | # To add Flutter specific assets to your application, add an assets section,
56 | # like this:
57 | # assets:
58 | # - images/a_dot_burr.jpeg
59 | # - images/a_dot_ham.jpeg
60 |
61 | # An image asset can refer to one or more resolution-specific "variants", see
62 | # https://flutter.dev/assets-and-images/#resolution-aware.
63 |
64 | # For details regarding adding assets from package dependencies, see
65 | # https://flutter.dev/assets-and-images/#from-packages
66 |
67 | # To add Flutter specific custom fonts to your application, add a fonts
68 | # section here, in this "flutter" section. Each entry in this list should
69 | # have a "family" key with the font family name, and a "fonts" key with a
70 | # list giving the asset and other descriptors for the font. For
71 | # example:
72 | # fonts:
73 | # - family: Schyler
74 | # fonts:
75 | # - asset: fonts/Schyler-Regular.ttf
76 | # - asset: fonts/Schyler-Italic.ttf
77 | # style: italic
78 | # - family: Trajan Pro
79 | # fonts:
80 | # - asset: fonts/TrajanPro.ttf
81 | # - asset: fonts/TrajanPro_Bold.ttf
82 | # weight: 700
83 | #
84 | # For details regarding fonts from package dependencies,
85 | # see https://flutter.dev/custom-fonts/#from-packages
86 |
87 |
88 | # This section identifies your Flutter project as a module meant for
89 | # embedding in a native host app. These identifiers should _not_ ordinarily
90 | # be changed after generation - they are used to ensure that the tooling can
91 | # maintain consistency when adding or modifying assets and plugins.
92 | # They also do not have any bearing on your native host application's
93 | # identifiers, which may be completely independent or the same as these.
94 | module:
95 | androidX: true
96 | androidPackage: com.ruben.funbox.data
97 | iosBundleIdentifier: com.ruben.funbox.data
98 |
--------------------------------------------------------------------------------
/domain/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | .idea/
8 | .vagrant/
9 | .sconsign.dblite
10 | .svn/
11 |
12 | *.swp
13 | profile
14 |
15 | DerivedData/
16 |
17 | .generated/
18 |
19 | *.pbxuser
20 | *.mode1v3
21 | *.mode2v3
22 | *.perspectivev3
23 |
24 | !default.pbxuser
25 | !default.mode1v3
26 | !default.mode2v3
27 | !default.perspectivev3
28 |
29 | xcuserdata
30 |
31 | *.moved-aside
32 |
33 | *.pyc
34 | *sync/
35 | Icon?
36 | .tags*
37 |
38 | build/
39 | .android/
40 | .ios/
41 | .flutter-plugins
42 | .flutter-plugins-dependencies
43 |
44 | # Symbolication related
45 | app.*.symbols
46 |
47 | # Obfuscation related
48 | app.*.map.json
49 |
--------------------------------------------------------------------------------
/domain/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
8 | channel: stable
9 |
10 | project_type: module
11 |
--------------------------------------------------------------------------------
/domain/README.md:
--------------------------------------------------------------------------------
1 | # domain
2 |
3 | A new flutter module project.
4 |
5 | ## Getting Started
6 |
7 | For help getting started with Flutter, view our online
8 | [documentation](https://flutter.dev/).
9 |
10 | For instructions integrating Flutter modules to your existing applications,
11 | see the [add-to-app documentation](https://flutter.dev/docs/development/add-to-app).
12 |
--------------------------------------------------------------------------------
/domain/domain.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/domain/domain_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/domain/lib/di/di.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/di/di.config.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @InjectableInit(
5 | initializerName: r'$initDomainGetIt'
6 | )
7 | Future configureDomainInjection(final getIt) async => $initDomainGetIt(getIt);
--------------------------------------------------------------------------------
/domain/lib/model/cast_record.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 |
3 | class CastRecord {
4 | int? id;
5 | List? cast;
6 | List? crew;
7 |
8 | CastRecord({this.id, this.cast, this.crew});
9 |
10 | CastRecord.fromJson(Map json) {
11 | id = json['id'];
12 | if (json['cast'] != null) {
13 | cast = [];
14 | try {
15 | json['cast'].forEach((v) {
16 | cast?.add(new Cast.fromJson(v));
17 | });
18 | } catch (_) {
19 | debugPrint('Data inconsistency');
20 | }
21 | }
22 | if (json['crew'] != null) {
23 | crew = [];
24 | try {
25 | json['crew'].forEach((v) {
26 | crew?.add(new Crew.fromJson(v));
27 | });
28 | } catch (_) {
29 | debugPrint('Data inconsistency');
30 | }
31 | }
32 | }
33 |
34 | Map toJson() {
35 | final Map data = new Map();
36 | data['id'] = this.id;
37 | if (this.cast != null) {
38 | data['cast'] = this.cast!.map((v) => v.toJson()).toList();
39 | }
40 | if (this.crew != null) {
41 | data['crew'] = this.crew!.map((v) => v.toJson()).toList();
42 | }
43 | return data;
44 | }
45 | }
46 |
47 | class Cast {
48 | bool? adult;
49 | int? gender;
50 | int? id;
51 | String? knownForDepartment;
52 | String? name;
53 | String? originalName;
54 | double? popularity;
55 | String? profilePath;
56 | int? castId;
57 | String? character;
58 | String? creditId;
59 | int? order;
60 |
61 | Cast(
62 | {this.adult,
63 | this.gender,
64 | this.id,
65 | this.knownForDepartment,
66 | this.name,
67 | this.originalName,
68 | this.popularity,
69 | this.profilePath,
70 | this.castId,
71 | this.character,
72 | this.creditId,
73 | this.order});
74 |
75 | Cast.fromJson(Map json) {
76 | adult = json['adult'];
77 | gender = json['gender'];
78 | id = json['id'];
79 | knownForDepartment = json['known_for_department'];
80 | name = json['name'];
81 | originalName = json['original_name'];
82 | popularity = json['popularity'].toDouble();
83 | profilePath = json['profile_path'];
84 | castId = json['cast_id'];
85 | character = json['character'];
86 | creditId = json['credit_id'];
87 | order = json['order'];
88 | }
89 |
90 | Map toJson() {
91 | final Map data = new Map();
92 | data['adult'] = this.adult;
93 | data['gender'] = this.gender;
94 | data['id'] = this.id;
95 | data['known_for_department'] = this.knownForDepartment;
96 | data['name'] = this.name;
97 | data['original_name'] = this.originalName;
98 | data['popularity'] = this.popularity;
99 | data['profile_path'] = this.profilePath;
100 | data['cast_id'] = this.castId;
101 | data['character'] = this.character;
102 | data['credit_id'] = this.creditId;
103 | data['order'] = this.order;
104 | return data;
105 | }
106 | }
107 |
108 | class Crew {
109 | bool? adult;
110 | int? gender;
111 | int? id;
112 | String? knownForDepartment;
113 | String? name;
114 | String? originalName;
115 | double? popularity;
116 | String? profilePath;
117 | String? creditId;
118 | String? department;
119 | String? job;
120 |
121 | Crew(
122 | {this.adult,
123 | this.gender,
124 | this.id,
125 | this.knownForDepartment,
126 | this.name,
127 | this.originalName,
128 | this.popularity,
129 | this.profilePath,
130 | this.creditId,
131 | this.department,
132 | this.job});
133 |
134 | Crew.fromJson(Map json) {
135 | adult = json['adult'];
136 | gender = json['gender'];
137 | id = json['id'];
138 | knownForDepartment = json['known_for_department'];
139 | name = json['name'];
140 | originalName = json['original_name'];
141 | popularity = json['popularity'].toDouble();
142 | profilePath = json['profile_path'];
143 | creditId = json['credit_id'];
144 | department = json['department'];
145 | job = json['job'];
146 | }
147 |
148 | Map toJson() {
149 | final Map data = new Map();
150 | data['adult'] = this.adult;
151 | data['gender'] = this.gender;
152 | data['id'] = this.id;
153 | data['known_for_department'] = this.knownForDepartment;
154 | data['name'] = this.name;
155 | data['original_name'] = this.originalName;
156 | data['popularity'] = this.popularity;
157 | data['profile_path'] = this.profilePath;
158 | data['credit_id'] = this.creditId;
159 | data['department'] = this.department;
160 | data['job'] = this.job;
161 | return data;
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/domain/lib/model/config_record.dart:
--------------------------------------------------------------------------------
1 | class ConfigRecord {
2 | Images? images;
3 | List? changeKeys;
4 |
5 | ConfigRecord({this.images, this.changeKeys});
6 |
7 | ConfigRecord.fromJson(Map json) {
8 | images =
9 | json['images'] != null ? new Images.fromJson(json['images']) : null;
10 | changeKeys = json['change_keys'].cast();
11 | }
12 |
13 | Map toJson() {
14 | final Map data = new Map();
15 | if (this.images != null) {
16 | data['images'] = this.images!.toJson();
17 | }
18 | data['change_keys'] = this.changeKeys;
19 | return data;
20 | }
21 | }
22 |
23 | class Images {
24 | String? baseUrl;
25 | String? secureBaseUrl;
26 | List? backdropSizes;
27 | List? logoSizes;
28 | List? posterSizes;
29 | List? profileSizes;
30 | List? stillSizes;
31 |
32 | Images(
33 | {this.baseUrl,
34 | this.secureBaseUrl,
35 | this.backdropSizes,
36 | this.logoSizes,
37 | this.posterSizes,
38 | this.profileSizes,
39 | this.stillSizes});
40 |
41 | Images.fromJson(Map json) {
42 | baseUrl = json['base_url'];
43 | secureBaseUrl = json['secure_base_url'];
44 | backdropSizes = json['backdrop_sizes'].cast();
45 | logoSizes = json['logo_sizes'].cast();
46 | posterSizes = json['poster_sizes'].cast();
47 | profileSizes = json['profile_sizes'].cast();
48 | stillSizes = json['still_sizes'].cast();
49 | }
50 |
51 | Map toJson() {
52 | final Map data = new Map();
53 | data['base_url'] = this.baseUrl;
54 | data['secure_base_url'] = this.secureBaseUrl;
55 | data['backdrop_sizes'] = this.backdropSizes;
56 | data['logo_sizes'] = this.logoSizes;
57 | data['poster_sizes'] = this.posterSizes;
58 | data['profile_sizes'] = this.profileSizes;
59 | data['still_sizes'] = this.stillSizes;
60 | return data;
61 | }
62 | }
--------------------------------------------------------------------------------
/domain/lib/model/movie_show_genres_record.dart:
--------------------------------------------------------------------------------
1 | class MovieShowGenresRecord {
2 | List? genres;
3 |
4 | MovieShowGenresRecord({this.genres});
5 |
6 | MovieShowGenresRecord.fromJson(Map json) {
7 | if (json['genres'] != null) {
8 | genres = [];
9 | json['genres'].forEach((v) {
10 | genres?.add(new Genres.fromJson(v));
11 | });
12 | }
13 | }
14 |
15 | Map toJson() {
16 | final Map data = new Map();
17 | if (this.genres != null) {
18 | data['genres'] = this.genres!.map((v) => v.toJson()).toList();
19 | }
20 | return data;
21 | }
22 | }
23 |
24 | class Genres {
25 | int? id;
26 | String? name;
27 |
28 | Genres({this.id, this.name});
29 |
30 | Genres.fromJson(Map json) {
31 | id = json['id'];
32 | name = json['name'];
33 | }
34 |
35 | Map toJson() {
36 | final Map data = new Map();
37 | data['id'] = this.id;
38 | data['name'] = this.name;
39 | return data;
40 | }
41 | }
--------------------------------------------------------------------------------
/domain/lib/model/movies_shows_record.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsRecord {
2 | int? page;
3 | List? results;
4 | int? totalPages;
5 | int? totalResults;
6 |
7 | MoviesShowsRecord({this.page, this.results, this.totalPages, this.totalResults});
8 |
9 | MoviesShowsRecord.fromJson(Map json) {
10 | page = json['page'];
11 | if (json['results'] != null) {
12 | results = [];
13 | json['results'].forEach((v) {
14 | results?.add(new Results.fromJson(v));
15 | });
16 | }
17 | totalPages = json['total_pages'];
18 | totalResults = json['total_results'];
19 | }
20 |
21 | Map toJson() {
22 | final Map data = new Map();
23 | data['page'] = this.page;
24 | if (this.results != null) {
25 | data['results'] = this.results?.map((v) => v.toJson()).toList();
26 | }
27 | data['total_pages'] = this.totalPages;
28 | data['total_results'] = this.totalResults;
29 | return data;
30 | }
31 | }
32 |
33 | class Results {
34 | String? title;
35 | String? originalLanguage;
36 | String? originalTitle;
37 | String? posterPath;
38 | bool? video;
39 | double? voteAverage;
40 | String? overview;
41 | int? id;
42 | int? voteCount;
43 | bool? adult;
44 | String? backdropPath;
45 | String? releaseDate;
46 | List? genreIds;
47 | double? popularity;
48 | String? mediaType;
49 | String? firstAirDate;
50 | List? originCountry;
51 | String? name;
52 | String? originalName;
53 |
54 | Results(
55 | {this.title,
56 | this.originalLanguage,
57 | this.originalTitle,
58 | this.posterPath,
59 | this.video,
60 | this.voteAverage,
61 | this.overview,
62 | this.id,
63 | this.voteCount,
64 | this.adult,
65 | this.backdropPath,
66 | this.releaseDate,
67 | this.genreIds,
68 | this.popularity,
69 | this.mediaType,
70 | this.firstAirDate,
71 | this.originCountry,
72 | this.name,
73 | this.originalName});
74 |
75 | Results.fromJson(Map json) {
76 | title = json['title'];
77 | originalLanguage = json['original_language'];
78 | originalTitle = json['original_title'];
79 | if(json['poster_path'] != null) {
80 | posterPath = json['poster_path'];
81 | }
82 | video = json['video'];
83 | if(json['vote_average'] != null) {
84 | voteAverage = json['vote_average'].toDouble();
85 | }
86 | overview = json['overview'];
87 | id = json['id'];
88 | voteCount = json['vote_count'];
89 | adult = json['adult'];
90 | if(json['backdrop_path'] != null) {
91 | backdropPath = json['backdrop_path'];
92 | }
93 | releaseDate = json['release_date'];
94 | if(json['genre_ids'] != null) {
95 | genreIds = json['genre_ids'].cast();
96 | }
97 | popularity = json['popularity'].toDouble();
98 | if (json['media_type'] != null) {
99 | mediaType = json['media_type'];
100 | }
101 | if (json['first_air_date'] != null) {
102 | firstAirDate = json['first_air_date'];
103 | }
104 | if (json['origin_country'] != null) {
105 | originCountry = json['origin_country'].cast();
106 | }
107 | if (json['name'] != null) {
108 | name = json['name'];
109 | }
110 | if (json['original_name'] != null) {
111 | originalName = json['original_name'];
112 | }
113 | }
114 |
115 | Map toJson() {
116 | final Map data = new Map();
117 | data['title'] = this.title;
118 | data['original_language'] = this.originalLanguage;
119 | data['original_title'] = this.originalTitle;
120 | data['poster_path'] = this.posterPath;
121 | data['video'] = this.video;
122 | data['vote_average'] = this.voteAverage;
123 | data['overview'] = this.overview;
124 | data['id'] = this.id;
125 | data['vote_count'] = this.voteCount;
126 | data['adult'] = this.adult;
127 | data['backdrop_path'] = this.backdropPath;
128 | data['release_date'] = this.releaseDate;
129 | data['genre_ids'] = this.genreIds;
130 | data['popularity'] = this.popularity;
131 | data['media_type'] = this.mediaType;
132 | data['first_air_date'] = this.firstAirDate;
133 | data['origin_country'] = this.originCountry;
134 | data['name'] = this.name;
135 | data['original_name'] = this.originalName;
136 | return data;
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/domain/lib/model/person_info_record.dart:
--------------------------------------------------------------------------------
1 | class PersonInfoRecord {
2 | bool? adult;
3 | List? alsoKnownAs;
4 | String? biography;
5 | String? birthday;
6 | String? deathday;
7 | int? gender;
8 | String? homepage;
9 | int? id;
10 | String? imdbId;
11 | String? knownForDepartment;
12 | String? name;
13 | String? placeOfBirth;
14 | double? popularity;
15 | String? profilePath;
16 |
17 | PersonInfoRecord(
18 | {this.adult,
19 | this.alsoKnownAs,
20 | this.biography,
21 | this.birthday,
22 | this.deathday,
23 | this.gender,
24 | this.homepage,
25 | this.id,
26 | this.imdbId,
27 | this.knownForDepartment,
28 | this.name,
29 | this.placeOfBirth,
30 | this.popularity,
31 | this.profilePath});
32 |
33 | PersonInfoRecord.fromJson(Map json) {
34 | adult = json['adult'];
35 | alsoKnownAs = json['also_known_as'].cast();
36 | biography = json['biography'];
37 | birthday = json['birthday'];
38 | deathday = json['deathday'];
39 | gender = json['gender'];
40 | homepage = json['homepage'];
41 | id = json['id'];
42 | imdbId = json['imdb_id'];
43 | knownForDepartment = json['known_for_department'];
44 | name = json['name'];
45 | placeOfBirth = json['place_of_birth'];
46 | popularity = json['popularity'].toDouble();
47 | profilePath = json['profile_path'];
48 | }
49 |
50 | Map toJson() {
51 | final Map data = new Map();
52 | data['adult'] = this.adult;
53 | data['also_known_as'] = this.alsoKnownAs;
54 | data['biography'] = this.biography;
55 | data['birthday'] = this.birthday;
56 | data['deathday'] = this.deathday;
57 | data['gender'] = this.gender;
58 | data['homepage'] = this.homepage;
59 | data['id'] = this.id;
60 | data['imdb_id'] = this.imdbId;
61 | data['known_for_department'] = this.knownForDepartment;
62 | data['name'] = this.name;
63 | data['place_of_birth'] = this.placeOfBirth;
64 | data['popularity'] = this.popularity;
65 | data['profile_path'] = this.profilePath;
66 | return data;
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/domain/lib/model/trailer_record.dart:
--------------------------------------------------------------------------------
1 | class TrailerRecord {
2 | int? id;
3 | List? results;
4 |
5 | TrailerRecord({this.id, this.results});
6 |
7 | TrailerRecord.fromJson(Map json) {
8 | id = json['id'];
9 | if (json['results'] != null) {
10 | results = [];
11 | json['results'].forEach((v) {
12 | results?.add(new Results.fromJson(v));
13 | });
14 | }
15 | }
16 |
17 | Map toJson() {
18 | final Map data = new Map();
19 | data['id'] = this.id;
20 | if (this.results != null) {
21 | data['results'] = this.results!.map((v) => v.toJson()).toList();
22 | }
23 | return data;
24 | }
25 | }
26 |
27 | class Results {
28 | String? id;
29 | String? iso6391;
30 | String? iso31661;
31 | String? key;
32 | String? name;
33 | String? site;
34 | int? size;
35 | String? type;
36 |
37 | Results(
38 | {this.id,
39 | this.iso6391,
40 | this.iso31661,
41 | this.key,
42 | this.name,
43 | this.site,
44 | this.size,
45 | this.type});
46 |
47 | Results.fromJson(Map json) {
48 | id = json['id'];
49 | iso6391 = json['iso_639_1'];
50 | iso31661 = json['iso_3166_1'];
51 | key = json['key'];
52 | name = json['name'];
53 | site = json['site'];
54 | size = json['size'];
55 | type = json['type'];
56 | }
57 |
58 | Map toJson() {
59 | final Map data = new Map();
60 | data['id'] = this.id;
61 | data['iso_639_1'] = this.iso6391;
62 | data['iso_3166_1'] = this.iso31661;
63 | data['key'] = this.key;
64 | data['name'] = this.name;
65 | data['site'] = this.site;
66 | data['size'] = this.size;
67 | data['type'] = this.type;
68 | return data;
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/domain/lib/repository/cast_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class CastRepository {
2 |
3 | Future getMovieCast(String type, double id);
4 | Future getShowCast(String type, double id);
5 |
6 | }
--------------------------------------------------------------------------------
/domain/lib/repository/config_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class ConfigRepository {
2 |
3 | Future getConfig();
4 |
5 | }
--------------------------------------------------------------------------------
/domain/lib/repository/details_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class DetailsRepository {
2 |
3 | Future getMovieDetails(String type, double id);
4 | Future getShowDetails(String type, double id);
5 | }
--------------------------------------------------------------------------------
/domain/lib/repository/filter_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class FilterRepository {
2 | Future getGenres(String type);
3 | }
--------------------------------------------------------------------------------
/domain/lib/repository/movies_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class MoviesRepository {
2 |
3 | Future getCurrentPlayingMovies(int page);
4 | Future getPopularMovies(String type, int page);
5 | Future getLatestMovies(String type, int page);
6 | Future getTopRatedMovies(String type, int page);
7 | Future getUpcomingMovies(int page);
8 | Future getMoviesByGenre(String type, int genreId, int page);
9 |
10 | }
--------------------------------------------------------------------------------
/domain/lib/repository/person_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class PersonRepository {
2 |
3 | Future getPersonInfo(double id);
4 | Future getPersonCredits(double id);
5 |
6 | }
--------------------------------------------------------------------------------
/domain/lib/repository/search_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class SearchRepository {
2 | Future searchMoviesShows(String searchTerm);
3 | }
--------------------------------------------------------------------------------
/domain/lib/repository/shows_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class ShowsRepository {
2 |
3 | Future getCurrentPlayingShows(int page);
4 | Future getPopularShows(String type, int page);
5 | Future getLatestShows(String type, int page);
6 | Future getTopRatedShows(String type, int page);
7 | Future getAiringTodayShows(int page);
8 | Future getShowsByGenre(String type, int genreId, int page);
9 |
10 | }
--------------------------------------------------------------------------------
/domain/lib/repository/trending_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class TrendingRepository {
2 |
3 | Future getTrendingMovies(String type);
4 | Future getTrendingShows(String type);
5 | Future getTrendingPeople(String type);
6 |
7 | }
--------------------------------------------------------------------------------
/domain/lib/repository/video_repository.dart:
--------------------------------------------------------------------------------
1 | abstract class VideoRepository {
2 |
3 | Future getMovieTrailer(String type, double id);
4 | Future getShowTrailer(String type, double id);
5 | }
--------------------------------------------------------------------------------
/domain/lib/usecase/cast/movie_cast_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/cast_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class MovieCastUseCase {
6 | final CastRepository repository;
7 |
8 | MovieCastUseCase(this.repository);
9 |
10 | Future getMovieCast({required String type, required double id}) {
11 | return repository.getMovieCast(type, id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/cast/show_cast_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/cast_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class ShowCastUseCase {
6 | final CastRepository repository;
7 |
8 | ShowCastUseCase(this.repository);
9 |
10 | Future getShowCast({required String type, required double id}) {
11 | return repository.getShowCast(type, id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/details/movie_details_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/details_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class MovieDetailsUseCase {
6 | final DetailsRepository repository;
7 |
8 | MovieDetailsUseCase(this.repository);
9 |
10 | Future getMovieDetails({required String type, required double id}) {
11 | return repository.getMovieDetails(type, id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/details/show_details_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/details_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class ShowDetailsUseCase {
6 |
7 | final DetailsRepository repository;
8 |
9 | ShowDetailsUseCase(this.repository);
10 |
11 | Future getShowDetails({required String type, required double id}) {
12 | return repository.getShowDetails(type, id);
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/domain/lib/usecase/filter/movie_filter_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/filter_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class MovieFilterUseCase {
6 | final FilterRepository repository;
7 |
8 | MovieFilterUseCase(this.repository);
9 |
10 | Future getMovieGenres({required String type}) {
11 | return repository.getGenres(type);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/filter/show_filter_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/filter_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class ShowFilterUseCase {
6 | final FilterRepository repository;
7 |
8 | ShowFilterUseCase(this.repository);
9 |
10 | Future getShowGenres({required String type}) {
11 | return repository.getGenres(type);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/get_config_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/config_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class GetConfigUseCase {
6 |
7 | final ConfigRepository repository;
8 |
9 | GetConfigUseCase(this.repository);
10 |
11 | Future getConfig() async {
12 | return repository.getConfig();
13 | }
14 | }
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/current_playing_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class CurrentPlayingMoviesUseCase {
6 | final MoviesRepository repository;
7 |
8 | CurrentPlayingMoviesUseCase(this.repository);
9 |
10 | Future getCurrentPlayingMovies({required int page}) {
11 | return repository.getCurrentPlayingMovies(page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/latest_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class LatestMoviesUseCase {
6 | final MoviesRepository repository;
7 |
8 | LatestMoviesUseCase(this.repository);
9 |
10 | Future getLatestMovies({required String type, required int page}) {
11 | return repository.getLatestMovies(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/movies_by_genres_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class MoviesByGenresUseCase {
6 | final MoviesRepository repository;
7 |
8 | MoviesByGenresUseCase(this.repository);
9 |
10 | Future getMoviesByGenre(
11 | {required String type, required int genreId, required int page}) {
12 | return repository.getMoviesByGenre(type, genreId, page);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/popular_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class PopularMoviesUseCase {
6 | final MoviesRepository repository;
7 |
8 | PopularMoviesUseCase(this.repository);
9 |
10 | Future getPopularMovies({required String type, required int page}) {
11 | return repository.getPopularMovies(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/top_rated_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class TopRatedMoviesUseCase {
6 | final MoviesRepository repository;
7 |
8 | TopRatedMoviesUseCase(this.repository);
9 |
10 | Future getTopRatedMovies({required String type, required int page}) {
11 | return repository.getTopRatedMovies(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/movies/upcoming_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/movies_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class UpcomingMoviesUseCase {
6 | final MoviesRepository repository;
7 |
8 | UpcomingMoviesUseCase(this.repository);
9 |
10 | Future getUpcomingMovies({required int page}) {
11 | return repository.getUpcomingMovies(page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/person/person_credits_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/person_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class PersonCreditsUseCase {
6 | final PersonRepository repository;
7 |
8 | PersonCreditsUseCase(this.repository);
9 |
10 | Future getPersonCredits({required double id}) {
11 | return repository.getPersonCredits(id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/person/person_info_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/person_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class PersonInfoUseCase {
6 | final PersonRepository repository;
7 |
8 | PersonInfoUseCase(this.repository);
9 |
10 | Future getPersonIfo({required double id}) {
11 | return repository.getPersonInfo(id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/search_movies_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/search_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class SearchMoviesShowsUseCase {
6 | final SearchRepository repository;
7 |
8 | SearchMoviesShowsUseCase(this.repository);
9 |
10 | Future searchMoviesShows({required String searchTerm}) {
11 | return repository.searchMoviesShows(searchTerm);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/airing_today_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class AiringTodayShowsUseCase {
6 | final ShowsRepository repository;
7 |
8 | AiringTodayShowsUseCase(this.repository);
9 |
10 | Future getAiringTodayShows({required int page}) {
11 | return repository.getAiringTodayShows(page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/current_playing_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class CurrentPlayingShowsUseCase {
6 | final ShowsRepository repository;
7 |
8 | CurrentPlayingShowsUseCase(this.repository);
9 |
10 | Future getCurrentPlayingShows({required int page}) {
11 | return repository.getCurrentPlayingShows(page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/latest_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class LatestShowsUseCase {
6 | final ShowsRepository repository;
7 |
8 | LatestShowsUseCase(this.repository);
9 |
10 | Future getLatestShows({required String type, required int page}) {
11 | return repository.getLatestShows(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/popular_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class PopularShowsUseCase {
6 | final ShowsRepository repository;
7 |
8 | PopularShowsUseCase(this.repository);
9 |
10 | Future getPopularShows({required String type, required int page}) {
11 | return repository.getPopularShows(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/shows_by_genres_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class ShowsByGenresUseCase {
6 | final ShowsRepository repository;
7 |
8 | ShowsByGenresUseCase(this.repository);
9 |
10 | Future getShowsByGenres(
11 | {required String type, required int genreId, required int page}) {
12 | return repository.getShowsByGenre(type, genreId, page);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/domain/lib/usecase/shows/top_rated_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/shows_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class TopRatedShowsUseCase {
6 | final ShowsRepository repository;
7 |
8 | TopRatedShowsUseCase(this.repository);
9 |
10 | Future getTopRatedShows({required String type, required int page}) {
11 | return repository.getTopRatedShows(type, page);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/trending/trending_movies_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/trending_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class TrendingMoviesUseCase {
6 | final TrendingRepository repository;
7 |
8 | TrendingMoviesUseCase(this.repository);
9 |
10 | Future getTrendingMovies({required String type}) async {
11 | return repository.getTrendingMovies(type);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/trending/trending_people_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/trending_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class TrendingPeopleUseCase {
6 | final TrendingRepository repository;
7 |
8 | TrendingPeopleUseCase(this.repository);
9 |
10 | Future getTrendingPeople({required String type}) {
11 | return repository.getTrendingPeople(type);
12 | }
13 | }
--------------------------------------------------------------------------------
/domain/lib/usecase/trending/trending_shows_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/trending_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class TrendingShowsUseCase {
6 |
7 | final TrendingRepository repository;
8 |
9 | TrendingShowsUseCase(this.repository);
10 |
11 | Future getTrendingShows({required String type}) {
12 | return repository.getTrendingShows(type);
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/domain/lib/usecase/video/movie_trailer_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/video_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class MovieTrailerUseCase {
6 | final VideoRepository repository;
7 |
8 | MovieTrailerUseCase(this.repository);
9 |
10 | Future getMovieTrailer({required String type, required double id}) {
11 | return repository.getMovieTrailer(type, id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/lib/usecase/video/show_trailer_use_case.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/repository/video_repository.dart';
2 | import 'package:injectable/injectable.dart';
3 |
4 | @injectable
5 | class ShowTrailerUseCase {
6 | final VideoRepository repository;
7 |
8 | ShowTrailerUseCase(this.repository);
9 |
10 | Future getShowTrailer({required String type, required double id}) {
11 | return repository.getShowTrailer(type, id);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/domain/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: domain
2 | description: A new flutter module project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | #
15 | # This version is used _only_ for the Runner app, which is used if you just do
16 | # a `flutter run` or a `flutter make-host-app-editable`. It has no impact
17 | # on any other native host app that you embed your Flutter project into.
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.12.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 | # The following adds the Cupertino Icons font to your application.
28 | # Use with the CupertinoIcons class for iOS style icons.
29 | cupertino_icons: ^1.0.0
30 | injectable: ^1.2.2
31 | get_it: ^6.0.0
32 |
33 | dev_dependencies:
34 | flutter_test:
35 | sdk: flutter
36 | injectable_generator: 1.2.2
37 | build_runner: 1.12.2
38 |
39 | # For information on the generic Dart part of this file, see the
40 | # following page: https://dart.dev/tools/pub/pubspec
41 |
42 | flutter:
43 | # The following line ensures that the Material Icons font is
44 | # included with your application, so that you can use the icons in
45 | # the material Icons class.
46 | uses-material-design: true
47 |
48 | # To add Flutter specific assets to your application, add an assets section,
49 | # like this:
50 | # assets:
51 | # - images/a_dot_burr.jpeg
52 | # - images/a_dot_ham.jpeg
53 |
54 | # An image asset can refer to one or more resolution-specific "variants", see
55 | # https://flutter.dev/assets-and-images/#resolution-aware.
56 |
57 | # For details regarding adding assets from package dependencies, see
58 | # https://flutter.dev/assets-and-images/#from-packages
59 |
60 | # To add Flutter specific custom fonts to your application, add a fonts
61 | # section here, in this "flutter" section. Each entry in this list should
62 | # have a "family" key with the font family name, and a "fonts" key with a
63 | # list giving the asset and other descriptors for the font. For
64 | # example:
65 | # fonts:
66 | # - family: Schyler
67 | # fonts:
68 | # - asset: fonts/Schyler-Regular.ttf
69 | # - asset: fonts/Schyler-Italic.ttf
70 | # style: italic
71 | # - family: Trajan Pro
72 | # fonts:
73 | # - asset: fonts/TrajanPro.ttf
74 | # - asset: fonts/TrajanPro_Bold.ttf
75 | # weight: 700
76 | #
77 | # For details regarding fonts from package dependencies,
78 | # see https://flutter.dev/custom-fonts/#from-packages
79 |
80 |
81 | # This section identifies your Flutter project as a module meant for
82 | # embedding in a native host app. These identifiers should _not_ ordinarily
83 | # be changed after generation - they are used to ensure that the tooling can
84 | # maintain consistency when adding or modifying assets and plugins.
85 | # They also do not have any bearing on your native host application's
86 | # identifiers, which may be completely independent or the same as these.
87 | module:
88 | androidX: true
89 | androidPackage: com.ruben.funbox.domain
90 | iosBundleIdentifier: com.ruben.funbox.domain
91 |
--------------------------------------------------------------------------------
/fonts/ironclad.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/fonts/ironclad.ttf
--------------------------------------------------------------------------------
/fonts/metropolis.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/fonts/metropolis.otf
--------------------------------------------------------------------------------
/fun_box.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/images/error_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/images/error_image.png
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | *.mode1v3
2 | *.mode2v3
3 | *.moved-aside
4 | *.pbxuser
5 | *.perspectivev3
6 | **/*sync/
7 | .sconsign.dblite
8 | .tags*
9 | **/.vagrant/
10 | **/DerivedData/
11 | Icon?
12 | **/Pods/
13 | **/.symlinks/
14 | profile
15 | xcuserdata
16 | **/.generated/
17 | Flutter/App.framework
18 | Flutter/Flutter.framework
19 | Flutter/Flutter.podspec
20 | Flutter/Generated.xcconfig
21 | Flutter/app.flx
22 | Flutter/app.zip
23 | Flutter/flutter_assets/
24 | Flutter/flutter_export_environment.sh
25 | ServiceDefinitions.json
26 | Runner/GeneratedPluginRegistrant.*
27 |
28 | # Exceptions to above rules.
29 | !default.mode1v3
30 | !default.mode2v3
31 | !default.pbxuser
32 | !default.perspectivev3
33 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 8.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include "Generated.xcconfig"
2 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
39 |
40 |
41 |
42 |
43 |
44 |
54 |
56 |
62 |
63 |
64 |
65 |
66 |
67 |
73 |
75 |
81 |
82 |
83 |
84 |
86 |
87 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "20x20",
5 | "idiom" : "iphone",
6 | "filename" : "Icon-App-20x20@2x.png",
7 | "scale" : "2x"
8 | },
9 | {
10 | "size" : "20x20",
11 | "idiom" : "iphone",
12 | "filename" : "Icon-App-20x20@3x.png",
13 | "scale" : "3x"
14 | },
15 | {
16 | "size" : "29x29",
17 | "idiom" : "iphone",
18 | "filename" : "Icon-App-29x29@1x.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "29x29",
23 | "idiom" : "iphone",
24 | "filename" : "Icon-App-29x29@2x.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "29x29",
29 | "idiom" : "iphone",
30 | "filename" : "Icon-App-29x29@3x.png",
31 | "scale" : "3x"
32 | },
33 | {
34 | "size" : "40x40",
35 | "idiom" : "iphone",
36 | "filename" : "Icon-App-40x40@2x.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "40x40",
41 | "idiom" : "iphone",
42 | "filename" : "Icon-App-40x40@3x.png",
43 | "scale" : "3x"
44 | },
45 | {
46 | "size" : "60x60",
47 | "idiom" : "iphone",
48 | "filename" : "Icon-App-60x60@2x.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "60x60",
53 | "idiom" : "iphone",
54 | "filename" : "Icon-App-60x60@3x.png",
55 | "scale" : "3x"
56 | },
57 | {
58 | "size" : "20x20",
59 | "idiom" : "ipad",
60 | "filename" : "Icon-App-20x20@1x.png",
61 | "scale" : "1x"
62 | },
63 | {
64 | "size" : "20x20",
65 | "idiom" : "ipad",
66 | "filename" : "Icon-App-20x20@2x.png",
67 | "scale" : "2x"
68 | },
69 | {
70 | "size" : "29x29",
71 | "idiom" : "ipad",
72 | "filename" : "Icon-App-29x29@1x.png",
73 | "scale" : "1x"
74 | },
75 | {
76 | "size" : "29x29",
77 | "idiom" : "ipad",
78 | "filename" : "Icon-App-29x29@2x.png",
79 | "scale" : "2x"
80 | },
81 | {
82 | "size" : "40x40",
83 | "idiom" : "ipad",
84 | "filename" : "Icon-App-40x40@1x.png",
85 | "scale" : "1x"
86 | },
87 | {
88 | "size" : "40x40",
89 | "idiom" : "ipad",
90 | "filename" : "Icon-App-40x40@2x.png",
91 | "scale" : "2x"
92 | },
93 | {
94 | "size" : "76x76",
95 | "idiom" : "ipad",
96 | "filename" : "Icon-App-76x76@1x.png",
97 | "scale" : "1x"
98 | },
99 | {
100 | "size" : "76x76",
101 | "idiom" : "ipad",
102 | "filename" : "Icon-App-76x76@2x.png",
103 | "scale" : "2x"
104 | },
105 | {
106 | "size" : "83.5x83.5",
107 | "idiom" : "ipad",
108 | "filename" : "Icon-App-83.5x83.5@2x.png",
109 | "scale" : "2x"
110 | },
111 | {
112 | "size" : "1024x1024",
113 | "idiom" : "ios-marketing",
114 | "filename" : "Icon-App-1024x1024@1x.png",
115 | "scale" : "1x"
116 | }
117 | ],
118 | "info" : {
119 | "version" : 1,
120 | "author" : "xcode"
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/ios/Runner/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ios/Runner/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | fun_box
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | $(FLUTTER_BUILD_NAME)
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(FLUTTER_BUILD_NUMBER)
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UISupportedInterfaceOrientations
30 |
31 | UIInterfaceOrientationPortrait
32 | UIInterfaceOrientationLandscapeLeft
33 | UIInterfaceOrientationLandscapeRight
34 |
35 | UISupportedInterfaceOrientations~ipad
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationPortraitUpsideDown
39 | UIInterfaceOrientationLandscapeLeft
40 | UIInterfaceOrientationLandscapeRight
41 |
42 | UIViewControllerBasedStatusBarAppearance
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/lib/bloc/all/trending_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:domain/model/trending_people_record.dart';
3 | import 'package:flutter/cupertino.dart';
4 | import 'package:flutter_bloc/flutter_bloc.dart';
5 | import 'package:domain/usecase/trending/trending_movies_use_case.dart';
6 | import 'package:domain/usecase/trending/trending_people_use_case.dart';
7 | import 'package:domain/usecase/trending/trending_shows_use_case.dart';
8 | import 'package:fun_box/utils/app_constants.dart';
9 | import 'package:injectable/injectable.dart';
10 | import 'trending_event.dart';
11 | import 'trending_state.dart';
12 |
13 | @injectable
14 | class TrendingBloc extends Bloc {
15 | final TrendingMoviesUseCase trendingMoviesUseCase;
16 | final TrendingShowsUseCase trendingShowsUseCase;
17 | final TrendingPeopleUseCase trendingPeopleUseCase;
18 |
19 | TrendingBloc(this.trendingMoviesUseCase, this.trendingShowsUseCase,
20 | this.trendingPeopleUseCase)
21 | : super(InitialTrendingMoviesShowsState());
22 |
23 | @override
24 | Stream mapEventToState(TrendingEvent event) async* {
25 | switch (event) {
26 | case TrendingEvent.movie:
27 | yield* _fetchTrendingMovies(AppConstants.movie);
28 | break;
29 | case TrendingEvent.tv:
30 | yield* _fetchTrendingShows(AppConstants.tvShow);
31 | break;
32 | case TrendingEvent.person:
33 | yield* _fetchTrendingPeople(AppConstants.person);
34 | break;
35 | default:
36 | break;
37 | }
38 | }
39 |
40 | Stream _fetchTrendingMovies(String type) async* {
41 | try {
42 | var response = await trendingMoviesUseCase.getTrendingMovies(type: type);
43 | yield SuccessTrendingMoviesState(MoviesShowsRecord.fromJson(response));
44 | } catch (exception) {
45 | debugPrint('Error ${exception.toString()}');
46 | yield ErrorMoviesShowsState();
47 | }
48 | }
49 |
50 | Stream _fetchTrendingShows(String type) async* {
51 | try {
52 | var response = await trendingShowsUseCase.getTrendingShows(type: type);
53 | yield SuccessTrendingShowsState(MoviesShowsRecord.fromJson(response));
54 | } catch (exception) {
55 | debugPrint('Error ${exception.toString()}');
56 | yield ErrorMoviesShowsState();
57 | }
58 | }
59 |
60 | Stream _fetchTrendingPeople(String type) async* {
61 | try {
62 | var response = await trendingPeopleUseCase.getTrendingPeople(type: type);
63 | yield SuccessTrendingPersonState(TrendingPeopleRecord.fromJson(response));
64 | } catch (exception) {
65 | debugPrint('Error ${exception.toString()}');
66 | yield ErrorMoviesShowsState();
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/lib/bloc/all/trending_event.dart:
--------------------------------------------------------------------------------
1 | enum TrendingEvent {
2 | movie,
3 | tv,
4 | person
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/lib/bloc/all/trending_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:domain/model/trending_people_record.dart';
3 |
4 | abstract class TrendingState {}
5 |
6 | class InitialTrendingMoviesShowsState extends TrendingState {}
7 |
8 | class SuccessTrendingMoviesState extends TrendingState {
9 | final MoviesShowsRecord record;
10 |
11 | SuccessTrendingMoviesState(this.record);
12 | }
13 |
14 | class SuccessTrendingShowsState extends TrendingState {
15 | final MoviesShowsRecord record;
16 |
17 | SuccessTrendingShowsState(this.record);
18 | }
19 |
20 | class SuccessTrendingPersonState extends TrendingState {
21 | final TrendingPeopleRecord record;
22 |
23 | SuccessTrendingPersonState(this.record);
24 | }
25 |
26 | class ErrorMoviesShowsState extends TrendingState {}
27 |
--------------------------------------------------------------------------------
/lib/bloc/cast/movie_show_cast_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/cast_record.dart';
2 | import 'package:domain/usecase/cast/movie_cast_use_case.dart';
3 | import 'package:domain/usecase/cast/show_cast_use_case.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter_bloc/flutter_bloc.dart';
6 | import 'package:fun_box/bloc/cast/movie_show_cast_event.dart';
7 | import 'package:fun_box/bloc/cast/movie_show_cast_state.dart';
8 | import 'package:fun_box/utils/app_constants.dart';
9 | import 'package:injectable/injectable.dart';
10 |
11 | @injectable
12 | class MovieShowCastBloc extends Bloc {
13 | final MovieCastUseCase movieCastUseCase;
14 | final ShowCastUseCase showCastUseCase;
15 |
16 | MovieShowCastBloc(this.movieCastUseCase, this.showCastUseCase)
17 | : super(InitialMovieShowCastState());
18 |
19 | @override
20 | Stream mapEventToState(MovieShowCastEvent event) async* {
21 | switch (event.type) {
22 | case AppConstants.movie:
23 | yield* _fetchMovieCast(event.type, event.id);
24 | break;
25 | case AppConstants.tvShow:
26 | yield* _fetchShowCast(event.type, event.id);
27 | break;
28 | default:
29 | break;
30 | }
31 | }
32 |
33 | Stream _fetchMovieCast(String type, double id) async* {
34 | try {
35 | var response = await movieCastUseCase.getMovieCast(type: type, id: id);
36 | yield SuccessMovieShowCastState(CastRecord.fromJson(response));
37 | } catch (exception) {
38 | debugPrint('Error ${exception.toString()}');
39 | yield ErrorMovieShowCastState();
40 | }
41 | }
42 |
43 | Stream _fetchShowCast(String type, double id) async* {
44 | try {
45 | var response = await showCastUseCase.getShowCast(type: type, id: id);
46 | yield SuccessMovieShowCastState(CastRecord.fromJson(response));
47 | } catch (exception) {
48 | debugPrint('Error ${exception.toString()}');
49 | yield ErrorMovieShowCastState();
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/lib/bloc/cast/movie_show_cast_event.dart:
--------------------------------------------------------------------------------
1 | class MovieShowCastEvent {
2 | final String type;
3 | final double id;
4 |
5 | MovieShowCastEvent({required this.type, required this.id});
6 | }
7 |
--------------------------------------------------------------------------------
/lib/bloc/cast/movie_show_cast_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/cast_record.dart';
2 |
3 | abstract class MovieShowCastState {}
4 |
5 | class InitialMovieShowCastState extends MovieShowCastState {}
6 |
7 | class SuccessMovieShowCastState extends MovieShowCastState {
8 | final CastRecord record;
9 |
10 | SuccessMovieShowCastState(this.record);
11 | }
12 |
13 | class ErrorMovieShowCastState extends MovieShowCastState {}
14 |
--------------------------------------------------------------------------------
/lib/bloc/details/movie_show_details_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movie_details_record.dart';
2 | import 'package:domain/model/show_details_record.dart';
3 | import 'package:domain/usecase/details/movie_details_use_case.dart';
4 | import 'package:domain/usecase/details/show_details_use_case.dart';
5 | import 'package:flutter/cupertino.dart';
6 | import 'package:flutter_bloc/flutter_bloc.dart';
7 | import 'package:fun_box/bloc/details/movie_show_details_event.dart';
8 | import 'package:fun_box/bloc/details/movie_show_details_state.dart';
9 | import 'package:fun_box/utils/app_constants.dart';
10 | import 'package:injectable/injectable.dart';
11 |
12 | @injectable
13 | class MovieShowDetailsBloc
14 | extends Bloc {
15 | final MovieDetailsUseCase movieDetailsUseCase;
16 | final ShowDetailsUseCase showDetailsUseCase;
17 |
18 | MovieShowDetailsBloc(this.movieDetailsUseCase, this.showDetailsUseCase)
19 | : super(InitialMovieShowDetailsState());
20 |
21 | @override
22 | Stream mapEventToState(
23 | MovieShowDetailsEvent event) async* {
24 | switch (event.type) {
25 | case AppConstants.movie:
26 | yield* _fetchMovieDetail(event.type, event.id);
27 | break;
28 | case AppConstants.tvShow:
29 | yield* _fetchShowDetail(event.type, event.id);
30 | break;
31 | default:
32 | break;
33 | }
34 | }
35 |
36 | Stream _fetchMovieDetail(
37 | String type, double id) async* {
38 | try {
39 | var response = await movieDetailsUseCase.getMovieDetails(type: type, id: id);
40 | yield SuccessMovieDetailsState(MovieDetailsRecord.fromJson(response));
41 | } catch (exception) {
42 | debugPrint('Error ${exception.toString()}');
43 | yield ErrorMovieShowDetailsState();
44 | }
45 | }
46 |
47 | Stream _fetchShowDetail(
48 | String type, double id) async* {
49 | try {
50 | var response = await showDetailsUseCase.getShowDetails(type: type, id: id);
51 | yield SuccessShowDetailsState(ShowDetailsRecord.fromJson(response));
52 | } catch (exception) {
53 | debugPrint('Error ${exception.toString()}');
54 | yield ErrorMovieShowDetailsState();
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/bloc/details/movie_show_details_event.dart:
--------------------------------------------------------------------------------
1 | class MovieShowDetailsEvent {
2 | final String type;
3 | final double id;
4 |
5 | MovieShowDetailsEvent({required this.type, required this.id});
6 | }
7 |
--------------------------------------------------------------------------------
/lib/bloc/details/movie_show_details_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movie_details_record.dart';
2 | import 'package:domain/model/show_details_record.dart';
3 |
4 | abstract class MovieShowDetailsState {}
5 |
6 | class InitialMovieShowDetailsState extends MovieShowDetailsState {}
7 |
8 | class SuccessMovieDetailsState extends MovieShowDetailsState {
9 | final MovieDetailsRecord record;
10 |
11 | SuccessMovieDetailsState(this.record);
12 | }
13 |
14 | class SuccessShowDetailsState extends MovieShowDetailsState {
15 | final ShowDetailsRecord record;
16 |
17 | SuccessShowDetailsState(this.record);
18 | }
19 |
20 | class ErrorMovieShowDetailsState extends MovieShowDetailsState {}
21 |
--------------------------------------------------------------------------------
/lib/bloc/filter/movies_shows_filter_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movie_show_genres_record.dart';
2 | import 'package:domain/usecase/filter/movie_filter_use_case.dart';
3 | import 'package:domain/usecase/filter/show_filter_use_case.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter_bloc/flutter_bloc.dart';
6 | import 'package:fun_box/bloc/filter/movies_shows_filter_event.dart';
7 | import 'package:fun_box/bloc/filter/movies_shows_filter_state.dart';
8 | import 'package:fun_box/utils/app_constants.dart';
9 | import 'package:injectable/injectable.dart';
10 |
11 | @injectable
12 | class MoviesShowsFilterBloc
13 | extends Bloc {
14 | final MovieFilterUseCase movieFilterUseCase;
15 | final ShowFilterUseCase showFilterUseCase;
16 |
17 | MoviesShowsFilterBloc(this.movieFilterUseCase, this.showFilterUseCase)
18 | : super(InitialMoviesShowsFilterState());
19 |
20 | @override
21 | Stream mapEventToState(
22 | MoviesShowsFilterEvent event) async* {
23 | switch (event.type) {
24 | case AppConstants.movie:
25 | yield* _fetchMovieFilters(event.type);
26 | break;
27 | case AppConstants.tvShow:
28 | yield* _fetchShowFilters(event.type);
29 | break;
30 | default:
31 | break;
32 | }
33 | }
34 |
35 | Stream _fetchMovieFilters(String type) async* {
36 | try {
37 | var response = await movieFilterUseCase.getMovieGenres(type: type);
38 | yield SuccessMoviesShowsFilterState(
39 | MovieShowGenresRecord.fromJson(response));
40 | } catch (exception) {
41 | debugPrint('Error ${exception.toString()}');
42 | yield ErrorMoviesShowsFilterState();
43 | }
44 | }
45 |
46 | Stream _fetchShowFilters(String type) async* {
47 | try {
48 | var response = await showFilterUseCase.getShowGenres(type: type);
49 | yield SuccessMoviesShowsFilterState(
50 | MovieShowGenresRecord.fromJson(response));
51 | } catch (exception) {
52 | debugPrint('Error ${exception.toString()}');
53 | yield ErrorMoviesShowsFilterState();
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/lib/bloc/filter/movies_shows_filter_event.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsFilterEvent {
2 | final String type;
3 |
4 | MoviesShowsFilterEvent({required this.type});
5 | }
6 |
--------------------------------------------------------------------------------
/lib/bloc/filter/movies_shows_filter_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movie_show_genres_record.dart';
2 |
3 | abstract class MoviesShowsFilterState {}
4 |
5 | class InitialMoviesShowsFilterState extends MoviesShowsFilterState {}
6 |
7 | class SuccessMoviesShowsFilterState extends MoviesShowsFilterState {
8 | final MovieShowGenresRecord record;
9 |
10 | SuccessMoviesShowsFilterState(this.record);
11 | }
12 |
13 | class ErrorMoviesShowsFilterState extends MoviesShowsFilterState {}
14 |
--------------------------------------------------------------------------------
/lib/bloc/movieshow/movies_shows_event.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsEvent {
2 | final String type;
3 | final String event;
4 | final int page;
5 |
6 | MoviesShowsEvent(
7 | {required this.type, required this.event, required this.page});
8 | }
9 |
--------------------------------------------------------------------------------
/lib/bloc/movieshow/movies_shows_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 |
3 | abstract class MoviesShowsState {}
4 |
5 | class InitialMoviesShowsState extends MoviesShowsState {}
6 |
7 | class SuccessMoviesShowsState extends MoviesShowsState {
8 | final MoviesShowsRecord record;
9 |
10 | SuccessMoviesShowsState(this.record);
11 | }
12 |
13 | class ErrorMoviesShowsState extends MoviesShowsState {}
14 |
--------------------------------------------------------------------------------
/lib/bloc/person/person_details_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/person_credits_record.dart';
2 | import 'package:domain/model/person_info_record.dart';
3 | import 'package:domain/usecase/person/person_credits_use_case.dart';
4 | import 'package:domain/usecase/person/person_info_use_case.dart';
5 | import 'package:flutter/cupertino.dart';
6 | import 'package:flutter_bloc/flutter_bloc.dart';
7 | import 'package:fun_box/bloc/person/person_details_event.dart';
8 | import 'package:fun_box/bloc/person/person_details_state.dart';
9 | import 'package:fun_box/utils/app_constants.dart';
10 | import 'package:injectable/injectable.dart';
11 |
12 | @injectable
13 | class PersonDetailsBloc extends Bloc {
14 | final PersonInfoUseCase personInfoUseCase;
15 | final PersonCreditsUseCase personCreditsUseCase;
16 |
17 | PersonDetailsBloc(this.personInfoUseCase, this.personCreditsUseCase)
18 | : super(InitialPersonDetailsState());
19 |
20 | @override
21 | Stream mapEventToState(PersonDetailsEvent event) async* {
22 | switch (event.type) {
23 | case AppConstants.personalInfo:
24 | yield* _fetchPersonalInfo(event.id);
25 | break;
26 | case AppConstants.credits:
27 | yield* _fetchCredits(event.id);
28 | break;
29 | default:
30 | break;
31 | }
32 | }
33 |
34 | Stream _fetchPersonalInfo(double id) async* {
35 | try {
36 | var response = await personInfoUseCase.getPersonIfo(id: id);
37 | yield SuccessPersonInfoState(PersonInfoRecord.fromJson(response));
38 | } catch (exception) {
39 | debugPrint('Error ${exception.toString()}');
40 | yield ErrorPersonDetailsState();
41 | }
42 | }
43 |
44 | Stream _fetchCredits(double id) async* {
45 | try {
46 | var response = await personCreditsUseCase.getPersonCredits(id: id);
47 | yield SuccessPersonCreditsState(PersonCreditsRecord.fromJson(response));
48 | } catch (exception) {
49 | debugPrint('Error ${exception.toString()}');
50 | yield ErrorPersonDetailsState();
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/lib/bloc/person/person_details_event.dart:
--------------------------------------------------------------------------------
1 | class PersonDetailsEvent {
2 | final String type;
3 | final double id;
4 |
5 | PersonDetailsEvent({required this.type, required this.id});
6 | }
7 |
--------------------------------------------------------------------------------
/lib/bloc/person/person_details_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/person_credits_record.dart';
2 | import 'package:domain/model/person_info_record.dart';
3 |
4 | abstract class PersonDetailsState {}
5 |
6 | class InitialPersonDetailsState extends PersonDetailsState {}
7 |
8 | class SuccessPersonInfoState extends PersonDetailsState {
9 | final PersonInfoRecord record;
10 |
11 | SuccessPersonInfoState(this.record);
12 | }
13 |
14 | class SuccessPersonCreditsState extends PersonDetailsState {
15 | final PersonCreditsRecord record;
16 |
17 | SuccessPersonCreditsState(this.record);
18 | }
19 |
20 | class ErrorPersonDetailsState extends PersonDetailsState {}
21 |
--------------------------------------------------------------------------------
/lib/bloc/search/movies_shows_search_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/search/movies_shows_search_event.dart';
5 | import 'package:fun_box/bloc/search/movies_shows_search_state.dart';
6 | import 'package:fun_box/utils/app_constants.dart';
7 | import 'package:injectable/injectable.dart';
8 | import 'package:domain/usecase/search_movies_shows_use_case.dart';
9 |
10 | @injectable
11 | class MoviesShowsSearchBloc
12 | extends Bloc {
13 | final SearchMoviesShowsUseCase searchMoviesShowsUseCase;
14 |
15 | MoviesShowsSearchBloc(this.searchMoviesShowsUseCase)
16 | : super(InitialMoviesShowsSearchState());
17 |
18 | @override
19 | Stream mapEventToState(
20 | MoviesShowsSearchEvent event) async* {
21 | switch (event.event) {
22 | case AppConstants.suggestions:
23 | yield* _fetchSuggestions(event.searchTerm);
24 | break;
25 | case AppConstants.progress:
26 | yield* _showProgress();
27 | break;
28 | default:
29 | break;
30 | }
31 | }
32 |
33 | Stream _showProgress() async* {
34 | yield ProgressMoviesShowsSearchState();
35 | }
36 |
37 | Stream _fetchSuggestions(String searchTerm) async* {
38 | try {
39 | var response = await searchMoviesShowsUseCase.searchMoviesShows(
40 | searchTerm: searchTerm);
41 | yield SuccessSuggestionsMoviesShowsState(
42 | MoviesShowsRecord.fromJson(response));
43 | } catch (exception) {
44 | debugPrint('Error ${exception.toString()}');
45 | yield ErrorMoviesShowsSearchState();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/lib/bloc/search/movies_shows_search_event.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsSearchEvent {
2 | String event;
3 | String searchTerm;
4 |
5 | MoviesShowsSearchEvent({required this.event, required this.searchTerm});
6 | }
7 |
--------------------------------------------------------------------------------
/lib/bloc/search/movies_shows_search_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 |
3 | abstract class MoviesShowsSearchState {}
4 |
5 | class InitialMoviesShowsSearchState extends MoviesShowsSearchState {}
6 |
7 | class ProgressMoviesShowsSearchState extends MoviesShowsSearchState {}
8 |
9 | class SuccessSuggestionsMoviesShowsState extends MoviesShowsSearchState {
10 | final MoviesShowsRecord record;
11 |
12 | SuccessSuggestionsMoviesShowsState(this.record);
13 | }
14 |
15 | class ErrorMoviesShowsSearchState extends MoviesShowsSearchState {}
16 |
--------------------------------------------------------------------------------
/lib/bloc/video/movie_show_trailer_bloc.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/trailer_record.dart';
2 | import 'package:domain/usecase/video/movie_trailer_use_case.dart';
3 | import 'package:domain/usecase/video/show_trailer_use_case.dart';
4 | import 'package:flutter/cupertino.dart';
5 | import 'package:flutter_bloc/flutter_bloc.dart';
6 | import 'package:fun_box/bloc/video/movie_show_trailer_event.dart';
7 | import 'package:fun_box/bloc/video/movie_show_trailer_state.dart';
8 | import 'package:fun_box/utils/app_constants.dart';
9 | import 'package:injectable/injectable.dart';
10 |
11 | @injectable
12 | class MovieShowTrailerBloc
13 | extends Bloc {
14 | final MovieTrailerUseCase movieTrailerUseCase;
15 | final ShowTrailerUseCase showTrailerUseCase;
16 |
17 | MovieShowTrailerBloc(this.movieTrailerUseCase, this.showTrailerUseCase)
18 | : super(InitialMovieShowTrailerState());
19 |
20 | @override
21 | Stream mapEventToState(
22 | MovieShowTrailerEvent event) async* {
23 | switch (event.type) {
24 | case AppConstants.movie:
25 | yield* _fetchMovieTrailer(event.type, event.id);
26 | break;
27 | case AppConstants.tvShow:
28 | yield* _fetchTvShowTrailer(event.type, event.id);
29 | break;
30 | default:
31 | break;
32 | }
33 | }
34 |
35 | Stream _fetchMovieTrailer(
36 | String type, double id) async* {
37 | try {
38 | var response =
39 | await movieTrailerUseCase.getMovieTrailer(type: type, id: id);
40 | yield SuccessMovieShowTrailerState(TrailerRecord.fromJson(response));
41 | } catch (exception) {
42 | debugPrint('Error ${exception.toString()}');
43 | yield ErrorMovieShowTrailerState();
44 | }
45 | }
46 |
47 | Stream _fetchTvShowTrailer(
48 | String type, double id) async* {
49 | try {
50 | var response =
51 | await showTrailerUseCase.getShowTrailer(type: type, id: id);
52 | yield SuccessMovieShowTrailerState(TrailerRecord.fromJson(response));
53 | } catch (exception) {
54 | debugPrint('Error ${exception.toString()}');
55 | yield ErrorMovieShowTrailerState();
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/bloc/video/movie_show_trailer_event.dart:
--------------------------------------------------------------------------------
1 | class MovieShowTrailerEvent {
2 | final String type;
3 | final double id;
4 |
5 | MovieShowTrailerEvent({required this.type, required this.id});
6 | }
7 |
--------------------------------------------------------------------------------
/lib/bloc/video/movie_show_trailer_state.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/trailer_record.dart';
2 |
3 | abstract class MovieShowTrailerState {}
4 |
5 | class InitialMovieShowTrailerState extends MovieShowTrailerState {}
6 |
7 | class SuccessMovieShowTrailerState extends MovieShowTrailerState {
8 | final TrailerRecord record;
9 |
10 | SuccessMovieShowTrailerState(this.record);
11 | }
12 |
13 | class ErrorMovieShowTrailerState extends MovieShowTrailerState {}
14 |
--------------------------------------------------------------------------------
/lib/config/configurations.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 | import 'package:fun_box/config/default_config.dart';
3 | import 'package:fun_box/utils/app_constants.dart';
4 | import 'package:get_it/get_it.dart';
5 | import 'package:domain/model/config_record.dart';
6 | import 'package:domain/usecase/get_config_use_case.dart';
7 |
8 | class Configurations {
9 | static String _configStatus = AppConstants.localConfig;
10 | static String _imageUrl = DefaultConfig.secureImageUrl;
11 | static String _imageSize = DefaultConfig.imageSize;
12 |
13 | final GetConfigUseCase _useCase = GetIt.instance.get();
14 |
15 | Future getConfig() async {
16 | try {
17 | var response = await _useCase.getConfig();
18 | var config = ConfigRecord.fromJson(response);
19 | var imageLength = 0;
20 | _configStatus = AppConstants.remoteConfig;
21 | _imageUrl = config.images?.secureBaseUrl ?? DefaultConfig.secureImageUrl;
22 | if (config.images?.logoSizes != null) {
23 | imageLength = config.images?.logoSizes!.length ?? 0;
24 | if (imageLength > 0) {
25 | _imageSize = config.images?.logoSizes![imageLength - 2] ??
26 | DefaultConfig.imageSize;
27 | }
28 | }
29 | } catch (exception) {
30 | debugPrint('Error ${exception.toString()}');
31 | }
32 | }
33 |
34 | static String get configStatus => _configStatus;
35 |
36 | static String get imageUrl => _imageUrl;
37 |
38 | static String get imageSize => _imageSize;
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/lib/config/default_config.dart:
--------------------------------------------------------------------------------
1 | class DefaultConfig {
2 | static const baseUrl = 'https://api.themoviedb.org/3';
3 | static const imageUrl = 'http://image.tmdb.org/t/p/';
4 | static const secureImageUrl = 'https://image.tmdb.org/t/p/';
5 | static const imageSize = 'w500';
6 | }
--------------------------------------------------------------------------------
/lib/di/di.config.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | // **************************************************************************
4 | // InjectableConfigGenerator
5 | // **************************************************************************
6 |
7 | import 'package:domain/usecase/cast/movie_cast_use_case.dart' as _i4;
8 | import 'package:domain/usecase/cast/show_cast_use_case.dart' as _i5;
9 | import 'package:domain/usecase/details/movie_details_use_case.dart' as _i7;
10 | import 'package:domain/usecase/details/show_details_use_case.dart' as _i8;
11 | import 'package:domain/usecase/filter/movie_filter_use_case.dart' as _i26;
12 | import 'package:domain/usecase/filter/show_filter_use_case.dart' as _i27;
13 | import 'package:domain/usecase/movies/current_playing_movies_use_case.dart'
14 | as _i13;
15 | import 'package:domain/usecase/movies/latest_movies_use_case.dart' as _i15;
16 | import 'package:domain/usecase/movies/movies_by_genres_use_case.dart' as _i18;
17 | import 'package:domain/usecase/movies/popular_movies_use_case.dart' as _i14;
18 | import 'package:domain/usecase/movies/top_rated_movies_use_case.dart' as _i16;
19 | import 'package:domain/usecase/movies/upcoming_movies_use_case.dart' as _i17;
20 | import 'package:domain/usecase/person/person_credits_use_case.dart' as _i32;
21 | import 'package:domain/usecase/person/person_info_use_case.dart' as _i31;
22 | import 'package:domain/usecase/search_movies_shows_use_case.dart' as _i29;
23 | import 'package:domain/usecase/shows/airing_today_shows_use_case.dart' as _i23;
24 | import 'package:domain/usecase/shows/current_playing_shows_use_case.dart'
25 | as _i19;
26 | import 'package:domain/usecase/shows/latest_shows_use_case.dart' as _i21;
27 | import 'package:domain/usecase/shows/popular_shows_use_case.dart' as _i20;
28 | import 'package:domain/usecase/shows/shows_by_genres_use_case.dart' as _i24;
29 | import 'package:domain/usecase/shows/top_rated_shows_use_case.dart' as _i22;
30 | import 'package:domain/usecase/trending/trending_movies_use_case.dart' as _i34;
31 | import 'package:domain/usecase/trending/trending_people_use_case.dart' as _i36;
32 | import 'package:domain/usecase/trending/trending_shows_use_case.dart' as _i35;
33 | import 'package:domain/usecase/video/movie_trailer_use_case.dart' as _i10;
34 | import 'package:domain/usecase/video/show_trailer_use_case.dart' as _i11;
35 | import 'package:get_it/get_it.dart' as _i1;
36 | import 'package:injectable/injectable.dart' as _i2;
37 |
38 | import '../bloc/all/trending_bloc.dart' as _i33;
39 | import '../bloc/cast/movie_show_cast_bloc.dart' as _i3;
40 | import '../bloc/details/movie_show_details_bloc.dart' as _i6;
41 | import '../bloc/filter/movies_shows_filter_bloc.dart' as _i25;
42 | import '../bloc/movieshow/movies_shows_bloc.dart' as _i12;
43 | import '../bloc/person/person_details_bloc.dart' as _i30;
44 | import '../bloc/search/movies_shows_search_bloc.dart' as _i28;
45 | import '../bloc/video/movie_show_trailer_bloc.dart'
46 | as _i9; // ignore_for_file: unnecessary_lambdas
47 |
48 | // ignore_for_file: lines_longer_than_80_chars
49 | /// initializes the registration of provided dependencies inside of [GetIt]
50 | _i1.GetIt $initGetIt(_i1.GetIt get,
51 | {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
52 | final gh = _i2.GetItHelper(get, environment, environmentFilter);
53 | gh.factory<_i3.MovieShowCastBloc>(() => _i3.MovieShowCastBloc(
54 | get<_i4.MovieCastUseCase>(), get<_i5.ShowCastUseCase>()));
55 | gh.factory<_i6.MovieShowDetailsBloc>(() => _i6.MovieShowDetailsBloc(
56 | get<_i7.MovieDetailsUseCase>(), get<_i8.ShowDetailsUseCase>()));
57 | gh.factory<_i9.MovieShowTrailerBloc>(() => _i9.MovieShowTrailerBloc(
58 | get<_i10.MovieTrailerUseCase>(), get<_i11.ShowTrailerUseCase>()));
59 | gh.factory<_i12.MoviesShowsBloc>(() => _i12.MoviesShowsBloc(
60 | get<_i13.CurrentPlayingMoviesUseCase>(),
61 | get<_i14.PopularMoviesUseCase>(),
62 | get<_i15.LatestMoviesUseCase>(),
63 | get<_i16.TopRatedMoviesUseCase>(),
64 | get<_i17.UpcomingMoviesUseCase>(),
65 | get<_i18.MoviesByGenresUseCase>(),
66 | get<_i19.CurrentPlayingShowsUseCase>(),
67 | get<_i20.PopularShowsUseCase>(),
68 | get<_i21.LatestShowsUseCase>(),
69 | get<_i22.TopRatedShowsUseCase>(),
70 | get<_i23.AiringTodayShowsUseCase>(),
71 | get<_i24.ShowsByGenresUseCase>()));
72 | gh.factory<_i25.MoviesShowsFilterBloc>(() => _i25.MoviesShowsFilterBloc(
73 | get<_i26.MovieFilterUseCase>(), get<_i27.ShowFilterUseCase>()));
74 | gh.factory<_i28.MoviesShowsSearchBloc>(
75 | () => _i28.MoviesShowsSearchBloc(get<_i29.SearchMoviesShowsUseCase>()));
76 | gh.factory<_i30.PersonDetailsBloc>(() => _i30.PersonDetailsBloc(
77 | get<_i31.PersonInfoUseCase>(), get<_i32.PersonCreditsUseCase>()));
78 | gh.factory<_i33.TrendingBloc>(() => _i33.TrendingBloc(
79 | get<_i34.TrendingMoviesUseCase>(),
80 | get<_i35.TrendingShowsUseCase>(),
81 | get<_i36.TrendingPeopleUseCase>()));
82 | return get;
83 | }
84 |
--------------------------------------------------------------------------------
/lib/di/di.dart:
--------------------------------------------------------------------------------
1 | import 'package:data/di/di.dart';
2 | import 'package:domain/di/di.dart';
3 | import 'package:fun_box/di/di.config.dart';
4 | import 'package:get_it/get_it.dart';
5 | import 'package:injectable/injectable.dart';
6 | import 'package:remote/di/di.dart';
7 |
8 | final GetIt _getIt = GetIt.instance;
9 |
10 | @InjectableInit(
11 | initializerName: r'$initGetIt'
12 | )
13 | Future configureInjection() async {
14 | configureRemoteInjection(_getIt);
15 | configureDataInjection(_getIt);
16 | configureDomainInjection(_getIt);
17 | $initGetIt(_getIt);
18 | }
--------------------------------------------------------------------------------
/lib/main.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter/services.dart';
3 | import 'package:fun_box/config/configurations.dart';
4 | import 'package:fun_box/di/di.dart';
5 | import 'package:fun_box/presentation/home/home.dart';
6 | import 'package:fun_box/utils/app_navigator_observer.dart';
7 | import 'package:get_it/get_it.dart';
8 |
9 | void main() async {
10 | WidgetsFlutterBinding.ensureInitialized();
11 | GetIt.instance.allowReassignment = true;
12 | await configureInjection();
13 | await Configurations().getConfig();
14 | await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
15 | .then((_) => runApp(MyApp()));
16 | }
17 |
18 | class MyApp extends StatelessWidget {
19 | // This widget is the root of your application.
20 | @override
21 | Widget build(BuildContext context) {
22 | final _observer = AppNavigatorObserver();
23 | return MaterialApp(
24 | title: 'Fun Box',
25 | debugShowCheckedModeBanner: false,
26 | theme: ThemeData(
27 | primarySwatch: Colors.deepOrange,
28 | visualDensity: VisualDensity.adaptivePlatformDensity,
29 | ),
30 | navigatorObservers: [_observer],
31 | home: Home(),
32 | );
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/lib/presentation/common/common_display_tiles.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:fun_box/config/configurations.dart';
4 | import 'package:fun_box/presentation/details/movie_show_details.dart';
5 |
6 | class CommonDisplayTiles extends StatelessWidget {
7 | final double width;
8 | final int itemCount;
9 | final List? results;
10 | final String type;
11 |
12 | CommonDisplayTiles(
13 | {required this.width,
14 | required this.itemCount,
15 | required this.results,
16 | required this.type});
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Container(
21 | height: width / 2,
22 | width: width,
23 | margin: EdgeInsets.only(bottom: 8.0),
24 | child: ListView.builder(
25 | scrollDirection: Axis.horizontal,
26 | itemCount: itemCount,
27 | itemBuilder: (context, index) {
28 | return _trendingMoviesShowsCell(
29 | context,
30 | results?[index].posterPath ?? '',
31 | type,
32 | results?[index].id?.toDouble() ?? 0);
33 | }),
34 | );
35 | }
36 |
37 | Widget _trendingMoviesShowsCell(
38 | BuildContext context, String imagePath, String type, double id) {
39 | return GestureDetector(
40 | onTap: () => _navigateToDetails(context, type, id),
41 | child: Card(
42 | clipBehavior: Clip.antiAliasWithSaveLayer,
43 | elevation: 5.0,
44 | shape: RoundedRectangleBorder(
45 | borderRadius: BorderRadius.all(Radius.circular(10.0))),
46 | child: Image.network(
47 | '${Configurations.imageUrl}/${Configurations.imageSize}$imagePath',
48 | fit: BoxFit.cover,
49 | ),
50 | ),
51 | );
52 | }
53 |
54 | void _navigateToDetails(BuildContext context, String type, double id) {
55 | Navigator.push(context, MaterialPageRoute(builder: (context) {
56 | return MovieShowDetails(
57 | type: type,
58 | id: id,
59 | );
60 | }));
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/lib/presentation/common/common_error_ui.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/ui_constants.dart';
3 |
4 | class ErrorUI extends StatelessWidget {
5 | @override
6 | Widget build(BuildContext context) {
7 | return Center(
8 | child: Column(
9 | children: [
10 | Padding(
11 | padding: EdgeInsets.all(10.0),
12 | child: Image(
13 | image: AssetImage('images/error_image.png'),
14 | width: 125.0,
15 | height: 125.0,
16 | ),
17 | ),
18 | Text(
19 | UIConstants.errorMessage,
20 | style: TextStyle(
21 | fontSize: 14.0,
22 | fontFamily: UIConstants.fontFamilyIronclad,
23 | fontWeight: FontWeight.w400),
24 | )
25 | ],
26 | ),
27 | );
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/presentation/common/common_people_tiles.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/trending_people_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:fun_box/config/configurations.dart';
4 | import 'package:fun_box/presentation/person/person_details.dart';
5 |
6 | class CommonPeopleTiles extends StatelessWidget {
7 | final double radius;
8 | final double width;
9 | final int itemCount;
10 | final List? results;
11 |
12 | CommonPeopleTiles(
13 | {required this.radius,
14 | required this.width,
15 | required this.itemCount,
16 | required this.results});
17 |
18 | @override
19 | Widget build(BuildContext context) {
20 | return Container(
21 | height: width / 2,
22 | width: width,
23 | margin: EdgeInsets.only(top: 8.0, bottom: 8.0),
24 | child: ListView.builder(
25 | scrollDirection: Axis.horizontal,
26 | itemCount: itemCount,
27 | itemBuilder: (context, index) {
28 | return _trendingPeopleCell(
29 | context,
30 | results?[index].profilePath ?? '',
31 | results?[index].id?.toDouble() ?? 0);
32 | }),
33 | );
34 | }
35 |
36 | Widget _trendingPeopleCell(
37 | BuildContext context, String imagePath, double id) {
38 | return GestureDetector(
39 | onTap: () => _navigateToPersonDetails(context, id),
40 | child: Card(
41 | clipBehavior: Clip.antiAliasWithSaveLayer,
42 | elevation: 5.0,
43 | shape: RoundedRectangleBorder(
44 | borderRadius: BorderRadius.all(Radius.circular(10.0))),
45 | child: Image.network(
46 | '${Configurations.imageUrl}/${Configurations.imageSize}$imagePath',
47 | fit: BoxFit.cover,
48 | ),
49 | ),
50 | );
51 | }
52 |
53 | void _navigateToPersonDetails(BuildContext context, double id) {
54 | Navigator.push(context, MaterialPageRoute(builder: (context) {
55 | return PersonDetails(id: id);
56 | }));
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/lib/presentation/common/common_search_bar.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/config/configurations.dart';
3 | import 'package:fun_box/presentation/search/search.dart';
4 | import 'package:fun_box/utils/app_constants.dart';
5 |
6 | import '../ui_constants.dart';
7 |
8 | class CommonSearchBar extends StatelessWidget {
9 | @override
10 | Widget build(BuildContext context) {
11 | return Padding(
12 | padding: EdgeInsets.all(10.0),
13 | child: Theme(
14 | data: ThemeData(primaryColor: Colors.black),
15 | child: TextField(
16 | focusNode: SearchFocusNode(),
17 | style: TextStyle(
18 | fontFamily: UIConstants.fontFamilyIronclad,
19 | fontWeight: FontWeight.w400,
20 | fontSize: 16.0
21 | ),
22 | decoration: InputDecoration(
23 | prefixIcon: Icon(Icons.search),
24 | hintText: UIConstants.searchHint,
25 | border: OutlineInputBorder(
26 | borderRadius: BorderRadius.circular(30.0))),
27 | onTap: () {
28 | Navigator.push(context, MaterialPageRoute(builder: (context) {
29 | return Search();
30 | }));
31 | },
32 | ),
33 | ),
34 | );
35 | }
36 | }
37 |
38 | class SearchFocusNode extends FocusNode {
39 | @override
40 | bool get hasFocus {
41 | return Configurations.configStatus == AppConstants.remoteConfig;
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/lib/presentation/common/common_widgets.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | class CommonProgressBar extends StatelessWidget {
4 | @override
5 | Widget build(BuildContext context) {
6 | return Center(
7 | child: CircularProgressIndicator(),
8 | );
9 | }
10 | }
11 |
12 | class CommonEmptyInit extends StatelessWidget {
13 | @override
14 | Widget build(BuildContext context) {
15 | return SizedBox();
16 | }
17 |
18 | }
--------------------------------------------------------------------------------
/lib/presentation/details/movie_show_details.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/details/widgets/movie_show_cast.dart';
3 | import 'package:fun_box/presentation/details/widgets/movie_show_info.dart';
4 |
5 | class MovieShowDetails extends StatefulWidget {
6 | final String type;
7 | final double id;
8 |
9 | MovieShowDetails({required this.type, required this.id});
10 |
11 | @override
12 | State createState() => _MovieShowDetailsState(type, id);
13 | }
14 |
15 | class _MovieShowDetailsState extends State {
16 | final String type;
17 | final double id;
18 |
19 | _MovieShowDetailsState(this.type, this.id);
20 |
21 | @override
22 | Widget build(BuildContext context) {
23 | return Material(
24 | child: SafeArea(
25 | child: ListView(
26 | shrinkWrap: true,
27 | children: [
28 | MovieShowInfo(type: type, id: id),
29 | Padding(
30 | padding: EdgeInsets.only(top: 24.0, left: 16.0, right: 16.0),
31 | child: MovieShowCast(type: type, id: id),
32 | )
33 | ],
34 | ),
35 | ),
36 | );
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/presentation/filter/filters.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/filter/movies_shows_filters.dart';
3 |
4 | import '../ui_constants.dart';
5 |
6 | class Filters extends StatefulWidget {
7 | final String type;
8 | final String selectedValue;
9 |
10 | Filters({required this.type, required this.selectedValue});
11 |
12 | @override
13 | State createState() => _FiltersState(type, selectedValue);
14 | }
15 |
16 | class _FiltersState extends State {
17 | final String type;
18 | final String selectedValue;
19 |
20 | _FiltersState(this.type, this.selectedValue);
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return Material(
25 | child: SafeArea(
26 | child: Column(
27 | children: [
28 | Container(
29 | decoration: BoxDecoration(
30 | border: Border(
31 | bottom: BorderSide(color: Colors.grey, width: 0.5))),
32 | child: Row(
33 | children: [
34 | GestureDetector(
35 | onTap: () => _navigateToMoviesShows(context),
36 | child: Padding(
37 | padding:
38 | EdgeInsets.only(top: 10.0, bottom: 10.0, left: 10.0),
39 | child: Align(
40 | alignment: Alignment.centerLeft,
41 | child: Icon(
42 | Icons.clear_rounded,
43 | size: 30.0,
44 | ),
45 | ),
46 | ),
47 | ),
48 | Expanded(
49 | child: Padding(
50 | padding:
51 | EdgeInsets.only(top: 10.0, bottom: 10.0, right: 10.0),
52 | child: Center(
53 | child: Text(
54 | UIConstants.filters,
55 | style: TextStyle(
56 | color: Colors.black,
57 | fontSize: 20.0,
58 | fontFamily: UIConstants.fontFamilyIronclad,
59 | fontWeight: FontWeight.w700),
60 | ),
61 | ),
62 | ))
63 | ],
64 | ),
65 | ),
66 | MoviesShowsFilters(type: type, selectedValue: selectedValue)
67 | ],
68 | ),
69 | ),
70 | );
71 | }
72 |
73 | void _navigateToMoviesShows(BuildContext context) {
74 | Navigator.pop(context, '');
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/lib/presentation/home/home.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/common/common_search_bar.dart';
3 | import 'package:fun_box/presentation/home/widgets/trending_movies.dart';
4 | import 'package:fun_box/presentation/home/widgets/trending_people.dart';
5 | import 'package:fun_box/presentation/home/widgets/trending_shows.dart';
6 |
7 | class Home extends StatefulWidget {
8 | @override
9 | State createState() => _HomeState();
10 | }
11 |
12 | class _HomeState extends State {
13 | @override
14 | Widget build(BuildContext context) {
15 | return Material(
16 | child: SafeArea(
17 | child: ListView(
18 | children: [
19 | CommonSearchBar(),
20 | Padding(
21 | padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
22 | child: TrendingMovies(),
23 | ),
24 | Padding(
25 | padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
26 | child: TrendingShows(),
27 | ),
28 | Padding(
29 | padding: EdgeInsets.only(left: 10.0, right: 10.0, bottom: 10.0),
30 | child: TrendingPeople(),
31 | )
32 | ],
33 | )));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/presentation/home/widgets/trending_movies.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/all/trending_bloc.dart';
5 | import 'package:fun_box/bloc/all/trending_event.dart';
6 | import 'package:fun_box/bloc/all/trending_state.dart';
7 | import 'package:fun_box/presentation/common/common_display_tiles.dart';
8 | import 'package:fun_box/presentation/common/common_error_ui.dart';
9 | import 'package:fun_box/presentation/common/common_widgets.dart';
10 | import 'package:fun_box/presentation/movieshow/movies_shows.dart';
11 | import 'package:fun_box/presentation/ui_constants.dart';
12 | import 'package:fun_box/utils/app_constants.dart';
13 | import 'package:get_it/get_it.dart';
14 |
15 | class TrendingMovies extends StatefulWidget {
16 | @override
17 | State createState() => _TrendingMoviesState();
18 | }
19 |
20 | class _TrendingMoviesState extends State {
21 | final TrendingBloc _trendingBloc = GetIt.instance.get();
22 |
23 | @override
24 | void dispose() {
25 | _trendingBloc.close();
26 | super.dispose();
27 | }
28 |
29 | @override
30 | Widget build(BuildContext context) {
31 | BlocProvider(create: (BuildContext context) => _trendingBloc);
32 | _trendingBloc.add(TrendingEvent.movie);
33 | return BlocBuilder(
34 | bloc: _trendingBloc,
35 | builder: (context, state) {
36 | if (state is InitialTrendingMoviesShowsState) {
37 | return _initState();
38 | } else if (state is SuccessTrendingMoviesState) {
39 | return _trendingMovies(context, state.record);
40 | } else if (state is ErrorMoviesShowsState) {
41 | return _error();
42 | } else {
43 | return _error();
44 | }
45 | },
46 | );
47 | }
48 |
49 | Widget _trendingMovies(BuildContext context, MoviesShowsRecord trendingMovies) {
50 | final width = MediaQuery.of(context).size.width;
51 | return Column(
52 | children: [
53 | Padding(
54 | padding: EdgeInsets.only(left: 8.0),
55 | child: Row(
56 | children: [
57 | Text(
58 | UIConstants.trendingMovies,
59 | style: TextStyle(
60 | color: Colors.black,
61 | fontSize: 20.0,
62 | fontFamily: UIConstants.fontFamilyIronclad,
63 | fontWeight: FontWeight.w700),
64 | ),
65 | Expanded(child: SizedBox()),
66 | GestureDetector(
67 | onTap: () => _navigateToMovies(context),
68 | child: Icon(
69 | Icons.arrow_right_alt_rounded,
70 | size: 40.0,
71 | ),
72 | )
73 | ],
74 | ),
75 | ),
76 | CommonDisplayTiles(
77 | width: width,
78 | itemCount: trendingMovies.results?.length ?? 0,
79 | results: trendingMovies.results,
80 | type: AppConstants.movie,
81 | )
82 | ],
83 | );
84 | }
85 |
86 | Widget _initState() {
87 | return CommonProgressBar();
88 | }
89 |
90 | Widget _error() {
91 | return ErrorUI();
92 | }
93 |
94 | void _navigateToMovies(BuildContext context) {
95 | Navigator.push(context, MaterialPageRoute(builder: (context) {
96 | return MoviesShows(type: AppConstants.movie);
97 | }));
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/lib/presentation/home/widgets/trending_people.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/trending_people_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/all/trending_bloc.dart';
5 | import 'package:fun_box/bloc/all/trending_event.dart';
6 | import 'package:fun_box/bloc/all/trending_state.dart';
7 | import 'package:fun_box/presentation/common/common_error_ui.dart';
8 | import 'package:fun_box/presentation/common/common_people_tiles.dart';
9 | import 'package:fun_box/presentation/common/common_widgets.dart';
10 | import 'package:get_it/get_it.dart';
11 |
12 | import '../../ui_constants.dart';
13 |
14 | class TrendingPeople extends StatefulWidget {
15 | @override
16 | State createState() => _TrendingPeopleState();
17 | }
18 |
19 | class _TrendingPeopleState extends State {
20 | final TrendingBloc _trendingBloc = GetIt.instance.get();
21 |
22 | @override
23 | void dispose() {
24 | _trendingBloc.close();
25 | super.dispose();
26 | }
27 |
28 | @override
29 | Widget build(BuildContext context) {
30 | BlocProvider(create: (BuildContext context) => _trendingBloc);
31 | _trendingBloc.add(TrendingEvent.person);
32 | return BlocBuilder(
33 | bloc: _trendingBloc,
34 | builder: (context, state) {
35 | if (state is InitialTrendingMoviesShowsState) {
36 | return _initState();
37 | } else if (state is SuccessTrendingPersonState) {
38 | return _trendingPeople(context, state.record);
39 | } else {
40 | return _error();
41 | }
42 | },
43 | );
44 | }
45 |
46 | Widget _trendingPeople(
47 | BuildContext context, TrendingPeopleRecord trendingPeople) {
48 | final width = MediaQuery.of(context).size.width;
49 | return Column(
50 | children: [
51 | Padding(
52 | padding: EdgeInsets.only(left: 8.0),
53 | child: Align(
54 | alignment: Alignment.centerLeft,
55 | child: Text(
56 | UIConstants.trendingPeople,
57 | style: TextStyle(
58 | color: Colors.black,
59 | fontSize: 20.0,
60 | fontFamily: UIConstants.fontFamilyIronclad,
61 | fontWeight: FontWeight.w700),
62 | ),
63 | ),
64 | ),
65 | CommonPeopleTiles(
66 | radius: 20.0,
67 | width: width,
68 | itemCount: trendingPeople.results?.length ?? 0,
69 | results: trendingPeople.results)
70 | ],
71 | );
72 | }
73 |
74 | Widget _initState() {
75 | return CommonEmptyInit();
76 | }
77 |
78 | Widget _error() {
79 | return ErrorUI();
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/lib/presentation/home/widgets/trending_shows.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/all/trending_bloc.dart';
5 | import 'package:fun_box/bloc/all/trending_event.dart';
6 | import 'package:fun_box/bloc/all/trending_state.dart';
7 | import 'package:fun_box/presentation/common/common_display_tiles.dart';
8 | import 'package:fun_box/presentation/common/common_error_ui.dart';
9 | import 'package:fun_box/presentation/common/common_widgets.dart';
10 | import 'package:fun_box/presentation/movieshow/movies_shows.dart';
11 | import 'package:fun_box/utils/app_constants.dart';
12 | import 'package:get_it/get_it.dart';
13 |
14 | import '../../ui_constants.dart';
15 |
16 | class TrendingShows extends StatefulWidget {
17 | @override
18 | State createState() => _TrendingShowsState();
19 | }
20 |
21 | class _TrendingShowsState extends State {
22 | final TrendingBloc _trendingBloc = GetIt.instance.get();
23 |
24 | @override
25 | void dispose() {
26 | _trendingBloc.close();
27 | super.dispose();
28 | }
29 |
30 | @override
31 | Widget build(BuildContext context) {
32 | BlocProvider(create: (BuildContext context) => _trendingBloc);
33 | _trendingBloc.add(TrendingEvent.tv);
34 | return BlocBuilder(
35 | bloc: _trendingBloc,
36 | builder: (context, state) {
37 | if (state is InitialTrendingMoviesShowsState) {
38 | return _initState();
39 | } else if (state is SuccessTrendingShowsState) {
40 | return _trendingShows(context, state.record);
41 | } else if (state is ErrorMoviesShowsState) {
42 | return _error();
43 | } else {
44 | return _error();
45 | }
46 | },
47 | );
48 | }
49 |
50 | Widget _trendingShows(BuildContext context, MoviesShowsRecord trendingShows) {
51 | final width = MediaQuery.of(context).size.width;
52 | return Column(
53 | children: [
54 | Padding(
55 | padding: EdgeInsets.only(left: 8.0),
56 | child: Row(
57 | children: [
58 | Text(
59 | UIConstants.trendingShows,
60 | style: TextStyle(
61 | color: Colors.black,
62 | fontSize: 20.0,
63 | fontFamily: UIConstants.fontFamilyIronclad,
64 | fontWeight: FontWeight.w700),
65 | ),
66 | Expanded(child: SizedBox()),
67 | GestureDetector(
68 | onTap: () => _navigateToShows(context),
69 | child: Icon(
70 | Icons.arrow_right_alt_rounded,
71 | size: 40.0,
72 | ),
73 | )
74 | ],
75 | ),
76 | ),
77 | CommonDisplayTiles(
78 | width: width,
79 | itemCount: trendingShows.results?.length ?? 0,
80 | results: trendingShows.results,
81 | type: AppConstants.tvShow,
82 | )
83 | ],
84 | );
85 | }
86 |
87 | Widget _initState() {
88 | return CommonEmptyInit();
89 | }
90 |
91 | Widget _error() {
92 | return ErrorUI();
93 | }
94 |
95 | void _navigateToShows(BuildContext context) {
96 | Navigator.push(context, MaterialPageRoute(builder: (context) {
97 | return MoviesShows(type: AppConstants.tvShow);
98 | }));
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/lib/presentation/movieshow/movies_shows.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/common/common_search_bar.dart';
3 | import 'package:fun_box/presentation/filter/filters.dart';
4 | import 'package:fun_box/presentation/movieshow/widgets/most_popular.dart';
5 | import 'package:fun_box/utils/app_constants.dart';
6 |
7 | class MoviesShows extends StatefulWidget {
8 | final String type;
9 |
10 | MoviesShows({required this.type});
11 |
12 | @override
13 | State createState() => _MoviesShowsState(type);
14 | }
15 |
16 | class _MoviesShowsState extends State {
17 | final String type;
18 | var filter = '${AppConstants.sortBy},${AppConstants.popular}';
19 |
20 | _MoviesShowsState(this.type);
21 |
22 | @override
23 | Widget build(BuildContext context) {
24 | return Material(
25 | child: SafeArea(
26 | child: Column(
27 | children: [
28 | Row(
29 | children: [
30 | GestureDetector(
31 | onTap: () => _navigateToHome(context),
32 | child: Padding(
33 | padding:
34 | EdgeInsets.only(top: 10.0, bottom: 10.0, left: 10.0),
35 | child: Align(
36 | alignment: Alignment.centerLeft,
37 | child: Icon(
38 | Icons.arrow_back_rounded,
39 | size: 30.0,
40 | ),
41 | ),
42 | ),
43 | ),
44 | Expanded(child: CommonSearchBar()),
45 | GestureDetector(
46 | onTap: () => _navigateToFilters(context),
47 | child: Padding(
48 | padding:
49 | EdgeInsets.only(top: 10.0, bottom: 10.0, right: 10.0),
50 | child: Align(
51 | alignment: Alignment.centerLeft,
52 | child: Icon(
53 | Icons.filter_list_rounded,
54 | size: 30.0,
55 | ),
56 | ),
57 | ),
58 | )
59 | ],
60 | ),
61 | MostPopular(type: type, filter: filter)
62 | ],
63 | ),
64 | ),
65 | );
66 | }
67 |
68 | void _navigateToHome(BuildContext context) {
69 | Navigator.pop(context);
70 | }
71 |
72 | void _navigateToFilters(BuildContext context) async {
73 | var result =
74 | await Navigator.push(context, MaterialPageRoute(builder: (context) {
75 | return Filters(type: type, selectedValue: filter);
76 | }));
77 |
78 | if(result != '') {
79 | setState(() {
80 | filter = result;
81 | });
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/lib/presentation/movieshow/widgets/currently_playing.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/movieshow/movies_shows_bloc.dart';
5 | import 'package:fun_box/bloc/movieshow/movies_shows_event.dart';
6 | import 'package:fun_box/bloc/movieshow/movies_shows_state.dart';
7 | import 'package:fun_box/presentation/common/common_display_tiles.dart';
8 | import 'package:fun_box/presentation/common/common_error_ui.dart';
9 | import 'package:fun_box/presentation/common/common_widgets.dart';
10 | import 'package:fun_box/utils/app_constants.dart';
11 | import 'package:get_it/get_it.dart';
12 |
13 | import '../../ui_constants.dart';
14 |
15 | class CurrentlyPlaying extends StatefulWidget {
16 | final String type;
17 |
18 | CurrentlyPlaying({required this.type});
19 |
20 | @override
21 | State createState() => _CurrentlyPlayingState(type);
22 | }
23 |
24 | class _CurrentlyPlayingState extends State {
25 | final String type;
26 | final MoviesShowsBloc _moviesShowsBloc =
27 | GetIt.instance.get();
28 |
29 | _CurrentlyPlayingState(this.type);
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | BlocProvider(create: (BuildContext context) => _moviesShowsBloc);
34 | _moviesShowsBloc.add(
35 | MoviesShowsEvent(type: type, event: AppConstants.currentlyPlaying, page: 1));
36 | return BlocBuilder(
37 | bloc: _moviesShowsBloc,
38 | builder: (context, state) {
39 | if (state is InitialMoviesShowsState) {
40 | return _initState();
41 | } else if (state is SuccessMoviesShowsState) {
42 | return _showCurrentPlaying(context, state.record);
43 | } else if (state is ErrorMoviesShowsState) {
44 | return _errorState();
45 | } else {
46 | return _errorState();
47 | }
48 | });
49 | }
50 |
51 | Widget _showCurrentPlaying(
52 | BuildContext context, MoviesShowsRecord currentPlaying) {
53 | final width = MediaQuery.of(context).size.width;
54 | return Column(
55 | children: [
56 | Padding(
57 | padding: EdgeInsets.only(left: 8.0, top: 8.0, bottom: 8.0),
58 | child: Align(
59 | alignment: Alignment.centerLeft,
60 | child: Text(
61 | UIConstants.currentlyPlaying,
62 | style: TextStyle(
63 | color: Colors.black,
64 | fontSize: 20.0,
65 | fontFamily: UIConstants.fontFamilyIronclad,
66 | fontWeight: FontWeight.w700),
67 | ),
68 | ),
69 | ),
70 | Padding(
71 | padding: EdgeInsets.only(left: 8.0, right: 8.0),
72 | child: CommonDisplayTiles(
73 | width: width,
74 | itemCount: currentPlaying.results?.length ?? 0,
75 | results: currentPlaying.results,
76 | type: type),
77 | )
78 | ],
79 | );
80 | }
81 |
82 | Widget _initState() {
83 | return CommonProgressBar();
84 | }
85 |
86 | Widget _errorState() {
87 | return ErrorUI();
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/lib/presentation/movieshow/widgets/most_popular.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/movies_shows_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/movieshow/movies_shows_bloc.dart';
5 | import 'package:fun_box/bloc/movieshow/movies_shows_event.dart';
6 | import 'package:fun_box/bloc/movieshow/movies_shows_state.dart';
7 | import 'package:fun_box/config/configurations.dart';
8 | import 'package:fun_box/presentation/common/common_error_ui.dart';
9 | import 'package:fun_box/presentation/common/common_widgets.dart';
10 | import 'package:fun_box/presentation/details/movie_show_details.dart';
11 | import 'package:fun_box/utils/app_constants.dart';
12 | import 'package:get_it/get_it.dart';
13 |
14 | class MostPopular extends StatefulWidget {
15 | final String type;
16 | final String filter;
17 |
18 | MostPopular({required this.type, required this.filter});
19 |
20 | @override
21 | State createState() => _MostPopularState(type, filter);
22 | }
23 |
24 | class _MostPopularState extends State {
25 | final String type;
26 | final String filter;
27 | final MoviesShowsBloc _moviesShowsBloc =
28 | GetIt.instance.get();
29 | var _page = 1;
30 |
31 | _MostPopularState(this.type, this.filter);
32 |
33 | @override
34 | Widget build(BuildContext context) {
35 | final List _popularList = [];
36 | BlocProvider(create: (BuildContext context) => _moviesShowsBloc);
37 | _moviesShowsBloc.add(MoviesShowsEvent(
38 | type: type, event: filter, page: _page));
39 | return BlocBuilder(
40 | bloc: _moviesShowsBloc,
41 | builder: (context, state) {
42 | if (state is InitialMoviesShowsState) {
43 | return _initState();
44 | } else if (state is SuccessMoviesShowsState) {
45 | _page = _page + 1;
46 | _popularList.addAll(state.record.results!);
47 | return _showPopular(context, type, _popularList);
48 | } else if (state is ErrorMoviesShowsState) {
49 | return _errorState();
50 | } else {
51 | return _errorState();
52 | }
53 | });
54 | }
55 |
56 | Widget _showPopular(
57 | BuildContext context, String type, List popularList) {
58 | final width = MediaQuery.of(context).size.width;
59 | final height = MediaQuery.of(context).size.height;
60 | final itemWidth = width / 2;
61 | final ScrollController _scrollController = ScrollController();
62 | return Container(
63 | width: width,
64 | height: height - 120.0,
65 | child: Padding(
66 | padding: EdgeInsets.only(left: 8.0, right: 8.0),
67 | child: GridView.builder(
68 | controller: _scrollController
69 | ..addListener(() {
70 | if (_scrollController.offset ==
71 | _scrollController.position.maxScrollExtent &&
72 | _page < AppConstants.maxPages) {
73 | _moviesShowsBloc.add(MoviesShowsEvent(
74 | type: type, event: filter, page: _page));
75 | }
76 | }),
77 | itemCount: popularList.length,
78 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
79 | childAspectRatio: itemWidth / (itemWidth + 100),
80 | crossAxisCount: 2,
81 | crossAxisSpacing: 5.0,
82 | mainAxisSpacing: 5.0),
83 | itemBuilder: (context, index) {
84 | return _popularCell(
85 | context,
86 | type,
87 | popularList[index].id?.toDouble() ?? 0,
88 | popularList[index].posterPath ?? '');
89 | }),
90 | ),
91 | );
92 | }
93 |
94 | Widget _popularCell(
95 | BuildContext context, String type, double id, String imagePath) {
96 | return GestureDetector(
97 | onTap: () => _navigateToDetails(context, type, id),
98 | child: Card(
99 | clipBehavior: Clip.antiAliasWithSaveLayer,
100 | elevation: 5.0,
101 | shape: RoundedRectangleBorder(
102 | borderRadius: BorderRadius.all(Radius.circular(10.0))),
103 | child: Image.network(
104 | '${Configurations.imageUrl}/${Configurations.imageSize}$imagePath',
105 | fit: BoxFit.cover,
106 | ),
107 | ),
108 | );
109 | }
110 |
111 | Widget _initState() {
112 | return CommonProgressBar();
113 | }
114 |
115 | Widget _errorState() {
116 | return ErrorUI();
117 | }
118 |
119 | void _navigateToDetails(BuildContext context, String type, double id) {
120 | Navigator.push(context, MaterialPageRoute(builder: (context) {
121 | return MovieShowDetails(
122 | type: type,
123 | id: id,
124 | );
125 | }));
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/lib/presentation/person/person_details.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/person/widgets/person_credits.dart';
3 | import 'package:fun_box/presentation/person/widgets/person_info.dart';
4 |
5 | class PersonDetails extends StatefulWidget {
6 | final double id;
7 |
8 | PersonDetails({required this.id});
9 |
10 | @override
11 | State createState() => _PersonDetailsState(id);
12 | }
13 |
14 | class _PersonDetailsState extends State {
15 | final double id;
16 |
17 | _PersonDetailsState(this.id);
18 |
19 | @override
20 | Widget build(BuildContext context) {
21 | return Material(
22 | child: SafeArea(
23 | child: ListView(
24 | shrinkWrap: true,
25 | children: [
26 | PersonInfo(id: id),
27 | PersonCredits(id: id)
28 | ],
29 | ),
30 | ),
31 | );
32 | }
33 |
34 | }
--------------------------------------------------------------------------------
/lib/presentation/person/widgets/person_credits.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/person_credits_record.dart';
2 | import 'package:flutter/cupertino.dart';
3 | import 'package:flutter/material.dart';
4 | import 'package:flutter_bloc/flutter_bloc.dart';
5 | import 'package:fun_box/bloc/person/person_details_bloc.dart';
6 | import 'package:fun_box/bloc/person/person_details_event.dart';
7 | import 'package:fun_box/bloc/person/person_details_state.dart';
8 | import 'package:fun_box/config/configurations.dart';
9 | import 'package:fun_box/presentation/common/common_error_ui.dart';
10 | import 'package:fun_box/presentation/common/common_widgets.dart';
11 | import 'package:fun_box/presentation/details/movie_show_details.dart';
12 | import 'package:fun_box/presentation/ui_constants.dart';
13 | import 'package:fun_box/utils/app_constants.dart';
14 | import 'package:get_it/get_it.dart';
15 |
16 | class PersonCredits extends StatefulWidget {
17 | final double id;
18 |
19 | PersonCredits({required this.id});
20 |
21 | @override
22 | State createState() => _PersonCreditsState(id);
23 | }
24 |
25 | class _PersonCreditsState extends State {
26 | final double id;
27 | final PersonDetailsBloc _personDetailsBloc =
28 | GetIt.instance.get();
29 |
30 | _PersonCreditsState(this.id);
31 |
32 | @override
33 | Widget build(BuildContext context) {
34 | BlocProvider(create: (BuildContext context) => _personDetailsBloc);
35 | _personDetailsBloc
36 | .add(PersonDetailsEvent(type: AppConstants.credits, id: id));
37 | return BlocBuilder(
38 | bloc: _personDetailsBloc,
39 | builder: (context, state) {
40 | if (state is InitialPersonDetailsState) {
41 | return _initState();
42 | } else if (state is SuccessPersonCreditsState) {
43 | return _showCredits(context, state.record);
44 | } else if (state is ErrorPersonDetailsState) {
45 | return _errorState();
46 | } else {
47 | return _errorState();
48 | }
49 | });
50 | }
51 |
52 | Widget _showCredits(BuildContext context, PersonCreditsRecord credits) {
53 | return Column(
54 | children: [
55 | Padding(
56 | padding: EdgeInsets.all(10.0),
57 | child: Align(
58 | alignment: Alignment.centerLeft,
59 | child: Text(
60 | UIConstants.popular,
61 | style: TextStyle(
62 | color: Colors.black,
63 | fontFamily: UIConstants.fontFamilyMetropolis,
64 | fontSize: 20.0,
65 | fontWeight: FontWeight.w700),
66 | ),
67 | ),
68 | ),
69 | _showPopular(context, credits)
70 | ],
71 | );
72 | }
73 |
74 | Widget _showPopular(BuildContext context, PersonCreditsRecord credits) {
75 | final width = MediaQuery.of(context).size.width;
76 | var _itemCount = 0;
77 | if (credits.cast != null && credits.cast!.length < 10) {
78 | _itemCount = credits.cast!.length;
79 | } else {
80 | _itemCount = 10;
81 | }
82 | return Container(
83 | height: width / 2,
84 | width: width,
85 | margin: EdgeInsets.only(bottom: 8.0),
86 | child: ListView.builder(
87 | scrollDirection: Axis.horizontal,
88 | itemCount: _itemCount,
89 | itemBuilder: (context, index) {
90 | var type = '';
91 | if (credits.cast?[index].mediaType == AppConstants.movie) {
92 | type = AppConstants.movie;
93 | } else {
94 | type = AppConstants.tvShow;
95 | }
96 | return _popularCell(context, credits.cast?[index].posterPath ?? '',
97 | type, credits.cast?[index].id?.toDouble() ?? 0);
98 | }),
99 | );
100 | }
101 |
102 | Widget _popularCell(
103 | BuildContext context, String imagePath, String type, double id) {
104 | return GestureDetector(
105 | onTap: () => _navigateToDetails(context, type, id),
106 | child: Card(
107 | clipBehavior: Clip.antiAliasWithSaveLayer,
108 | elevation: 5.0,
109 | shape: RoundedRectangleBorder(
110 | borderRadius: BorderRadius.all(Radius.circular(10.0))),
111 | child: Image.network(
112 | '${Configurations.imageUrl}/${Configurations.imageSize}$imagePath',
113 | fit: BoxFit.cover,
114 | ),
115 | ),
116 | );
117 | }
118 |
119 | Widget _initState() {
120 | return CommonEmptyInit();
121 | }
122 |
123 | Widget _errorState() {
124 | return ErrorUI();
125 | }
126 |
127 | void _navigateToDetails(BuildContext context, String type, double id) {
128 | Navigator.push(context, MaterialPageRoute(builder: (context) {
129 | return MovieShowDetails(
130 | type: type,
131 | id: id,
132 | );
133 | }));
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/lib/presentation/ui_constants.dart:
--------------------------------------------------------------------------------
1 | class UIConstants {
2 | static const searchHint = 'Search...';
3 | static const trendingToday = 'Trending Today';
4 | static const trendingMovies = 'Movies';
5 | static const trendingShows = 'TV Shows';
6 | static const trendingPeople = 'People';
7 | static const rating = 'Rating';
8 | static const release = 'Release';
9 | static const seasons = 'Seasons';
10 | static const episodes = 'Episodes';
11 | static const cast = 'Cast';
12 | static const popular = 'Popular';
13 | static const filters = 'Filters';
14 | static const sortBy = 'Sort By';
15 | static const genres = 'Genres';
16 | static const currentlyPlaying = 'Currently Playing';
17 | static const errorMessage = 'Oops! There was an error';
18 | static const fontFamilyIronclad = 'iron';
19 | static const fontFamilyMetropolis = 'metropolis';
20 | }
--------------------------------------------------------------------------------
/lib/presentation/video/movie_show_trailer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:fun_box/presentation/video/video_player.dart';
3 |
4 | class MovieShowTrailer extends StatefulWidget {
5 | final String type;
6 | final double id;
7 |
8 | MovieShowTrailer({required this.type, required this.id});
9 |
10 | @override
11 | State createState() => _MovieShowTrailerState(type, id);
12 | }
13 |
14 | class _MovieShowTrailerState extends State {
15 | final String type;
16 | final double id;
17 |
18 | _MovieShowTrailerState(this.type, this.id);
19 |
20 | @override
21 | Widget build(BuildContext context) {
22 | return Material(
23 | child: SafeArea(
24 | child: VideoPlayer(type: type, id: id),
25 | ),
26 | );
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/lib/presentation/video/video_player.dart:
--------------------------------------------------------------------------------
1 | import 'package:domain/model/trailer_record.dart';
2 | import 'package:flutter/material.dart';
3 | import 'package:flutter_bloc/flutter_bloc.dart';
4 | import 'package:fun_box/bloc/video/movie_show_trailer_bloc.dart';
5 | import 'package:fun_box/bloc/video/movie_show_trailer_event.dart';
6 | import 'package:fun_box/bloc/video/movie_show_trailer_state.dart';
7 | import 'package:fun_box/presentation/common/common_error_ui.dart';
8 | import 'package:fun_box/presentation/common/common_widgets.dart';
9 | import 'package:fun_box/utils/app_constants.dart';
10 | import 'package:get_it/get_it.dart';
11 | import 'package:youtube_player_flutter/youtube_player_flutter.dart';
12 |
13 | class VideoPlayer extends StatefulWidget {
14 | final String type;
15 | final double id;
16 |
17 | VideoPlayer({required this.type, required this.id});
18 |
19 | @override
20 | State createState() => _VideoPlayerState(type, id);
21 | }
22 |
23 | class _VideoPlayerState extends State {
24 | final String type;
25 | final double id;
26 | final MovieShowTrailerBloc _movieShowTrailerBloc =
27 | GetIt.instance.get();
28 |
29 | _VideoPlayerState(this.type, this.id);
30 |
31 | @override
32 | Widget build(BuildContext context) {
33 | BlocProvider(create: (BuildContext context) => _movieShowTrailerBloc);
34 | _movieShowTrailerBloc.add(MovieShowTrailerEvent(type: type, id: id));
35 | return BlocBuilder(
36 | bloc: _movieShowTrailerBloc,
37 | builder: (context, state) {
38 | if (state is InitialMovieShowTrailerState) {
39 | return _initState();
40 | } else if (state is SuccessMovieShowTrailerState) {
41 | return _playTrailer(state.record);
42 | } else if (state is ErrorMovieShowTrailerState) {
43 | return _errorState();
44 | } else {
45 | return _errorState();
46 | }
47 | });
48 | }
49 |
50 | Widget _playTrailer(TrailerRecord trailers) {
51 | var trailer = '';
52 | if (trailers.results != null && trailers.results!.length > 0) {
53 | for (var i = 0; i < trailers.results!.length; i++) {
54 | if (trailers.results![i].name == AppConstants.trailer) {
55 | trailer = trailers.results![i].key ?? '';
56 | }
57 | }
58 | if (trailer.isEmpty) {
59 | trailer = trailers.results![0].key ?? '';
60 | }
61 | }
62 |
63 | YoutubePlayerController _controller = YoutubePlayerController(
64 | initialVideoId: trailer,
65 | flags: YoutubePlayerFlags(autoPlay: true, loop: true));
66 | return Container(
67 | child: YoutubePlayer(
68 | controller: _controller,
69 | ),
70 | );
71 | }
72 |
73 | Widget _initState() {
74 | return CommonProgressBar();
75 | }
76 |
77 | Widget _errorState() {
78 | return ErrorUI();
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/lib/utils/app_constants.dart:
--------------------------------------------------------------------------------
1 | class AppConstants {
2 | static const String localConfig = 'local_config';
3 | static const String remoteConfig = 'remote_config';
4 | static const String movie = 'movie';
5 | static const String tvShow = 'tv';
6 | static const String person = 'person';
7 | static const String personalInfo = 'personal_info';
8 | static const String credits = 'credits';
9 | static const String sortBy = 'sort_by';
10 | static const String genres = 'genres';
11 | static const String popular = 'popular';
12 | static const String currentlyPlaying = 'currently_playing';
13 | static const String topRated = 'Top Rated';
14 | static const String latest = 'Latest';
15 | static const String upcoming = 'Upcoming';
16 | static const String nowPlaying = 'Now Playing';
17 | static const String airingToday = 'Airing Today';
18 | static const String onTheAir = 'On The Air';
19 | static const String suggestions = 'suggestions';
20 | static const String search = 'search';
21 | static const String progress = 'progress';
22 | static const String yearFormat = 'yyyy';
23 | static const String dateFormat = 'dd-MM-yyyy';
24 | static const String NA = 'NA';
25 | static const String trailer = 'Trailer';
26 | static const List movieSortByList = ['Upcoming', 'Now Playing', 'Latest', 'Top Rated'];
27 | static const List showSortByList = ['Airing Today', 'On The Air', 'Latest', 'Top Rated'];
28 | static const int maxPages = 500;
29 | }
--------------------------------------------------------------------------------
/lib/utils/app_navigator_observer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/services.dart';
2 | import 'package:flutter/widgets.dart';
3 |
4 | class AppNavigatorObserver extends NavigatorObserver {
5 |
6 | @override
7 | void didPush(Route route, Route? previousRoute) {
8 | _setOrientation();
9 | }
10 |
11 | @override
12 | void didPop(Route route, Route? previousRoute) {
13 | _setOrientation();
14 | }
15 |
16 | void _setOrientation() {
17 | SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
18 | }
19 | }
--------------------------------------------------------------------------------
/lib/utils/app_utility.dart:
--------------------------------------------------------------------------------
1 | import 'package:fun_box/utils/app_constants.dart';
2 | import 'package:intl/intl.dart';
3 |
4 | class AppUtility {
5 | static String getYearFromDate(String date) {
6 | if (date.isNotEmpty) {
7 | var parseDate = DateTime.parse(date);
8 | var formatter = DateFormat(AppConstants.yearFormat);
9 | return formatter.format(parseDate);
10 | } else {
11 | return AppConstants.NA;
12 | }
13 | }
14 |
15 | static String getCorrectDate(String date) {
16 | if (date.isNotEmpty) {
17 | var parseDate = DateTime.parse(date);
18 | var formatter = DateFormat(AppConstants.dateFormat);
19 | return formatter.format(parseDate);
20 | } else {
21 | return '';
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: fun_box
2 | description: Movies and Tv shows finder.
3 |
4 | # The following line prevents the package from being accidentally published to
5 | # pub.dev using `pub publish`. This is preferred for private packages.
6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev
7 |
8 | # The following defines the version and build number for your application.
9 | # A version number is three numbers separated by dots, like 1.2.43
10 | # followed by an optional build number separated by a +.
11 | # Both the version and the builder number may be overridden in flutter
12 | # build by specifying --build-name and --build-number, respectively.
13 | # In Android, build-name is used as versionName while build-number used as versionCode.
14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
16 | # Read more about iOS versioning at
17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.12.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 |
28 | # The following adds the Cupertino Icons font to your application.
29 | # Use with the CupertinoIcons class for iOS style icons.
30 | cupertino_icons: ^1.0.0
31 | intl: ^0.17.0
32 | flutter_bloc: ^7.0.0
33 | injectable: ^1.2.2
34 | get_it: ^6.0.0
35 | youtube_player_flutter: ^8.0.0
36 |
37 | data:
38 | path: ./data
39 |
40 | domain:
41 | path: ./domain
42 |
43 | remote:
44 | path: ./remote
45 |
46 | dev_dependencies:
47 | flutter_test:
48 | sdk: flutter
49 | injectable_generator: 1.2.2
50 | build_runner: 1.12.2
51 |
52 | # For information on the generic Dart part of this file, see the
53 | # following page: https://dart.dev/tools/pub/pubspec
54 |
55 | # The following section is specific to Flutter.
56 | flutter:
57 |
58 | # The following line ensures that the Material Icons font is
59 | # included with your application, so that you can use the icons in
60 | # the material Icons class.
61 | uses-material-design: true
62 |
63 | # To add assets to your application, add an assets section, like this:
64 | assets:
65 | - images/error_image.png
66 |
67 | # An image asset can refer to one or more resolution-specific "variants", see
68 | # https://flutter.dev/assets-and-images/#resolution-aware.
69 |
70 | # For details regarding adding assets from package dependencies, see
71 | # https://flutter.dev/assets-and-images/#from-packages
72 |
73 | # To add custom fonts to your application, add a fonts section here,
74 | # in this "flutter" section. Each entry in this list should have a
75 | # "family" key with the font family name, and a "fonts" key with a
76 | # list giving the asset and other descriptors for the font. For
77 | # example:
78 | fonts:
79 | - family: iron
80 | fonts:
81 | - asset: fonts/ironclad.ttf
82 | - family: metropolis
83 | fonts:
84 | - asset: fonts/metropolis.otf
85 | # For details regarding fonts from package dependencies,
86 | # see https://flutter.dev/custom-fonts/#from-packages
87 |
--------------------------------------------------------------------------------
/remote/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .dart_tool/
3 |
4 | .packages
5 | .pub/
6 |
7 | .idea/
8 | .vagrant/
9 | .sconsign.dblite
10 | .svn/
11 |
12 | *.swp
13 | profile
14 |
15 | DerivedData/
16 |
17 | .generated/
18 |
19 | *.pbxuser
20 | *.mode1v3
21 | *.mode2v3
22 | *.perspectivev3
23 |
24 | !default.pbxuser
25 | !default.mode1v3
26 | !default.mode2v3
27 | !default.perspectivev3
28 |
29 | xcuserdata
30 |
31 | *.moved-aside
32 |
33 | *.pyc
34 | *sync/
35 | Icon?
36 | .tags*
37 |
38 | build/
39 | .android/
40 | .ios/
41 | .flutter-plugins
42 | .flutter-plugins-dependencies
43 |
44 | # Symbolication related
45 | app.*.symbols
46 |
47 | # Obfuscation related
48 | app.*.map.json
49 |
--------------------------------------------------------------------------------
/remote/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled and should not be manually edited.
5 |
6 | version:
7 | revision: 9b2d32b605630f28625709ebd9d78ab3016b2bf6
8 | channel: stable
9 |
10 | project_type: module
11 |
--------------------------------------------------------------------------------
/remote/README.md:
--------------------------------------------------------------------------------
1 | # remote
2 |
3 | A new flutter module project.
4 |
5 | ## Getting Started
6 |
7 | For help getting started with Flutter, view our online
8 | [documentation](https://flutter.dev/).
9 |
10 | For instructions integrating Flutter modules to your existing applications,
11 | see the [add-to-app documentation](https://flutter.dev/docs/development/add-to-app).
12 |
--------------------------------------------------------------------------------
/remote/lib/datasource/movies_shows_data_source.dart:
--------------------------------------------------------------------------------
1 | import 'package:remote/model/cast_request.dart';
2 | import 'package:remote/model/details_request.dart';
3 | import 'package:remote/model/genres_request.dart';
4 | import 'package:remote/model/movies_shows_genre_request.dart';
5 | import 'package:remote/model/page_request.dart';
6 | import 'package:remote/model/person_credits_request.dart';
7 | import 'package:remote/model/person_info_request.dart';
8 | import 'package:remote/model/movies_shows_request.dart';
9 | import 'package:remote/model/search_request.dart';
10 | import 'package:remote/model/trailer_request.dart';
11 | import 'package:remote/model/trending_request.dart';
12 |
13 | abstract class MoviesShowsDataSource {
14 |
15 | Future getConfig();
16 | Future getTrending(TrendingRequest request);
17 | Future getTrendingPeople(TrendingRequest request);
18 | Future getDetails(DetailsRequest request);
19 | Future getTrailer(TrailerRequest request);
20 | Future getCast(CastRequest request);
21 | Future getPersonInfo(PersonInfoRequest request);
22 | Future getPersonCredits(PersonCreditsRequest request);
23 | Future getCurrentPlayingMovies(PageRequest request);
24 | Future getCurrentPlayingShows(PageRequest request);
25 | Future getPopularMoviesShows(MoviesShowsRequest request);
26 | Future getLatestMoviesShows(MoviesShowsRequest request);
27 | Future getTopRatedMoviesShows(MoviesShowsRequest request);
28 | Future getUpcomingMovies(PageRequest request);
29 | Future getAiringTodayShows(PageRequest request);
30 | Future getMoviesShowsByGenre(MoviesShowsGenreRequest request);
31 | Future getGenres(GenresRequest request);
32 | Future searchMoviesShows(SearchRequest request);
33 | }
--------------------------------------------------------------------------------
/remote/lib/di/di.config.dart:
--------------------------------------------------------------------------------
1 | // GENERATED CODE - DO NOT MODIFY BY HAND
2 |
3 | // **************************************************************************
4 | // InjectableConfigGenerator
5 | // **************************************************************************
6 |
7 | import 'package:get_it/get_it.dart' as _i1;
8 | import 'package:injectable/injectable.dart' as _i2;
9 |
10 | import '../datasource/movies_shows_data_source.dart' as _i3;
11 | import '../datasource/movies_shows_data_source_impl.dart'
12 | as _i4; // ignore_for_file: unnecessary_lambdas
13 |
14 | // ignore_for_file: lines_longer_than_80_chars
15 | /// initializes the registration of provided dependencies inside of [GetIt]
16 | _i1.GetIt $initRemoteGetIt(_i1.GetIt get,
17 | {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
18 | final gh = _i2.GetItHelper(get, environment, environmentFilter);
19 | gh.singleton<_i3.MoviesShowsDataSource>(_i4.MoviesShowsDataSourceImpl());
20 | return get;
21 | }
22 |
--------------------------------------------------------------------------------
/remote/lib/di/di.dart:
--------------------------------------------------------------------------------
1 | import 'package:injectable/injectable.dart';
2 | import 'package:remote/di/di.config.dart';
3 |
4 | @InjectableInit(
5 | initializerName: r'$initRemoteGetIt'
6 | )
7 | Future configureRemoteInjection(final getIt) async => $initRemoteGetIt(getIt);
--------------------------------------------------------------------------------
/remote/lib/http_client.dart:
--------------------------------------------------------------------------------
1 | import 'dart:io';
2 | import 'package:http/http.dart' as http;
3 | import 'package:remote/util/http_util.dart';
4 |
5 | class HttpClient {
6 | final bearer =
7 | 'eyJhbGciOiJIUzI1NiJ9.eyJhdWQiOiI1MzRjNDliM2EwOWUzNzMwM2YxNmJmMjQxNDMyOTIyZCIsInN1YiI6IjYwM2E5M2E5YzJmZjNkMDA1MjA2MzIwZCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.o6T32zw2hIBReqzSDx7hmBRsjUdma-IyTCY7bm-1lCM';
8 |
9 | Future get({required String url}) async {
10 | var response = await http.get(Uri.parse(url), headers: _getHeaders());
11 | return HttpUtil.getResponse(response);
12 | }
13 |
14 | Map _getHeaders() {
15 | final headers = {};
16 | headers[HttpHeaders.authorizationHeader] = 'Bearer $bearer';
17 | return headers;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/remote/lib/model/cast_request.dart:
--------------------------------------------------------------------------------
1 | class CastRequest {
2 | String type;
3 | double id;
4 |
5 | CastRequest(this.type, this.id);
6 | }
--------------------------------------------------------------------------------
/remote/lib/model/details_request.dart:
--------------------------------------------------------------------------------
1 | class DetailsRequest {
2 | String type;
3 | double id;
4 |
5 | DetailsRequest({required this.type, required this.id});
6 | }
7 |
--------------------------------------------------------------------------------
/remote/lib/model/genres_request.dart:
--------------------------------------------------------------------------------
1 | class GenresRequest {
2 | String type;
3 |
4 | GenresRequest({required this.type});
5 | }
6 |
--------------------------------------------------------------------------------
/remote/lib/model/movies_shows_genre_request.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsGenreRequest {
2 | String type;
3 | int genreId;
4 | int page;
5 |
6 | MoviesShowsGenreRequest(
7 | {required this.type, required this.genreId, required this.page});
8 | }
9 |
--------------------------------------------------------------------------------
/remote/lib/model/movies_shows_request.dart:
--------------------------------------------------------------------------------
1 | class MoviesShowsRequest {
2 | String type;
3 | int page;
4 |
5 | MoviesShowsRequest({required this.type, required this.page});
6 | }
7 |
--------------------------------------------------------------------------------
/remote/lib/model/page_request.dart:
--------------------------------------------------------------------------------
1 | class PageRequest {
2 | int page;
3 |
4 | PageRequest({required this.page});
5 | }
6 |
--------------------------------------------------------------------------------
/remote/lib/model/person_credits_request.dart:
--------------------------------------------------------------------------------
1 | class PersonCreditsRequest {
2 | double id;
3 |
4 | PersonCreditsRequest({required this.id});
5 | }
6 |
--------------------------------------------------------------------------------
/remote/lib/model/person_info_request.dart:
--------------------------------------------------------------------------------
1 | class PersonInfoRequest {
2 | double id;
3 |
4 | PersonInfoRequest({required this.id});
5 | }
--------------------------------------------------------------------------------
/remote/lib/model/search_request.dart:
--------------------------------------------------------------------------------
1 | class SearchRequest {
2 | String searchTerm;
3 |
4 | SearchRequest({required this.searchTerm});
5 | }
6 |
--------------------------------------------------------------------------------
/remote/lib/model/trailer_request.dart:
--------------------------------------------------------------------------------
1 | class TrailerRequest {
2 | String type;
3 | double id;
4 |
5 | TrailerRequest(this.type, this.id);
6 | }
7 |
--------------------------------------------------------------------------------
/remote/lib/model/trending_request.dart:
--------------------------------------------------------------------------------
1 | class TrendingRequest {
2 | String type;
3 |
4 | TrendingRequest({required this.type});
5 | }
--------------------------------------------------------------------------------
/remote/lib/util/api_constants.dart:
--------------------------------------------------------------------------------
1 | class ApiConstants {
2 | static const base_url = 'https://api.themoviedb.org/3';
3 | static const http_success = 200;
4 | }
--------------------------------------------------------------------------------
/remote/lib/util/http_util.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:http/http.dart';
4 | import 'package:remote/util/api_constants.dart';
5 |
6 | class HttpUtil {
7 |
8 | static dynamic getResponse(Response response) {
9 | switch(response.statusCode) {
10 | case ApiConstants.http_success:
11 | return _getSuccessResponse(response);
12 | default:
13 | return Exception('Remote Error');
14 | }
15 | }
16 |
17 | static dynamic _getSuccessResponse(Response response) {
18 | final _responseJson = json.decode(response.body);
19 | print('Response: $_responseJson');
20 | return _responseJson;
21 | }
22 |
23 | }
--------------------------------------------------------------------------------
/remote/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: remote
2 | description: A new flutter module project.
3 |
4 | # The following defines the version and build number for your application.
5 | # A version number is three numbers separated by dots, like 1.2.43
6 | # followed by an optional build number separated by a +.
7 | # Both the version and the builder number may be overridden in flutter
8 | # build by specifying --build-name and --build-number, respectively.
9 | # In Android, build-name is used as versionName while build-number used as versionCode.
10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning
11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
12 | # Read more about iOS versioning at
13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
14 | #
15 | # This version is used _only_ for the Runner app, which is used if you just do
16 | # a `flutter run` or a `flutter make-host-app-editable`. It has no impact
17 | # on any other native host app that you embed your Flutter project into.
18 | version: 1.0.0+1
19 |
20 | environment:
21 | sdk: ">=2.12.0 <3.0.0"
22 |
23 | dependencies:
24 | flutter:
25 | sdk: flutter
26 |
27 | # The following adds the Cupertino Icons font to your application.
28 | # Use with the CupertinoIcons class for iOS style icons.
29 | cupertino_icons: ^1.0.0
30 | http: ^0.13.1
31 | injectable: ^1.2.2
32 | get_it: ^6.0.0
33 |
34 | dev_dependencies:
35 | flutter_test:
36 | sdk: flutter
37 | injectable_generator: 1.2.2
38 | build_runner: 1.12.2
39 |
40 | # For information on the generic Dart part of this file, see the
41 | # following page: https://dart.dev/tools/pub/pubspec
42 |
43 | flutter:
44 | # The following line ensures that the Material Icons font is
45 | # included with your application, so that you can use the icons in
46 | # the material Icons class.
47 | uses-material-design: true
48 |
49 | # To add Flutter specific assets to your application, add an assets section,
50 | # like this:
51 | # assets:
52 | # - images/a_dot_burr.jpeg
53 | # - images/a_dot_ham.jpeg
54 |
55 | # An image asset can refer to one or more resolution-specific "variants", see
56 | # https://flutter.dev/assets-and-images/#resolution-aware.
57 |
58 | # For details regarding adding assets from package dependencies, see
59 | # https://flutter.dev/assets-and-images/#from-packages
60 |
61 | # To add Flutter specific custom fonts to your application, add a fonts
62 | # section here, in this "flutter" section. Each entry in this list should
63 | # have a "family" key with the font family name, and a "fonts" key with a
64 | # list giving the asset and other descriptors for the font. For
65 | # example:
66 | # fonts:
67 | # - family: Schyler
68 | # fonts:
69 | # - asset: fonts/Schyler-Regular.ttf
70 | # - asset: fonts/Schyler-Italic.ttf
71 | # style: italic
72 | # - family: Trajan Pro
73 | # fonts:
74 | # - asset: fonts/TrajanPro.ttf
75 | # - asset: fonts/TrajanPro_Bold.ttf
76 | # weight: 700
77 | #
78 | # For details regarding fonts from package dependencies,
79 | # see https://flutter.dev/custom-fonts/#from-packages
80 |
81 |
82 | # This section identifies your Flutter project as a module meant for
83 | # embedding in a native host app. These identifiers should _not_ ordinarily
84 | # be changed after generation - they are used to ensure that the tooling can
85 | # maintain consistency when adding or modifying assets and plugins.
86 | # They also do not have any bearing on your native host application's
87 | # identifiers, which may be completely independent or the same as these.
88 | module:
89 | androidX: true
90 | androidPackage: com.ruben.funbox.remote
91 | iosBundleIdentifier: com.ruben.funbox.remote
92 |
--------------------------------------------------------------------------------
/remote/remote.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/remote/remote_android.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/screenshots/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/home.jpg
--------------------------------------------------------------------------------
/screenshots/movie_show_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/movie_show_details.jpg
--------------------------------------------------------------------------------
/screenshots/movie_show_filters.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/movie_show_filters.jpg
--------------------------------------------------------------------------------
/screenshots/movie_show_search.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/movie_show_search.jpg
--------------------------------------------------------------------------------
/screenshots/movies.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/movies.jpg
--------------------------------------------------------------------------------
/screenshots/person_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/person_details.jpg
--------------------------------------------------------------------------------
/screenshots/tv_show_details.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/tv_show_details.jpg
--------------------------------------------------------------------------------
/screenshots/tv_shows.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rubenquadros/Flutter-BLoC-Clean-Architecture-Example/748a999fd828e7b71e2fcc9c567cb62cbb260c1f/screenshots/tv_shows.jpg
--------------------------------------------------------------------------------