├── .vscode ├── settings.json └── launch.json ├── linux ├── .gitignore ├── main.cc ├── flutter │ ├── generated_plugin_registrant.h │ ├── generated_plugin_registrant.cc │ └── generated_plugins.cmake └── my_application.h ├── lib ├── core │ ├── utils │ │ └── generics │ │ │ ├── routes.dart │ │ │ ├── double_to_fractional_digit.dart │ │ │ ├── minute_to_hour_convertion.dart │ │ │ ├── get_random_no_from_range.dart │ │ │ ├── is_keyboard_active.dart │ │ │ ├── custom_scroll_behavior.dart │ │ │ ├── dialoge_and_snackbar_strings.dart │ │ │ ├── app_route │ │ │ └── app_router.dart │ │ │ ├── sort_list_by.dart │ │ │ └── string_manipulation.dart │ └── services │ │ ├── debouncer.dart │ │ ├── app_default_preferences.dart │ │ └── navigator.dart ├── data │ ├── bloc │ │ ├── home │ │ │ ├── image_slider │ │ │ │ ├── image_slider_event.dart │ │ │ │ ├── image_slider_state.dart │ │ │ │ └── image_slider_bloc.dart │ │ │ └── home_data │ │ │ │ ├── home_data_event.dart │ │ │ │ └── home_data_state.dart │ │ ├── login │ │ │ └── login_poster │ │ │ │ ├── login_poster_event.dart │ │ │ │ ├── login_poster_state.dart │ │ │ │ └── login_poster_bloc.dart │ │ ├── upcoming_movies │ │ │ ├── upcoming_movies_event.dart │ │ │ ├── upcoming_movies_state.dart │ │ │ └── upcoming_movies_bloc.dart │ │ ├── movie_details │ │ │ ├── movie_details_event.dart │ │ │ ├── movie_details_state.dart │ │ │ └── movie_details_bloc.dart │ │ ├── discover │ │ │ ├── discover_event.dart │ │ │ └── discover_state.dart │ │ ├── search_result │ │ │ ├── search_result_event.dart │ │ │ └── search_result_state.dart │ │ ├── actor_profile │ │ │ ├── person_details_event.dart │ │ │ └── person_details_state.dart │ │ └── movies_result_grid │ │ │ ├── movies_result_grid_event.dart │ │ │ └── movies_result_grid_state.dart │ ├── sources │ │ └── remote_data_sources │ │ │ └── constatnts.dart │ ├── models │ │ ├── login │ │ │ ├── login_poster_model.dart │ │ │ └── login_poster_model.g.dart │ │ ├── home │ │ │ ├── image_slider │ │ │ │ ├── image_slider_model.dart │ │ │ │ └── image_slider_model.g.dart │ │ │ └── movie_list │ │ │ │ ├── movie_list_model.dart │ │ │ │ └── movie_list_model.g.dart │ │ ├── upcoming_movies │ │ │ ├── upcoming_movies_model.dart │ │ │ └── upcoming_movies_model.g.dart │ │ └── actor_profile │ │ │ ├── actor_profile_model.dart │ │ │ └── actor_profile_model.g.dart │ └── repositories │ │ ├── actor_profile │ │ └── actor_profile_repo.dart │ │ ├── movie_details │ │ └── movie_details_repo.dart │ │ ├── login │ │ └── login_poster_repo.dart │ │ ├── upcoming_movies │ │ └── upcoming_movies_repo.dart │ │ ├── discover │ │ └── discover_repo.dart │ │ ├── search_result │ │ └── search_result_repo.dart │ │ ├── home │ │ ├── image_slider │ │ │ └── image_slider_repo.dart │ │ └── movie_list │ │ │ └── movie_list_repo.dart │ │ └── movies_result_grid │ │ └── movies_result_grid_repo.dart ├── presentation │ ├── bloc │ │ ├── main │ │ │ ├── appbar │ │ │ │ ├── appbar_state.dart │ │ │ │ ├── appbar_event.dart │ │ │ │ └── appbar_bloc.dart │ │ │ └── bottom_navbar │ │ │ │ ├── botom_nav_state.dart │ │ │ │ └── botom_nav_cubit.dart │ │ ├── home │ │ │ └── slider_image │ │ │ │ ├── slider_image_state.dart │ │ │ │ └── slider_image_cubit.dart │ │ ├── navigation_from │ │ │ ├── navigation_from_state.dart │ │ │ ├── navigation_from_event.dart │ │ │ └── navigation_from_bloc.dart │ │ ├── watchlist │ │ │ └── watchlist_scroll │ │ │ │ ├── watchlist_scroll_state.dart │ │ │ │ └── watchlist_scroll_cubit.dart │ │ └── components │ │ │ ├── inner_appbars │ │ │ └── bloc │ │ │ │ ├── appbar_search_event.dart │ │ │ │ ├── appbar_search_state.dart │ │ │ │ └── appbar_search_bloc.dart │ │ │ └── widgets_functionality │ │ │ ├── widgets_functionality_event.dart │ │ │ ├── widgets_functionality_state.dart │ │ │ └── widgets_functionality_bloc.dart │ ├── pages │ │ ├── home │ │ │ └── widgets │ │ │ │ └── skelton │ │ │ │ └── widgets │ │ │ │ ├── image_slider_skelton.dart │ │ │ │ ├── movie_list_scroll.skelton.dart │ │ │ │ ├── movie_list_scroll_skelton.dart │ │ │ │ └── genres_scroll_skelton.dart │ │ ├── movie_details │ │ │ └── widgets │ │ │ │ ├── skelton │ │ │ │ └── poster_image_skelton.dart │ │ │ │ ├── movie_title_section.dart │ │ │ │ └── button_group_section.dart │ │ ├── actor_profile │ │ │ └── widgets │ │ │ │ ├── biogarphy_bottomsheet.dart │ │ │ │ └── title_and_data.dart │ │ ├── splash │ │ │ └── view │ │ │ │ └── splash_page.dart │ │ ├── profile │ │ │ └── widgets │ │ │ │ └── profile_menu_item.dart │ │ ├── watchlist │ │ │ └── widgets │ │ │ │ └── title_with_toggle.dart │ │ ├── upcoming_movies │ │ │ └── widgets │ │ │ │ └── upcoming_movie_date.dart │ │ ├── video_playback │ │ │ └── widgets │ │ │ │ └── youtube_player_iframe.dart │ │ ├── search_result │ │ │ └── widgtes │ │ │ │ └── skelton │ │ │ │ └── movie_poster_grid_skelton.dart │ │ └── main │ │ │ └── widgets │ │ │ └── bottom_navbar │ │ │ └── bottom_navbar_item.dart │ ├── themes │ │ ├── colors.dart │ │ ├── values.dart │ │ ├── theme.dart │ │ ├── text_form_field.dart │ │ └── screen_size_config.dart │ └── components │ │ ├── poster_card.dart │ │ ├── blurred_background.dart │ │ ├── snackbar │ │ └── snackbar.dart │ │ ├── image_container.dart │ │ ├── dialogs │ │ ├── error_widget.dart │ │ ├── exit_app_dialoge.dart │ │ └── error_dialog.dart │ │ ├── rating_indicator.dart │ │ ├── background.dart │ │ ├── inner_appbars │ │ └── movie_grid_layout_button.dart │ │ └── skelton.dart ├── domain │ ├── repositories │ │ ├── login │ │ │ └── i_login_poster_repo.dart │ │ ├── home │ │ │ ├── image_slider │ │ │ │ └── i_image_slider_repo.dart │ │ │ ├── movie_sroll_list │ │ │ │ └── i_movie_list_repo.dart │ │ │ └── i_home_repo.dart │ │ ├── dicover │ │ │ └── i_discover_repo.dart │ │ ├── movie_details │ │ │ └── i_movie_details_repo.dart │ │ ├── actor_profile │ │ │ └── i_actor_profile_repo.dart │ │ ├── upcoming_movies │ │ │ └── i_upcoming_movies_repo.dart │ │ ├── search_result │ │ │ └── i_search_result_repo.dart │ │ └── movies_result_grid │ │ │ └── i_movies_result_grid_repo.dart │ └── usecase │ │ └── dependancy_injection │ │ └── injectable.dart └── gen │ └── fonts.gen.dart ├── ios ├── Flutter │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── AppFrameworkInfo.plist ├── Runner │ ├── Runner-Bridging-Header.h │ ├── Assets.xcassets │ │ ├── LaunchImage.imageset │ │ │ ├── LaunchImage.png │ │ │ ├── LaunchImage@2x.png │ │ │ ├── LaunchImage@3x.png │ │ │ ├── README.md │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── 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-1024x1024@1x.png │ │ │ └── Icon-App-83.5x83.5@2x.png │ ├── AppDelegate.swift │ ├── Base.lproj │ │ └── Main.storyboard │ └── Info.plist ├── Runner.xcodeproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── WorkspaceSettings.xcsettings │ │ └── IDEWorkspaceChecks.plist └── .gitignore ├── macos ├── Flutter │ ├── Flutter-Debug.xcconfig │ ├── Flutter-Release.xcconfig │ └── GeneratedPluginRegistrant.swift ├── Runner │ ├── Configs │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ ├── Warnings.xcconfig │ │ └── AppInfo.xcconfig │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── app_icon_128.png │ │ │ ├── app_icon_16.png │ │ │ ├── app_icon_256.png │ │ │ ├── app_icon_32.png │ │ │ ├── app_icon_512.png │ │ │ ├── app_icon_64.png │ │ │ ├── app_icon_1024.png │ │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── Release.entitlements │ ├── DebugProfile.entitlements │ ├── MainFlutterWindow.swift │ └── Info.plist ├── .gitignore ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── Runner.xcodeproj │ └── project.xcworkspace │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── web ├── favicon.png ├── icons │ ├── Icon-192.png │ ├── Icon-512.png │ ├── Icon-maskable-192.png │ └── Icon-maskable-512.png └── manifest.json ├── screenshots ├── home.jpg ├── github.png ├── profile.jpg ├── discover1.jpg ├── discover2.jpg ├── watchlist.jpg └── file_structure.png ├── assets ├── images │ ├── bg_image.jpg │ ├── no_signal.png │ ├── logo2.svg │ └── logo1.svg ├── fonts │ ├── Poppins-Bold.ttf │ ├── Poppins-Medium.ttf │ ├── Poppins-Regular.ttf │ └── Poppins-SemiBold.ttf └── icons │ ├── column_2.svg │ ├── column_3.svg │ ├── play.svg │ ├── search.svg │ ├── chevron_right.svg │ ├── edit.svg │ ├── chevron_left.svg │ ├── home.svg │ ├── heart_fill.svg │ ├── arrow_left.svg │ ├── arrow_right.svg │ ├── close.svg │ ├── person.svg │ ├── user.svg │ ├── download.svg │ ├── chat.svg │ ├── share.svg │ ├── password.svg │ ├── mic.svg │ ├── time.svg │ ├── logout.svg │ ├── heart_outline.svg │ ├── film.svg │ └── discover.svg ├── android ├── gradle.properties ├── app │ └── src │ │ ├── main │ │ ├── res │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable │ │ │ │ └── launch_background.xml │ │ │ ├── drawable-v21 │ │ │ │ └── launch_background.xml │ │ │ ├── values │ │ │ │ └── styles.xml │ │ │ └── values-night │ │ │ │ └── styles.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── example │ │ │ │ └── movie_app │ │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── .gitignore ├── settings.gradle └── build.gradle ├── windows ├── runner │ ├── resources │ │ └── app_icon.ico │ ├── resource.h │ ├── utils.h │ ├── runner.exe.manifest │ ├── flutter_window.h │ ├── CMakeLists.txt │ ├── main.cpp │ └── utils.cpp ├── .gitignore └── flutter │ ├── generated_plugin_registrant.h │ ├── generated_plugin_registrant.cc │ └── generated_plugins.cmake ├── .github └── workflows │ └── build_apk_action.yml ├── .gitignore ├── analysis_options.yaml ├── pubspec.yaml └── .metadata /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | } -------------------------------------------------------------------------------- /linux/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral 2 | -------------------------------------------------------------------------------- /lib/core/utils/generics/routes.dart: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /macos/Flutter/Flutter-Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "ephemeral/Flutter-Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /web/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/web/favicon.png -------------------------------------------------------------------------------- /screenshots/home.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/home.jpg -------------------------------------------------------------------------------- /screenshots/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/github.png -------------------------------------------------------------------------------- /screenshots/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/profile.jpg -------------------------------------------------------------------------------- /web/icons/Icon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/web/icons/Icon-192.png -------------------------------------------------------------------------------- /web/icons/Icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/web/icons/Icon-512.png -------------------------------------------------------------------------------- /assets/images/bg_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/images/bg_image.jpg -------------------------------------------------------------------------------- /screenshots/discover1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/discover1.jpg -------------------------------------------------------------------------------- /screenshots/discover2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/discover2.jpg -------------------------------------------------------------------------------- /screenshots/watchlist.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/watchlist.jpg -------------------------------------------------------------------------------- /assets/fonts/Poppins-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/fonts/Poppins-Bold.ttf -------------------------------------------------------------------------------- /assets/images/no_signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/images/no_signal.png -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.useAndroidX=true 3 | android.enableJetifier=true 4 | -------------------------------------------------------------------------------- /assets/fonts/Poppins-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/fonts/Poppins-Medium.ttf -------------------------------------------------------------------------------- /macos/Runner/Configs/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Debug.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /screenshots/file_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/screenshots/file_structure.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/web/icons/Icon-maskable-192.png -------------------------------------------------------------------------------- /web/icons/Icon-maskable-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/web/icons/Icon-maskable-512.png -------------------------------------------------------------------------------- /assets/fonts/Poppins-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/fonts/Poppins-Regular.ttf -------------------------------------------------------------------------------- /assets/fonts/Poppins-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/assets/fonts/Poppins-SemiBold.ttf -------------------------------------------------------------------------------- /macos/Runner/Configs/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "../../Flutter/Flutter-Release.xcconfig" 2 | #include "Warnings.xcconfig" 3 | -------------------------------------------------------------------------------- /macos/.gitignore: -------------------------------------------------------------------------------- 1 | # Flutter-related 2 | **/Flutter/ephemeral/ 3 | **/Pods/ 4 | 5 | # Xcode-related 6 | **/dgph 7 | **/xcuserdata/ 8 | -------------------------------------------------------------------------------- /windows/runner/resources/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/windows/runner/resources/app_icon.ico -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/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/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vishnumukundan/movie-app/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/example/movie_app/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.movie_app 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /linux/main.cc: -------------------------------------------------------------------------------- 1 | #include "my_application.h" 2 | 3 | int main(int argc, char** argv) { 4 | g_autoptr(MyApplication) app = my_application_new(); 5 | return g_application_run(G_APPLICATION(app), argc, argv); 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /macos/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /lib/data/bloc/home/image_slider/image_slider_event.dart: -------------------------------------------------------------------------------- 1 | part of 'image_slider_bloc.dart'; 2 | 3 | @freezed 4 | class ImageSliderEvent with _$ImageSliderEvent { 5 | const factory ImageSliderEvent.getImageSliderData() = _GetImageSliderData; 6 | } 7 | -------------------------------------------------------------------------------- /lib/data/bloc/login/login_poster/login_poster_event.dart: -------------------------------------------------------------------------------- 1 | part of 'login_poster_bloc.dart'; 2 | 3 | @freezed 4 | class LoginPosterEvent with _$LoginPosterEvent { 5 | const factory LoginPosterEvent.getLoginPosterImages() = _GetLoginPosterImages; 6 | } 7 | -------------------------------------------------------------------------------- /lib/data/bloc/upcoming_movies/upcoming_movies_event.dart: -------------------------------------------------------------------------------- 1 | part of 'upcoming_movies_bloc.dart'; 2 | 3 | @freezed 4 | class UpcomingMoviesEvent with _$UpcomingMoviesEvent { 5 | const factory UpcomingMoviesEvent.getUpcomingMovies() = GetUpcomingMovies; 6 | } 7 | -------------------------------------------------------------------------------- /lib/presentation/bloc/main/appbar/appbar_state.dart: -------------------------------------------------------------------------------- 1 | part of 'appbar_bloc.dart'; 2 | 3 | @freezed 4 | class AppbarState with _$AppbarState { 5 | const factory AppbarState.initial({ 6 | required HomePageCurrentPage currentPage, 7 | }) = _Initial; 8 | } 9 | -------------------------------------------------------------------------------- /lib/core/utils/generics/double_to_fractional_digit.dart: -------------------------------------------------------------------------------- 1 | doubleToFactionalDigit(double value, int digits) { 2 | final String stringValue = value.toStringAsFixed(digits); 3 | final double finalValue = double.parse(stringValue); 4 | return finalValue; 5 | } 6 | -------------------------------------------------------------------------------- /assets/icons/column_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /lib/core/utils/generics/minute_to_hour_convertion.dart: -------------------------------------------------------------------------------- 1 | String minToHourConvertion(int value) { 2 | final int hour = value ~/ 60; 3 | final int minutes = value % 60; 4 | return '${hour.toString().padLeft(2, "0")}h ${minutes.toString().padLeft(2, "0")}m'; 5 | } 6 | -------------------------------------------------------------------------------- /lib/presentation/bloc/main/bottom_navbar/botom_nav_state.dart: -------------------------------------------------------------------------------- 1 | part of 'botom_nav_cubit.dart'; 2 | 3 | @freezed 4 | class BottomNavState with _$BottomNavState { 5 | const factory BottomNavState.initial({ 6 | required int selectedIndex, 7 | }) = _Initial; 8 | } 9 | -------------------------------------------------------------------------------- /lib/core/utils/generics/get_random_no_from_range.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | 3 | import 'dart:math'; 4 | 5 | getRandRange(int min, int max) { 6 | final _random = Random(); 7 | return min + _random.nextInt(max - min); 8 | } 9 | -------------------------------------------------------------------------------- /lib/core/utils/generics/is_keyboard_active.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | bool isKeyboardActive(context) { 4 | if (!(MediaQuery.of(context).viewInsets.bottom == 0.0)) { 5 | return true; 6 | } else { 7 | return false; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/presentation/bloc/home/slider_image/slider_image_state.dart: -------------------------------------------------------------------------------- 1 | part of 'slider_image_cubit.dart'; 2 | 3 | @freezed 4 | class SliderImageState with _$SliderImageState { 5 | const factory SliderImageState.initial({ 6 | required int currentIndex, 7 | }) = _Initial; 8 | } 9 | -------------------------------------------------------------------------------- /lib/data/bloc/movie_details/movie_details_event.dart: -------------------------------------------------------------------------------- 1 | part of 'movie_details_bloc.dart'; 2 | 3 | @freezed 4 | class MovieDetailsEvent with _$MovieDetailsEvent { 5 | const factory MovieDetailsEvent.getMovieDetails({ 6 | required String movieId, 7 | }) = _GetMovieDetails; 8 | } 9 | -------------------------------------------------------------------------------- /lib/presentation/bloc/main/appbar/appbar_event.dart: -------------------------------------------------------------------------------- 1 | part of 'appbar_bloc.dart'; 2 | 3 | @freezed 4 | class AppbarEvent with _$AppbarEvent { 5 | const factory AppbarEvent.moviesSelected() = _MoviesSelected; 6 | const factory AppbarEvent.tvShowsSelected() = _TvShowsSelected; 7 | } 8 | -------------------------------------------------------------------------------- /lib/data/bloc/discover/discover_event.dart: -------------------------------------------------------------------------------- 1 | part of 'discover_bloc.dart'; 2 | 3 | @freezed 4 | class DiscoverEvent with _$DiscoverEvent { 5 | const factory DiscoverEvent.getMovieGenres() = GetMovieGenres; 6 | const factory DiscoverEvent.getPopularPersons() = GetPopularPersons; 7 | } 8 | -------------------------------------------------------------------------------- /macos/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | @NSApplicationMain 5 | class AppDelegate: FlutterAppDelegate { 6 | override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { 7 | return true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /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-7.4-all.zip 7 | -------------------------------------------------------------------------------- /lib/presentation/bloc/navigation_from/navigation_from_state.dart: -------------------------------------------------------------------------------- 1 | part of 'navigation_from_bloc.dart'; 2 | 3 | @freezed 4 | class NavigationFromState with _$NavigationFromState { 5 | const factory NavigationFromState.initial({ 6 | required NavigateFrom navigateFrom, 7 | }) = _Initial; 8 | } 9 | -------------------------------------------------------------------------------- /macos/Runner/Release.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/core/utils/generics/custom_scroll_behavior.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CustomScroll extends ScrollBehavior { 4 | @override 5 | Widget buildViewportChrome( 6 | BuildContext context, Widget child, AxisDirection axisDirection) { 7 | return child; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/presentation/bloc/navigation_from/navigation_from_event.dart: -------------------------------------------------------------------------------- 1 | part of 'navigation_from_bloc.dart'; 2 | 3 | @freezed 4 | class NavigationFromEvent with _$NavigationFromEvent { 5 | const factory NavigationFromEvent.setNavigationFrom({ 6 | required NavigateFrom navigateFrom, 7 | }) = _SetNavigationFrom; 8 | } 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.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 | -------------------------------------------------------------------------------- /lib/core/utils/generics/dialoge_and_snackbar_strings.dart: -------------------------------------------------------------------------------- 1 | class SnackBarMessage { 2 | static const String noSignupPage = 3 | 'There isn\'t currently a signup page. Thank you for your patience. We are attempting to fix it.'; 4 | static const String credentialsNotMatch = 5 | 'Username and Password should be same'; 6 | } 7 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/column_3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/domain/repositories/login/i_login_poster_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/data/models/login/login_poster_model.dart'; 3 | 4 | import '../../../core/errors/network_error/network_error.dart'; 5 | 6 | abstract class ILoginImagesRepo { 7 | Future>> getLoginPosterImages(); 8 | } 9 | -------------------------------------------------------------------------------- /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 | **/*.keystore 13 | **/*.jks 14 | -------------------------------------------------------------------------------- /lib/domain/usecase/dependancy_injection/injectable.dart: -------------------------------------------------------------------------------- 1 | import 'package:get_it/get_it.dart'; 2 | import 'package:injectable/injectable.dart'; 3 | 4 | import 'injectable.config.dart'; 5 | 6 | final getIt = GetIt.instance; 7 | 8 | @InjectableInit() 9 | Future configureInjectable() async { 10 | $initGetIt(getIt, environment: Environment.prod); 11 | } 12 | -------------------------------------------------------------------------------- /lib/data/bloc/search_result/search_result_event.dart: -------------------------------------------------------------------------------- 1 | part of 'search_result_bloc.dart'; 2 | 3 | @freezed 4 | class SearchResultEvent with _$SearchResultEvent { 5 | const factory SearchResultEvent.getPopularMovies() = _GetPopularMovies; 6 | const factory SearchResultEvent.getSearchedMovies({ 7 | required String? query, 8 | }) = _GetSearchedMovies; 9 | } 10 | -------------------------------------------------------------------------------- /lib/domain/repositories/home/image_slider/i_image_slider_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/home/image_slider/image_slider_model.dart'; 4 | 5 | abstract class IImageSliderRepo { 6 | Future>> getImageSliderData(); 7 | } 8 | -------------------------------------------------------------------------------- /lib/core/services/debouncer.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/foundation.dart'; 2 | import 'dart:async'; 3 | 4 | class Debouncer { 5 | final int milliseconds; 6 | Timer? _timer; 7 | 8 | Debouncer({required this.milliseconds}); 9 | 10 | run(VoidCallback action) { 11 | _timer?.cancel(); 12 | _timer = Timer(Duration(milliseconds: milliseconds), action); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /windows/.gitignore: -------------------------------------------------------------------------------- 1 | flutter/ephemeral/ 2 | 3 | # Visual Studio user-specific files. 4 | *.suo 5 | *.user 6 | *.userosscache 7 | *.sln.docstates 8 | 9 | # Visual Studio build-related files. 10 | x64/ 11 | x86/ 12 | 13 | # Visual Studio cache files 14 | # files ending in .cache can be ignored 15 | *.[Cc]ache 16 | # but keep track of directories ending in .cache 17 | !*.[Cc]ache/ 18 | -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /lib/data/sources/remote_data_sources/constatnts.dart: -------------------------------------------------------------------------------- 1 | import 'package:movie_app/domain/usecase/apiKey.dart'; 2 | 3 | const String kBaseUrl = 'https://api.themoviedb.org/3'; 4 | const String kImageBaseUrl = 'https://image.tmdb.org/t/p'; 5 | const String kYoutubeImageBaseUrl = 'https://img.youtube.com/vi/'; 6 | const String kDiscoverUrl = 7 | 'https://api.themoviedb.org/3/discover/movie?api_key=$apiKey'; 8 | -------------------------------------------------------------------------------- /lib/presentation/bloc/watchlist/watchlist_scroll/watchlist_scroll_state.dart: -------------------------------------------------------------------------------- 1 | part of 'watchlist_scroll_cubit.dart'; 2 | 3 | @freezed 4 | class WatchlistScrollState with _$WatchlistScrollState { 5 | const factory WatchlistScrollState.initial({ 6 | required bool watchlistExpanded, 7 | required double watchlistSectionHeight, 8 | required double watchlistHeight, 9 | }) = _Initial; 10 | } 11 | -------------------------------------------------------------------------------- /lib/data/bloc/actor_profile/person_details_event.dart: -------------------------------------------------------------------------------- 1 | part of 'person_details_bloc.dart'; 2 | 3 | @freezed 4 | class PersonDetailsEvent with _$PersonDetailsEvent { 5 | const factory PersonDetailsEvent.getPersonDetails({ 6 | required String personId, 7 | }) = GetPersonDetails; 8 | const factory PersonDetailsEvent.getMovieList({ 9 | required String personId, 10 | }) = GetMovieList; 11 | } 12 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void fl_register_plugins(FlPluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.h: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #ifndef GENERATED_PLUGIN_REGISTRANT_ 8 | #define GENERATED_PLUGIN_REGISTRANT_ 9 | 10 | #include 11 | 12 | // Registers Flutter plugins. 13 | void RegisterPlugins(flutter::PluginRegistry* registry); 14 | 15 | #endif // GENERATED_PLUGIN_REGISTRANT_ 16 | -------------------------------------------------------------------------------- /lib/domain/repositories/dicover/i_discover_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/movie_details/movie_details_model.dart'; 4 | 5 | abstract class IDiscoverRepo { 6 | Future>> getMovieGenres(); 7 | Future>> getPopularPersons(); 8 | } 9 | -------------------------------------------------------------------------------- /lib/domain/repositories/movie_details/i_movie_details_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/movie_details/movie_details_model.dart'; 4 | 5 | abstract class IMovieDetailsRepo { 6 | Future> getMovieDetails({ 7 | required String movieId, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /lib/domain/repositories/actor_profile/i_actor_profile_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/actor_profile/actor_profile_model.dart'; 4 | 5 | abstract class IActorProfileRepo { 6 | Future> getPersonDetails({ 7 | required String personId, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /lib/domain/repositories/home/movie_sroll_list/i_movie_list_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 4 | 5 | abstract class IMovieListRepo { 6 | Future> getMovieListByPerson({ 7 | required String personId, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /macos/Runner/DebugProfile.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.cs.allow-jit 8 | 9 | com.apple.security.network.server 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lib/data/bloc/movies_result_grid/movies_result_grid_event.dart: -------------------------------------------------------------------------------- 1 | part of 'movies_result_grid_bloc.dart'; 2 | 3 | @freezed 4 | class MoviesResultGridEvent with _$MoviesResultGridEvent { 5 | const factory MoviesResultGridEvent.getMovieByGenre({ 6 | required String genre, 7 | }) = _GetMovieByGenre; 8 | const factory MoviesResultGridEvent.getMovieByPerson({ 9 | required String personId, 10 | }) = _GetMovieByPerson; 11 | } 12 | -------------------------------------------------------------------------------- /lib/domain/repositories/upcoming_movies/i_upcoming_movies_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/upcoming_movies/upcoming_movies_model.dart'; 4 | 5 | abstract class IUpcomingMoviesRepo { 6 | Future>> getUpcomingMovies({ 7 | required String date, 8 | }); 9 | } 10 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/inner_appbars/bloc/appbar_search_event.dart: -------------------------------------------------------------------------------- 1 | part of 'appbar_search_bloc.dart'; 2 | 3 | @freezed 4 | class AppbarSearchEvent with _$AppbarSearchEvent { 5 | const factory AppbarSearchEvent.userTappedTextField({ 6 | required bool isTextFieldFocused, 7 | }) = _UserTappedTextField; 8 | const factory AppbarSearchEvent.columnButtonPress({ 9 | required int columnIconIndex, 10 | }) = _ColumnButtonPress; 11 | } 12 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 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 | -------------------------------------------------------------------------------- /lib/domain/repositories/search_result/i_search_result_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 4 | 5 | abstract class ISearchResultRepo { 6 | Future> getPopularMovies(); 7 | Future> getSearchedMovies({ 8 | required String query, 9 | }); 10 | } 11 | -------------------------------------------------------------------------------- /lib/gen/fonts.gen.dart: -------------------------------------------------------------------------------- 1 | /// GENERATED CODE - DO NOT MODIFY BY HAND 2 | /// ***************************************************** 3 | /// FlutterGen 4 | /// ***************************************************** 5 | 6 | // coverage:ignore-file 7 | // ignore_for_file: type=lint 8 | // ignore_for_file: directives_ordering,unnecessary_import 9 | 10 | class FontFamily { 11 | FontFamily._(); 12 | 13 | /// Font family: Poppins 14 | static const String poppins = 'Poppins'; 15 | } 16 | -------------------------------------------------------------------------------- /lib/presentation/bloc/main/bottom_navbar/botom_nav_cubit.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | 4 | part 'botom_nav_state.dart'; 5 | part 'botom_nav_cubit.freezed.dart'; 6 | 7 | class BottomNavCubit extends Cubit { 8 | BottomNavCubit() : super(const BottomNavState.initial(selectedIndex: 0)); 9 | void setIndex(index) => emit(BottomNavState.initial(selectedIndex: index)); 10 | } 11 | -------------------------------------------------------------------------------- /linux/my_application.h: -------------------------------------------------------------------------------- 1 | #ifndef FLUTTER_MY_APPLICATION_H_ 2 | #define FLUTTER_MY_APPLICATION_H_ 3 | 4 | #include 5 | 6 | G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, 7 | GtkApplication) 8 | 9 | /** 10 | * my_application_new: 11 | * 12 | * Creates a new Flutter-based application. 13 | * 14 | * Returns: a new #MyApplication. 15 | */ 16 | MyApplication* my_application_new(); 17 | 18 | #endif // FLUTTER_MY_APPLICATION_H_ 19 | -------------------------------------------------------------------------------- /macos/Runner/MainFlutterWindow.swift: -------------------------------------------------------------------------------- 1 | import Cocoa 2 | import FlutterMacOS 3 | 4 | class MainFlutterWindow: NSWindow { 5 | override func awakeFromNib() { 6 | let flutterViewController = FlutterViewController.init() 7 | let windowFrame = self.frame 8 | self.contentViewController = flutterViewController 9 | self.setFrame(windowFrame, display: true) 10 | 11 | RegisterGeneratedPlugins(registry: flutterViewController) 12 | 13 | super.awakeFromNib() 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /lib/presentation/bloc/home/slider_image/slider_image_cubit.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | 4 | part 'slider_image_state.dart'; 5 | part 'slider_image_cubit.freezed.dart'; 6 | 7 | class SliderImageCubit extends Cubit { 8 | SliderImageCubit() : super(const SliderImageState.initial(currentIndex: 0)); 9 | void setIndex(index) => emit(SliderImageState.initial(currentIndex: index)); 10 | } 11 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/widgets_functionality/widgets_functionality_event.dart: -------------------------------------------------------------------------------- 1 | part of 'widgets_functionality_bloc.dart'; 2 | 3 | @freezed 4 | class WidgetsFunctionalityEvent with _$WidgetsFunctionalityEvent { 5 | // 6 | /// this event is called when user click the button in the movie list scroll widget 7 | const factory WidgetsFunctionalityEvent.listScrollButtonPress({ 8 | required String dayOrWeek, 9 | required int buttonIndex, 10 | }) = _ListScrollButtonPress; 11 | // 12 | } 13 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/inner_appbars/bloc/appbar_search_state.dart: -------------------------------------------------------------------------------- 1 | part of 'appbar_search_bloc.dart'; 2 | 3 | @freezed 4 | class AppbarSearchState with _$AppbarSearchState { 5 | const factory AppbarSearchState({ 6 | required int columnIconIndex, 7 | required bool isTextFieldFocused, 8 | }) = _AppbarSearchState; 9 | factory AppbarSearchState.initial() { 10 | return const AppbarSearchState( 11 | columnIconIndex: 0, 12 | isTextFieldFocused: false, 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /windows/runner/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Runner.rc 4 | // 5 | #define IDI_APP_ICON 101 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 102 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /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/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-v21/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /lib/domain/repositories/movies_result_grid/i_movies_result_grid_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 4 | 5 | abstract class IMoviesResultGridRepo { 6 | Future> getMoviesByGenre({ 7 | required String genre, 8 | }); 9 | Future> getMoviesByPerson({ 10 | required String personId, 11 | }); 12 | } 13 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | 11 | void fl_register_plugins(FlPluginRegistry* registry) { 12 | g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = 13 | fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); 14 | url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); 15 | } 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/data/bloc/home/image_slider/image_slider_state.dart: -------------------------------------------------------------------------------- 1 | part of 'image_slider_bloc.dart'; 2 | 3 | @freezed 4 | class ImageSliderState with _$ImageSliderState { 5 | const factory ImageSliderState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required List imageSliderDataList, 9 | }) = _ImageSliderState; 10 | 11 | factory ImageSliderState.initial() { 12 | return const ImageSliderState( 13 | isLoading: true, 14 | hasError: false, 15 | imageSliderDataList: [], 16 | ); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /lib/data/bloc/home/home_data/home_data_event.dart: -------------------------------------------------------------------------------- 1 | part of 'home_data_bloc.dart'; 2 | 3 | @freezed 4 | class HomeDataEvent with _$HomeDataEvent { 5 | const factory HomeDataEvent.getTopRatedMovies() = _GetTopRatedMovies; 6 | const factory HomeDataEvent.getTrendingMovies({ 7 | required String dayOrWeek, 8 | }) = _GetTrendingMovies; 9 | const factory HomeDataEvent.getTopTamilMovies() = _GetTopTamilMovies; 10 | const factory HomeDataEvent.getTopHindiMovies() = _GetTopHindiMovies; 11 | const factory HomeDataEvent.getTopMalayalamMovies() = _GetTopMalayalamMovies; 12 | } 13 | -------------------------------------------------------------------------------- /lib/data/models/login/login_poster_model.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | part 'login_poster_model.freezed.dart'; 5 | part 'login_poster_model.g.dart'; 6 | 7 | @freezed 8 | class LoginPoster with _$LoginPoster { 9 | const factory LoginPoster({ 10 | required double? popularity, 11 | @JsonKey(name: "poster_path") required String? posterPath, 12 | }) = _LoginPoster; 13 | 14 | factory LoginPoster.fromJson(Map json) => 15 | _$LoginPosterFromJson(json); 16 | } 17 | -------------------------------------------------------------------------------- /lib/data/bloc/login/login_poster/login_poster_state.dart: -------------------------------------------------------------------------------- 1 | part of 'login_poster_bloc.dart'; 2 | 3 | @freezed 4 | class LoginPosterState with _$LoginPosterState { 5 | const factory LoginPosterState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required List loginPosterDataList, 10 | }) = _LoginPosterState; 11 | 12 | factory LoginPosterState.initial() { 13 | return const LoginPosterState( 14 | isLoading: true, 15 | hasError: false, 16 | isSuccess: false, 17 | loginPosterDataList: [], 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/data/bloc/upcoming_movies/upcoming_movies_state.dart: -------------------------------------------------------------------------------- 1 | part of 'upcoming_movies_bloc.dart'; 2 | 3 | @freezed 4 | class UpcomingMoviesState with _$UpcomingMoviesState { 5 | const factory UpcomingMoviesState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required List dataList, 10 | }) = _UpcomingMoviesState; 11 | 12 | factory UpcomingMoviesState.initial() { 13 | return const UpcomingMoviesState( 14 | isLoading: true, 15 | hasError: false, 16 | isSuccess: false, 17 | dataList: [], 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/data/models/home/image_slider/image_slider_model.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: invalid_annotation_target 2 | 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | 5 | part 'image_slider_model.freezed.dart'; 6 | part 'image_slider_model.g.dart'; 7 | 8 | @freezed 9 | class ImageSlider with _$ImageSlider { 10 | const factory ImageSlider({ 11 | required int id, 12 | @JsonKey(name: 'poster_path') required String posterPath, 13 | required String title, 14 | }) = _ImageSlider; 15 | 16 | factory ImageSlider.fromJson(Map json) => 17 | _$ImageSliderFromJson(json); 18 | } 19 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugin_registrant.cc: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | // clang-format off 6 | 7 | #include "generated_plugin_registrant.h" 8 | 9 | #include 10 | #include 11 | 12 | void RegisterPlugins(flutter::PluginRegistry* registry) { 13 | ConnectivityPlusWindowsPluginRegisterWithRegistrar( 14 | registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); 15 | UrlLauncherWindowsRegisterWithRegistrar( 16 | registry->GetRegistrarForPlugin("UrlLauncherWindows")); 17 | } 18 | -------------------------------------------------------------------------------- /lib/core/utils/generics/app_route/app_router.dart: -------------------------------------------------------------------------------- 1 | // import 'package:auto_route/auto_route.dart'; 2 | // import 'package:flutter/material.dart'; 3 | 4 | // import '../../../../presentation/pages/home/view/home_page.dart'; 5 | // import '../../../../presentation/pages/splash/view/splash_page.dart'; 6 | 7 | // part 'app_router.gr.dart'; 8 | 9 | // @MaterialAutoRouter( 10 | // replaceInRouteName: 'Page,Route', 11 | // routes: [ 12 | // MaterialRoute(page: SplashPage, path: '/splash', initial: true), 13 | // MaterialRoute(page: HomePage, path: '/home'), 14 | // ], 15 | // ) 16 | // class $AppRouter {} 17 | -------------------------------------------------------------------------------- /lib/data/bloc/discover/discover_state.dart: -------------------------------------------------------------------------------- 1 | part of 'discover_bloc.dart'; 2 | 3 | @freezed 4 | class DiscoverState with _$DiscoverState { 5 | const factory DiscoverState( 6 | {required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required List genresDataList, 10 | required List personDataList}) = _DiscoverState; 11 | factory DiscoverState.initial() { 12 | return const DiscoverState( 13 | isLoading: true, 14 | hasError: false, 15 | isSuccess: false, 16 | genresDataList: [], 17 | personDataList: [], 18 | ); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/presentation/pages/home/widgets/skelton/widgets/image_slider_skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/components/skelton.dart'; 5 | import 'package:movie_app/presentation/themes/values.dart'; 6 | 7 | class ImageSliderSkelton__widget extends StatelessWidget { 8 | const ImageSliderSkelton__widget({Key? key}) : super(key: key); 9 | @override 10 | Widget build(BuildContext context) { 11 | return Skelton__widget( 12 | child: Container( 13 | decoration: const BoxDecoration(color: kSkeltonColor), 14 | ), 15 | ); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /macos/Runner/Configs/Warnings.xcconfig: -------------------------------------------------------------------------------- 1 | WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings 2 | GCC_WARN_UNDECLARED_SELECTOR = YES 3 | CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES 4 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE 5 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES 6 | CLANG_WARN_PRAGMA_PACK = YES 7 | CLANG_WARN_STRICT_PROTOTYPES = YES 8 | CLANG_WARN_COMMA = YES 9 | GCC_WARN_STRICT_SELECTOR_MATCH = YES 10 | CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES 11 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES 12 | GCC_WARN_SHADOW = YES 13 | CLANG_WARN_UNREACHABLE_CODE = YES 14 | -------------------------------------------------------------------------------- /macos/Runner/Configs/AppInfo.xcconfig: -------------------------------------------------------------------------------- 1 | // Application-level settings for the Runner target. 2 | // 3 | // This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the 4 | // future. If not, the values below would default to using the project name when this becomes a 5 | // 'flutter create' template. 6 | 7 | // The application's name. By default this is also the title of the Flutter window. 8 | PRODUCT_NAME = movie_app 9 | 10 | // The application's bundle identifier 11 | PRODUCT_BUNDLE_IDENTIFIER = com.example.movieApp 12 | 13 | // The copyright displayed in application information 14 | PRODUCT_COPYRIGHT = Copyright © 2022 com.example. All rights reserved. 15 | -------------------------------------------------------------------------------- /lib/core/services/app_default_preferences.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:shared_preferences/shared_preferences.dart'; 4 | 5 | Future prefInit() async { 6 | return await SharedPreferences.getInstance(); 7 | } 8 | 9 | Future setIconIndex(int index) async { 10 | final pref = await SharedPreferences.getInstance(); 11 | pref.setInt('indexKey', index); 12 | log('Set index to $index '); 13 | } 14 | 15 | Future getIconIndex() async { 16 | final pref = await SharedPreferences.getInstance(); 17 | final getIndexKey = pref.getInt('indexKey'); 18 | if (getIndexKey != null) { 19 | return getIndexKey; 20 | } 21 | return 0; 22 | } 23 | -------------------------------------------------------------------------------- /assets/icons/play.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/widgets_functionality/widgets_functionality_state.dart: -------------------------------------------------------------------------------- 1 | part of 'widgets_functionality_bloc.dart'; 2 | 3 | @freezed 4 | class WidgetsFunctionalityState with _$WidgetsFunctionalityState { 5 | const factory WidgetsFunctionalityState({ 6 | /// 7 | /// state for movie list scroll button 8 | required int movieListScrollButtonCurrentIndex, 9 | required String movieListScrollButtonQuery, 10 | // 11 | }) = _WidgetsFunctionalityState; 12 | factory WidgetsFunctionalityState.initial() { 13 | // 14 | return const WidgetsFunctionalityState( 15 | movieListScrollButtonCurrentIndex: 0, 16 | movieListScrollButtonQuery: TrendigMovies.allDay); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /ios/.gitignore: -------------------------------------------------------------------------------- 1 | **/dgph 2 | *.mode1v3 3 | *.mode2v3 4 | *.moved-aside 5 | *.pbxuser 6 | *.perspectivev3 7 | **/*sync/ 8 | .sconsign.dblite 9 | .tags* 10 | **/.vagrant/ 11 | **/DerivedData/ 12 | Icon? 13 | **/Pods/ 14 | **/.symlinks/ 15 | profile 16 | xcuserdata 17 | **/.generated/ 18 | Flutter/App.framework 19 | Flutter/Flutter.framework 20 | Flutter/Flutter.podspec 21 | Flutter/Generated.xcconfig 22 | Flutter/ephemeral/ 23 | Flutter/app.flx 24 | Flutter/app.zip 25 | Flutter/flutter_assets/ 26 | Flutter/flutter_export_environment.sh 27 | ServiceDefinitions.json 28 | Runner/GeneratedPluginRegistrant.* 29 | 30 | # Exceptions to above rules. 31 | !default.mode1v3 32 | !default.mode2v3 33 | !default.pbxuser 34 | !default.perspectivev3 35 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:7.1.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 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 | -------------------------------------------------------------------------------- /lib/domain/repositories/home/i_home_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 3 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 4 | 5 | abstract class IHomeRepo { 6 | Future>> getTopRatedMovies(); 7 | Future>> getTrendingMovies({ 8 | required String dayOrWeek, 9 | }); 10 | // Future>> getLatestTrailers(); 11 | Future>> getTopTamilMovies(); 12 | Future>> getTopHindiMovies(); 13 | Future>> getTopMalayalamMovies(); 14 | } 15 | -------------------------------------------------------------------------------- /lib/data/bloc/movies_result_grid/movies_result_grid_state.dart: -------------------------------------------------------------------------------- 1 | part of 'movies_result_grid_bloc.dart'; 2 | 3 | @freezed 4 | class MoviesResultGridState with _$MoviesResultGridState { 5 | const factory MoviesResultGridState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required MovieList movieDataList, 10 | }) = _MoviesResultGridState; 11 | factory MoviesResultGridState.initial() { 12 | return const MoviesResultGridState( 13 | isLoading: true, 14 | hasError: false, 15 | isSuccess: false, 16 | movieDataList: MovieList( 17 | page: 0, 18 | results: [], 19 | totalPages: 0, 20 | totalResults: 0, 21 | ), 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /windows/runner/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_UTILS_H_ 2 | #define RUNNER_UTILS_H_ 3 | 4 | #include 5 | #include 6 | 7 | // Creates a console for the process, and redirects stdout and stderr to 8 | // it for both the runner and the Flutter library. 9 | void CreateAndAttachConsole(); 10 | 11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string 12 | // encoded in UTF-8. Returns an empty std::string on failure. 13 | std::string Utf8FromUtf16(const wchar_t* utf16_string); 14 | 15 | // Gets the command line arguments passed in as a std::vector, 16 | // encoded in UTF-8. Returns an empty std::vector on failure. 17 | std::vector GetCommandLineArguments(); 18 | 19 | #endif // RUNNER_UTILS_H_ 20 | -------------------------------------------------------------------------------- /lib/data/models/login/login_poster_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'login_poster_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$_LoginPoster _$$_LoginPosterFromJson(Map json) => 10 | _$_LoginPoster( 11 | popularity: (json['popularity'] as num?)?.toDouble(), 12 | posterPath: json['poster_path'] as String?, 13 | ); 14 | 15 | Map _$$_LoginPosterToJson(_$_LoginPoster instance) => 16 | { 17 | 'popularity': instance.popularity, 18 | 'poster_path': instance.posterPath, 19 | }; 20 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/inner_appbars/bloc/appbar_search_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | 4 | part 'appbar_search_bloc.freezed.dart'; 5 | part 'appbar_search_event.dart'; 6 | part 'appbar_search_state.dart'; 7 | 8 | class AppbarSearchBloc extends Bloc { 9 | AppbarSearchBloc() : super(AppbarSearchState.initial()) { 10 | /// 11 | /// 12 | on<_UserTappedTextField>((event, emit) { 13 | emit(state.copyWith(isTextFieldFocused: event.isTextFieldFocused)); 14 | }); 15 | // 16 | on<_ColumnButtonPress>((event, emit) { 17 | emit(state.copyWith(columnIconIndex: event.columnIconIndex)); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/presentation/pages/movie_details/widgets/skelton/poster_image_skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/components/skelton.dart'; 5 | import 'package:movie_app/presentation/themes/screen_size_config.dart'; 6 | import 'package:movie_app/presentation/themes/values.dart'; 7 | 8 | class PosterImageSkelton__widget extends StatelessWidget { 9 | const PosterImageSkelton__widget({Key? key}) : super(key: key); 10 | @override 11 | Widget build(BuildContext context) { 12 | return Skelton__widget( 13 | child: Container( 14 | height: getScreenHeightPercentage(80.0), 15 | width: ScreenConfig.screenWidth, 16 | color: kSkeltonColor, 17 | )); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/core/utils/generics/sort_list_by.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | class SortListBy { 4 | static desc(List list, String sortKey) { 5 | List newList = list.toList(); 6 | if (list.isNotEmpty) { 7 | newList.sort((a, b) => (a[sortKey]).compareTo(b[sortKey])); 8 | if (newList.isNotEmpty) { 9 | return newList.reversed.toList(); 10 | } else { 11 | log(newList.toString()); 12 | } 13 | } 14 | } 15 | 16 | static asce(List list, sortKey) { 17 | List newList = list; 18 | if (list.isNotEmpty) { 19 | newList.sort((a, b) => (a.sortKey).compareTo(b.sortkey)); 20 | if (newList.isNotEmpty) { 21 | return newList.toList(); 22 | } else { 23 | log(newList.toString()); 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/presentation/bloc/navigation_from/navigation_from_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:movie_app/presentation/pages/main/view/main_page.dart'; 4 | 5 | part 'navigation_from_bloc.freezed.dart'; 6 | part 'navigation_from_event.dart'; 7 | part 'navigation_from_state.dart'; 8 | 9 | class NavigationFromBloc 10 | extends Bloc { 11 | NavigationFromBloc() 12 | : super(const _Initial( 13 | navigateFrom: NavigateFrom.none, 14 | )) { 15 | // 16 | // 17 | // 18 | on<_SetNavigationFrom>((event, emit) { 19 | emit(NavigationFromState.initial(navigateFrom: event.navigateFrom)); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/core/services/navigator.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class PageNav { 4 | static push(BuildContext context, page) { 5 | Navigator.of(context).push(MaterialPageRoute(builder: (ctx) => page)); 6 | } 7 | 8 | static pushAndReplace(BuildContext context, page) { 9 | Navigator.of(context) 10 | .pushReplacement(MaterialPageRoute(builder: (ctx) => page)); 11 | } 12 | 13 | static pop(BuildContext context) { 14 | Navigator.pop(context); 15 | } 16 | 17 | static popUntil(BuildContext context) { 18 | Navigator.popUntil(context, (route) => false); 19 | } 20 | 21 | static pushAndRemoveUntil(BuildContext context, page) { 22 | Navigator.pushAndRemoveUntil(context, 23 | MaterialPageRoute(builder: (context) => page), (route) => false); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/data/models/home/image_slider/image_slider_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'image_slider_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$_ImageSlider _$$_ImageSliderFromJson(Map json) => 10 | _$_ImageSlider( 11 | id: json['id'] as int, 12 | posterPath: json['poster_path'] as String, 13 | title: json['title'] as String, 14 | ); 15 | 16 | Map _$$_ImageSliderToJson(_$_ImageSlider instance) => 17 | { 18 | 'id': instance.id, 19 | 'poster_path': instance.posterPath, 20 | 'title': instance.title, 21 | }; 22 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "movie_app", 9 | "request": "launch", 10 | "type": "dart" 11 | }, 12 | { 13 | "name": "movie_app (profile mode)", 14 | "request": "launch", 15 | "type": "dart", 16 | "flutterMode": "profile" 17 | }, 18 | { 19 | "name": "movie_app (release mode)", 20 | "request": "launch", 21 | "type": "dart", 22 | "flutterMode": "release" 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /lib/data/bloc/actor_profile/person_details_state.dart: -------------------------------------------------------------------------------- 1 | part of 'person_details_bloc.dart'; 2 | 3 | @freezed 4 | class PersonDetailsState with _$PersonDetailsState { 5 | const factory PersonDetailsState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required PersonDetails personData, 10 | required MovieList movieDataList, 11 | }) = _PersonDetailsState; 12 | 13 | factory PersonDetailsState.initial() { 14 | return const PersonDetailsState( 15 | isLoading: true, 16 | hasError: false, 17 | isSuccess: false, 18 | personData: PersonDetails(id: 0), 19 | movieDataList: MovieList( 20 | page: 0, 21 | results: [], 22 | totalPages: 0, 23 | totalResults: 0, 24 | ), 25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lib/presentation/pages/actor_profile/widgets/biogarphy_bottomsheet.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../components/basic_bottomsheet.dart'; 6 | import '../../../components/text.dart'; 7 | 8 | class BiogarphyBottomsheet__widget extends StatelessWidget { 9 | const BiogarphyBottomsheet__widget({Key? key, required this.text}) 10 | : super(key: key); 11 | 12 | final String text; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return BasicBottomsheet__widget( 17 | title: 'Biography', 18 | children: [ 19 | Medium__text( 20 | text: text, 21 | fontSize: 14.0, 22 | height: 1.4, 23 | letterSpacing: 0.9, 24 | ), 25 | ], 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/data/bloc/search_result/search_result_state.dart: -------------------------------------------------------------------------------- 1 | part of 'search_result_bloc.dart'; 2 | 3 | @freezed 4 | class SearchResultState with _$SearchResultState { 5 | const factory SearchResultState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSuccess, 9 | required MovieList popularDataList, 10 | required MovieList searchedDataList, 11 | }) = _SearchResultState; 12 | 13 | factory SearchResultState.initial() { 14 | return const SearchResultState( 15 | isLoading: true, 16 | hasError: false, 17 | isSuccess: false, 18 | popularDataList: 19 | MovieList(page: 0, results: [], totalPages: 0, totalResults: 0), 20 | searchedDataList: 21 | MovieList(page: 0, results: [], totalPages: 0, totalResults: 0)); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /macos/Flutter/GeneratedPluginRegistrant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Generated file. Do not edit. 3 | // 4 | 5 | import FlutterMacOS 6 | import Foundation 7 | 8 | import connectivity_plus 9 | import path_provider_macos 10 | import shared_preferences_macos 11 | import sqflite 12 | import url_launcher_macos 13 | 14 | func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { 15 | ConnectivityPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlugin")) 16 | PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) 17 | SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) 18 | SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) 19 | UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) 20 | } 21 | -------------------------------------------------------------------------------- /lib/data/models/upcoming_movies/upcoming_movies_model.dart: -------------------------------------------------------------------------------- 1 | // To parse this JSON data, do 2 | // 3 | // final upcomingMovies = upcomingMoviesFromJson(jsonString); 4 | 5 | // ignore_for_file: invalid_annotation_target 6 | 7 | import 'package:freezed_annotation/freezed_annotation.dart'; 8 | 9 | part 'upcoming_movies_model.freezed.dart'; 10 | part 'upcoming_movies_model.g.dart'; 11 | 12 | @freezed 13 | abstract class UpcomingMovies with _$UpcomingMovies { 14 | const factory UpcomingMovies({ 15 | required int id, 16 | String? overview, 17 | @JsonKey(name: 'poster_path') String? posterPath, 18 | @JsonKey(name: 'release_date') String? releaseDate, 19 | String? title, 20 | }) = _UpcomingMovies; 21 | 22 | factory UpcomingMovies.fromJson(Map json) => 23 | _$UpcomingMoviesFromJson(json); 24 | } 25 | -------------------------------------------------------------------------------- /lib/presentation/bloc/main/appbar/appbar_bloc.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unused_element, invalid_use_of_visible_for_testing_member 2 | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | 6 | part 'appbar_event.dart'; 7 | part 'appbar_state.dart'; 8 | part 'appbar_bloc.freezed.dart'; 9 | 10 | enum HomePageCurrentPage { movies, tvShows } 11 | 12 | class AppbarBloc extends Bloc { 13 | AppbarBloc() 14 | : super(const _Initial(currentPage: HomePageCurrentPage.movies)) { 15 | on<_MoviesSelected>((event, emit) { 16 | emit(state.copyWith(currentPage: HomePageCurrentPage.movies)); 17 | }); 18 | 19 | on<_TvShowsSelected>((event, emit) { 20 | emit(state.copyWith(currentPage: HomePageCurrentPage.tvShows)); 21 | }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /.github/workflows/build_apk_action.yml: -------------------------------------------------------------------------------- 1 | name: Flutter Apk Build Action 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v1 13 | - uses: actions/setup-java@v1 14 | with: 15 | java-version: '12.x' 16 | - uses: subosito/flutter-action@v1 17 | with: 18 | channel: 'stable' 19 | - uses: "finnp/create-file-action@master" 20 | env: 21 | FILE_NAME: "lib/domain/usecase/apiKey.dart" 22 | FILE_DATA: "const String apiKey = '${{secrets.API_KEY}}';" 23 | - run: flutter pub get 24 | - run: flutter build apk 25 | - uses: actions/upload-artifact@v1 26 | with: 27 | name: release-apk 28 | path: build/app/outputs/apk/release/app-release.apk 29 | -------------------------------------------------------------------------------- /lib/data/bloc/home/home_data/home_data_state.dart: -------------------------------------------------------------------------------- 1 | part of 'home_data_bloc.dart'; 2 | 3 | @freezed 4 | class HomeDataState with _$HomeDataState { 5 | const factory HomeDataState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required bool isSucces, 9 | required List topRatedList, 10 | required List trendingList, 11 | required List topTamilList, 12 | required List topHindiList, 13 | required List topMalayalamList, 14 | }) = _HomeDataState; 15 | 16 | factory HomeDataState.initial() { 17 | return const HomeDataState( 18 | isLoading: true, 19 | hasError: false, 20 | isSucces: false, 21 | topRatedList: [], 22 | trendingList: [], 23 | topTamilList: [], 24 | topHindiList: [], 25 | topMalayalamList: [], 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/presentation/themes/colors.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | const kColorWhite = Color(0xffffffff); 4 | const kColorBlack = Color(0xff000000); 5 | 6 | const kColorWhite10 = Color(0x10ffffff); 7 | const kColorWhite20 = Color(0x20ffffff); 8 | const kColorWhite50 = Color(0x50ffffff); 9 | const kColorWhite60 = Color(0x60ffffff); 10 | const kColorWhite70 = Color(0x70ffffff); 11 | const kColorWhite80 = Color(0x80ffffff); 12 | 13 | const kColorPrimary = Color(0xff14181D); 14 | const kColorSecondary = Color(0x10FFFFFF); 15 | const kColorAccent = Color(0xffF83A43); 16 | 17 | const kColorPrimary80 = Color(0x8014181D); 18 | 19 | const kColorPrimaryTint_1 = Color(0xff202428); 20 | const kColorPrimaryTint_2 = Color(0xff4D5259); 21 | const kColorPrimaryTint_3 = Color(0xff788189); 22 | const kColorGreen = Color(0xff00E164); 23 | const kColorYellow = Color(0xffF8D043); 24 | -------------------------------------------------------------------------------- /linux/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | url_launcher_linux 7 | ) 8 | 9 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 10 | ) 11 | 12 | set(PLUGIN_BUNDLED_LIBRARIES) 13 | 14 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 15 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) 16 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 17 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 19 | endforeach(plugin) 20 | 21 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 22 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) 23 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 24 | endforeach(ffi_plugin) 25 | -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 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 | 9.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /windows/flutter/generated_plugins.cmake: -------------------------------------------------------------------------------- 1 | # 2 | # Generated file, do not edit. 3 | # 4 | 5 | list(APPEND FLUTTER_PLUGIN_LIST 6 | connectivity_plus 7 | url_launcher_windows 8 | ) 9 | 10 | list(APPEND FLUTTER_FFI_PLUGIN_LIST 11 | ) 12 | 13 | set(PLUGIN_BUNDLED_LIBRARIES) 14 | 15 | foreach(plugin ${FLUTTER_PLUGIN_LIST}) 16 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) 17 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) 18 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $) 19 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) 20 | endforeach(plugin) 21 | 22 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) 23 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) 24 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) 25 | endforeach(ffi_plugin) 26 | -------------------------------------------------------------------------------- /assets/icons/chevron_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/presentation/components/poster_card.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, prefer_typing_uninitialized_variables 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | class PosterCard__widget extends StatelessWidget { 6 | const PosterCard__widget({ 7 | Key? key, 8 | required this.image, 9 | this.onTap, 10 | }) : super(key: key); 11 | 12 | final image; 13 | final VoidCallback? onTap; 14 | 15 | @override 16 | Widget build(BuildContext context) { 17 | return GestureDetector( 18 | onTap: onTap, 19 | child: AspectRatio( 20 | aspectRatio: 10 / 16, 21 | child: Container( 22 | decoration: BoxDecoration( 23 | borderRadius: BorderRadius.circular(8), 24 | image: DecorationImage( 25 | image: image, 26 | fit: BoxFit.cover, 27 | ), 28 | ), 29 | ), 30 | ), 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/presentation/bloc/components/widgets_functionality/widgets_functionality_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_bloc/flutter_bloc.dart'; 2 | import 'package:freezed_annotation/freezed_annotation.dart'; 3 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 4 | 5 | part 'widgets_functionality_bloc.freezed.dart'; 6 | part 'widgets_functionality_event.dart'; 7 | part 'widgets_functionality_state.dart'; 8 | 9 | class WidgetsFunctionalityBloc 10 | extends Bloc { 11 | WidgetsFunctionalityBloc() : super(WidgetsFunctionalityState.initial()) { 12 | /// 13 | /// On movie list scroll button press event 14 | on<_ListScrollButtonPress>((event, emit) { 15 | emit(state.copyWith( 16 | movieListScrollButtonCurrentIndex: event.buttonIndex, 17 | movieListScrollButtonQuery: event.dayOrWeek, 18 | )); 19 | }); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /assets/icons/chevron_left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /windows/runner/runner.exe.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PerMonitorV2 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /lib/presentation/pages/splash/view/splash_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:movie_app/core/services/login_service.dart'; 3 | import 'package:movie_app/presentation/components/background.dart'; 4 | 5 | import '../../../../gen/assets.gen.dart'; 6 | import '../../../themes/screen_size_config.dart'; 7 | 8 | class SplashPage extends StatefulWidget { 9 | const SplashPage({Key? key}) : super(key: key); 10 | 11 | @override 12 | State createState() => _SplashPageState(); 13 | } 14 | 15 | class _SplashPageState extends State { 16 | @override 17 | void initState() { 18 | chechkUserLoggedIn(context); 19 | super.initState(); 20 | } 21 | 22 | @override 23 | Widget build(BuildContext context) { 24 | ScreenConfig().init(context); 25 | return Scaffold( 26 | body: Background( 27 | child: Center( 28 | child: Assets.images.logo1.svg(), 29 | ), 30 | ), 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/data/models/actor_profile/actor_profile_model.dart: -------------------------------------------------------------------------------- 1 | // To parse this JSON data, do 2 | // 3 | // final personDetails = personDetailsFromJson(jsonString); 4 | 5 | // ignore_for_file: invalid_annotation_target 6 | 7 | import 'package:freezed_annotation/freezed_annotation.dart'; 8 | 9 | part 'actor_profile_model.freezed.dart'; 10 | part 'actor_profile_model.g.dart'; 11 | 12 | @freezed 13 | abstract class PersonDetails with _$PersonDetails { 14 | const factory PersonDetails({ 15 | required int id, 16 | String? name, 17 | String? birthday, 18 | dynamic deathday, 19 | int? gender, 20 | @JsonKey(name: 'known_for_department') String? knownForDepartment, 21 | String? biography, 22 | @JsonKey(name: 'place_of_birth') String? placeOfBirth, 23 | double? popularity, 24 | @JsonKey(name: 'profile_path') String? profilePath, 25 | }) = _PersonDetails; 26 | 27 | factory PersonDetails.fromJson(Map json) => 28 | _$PersonDetailsFromJson(json); 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | migrate_working_dir/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | **/ios/Flutter/.last_build_id 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | /build/ 34 | 35 | # Web related 36 | lib/generated_plugin_registrant.dart 37 | 38 | # Symbolication related 39 | app.*.symbols 40 | 41 | # Obfuscation related 42 | app.*.map.json 43 | 44 | # Android Studio will place build artifacts here 45 | /android/app/debug 46 | /android/app/profile 47 | /android/app/release 48 | 49 | # ingored files 50 | lib/domain/usecase/apiKey.dart -------------------------------------------------------------------------------- /assets/icons/home.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/data/models/upcoming_movies/upcoming_movies_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'upcoming_movies_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$_UpcomingMovies _$$_UpcomingMoviesFromJson(Map json) => 10 | _$_UpcomingMovies( 11 | id: json['id'] as int, 12 | overview: json['overview'] as String?, 13 | posterPath: json['poster_path'] as String?, 14 | releaseDate: json['release_date'] as String?, 15 | title: json['title'] as String?, 16 | ); 17 | 18 | Map _$$_UpcomingMoviesToJson(_$_UpcomingMovies instance) => 19 | { 20 | 'id': instance.id, 21 | 'overview': instance.overview, 22 | 'poster_path': instance.posterPath, 23 | 'release_date': instance.releaseDate, 24 | 'title': instance.title, 25 | }; 26 | -------------------------------------------------------------------------------- /assets/icons/heart_fill.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /web/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "movie_app", 3 | "short_name": "movie_app", 4 | "start_url": ".", 5 | "display": "standalone", 6 | "background_color": "#0175C2", 7 | "theme_color": "#0175C2", 8 | "description": "A new Flutter project.", 9 | "orientation": "portrait-primary", 10 | "prefer_related_applications": false, 11 | "icons": [ 12 | { 13 | "src": "icons/Icon-192.png", 14 | "sizes": "192x192", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "icons/Icon-512.png", 19 | "sizes": "512x512", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "icons/Icon-maskable-192.png", 24 | "sizes": "192x192", 25 | "type": "image/png", 26 | "purpose": "maskable" 27 | }, 28 | { 29 | "src": "icons/Icon-maskable-512.png", 30 | "sizes": "512x512", 31 | "type": "image/png", 32 | "purpose": "maskable" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /windows/runner/flutter_window.h: -------------------------------------------------------------------------------- 1 | #ifndef RUNNER_FLUTTER_WINDOW_H_ 2 | #define RUNNER_FLUTTER_WINDOW_H_ 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include "win32_window.h" 10 | 11 | // A window that does nothing but host a Flutter view. 12 | class FlutterWindow : public Win32Window { 13 | public: 14 | // Creates a new FlutterWindow hosting a Flutter view running |project|. 15 | explicit FlutterWindow(const flutter::DartProject& project); 16 | virtual ~FlutterWindow(); 17 | 18 | protected: 19 | // Win32Window: 20 | bool OnCreate() override; 21 | void OnDestroy() override; 22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, 23 | LPARAM const lparam) noexcept override; 24 | 25 | private: 26 | // The project to run. 27 | flutter::DartProject project_; 28 | 29 | // The Flutter instance hosted by this window. 30 | std::unique_ptr flutter_controller_; 31 | }; 32 | 33 | #endif // RUNNER_FLUTTER_WINDOW_H_ 34 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /lib/data/bloc/movie_details/movie_details_state.dart: -------------------------------------------------------------------------------- 1 | part of 'movie_details_bloc.dart'; 2 | 3 | @freezed 4 | class MovieDetailsState with _$MovieDetailsState { 5 | const factory MovieDetailsState({ 6 | required bool isLoading, 7 | required bool hasError, 8 | required MovieDetails movieDetailsData, 9 | }) = _MovieDetailsState; 10 | 11 | factory MovieDetailsState.initial() { 12 | return const MovieDetailsState( 13 | isLoading: true, 14 | hasError: false, 15 | movieDetailsData: MovieDetails( 16 | id: 0, 17 | backdropPath: '', 18 | genres: [], 19 | overview: '', 20 | popularity: 0.0, 21 | posterPath: '', 22 | releaseDate: '', 23 | runtime: 0, 24 | status: '', 25 | tagline: '', 26 | title: '', 27 | voteAverage: 0.0, 28 | videos: Videos(results: []), 29 | casts: Casts(cast: []), 30 | reviews: Reviews( 31 | page: 0, 32 | results: [], 33 | totalPages: 0, 34 | totalResults: 0, 35 | ), 36 | ), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/icons/arrow_left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /macos/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | $(PRODUCT_COPYRIGHT) 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /lib/presentation/components/blurred_background.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'dart:ui'; 4 | 5 | import 'package:flutter/material.dart'; 6 | import 'package:movie_app/presentation/themes/colors.dart'; 7 | import 'package:movie_app/presentation/themes/screen_size_config.dart'; 8 | 9 | class BlurredBackground__widget extends StatelessWidget { 10 | const BlurredBackground__widget({ 11 | Key? key, 12 | required this.child, 13 | this.borderRadius, 14 | this.blur, 15 | this.color, 16 | }) : super(key: key); 17 | 18 | final Widget child; 19 | final BorderRadius? borderRadius; 20 | final double? blur; 21 | final Color? color; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return ClipRRect( 26 | borderRadius: borderRadius ?? BorderRadius.circular(0), 27 | child: BackdropFilter( 28 | filter: ImageFilter.blur(sigmaX: blur ?? 10.0, sigmaY: blur ?? 10.0), 29 | child: Container( 30 | width: ScreenConfig.screenWidth, 31 | decoration: BoxDecoration( 32 | color: color ?? kColorBlack.withOpacity(0.2), 33 | ), 34 | child: child, 35 | ), 36 | ), 37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /assets/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/presentation/components/snackbar/snackbar.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:get/get.dart'; 5 | import 'package:movie_app/presentation/themes/colors.dart'; 6 | import 'package:movie_app/presentation/themes/values.dart'; 7 | 8 | class Snackbar__widget { 9 | const Snackbar__widget({ 10 | required this.message, 11 | this.title, 12 | this.isDismissible, 13 | }); 14 | 15 | final String? title; 16 | final String message; 17 | final bool? isDismissible; 18 | 19 | buildSnackBar() { 20 | return Get.snackbar(title ?? '', message, 21 | snackPosition: SnackPosition.BOTTOM, 22 | snackStyle: SnackStyle.GROUNDED, 23 | margin: const EdgeInsets.only(bottom: 0), 24 | duration: const Duration(seconds: 4), 25 | isDismissible: isDismissible ?? true, 26 | backgroundColor: kColorPrimary80, 27 | padding: title != null 28 | ? null 29 | : const EdgeInsets.only( 30 | bottom: kDefaultPadding, 31 | left: kDefaultPadding, 32 | right: kDefaultPadding, 33 | ), 34 | animationDuration: const Duration(milliseconds: 500)); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /lib/data/repositories/actor_profile/actor_profile_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/actor_profile/actor_profile_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/actor_profile/i_actor_profile_repo.dart'; 10 | 11 | @LazySingleton(as: IActorProfileRepo) 12 | class PersonDetailsRepository implements IActorProfileRepo { 13 | @override 14 | Future> getPersonDetails({ 15 | required String personId, 16 | }) async { 17 | try { 18 | final response = 19 | await Dio(BaseOptions()).get(ApiEndPoints.personDetails(personId)); 20 | 21 | // log(jsonEncode(response.data).toString()); 22 | 23 | final dataList = PersonDetails.fromJson(response.data); 24 | 25 | // log(jsonEncode(dataList).toString()); 26 | return Right(dataList); 27 | } catch (e) { 28 | log(e.toString()); 29 | return Left(NetworkError.getDioException(e)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/data/repositories/movie_details/movie_details_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/movie_details/movie_details_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/movie_details/i_movie_details_repo.dart'; 10 | 11 | @LazySingleton(as: IMovieDetailsRepo) 12 | class MovieDetailsRepository implements IMovieDetailsRepo { 13 | @override 14 | Future> getMovieDetails({ 15 | required String movieId, 16 | }) async { 17 | try { 18 | final response = 19 | await Dio(BaseOptions()).get(ApiEndPoints.movieDetils(movieId)); 20 | 21 | // log(jsonEncode(response.data).toString()); 22 | 23 | final dataList = MovieDetails.fromJson(response.data); 24 | 25 | // log(jsonEncode(dataList.casts!.cast).toString()); 26 | return Right(dataList); 27 | } catch (e) { 28 | log(e.toString()); 29 | return Left(NetworkError.getDioException(e)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/data/models/home/movie_list/movie_list_model.dart: -------------------------------------------------------------------------------- 1 | // To parse this JSON data, do 2 | // 3 | // final movieList = movieListFromJson(jsonString); 4 | 5 | // ignore_for_file: invalid_annotation_target 6 | 7 | import 'package:freezed_annotation/freezed_annotation.dart'; 8 | 9 | part 'movie_list_model.freezed.dart'; 10 | part 'movie_list_model.g.dart'; 11 | 12 | @freezed 13 | class MovieList with _$MovieList { 14 | const factory MovieList({ 15 | required int page, 16 | required List results, 17 | @JsonKey(name: 'total_pages') required int totalPages, 18 | @JsonKey(name: 'total_results') required int totalResults, 19 | }) = _MovieList; 20 | 21 | factory MovieList.fromJson(Map json) => 22 | _$MovieListFromJson(json); 23 | } 24 | 25 | @freezed 26 | class Result with _$Result { 27 | const factory Result({ 28 | required int id, 29 | String? title, 30 | @JsonKey(name: 'poster_path') String? posterPath, 31 | double? popularity, 32 | @JsonKey(name: 'release_date') String? releaseDate, 33 | @JsonKey(name: 'vote_average') double? voteAverage, 34 | @JsonKey(name: 'vote_count') int? voteCount, 35 | }) = _Result; 36 | 37 | factory Result.fromJson(Map json) => _$ResultFromJson(json); 38 | } 39 | -------------------------------------------------------------------------------- /lib/presentation/components/image_container.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 5 | 6 | import '../themes/colors.dart'; 7 | 8 | class ImageContainer__widget extends StatelessWidget { 9 | const ImageContainer__widget({ 10 | Key? key, 11 | required this.imageData, 12 | required this.height, 13 | required this.width, 14 | this.radius, 15 | this.boxshadow, 16 | this.imageWidth = ImageWidth.w342, 17 | }) : super(key: key); 18 | 19 | final String imageData; 20 | final double height; 21 | final double width; 22 | final double? radius; 23 | final List? boxshadow; 24 | final ImageWidth? imageWidth; 25 | 26 | @override 27 | Widget build(BuildContext context) { 28 | return Container( 29 | height: height, 30 | width: width, 31 | decoration: BoxDecoration( 32 | color: kColorPrimary, 33 | boxShadow: boxshadow, 34 | borderRadius: BorderRadius.circular(radius ?? 0.0), 35 | image: DecorationImage( 36 | image: NetworkImage(ApiDataFetching.image(imageData, imageWidth!)), 37 | fit: BoxFit.cover, 38 | ), 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/data/repositories/login/login_poster_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:dio/dio.dart'; 3 | import 'package:injectable/injectable.dart'; 4 | import 'package:movie_app/data/models/login/login_poster_model.dart'; 5 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 6 | import 'package:movie_app/domain/repositories/login/i_login_poster_repo.dart'; 7 | 8 | import '../../../core/errors/network_error/network_error.dart'; 9 | 10 | @LazySingleton(as: ILoginImagesRepo) 11 | class LoginPosterRepository implements ILoginImagesRepo { 12 | @override 13 | Future>> getLoginPosterImages() async { 14 | try { 15 | final response = await Dio(BaseOptions()) 16 | .get(ApiEndPoints.trendingMovies(TrendigMovies.allDay)); 17 | 18 | final loginPostersList = (response.data["results"] as List) 19 | .map((e) => LoginPoster.fromJson(e)) 20 | .toList(); 21 | loginPostersList.sort(((a, b) => a.popularity!.compareTo(b.popularity!))); 22 | 23 | // log(loginPostersList.reversed.toList().toString()); 24 | return Right(loginPostersList.reversed.toList()); 25 | } catch (e) { 26 | // log(e.toString()); 27 | return Left(NetworkError.getDioException(e)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/presentation/pages/actor_profile/widgets/title_and_data.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: public_member_api_docs, sort_constructors_first, camel_case_types 2 | import 'package:flutter/material.dart'; 3 | 4 | import '../../../components/text.dart'; 5 | import '../../../themes/colors.dart'; 6 | import '../../../themes/values.dart'; 7 | 8 | class TitleAndData__widget extends StatelessWidget { 9 | const TitleAndData__widget({ 10 | Key? key, 11 | required this.title, 12 | required this.data, 13 | }) : super(key: key); 14 | 15 | final String title; 16 | final String data; 17 | 18 | @override 19 | Widget build(BuildContext context) { 20 | return Column( 21 | crossAxisAlignment: CrossAxisAlignment.start, 22 | children: [ 23 | const SizedBox(height: kDefaultPadding / 2), 24 | Regular__text( 25 | text: title, 26 | fontSize: 14.0, 27 | color: kColorWhite60, 28 | height: 1.4, 29 | maxLines: 1, 30 | textOverFlow: TextOverflow.ellipsis, 31 | ), 32 | Regular__text( 33 | text: data, 34 | fontSize: 14.0, 35 | color: kColorWhite, 36 | height: 1.4, 37 | maxLines: 3, 38 | textOverFlow: TextOverflow.ellipsis, 39 | ), 40 | ], 41 | ); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/presentation/pages/home/widgets/skelton/widgets/movie_list_scroll.skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/core/utils/generics/custom_widget_builder.dart'; 5 | import 'package:movie_app/presentation/components/skelton.dart'; 6 | import 'package:movie_app/presentation/themes/values.dart'; 7 | 8 | class MovieListScrollSkelton__widget extends StatelessWidget { 9 | const MovieListScrollSkelton__widget({Key? key}) : super(key: key); 10 | @override 11 | Widget build(BuildContext context) { 12 | return Skelton__widget( 13 | child: Padding( 14 | padding: const EdgeInsets.symmetric(horizontal: 32), 15 | child: Column( 16 | crossAxisAlignment: CrossAxisAlignment.start, 17 | children: [ 18 | const SkeltonContent(height: 16.0, width: 150.0), 19 | const SizedBox(height: kDefaultPadding), 20 | CustomListViewBuilder( 21 | scrollDirection: Axis.horizontal, 22 | itemCount: 3, 23 | contentSpacing: kDefaultPadding, 24 | builder: (context, index) => 25 | const SkeltonContent(height: 200.0, width: 130.0), 26 | ) 27 | ], 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/presentation/pages/home/widgets/skelton/widgets/movie_list_scroll_skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/core/utils/generics/custom_widget_builder.dart'; 5 | import 'package:movie_app/presentation/components/skelton.dart'; 6 | import 'package:movie_app/presentation/themes/values.dart'; 7 | 8 | class MovieListScrollSkelton__widget extends StatelessWidget { 9 | const MovieListScrollSkelton__widget({Key? key}) : super(key: key); 10 | @override 11 | Widget build(BuildContext context) { 12 | return Skelton__widget( 13 | child: Padding( 14 | padding: const EdgeInsets.symmetric(horizontal: 32), 15 | child: Column( 16 | crossAxisAlignment: CrossAxisAlignment.start, 17 | children: [ 18 | const SkeltonContent(height: 16.0, width: 150.0), 19 | const SizedBox(height: kDefaultPadding), 20 | CustomListViewBuilder( 21 | scrollDirection: Axis.horizontal, 22 | itemCount: 3, 23 | contentSpacing: kDefaultPadding, 24 | builder: (context, index) => 25 | const SkeltonContent(height: 200.0, width: 130.0), 26 | ) 27 | ], 28 | ), 29 | ), 30 | ); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/presentation/themes/values.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'colors.dart'; 6 | 7 | const kFontFamily = 'Poppins'; 8 | 9 | /// 10 | /// spacing values 11 | const double kDefaultPadding = 16; 12 | 13 | // blur 14 | const double kDefaultBlur = 50.0; 15 | 16 | // boxshadow 17 | final kDefaultBoxShadow = [ 18 | BoxShadow( 19 | color: kColorPrimary.withOpacity(0.7), 20 | offset: const Offset(0, 7), 21 | blurRadius: 20, 22 | ), 23 | ]; 24 | 25 | //hint text style 26 | const TextStyle kHintTextStyle = TextStyle( 27 | fontFamily: 'Poppins', 28 | fontSize: 16, 29 | fontWeight: FontWeight.w400, 30 | color: kColorWhite50, 31 | ); 32 | 33 | //error text style 34 | const TextStyle kErrorTextStyle = TextStyle( 35 | fontFamily: 'Poppins', 36 | fontSize: 12, 37 | fontWeight: FontWeight.w500, 38 | color: kColorAccent, 39 | ); 40 | 41 | //hint text style 42 | const TextStyle kLabelTextStyle = TextStyle( 43 | fontFamily: 'Poppins', 44 | fontSize: 16, 45 | fontWeight: FontWeight.w400, 46 | color: kColorWhite, 47 | ); 48 | 49 | // skelton Colors 50 | const kSkeltonColor = kColorWhite; 51 | const kSkeltonBaseColor = kColorPrimaryTint_2; 52 | const kSkeltonHighlightColor = kColorPrimaryTint_3; 53 | 54 | 55 | //enums 56 | 57 | -------------------------------------------------------------------------------- /assets/icons/person.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /windows/runner/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(runner LANGUAGES CXX) 3 | 4 | # Define the application target. To change its name, change BINARY_NAME in the 5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer 6 | # work. 7 | # 8 | # Any new source files that you add to the application should be added here. 9 | add_executable(${BINARY_NAME} WIN32 10 | "flutter_window.cpp" 11 | "main.cpp" 12 | "utils.cpp" 13 | "win32_window.cpp" 14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" 15 | "Runner.rc" 16 | "runner.exe.manifest" 17 | ) 18 | 19 | # Apply the standard set of build settings. This can be removed for applications 20 | # that need different build settings. 21 | apply_standard_settings(${BINARY_NAME}) 22 | 23 | # Disable Windows macros that collide with C++ standard library functions. 24 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") 25 | 26 | # Add dependency libraries and include directories. Add any application-specific 27 | # dependencies here. 28 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) 29 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") 30 | 31 | # Run the Flutter tool portions of the build. This must not be removed. 32 | add_dependencies(${BINARY_NAME} flutter_assemble) 33 | -------------------------------------------------------------------------------- /assets/icons/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/presentation/pages/home/widgets/skelton/widgets/genres_scroll_skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/core/utils/generics/custom_widget_builder.dart'; 5 | import 'package:movie_app/presentation/components/skelton.dart'; 6 | import 'package:movie_app/presentation/themes/values.dart'; 7 | 8 | class GenresScrollSkelton__widget extends StatelessWidget { 9 | const GenresScrollSkelton__widget({Key? key}) : super(key: key); 10 | @override 11 | Widget build(BuildContext context) { 12 | return Skelton__widget( 13 | child: CustomListViewBuilder( 14 | scrollDirection: Axis.horizontal, 15 | padding: const EdgeInsets.symmetric(horizontal: kDefaultPadding * 2), 16 | itemCount: 5, 17 | contentSpacing: kDefaultPadding, 18 | builder: (context, index) { 19 | return Container( 20 | padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 32), 21 | decoration: BoxDecoration( 22 | borderRadius: BorderRadius.circular(8), 23 | color: kSkeltonBaseColor, 24 | ), 25 | child: const Center( 26 | child: SkeltonContent(height: 14.0, width: 56.0), 27 | ), 28 | ); 29 | }, 30 | ), 31 | ); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /lib/data/repositories/upcoming_movies/upcoming_movies_repo.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:dio/dio.dart'; 3 | import 'package:injectable/injectable.dart'; 4 | import 'package:movie_app/data/models/upcoming_movies/upcoming_movies_model.dart'; 5 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 6 | import 'package:movie_app/domain/repositories/upcoming_movies/i_upcoming_movies_repo.dart'; 7 | 8 | import '../../../core/errors/network_error/network_error.dart'; 9 | 10 | @LazySingleton(as: IUpcomingMoviesRepo) 11 | class UpcomingMoviesRepository implements IUpcomingMoviesRepo { 12 | @override 13 | Future>> getUpcomingMovies({ 14 | required String date, 15 | }) async { 16 | try { 17 | final response = await Dio(BaseOptions()) 18 | .get(ApiEndPoints.upcomingMovies(date, Language.malayalam)); 19 | 20 | final dataList = (response.data["results"] as List) 21 | .map((e) => UpcomingMovies.fromJson(e)) 22 | .toList(); 23 | dataList.sort(((a, b) => a.releaseDate!.compareTo(b.releaseDate!))); 24 | 25 | // log(json.encode(dataList).toString()); 26 | return Right(dataList); 27 | } catch (e) { 28 | // log(e.toString()); 29 | return Left(NetworkError.getDioException(e)); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /lib/presentation/pages/profile/widgets/profile_menu_item.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, prefer_typing_uninitialized_variables 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../components/text.dart'; 6 | import '../../../themes/colors.dart'; 7 | import '../../../themes/values.dart'; 8 | 9 | class ProfileMenuItem__widget extends StatelessWidget { 10 | const ProfileMenuItem__widget({ 11 | Key? key, 12 | required this.icon, 13 | required this.text, 14 | this.onTap, 15 | }) : super(key: key); 16 | 17 | final icon; 18 | final String text; 19 | final VoidCallback? onTap; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return GestureDetector( 24 | onTap: onTap, 25 | child: Padding( 26 | padding: const EdgeInsets.only(bottom: 8.0), 27 | child: Container( 28 | padding: const EdgeInsets.all(kDefaultPadding), 29 | decoration: BoxDecoration( 30 | color: kColorWhite10, 31 | borderRadius: BorderRadius.circular(8), 32 | ), 33 | child: Row( 34 | children: [ 35 | icon.svg(), 36 | const SizedBox(width: kDefaultPadding / 2), 37 | Regular__text( 38 | text: text, 39 | fontSize: 14.0, 40 | ), 41 | ], 42 | ), 43 | ), 44 | ), 45 | ); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/presentation/pages/watchlist/widgets/title_with_toggle.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/themes/colors.dart'; 5 | 6 | import '../../../components/text.dart'; 7 | 8 | class TitleWithToggle__widget extends StatefulWidget { 9 | const TitleWithToggle__widget({Key? key}) : super(key: key); 10 | 11 | @override 12 | State createState() => 13 | _TitleWithToggle__widgetState(); 14 | } 15 | 16 | bool _buttonstate = false; 17 | 18 | class _TitleWithToggle__widgetState extends State { 19 | @override 20 | Widget build(BuildContext context) { 21 | return Padding( 22 | padding: const EdgeInsets.symmetric( 23 | horizontal: 32, 24 | ), 25 | child: Row( 26 | crossAxisAlignment: CrossAxisAlignment.center, 27 | children: [ 28 | const Medium__text(text: 'Watch List', fontSize: 16.0), 29 | const Spacer(), 30 | const Regular__text(text: 'Downloaded Only', fontSize: 14.0), 31 | Switch( 32 | activeColor: kColorAccent, 33 | activeTrackColor: kColorWhite.withOpacity(0.8), 34 | value: _buttonstate, 35 | onChanged: (value) { 36 | setState(() => _buttonstate = !_buttonstate); 37 | }) 38 | ], 39 | ), 40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /windows/runner/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "flutter_window.h" 6 | #include "utils.h" 7 | 8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, 9 | _In_ wchar_t *command_line, _In_ int show_command) { 10 | // Attach to console when present (e.g., 'flutter run') or create a 11 | // new console when running with a debugger. 12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { 13 | CreateAndAttachConsole(); 14 | } 15 | 16 | // Initialize COM, so that it is available for use in the library and/or 17 | // plugins. 18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); 19 | 20 | flutter::DartProject project(L"data"); 21 | 22 | std::vector command_line_arguments = 23 | GetCommandLineArguments(); 24 | 25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); 26 | 27 | FlutterWindow window(project); 28 | Win32Window::Point origin(10, 10); 29 | Win32Window::Size size(1280, 720); 30 | if (!window.CreateAndShow(L"movie_app", origin, size)) { 31 | return EXIT_FAILURE; 32 | } 33 | window.SetQuitOnClose(true); 34 | 35 | ::MSG msg; 36 | while (::GetMessage(&msg, nullptr, 0, 0)) { 37 | ::TranslateMessage(&msg); 38 | ::DispatchMessage(&msg); 39 | } 40 | 41 | ::CoUninitialize(); 42 | return EXIT_SUCCESS; 43 | } 44 | -------------------------------------------------------------------------------- /assets/icons/download.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/chat.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/presentation/components/dialogs/error_widget.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/components/text.dart'; 5 | 6 | class ErrorWidget__widget extends StatelessWidget { 7 | const ErrorWidget__widget({Key? key, required this.errorDetails}) 8 | : super(key: key); 9 | 10 | final FlutterErrorDetails errorDetails; 11 | 12 | @override 13 | Widget build(BuildContext context) { 14 | return Container( 15 | decoration: const BoxDecoration(color: Colors.red), 16 | child: Padding( 17 | padding: const EdgeInsets.all(16), 18 | child: Column( 19 | children: [ 20 | Row( 21 | crossAxisAlignment: CrossAxisAlignment.center, 22 | children: const [ 23 | Icon(Icons.error), 24 | SizedBox(width: 8), 25 | Medium__text( 26 | text: 'Error', 27 | fontSize: 16.0, 28 | color: Colors.white, 29 | ) 30 | ], 31 | ), 32 | const SizedBox(height: 16.0), 33 | Regular__text( 34 | text: errorDetails.exceptionAsString(), 35 | fontSize: 16.0, 36 | color: Colors.white, 37 | height: 1.2, 38 | letterSpacing: 0.5, 39 | ), 40 | ], 41 | ), 42 | ), 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/data/models/actor_profile/actor_profile_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'actor_profile_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$_PersonDetails _$$_PersonDetailsFromJson(Map json) => 10 | _$_PersonDetails( 11 | id: json['id'] as int, 12 | name: json['name'] as String?, 13 | birthday: json['birthday'] as String?, 14 | deathday: json['deathday'], 15 | gender: json['gender'] as int?, 16 | knownForDepartment: json['known_for_department'] as String?, 17 | biography: json['biography'] as String?, 18 | placeOfBirth: json['place_of_birth'] as String?, 19 | popularity: (json['popularity'] as num?)?.toDouble(), 20 | profilePath: json['profile_path'] as String?, 21 | ); 22 | 23 | Map _$$_PersonDetailsToJson(_$_PersonDetails instance) => 24 | { 25 | 'id': instance.id, 26 | 'name': instance.name, 27 | 'birthday': instance.birthday, 28 | 'deathday': instance.deathday, 29 | 'gender': instance.gender, 30 | 'known_for_department': instance.knownForDepartment, 31 | 'biography': instance.biography, 32 | 'place_of_birth': instance.placeOfBirth, 33 | 'popularity': instance.popularity, 34 | 'profile_path': instance.profilePath, 35 | }; 36 | -------------------------------------------------------------------------------- /lib/presentation/components/dialogs/exit_app_dialoge.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/components/button.dart'; 5 | import 'package:movie_app/presentation/components/text.dart'; 6 | import 'package:movie_app/presentation/themes/colors.dart'; 7 | import 'package:movie_app/presentation/themes/values.dart'; 8 | 9 | Future showExitAppDialoge(BuildContext ctx) async { 10 | bool? exitApp = await showDialog( 11 | context: ctx, 12 | builder: (ctx) => AlertDialog( 13 | backgroundColor: kColorPrimary, 14 | title: const Medium__text(text: 'Confirm Exit', fontSize: 16.0), 15 | content: const Regular__text( 16 | text: 'Are you sure to exit the application ?', fontSize: 14.0), 17 | actions: [ 18 | Row( 19 | mainAxisAlignment: MainAxisAlignment.end, 20 | children: [ 21 | Primary_Small__button( 22 | text: 'No', 23 | onTap: () => Navigator.of(ctx).pop(false), 24 | ), 25 | const SizedBox(width: kDefaultPadding), 26 | Primary_Small__button( 27 | text: 'Yes', 28 | onTap: () => Navigator.of(ctx).pop(true), 29 | ), 30 | ], 31 | ), 32 | ], 33 | actionsPadding: const EdgeInsets.only( 34 | right: kDefaultPadding, 35 | bottom: kDefaultPadding, 36 | ), 37 | ), 38 | ); 39 | return exitApp ?? false; 40 | } 41 | -------------------------------------------------------------------------------- /lib/presentation/themes/theme.dart: -------------------------------------------------------------------------------- 1 | // import 'package:flutter/material.dart'; 2 | 3 | // ThemeData themeData(BuildContext context) { 4 | // return ThemeData( 5 | // scaffoldBackgroundColor: Colors.white, 6 | // appBarTheme: const AppBarTheme(color: Colors.transparent, elevation: 0), 7 | // colorScheme: ColorScheme.fromSwatch( 8 | // primarySwatch: Colors.indigo, 9 | // ).copyWith(secondary: Colors.amber), 10 | // cardTheme: const CardTheme( 11 | // color: kSurfaceColorLight, 12 | // elevation: 0, 13 | // // shadowColor: kShadowColor, 14 | // ), 15 | // textTheme: TextTheme( 16 | // bodyText2: kBodyText2Light, 17 | // subtitle1: kSubtitle1Light, 18 | // headlineLarge: kHeadlineLargeLight, 19 | // ), 20 | // ); 21 | // } 22 | 23 | // ThemeData themeDataDark(BuildContext context) { 24 | // return ThemeData( 25 | // scaffoldBackgroundColor: const Color(0xff0A0E0F), 26 | // appBarTheme: const AppBarTheme(color: Colors.transparent, elevation: 0), 27 | // colorScheme: ColorScheme.fromSwatch( 28 | // primarySwatch: Colors.indigo, 29 | // ).copyWith(secondary: Colors.amber), 30 | // cardTheme: const CardTheme( 31 | // color: kSurfaceColorDark, 32 | // elevation: 0, 33 | // // shadowColor: kShadowColor, 34 | // ), 35 | // textTheme: TextTheme( 36 | // bodyText2: kBodyText2Dark, 37 | // subtitle1: kSubtitle1Dark, 38 | // headlineLarge: kHeadlineLargeDark, 39 | // ), 40 | // ); 41 | // } 42 | -------------------------------------------------------------------------------- /lib/presentation/themes/text_form_field.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, prefer_typing_uninitialized_variables 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import 'colors.dart'; 6 | import 'values.dart'; 7 | 8 | class TextFormField__widget extends StatelessWidget { 9 | const TextFormField__widget({ 10 | Key? key, 11 | required this.hint, 12 | this.prefixIcon, 13 | required this.controller, 14 | this.validator, 15 | this.initialValue, 16 | this.obscureText = false, 17 | this.keyboardType = TextInputType.text, 18 | this.onChanged, 19 | }) : super(key: key); 20 | 21 | final String hint; 22 | 23 | final String? initialValue; 24 | final prefixIcon; 25 | final TextEditingController controller; 26 | final bool obscureText; 27 | final TextInputType keyboardType; 28 | final String? Function(String?)? validator; 29 | final Function(String)? onChanged; 30 | 31 | @override 32 | Widget build(BuildContext context) { 33 | return TextFormField( 34 | initialValue: initialValue, 35 | obscureText: obscureText, 36 | controller: controller, 37 | keyboardType: keyboardType, 38 | validator: validator, 39 | decoration: InputDecoration( 40 | border: InputBorder.none, 41 | hintText: hint, 42 | hintStyle: kHintTextStyle, 43 | labelStyle: kLabelTextStyle, 44 | errorStyle: kErrorTextStyle, 45 | ), 46 | cursorColor: kColorWhite, 47 | onChanged: onChanged, 48 | ); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /assets/icons/share.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/password.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /lib/presentation/pages/upcoming_movies/widgets/upcoming_movie_date.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/core/utils/generics/string_manipulation.dart'; 5 | 6 | import '../../../components/text.dart'; 7 | import '../../../themes/colors.dart'; 8 | import '../../../themes/values.dart'; 9 | 10 | class UpcomingMovieDate__widget extends StatelessWidget { 11 | const UpcomingMovieDate__widget({Key? key, required this.date}) 12 | : super(key: key); 13 | 14 | final String date; 15 | 16 | @override 17 | Widget build(BuildContext context) { 18 | return Row( 19 | crossAxisAlignment: CrossAxisAlignment.start, 20 | children: [ 21 | Regular__text( 22 | text: StringExtraction.toDay(date), 23 | fontSize: 64.0, 24 | color: kColorWhite60, 25 | ), 26 | const SizedBox(width: kDefaultPadding / 2), 27 | Column( 28 | crossAxisAlignment: CrossAxisAlignment.start, 29 | children: [ 30 | Regular__text( 31 | text: StringExtraction.toMonthText(date), 32 | fontSize: 20.0, 33 | color: kColorWhite60, 34 | ), 35 | const SizedBox(height: kDefaultPadding / 2), 36 | Regular__text( 37 | text: StringExtraction.toYear(date), 38 | fontSize: 20.0, 39 | color: kColorWhite60, 40 | ), 41 | ], 42 | ) 43 | ], 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lib/presentation/components/rating_indicator.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, unnecessary_null_comparison 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/components/text.dart'; 5 | 6 | import '../themes/colors.dart'; 7 | 8 | class RatingIndicator__widget extends StatelessWidget { 9 | const RatingIndicator__widget({Key? key, required this.ratingValue}) 10 | : super(key: key); 11 | 12 | final double ratingValue; 13 | 14 | @override 15 | Widget build(BuildContext context) { 16 | return ClipOval( 17 | child: Container( 18 | color: kColorPrimary, 19 | height: 50, 20 | width: 50, 21 | child: Stack( 22 | children: [ 23 | Center( 24 | child: CircularProgressIndicator( 25 | backgroundColor: kColorWhite50, 26 | color: getColor(ratingValue), 27 | strokeWidth: 3, 28 | value: ratingValue != null ? ratingValue / 10 : 0.0, 29 | ), 30 | ), 31 | Center( 32 | child: SemiBold__text( 33 | text: ratingValue.toString(), 34 | fontSize: 16.0, 35 | ), 36 | ) 37 | ], 38 | ), 39 | ), 40 | ); 41 | } 42 | 43 | getColor(double rating) { 44 | if (rating >= 6) { 45 | return kColorGreen; 46 | } 47 | if (rating >= 4) { 48 | return kColorYellow; 49 | } else { 50 | return kColorAccent; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /assets/icons/mic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | # This file configures the analyzer, which statically analyzes Dart code to 2 | # check for errors, warnings, and lints. 3 | # 4 | # The issues identified by the analyzer are surfaced in the UI of Dart-enabled 5 | # IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be 6 | # invoked from the command line by running `flutter analyze`. 7 | 8 | # The following line activates a set of recommended lints for Flutter apps, 9 | # packages, and plugins designed to encourage good coding practices. 10 | include: package:flutter_lints/flutter.yaml 11 | 12 | linter: 13 | # The lint rules applied to this project can be customized in the 14 | # section below to disable rules from the `package:flutter_lints/flutter.yaml` 15 | # included above or to enable additional rules. A list of all available lints 16 | # and their documentation is published at 17 | # https://dart-lang.github.io/linter/lints/index.html. 18 | # 19 | # Instead of disabling a lint rule for the entire project in the 20 | # section below, it can also be suppressed for a single line of code 21 | # or a specific dart file by using the `// ignore: name_of_lint` and 22 | # `// ignore_for_file: name_of_lint` syntax on the line or in the file 23 | # producing the lint. 24 | rules: 25 | # avoid_print: false # Uncomment to disable the `avoid_print` rule 26 | # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule 27 | 28 | # Additional information about this file can be found at 29 | # https://dart.dev/guides/language/analysis-options 30 | -------------------------------------------------------------------------------- /assets/icons/time.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/icons/logout.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: movie_app 2 | description: A new Flutter project. 3 | 4 | publish_to: 'none' # Remove this line if 5 | 6 | version: 1.0.0+1 7 | 8 | environment: 9 | sdk: ">=2.17.6 <3.0.0" 10 | 11 | dependencies: 12 | auto_route: ^5.0.1 13 | cached_network_image: ^3.2.1 14 | carousel_slider: ^4.1.1 15 | connectivity_plus: ^3.0.2 16 | dartz: ^0.10.1 17 | dio: ^4.0.6 18 | flutter: 19 | sdk: flutter 20 | flutter_bloc: ^8.0.1 21 | flutter_svg: ^1.1.3 22 | freezed_annotation: ^2.1.0 23 | get: ^4.6.5 24 | get_it: ^7.2.0 25 | injectable: ^1.5.3 26 | intl: ^0.17.0 27 | json_annotation: ^4.6.0 28 | shared_preferences: ^2.0.15 29 | shimmer: ^2.0.0 30 | youtube_player_iframe: ^3.1.0 31 | 32 | dev_dependencies: 33 | auto_route_generator: ^5.0.1 34 | build_runner: ^2.2.0 35 | flutter_gen_runner: ^4.3.0 36 | flutter_lints: ^2.0.0 37 | flutter_test: 38 | sdk: flutter 39 | freezed: ^2.1.0+1 40 | injectable_generator: ^1.5.4 41 | json_serializable: ^6.3.1 42 | 43 | flutter_gen: 44 | integrations: 45 | flutter_svg: true 46 | 47 | flutter: 48 | 49 | uses-material-design: true 50 | 51 | assets: 52 | - assets/icons/ 53 | - assets/images/ 54 | 55 | fonts: 56 | - family: Poppins 57 | fonts: 58 | - asset: assets/fonts/Poppins-Bold.ttf 59 | weight: 700 60 | 61 | - asset: assets/fonts/Poppins-Medium.ttf 62 | weight: 600 63 | 64 | - asset: assets/fonts/Poppins-SemiBold.ttf 65 | weight: 500 66 | 67 | - asset: assets/fonts/Poppins-Regular.ttf 68 | weight: 400 69 | -------------------------------------------------------------------------------- /lib/core/utils/generics/string_manipulation.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: unrelated_type_equality_checks 2 | 3 | import 'package:intl/intl.dart'; 4 | 5 | // 6 | class StringExtraction { 7 | static toYear(String stringDate) { 8 | assert(stringDate.length >= 10, 'toYear: json data error'); 9 | final String year = stringDate.substring(0, 4); 10 | return year; 11 | } 12 | 13 | static toMonthNumber(String stringDate) { 14 | assert(stringDate.length >= 10, 'toMonthNumber: json data error'); 15 | final String monthNumber = stringDate.substring(5, 7); 16 | return monthNumber; 17 | } 18 | 19 | static toMonthText(String stringDate) { 20 | assert(stringDate.length >= 10, 'toMonthText: json data error'); 21 | String monthString = toMonthNumber(stringDate); 22 | int monthNumber = int.parse(monthString); 23 | String monthText = DateFormat('MMM').format(DateTime(0, monthNumber)); 24 | return monthText; 25 | } 26 | 27 | static toDay(String stringDate) { 28 | assert(stringDate.length >= 10, 'toDay: json data error'); 29 | final String day = stringDate.substring(8, 10); 30 | return day; 31 | } 32 | 33 | static toMovieRating(String string) { 34 | final padLeft = string.padLeft(5, "0"); 35 | assert(padLeft.length >= 5, 'toMovieRating: json data error'); 36 | final String rating = padLeft.substring(0, 4); 37 | return rating; 38 | } 39 | } 40 | 41 | // slipting text and picking the words from the list 42 | 43 | getFirstWord(String string) { 44 | List splitted = splitText(string); 45 | return splitted[0]; 46 | } 47 | 48 | splitText(String string) => string.split(' '); 49 | -------------------------------------------------------------------------------- /macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "app_icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "app_icon_32.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "app_icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "app_icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "app_icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "app_icon_256.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "app_icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "app_icon_512.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "app_icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "app_icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/presentation/bloc/watchlist/watchlist_scroll/watchlist_scroll_cubit.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | import 'package:flutter/rendering.dart'; 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | import 'package:movie_app/presentation/themes/screen_size_config.dart'; 6 | 7 | part 'watchlist_scroll_state.dart'; 8 | part 'watchlist_scroll_cubit.freezed.dart'; 9 | 10 | class WatchlistScrollCubit extends Cubit { 11 | WatchlistScrollCubit() 12 | : super(WatchlistScrollState.initial( 13 | watchlistExpanded: false, 14 | watchlistSectionHeight: getScreenHeightPercentage(63.0), 15 | watchlistHeight: getScreenHeightPercentage(51.0), 16 | )); 17 | 18 | void userScrolled(ScrollController controller) { 19 | controller.addListener(() { 20 | if (controller.offset > 40.0 && 21 | controller.position.userScrollDirection == ScrollDirection.reverse) { 22 | emit(WatchlistScrollState.initial( 23 | watchlistExpanded: true, 24 | watchlistSectionHeight: getScreenHeightPercentage(83.0), 25 | watchlistHeight: getScreenHeightPercentage(73.0), 26 | )); 27 | } 28 | if (controller.offset < 40.0 && 29 | controller.position.userScrollDirection == ScrollDirection.forward) { 30 | emit(WatchlistScrollState.initial( 31 | watchlistExpanded: false, 32 | watchlistSectionHeight: getScreenHeightPercentage(63.0), 33 | watchlistHeight: getScreenHeightPercentage(51.0), 34 | )); 35 | } 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lib/presentation/components/background.dart: -------------------------------------------------------------------------------- 1 | import 'dart:ui'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/themes/values.dart'; 5 | 6 | import '../../gen/assets.gen.dart'; 7 | import '../themes/colors.dart'; 8 | import '../themes/screen_size_config.dart'; 9 | 10 | class Background extends StatelessWidget { 11 | const Background({ 12 | Key? key, 13 | required this.child, 14 | this.height, 15 | this.borderRadius, 16 | }) : super(key: key); 17 | final Widget child; 18 | final double? height; 19 | final BorderRadius? borderRadius; 20 | @override 21 | Widget build(BuildContext context) { 22 | return Stack( 23 | alignment: Alignment.topCenter, 24 | children: [ 25 | ClipRRect( 26 | borderRadius: borderRadius ?? BorderRadius.zero, 27 | child: Container( 28 | width: ScreenConfig.screenWidth, 29 | height: height, 30 | decoration: BoxDecoration( 31 | image: DecorationImage( 32 | image: AssetImage(Assets.images.bgImage.path), 33 | fit: BoxFit.cover, 34 | colorFilter: ColorFilter.mode( 35 | kColorPrimary.withOpacity(0.5), 36 | BlendMode.multiply, 37 | ), 38 | ), 39 | ), 40 | child: BackdropFilter( 41 | filter: ImageFilter.blur( 42 | sigmaX: kDefaultBlur, 43 | sigmaY: kDefaultBlur, 44 | ), 45 | child: child, 46 | ), 47 | ), 48 | ), 49 | ], 50 | ); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /lib/presentation/themes/screen_size_config.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/cupertino.dart'; 2 | 3 | const double designScreenHeight = 844.0; 4 | const double designScreenWidth = 390.0; 5 | 6 | /// 7 | /// return current screen's height, width and orientation 8 | class ScreenConfig { 9 | static MediaQueryData? _mediaQueryData; 10 | static late double screenHeight; 11 | static late double screenWidth; 12 | static Orientation? orientation; 13 | 14 | void init(BuildContext context) { 15 | _mediaQueryData = MediaQuery.of(context); 16 | screenWidth = _mediaQueryData!.size.width; 17 | screenHeight = _mediaQueryData!.size.height; 18 | orientation = _mediaQueryData!.orientation; 19 | } 20 | } 21 | 22 | /// 23 | /// return screen's height percentage 24 | double getScreenHeightPercentage(double percentageValue) { 25 | double screenHeight = ScreenConfig.screenHeight; 26 | return (percentageValue / 100) * screenHeight; 27 | } 28 | 29 | /// 30 | /// return screen's with percentage 31 | double getScreenWidthPercentage(double percentageValue) { 32 | double screenWidth = ScreenConfig.screenWidth; 33 | return (percentageValue / 100) * screenWidth; 34 | } 35 | 36 | /// 37 | /// return size based on design screen height 38 | double getScreenPropotionalHeight(double inputHeight) { 39 | double screenHeight = ScreenConfig.screenHeight; 40 | return (inputHeight / designScreenHeight) * screenHeight; 41 | } 42 | 43 | /// 44 | /// return size based on design screen width 45 | double getScreenPropotionalWidth(double inputWidth) { 46 | double screenWidth = ScreenConfig.screenWidth; 47 | return (inputWidth / designScreenWidth) * screenWidth; 48 | } 49 | -------------------------------------------------------------------------------- /lib/presentation/pages/movie_details/widgets/movie_title_section.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../../gen/assets.gen.dart'; 6 | import '../../../components/icon_button.dart'; 7 | import '../../../components/text.dart'; 8 | import '../../../themes/colors.dart'; 9 | import '../../../themes/values.dart'; 10 | 11 | class MovieTitleSection__widget extends StatelessWidget { 12 | const MovieTitleSection__widget({ 13 | Key? key, 14 | required this.title, 15 | required this.tagline, 16 | }) : super(key: key); 17 | 18 | final String title; 19 | final String tagline; 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return Row( 24 | crossAxisAlignment: CrossAxisAlignment.start, 25 | children: [ 26 | Expanded( 27 | child: Column( 28 | crossAxisAlignment: CrossAxisAlignment.start, 29 | children: [ 30 | Bold__text( 31 | text: title, 32 | fontSize: 20.0, 33 | height: 1.3, 34 | ), 35 | const SizedBox(height: kDefaultPadding / 2), 36 | Regular__text( 37 | text: tagline, 38 | fontSize: 14.0, 39 | color: kColorWhite80, 40 | height: 1.2, 41 | ), 42 | ], 43 | ), 44 | ), 45 | const SizedBox(width: kDefaultPadding / 2), 46 | Accent_Medium__IconButton( 47 | icon: Assets.icons.play, 48 | borderRadius: 60.0, 49 | onTap: () {}, 50 | ) 51 | ], 52 | ); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /lib/data/bloc/movie_details/movie_details_bloc.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers, unnecessary_null_comparison 2 | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/data/models/movie_details/movie_details_model.dart'; 7 | import 'package:movie_app/domain/repositories/movie_details/i_movie_details_repo.dart'; 8 | 9 | part 'movie_details_bloc.freezed.dart'; 10 | part 'movie_details_event.dart'; 11 | part 'movie_details_state.dart'; 12 | 13 | @injectable 14 | class MovieDetailsBloc extends Bloc { 15 | final IMovieDetailsRepo _iMovieDetailsRepo; 16 | MovieDetailsBloc(this._iMovieDetailsRepo) 17 | : super(MovieDetailsState.initial()) { 18 | on<_GetMovieDetails>((event, emit) async { 19 | if (state.movieDetailsData.id != null) { 20 | emit(MovieDetailsState( 21 | isLoading: false, 22 | hasError: false, 23 | movieDetailsData: state.movieDetailsData, 24 | )); 25 | } 26 | 27 | emit(state.copyWith(isLoading: true)); 28 | final _result = 29 | await _iMovieDetailsRepo.getMovieDetails(movieId: event.movieId); 30 | 31 | final _state = _result.fold( 32 | (failure) => state.copyWith( 33 | isLoading: false, 34 | hasError: true, 35 | ), 36 | (success) => MovieDetailsState( 37 | isLoading: false, 38 | hasError: false, 39 | movieDetailsData: success, 40 | ), 41 | ); 42 | emit(_state); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /assets/images/logo2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /lib/presentation/pages/movie_details/widgets/button_group_section.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, prefer_typing_uninitialized_variables 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../../gen/assets.gen.dart'; 6 | import '../../../components/icon_button.dart'; 7 | import '../../../components/rating_indicator.dart'; 8 | import '../../../themes/colors.dart'; 9 | import '../../../themes/values.dart'; 10 | 11 | class ButtonGroupSection__widget extends StatelessWidget { 12 | const ButtonGroupSection__widget({Key? key, required this.ratingValue}) 13 | : super(key: key); 14 | 15 | final ratingValue; 16 | 17 | @override 18 | Widget build(BuildContext context) { 19 | return Row( 20 | mainAxisAlignment: MainAxisAlignment.center, 21 | children: [ 22 | RatingIndicator__widget( 23 | ratingValue: ratingValue, 24 | ), 25 | const SizedBox(width: kDefaultPadding / 2), 26 | Primary_Medium__IconButton( 27 | icon: Assets.icons.heartFill, 28 | borderRadius: 60.0, 29 | bgColor: kColorPrimary80, 30 | onTap: () {}, 31 | ), 32 | const SizedBox(width: kDefaultPadding / 2), 33 | Primary_Medium__IconButton( 34 | icon: Assets.icons.download, 35 | borderRadius: 60.0, 36 | bgColor: kColorPrimary80, 37 | onTap: () {}, 38 | ), 39 | const SizedBox(width: kDefaultPadding / 2), 40 | Primary_Medium__IconButton( 41 | icon: Assets.icons.share, 42 | borderRadius: 60.0, 43 | bgColor: kColorPrimary80, 44 | onTap: () {}, 45 | ), 46 | ], 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/data/bloc/home/image_slider/image_slider_bloc.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers, await_only_futures, unused_local_variable 2 | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/data/models/home/image_slider/image_slider_model.dart'; 7 | import 'package:movie_app/domain/repositories/home/image_slider/i_image_slider_repo.dart'; 8 | 9 | part 'image_slider_bloc.freezed.dart'; 10 | part 'image_slider_event.dart'; 11 | part 'image_slider_state.dart'; 12 | 13 | @injectable 14 | class ImageSliderBloc extends Bloc { 15 | final IImageSliderRepo _iImageSliderRepo; 16 | ImageSliderBloc(this._iImageSliderRepo) : super(ImageSliderState.initial()) { 17 | // 18 | on<_GetImageSliderData>((event, emit) async { 19 | if (state.imageSliderDataList.isNotEmpty) { 20 | emit(ImageSliderState( 21 | isLoading: false, 22 | hasError: false, 23 | imageSliderDataList: state.imageSliderDataList, 24 | )); 25 | } 26 | final _result = await _iImageSliderRepo.getImageSliderData(); 27 | 28 | final _state = _result.fold( 29 | (failure) => const ImageSliderState( 30 | isLoading: false, 31 | hasError: true, 32 | imageSliderDataList: [], 33 | ), 34 | (success) => ImageSliderState( 35 | isLoading: false, 36 | hasError: false, 37 | imageSliderDataList: success, 38 | )); 39 | emit(_state); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /lib/presentation/components/dialogs/error_dialog.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/core/services/navigator.dart'; 5 | import 'package:movie_app/presentation/components/button.dart'; 6 | import 'package:movie_app/presentation/components/text.dart'; 7 | import 'package:movie_app/presentation/themes/colors.dart'; 8 | import 'package:movie_app/presentation/themes/values.dart'; 9 | 10 | showErrorDialog(BuildContext ctx, String errorMessage, VoidCallback onRefresh) { 11 | Future.delayed(const Duration(milliseconds: 1000 * 1), () { 12 | showDialog( 13 | context: ctx, 14 | barrierDismissible: false, 15 | builder: (ctx) => AlertDialog( 16 | // title: const SemiBold__text(text: 'Network Issue', fontSize: 16.0), 17 | icon: const Icon( 18 | Icons.warning_rounded, 19 | size: kDefaultPadding * 8, 20 | color: kColorWhite50, 21 | ), 22 | contentPadding: const EdgeInsets.all(kDefaultPadding * 1.5), 23 | content: Regular__text(text: errorMessage, fontSize: 16.0, height: 1.4), 24 | actions: [ 25 | Accent_Medium__button( 26 | text: 'Refresh', 27 | onTap: onRefresh, 28 | ), 29 | const SizedBox(height: kDefaultPadding / 2), 30 | Primary_Medium__button(text: 'Exit', onTap: () => PageNav.pop(ctx)), 31 | const SizedBox(height: kDefaultPadding), 32 | ], 33 | actionsAlignment: MainAxisAlignment.center, 34 | actionsPadding: const EdgeInsets.symmetric(horizontal: kDefaultPadding), 35 | backgroundColor: kColorPrimary, 36 | ), 37 | ); 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /lib/data/repositories/discover/discover_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/movie_details/movie_details_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/dicover/i_discover_repo.dart'; 10 | 11 | @LazySingleton(as: IDiscoverRepo) 12 | class DiscoverRepository implements IDiscoverRepo { 13 | @override 14 | Future>> getMovieGenres() async { 15 | try { 16 | final response = await Dio(BaseOptions()).get(ApiEndPoints.movieGenres); 17 | 18 | final dataList = (response.data["genres"] as List) 19 | .map((e) => Genre.fromJson(e)) 20 | .toList(); 21 | 22 | // log(json.encode(dataList).toString()); 23 | return Right(dataList); 24 | } catch (e) { 25 | log(e.toString()); 26 | return Left(NetworkError.getDioException(e)); 27 | } 28 | } 29 | 30 | @override 31 | Future>> getPopularPersons() async { 32 | try { 33 | final response = 34 | await Dio(BaseOptions()).get(ApiEndPoints.popularPersons); 35 | 36 | final dataList = (response.data["results"] as List) 37 | .map((e) => Cast.fromJson(e)) 38 | .toList(); 39 | 40 | // log(json.encode(dataList).toString()); 41 | return Right(dataList); 42 | } catch (e) { 43 | log(e.toString()); 44 | return Left(NetworkError.getDioException(e)); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /lib/data/bloc/login/login_poster/login_poster_bloc.dart: -------------------------------------------------------------------------------- 1 | import 'package:dartz/dartz.dart'; 2 | import 'package:flutter_bloc/flutter_bloc.dart'; 3 | import 'package:freezed_annotation/freezed_annotation.dart'; 4 | import 'package:injectable/injectable.dart'; 5 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 6 | import 'package:movie_app/domain/repositories/login/i_login_poster_repo.dart'; 7 | 8 | import '../../../models/login/login_poster_model.dart'; 9 | 10 | part 'login_poster_bloc.freezed.dart'; 11 | part 'login_poster_event.dart'; 12 | part 'login_poster_state.dart'; 13 | 14 | @injectable 15 | class LoginPosterBloc extends Bloc { 16 | final ILoginImagesRepo _loginImagesRepo; 17 | LoginPosterBloc(this._loginImagesRepo) : super(LoginPosterState.initial()) { 18 | on<_GetLoginPosterImages>((event, emit) async { 19 | if (state.loginPosterDataList.isNotEmpty) { 20 | emit(LoginPosterState( 21 | isLoading: false, 22 | hasError: false, 23 | isSuccess: true, 24 | loginPosterDataList: state.loginPosterDataList, 25 | )); 26 | } 27 | 28 | emit(state.copyWith(isLoading: true)); 29 | final Either> loginPosterOption = 30 | await _loginImagesRepo.getLoginPosterImages(); 31 | emit(loginPosterOption.fold( 32 | (failure) => state.copyWith( 33 | isLoading: false, 34 | hasError: true, 35 | ), 36 | (success) => LoginPosterState( 37 | isLoading: false, 38 | hasError: false, 39 | isSuccess: true, 40 | loginPosterDataList: success, 41 | ), 42 | )); 43 | }); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/presentation/pages/video_playback/widgets/youtube_player_iframe.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, library_private_types_in_public_api 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/themes/screen_size_config.dart'; 5 | import 'package:youtube_player_iframe/youtube_player_iframe.dart'; 6 | 7 | class YoutubePlayerIframe__widget extends StatefulWidget { 8 | const YoutubePlayerIframe__widget({ 9 | Key? key, 10 | required this.youtubeKey, 11 | }) : super(key: key); 12 | 13 | final String youtubeKey; 14 | 15 | @override 16 | _YoutubePlayerIframe__widgetState createState() => 17 | _YoutubePlayerIframe__widgetState(); 18 | } 19 | 20 | class _YoutubePlayerIframe__widgetState 21 | extends State { 22 | late YoutubePlayerController _controller; 23 | 24 | @override 25 | void initState() { 26 | _controller = YoutubePlayerController( 27 | params: const YoutubePlayerParams( 28 | color: 'transparent', 29 | enableCaption: false, 30 | strictRelatedVideos: true, 31 | ), 32 | )..onInit = () { 33 | _controller.loadVideoById(videoId: widget.youtubeKey); 34 | // _controller.loadVideoByUrl( 35 | // mediaContentUrl: 'https://www.youtube.com/watch?v=3kAsxVzRJmI'); 36 | }; 37 | super.initState(); 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | return SizedBox( 43 | height: getScreenHeightPercentage(50.0), 44 | width: getScreenHeightPercentage(80.0), 45 | child: YoutubePlayerControllerProvider( 46 | controller: _controller, 47 | child: YoutubePlayer( 48 | controller: _controller, 49 | ), 50 | ), 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/data/repositories/search_result/search_result_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/search_result/i_search_result_repo.dart'; 10 | 11 | @LazySingleton(as: ISearchResultRepo) 12 | class MovieDetailsRepository implements ISearchResultRepo { 13 | @override 14 | Future> getPopularMovies() async { 15 | try { 16 | final response = await Dio(BaseOptions()).get(ApiEndPoints.popularMovies); 17 | 18 | // log(jsonEncode(response.data).toString()); 19 | 20 | final dataList = MovieList.fromJson(response.data); 21 | 22 | // log(jsonEncode(dataList.results).toString()); 23 | return Right(dataList); 24 | } catch (e) { 25 | log(e.toString()); 26 | return Left(NetworkError.getDioException(e)); 27 | } 28 | } 29 | 30 | @override 31 | Future> getSearchedMovies( 32 | {required String query}) async { 33 | try { 34 | final response = 35 | await Dio(BaseOptions()).get(ApiEndPoints.searchMovie(query)); 36 | 37 | // log(jsonEncode(response.data).toString()); 38 | 39 | final dataList = MovieList.fromJson(response.data); 40 | 41 | // log(jsonEncode(dataList.results).toString()); 42 | return Right(dataList); 43 | } catch (e) { 44 | log(e.toString()); 45 | return Left(NetworkError.getDioException(e)); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /assets/icons/heart_outline.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.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. 5 | 6 | version: 7 | revision: f1875d570e39de09040c8f79aa13cc56baab8db1 8 | channel: stable 9 | 10 | project_type: app 11 | 12 | # Tracks metadata for the flutter migrate command 13 | migration: 14 | platforms: 15 | - platform: root 16 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 17 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 18 | - platform: android 19 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 20 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 21 | - platform: ios 22 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 23 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 24 | - platform: linux 25 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 26 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 27 | - platform: macos 28 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 29 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 30 | - platform: web 31 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 32 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 33 | - platform: windows 34 | create_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 35 | base_revision: f1875d570e39de09040c8f79aa13cc56baab8db1 36 | 37 | # User provided section 38 | 39 | # List of Local paths (relative to this file) that should be 40 | # ignored by the migrate tool. 41 | # 42 | # Files that are not part of the templates will be ignored by default. 43 | unmanaged_files: 44 | - 'lib/main.dart' 45 | - 'ios/Runner.xcodeproj/project.pbxproj' 46 | -------------------------------------------------------------------------------- /lib/data/repositories/home/image_slider/image_slider_repo.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: non_constant_identifier_names 2 | 3 | import 'dart:developer'; 4 | 5 | import 'package:dartz/dartz.dart'; 6 | import 'package:dio/dio.dart'; 7 | import 'package:injectable/injectable.dart'; 8 | import 'package:intl/intl.dart'; 9 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 10 | import 'package:movie_app/data/models/home/image_slider/image_slider_model.dart'; 11 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 12 | import 'package:movie_app/domain/repositories/home/image_slider/i_image_slider_repo.dart'; 13 | 14 | @LazySingleton(as: IImageSliderRepo) 15 | class ImageSliderRepository implements IImageSliderRepo { 16 | @override 17 | Future>> getImageSliderData() async { 18 | // 19 | // 20 | // date 21 | final DateTime now = DateTime.now(); 22 | 23 | // subtract 15 days 24 | final DateTime past_15_Days = now.subtract(const Duration(days: 15)); 25 | 26 | final DateFormat formatter = DateFormat('yyyy-MM-dd'); 27 | final String formatedPastDate = formatter.format(past_15_Days); 28 | final String formattedTodayDate = formatter.format(now); 29 | 30 | try { 31 | // popular Malayalam movies by popularity 32 | final response = await Dio(BaseOptions()).get( 33 | ApiEndPoints.popularMoviesWithOriginalLanguage( 34 | Language.malayalam, formatedPastDate, formattedTodayDate)); 35 | 36 | final imageSliderData = (response.data["results"] as List) 37 | .map((e) => ImageSlider.fromJson(e)) 38 | .toList(); 39 | return Right(imageSliderData); 40 | } catch (e) { 41 | log(e.toString()); 42 | return Left(NetworkError.getDioException(e)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lib/presentation/components/inner_appbars/movie_grid_layout_button.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:movie_app/core/services/app_default_preferences.dart'; 6 | import 'package:movie_app/gen/assets.gen.dart'; 7 | import 'package:movie_app/presentation/bloc/components/inner_appbars/bloc/appbar_search_bloc.dart'; 8 | import 'package:movie_app/presentation/themes/colors.dart'; 9 | 10 | class MovieGridLayoutButton__widget extends StatelessWidget { 11 | const MovieGridLayoutButton__widget({Key? key}) : super(key: key); 12 | @override 13 | Widget build(BuildContext context) { 14 | return BlocBuilder( 15 | builder: (context, state) { 16 | return IndexedStack( 17 | index: state.columnIconIndex, 18 | children: [ 19 | GestureDetector( 20 | onTap: () { 21 | context.read().add( 22 | const AppbarSearchEvent.columnButtonPress( 23 | columnIconIndex: 1)); 24 | setIconIndex(1); 25 | }, 26 | child: Assets.icons.column2 27 | .svg(width: 32, height: 32, color: kColorWhite50), 28 | ), 29 | GestureDetector( 30 | onTap: () { 31 | context.read().add( 32 | const AppbarSearchEvent.columnButtonPress( 33 | columnIconIndex: 0)); 34 | setIconIndex(0); 35 | }, 36 | child: Assets.icons.column3 37 | .svg(width: 32, height: 32, color: kColorWhite50), 38 | ), 39 | ], 40 | ); 41 | }, 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /assets/icons/film.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | Movie App 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | movie_app 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(FLUTTER_BUILD_NAME) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(FLUTTER_BUILD_NUMBER) 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UIViewControllerBasedStatusBarAppearance 45 | 46 | CADisableMinimumFrameDurationOnPhone 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /lib/data/repositories/home/movie_list/movie_list_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/home/movie_sroll_list/i_movie_list_repo.dart'; 10 | 11 | @LazySingleton(as: IMovieListRepo) 12 | class MovieScrollListRepository implements IMovieListRepo { 13 | @override 14 | Future> getMovieListByPerson({ 15 | required String personId, 16 | }) async { 17 | try { 18 | final response = 19 | await Dio(BaseOptions()).get(ApiEndPoints.personMovies(personId)); 20 | 21 | // log(jsonEncode(response.data).toString()); 22 | 23 | final dataList = MovieList.fromJson(response.data); 24 | 25 | // log(jsonEncode(dataList).toString()); 26 | return Right(dataList); 27 | } catch (e) { 28 | log(e.toString()); 29 | return Left(NetworkError.getDioException(e)); 30 | } 31 | } 32 | 33 | Future> getMoviesByQuery({ 34 | required String query, 35 | }) async { 36 | try { 37 | final response = await Dio(BaseOptions()) 38 | .get(ApiEndPoints.moviesByGenre(query, Language.malayalam)); 39 | 40 | // log(jsonEncode(response.data).toString()); 41 | 42 | final dataList = MovieList.fromJson(response.data); 43 | 44 | // log(jsonEncode(dataList).toString()); 45 | return Right(dataList); 46 | } catch (e) { 47 | log(e.toString()); 48 | return Left(NetworkError.getDioException(e)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/data/bloc/upcoming_movies/upcoming_movies_bloc.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: no_leading_underscores_for_local_identifiers 2 | 3 | import 'package:flutter_bloc/flutter_bloc.dart'; 4 | import 'package:freezed_annotation/freezed_annotation.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:intl/intl.dart'; 7 | import 'package:movie_app/data/models/upcoming_movies/upcoming_movies_model.dart'; 8 | import 'package:movie_app/domain/repositories/upcoming_movies/i_upcoming_movies_repo.dart'; 9 | 10 | part 'upcoming_movies_bloc.freezed.dart'; 11 | part 'upcoming_movies_event.dart'; 12 | part 'upcoming_movies_state.dart'; 13 | 14 | @injectable 15 | class UpcomingMoviesBloc 16 | extends Bloc { 17 | final IUpcomingMoviesRepo _iUpcomingMoviesRepo; 18 | UpcomingMoviesBloc(this._iUpcomingMoviesRepo) 19 | : super(UpcomingMoviesState.initial()) { 20 | on((event, emit) async { 21 | emit(state.copyWith(isLoading: true)); 22 | 23 | //date 24 | final DateTime now = DateTime.now(); 25 | 26 | //add 2 days 27 | // final DateTime newDate = now.add(const Duration(days: 2)); 28 | 29 | final DateFormat formatter = DateFormat('yyyy-MM-dd'); 30 | final String formattedNewDate = formatter.format(now); 31 | 32 | // fetching data 33 | final _result = 34 | await _iUpcomingMoviesRepo.getUpcomingMovies(date: formattedNewDate); 35 | 36 | final _state = _result.fold( 37 | (failure) => state.copyWith( 38 | isLoading: false, 39 | hasError: true, 40 | ), 41 | (success) => UpcomingMoviesState( 42 | isLoading: false, 43 | hasError: false, 44 | isSuccess: true, 45 | dataList: success, 46 | ), 47 | ); 48 | emit(_state); 49 | }); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/data/models/home/movie_list/movie_list_model.g.dart: -------------------------------------------------------------------------------- 1 | // GENERATED CODE - DO NOT MODIFY BY HAND 2 | 3 | part of 'movie_list_model.dart'; 4 | 5 | // ************************************************************************** 6 | // JsonSerializableGenerator 7 | // ************************************************************************** 8 | 9 | _$_MovieList _$$_MovieListFromJson(Map json) => _$_MovieList( 10 | page: json['page'] as int, 11 | results: (json['results'] as List) 12 | .map((e) => Result.fromJson(e as Map)) 13 | .toList(), 14 | totalPages: json['total_pages'] as int, 15 | totalResults: json['total_results'] as int, 16 | ); 17 | 18 | Map _$$_MovieListToJson(_$_MovieList instance) => 19 | { 20 | 'page': instance.page, 21 | 'results': instance.results.map((e) => e.toJson()).toList(), 22 | 'total_pages': instance.totalPages, 23 | 'total_results': instance.totalResults, 24 | }; 25 | 26 | _$_Result _$$_ResultFromJson(Map json) => _$_Result( 27 | id: json['id'] as int, 28 | title: json['title'] as String?, 29 | posterPath: json['poster_path'] as String?, 30 | popularity: (json['popularity'] as num?)?.toDouble(), 31 | releaseDate: json['release_date'] as String?, 32 | voteAverage: (json['vote_average'] as num?)?.toDouble(), 33 | voteCount: json['vote_count'] as int?, 34 | ); 35 | 36 | Map _$$_ResultToJson(_$_Result instance) => { 37 | 'id': instance.id, 38 | 'title': instance.title, 39 | 'poster_path': instance.posterPath, 40 | 'popularity': instance.popularity, 41 | 'release_date': instance.releaseDate, 42 | 'vote_average': instance.voteAverage, 43 | 'vote_count': instance.voteCount, 44 | }; 45 | -------------------------------------------------------------------------------- /lib/presentation/components/skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:movie_app/presentation/themes/colors.dart'; 5 | import 'package:movie_app/presentation/themes/values.dart'; 6 | import 'package:shimmer/shimmer.dart'; 7 | 8 | class Skelton__widget extends StatelessWidget { 9 | const Skelton__widget({ 10 | Key? key, 11 | this.baseColor, 12 | this.highlightColor, 13 | required this.child, 14 | this.period, 15 | this.direction, 16 | this.loop, 17 | this.enabled, 18 | }) : super(key: key); 19 | 20 | final Widget child; 21 | final Color? baseColor; 22 | final Color? highlightColor; 23 | final Duration? period; 24 | final ShimmerDirection? direction; 25 | final int? loop; 26 | final bool? enabled; 27 | @override 28 | Widget build(BuildContext context) { 29 | return Shimmer.fromColors( 30 | baseColor: baseColor ?? kSkeltonBaseColor, 31 | highlightColor: highlightColor ?? kSkeltonHighlightColor, 32 | period: period ?? const Duration(milliseconds: 1500), 33 | direction: direction ?? ShimmerDirection.ltr, 34 | loop: loop ?? 0, 35 | enabled: enabled ?? true, 36 | child: child, 37 | ); 38 | } 39 | } 40 | 41 | class SkeltonContent extends StatelessWidget { 42 | const SkeltonContent({ 43 | Key? key, 44 | required this.height, 45 | this.width, 46 | this.radius, 47 | }) : super(key: key); 48 | 49 | final double height; 50 | final double? width; 51 | final double? radius; 52 | 53 | @override 54 | Widget build(BuildContext context) { 55 | return Container( 56 | height: height, 57 | width: width ?? double.infinity, 58 | decoration: BoxDecoration( 59 | color: kColorWhite, 60 | borderRadius: BorderRadius.circular(radius ?? 8), 61 | ), 62 | ); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /lib/data/repositories/movies_result_grid/movies_result_grid_repo.dart: -------------------------------------------------------------------------------- 1 | import 'dart:developer'; 2 | 3 | import 'package:dartz/dartz.dart'; 4 | import 'package:dio/dio.dart'; 5 | import 'package:injectable/injectable.dart'; 6 | import 'package:movie_app/core/errors/network_error/network_error.dart'; 7 | import 'package:movie_app/data/models/home/movie_list/movie_list_model.dart'; 8 | import 'package:movie_app/data/sources/remote_data_sources/api_end_points.dart'; 9 | import 'package:movie_app/domain/repositories/movies_result_grid/i_movies_result_grid_repo.dart'; 10 | 11 | @LazySingleton(as: IMoviesResultGridRepo) 12 | class MoviesResultGridRepository implements IMoviesResultGridRepo { 13 | @override 14 | Future> getMoviesByGenre( 15 | {required String genre}) async { 16 | try { 17 | final response = await Dio(BaseOptions()) 18 | .get(ApiEndPoints.moviesByGenre(genre, Language.malayalam)); 19 | 20 | // log(jsonEncode(response.data).toString()); 21 | 22 | final dataList = MovieList.fromJson(response.data); 23 | 24 | // log(jsonEncode(dataList).toString()); 25 | 26 | return Right(dataList); 27 | } catch (e) { 28 | log(e.toString()); 29 | return Left(NetworkError.getDioException(e)); 30 | } 31 | } 32 | 33 | @override 34 | Future> getMoviesByPerson( 35 | {required String personId}) async { 36 | try { 37 | final response = 38 | await Dio(BaseOptions()).get(ApiEndPoints.personMovies(personId)); 39 | 40 | // log(jsonEncode(response.data).toString()); 41 | 42 | final dataList = MovieList.fromJson(response.data); 43 | 44 | // log(jsonEncode(dataList).toString()); 45 | return Right(dataList); 46 | } catch (e) { 47 | log(e.toString()); 48 | return Left(NetworkError.getDioException(e)); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /lib/presentation/pages/search_result/widgtes/skelton/movie_poster_grid_skelton.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_bloc/flutter_bloc.dart'; 5 | import 'package:movie_app/core/utils/generics/custom_widget_builder.dart'; 6 | import 'package:movie_app/presentation/bloc/components/inner_appbars/bloc/appbar_search_bloc.dart'; 7 | import 'package:movie_app/presentation/components/skelton.dart'; 8 | import 'package:movie_app/presentation/themes/screen_size_config.dart'; 9 | import 'package:movie_app/presentation/themes/values.dart'; 10 | 11 | class MoviePosterGridSkelton__widget extends StatelessWidget { 12 | const MoviePosterGridSkelton__widget({Key? key}) : super(key: key); 13 | @override 14 | Widget build(BuildContext context) { 15 | /// 16 | /// 17 | final iconIndex = context.watch().state.columnIconIndex; 18 | 19 | /// 20 | /// 21 | return Skelton__widget( 22 | child: CustomGridViewBuilder( 23 | padding: EdgeInsets.only( 24 | left: kDefaultPadding * 2, 25 | top: getScreenHeightPercentage(16.0), 26 | right: kDefaultPadding * 2, 27 | bottom: kDefaultPadding * 2, 28 | ), 29 | crossAxisCount: iconIndex == 0 ? 3 : 2, 30 | itemCount: 6 * 3, 31 | mainAxisSpacing: kDefaultPadding / 2, 32 | crossAxisSpacing: kDefaultPadding / 2, 33 | keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag, 34 | childAspectRatio: 6 / 10, 35 | builder: (context, index) { 36 | return Container( 37 | height: 100, 38 | decoration: BoxDecoration( 39 | color: Colors.black, 40 | borderRadius: BorderRadius.circular(8), 41 | ), 42 | ); 43 | }), 44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /assets/icons/discover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /assets/images/logo1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /lib/presentation/pages/main/widgets/bottom_navbar/bottom_navbar_item.dart: -------------------------------------------------------------------------------- 1 | // ignore_for_file: camel_case_types, prefer_typing_uninitialized_variables 2 | 3 | import 'package:flutter/material.dart'; 4 | 5 | import '../../../../components/text.dart'; 6 | import '../../../../themes/colors.dart'; 7 | import '../../../../themes/values.dart'; 8 | 9 | class BottomNavbarItem__widget extends StatelessWidget { 10 | const BottomNavbarItem__widget({ 11 | Key? key, 12 | this.icon, 13 | required this.label, 14 | required this.onTap, 15 | this.isActive = false, 16 | }) : super(key: key); 17 | 18 | final icon; 19 | final String label; 20 | final VoidCallback onTap; 21 | final bool isActive; 22 | 23 | @override 24 | Widget build(BuildContext context) { 25 | return GestureDetector( 26 | onTap: onTap, 27 | child: AnimatedContainer( 28 | duration: const Duration(milliseconds: 150), 29 | curve: Curves.linear, 30 | padding: EdgeInsets.symmetric( 31 | vertical: isActive ? 12.0 : 8.0, 32 | horizontal: isActive ? 20.0 : 16.0, 33 | ), 34 | decoration: BoxDecoration( 35 | color: isActive ? kColorAccent : Colors.transparent, 36 | borderRadius: BorderRadius.circular(60.0), 37 | ), 38 | child: Row( 39 | crossAxisAlignment: CrossAxisAlignment.center, 40 | mainAxisAlignment: MainAxisAlignment.center, 41 | children: [ 42 | icon.svg( 43 | height: isActive ? 24.0 : 32.0, 44 | width: isActive ? 24.0 : 32.0, 45 | color: kColorWhite, 46 | ), 47 | const SizedBox(width: kDefaultPadding / 4), 48 | Regular__text( 49 | text: isActive ? label : '', 50 | fontSize: 14.0, 51 | height: 1.6, 52 | ) 53 | ], 54 | ), 55 | ), 56 | ); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 7 | 15 | 19 | 23 | 24 | 25 | 26 | 27 | 28 | 30 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /windows/runner/utils.cpp: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | void CreateAndAttachConsole() { 11 | if (::AllocConsole()) { 12 | FILE *unused; 13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) { 14 | _dup2(_fileno(stdout), 1); 15 | } 16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) { 17 | _dup2(_fileno(stdout), 2); 18 | } 19 | std::ios::sync_with_stdio(); 20 | FlutterDesktopResyncOutputStreams(); 21 | } 22 | } 23 | 24 | std::vector GetCommandLineArguments() { 25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. 26 | int argc; 27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); 28 | if (argv == nullptr) { 29 | return std::vector(); 30 | } 31 | 32 | std::vector command_line_arguments; 33 | 34 | // Skip the first argument as it's the binary name. 35 | for (int i = 1; i < argc; i++) { 36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i])); 37 | } 38 | 39 | ::LocalFree(argv); 40 | 41 | return command_line_arguments; 42 | } 43 | 44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) { 45 | if (utf16_string == nullptr) { 46 | return std::string(); 47 | } 48 | int target_length = ::WideCharToMultiByte( 49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 50 | -1, nullptr, 0, nullptr, nullptr); 51 | std::string utf8_string; 52 | if (target_length == 0 || target_length > utf8_string.max_size()) { 53 | return utf8_string; 54 | } 55 | utf8_string.resize(target_length); 56 | int converted_length = ::WideCharToMultiByte( 57 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, 58 | -1, utf8_string.data(), 59 | target_length, nullptr, nullptr); 60 | if (converted_length == 0) { 61 | return std::string(); 62 | } 63 | return utf8_string; 64 | } 65 | --------------------------------------------------------------------------------