Repository: devdennysegura/flutter-netflix-clone Branch: master Commit: 34a03cb6bf82 Files: 61 Total size: 172.8 KB Directory structure: gitextract_h2gmahf_/ ├── .gitignore ├── .metadata ├── README.md ├── android/ │ ├── app/ │ │ ├── build.gradle │ │ └── src/ │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── example/ │ │ │ └── netflixclone/ │ │ │ └── MainActivity.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── launch_background.xml │ │ └── values/ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle/ │ │ └── wrapper/ │ │ └── gradle-wrapper.properties │ ├── gradle.properties │ └── settings.gradle ├── ios/ │ ├── Flutter/ │ │ ├── AppFrameworkInfo.plist │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── flutter_export_environment.sh │ ├── Podfile │ ├── Runner/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets/ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── LaunchImage.imageset/ │ │ │ ├── Contents.json │ │ │ └── README.md │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ └── main.m │ ├── Runner.xcodeproj/ │ │ ├── project.pbxproj │ │ ├── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ └── xcshareddata/ │ │ └── xcschemes/ │ │ └── Runner.xcscheme │ └── Runner.xcworkspace/ │ └── contents.xcworkspacedata ├── lib/ │ ├── app.dart │ ├── main.dart │ └── src/ │ ├── blocs/ │ │ └── movies_bloc.dart │ ├── helpers/ │ │ └── config/ │ │ ├── application.dart │ │ ├── constants.dart │ │ ├── route_handlers.dart │ │ └── routes.dart │ ├── models/ │ │ ├── episode.dart │ │ ├── item_model.dart │ │ └── result.dart │ ├── pages/ │ │ ├── detail/ │ │ │ ├── index.dart │ │ │ └── state.dart │ │ ├── filter/ │ │ │ ├── index.dart │ │ │ └── state.dart │ │ ├── home/ │ │ │ ├── index.dart │ │ │ └── state.dart │ │ ├── summary/ │ │ │ ├── index.dart │ │ │ └── state.dart │ │ └── video/ │ │ ├── index.dart │ │ └── state.dart │ ├── resources/ │ │ ├── movie_api_provider.dart │ │ └── repository.dart │ ├── utils/ │ │ └── theme/ │ │ ├── color.dart │ │ └── typography.dart │ └── widgets/ │ ├── player-controls/ │ │ ├── index.dart │ │ └── state.dart │ ├── player-life-cycle/ │ │ ├── index.dart │ │ └── state.dart │ └── tvshow-list/ │ └── index.dart ├── pubspec.yaml └── test/ └── widget_test.dart ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Miscellaneous *.class *.lock *.log *.pyc *.swp .DS_Store .atom/ .buildlog/ .history .svn/ # IntelliJ related *.iml *.ipr *.iws .idea/ # Visual Studio Code related .vscode/ # Flutter/Dart/Pub related **/doc/api/ .dart_tool/ .flutter-plugins .packages .pub-cache/ .pub/ build/ # Android related **/android/**/gradle-wrapper.jar **/android/.gradle **/android/captures/ **/android/gradlew **/android/gradlew.bat **/android/local.properties **/android/**/GeneratedPluginRegistrant.java # iOS/XCode related **/ios/**/*.mode1v3 **/ios/**/*.mode2v3 **/ios/**/*.moved-aside **/ios/**/*.pbxuser **/ios/**/*.perspectivev3 **/ios/**/*sync/ **/ios/**/.sconsign.dblite **/ios/**/.tags* **/ios/**/.vagrant/ **/ios/**/DerivedData/ **/ios/**/Icon? **/ios/**/Pods/ **/ios/**/.symlinks/ **/ios/**/profile **/ios/**/xcuserdata **/ios/.generated/ **/ios/Flutter/App.framework **/ios/Flutter/Flutter.framework **/ios/Flutter/Generated.xcconfig **/ios/Flutter/app.flx **/ios/Flutter/app.zip **/ios/Flutter/flutter_assets/ **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* # Exceptions to above rules. !**/ios/**/default.mode1v3 !**/ios/**/default.mode2v3 !**/ios/**/default.pbxuser !**/ios/**/default.perspectivev3 !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages ================================================ FILE: .metadata ================================================ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # # This file should be version controlled and should not be manually edited. version: revision: 97e03104a0913886a666a36f5d11ab5763d45e6e channel: dev project_type: app ================================================ FILE: README.md ================================================ # Flutter Netflix Clone Flutter App with the same style as Netflix for Android and iOS.
screen_01 screen_02 screen_03 screen_04
screen_01 screen_03 screen_02 screen_04 screen_04
## Server [Netflix Flutter NodeJS & MongoDB](https://github.com/devdennysegura/nodejs-server-Flutter-Netflix-App) ## Installation $ clone this repo $ Install flutter dependencies $ Install Netflix NodeJS & MongoDB $ Run NodeJS $ Change host String on `src/resources/movie_api_provider.dart` $ flutter run Thanks ------ **Denny Segura** © 2018+, Released under the [MIT License].
> GitHub [@devdennysegura](https://github.com/devdennysegura)  ·  > Twitter [@dennysegura3](https://twitter.com/dennysegura3) [MIT License]: http://mit-license.org/ ================================================ FILE: android/app/build.gradle ================================================ def localProperties = new Properties() def localPropertiesFile = rootProject.file('local.properties') if (localPropertiesFile.exists()) { localPropertiesFile.withReader('UTF-8') { reader -> localProperties.load(reader) } } def flutterRoot = localProperties.getProperty('flutter.sdk') if (flutterRoot == null) { throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") } def flutterVersionCode = localProperties.getProperty('flutter.versionCode') if (flutterVersionCode == null) { flutterVersionCode = '1' } def flutterVersionName = localProperties.getProperty('flutter.versionName') if (flutterVersionName == null) { flutterVersionName = '1.0' } apply plugin: 'com.android.application' apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" android { compileSdkVersion 27 lintOptions { disable 'InvalidPackage' } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.example.netflix.clone" minSdkVersion 21 targetSdkVersion 27 versionCode flutterVersionCode.toInteger() versionName flutterVersionName testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug } } } flutter { source '../..' } dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' } ================================================ FILE: android/app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: android/app/src/main/java/com/example/netflixclone/MainActivity.java ================================================ package com.example.netflixclone; import android.os.Bundle; import io.flutter.app.FlutterActivity; import io.flutter.plugins.GeneratedPluginRegistrant; public class MainActivity extends FlutterActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); GeneratedPluginRegistrant.registerWith(this); } } ================================================ FILE: android/app/src/main/res/drawable/launch_background.xml ================================================ ================================================ FILE: android/app/src/main/res/values/styles.xml ================================================ ================================================ FILE: android/build.gradle ================================================ buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.2.1' } } allprojects { repositories { google() jcenter() } } rootProject.buildDir = '../build' subprojects { project.buildDir = "${rootProject.buildDir}/${project.name}" } subprojects { project.evaluationDependsOn(':app') } task clean(type: Delete) { delete rootProject.buildDir } ================================================ FILE: android/gradle/wrapper/gradle-wrapper.properties ================================================ #Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip ================================================ FILE: android/gradle.properties ================================================ org.gradle.jvmargs=-Xmx1536M ================================================ FILE: android/settings.gradle ================================================ include ':app' def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() def plugins = new Properties() def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') if (pluginsFile.exists()) { pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } } plugins.each { name, path -> def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() include ":$name" project(":$name").projectDir = pluginDirectory } ================================================ FILE: ios/Flutter/AppFrameworkInfo.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable App CFBundleIdentifier io.flutter.flutter.app CFBundleInfoDictionaryVersion 6.0 CFBundleName App CFBundlePackageType FMWK CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 MinimumOSVersion 8.0 ================================================ FILE: ios/Flutter/Debug.xcconfig ================================================ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" ================================================ FILE: ios/Flutter/Release.xcconfig ================================================ #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" ================================================ FILE: ios/Flutter/flutter_export_environment.sh ================================================ #!/bin/sh # This is a generated file; do not edit or check into version control. export "FLUTTER_ROOT=/Users/dennysegura/development/flutter" export "FLUTTER_APPLICATION_PATH=/Users/dennysegura/Dev/Flutter/flutter-netflix-clone" export "FLUTTER_TARGET=lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "FLUTTER_FRAMEWORK_DIR=/Users/dennysegura/development/flutter/bin/cache/artifacts/engine/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" ================================================ FILE: ios/Podfile ================================================ # Uncomment this line to define a global platform for your project # platform :ios, '9.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' project 'Runner', { 'Debug' => :debug, 'Profile' => :release, 'Release' => :release, } def parse_KV_file(file, separator='=') file_abs_path = File.expand_path(file) if !File.exists? file_abs_path return []; end pods_ary = [] skip_line_start_symbols = ["#", "/"] File.foreach(file_abs_path) { |line| next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } plugin = line.split(pattern=separator) if plugin.length == 2 podname = plugin[0].strip() path = plugin[1].strip() podpath = File.expand_path("#{path}", file_abs_path) pods_ary.push({:name => podname, :path => podpath}); else puts "Invalid plugin specification: #{line}" end } return pods_ary end target 'Runner' do # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock # referring to absolute paths on developers' machines. system('rm -rf .symlinks') system('mkdir -p .symlinks/plugins') # Flutter Pods generated_xcode_build_settings = parse_KV_file('./Flutter/Generated.xcconfig') if generated_xcode_build_settings.empty? puts "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter packages get is executed first." end generated_xcode_build_settings.map { |p| if p[:name] == 'FLUTTER_FRAMEWORK_DIR' symlink = File.join('.symlinks', 'flutter') File.symlink(File.dirname(p[:path]), symlink) pod 'Flutter', :path => File.join(symlink, File.basename(p[:path])) end } # Plugin Pods plugin_pods = parse_KV_file('../.flutter-plugins') plugin_pods.map { |p| symlink = File.join('.symlinks', 'plugins', p[:name]) File.symlink(p[:path], symlink) pod p[:name], :path => File.join(symlink, 'ios') } end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['ENABLE_BITCODE'] = 'NO' end end end ================================================ FILE: ios/Runner/AppDelegate.h ================================================ #import #import @interface AppDelegate : FlutterAppDelegate @end ================================================ FILE: ios/Runner/AppDelegate.m ================================================ #include "AppDelegate.h" #include "GeneratedPluginRegistrant.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [GeneratedPluginRegistrant registerWithRegistry:self]; // Override point for customization after application launch. return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end ================================================ FILE: ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "20x20", "idiom" : "iphone", "filename" : "Icon-App-20x20@3x.png", "scale" : "3x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-App-29x29@3x.png", "scale" : "3x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-App-40x40@3x.png", "scale" : "3x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-App-60x60@3x.png", "scale" : "3x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@1x.png", "scale" : "1x" }, { "size" : "20x20", "idiom" : "ipad", "filename" : "Icon-App-20x20@2x.png", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@1x.png", "scale" : "1x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-App-29x29@2x.png", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@1x.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-App-40x40@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@1x.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-App-76x76@2x.png", "scale" : "2x" }, { "size" : "83.5x83.5", "idiom" : "ipad", "filename" : "Icon-App-83.5x83.5@2x.png", "scale" : "2x" }, { "size" : "1024x1024", "idiom" : "ios-marketing", "filename" : "Icon-App-1024x1024@1x.png", "scale" : "1x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "filename" : "LaunchImage.png", "scale" : "1x" }, { "idiom" : "universal", "filename" : "LaunchImage@2x.png", "scale" : "2x" }, { "idiom" : "universal", "filename" : "LaunchImage@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md ================================================ # Launch Screen Assets You can customize the launch screen with your own desired assets by replacing the image files in this directory. 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. ================================================ FILE: ios/Runner/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: ios/Runner/Base.lproj/Main.storyboard ================================================ ================================================ FILE: ios/Runner/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName netflix_clone CFBundlePackageType APPL CFBundleShortVersionString $(FLUTTER_BUILD_NAME) CFBundleSignature ???? CFBundleVersion $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance ================================================ FILE: ios/Runner/main.m ================================================ #import #import #import "AppDelegate.h" int main(int argc, char* argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: ios/Runner.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; }; 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; }; 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; }; 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; }; 97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 9705A1C41CF9048500538489 /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( 3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */, 9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; 2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; 9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = ""; }; 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 97C146EB1CF9000F007C117D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */, 3B80C3941E831B6300D905FE /* App.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( 2D5378251FAA1A9400D5DBA9 /* flutter_assets */, 3B80C3931E831B6300D905FE /* App.framework */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEBA1CF902C7004384FC /* Flutter.framework */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */, ); name = Flutter; sourceTree = ""; }; 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, 97C146EF1CF9000F007C117D /* Products */, CF3B75C9A7D2FA2A4C99F110 /* Frameworks */, ); sourceTree = ""; }; 97C146EF1CF9000F007C117D /* Products */ = { isa = PBXGroup; children = ( 97C146EE1CF9000F007C117D /* Runner.app */, ); name = Products; sourceTree = ""; }; 97C146F01CF9000F007C117D /* Runner */ = { isa = PBXGroup; children = ( 7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */, 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */, 97C146FA1CF9000F007C117D /* Main.storyboard */, 97C146FD1CF9000F007C117D /* Assets.xcassets */, 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, 97C147021CF9000F007C117D /* Info.plist */, 97C146F11CF9000F007C117D /* Supporting Files */, 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, ); path = Runner; sourceTree = ""; }; 97C146F11CF9000F007C117D /* Supporting Files */ = { isa = PBXGroup; children = ( 97C146F21CF9000F007C117D /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 97C146ED1CF9000F007C117D /* Runner */ = { isa = PBXNativeTarget; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( 9740EEB61CF901F6004384FC /* Run Script */, 97C146EA1CF9000F007C117D /* Sources */, 97C146EB1CF9000F007C117D /* Frameworks */, 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, ); buildRules = ( ); dependencies = ( ); name = Runner; productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0910; ORGANIZATIONNAME = "The Chromium Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { CreatedOnToolsVersion = 7.3.1; }; }; }; buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 97C146E51CF9000F007C117D; productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 97C146ED1CF9000F007C117D /* Runner */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 97C146EC1CF9000F007C117D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, 9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */, 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, 2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */, 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Thin Binary"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" thin"; }; 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); name = "Run Script"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 97C146EA1CF9000F007C117D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */, 97C146F31CF9000F007C117D /* main.m in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 97C146FA1CF9000F007C117D /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 97C146FB1CF9000F007C117D /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 97C147001CF9000F007C117D /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 249021D3217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Profile; }; 249021D4217E4FDB00AE95B9 /* Profile */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; DEVELOPMENT_TEAM = S8QB4VV633; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.example.netflixClone; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Profile; }; 97C147031CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 97C147041CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 97C147061CF9000F007C117D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.example.netflixClone; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Debug; }; 97C147071CF9000F007C117D /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; ENABLE_BITCODE = NO; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", ); PRODUCT_BUNDLE_IDENTIFIER = com.example.netflixClone; PRODUCT_NAME = "$(TARGET_NAME)"; VERSIONING_SYSTEM = "apple-generic"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147031CF9000F007C117D /* Debug */, 97C147041CF9000F007C117D /* Release */, 249021D3217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { isa = XCConfigurationList; buildConfigurations = ( 97C147061CF9000F007C117D /* Debug */, 97C147071CF9000F007C117D /* Release */, 249021D4217E4FDB00AE95B9 /* Profile */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } ================================================ FILE: ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme ================================================ ================================================ FILE: ios/Runner.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: lib/app.dart ================================================ library netflix; // Dart Imports import 'dart:async'; import 'dart:convert'; // Flutter imports import 'package:http/http.dart' show Client; import 'package:rxdart/rxdart.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; // Plugins import... import 'package:fluro/fluro.dart'; import 'package:video_player/video_player.dart'; // Router part 'src/helpers/config/constants.dart'; part 'src/helpers/config/application.dart'; part 'src/helpers/config/routes.dart'; part 'src/helpers/config/route_handlers.dart'; // Models part 'src/models/episode.dart'; part 'src/models/result.dart'; part 'src/models/item_model.dart'; // Blocs part 'src/blocs/movies_bloc.dart'; // Resources part 'src/resources/movie_api_provider.dart'; part 'src/resources/repository.dart'; part 'src/utils/theme/color.dart'; part 'src/utils/theme/typography.dart'; part 'src/pages/video/index.dart'; part 'src/pages/video/state.dart'; part 'src/pages/home/index.dart'; part 'src/pages/home/state.dart'; part 'src/pages/summary/index.dart'; part 'src/pages/summary/state.dart'; part 'src/pages/filter/index.dart'; part 'src/pages/filter/state.dart'; part 'src/pages/detail/index.dart'; part 'src/pages/detail/state.dart'; // Widgets part 'src/widgets/tvshow-list/index.dart'; part 'src/widgets/player-life-cycle/index.dart'; part 'src/widgets/player-life-cycle/state.dart'; part 'src/widgets/player-controls/index.dart'; part 'src/widgets/player-controls/state.dart'; class Netflix extends StatelessWidget { Netflix({Key key}) : super(key: key) { final router = Router(); Routes.configureRoutes(router); Application.router = router; } @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Netflix', theme: ThemeData( fontFamily: 'GoogleSans', primaryColor: Colors.black, ), onGenerateRoute: Application.router.generator, home: Home(), ); } } ================================================ FILE: lib/main.dart ================================================ import 'package:flutter/material.dart'; import 'package:netflix_clone/app.dart'; void main() => runApp(Netflix()); ================================================ FILE: lib/src/blocs/movies_bloc.dart ================================================ part of netflix; class MoviesBloc { final _repository = Repository(); final _moviesFetcher = PublishSubject>(); final _movieFetcher = PublishSubject(); Observable> get allMovies => _moviesFetcher.stream; Observable get oneMovie => _movieFetcher.stream; fetchAllMovies() async { List items = await _repository.fetchAllMovies(); _moviesFetcher.sink.add(items); } fetchOneMovie(int id) async { Result item = await _repository.fetchMovie(id); _movieFetcher.sink.add(item); } dispose() { _moviesFetcher.close(); _movieFetcher.close(); } } final bloc = MoviesBloc(); ================================================ FILE: lib/src/helpers/config/application.dart ================================================ part of netflix; class Application { static Router router; } ================================================ FILE: lib/src/helpers/config/constants.dart ================================================ part of netflix; Map tvShow = { "details": { "genres": ["Drama", "Crime"], "cast": [ { "person": { "id": 15429, "url": "http://www.tvmaze.com/people/15429/poppy-montgomery", "name": "Poppy Montgomery", "country": { "name": "Australia", "code": "AU", "timezone": "Australia/Sydney" }, "birthday": "1972-06-15", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/161/402509.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/161/402509.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/15429"} } }, "character": { "id": 17370, "url": "http://www.tvmaze.com/characters/17370/unforgettable-carrie-wells", "name": "Carrie Wells", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/664.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/664.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17370"} } }, "self": false, "voice": false }, { "person": { "id": 1368, "url": "http://www.tvmaze.com/people/1368/dylan-walsh", "name": "Dylan Walsh", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1963-11-17", "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/1110.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/1110.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/1368"} } }, "character": { "id": 17371, "url": "http://www.tvmaze.com/characters/17371/unforgettable-al-burns", "name": "Al Burns", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/1717.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/1717.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17371"} } }, "self": false, "voice": false }, { "person": { "id": 15430, "url": "http://www.tvmaze.com/people/15430/james-hiroyuki-liao", "name": "James Hiroyuki Liao", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": null, "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/3/8721.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/3/8721.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/15430"} } }, "character": { "id": 17373, "url": "http://www.tvmaze.com/characters/17373/unforgettable-jay-lee", "name": "Jay Lee", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/666.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/666.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17373"} } }, "self": false, "voice": false }, { "person": { "id": 15432, "url": "http://www.tvmaze.com/people/15432/jane-curtin", "name": "Jane Curtin", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1947-09-06", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/3/8723.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/3/8723.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/15432"} } }, "character": { "id": 176064, "url": "http://www.tvmaze.com/characters/176064/unforgettable-joanne-webster", "name": "Joanne Webster", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/668.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/668.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/176064"} } }, "self": false, "voice": false }, { "person": { "id": 10404, "url": "http://www.tvmaze.com/people/10404/dallas-roberts", "name": "Dallas Roberts", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1970-05-10", "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/161/404900.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/161/404900.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/10404"} } }, "character": { "id": 17372, "url": "http://www.tvmaze.com/characters/17372/unforgettable-eliot-delson", "name": "Eliot Delson", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/669.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/669.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17372"} } }, "self": false, "voice": false }, { "person": { "id": 15431, "url": "http://www.tvmaze.com/people/15431/tawny-cypress", "name": "Tawny Cypress", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1976-08-08", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/130/327329.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/130/327329.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/15431"} } }, "character": { "id": 17374, "url": "http://www.tvmaze.com/characters/17374/unforgettable-cherie-rollins-murray", "name": "Cherie Rollins-Murray", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/667.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/667.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17374"} } }, "self": false, "voice": false }, { "person": { "id": 8640, "url": "http://www.tvmaze.com/people/8640/daya-vaidya", "name": "Daya Vaidya", "country": { "name": "Nepal", "code": "NP", "timezone": "Asia/Kathmandu" }, "birthday": "1980-05-20", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/108/271770.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/108/271770.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/8640"} } }, "character": { "id": 17376, "url": "http://www.tvmaze.com/characters/17376/unforgettable-nina-inara", "name": "Nina Inara", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/670.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/670.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17376"} } }, "self": false, "voice": false }, { "person": { "id": 9105, "url": "http://www.tvmaze.com/people/9105/kevin-rankin", "name": "Kevin Rankin", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1976-04-18", "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/2/7246.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/2/7246.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/9105"} } }, "character": { "id": 17377, "url": "http://www.tvmaze.com/characters/17377/unforgettable-roe-saunders", "name": "Roe Saunders", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/671.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/671.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17377"} } }, "self": false, "voice": false }, { "person": { "id": 7197, "url": "http://www.tvmaze.com/people/7197/michael-gaston", "name": "Michael Gaston", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1962-11-05", "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/3/8724.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/3/8724.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/7197"} } }, "character": { "id": 17378, "url": "http://www.tvmaze.com/characters/17378/unforgettable-mike-costello", "name": "Mike Costello", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/0/665.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/0/665.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/characters/17378"} } }, "self": false, "voice": false }, { "person": { "id": 103992, "url": "http://www.tvmaze.com/people/103992/e-j-bonilla", "name": "E. J. Bonilla", "country": null, "birthday": null, "deathday": null, "gender": "Male", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/32/81059.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/32/81059.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/103992"} } }, "character": { "id": 209904, "url": "http://www.tvmaze.com/characters/209904/unforgettable-denny-padilla", "name": "Denny Padilla", "image": null, "_links": { "self": {"href": "http://api.tvmaze.com/characters/209904"} } }, "self": false, "voice": false }, { "person": { "id": 141871, "url": "http://www.tvmaze.com/people/141871/la-la-anthony", "name": "La La Anthony", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1979-06-25", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/118/295914.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/118/295914.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/141871"} } }, "character": { "id": 209906, "url": "http://www.tvmaze.com/characters/209906/unforgettable-delina-michaels", "name": "Delina Michaels", "image": null, "_links": { "self": {"href": "http://api.tvmaze.com/characters/209906"} } }, "self": false, "voice": false }, { "person": { "id": 25007, "url": "http://www.tvmaze.com/people/25007/kathy-najimy", "name": "Kathy Najimy", "country": { "name": "United States", "code": "US", "timezone": "America/New_York" }, "birthday": "1957-02-06", "deathday": null, "gender": "Female", "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_portrait/3/7855.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/3/7855.jpg" }, "_links": { "self": {"href": "http://api.tvmaze.com/people/25007"} } }, "character": { "id": 216013, "url": "http://www.tvmaze.com/characters/216013/unforgettable-sandra-russo", "name": "Sandra Russo", "image": null, "_links": { "self": {"href": "http://api.tvmaze.com/characters/216013"} } }, "self": false, "voice": false } ], "episodes": [ { "id": 5852, "url": "http://www.tvmaze.com/episodes/5852/unforgettable-1x01-pilot", "name": "Pilot", "season": 1, "number": 1, "airdate": "2011-09-20", "airtime": "22:00", "airstamp": "2011-09-21T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99519.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99519.jpg" }, "summary": "

When a murder reunites former detective Carrie Wells with her old colleague and flame, she must utilize her rare ability to revisit her every memory to catch the killer.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5852"} } }, { "id": 5853, "url": "http://www.tvmaze.com/episodes/5853/unforgettable-1x02-heroes", "name": "Heroes", "season": 1, "number": 2, "airdate": "2011-09-27", "airtime": "22:00", "airstamp": "2011-09-28T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99518.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99518.jpg" }, "summary": "

When a young boy witnesses a murder, Carrie must put aside the memories of her sister's death to help him lead the police to the killer.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5853"} } }, { "id": 5854, "url": "http://www.tvmaze.com/episodes/5854/unforgettable-1x03-check-out-time", "name": "Check Out Time", "season": 1, "number": 3, "airdate": "2011-10-04", "airtime": "22:00", "airstamp": "2011-10-05T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99517.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99517.jpg" }, "summary": "

When a hotel maid is accused of murdering a guest who she says tried to rape her, Carrie takes matters into her own hands to uncover the truth, threatening Al's investigation.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5854"} } }, { "id": 5855, "url": "http://www.tvmaze.com/episodes/5855/unforgettable-1x04-up-in-flames", "name": "Up in Flames", "season": 1, "number": 4, "airdate": "2011-10-11", "airtime": "22:00", "airstamp": "2011-10-12T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99516.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99516.jpg" }, "summary": "

When a crime scene is destroyed in an explosion moments after Carrie catches a glimpse of the room, her memories become a crucial piece of the investigation.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5855"} } }, { "id": 5856, "url": "http://www.tvmaze.com/episodes/5856/unforgettable-1x05-with-honor", "name": "With Honor", "season": 1, "number": 5, "airdate": "2011-10-18", "airtime": "22:00", "airstamp": "2011-10-19T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99514.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99514.jpg" }, "summary": "

When Al's ex-partner is gunned down and the investigation reveals he may have been a dirty cop, Carrie must decide how to support him without getting too close.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5856"} } }, { "id": 5857, "url": "http://www.tvmaze.com/episodes/5857/unforgettable-1x06-friended", "name": "Friended", "season": 1, "number": 6, "airdate": "2011-10-25", "airtime": "22:00", "airstamp": "2011-10-26T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99513.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99513.jpg" }, "summary": "

Carrie and Al's investigation into the murder of a hard-partying heiress takes an unexpected turn when they discover that the woman apparently didn't exist until 18 months earlier.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5857"} } }, { "id": 5858, "url": "http://www.tvmaze.com/episodes/5858/unforgettable-1x07-road-block", "name": "Road Block", "season": 1, "number": 7, "airdate": "2011-11-01", "airtime": "22:00", "airstamp": "2011-11-02T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99512.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99512.jpg" }, "summary": "

Carrie's investigation into the death of her sister moves forward, but her inability to let go may hinder the search for a missing infant whose father was murdered.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5858"} } }, { "id": 5859, "url": "http://www.tvmaze.com/episodes/5859/unforgettable-1x08-lost-things", "name": "Lost Things", "season": 1, "number": 8, "airdate": "2011-11-08", "airtime": "22:00", "airstamp": "2011-11-09T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99511.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99511.jpg" }, "summary": "

Carrie and Al investigate the death of a public defender, only to discover that the killer has a larger plan which may lead to a second murder.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5859"} } }, { "id": 5860, "url": "http://www.tvmaze.com/episodes/5860/unforgettable-1x09-golden-bird", "name": "Golden Bird", "season": 1, "number": 9, "airdate": "2011-11-15", "airtime": "22:00", "airstamp": "2011-11-16T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99510.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99510.jpg" }, "summary": "

Al and Carrie investigate the murder of a teen who seemed to have no enemies. Meanwhile, Carrie looks to her estranged aunt for help with the investigation into her sister's murder.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5860"} } }, { "id": 5861, "url": "http://www.tvmaze.com/episodes/5861/unforgettable-1x10-trajectories", "name": "Trajectories", "season": 1, "number": 10, "airdate": "2011-11-22", "airtime": "22:00", "airstamp": "2011-11-23T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99509.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99509.jpg" }, "summary": "

When a second murder suddenly occurs at an active crime scene, Al and Carrie must wade through hundreds of bystanders to uncover if it was retribution or an unrelated attack.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5861"} } }, { "id": 5862, "url": "http://www.tvmaze.com/episodes/5862/unforgettable-1x11-spirited-away", "name": "Spirited Away", "season": 1, "number": 11, "airdate": "2011-12-13", "airtime": "22:00", "airstamp": "2011-12-14T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99507.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99507.jpg" }, "summary": "

When a renowned ghost hunter is killed, Carrie and Al discover that his death is linked to a chilling discovery he made on a recent assignment.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5862"} } }, { "id": 5863, "url": "http://www.tvmaze.com/episodes/5863/unforgettable-1x12-butterfly-effect", "name": "Butterfly Effect", "season": 1, "number": 12, "airdate": "2012-01-03", "airtime": "22:00", "airstamp": "2012-01-04T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99506.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99506.jpg" }, "summary": "

When a construction worker with a promising future is murdered, Carrie and Al wonder if his ties to the mob were the cause of his death or an unrelated coincidence.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5863"} } }, { "id": 5864, "url": "http://www.tvmaze.com/episodes/5864/unforgettable-1x13-brotherhood", "name": "Brotherhood", "season": 1, "number": 13, "airdate": "2012-01-10", "airtime": "22:00", "airstamp": "2012-01-11T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99505.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99505.jpg" }, "summary": "

Routine investigation into a college student's death takes a disturbing turn for Carrie when a suspect makes a dangerous move to outwit her memory.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5864"} } }, { "id": 5865, "url": "http://www.tvmaze.com/episodes/5865/unforgettable-1x14-carries-caller", "name": "Carrie's Caller", "season": 1, "number": 14, "airdate": "2012-02-07", "airtime": "22:00", "airstamp": "2012-02-08T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99503.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99503.jpg" }, "summary": "

Serial killer with knowledge of Carrie's memory abilities taunts the Queens PD as his list of victims grows.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5865"} } }, { "id": 5866, "url": "http://www.tvmaze.com/episodes/5866/unforgettable-1x15-the-following-sea", "name": "The Following Sea", "season": 1, "number": 15, "airdate": "2012-02-14", "airtime": "22:00", "airstamp": "2012-02-15T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99502.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99502.jpg" }, "summary": "

When a key witness in his murder case vanishes before testifying, Al scrambles to find her before the suspect walks free.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5866"} } }, { "id": 5867, "url": "http://www.tvmaze.com/episodes/5867/unforgettable-1x16-heartbreak", "name": "Heartbreak", "season": 1, "number": 16, "airdate": "2012-02-21", "airtime": "22:00", "airstamp": "2012-02-22T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99501.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99501.jpg" }, "summary": "

Carrie and Al are at a loss to explain how a murder victim mysteriously appeared in an empty ballpark.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5867"} } }, { "id": 5868, "url": "http://www.tvmaze.com/episodes/5868/unforgettable-1x17-blind-alleys", "name": "Blind Alleys", "season": 1, "number": 17, "airdate": "2012-02-28", "airtime": "22:00", "airstamp": "2012-02-29T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99500.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99500.jpg" }, "summary": "

Al and Carrie are forced to the sidelines by a negotiator when the father of a suspect that Roe shot takes members of the Queens PD, including Nina, hostage in a desperate quest for justice.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5868"} } }, { "id": 5869, "url": "http://www.tvmaze.com/episodes/5869/unforgettable-1x18-the-comeback", "name": "The Comeback", "season": 1, "number": 18, "airdate": "2012-03-20", "airtime": "22:00", "airstamp": "2012-03-21T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99498.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99498.jpg" }, "summary": "

When Carrie's latest case is stalled by a powerful family's influence, she receives assistance from a lawyer who may be the mysterious caller who orchestrated a series of sniper attacks.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5869"} } }, { "id": 5870, "url": "http://www.tvmaze.com/episodes/5870/unforgettable-1x19-allegiances", "name": "Allegiances", "season": 1, "number": 19, "airdate": "2012-03-27", "airtime": "22:00", "airstamp": "2012-03-28T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99497.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99497.jpg" }, "summary": "

Carrie's personal and professional lives collide when her boyfriend, the son of a mob boss, is revealed to have ties to suspects in a murder investigation.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5870"} } }, { "id": 5871, "url": "http://www.tvmaze.com/episodes/5871/unforgettable-1x20-you-are-here", "name": "You Are Here", "season": 1, "number": 20, "airdate": "2012-04-10", "airtime": "22:00", "airstamp": "2012-04-11T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99496.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99496.jpg" }, "summary": "

Carrie and Al must get inside the mind of a deranged conspiracy theorist before he sets off a series of bombs.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5871"} } }, { "id": 5872, "url": "http://www.tvmaze.com/episodes/5872/unforgettable-1x21-endgame", "name": "Endgame", "season": 1, "number": 21, "airdate": "2012-05-01", "airtime": "22:00", "airstamp": "2012-05-02T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99495.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99495.jpg" }, "summary": "

When Walter Morgan turns up dead, Carrie must locate his killer while deflecting attention from the prime suspect - her.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5872"} } }, { "id": 5873, "url": "http://www.tvmaze.com/episodes/5873/unforgettable-1x22-the-man-in-the-woods", "name": "The Man in the Woods", "season": 1, "number": 22, "airdate": "2012-05-08", "airtime": "22:00", "airstamp": "2012-05-09T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99492.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99492.jpg" }, "summary": "

When a murder occurs in Syracuse which mirrors the death of her sister, Carrie and Al travel upstate to confront the suspect.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5873"} } }, { "id": 5874, "url": "http://www.tvmaze.com/episodes/5874/unforgettable-2x01-bigtime", "name": "Bigtime", "season": 2, "number": 1, "airdate": "2013-07-28", "airtime": "21:00", "airstamp": "2013-07-29T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99490.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99490.jpg" }, "summary": "

Carrie and Al's reputation for closing cases results in an offer to join the Major Crimes Section of the NYPD. But when their first case - a high-profile child kidnapping - hits close to home for Carrie, it leaves her wondering if a move from Queens to Manhattan is what's best for her.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5874"} } }, { "id": 5875, "url": "http://www.tvmaze.com/episodes/5875/unforgettable-2x02-incognito", "name": "Incognito", "season": 2, "number": 2, "airdate": "2013-08-04", "airtime": "21:00", "airstamp": "2013-08-05T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99488.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99488.jpg" }, "summary": "

Carrie goes undercover with a team of bank robbers when The Major Crimes Section gets a lead on the gang's leader, a notorious thief who rarely shows his face.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5875"} } }, { "id": 5876, "url": "http://www.tvmaze.com/episodes/5876/unforgettable-2x03-day-of-the-jackie", "name": "Day of the Jackie", "season": 2, "number": 3, "airdate": "2013-08-11", "airtime": "21:00", "airstamp": "2013-08-12T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99487.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99487.jpg" }, "summary": "

Carrie and Al are unable to discern why a businessman was murdered in his hotel room until it's discovered that his death was collateral damage in a larger plot to assassinate a diplomat.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5876"} } }, { "id": 5877, "url": "http://www.tvmaze.com/episodes/5877/unforgettable-2x04-memory-kings", "name": "Memory Kings", "season": 2, "number": 4, "airdate": "2013-08-18", "airtime": "21:00", "airstamp": "2013-08-19T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99485.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99485.jpg" }, "summary": "

When the scientist who helped Carrie understand her memory abilities is murdered, she must track down other people with the same skill in the hopes that one of them holds the key to finding the killer.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5877"} } }, { "id": 5878, "url": "http://www.tvmaze.com/episodes/5878/unforgettable-2x05-past-tense", "name": "Past Tense", "season": 2, "number": 5, "airdate": "2013-08-25", "airtime": "21:00", "airstamp": "2013-08-26T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99484.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99484.jpg" }, "summary": "

Carrie and Al's latest case - the murder of an Afghani cab driver - has the potential to turn into a matter of national security when it's discovered that the victim was a government informant.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5878"} } }, { "id": 5879, "url": "http://www.tvmaze.com/episodes/5879/unforgettable-2x06-line-up-or-shut-up", "name": "Line Up or Shut Up", "season": 2, "number": 6, "airdate": "2013-09-01", "airtime": "21:00", "airstamp": "2013-09-02T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99483.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99483.jpg" }, "summary": "

When a young man is found dead in an expensive sports car he was delivering to a diplomat, each clue leads Carrie and Al to yet another possible motive for the murder.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5879"} } }, { "id": 5880, "url": "http://www.tvmaze.com/episodes/5880/unforgettable-2x07-maps-and-legends", "name": "Maps and Legends", "season": 2, "number": 7, "airdate": "2013-09-08", "airtime": "21:00", "airstamp": "2013-09-09T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99482.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99482.jpg" }, "summary": "

The murder of an urban explorer leads Carrie and Al to not only search for the killer, but to pick up the trail of clues the victim was following on the hunt for a treasure supposedly hidden under the streets of New York.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5880"} } }, { "id": 5881, "url": "http://www.tvmaze.com/episodes/5881/unforgettable-2x08-till-death", "name": "Till Death", "season": 2, "number": 8, "airdate": "2014-04-04", "airtime": "20:00", "airstamp": "2014-04-05T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99480.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99480.jpg" }, "summary": "

After a wealthy couple is murdered, Carrie and Al pose as a married couple to lure in the killer, who Al believes is linked to a series of unsolved homicides he once investigated.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5881"} } }, { "id": 5882, "url": "http://www.tvmaze.com/episodes/5882/unforgettable-2x09-flesh-and-blood", "name": "Flesh and Blood", "season": 2, "number": 9, "airdate": "2014-04-11", "airtime": "20:00", "airstamp": "2014-04-12T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99479.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99479.jpg" }, "summary": "

Carrie catches a deadly assassin who has eluded her before, but must put her personal vendetta aside when it's revealed that the woman has vital information to prevent a terrorist attack on New York City.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5882"} } }, { "id": 5883, "url": "http://www.tvmaze.com/episodes/5883/unforgettable-2x10-manhunt", "name": "Manhunt", "season": 2, "number": 10, "airdate": "2014-04-18", "airtime": "20:00", "airstamp": "2014-04-19T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99477.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99477.jpg" }, "summary": "

When a defense attorney is killed, Carrie and Al hunt for a recently paroled criminal who may be looking to settle other scores.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5883"} } }, { "id": 5884, "url": "http://www.tvmaze.com/episodes/5884/unforgettable-2x11-east-of-islip", "name": "East of Islip", "season": 2, "number": 11, "airdate": "2014-04-25", "airtime": "20:00", "airstamp": "2014-04-26T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99476.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99476.jpg" }, "summary": "

Eliot agrees to let Carrie and Al use his Hamptons beach house in exchange for their help with a local murder investigation, but uncovering the secrets of the tight-knit community prove to be a challenge.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5884"} } }, { "id": 5885, "url": "http://www.tvmaze.com/episodes/5885/unforgettable-2x12-omega-hour", "name": "Omega Hour", "season": 2, "number": 12, "airdate": "2014-05-02", "airtime": "20:00", "airstamp": "2014-05-03T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99475.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99475.jpg" }, "summary": "

Eliot and the mayor are trapped in an elevator by a cybercriminal who threatens to send them to their death, forcing Carrie to work from within the building to thwart his plans.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5885"} } }, { "id": 5886, "url": "http://www.tvmaze.com/episodes/5886/unforgettable-2x13-reunion", "name": "Reunion", "season": 2, "number": 13, "airdate": "2014-05-09", "airtime": "20:00", "airstamp": "2014-05-10T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99474.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99474.jpg" }, "summary": "

When a high school classmate of Carrie's is murdered at her reunion, she must revisit her memories as a teenager for clues to the motive.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5886"} } }, { "id": 5887, "url": "http://www.tvmaze.com/episodes/5887/unforgettable-3x01-new-hundred", "name": "New Hundred", "season": 3, "number": 1, "airdate": "2014-06-29", "airtime": "22:00", "airstamp": "2014-06-30T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/22/57048.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/22/57048.jpg" }, "summary": "

The Secret Service enlists Carrie and Al's help when a murder investigation leads them to uncover a counterfeiting ring run by an assassin.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5887"} } }, { "id": 5888, "url": "http://www.tvmaze.com/episodes/5888/unforgettable-3x02-the-combination", "name": "The Combination", "season": 3, "number": 2, "airdate": "2014-07-06", "airtime": "22:00", "airstamp": "2014-07-07T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/24/62286.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/24/62286.jpg" }, "summary": "

Carrie and Al must uncover the pieces of a championship boxer's past to figure out who was able to beat him to death without any indication that he defended himself or fought back.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5888"} } }, { "id": 5889, "url": "http://www.tvmaze.com/episodes/5889/unforgettable-3x03-the-haircut", "name": "The Haircut", "season": 3, "number": 3, "airdate": "2014-07-13", "airtime": "21:00", "airstamp": "2014-07-14T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/24/62289.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/24/62289.jpg" }, "summary": "

As Lee Anne's lawsuit against the police department continues to scandalize the city, a judge suggests that she accept a settlement offer. Meanwhile, Jamie and Roy argue opposing sides of a \"stand your ground\" case.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5889"} } }, { "id": 5890, "url": "http://www.tvmaze.com/episodes/5890/unforgettable-3x04-cashing-out", "name": "Cashing Out", "season": 3, "number": 4, "airdate": "2014-07-20", "airtime": "21:00", "airstamp": "2014-07-21T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99466.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99466.jpg" }, "summary": "

When Carrie recognizes a murdered city official as someone she played poker with at an underground casino, she puts her career on the line by admitting her illegal activities and volunteers to go back to the tables undercover.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5890"} } }, { "id": 5891, "url": "http://www.tvmaze.com/episodes/5891/unforgettable-3x05-a-moveable-feast", "name": "A Moveable Feast", "season": 3, "number": 5, "airdate": "2014-07-27", "airtime": "21:00", "airstamp": "2014-07-28T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99467.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99467.jpg" }, "summary": "

Carrie and Al must find the connection between a murdered coast guard officer, a celebrity chef who threw him out of his restaurant and a missing block of C-4 before the explosives are used.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5891"} } }, { "id": 5892, "url": "http://www.tvmaze.com/episodes/5892/unforgettable-3x06-stray-bullet", "name": "Stray Bullet", "season": 3, "number": 6, "airdate": "2014-08-03", "airtime": "21:00", "airstamp": "2014-08-04T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99469.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99469.jpg" }, "summary": "

Al becomes the prime suspect in the murder of a parolee he helped put in jail, forcing Carrie to conduct an off-the-books investigation to prove his innocence to Internal Affairs.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5892"} } }, { "id": 5893, "url": "http://www.tvmaze.com/episodes/5893/unforgettable-3x07-throwing-shade", "name": "Throwing Shade", "season": 3, "number": 7, "airdate": "2014-08-17", "airtime": "21:00", "airstamp": "2014-08-18T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99470.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99470.jpg" }, "summary": "

When one of Eliot's oldest friends, the campaign manager for a mayoral candidate, is murdered, he is forced to face his past and current demons as Carrie and Al work to uncover the killer.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5893"} } }, { "id": 5894, "url": "http://www.tvmaze.com/episodes/5894/unforgettable-3x08-the-island", "name": "The Island", "season": 3, "number": 8, "airdate": "2014-08-24", "airtime": "21:00", "airstamp": "2014-08-25T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99472.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99472.jpg" }, "summary": "

Carrie and Al's investigation into the death of a college dropout takes a surprising turn when they discover he had been living in an off-the-grid community on an abandoned island near Manhattan.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5894"} } }, { "id": 5895, "url": "http://www.tvmaze.com/episodes/5895/unforgettable-3x09-admissions", "name": "Admissions", "season": 3, "number": 9, "airdate": "2014-08-30", "airtime": "20:00", "airstamp": "2014-08-31T00:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99473.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99473.jpg" }, "summary": "

Carrie and Al dig into the secrets of students and faculty at an elite prep school when a high-powered CEO and father of one of the students is murdered.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5895"} } }, { "id": 5896, "url": "http://www.tvmaze.com/episodes/5896/unforgettable-3x10-fire-and-ice", "name": "Fire and Ice", "season": 3, "number": 10, "airdate": "2014-08-31", "airtime": "21:00", "airstamp": "2014-09-01T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99465.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99465.jpg" }, "summary": "

When Homeland Security takes over a bombing investigation from Major Crimes, Carrie doubts their conclusion that it's tied to terrorism and secretly continues her own investigation. Meanwhile, Webster makes friends with Murray's daughter.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5896"} } }, { "id": 5897, "url": "http://www.tvmaze.com/episodes/5897/unforgettable-3x11-true-identity", "name": "True Identity", "season": 3, "number": 11, "airdate": "2014-09-07", "airtime": "21:00", "airstamp": "2014-09-08T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99463.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99463.jpg" }, "summary": "

Carrie and Al investigate the murder of a high-end matchmaking service employee, but each secret they uncover in the victim's life only serves to create a new possible suspect and motive.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5897"} } }, { "id": 5898, "url": "http://www.tvmaze.com/episodes/5898/unforgettable-3x12-moving-on", "name": "Moving On", "season": 3, "number": 12, "airdate": "2014-09-14", "airtime": "21:30", "airstamp": "2014-09-15T01:30:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99461.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99461.jpg" }, "summary": "

Carrie and Al delve into the disturbing - and dangerous - world of celebrity obsession when a television star is found murdered in his dressing room.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5898"} } }, { "id": 5899, "url": "http://www.tvmaze.com/episodes/5899/unforgettable-3x13-doa", "name": "DOA", "season": 3, "number": 13, "airdate": "2014-09-14", "airtime": "22:30", "airstamp": "2014-09-15T02:30:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99460.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99460.jpg" }, "summary": "

Carrie is unable to utilize her perfect memory when an assassin doses her with a deadly poison that attacks her brain, leaving Al on a desperate hunt for the antidote.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/5899"} } }, { "id": 213033, "url": "http://www.tvmaze.com/episodes/213033/unforgettable-4x01-blast-from-the-past", "name": "Blast from the Past", "season": 4, "number": 1, "airdate": "2015-11-27", "airtime": "20:00", "airstamp": "2015-11-28T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/32/81086.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/32/81086.jpg" }, "summary": "

Eddie Martin, Carrie's long-lost husband, pays a visit to Major Crimes while investigating a meth crew that is involved in something more nefarious than dealing drugs.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/213033"} } }, { "id": 376859, "url": "http://www.tvmaze.com/episodes/376859/unforgettable-4x02-gut-check", "name": "Gut Check", "season": 4, "number": 2, "airdate": "2015-11-27", "airtime": "21:00", "airstamp": "2015-11-28T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/32/81087.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/32/81087.jpg" }, "summary": "

Carrie and Al are assigned to transport the star witness in a high-profile securities fraud case to Miami, while attempting to evade the killers on their trail.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/376859"} } }, { "id": 426210, "url": "http://www.tvmaze.com/episodes/426210/unforgettable-4x03-behind-the-beat", "name": "Behind the Beat", "season": 4, "number": 3, "airdate": "2015-12-04", "airtime": "20:00", "airstamp": "2015-12-05T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/32/81874.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/32/81874.jpg" }, "summary": "

When a young jazz prodigy is found shot to death, Major Crime is called in to investigate. Through their hunt for a murderer, Carrie and the team navigate the halls of an ultra-competitive music conservatory before diving deep into the underbelly of the city's jazz club scene where talent, fame and love might be just enough to get you killed.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/426210"} } }, { "id": 404149, "url": "http://www.tvmaze.com/episodes/404149/unforgettable-4x04-dollars-and-scents", "name": "Dollars And Scents", "season": 4, "number": 4, "airdate": "2015-12-11", "airtime": "20:00", "airstamp": "2015-12-12T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/34/86379.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/34/86379.jpg" }, "summary": "

The murder of a deli employee ignites a hunt for a criminal organization.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/404149"} } }, { "id": 480202, "url": "http://www.tvmaze.com/episodes/480202/unforgettable-4x05-all-in", "name": "All In", "season": 4, "number": 5, "airdate": "2015-12-18", "airtime": "20:00", "airstamp": "2015-12-19T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/35/89290.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/35/89290.jpg" }, "summary": "

Carrie's old flame resurfaces and a murder investigation leads the team to Atlantic City.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/480202"} } }, { "id": 532035, "url": "http://www.tvmaze.com/episodes/532035/unforgettable-4x06-the-return-of-eddie", "name": "The Return of Eddie", "season": 4, "number": 6, "airdate": "2016-01-01", "airtime": "22:00", "airstamp": "2016-01-02T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/37/94093.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/37/94093.jpg" }, "summary": "

Carrie and Al suspect that a tabloid cameraman's death during a convenience-store robbery may be more than just a random act of violence.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/532035"} } }, { "id": 532036, "url": "http://www.tvmaze.com/episodes/532036/unforgettable-4x07-we-can-be-heroes", "name": "We Can Be Heroes", "season": 4, "number": 7, "airdate": "2016-01-08", "airtime": "22:00", "airstamp": "2016-01-09T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99459.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99459.jpg" }, "summary": "

Major Crimes determines that the kidnapping of a prominent scientist's son was not a crime of opportunity but rather a calculated scheme for revenge.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/532036"} } }, { "id": 533174, "url": "http://www.tvmaze.com/episodes/533174/unforgettable-4x08-breathing-space", "name": "Breathing Space", "season": 4, "number": 8, "airdate": "2016-01-15", "airtime": "21:00", "airstamp": "2016-01-16T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99454.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99454.jpg" }, "summary": "

Suspects are plentiful in the case of a murdered aerospace engineer; the Major Crimes team learns that the victim was working on a billionaire's top-secret space mission.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/533174"} } }, { "id": 546033, "url": "http://www.tvmaze.com/episodes/546033/unforgettable-4x09-shelter-from-the-storm", "name": "Shelter from the Storm", "season": 4, "number": 9, "airdate": "2016-01-15", "airtime": "22:00", "airstamp": "2016-01-16T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/39/99520.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/39/99520.jpg" }, "summary": "

Carrie, Al and a captured criminal hole up in in an abandoned precinct as a sinister storm approaches, with their captive's violent crew hot on their tail.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/546033"} } }, { "id": 533175, "url": "http://www.tvmaze.com/episodes/533175/unforgettable-4x10-game-on", "name": "Game On", "season": 4, "number": 10, "airdate": "2016-01-22", "airtime": "20:00", "airstamp": "2016-01-23T01:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/40/102250.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/40/102250.jpg" }, "summary": "

Carrie and Al investigate the world of high-stakes video games and corporate espionage after a man is found dead inside a haunted-house attraction.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/533175"} } }, { "id": 570267, "url": "http://www.tvmaze.com/episodes/570267/unforgettable-4x11-about-face", "name": "About Face", "season": 4, "number": 11, "airdate": "2016-01-22", "airtime": "21:00", "airstamp": "2016-01-23T02:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/40/102251.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/40/102251.jpg" }, "summary": "

Carrie and Al receive new information in the cold case of a missing surgeon, putting them on the trail of two con artists.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/570267"} } }, { "id": 570269, "url": "http://www.tvmaze.com/episodes/570269/unforgettable-4x12-bad-company", "name": "Bad Company", "season": 4, "number": 12, "airdate": "2016-01-22", "airtime": "22:00", "airstamp": "2016-01-23T03:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/40/102252.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/40/102252.jpg" }, "summary": "

Capt. Russo is suspected in the murder of an informant, leading Carrie and Al into a cat-and-mouse game with a corrupt former cop.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/570269"} } }, { "id": 570271, "url": "http://www.tvmaze.com/episodes/570271/unforgettable-4x13-paranoid-android", "name": "Paranoid Android", "season": 4, "number": 13, "airdate": "2016-01-22", "airtime": "23:00", "airstamp": "2016-01-23T04:00:00+00:00", "runtime": 60, "image": { "medium": "http://static.tvmaze.com/uploads/images/medium_landscape/40/102253.jpg", "original": "http://static.tvmaze.com/uploads/images/original_untouched/40/102253.jpg" }, "summary": "

The search for a wanted shooter triggers a flashback that conflicts with Carrie's perfect memory; the Major Crimes team uncovers a nefarious conspiracy involving trained killers.

", "_links": { "self": {"href": "http://api.tvmaze.com/episodes/570271"} } } ], "year": "2011-09-20", "description": "

Unforgettable follows Carrie Wells, an enigmatic former police detective with a rare condition that makes her memory so flawless that every place, every conversation, every moment of joy and every heartbreak is forever embedded in her mind. It's not just that she doesn't forget anything - she can't; except for one thing: the details that would help solve her sister's long-ago murder. Carrie has tried to put her past behind her, but she's unexpectedly reunited with her ex-boyfriend and partner, NYPD Detective Al Burns when she consults on a homicide case.

" }, "_id": "5bedbeffa70245f2bbdd6a05", "id": 89, "name": "Unforgettable", "image": "http://static.tvmaze.com/uploads/images/original_untouched/0/663.jpg" }; ================================================ FILE: lib/src/helpers/config/route_handlers.dart ================================================ part of netflix; var rootHandler = Handler( handlerFunc: (BuildContext context, Map> params, [dynamic object]) { return Home(); }, ); var summaryRouteHandler = Handler( handlerFunc: (BuildContext context, Map> params, [dynamic object]) { return Summary(); }, ); var detailRouteHandler = Handler( handlerFunc: (BuildContext context, Map> params, [dynamic object]) { return TvShow(match: object['match'], item: object['show']); }, ); var trailerRouteHandler = Handler( handlerFunc: (BuildContext context, Map> params, [dynamic object]) { return Video(title: object['title']); }, ); var filterRouteHandler = Handler( handlerFunc: (BuildContext context, Map> params, [dynamic object]) { return Filter( type: object['type'], ); }, ); ================================================ FILE: lib/src/helpers/config/routes.dart ================================================ part of netflix; class Routes { static String root = '/'; static String summary = '/summary'; static String detail = '/detail'; static String filter = '/filter'; static String video = '/trailer'; static void configureRoutes(Router router) { router.notFoundHandler = Handler(handlerFunc: (BuildContext context, Map> params, [dynamic object]) { print('ROUTE WAS NOT FOUND !!!'); return null; }); router.define(root, handler: rootHandler); router.define(summary, handler: summaryRouteHandler); router.define(detail, handler: detailRouteHandler); router.define(filter, handler: filterRouteHandler); router.define(video, handler: trailerRouteHandler); } } ================================================ FILE: lib/src/models/episode.dart ================================================ part of netflix; class Episode { int _number; int _season; String _image; String _summary; String _name; int _duration; Episode.fromJson(Map parsedJson) { RegExp exp = new RegExp(r"<[^>]*>"); _number = parsedJson['number']; _season = parsedJson['season']; _image = (parsedJson['image'] ?? {})['medium']; _summary = parsedJson['summary'] != null ? parsedJson['summary'].replaceAll(exp, '') : ''; _name = parsedJson['name']; _duration = parsedJson['airtime'] != null && parsedJson['airtime'].toString().isNotEmpty ? int.parse(parsedJson['airtime'].split(':')[0]) : 0; } int get number => _number; int get season => _season; String get image => _image; String get summary => _summary; String get name => _name; int get duration => _duration; } ================================================ FILE: lib/src/models/item_model.dart ================================================ part of netflix; class ItemModel { String _title; List _results = []; ItemModel.fromJson(Map parsedJson) { _title = parsedJson['title']; _results = List.from(parsedJson['items']) .map( (r) => Result.fromJson(r), ) .toList(); } List get results => _results; String get title => _title; } ================================================ FILE: lib/src/models/result.dart ================================================ part of netflix; class Result { int id; String _name; String _image; List _genres; List _cast; List _episodes; List _seasons = []; DateTime _date; String _description; Result.fromJson(Map parsedJson) { _name = parsedJson['name']; _image = parsedJson['image']; _genres = List.from(parsedJson['details']['genres']) .map((genre) => genre.toString()) .toList(); _cast = List.from(parsedJson['details']['cast']) .map((cast) => cast['person']['name'].toString()) .toList(); _date = parsedJson['year'] != null ? DateTime.parse(parsedJson['year'].toString()) : DateTime.now(); RegExp exp = new RegExp(r"<[^>]*>"); _description = parsedJson['details']['description'].replaceAll(exp, ''); _episodes = List.from(parsedJson['details']['episodes']) .map((e) => Episode.fromJson(e)) .toList(); List.from(parsedJson['details']['episodes']).forEach((s) { int seasonNumber = int.parse(s['season'].toString()); if (!_seasons.contains(seasonNumber)) _seasons.add(seasonNumber); }); } String get name => _name; String get image => _image; List get genres => _genres; List get cast => _cast; DateTime get date => _date; String get description => _description; List get episodes => _episodes; List get seasons => _seasons; } ================================================ FILE: lib/src/pages/detail/index.dart ================================================ part of netflix; class TvShow extends StatefulWidget { final int match; final Result item; TvShow({ Key key, this.match, this.item, }) : super(key: key); @override TvShowState createState() => TvShowState(); } ================================================ FILE: lib/src/pages/detail/state.dart ================================================ part of netflix; class TvShowState extends State { var currentSeason = 1; @override void initState() { super.initState(); } @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; List seasonEpisodes = widget.item.episodes .where((Episode e) => e.season == currentSeason) .toList(); return Scaffold( backgroundColor: Colors.black, body: CustomScrollView( slivers: [ SliverAppBar( primary: true, expandedHeight: 430.0, backgroundColor: Colors.black, flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Container( child: Stack( fit: StackFit.loose, children: [ Container( width: screenSize.width, height: 220, child: Center( child: Container( height: 64.0, width: 64.0, child: OutlineButton( padding: EdgeInsets.all(0.0), onPressed: () => print('play'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(32.0), ), ), child: Container( height: 64.0, width: 64.0, decoration: BoxDecoration( color: Color.fromRGBO(0, 0, 0, 0.3), borderRadius: BorderRadius.circular(32.0), ), child: Icon( Icons.play_arrow, color: Colors.white, size: 48.0, ), ), ), ), ), decoration: BoxDecoration( image: DecorationImage( image: NetworkImage( widget.item.image, ), fit: BoxFit.fitWidth, ), ), ), Container( width: screenSize.width, height: 220, child: DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: FractionalOffset.topCenter, end: FractionalOffset.bottomCenter, stops: [0.1, 0.4, 1.0], colors: [ Colors.black54, Colors.transparent, Colors.black ], ), ), child: Padding( padding: EdgeInsets.only( left: 8.0, right: 8.0, bottom: 20.0), child: Column( mainAxisAlignment: MainAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( widget.item.name, maxLines: 3, textAlign: TextAlign.left, style: TextStyle( color: Colors.white, fontWeight: FontWeight.w700, fontSize: 18.0, ), ) ], ), ), ), ), Positioned( top: 220, child: Container( padding: EdgeInsets.only(left: 8.0, right: 30.0), width: screenSize.width, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( '${widget.match}% de coicidencia', textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(0, 255, 0, 0.8), fontWeight: FontWeight.w600, fontSize: 15.0, ), ), Text( widget.item.date.year.toString(), textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.3), fontWeight: FontWeight.w400, fontSize: 12.0, ), ), Text( '16 +', textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.3), fontWeight: FontWeight.w400, fontSize: 12.0, ), ), Text( '${widget.item.seasons.length} temporadas', textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.3), fontWeight: FontWeight.w400, fontSize: 12.0, ), ), ], ), ), ), Positioned( top: 240, child: Container( padding: EdgeInsets.symmetric(horizontal: 8.0), width: screenSize.width, child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: EdgeInsets.only(top: 8.0), child: Container( child: Text( widget.item.description, overflow: TextOverflow.ellipsis, maxLines: 3, textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.8), fontWeight: FontWeight.w400, fontSize: 12.0, ), ), ), ), Padding( padding: EdgeInsets.only(top: 8.0), child: Container( child: RichText( maxLines: 2, overflow: TextOverflow.ellipsis, text: TextSpan( style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.3), fontWeight: FontWeight.w400, fontSize: 12.0, ), children: [ TextSpan( text: 'Protagonizada por: ', style: TextStyle( fontWeight: FontWeight.bold), ), TextSpan( text: widget.item.cast.join(', ')), ], ), ), ), ), Padding( padding: EdgeInsets.only(top: 8.0), child: Row( children: [ FlatButton( textColor: Colors.white70, onPressed: () => print('Mi Lista'), child: Container( height: 50.0, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( Icons.add, size: 32.0, ), Text( 'Mi Lista', style: TextStyle(fontSize: 10.0), ) ], ), ), ), FlatButton( textColor: Colors.white70, onPressed: () => print('calificar'), child: Container( height: 50.0, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( Icons.thumb_up, size: 24.0, ), Text( 'Calificar', style: TextStyle(fontSize: 10.0), ) ], ), ), ), FlatButton( textColor: Colors.white70, onPressed: () => print('Compartir'), child: Container( height: 50.0, child: Column( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( Icons.share, size: 20.0, ), Text( 'Compartir', style: TextStyle(fontSize: 10.0), ) ], ), ), ), ], ), ), Padding( padding: EdgeInsets.only(top: 8.0), child: Container( child: Text( 'EPISODIOS', overflow: TextOverflow.ellipsis, maxLines: 3, textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.8), fontWeight: FontWeight.w700, fontSize: 15.0, ), ), ), ), FlatButton( padding: EdgeInsets.all(0.0), onPressed: widget.item.seasons.length > 1 ? () => print('cambiando temporada') : null, child: Row( children: [ Text( 'Temporada $currentSeason', overflow: TextOverflow.ellipsis, maxLines: 3, textAlign: TextAlign.left, style: TextStyle( color: Color.fromRGBO(255, 255, 255, 0.6), fontWeight: FontWeight.w500, fontSize: 15.0, ), ), (widget.item.seasons.length > 1 ? Padding( padding: EdgeInsets.only(left: 8.0), child: Icon( Icons.arrow_drop_down, color: Color.fromRGBO( 255, 255, 255, 0.6), ), ) : Container()) ], ), ), ], ), ), ), ], ), ), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) => Container( margin: EdgeInsets.only(bottom: 16.0), child: Column( children: [ Row( children: [ Container( margin: EdgeInsets.only(right: 8.0), width: 150.0, height: 90.0, decoration: BoxDecoration( image: DecorationImage( image: NetworkImage(seasonEpisodes[index].image), ), ), child: Center( child: Container( height: 32.0, width: 32.0, child: OutlineButton( padding: EdgeInsets.all(0.0), onPressed: () => print('play'), shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(32.0), ), ), child: Container( height: 32.0, width: 32.0, decoration: BoxDecoration( color: Color.fromRGBO(0, 0, 0, 0.3), borderRadius: BorderRadius.circular(16.0), ), child: Icon( Icons.play_arrow, color: Colors.white, size: 24.0, ), ), ), ), ), ), Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${index + 1}. ${seasonEpisodes[index].name}', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontWeight: FontWeight.w600, fontSize: 14.0, color: Color.fromRGBO(255, 255, 255, 0.8), ), ), Text( '${seasonEpisodes[index].duration}m', maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 12.0, color: Color.fromRGBO(255, 255, 255, 0.3), ), ) ], ) ], ), Text( seasonEpisodes[index].summary, maxLines: 3, overflow: TextOverflow.ellipsis, style: TextStyle( fontSize: 10.0, color: Color.fromRGBO(255, 255, 255, 0.3), ), ) ], ), ), childCount: seasonEpisodes.length, ), ) ], ), ); } } ================================================ FILE: lib/src/pages/filter/index.dart ================================================ part of netflix; class Filter extends StatefulWidget { final String title; final String type; Filter({ Key key, this.title, this.type, }) : super(key: key); @override FilterState createState() => FilterState(); } ================================================ FILE: lib/src/pages/filter/state.dart ================================================ part of netflix; class FilterState extends State { String filterSelected; List options = ['Series', 'Películas', 'Mi-lista']; dynamic tvShow = { "details": { "genres": ["Drama", "Crime"], "year": "2011-09-20", "description": "

Unforgettable follows Carrie Wells, an enigmatic former police detective with a rare condition that makes her memory so flawless that every place, every conversation, every moment of joy and every heartbreak is forever embedded in her mind. It's not just that she doesn't forget anything - she can't; except for one thing: the details that would help solve her sister's long-ago murder. Carrie has tried to put her past behind her, but she's unexpectedly reunited with her ex-boyfriend and partner, NYPD Detective Al Burns when she consults on a homicide case.

" }, "_id": "5bedbf00a70245f2bbdd6a64", "id": 89, "name": "Unforgettable", "image": "http://static.tvmaze.com/uploads/images/original_untouched/0/663.jpg" }; @override void initState() { filterSelected = widget.type; super.initState(); } @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; return CustomScrollView( slivers: [ SliverAppBar( primary: true, expandedHeight: screenSize.height * 0.65, backgroundColor: Colors.black, leading: Image.asset('assets/images/netflix_icon.png'), // titleSpacing: 20.0, title: Title( color: Colors.black, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Hero( tag: widget.type, child: FlatButton( onPressed: () => print(widget.type), child: Text( widget.type.replaceAll('-', ' '), style: TextStyle( color: Colors.white, fontWeight: FontWeight.w400, fontSize: 14.0, ), ), ), ), ], ), ), flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Container( child: Stack( fit: StackFit.expand, children: [ Image.network( tvShow['image'], fit: BoxFit.cover, ), DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: FractionalOffset.topCenter, end: FractionalOffset.bottomCenter, stops: [0.1, 0.6, 1.0], colors: [ Colors.black54, Colors.transparent, Colors.black ], ), ), ), ], ), ), ), ), ], ); } } ================================================ FILE: lib/src/pages/home/index.dart ================================================ part of netflix; class Home extends StatefulWidget { Home({Key key, this.title}) : super(key: key); final String title; @override HomeState createState() => HomeState(); } ================================================ FILE: lib/src/pages/home/state.dart ================================================ part of netflix; class HomeState extends State with SingleTickerProviderStateMixin { TabController controller; @override void initState() { super.initState(); SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light .copyWith(statusBarColor: Colors.transparent)); controller = TabController(length: 5, initialIndex: 0, vsync: this); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, bottomNavigationBar: TabBar( labelStyle: TextStyle(fontSize: 10.0), indicatorWeight: 0.1, controller: controller, tabs: [ Tab(text: 'Inicio', icon: Icon(Icons.home)), Tab(text: 'Buscar', icon: Icon(Icons.search)), Tab(text: 'Próximamente', icon: Icon(Icons.ondemand_video)), Tab(text: 'Descargas', icon: Icon(Icons.file_download)), Tab(text: 'Más', icon: Icon(Icons.menu)), ], ), body: TabBarView( controller: controller, physics: NeverScrollableScrollPhysics(), children: [ Summary(), Summary(), Summary(), Summary(), Summary(), ], ), ); } } ================================================ FILE: lib/src/pages/summary/index.dart ================================================ part of netflix; class Summary extends StatefulWidget { Summary({Key key, this.title}) : super(key: key); final String title; @override SummaryState createState() => SummaryState(); } ================================================ FILE: lib/src/pages/summary/state.dart ================================================ part of netflix; class SummaryState extends State { void goTo(String type) { Application.router.navigateTo( context, '${Routes.filter}', transition: TransitionType.nativeModal, transitionDuration: const Duration(milliseconds: 200), object: {'type': type}, ); } void goToDetail(Result item, int match) { Application.router.navigateTo( context, '${Routes.detail}', transition: TransitionType.inFromRight, transitionDuration: const Duration(milliseconds: 200), object: {'match': match, 'show': item}, ); } void showTrailer() { SystemChrome.setPreferredOrientations([ DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft, ]).then((e) { Application.router.navigateTo( context, Routes.video, object: {'title': 'Unforgettable'}, transition: TransitionType.inFromBottom, transitionDuration: const Duration(milliseconds: 200), ); }); } List renderMainGenres() { List genres = List.from(tvShow['details']['genres'].map((g) { return Padding( padding: EdgeInsets.symmetric(horizontal: 8.0), child: Text( g, style: TextStyle( color: Colors.white, fontWeight: FontWeight.w400, fontSize: 12.0, ), ), ); }).toList()); return genres; } Widget renderTitle(String tag, String text) { return Hero( tag: tag, child: FlatButton( onPressed: () => goTo(tag), child: Text( text, style: TextStyle( color: Colors.white, fontWeight: FontWeight.w400, fontSize: 14.0, ), ), ), ); } @override Widget build(BuildContext context) { final Size screenSize = MediaQuery.of(context).size; final Result show = Result.fromJson(tvShow); bloc.fetchAllMovies(); return StreamBuilder( stream: bloc.allMovies, builder: (context, AsyncSnapshot> snapshot) { if (snapshot.hasData) { return CustomScrollView( slivers: [ SliverAppBar( primary: true, expandedHeight: screenSize.height * 0.65, backgroundColor: Colors.black, leading: Image.asset('assets/images/netflix_icon.png'), titleSpacing: 20.0, title: Title( color: Colors.black, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ renderTitle('Series', 'Series'), renderTitle('Películas', 'Películas'), renderTitle('Mi-lista', 'Mi lista'), ], ), ), flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: Container( child: Stack( fit: StackFit.expand, children: [ Image.network(show.image, fit: BoxFit.cover), DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: FractionalOffset.topCenter, end: FractionalOffset.bottomCenter, stops: [0.1, 0.6, 1.0], colors: [ Colors.black54, Colors.transparent, Colors.black ], ), ), child: Container( height: 40.0, width: screenSize.width, child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Padding( padding: EdgeInsets.only(bottom: 8.0), child: Container( decoration: const BoxDecoration( border: Border( bottom: BorderSide( width: 3.0, color: Color.fromRGBO(185, 3, 12, 1.0), ), ), ), child: Text( tvShow['name'].replaceAll(' ', '\n'), maxLines: 3, textAlign: TextAlign.left, style: TextStyle( height: 0.65, color: Colors.white, fontWeight: FontWeight.w700, fontSize: 30.0, ), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.center, children: renderMainGenres(), ), Container( padding: EdgeInsets.symmetric(vertical: 16.0), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ FlatButton( textColor: Colors.white, child: Column( children: [ Icon(Icons.add), Text( 'Mi lista', style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w300), ), ], ), onPressed: () => print('mi lista'), ), RaisedButton( textColor: Colors.black, color: Colors.white, child: Row( children: [ Icon(Icons.play_arrow), Text( 'Reproducir', style: TextStyle( fontSize: 16.0, fontWeight: FontWeight.w500, ), ), ], ), onPressed: showTrailer, ), FlatButton( textColor: Colors.white, child: Column( children: [ Icon(Icons.info_outline), Text( 'Información', style: TextStyle( fontSize: 10.0, fontWeight: FontWeight.w300), ), ], ), onPressed: () => goToDetail(show, 99), ), ], ), ) ], ), ), ), ], ), ), ), ), SliverList( delegate: SliverChildBuilderDelegate( (context, index) => ShowsList( items: snapshot.data[index].results, onTap: goToDetail, title: snapshot.data[index].title, ), childCount: snapshot.data.length, ), ) ], ); } else if (snapshot.hasError) { return Text(snapshot.error.toString()); } return Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Color.fromRGBO(219, 0, 0, 1.0)), )); }, ); } } ================================================ FILE: lib/src/pages/video/index.dart ================================================ part of netflix; class Video extends StatefulWidget { final String title; Video({Key key, this.title}) : super(key: key); @override VideoState createState() => VideoState(); } ================================================ FILE: lib/src/pages/video/state.dart ================================================ part of netflix; class VideoState extends State