diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..dfe0770
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,2 @@
+# Auto detect text files and perform LF normalization
+* text=auto
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b2d5ee3
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,40 @@
+# Slidy History Files
+.slidy/
+
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+#.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Web related
+lib/generated_plugin_registrant.dart
+
+# Exceptions to above rules.
+!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages
\ No newline at end of file
diff --git a/.metadata b/.metadata
new file mode 100644
index 0000000..361e1e4
--- /dev/null
+++ b/.metadata
@@ -0,0 +1,10 @@
+# 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: 18cd7a3601bcffb36fdf2f679f763b5e827c2e8e
+ channel: beta
+
+project_type: app
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7f06643
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# yShare
+
+A Flutter project recreating designs.
+
+## Tools
+
+- [Slidy](https://pub.dev/packages/slidy)
+- [Mobx](https://pub.dev/packages/flutter_mobx)
+- [Modular](https://pub.dev/packages/flutter_modular)
+
+## Screens
+
+- ![HomeScreen](./gifs/homescreen.gif)
+- ![FilmPage](./gifs/filmpage.gif)
+- ![Favourite Example](./gifs/favourites_example.gif)
+- ![Actor Page](./gifs/actorpage.gif)
+
+### References
+
+- [Inspiration 1](https://dribbble.com/shots/7902411-Actors-Tracking-App)
+- [Inspiration 2](https://dribbble.com/shots/7895707-Social-Movie-Experience-App)
+- [Inspiration 3](https://dribbble.com/shots/9955876-Skeuomorph-Movie-App)
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..0381656
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,54 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# Google internally enforced rules. See README.md for more information,
+# including a list of lints that are intentionally _not_ enforced.
+
+linter:
+ rules:
+ - always_declare_return_types
+ - always_require_non_null_named_parameters
+ - annotate_overrides
+ - avoid_empty_else
+ - avoid_init_to_null
+ - avoid_null_checks_in_equality_operators
+ - avoid_relative_lib_imports
+ - avoid_return_types_on_setters
+ - avoid_shadowing_type_parameters
+ - avoid_types_as_parameter_names
+ - camel_case_extensions
+ - curly_braces_in_flow_control_structures
+ - empty_catches
+ - empty_constructor_bodies
+ - library_names
+ - library_prefixes
+ - no_duplicate_case_values
+ - null_closures
+ - omit_local_variable_types
+ - prefer_adjacent_string_concatenation
+ - prefer_collection_literals
+ - prefer_conditional_assignment
+ - prefer_contains
+ - prefer_equal_for_default_values
+ - prefer_final_fields
+ - prefer_for_elements_to_map_fromIterable
+ - prefer_generic_function_type_aliases
+ - prefer_if_null_operators
+ - prefer_is_empty
+ - prefer_is_not_empty
+ - prefer_iterable_whereType
+ - prefer_single_quotes
+ - prefer_spread_collections
+ - recursive_getters
+ - slash_for_doc_comments
+ - type_init_formals
+ - unawaited_futures
+ - unnecessary_const
+ - unnecessary_new
+ - unnecessary_null_in_if_null_operators
+ - unnecessary_this
+ - unrelated_type_equality_checks
+ - use_function_type_syntax_for_parameters
+ - use_rethrow_when_possible
+ - valid_regexps
\ No newline at end of file
diff --git a/android/.gitignore b/android/.gitignore
new file mode 100644
index 0000000..bc2100d
--- /dev/null
+++ b/android/.gitignore
@@ -0,0 +1,7 @@
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
diff --git a/android/app/build.gradle b/android/app/build.gradle
new file mode 100644
index 0000000..220732d
--- /dev/null
+++ b/android/app/build.gradle
@@ -0,0 +1,67 @@
+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 plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion 28
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ lintOptions {
+ disable 'InvalidPackage'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.azambuja.yshare"
+ minSdkVersion 16
+ targetSdkVersion 28
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ testInstrumentationRunner "androidx.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 {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test:runner:1.1.1'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
new file mode 100644
index 0000000..8706179
--- /dev/null
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..3889f1c
--- /dev/null
+++ b/android/app/src/main/AndroidManifest.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/example/bshare/MainActivity.kt b/android/app/src/main/kotlin/com/example/bshare/MainActivity.kt
new file mode 100644
index 0000000..7ef861c
--- /dev/null
+++ b/android/app/src/main/kotlin/com/example/bshare/MainActivity.kt
@@ -0,0 +1,12 @@
+package com.azambuja.yshare
+
+import androidx.annotation.NonNull;
+import io.flutter.embedding.android.FlutterActivity
+import io.flutter.embedding.engine.FlutterEngine
+import io.flutter.plugins.GeneratedPluginRegistrant
+
+class MainActivity: FlutterActivity() {
+ override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
+ GeneratedPluginRegistrant.registerWith(flutterEngine);
+ }
+}
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
new file mode 100644
index 0000000..304732f
--- /dev/null
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..db77bb4
Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..17987b7
Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..09d4391
Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..d5f1c8d
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..4d6372e
Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..00fa441
--- /dev/null
+++ b/android/app/src/main/res/values/styles.xml
@@ -0,0 +1,8 @@
+
+
+
+
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
new file mode 100644
index 0000000..8706179
--- /dev/null
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
new file mode 100644
index 0000000..3100ad2
--- /dev/null
+++ b/android/build.gradle
@@ -0,0 +1,31 @@
+buildscript {
+ ext.kotlin_version = '1.3.50'
+ repositories {
+ google()
+ jcenter()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+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
+}
diff --git a/android/gradle.properties b/android/gradle.properties
new file mode 100644
index 0000000..38c8d45
--- /dev/null
+++ b/android/gradle.properties
@@ -0,0 +1,4 @@
+org.gradle.jvmargs=-Xmx1536M
+android.enableR8=true
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..296b146
--- /dev/null
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#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-5.6.2-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
new file mode 100644
index 0000000..5a2f14f
--- /dev/null
+++ b/android/settings.gradle
@@ -0,0 +1,15 @@
+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
+}
diff --git a/assets/images/female_placeholder.jpg b/assets/images/female_placeholder.jpg
new file mode 100644
index 0000000..dbb0989
Binary files /dev/null and b/assets/images/female_placeholder.jpg differ
diff --git a/assets/images/male_placeholder.jpg b/assets/images/male_placeholder.jpg
new file mode 100644
index 0000000..239c2eb
Binary files /dev/null and b/assets/images/male_placeholder.jpg differ
diff --git a/gifs/actorpage.gif b/gifs/actorpage.gif
new file mode 100644
index 0000000..cea290f
Binary files /dev/null and b/gifs/actorpage.gif differ
diff --git a/gifs/favourites_example.gif b/gifs/favourites_example.gif
new file mode 100644
index 0000000..cce9c0b
Binary files /dev/null and b/gifs/favourites_example.gif differ
diff --git a/gifs/filmpage.gif b/gifs/filmpage.gif
new file mode 100644
index 0000000..cc2f8ca
Binary files /dev/null and b/gifs/filmpage.gif differ
diff --git a/gifs/homescreen.gif b/gifs/homescreen.gif
new file mode 100644
index 0000000..6ab537b
Binary files /dev/null and b/gifs/homescreen.gif differ
diff --git a/ios/.gitignore b/ios/.gitignore
new file mode 100644
index 0000000..e96ef60
--- /dev/null
+++ b/ios/.gitignore
@@ -0,0 +1,32 @@
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
new file mode 100644
index 0000000..6b4c0f7
--- /dev/null
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -0,0 +1,26 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 8.0
+
+
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
new file mode 100644
index 0000000..e8efba1
--- /dev/null
+++ b/ios/Flutter/Debug.xcconfig
@@ -0,0 +1,2 @@
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
new file mode 100644
index 0000000..399e934
--- /dev/null
+++ b/ios/Flutter/Release.xcconfig
@@ -0,0 +1,2 @@
+#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..1e8c3c9
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,41 @@
+# 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 flutter_root
+ generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
+ unless File.exist?(generated_xcode_build_settings_path)
+ raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
+ end
+
+ File.foreach(generated_xcode_build_settings_path) do |line|
+ matches = line.match(/FLUTTER_ROOT\=(.*)/)
+ return matches[1].strip if matches
+ end
+ raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
+end
+
+require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
+
+flutter_ios_podfile_setup
+
+target 'Runner' do
+ use_frameworks!
+ use_modular_headers!
+
+ flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
+end
+
+post_install do |installer|
+ installer.pods_project.targets.each do |target|
+ flutter_additional_ios_build_settings(target)
+ end
+end
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..378d4d2
--- /dev/null
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -0,0 +1,518 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 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, ); }; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 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, ); }; };
+ 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 = ""; };
+ 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 = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; 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; };
+ 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 = (
+ 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 */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 97C146F11CF9000F007C117D /* Supporting Files */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+ 97C146F11CF9000F007C117D /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ 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 = 1020;
+ ORGANIZATIONNAME = "The Chromium Authors";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ 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 */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets 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 = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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;
+ SUPPORTED_PLATFORMS = 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;
+ CLANG_ENABLE_MODULES = YES;
+ 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.azambuja.yshare;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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_DEPRECATED_OBJC_IMPLEMENTATIONS = 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_IMPLICIT_RETAIN_SELF = 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;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ 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.azambuja.yshare;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ 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.azambuja.yshare;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ 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 */;
+}
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
new file mode 100644
index 0000000..a28140c
--- /dev/null
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..1d526a1
--- /dev/null
+++ b/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
new file mode 100644
index 0000000..70693e4
--- /dev/null
+++ b/ios/Runner/AppDelegate.swift
@@ -0,0 +1,13 @@
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..d36b1fa
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,122 @@
+{
+ "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"
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
new file mode 100644
index 0000000..dc9ada4
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
new file mode 100644
index 0000000..28c6bf0
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
new file mode 100644
index 0000000..2ccbfd9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
new file mode 100644
index 0000000..f091b6b
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
new file mode 100644
index 0000000..4cde121
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
new file mode 100644
index 0000000..d0ef06e
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
new file mode 100644
index 0000000..dcdc230
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
new file mode 100644
index 0000000..2ccbfd9
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
new file mode 100644
index 0000000..c8f9ed8
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
new file mode 100644
index 0000000..a6d6b86
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
new file mode 100644
index 0000000..a6d6b86
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
new file mode 100644
index 0000000..75b2d16
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
new file mode 100644
index 0000000..c4df70d
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
new file mode 100644
index 0000000..6a84f41
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
new file mode 100644
index 0000000..d0e1f58
Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
new file mode 100644
index 0000000..0bedcf2
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -0,0 +1,23 @@
+{
+ "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"
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
new file mode 100644
index 0000000..9da19ea
Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
new file mode 100644
index 0000000..89c2725
--- /dev/null
+++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -0,0 +1,5 @@
+# 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.
\ No newline at end of file
diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..f2e259c
--- /dev/null
+++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..f3c2851
--- /dev/null
+++ b/ios/Runner/Base.lproj/Main.storyboard
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
new file mode 100644
index 0000000..5b21225
--- /dev/null
+++ b/ios/Runner/Info.plist
@@ -0,0 +1,45 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ yshare
+ 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
+
+
+
diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h
new file mode 100644
index 0000000..7335fdf
--- /dev/null
+++ b/ios/Runner/Runner-Bridging-Header.h
@@ -0,0 +1 @@
+#import "GeneratedPluginRegistrant.h"
\ No newline at end of file
diff --git a/lib/app/app_controller.dart b/lib/app/app_controller.dart
new file mode 100644
index 0000000..31fec5b
--- /dev/null
+++ b/lib/app/app_controller.dart
@@ -0,0 +1,123 @@
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:mobx/mobx.dart';
+import 'package:shared_preferences/shared_preferences.dart';
+
+part 'app_controller.g.dart';
+
+class AppController = _AppControllerBase with _$AppController;
+
+abstract class _AppControllerBase with Store {
+ Api api;
+
+ _AppControllerBase() {
+ api = Api();
+ loadTheme();
+ loadFavouriteFilms();
+ loadSubscribedActors();
+ }
+
+ @observable
+ ThemeData themeType;
+
+ @observable
+ List subscribedActors = [];
+
+ @observable
+ List favouriteFilms = [];
+
+ @computed
+ bool get isDark => themeType.brightness == Brightness.dark;
+
+ @action
+ void changeTheme() {
+ if (isDark) {
+ themeType = ThemeData.light();
+ } else {
+ themeType = ThemeData.dark();
+ }
+ saveThemePreferences();
+ }
+
+ void saveThemePreferences() {
+ SharedPreferences.getInstance().then((instance) {
+ instance.setBool('isDark', isDark);
+ });
+ }
+
+ @action
+ Future loadTheme() async {
+ final prefs = await SharedPreferences.getInstance();
+ if (prefs.containsKey('isDark') && prefs.getBool('isDark')) {
+ themeType = ThemeData.dark();
+ } else {
+ themeType = ThemeData.light();
+ }
+ }
+
+ List listIntegerToString(List array) {
+ var stringArray = [];
+ array.map((e) {
+ stringArray.add(e.toString());
+ }).toList();
+ return stringArray;
+ }
+
+ void saveListInSharedPreferences() {
+ SharedPreferences.getInstance().then((instance) {
+ instance.setStringList(
+ 'favouriteFilms', listIntegerToString(favouriteFilms));
+ });
+ }
+
+ @action
+ Future loadFavouriteFilms() async {
+ final prefs = await SharedPreferences.getInstance();
+ if (prefs.containsKey('favouriteFilms')) {
+ var films = prefs.getStringList('favouriteFilms');
+ films.map((e) {
+ favouriteFilms.add(int.parse(e));
+ }).toList();
+ }
+ }
+
+ @action
+ Future loadSubscribedActors() async {
+ final prefs = await SharedPreferences.getInstance();
+ if (prefs.containsKey('subscribedActors')) {
+ var actors = prefs.getStringList('subscribedActors');
+ actors.map((e) {
+ subscribedActors.add(int.parse(e));
+ }).toList();
+ }
+ }
+
+ @action
+ void addFilmIntoFavourites(int filmId) {
+ if (!favouriteFilms.contains(filmId)) {
+ favouriteFilms = List.from(favouriteFilms..add(filmId));
+ saveListInSharedPreferences();
+ } else {
+ favouriteFilms = List.from(favouriteFilms..remove(filmId));
+ saveListInSharedPreferences();
+ }
+ }
+
+ void saveSubscribedActors() {
+ SharedPreferences.getInstance().then((instance) {
+ instance.setStringList(
+ 'subscribedActors', listIntegerToString(subscribedActors));
+ });
+ }
+
+ @action
+ void addActorInFavourites(int actorId) {
+ if (!subscribedActors.contains(actorId)) {
+ subscribedActors = List.from(subscribedActors..add(actorId));
+ saveSubscribedActors();
+ } else {
+ subscribedActors = List.from(subscribedActors..remove(actorId));
+ saveSubscribedActors();
+ }
+ }
+}
diff --git a/lib/app/app_controller.g.dart b/lib/app/app_controller.g.dart
new file mode 100644
index 0000000..7aaa318
--- /dev/null
+++ b/lib/app/app_controller.g.dart
@@ -0,0 +1,135 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'app_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$AppController on _AppControllerBase, Store {
+ Computed _$isDarkComputed;
+
+ @override
+ bool get isDark => (_$isDarkComputed ??=
+ Computed(() => super.isDark, name: '_AppControllerBase.isDark'))
+ .value;
+
+ final _$themeTypeAtom = Atom(name: '_AppControllerBase.themeType');
+
+ @override
+ ThemeData get themeType {
+ _$themeTypeAtom.reportRead();
+ return super.themeType;
+ }
+
+ @override
+ set themeType(ThemeData value) {
+ _$themeTypeAtom.reportWrite(value, super.themeType, () {
+ super.themeType = value;
+ });
+ }
+
+ final _$subscribedActorsAtom =
+ Atom(name: '_AppControllerBase.subscribedActors');
+
+ @override
+ List get subscribedActors {
+ _$subscribedActorsAtom.reportRead();
+ return super.subscribedActors;
+ }
+
+ @override
+ set subscribedActors(List value) {
+ _$subscribedActorsAtom.reportWrite(value, super.subscribedActors, () {
+ super.subscribedActors = value;
+ });
+ }
+
+ final _$favouriteFilmsAtom = Atom(name: '_AppControllerBase.favouriteFilms');
+
+ @override
+ List get favouriteFilms {
+ _$favouriteFilmsAtom.reportRead();
+ return super.favouriteFilms;
+ }
+
+ @override
+ set favouriteFilms(List value) {
+ _$favouriteFilmsAtom.reportWrite(value, super.favouriteFilms, () {
+ super.favouriteFilms = value;
+ });
+ }
+
+ final _$loadThemeAsyncAction = AsyncAction('_AppControllerBase.loadTheme');
+
+ @override
+ Future loadTheme() {
+ return _$loadThemeAsyncAction.run(() => super.loadTheme());
+ }
+
+ final _$loadFavouriteFilmsAsyncAction =
+ AsyncAction('_AppControllerBase.loadFavouriteFilms');
+
+ @override
+ Future loadFavouriteFilms() {
+ return _$loadFavouriteFilmsAsyncAction
+ .run(() => super.loadFavouriteFilms());
+ }
+
+ final _$loadSubscribedActorsAsyncAction =
+ AsyncAction('_AppControllerBase.loadSubscribedActors');
+
+ @override
+ Future loadSubscribedActors() {
+ return _$loadSubscribedActorsAsyncAction
+ .run(() => super.loadSubscribedActors());
+ }
+
+ final _$_AppControllerBaseActionController =
+ ActionController(name: '_AppControllerBase');
+
+ @override
+ void changeTheme() {
+ final _$actionInfo = _$_AppControllerBaseActionController.startAction(
+ name: '_AppControllerBase.changeTheme');
+ try {
+ return super.changeTheme();
+ } finally {
+ _$_AppControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ void addFilmIntoFavourites(int filmId) {
+ final _$actionInfo = _$_AppControllerBaseActionController.startAction(
+ name: '_AppControllerBase.addFilmIntoFavourites');
+ try {
+ return super.addFilmIntoFavourites(filmId);
+ } finally {
+ _$_AppControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ void addActorInFavourites(int actorId) {
+ final _$actionInfo = _$_AppControllerBaseActionController.startAction(
+ name: '_AppControllerBase.addActorInFavourites');
+ try {
+ return super.addActorInFavourites(actorId);
+ } finally {
+ _$_AppControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+themeType: ${themeType},
+subscribedActors: ${subscribedActors},
+favouriteFilms: ${favouriteFilms},
+isDark: ${isDark}
+ ''';
+ }
+}
diff --git a/lib/app/app_module.dart b/lib/app/app_module.dart
new file mode 100644
index 0000000..d408455
--- /dev/null
+++ b/lib/app/app_module.dart
@@ -0,0 +1,83 @@
+import 'package:yshare/app/app_widget.dart';
+import 'package:yshare/app/modules/actor_page/actor_page_page.dart';
+import 'package:yshare/app/modules/film_page/film_page_page.dart';
+import 'package:yshare/app/modules/genre_page/genre_page_page.dart';
+import 'package:yshare/app/modules/home/home_module.dart';
+import 'package:yshare/app/modules/popular_page/popular_page_page.dart';
+import 'package:yshare/app/modules/search_page/search_page_page.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:yshare/app/modules/top_rated_page/top_rated_page_page.dart';
+import 'package:yshare/app/modules/trending_page/trending_page_page.dart';
+
+import 'app_controller.dart';
+import 'modules/actor_page/actor_page_controller.dart';
+import 'modules/film_page/film_page_controller.dart';
+import 'modules/genre_page/genre_page_controller.dart';
+import 'modules/popular_page/popular_page_controller.dart';
+import 'modules/search_page/search_page_controller.dart';
+import 'modules/top_rated_page/top_rated_page_controller.dart';
+import 'modules/trending_page/trending_page_controller.dart';
+
+class AppModule extends MainModule {
+ @override
+ List get binds => [
+ Bind((i) => TopRatedPageController(i.get())),
+ Bind((i) => PopularPageController(i.get())),
+ Bind((i) => TrendingPageController(i.get())),
+ Bind((i) => SearchPageController(i.get())),
+ Bind((i) => ActorPageController(i.get())),
+ Bind((i) => GenrePageController(i.get())),
+ Bind((i) => FilmPageController(i.get())),
+ Bind((i) => AppController()),
+ ];
+
+ @override
+ List get routers => [
+ ModularRouter(
+ Modular.initialRoute,
+ module: HomeModule(),
+ ),
+ ModularRouter(
+ '/filmPage/:id',
+ child: (context, args) => FilmPagePage(
+ id: args.params['id'],
+ ),
+ ),
+ ModularRouter(
+ '/genrePage/:id',
+ child: (context, args) => GenrePagePage(
+ id: args.params['id'],
+ ),
+ ),
+ ModularRouter(
+ '/actorPage/:id',
+ child: (context, args) => ActorPagePage(
+ id: args.params['id'],
+ ),
+ ),
+ ModularRouter(
+ '/searchFilmPage/:name',
+ child: (context, args) => SearchPagePage(name: args.params['name']),
+ ),
+ ModularRouter(
+ '/trendingFilms',
+ child: (context, args) => TrendingPagePage(),
+ ),
+ ModularRouter(
+ '/popularFilms',
+ child: (context, args) => PopularPagePage(),
+ ),
+ ModularRouter(
+ '/topRatedFilms',
+ child: (context, args) => TopRatedPagePage(),
+ ),
+ ];
+
+ @override
+ Widget get bootstrap => AppWidget(
+ controller: to.get(),
+ );
+
+ static Inject get to => Inject.of();
+}
diff --git a/lib/app/app_widget.dart b/lib/app/app_widget.dart
new file mode 100644
index 0000000..909085f
--- /dev/null
+++ b/lib/app/app_widget.dart
@@ -0,0 +1,32 @@
+import 'package:bot_toast/bot_toast.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+
+class AppWidget extends StatelessWidget {
+ final AppController controller;
+
+ const AppWidget({Key key, this.controller}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return Observer(builder: (_) {
+ if (controller.themeType != null) {
+ return MaterialApp(
+ builder: BotToastInit(),
+ navigatorKey: Modular.navigatorKey,
+ title: 'YShare',
+ debugShowCheckedModeBanner: false,
+ theme: controller.themeType,
+ initialRoute: '/',
+ onGenerateRoute: Modular.generateRoute,
+ );
+ } else {
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ }
+ });
+ }
+}
diff --git a/lib/app/modules/actor_page/actor_page_controller.dart b/lib/app/modules/actor_page/actor_page_controller.dart
new file mode 100644
index 0000000..f4b534d
--- /dev/null
+++ b/lib/app/modules/actor_page/actor_page_controller.dart
@@ -0,0 +1,12 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:mobx/mobx.dart';
+
+part 'actor_page_controller.g.dart';
+
+class ActorPageController = _ActorPageControllerBase with _$ActorPageController;
+
+abstract class _ActorPageControllerBase with Store {
+ final AppController appController;
+
+ _ActorPageControllerBase(this.appController);
+}
diff --git a/lib/app/modules/actor_page/actor_page_controller.g.dart b/lib/app/modules/actor_page/actor_page_controller.g.dart
new file mode 100644
index 0000000..86cfc00
--- /dev/null
+++ b/lib/app/modules/actor_page/actor_page_controller.g.dart
@@ -0,0 +1,18 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'actor_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$ActorPageController on _ActorPageControllerBase, Store {
+ @override
+ String toString() {
+ return '''
+
+ ''';
+ }
+}
diff --git a/lib/app/modules/actor_page/actor_page_page.dart b/lib/app/modules/actor_page/actor_page_page.dart
new file mode 100644
index 0000000..9f44e8e
--- /dev/null
+++ b/lib/app/modules/actor_page/actor_page_page.dart
@@ -0,0 +1,78 @@
+import 'package:yshare/app/modules/actor_page/widgets/actor_info_widget.dart';
+import 'package:yshare/app/modules/actor_page/widgets/actor_movie_list_widget.dart';
+import 'package:yshare/app/modules/actor_page/widgets/actor_page_app_bar.dart';
+import 'package:yshare/app/modules/actor_page/widgets/actor_participation_widget.dart';
+import 'package:yshare/app/modules/actor_page/widgets/actor_tv_participation_widget.dart';
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'actor_page_controller.dart';
+
+class ActorPagePage extends StatefulWidget {
+ final String title;
+ final dynamic id;
+
+ const ActorPagePage({
+ Key key,
+ this.title = 'ActorPage',
+ this.id,
+ }) : super(key: key);
+
+ @override
+ _ActorPagePageState createState() => _ActorPagePageState();
+}
+
+class _ActorPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: FutureBuilder(
+ future: Api().getActorDetails(widget.id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(child: CircularProgressIndicator());
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is ActorDetails) {
+ return CustomScrollView(
+ slivers: [
+ ActorPageAppBar(
+ controller: controller,
+ actorDetails: snapshot.data,
+ id: widget.id,
+ ),
+ ActorInfoWidget(
+ actorDetails: snapshot.data,
+ ),
+ ActorMovieListWidget(
+ id: snapshot.data.id.toString(), color: Colors.blue[300]),
+ ActorParticipationWidget(
+ id: snapshot.data.id.toString(), color: Colors.teal[300]),
+ ActorTvParticipationWidget(
+ id: snapshot.data.id.toString(),
+ color: Colors.deepOrange,
+ )
+ ],
+ physics: BouncingScrollPhysics(),
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ break;
+ }
+ },
+ ));
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_biography_widget.dart b/lib/app/modules/actor_page/widgets/actor_biography_widget.dart
new file mode 100644
index 0000000..5eab587
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_biography_widget.dart
@@ -0,0 +1,28 @@
+import 'package:yshare/model/actor_details.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class ActorBiographyWidget extends StatelessWidget {
+ final ActorDetails actorDetails;
+
+ const ActorBiographyWidget({Key key, this.actorDetails}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: ExpansionTile(
+ initiallyExpanded: false,
+ childrenPadding: const EdgeInsets.all(10),
+ title: Text('Biography'),
+ children: [
+ Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 10),
+ child: Text(actorDetails.biography,
+ style:
+ TextStyle(fontFamily: GoogleFonts.openSans().fontFamily)),
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_info_widget.dart b/lib/app/modules/actor_page/widgets/actor_info_widget.dart
new file mode 100644
index 0000000..74cdc2b
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_info_widget.dart
@@ -0,0 +1,122 @@
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/model/actor_participation.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:intl/intl.dart';
+
+class ActorInfoWidget extends StatelessWidget {
+ final ActorDetails actorDetails;
+
+ const ActorInfoWidget({Key key, this.actorDetails}) : super(key: key);
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Column(
+ children: [
+ Text(
+ actorDetails.name,
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 36,
+ fontWeight: FontWeight.bold),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Text(
+ 'participations',
+ style: TextStyle(
+ color: Theme.of(context)
+ .textTheme
+ .bodyText1
+ .color
+ .withOpacity(0.6),
+ fontSize: 12,
+ fontWeight: FontWeight.w200,
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ ),
+ FutureBuilder(
+ future: Api()
+ .getActorParticipation(actorDetails.id.toString()),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(child: CircularProgressIndicator());
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is ActorParticipation) {
+ return Text(
+ snapshot.data.cast.length.toString(),
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontFamily:
+ GoogleFonts.poppins().fontFamily),
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ })
+ ],
+ ),
+ Column(children: [
+ Text(
+ 'birthday',
+ style: TextStyle(
+ color: Theme.of(context)
+ .textTheme
+ .bodyText1
+ .color
+ .withOpacity(0.6),
+ fontSize: 12,
+ fontWeight: FontWeight.w200,
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ ),
+ Text(
+ DateFormat(DateFormat.ABBR_MONTH_DAY)
+ .format(DateTime.parse(actorDetails.birthday)),
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ )
+ ]),
+ Column(
+ children: [
+ Text(
+ 'popularity',
+ style: TextStyle(
+ color: Theme.of(context)
+ .textTheme
+ .bodyText1
+ .color
+ .withOpacity(0.6),
+ fontSize: 12,
+ fontWeight: FontWeight.w200,
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ ),
+ Text(
+ actorDetails.popularity.toString(),
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ )
+ ],
+ )
+ ],
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_movie_list_widget.dart b/lib/app/modules/actor_page/widgets/actor_movie_list_widget.dart
new file mode 100644
index 0000000..e0d3476
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_movie_list_widget.dart
@@ -0,0 +1,73 @@
+import 'package:yshare/components/card_film.dart';
+import 'package:yshare/model/actor_participation.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class ActorMovieListWidget extends StatelessWidget {
+ final String id;
+ final Color color;
+
+ const ActorMovieListWidget({Key key, @required this.id, @required this.color})
+ : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder(
+ future: Api().getActorParticipation(id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Container(
+ child: Center(child: CircularProgressIndicator()),
+ );
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is ActorParticipation) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Container(
+ padding:
+ EdgeInsets.symmetric(vertical: 20, horizontal: 20),
+ child: Text(
+ 'Movies',
+ style: TextStyle(
+ fontSize: 16,
+ fontWeight: FontWeight.bold,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ ),
+ ),
+ ),
+ Container(
+ height: 300,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ physics: BouncingScrollPhysics(),
+ itemCount: snapshot.data.cast.length,
+ itemBuilder: (context, index) {
+ return CardFilm(film: snapshot.data.cast[index]);
+ }),
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_page_app_bar.dart b/lib/app/modules/actor_page/widgets/actor_page_app_bar.dart
new file mode 100644
index 0000000..caf6ca6
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_page_app_bar.dart
@@ -0,0 +1,117 @@
+import 'package:bot_toast/bot_toast.dart';
+import 'package:yshare/app/modules/actor_page/actor_page_controller.dart';
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+
+class ActorPageAppBar extends StatelessWidget {
+ final ActorPageController controller;
+ final dynamic id;
+ final ActorDetails actorDetails;
+
+ const ActorPageAppBar({
+ Key key,
+ @required this.controller,
+ @required this.id,
+ @required this.actorDetails,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ final width = MediaQuery.of(context).size.width;
+ return SliverAppBar(
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.subscribedActors
+ .contains(int.parse(id))
+ ? Icon(
+ EvaIcons.star,
+ color: Colors.amber[800],
+ )
+ : Icon(
+ EvaIcons.starOutline,
+ color: Colors.amber[800],
+ ),
+ onPressed: () {
+ controller.appController.addActorInFavourites(int.parse(id));
+ controller.appController.subscribedActors
+ .contains(int.parse(id))
+ ? BotToast.showNotification(
+ title: (cancelFunc) => Wrap(
+ direction: Axis.horizontal,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Icon(
+ EvaIcons.heart,
+ color: Colors.red,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ '${actorDetails.name} added in favourites !'),
+ ),
+ ],
+ ),
+ )
+ : BotToast.showNotification(
+ title: (cancelFunc) => Wrap(
+ direction: Axis.horizontal,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Icon(
+ EvaIcons.heartOutline,
+ color: Colors.red,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ '${actorDetails.name} removed from favourites !'),
+ ),
+ ],
+ ),
+ );
+ },
+ );
+ },
+ ),
+ Observer(builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(EvaIcons.sun)
+ : Icon(EvaIcons.moon),
+ onPressed: () => controller.appController.changeTheme());
+ })
+ ],
+ backgroundColor: Colors.transparent,
+ iconTheme: IconTheme.of(context),
+ expandedHeight: 400,
+ pinned: true,
+ brightness: ThemeData().brightness,
+ flexibleSpace: Row(
+ children: [
+ Container(
+ width: width * 0.2,
+ ),
+ Container(
+ child: ClipRRect(
+ borderRadius: BorderRadius.only(bottomLeft: Radius.circular(120)),
+ child: Image.network(
+ IMAGE_BASE_URL + actorDetails.profilePath,
+ fit: BoxFit.fitWidth,
+ ),
+ ),
+ width: width * 0.8,
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_participation_widget.dart b/lib/app/modules/actor_page/widgets/actor_participation_widget.dart
new file mode 100644
index 0000000..d8562ff
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_participation_widget.dart
@@ -0,0 +1,76 @@
+import 'package:yshare/components/card_film.dart';
+import 'package:yshare/model/actor_participation.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class ActorParticipationWidget extends StatelessWidget {
+ final String id;
+ final Color color;
+
+ const ActorParticipationWidget({
+ Key key,
+ @required this.id,
+ @required this.color,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder(
+ future: Api().getActorParticipation(id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Center(child: Text('Have internet connection'));
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Container();
+ break;
+
+ case ConnectionState.done:
+ if (snapshot.data is ActorParticipation) {
+ if (snapshot.data.crew.isNotEmpty) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text('Participations',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 16,
+ fontWeight: FontWeight.bold)),
+ ),
+ Container(
+ height: 300,
+ decoration: BoxDecoration(
+ borderRadius:
+ BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ physics: BouncingScrollPhysics(),
+ itemCount: snapshot.data.crew.length,
+ itemBuilder: (context, index) {
+ return CardFilm(
+ film: snapshot.data.crew[index]);
+ }),
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ } else {
+ return Center(child: Text('Have internet connection'));
+ }
+ break;
+ default:
+ return Center(child: Text('Have internet connection'));
+ }
+ }),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/actor_tv_participation_widget.dart b/lib/app/modules/actor_page/widgets/actor_tv_participation_widget.dart
new file mode 100644
index 0000000..8348b23
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/actor_tv_participation_widget.dart
@@ -0,0 +1,75 @@
+import 'package:yshare/app/modules/actor_page/widgets/card_tv_widget.dart';
+import 'package:yshare/model/tv_participation.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class ActorTvParticipationWidget extends StatelessWidget {
+ final String id;
+ final Color color;
+
+ const ActorTvParticipationWidget({
+ Key key,
+ this.id,
+ this.color,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder>(
+ future: Api().getPersonTvParticipations(id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Center(child: Text('none'));
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Container();
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is List) {
+ if (snapshot.data.isNotEmpty) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text('Tv Participations',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 16,
+ fontWeight: FontWeight.bold)),
+ ),
+ Container(
+ height: 300,
+ decoration: BoxDecoration(
+ borderRadius:
+ BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ scrollDirection: Axis.horizontal,
+ physics: BouncingScrollPhysics(),
+ itemCount: snapshot.data.length,
+ itemBuilder: (context, index) {
+ return CardTvWidget(
+ tvParticipation: snapshot.data[index]);
+ }),
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ }),
+ );
+ }
+}
diff --git a/lib/app/modules/actor_page/widgets/card_tv_widget.dart b/lib/app/modules/actor_page/widgets/card_tv_widget.dart
new file mode 100644
index 0000000..3d33cd0
--- /dev/null
+++ b/lib/app/modules/actor_page/widgets/card_tv_widget.dart
@@ -0,0 +1,79 @@
+import 'package:bot_toast/bot_toast.dart';
+import 'package:yshare/model/tv_participation.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CardTvWidget extends StatelessWidget {
+ const CardTvWidget({
+ Key key,
+ @required this.tvParticipation,
+ }) : super(key: key);
+
+ final TvParticipation tvParticipation;
+
+ @override
+ Widget build(BuildContext context) {
+ if (tvParticipation.posterPath == null) {
+ return Container();
+ }
+ return Container(
+ margin: const EdgeInsets.all(4),
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ InkWell(
+ onTap: () => BotToast.showNotification(
+ title: (cancelFunc) => Text('not implemented yet !'),
+ ),
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${tvParticipation.posterPath}',
+ fit: BoxFit.cover,
+ height: 160,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${tvParticipation.name}',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ EvaIcons.star,
+ color: Colors.yellow.shade800,
+ size: 14,
+ ),
+ Text(
+ '${tvParticipation.voteAverage.toStringAsFixed(2)}/10',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily, fontSize: 12),
+ )
+ ],
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/film_page_controller.dart b/lib/app/modules/film_page/film_page_controller.dart
new file mode 100644
index 0000000..ee702fc
--- /dev/null
+++ b/lib/app/modules/film_page/film_page_controller.dart
@@ -0,0 +1,12 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:mobx/mobx.dart';
+
+part 'film_page_controller.g.dart';
+
+class FilmPageController = _FilmPageControllerBase with _$FilmPageController;
+
+abstract class _FilmPageControllerBase with Store {
+ _FilmPageControllerBase(this.appController);
+
+ final AppController appController;
+}
diff --git a/lib/app/modules/film_page/film_page_controller.g.dart b/lib/app/modules/film_page/film_page_controller.g.dart
new file mode 100644
index 0000000..1ccbc5a
--- /dev/null
+++ b/lib/app/modules/film_page/film_page_controller.g.dart
@@ -0,0 +1,18 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'film_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$FilmPageController on _FilmPageControllerBase, Store {
+ @override
+ String toString() {
+ return '''
+
+ ''';
+ }
+}
diff --git a/lib/app/modules/film_page/film_page_page.dart b/lib/app/modules/film_page/film_page_page.dart
new file mode 100644
index 0000000..550de2c
--- /dev/null
+++ b/lib/app/modules/film_page/film_page_page.dart
@@ -0,0 +1,89 @@
+import 'package:yshare/app/modules/film_page/widgets/film_info.dart';
+import 'package:yshare/app/modules/film_page/widgets/film_overview_widget.dart';
+import 'package:yshare/app/modules/film_page/widgets/film_page_app_bar.dart';
+import 'package:yshare/app/modules/film_page/widgets/film_page_crew_list.dart';
+import 'package:yshare/app/modules/film_page/widgets/film_recommendation_list.dart';
+import 'package:yshare/app/modules/film_page/widgets/genres_chip_list.dart';
+import 'package:yshare/components/cast_horizontal_list.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+
+import 'film_page_controller.dart';
+
+class FilmPagePage extends StatefulWidget {
+ final String title;
+ final String id;
+
+ FilmPagePage({
+ Key key,
+ @required this.id,
+ this.title = 'FilmPage',
+ }) : super(key: key);
+ @override
+ _FilmPagePageState createState() => _FilmPagePageState();
+}
+
+class _FilmPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+
+ @override
+ void initState() {
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: FutureBuilder(
+ future: Api().getFilmById(widget.id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Center(
+ child: Text('Without Internet access'),
+ );
+ break;
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+ case ConnectionState.active:
+ case ConnectionState.done:
+ if (snapshot.data is Film) {
+ return CustomScrollView(
+ slivers: [
+ FilmPageAppBar(
+ controller: controller,
+ film: snapshot.data,
+ ),
+ FilmInfo(film: snapshot.data),
+ GenresChipList(film: snapshot.data),
+ FilmOverviewWidget(film: snapshot.data),
+ CastHorizontalList(film: snapshot.data),
+ FilmPageCrewList(
+ id: snapshot.data.id.toString(),
+ ),
+ FilmRecommendationList(
+ id: widget.id,
+ color: Colors.green[800],
+ ),
+ ],
+ );
+ } else {
+ return Center(
+ child: Text('Something wrong happened'),
+ );
+ }
+ break;
+ default:
+ return Center(
+ child: Text('Something wrong happened'),
+ );
+ }
+ }));
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/film_info.dart b/lib/app/modules/film_page/widgets/film_info.dart
new file mode 100644
index 0000000..4858770
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/film_info.dart
@@ -0,0 +1,80 @@
+import 'package:yshare/model/film.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:intl/intl.dart';
+
+class FilmInfo extends StatelessWidget {
+ const FilmInfo({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Column(
+ children: [
+ Container(
+ padding: const EdgeInsets.all(10),
+ child: Center(
+ child: Text(film.tagline,
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 14,
+ fontWeight: FontWeight.bold)),
+ )),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ EvaIcons.star,
+ color: Colors.yellow[800],
+ size: 14,
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ '${film.voteAverage}/10',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ fontSize: 16),
+ ),
+ ),
+ Text(
+ 'IMDb',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 12),
+ )
+ ],
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ '${Duration(minutes: film.runtime).inHours.toString()}hr ${Duration(minutes: film.runtime).inMinutes.remainder(60)} Minutes',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 12,
+ fontWeight: FontWeight.w200),
+ ),
+ ),
+ Text(
+ '${DateFormat(DateFormat.MONTH).format(DateTime.parse(film.releaseDate))} ${DateFormat(DateFormat.YEAR).format(DateTime.parse(film.releaseDate))}',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily, fontSize: 12),
+ )
+ ],
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/film_overview_widget.dart b/lib/app/modules/film_page/widgets/film_overview_widget.dart
new file mode 100644
index 0000000..56967d2
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/film_overview_widget.dart
@@ -0,0 +1,26 @@
+import 'package:yshare/model/film.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class FilmOverviewWidget extends StatelessWidget {
+ final Film film;
+
+ const FilmOverviewWidget({
+ Key key,
+ this.film,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text(
+ film.overview,
+ textAlign: TextAlign.justify,
+ style: TextStyle(fontFamily: GoogleFonts.poppins().fontFamily),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/film_page_app_bar.dart b/lib/app/modules/film_page/widgets/film_page_app_bar.dart
new file mode 100644
index 0000000..870e6f0
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/film_page_app_bar.dart
@@ -0,0 +1,117 @@
+import 'package:bot_toast/bot_toast.dart';
+import 'package:yshare/app/modules/film_page/film_page_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+
+class FilmPageAppBar extends StatelessWidget {
+ final FilmPageController controller;
+ final Film film;
+
+ FilmPageAppBar({
+ @required this.controller,
+ @required this.film,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final width = MediaQuery.of(context).size.width;
+ return SliverAppBar(
+ backgroundColor: Colors.transparent,
+ iconTheme: IconTheme.of(context),
+ expandedHeight: 400,
+ pinned: true,
+ brightness: ThemeData().brightness,
+ actions: [
+ Observer(
+ builder: (context) => IconButton(
+ icon: controller.appController.favouriteFilms.contains(film.id)
+ ? Icon(
+ EvaIcons.star,
+ color: Colors.amber[800],
+ )
+ : Icon(
+ EvaIcons.starOutline,
+ color: Colors.amber[800],
+ ),
+ onPressed: () {
+ controller.appController.addFilmIntoFavourites(film.id);
+
+ controller.appController.favouriteFilms.contains(film.id)
+ ? BotToast.showNotification(
+ title: (cancelFunc) => Wrap(
+ direction: Axis.horizontal,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Icon(
+ EvaIcons.heart,
+ color: Colors.red,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child:
+ Text('${film.title} added in favourites !'),
+ ),
+ ],
+ ),
+ )
+ : BotToast.showNotification(
+ title: (cancelFunc) => Wrap(
+ direction: Axis.horizontal,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Icon(
+ EvaIcons.heartOutline,
+ color: Colors.red,
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: Text(
+ '${film.title} removed from favourites !'),
+ ),
+ ],
+ ),
+ );
+ },
+ ),
+ ),
+ IconButton(
+ icon: controller.appController.isDark
+ ? Icon(EvaIcons.sun)
+ : Icon(
+ EvaIcons.moon,
+ color: Colors.black,
+ ),
+ onPressed: () {
+ controller.appController.changeTheme();
+ },
+ )
+ ],
+ flexibleSpace: Row(
+ children: [
+ Container(
+ width: width * 0.2,
+ ),
+ Container(
+ child: ClipRRect(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(120)),
+ child: film.posterPath == null
+ ? Container()
+ : Image.network(
+ IMAGE_BASE_URL + film.posterPath,
+ fit: BoxFit.fitWidth,
+ ),
+ ),
+ width: width * 0.8,
+ ),
+ ],
+ ));
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/film_page_crew_list.dart b/lib/app/modules/film_page/widgets/film_page_crew_list.dart
new file mode 100644
index 0000000..13ddd00
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/film_page_crew_list.dart
@@ -0,0 +1,74 @@
+import 'package:yshare/app/modules/film_page/widgets/person_crew_card.dart';
+import 'package:yshare/model/film_credit.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class FilmPageCrewList extends StatelessWidget {
+ final String id;
+ const FilmPageCrewList({
+ Key key,
+ @required this.id,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder(
+ future: Api().getFilmCredits(id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Center(
+ child: Text('do you have internet access ?'),
+ );
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is FilmCredit) {
+ return Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 12.0, top: 10, bottom: 12),
+ child: Text('Crew',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 18)),
+ ),
+ Container(
+ height: 140,
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: snapshot.data.crew.length,
+ itemBuilder: (context, index) {
+ return PersonCrewCard(
+ crew: snapshot.data.crew[index]);
+ },
+ ),
+ ),
+ ],
+ );
+ } else {
+ return Center(
+ child: Text('something wrong happenmed'),
+ );
+ }
+ break;
+ default:
+ return Center(
+ child: Text('something wrong happenmed'),
+ );
+ }
+ }),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/film_recommendation_list.dart b/lib/app/modules/film_page/widgets/film_recommendation_list.dart
new file mode 100644
index 0000000..099da33
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/film_recommendation_list.dart
@@ -0,0 +1,82 @@
+import 'package:yshare/components/card_film.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class FilmRecommendationList extends StatelessWidget {
+ const FilmRecommendationList({
+ Key key,
+ @required this.id,
+ this.color,
+ }) : super(key: key);
+
+ final String id;
+ final Color color;
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder>(
+ future: Api().getRecommendations(id),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Center(
+ child: Text('do you have internet access?'),
+ );
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+
+ case ConnectionState.done:
+ if (snapshot.data is List) {
+ if (snapshot.data.isNotEmpty) {
+ return Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text('Recommendations',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 24,
+ fontWeight: FontWeight.bold)),
+ ),
+ Container(
+ height: 250,
+ decoration: BoxDecoration(
+ borderRadius:
+ BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: snapshot.data.length,
+ itemBuilder: (context, index) {
+ return CardFilm(film: snapshot.data[index]);
+ })),
+ ],
+ );
+ } else {
+ return Container();
+ }
+ } else {
+ return Center(
+ child: Text('something wrong happened'),
+ );
+ }
+ break;
+ default:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ }
+ }),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/genres_chip_list.dart b/lib/app/modules/film_page/widgets/genres_chip_list.dart
new file mode 100644
index 0000000..6c85a71
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/genres_chip_list.dart
@@ -0,0 +1,44 @@
+import 'package:yshare/model/film.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class GenresChipList extends StatelessWidget {
+ const GenresChipList({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Container(
+ padding: const EdgeInsets.all(10),
+ child: Wrap(
+ alignment: WrapAlignment.center,
+ children: film.genreIds
+ .map((e) => InkWell(
+ onTap: () => Modular.to.pushNamed('/genrePage/${e.id}'),
+ child: Card(
+ elevation: 10,
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ child: Container(
+ padding: const EdgeInsets.symmetric(
+ horizontal: 16, vertical: 10),
+ child: Text(
+ e.name,
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily),
+ ),
+ ),
+ ),
+ ))
+ .toList(),
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/person_cast_card.dart b/lib/app/modules/film_page/widgets/person_cast_card.dart
new file mode 100644
index 0000000..a3e2318
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/person_cast_card.dart
@@ -0,0 +1,60 @@
+import 'package:yshare/model/cast.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class PersonCastCard extends StatelessWidget {
+ const PersonCastCard({
+ Key key,
+ @required this.cast,
+ }) : super(key: key);
+
+ final Cast cast;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ InkWell(
+ onTap: () => Modular.to.pushNamed(
+ '/actorPage/${cast.id}',
+ ),
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${cast.profilePath}',
+ fit: BoxFit.cover,
+ height: 100,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${cast.name}',
+ style: TextStyle(
+ fontSize: 10,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/film_page/widgets/person_crew_card.dart b/lib/app/modules/film_page/widgets/person_crew_card.dart
new file mode 100644
index 0000000..bca4433
--- /dev/null
+++ b/lib/app/modules/film_page/widgets/person_crew_card.dart
@@ -0,0 +1,63 @@
+import 'package:yshare/model/crew.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class PersonCrewCard extends StatelessWidget {
+ const PersonCrewCard({
+ Key key,
+ @required this.crew,
+ }) : super(key: key);
+
+ final Crew crew;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ InkWell(
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: crew.profilePath != null
+ ? Image.network(
+ '$IMAGE_BASE_URL${crew.profilePath}',
+ fit: BoxFit.cover,
+ height: 100,
+ )
+ : Image.asset(
+ crew.gender == 2
+ ? 'assets/images/male_placeholder.jpg'
+ : 'assets/images/female_placeholder.jpg',
+ fit: BoxFit.cover,
+ height: 100,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${crew.name}',
+ style: TextStyle(
+ fontSize: 10,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ ],
+ ));
+ }
+}
diff --git a/lib/app/modules/genre_page/genre_page_controller.dart b/lib/app/modules/genre_page/genre_page_controller.dart
new file mode 100644
index 0000000..66c06ff
--- /dev/null
+++ b/lib/app/modules/genre_page/genre_page_controller.dart
@@ -0,0 +1,45 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:mobx/mobx.dart';
+
+part 'genre_page_controller.g.dart';
+
+class GenrePageController = _GenrePageControllerBase with _$GenrePageController;
+
+abstract class _GenrePageControllerBase with Store {
+ final AppController appController;
+
+ _GenrePageControllerBase(this.appController);
+
+ @observable
+ ObservableList films = ObservableList();
+
+ final Api api = Api();
+
+ @observable
+ int actualPage = 1;
+
+ @observable
+ String genreId;
+
+ @observable
+ String genreName;
+
+ @action
+ void setActualPage(actualPage) => this.actualPage = actualPage;
+
+ @action
+ void setGenreId(genreId) => this.genreId = genreId;
+
+ @action
+ void setGenreName(genreName) => this.genreName = genreName;
+
+ @action
+ Future fetchFilmsByGenre() async {
+ var response = await api.getFilmByGenre(genreId, actualPage);
+ for (var film in response) {
+ films.add(film);
+ }
+ }
+}
diff --git a/lib/app/modules/genre_page/genre_page_controller.g.dart b/lib/app/modules/genre_page/genre_page_controller.g.dart
new file mode 100644
index 0000000..974b813
--- /dev/null
+++ b/lib/app/modules/genre_page/genre_page_controller.g.dart
@@ -0,0 +1,125 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'genre_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$GenrePageController on _GenrePageControllerBase, Store {
+ final _$filmsAtom = Atom(name: '_GenrePageControllerBase.films');
+
+ @override
+ ObservableList get films {
+ _$filmsAtom.reportRead();
+ return super.films;
+ }
+
+ @override
+ set films(ObservableList value) {
+ _$filmsAtom.reportWrite(value, super.films, () {
+ super.films = value;
+ });
+ }
+
+ final _$actualPageAtom = Atom(name: '_GenrePageControllerBase.actualPage');
+
+ @override
+ int get actualPage {
+ _$actualPageAtom.reportRead();
+ return super.actualPage;
+ }
+
+ @override
+ set actualPage(int value) {
+ _$actualPageAtom.reportWrite(value, super.actualPage, () {
+ super.actualPage = value;
+ });
+ }
+
+ final _$genreIdAtom = Atom(name: '_GenrePageControllerBase.genreId');
+
+ @override
+ String get genreId {
+ _$genreIdAtom.reportRead();
+ return super.genreId;
+ }
+
+ @override
+ set genreId(String value) {
+ _$genreIdAtom.reportWrite(value, super.genreId, () {
+ super.genreId = value;
+ });
+ }
+
+ final _$genreNameAtom = Atom(name: '_GenrePageControllerBase.genreName');
+
+ @override
+ String get genreName {
+ _$genreNameAtom.reportRead();
+ return super.genreName;
+ }
+
+ @override
+ set genreName(String value) {
+ _$genreNameAtom.reportWrite(value, super.genreName, () {
+ super.genreName = value;
+ });
+ }
+
+ final _$fetchFilmsByGenreAsyncAction =
+ AsyncAction('_GenrePageControllerBase.fetchFilmsByGenre');
+
+ @override
+ Future fetchFilmsByGenre() {
+ return _$fetchFilmsByGenreAsyncAction.run(() => super.fetchFilmsByGenre());
+ }
+
+ final _$_GenrePageControllerBaseActionController =
+ ActionController(name: '_GenrePageControllerBase');
+
+ @override
+ void setActualPage(dynamic actualPage) {
+ final _$actionInfo = _$_GenrePageControllerBaseActionController.startAction(
+ name: '_GenrePageControllerBase.setActualPage');
+ try {
+ return super.setActualPage(actualPage);
+ } finally {
+ _$_GenrePageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ void setGenreId(dynamic genreId) {
+ final _$actionInfo = _$_GenrePageControllerBaseActionController.startAction(
+ name: '_GenrePageControllerBase.setGenreId');
+ try {
+ return super.setGenreId(genreId);
+ } finally {
+ _$_GenrePageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ void setGenreName(dynamic genreName) {
+ final _$actionInfo = _$_GenrePageControllerBaseActionController.startAction(
+ name: '_GenrePageControllerBase.setGenreName');
+ try {
+ return super.setGenreName(genreName);
+ } finally {
+ _$_GenrePageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+films: ${films},
+actualPage: ${actualPage},
+genreId: ${genreId},
+genreName: ${genreName}
+ ''';
+ }
+}
diff --git a/lib/app/modules/genre_page/genre_page_page.dart b/lib/app/modules/genre_page/genre_page_page.dart
new file mode 100644
index 0000000..3590924
--- /dev/null
+++ b/lib/app/modules/genre_page/genre_page_page.dart
@@ -0,0 +1,118 @@
+import 'package:yshare/components/compact_card_film.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import 'genre_page_controller.dart';
+
+class GenrePagePage extends StatefulWidget {
+ final String title;
+ final String id;
+ const GenrePagePage({
+ Key key,
+ this.title = 'GenrePage',
+ @required this.id,
+ }) : super(key: key);
+
+ @override
+ _GenrePagePageState createState() => _GenrePagePageState();
+}
+
+class _GenrePagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+ final ScrollController _scrollController = ScrollController();
+
+ void _scrollListener() {
+ if (_scrollController.offset >=
+ _scrollController.position.maxScrollExtent &&
+ !_scrollController.position.outOfRange) {
+ controller.setActualPage(controller.actualPage + 1);
+ controller.fetchFilmsByGenre();
+ }
+ }
+
+ @override
+ void initState() {
+ var genreName = GENRES
+ .firstWhere((element) => element['id'] == int.parse(widget.id))['name'];
+
+ controller.setGenreName(genreName);
+ controller.setGenreId(widget.id);
+
+ controller.fetchFilmsByGenre();
+ _scrollController.addListener(_scrollListener);
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Observer(
+ builder: (_) => CustomScrollView(
+ controller: _scrollController,
+ slivers: [
+ SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ floating: false,
+ pinned: true,
+ snap: false,
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text(controller.genreName,
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(50))),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(
+ EvaIcons.sun,
+ color: Colors.white,
+ )
+ : Icon(EvaIcons.moon, color: Colors.white),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ ),
+ SliverToBoxAdapter(
+ child: GridView.builder(
+ shrinkWrap: true,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ childAspectRatio: 0.6,
+ ),
+ itemCount: controller.films.length,
+ physics: BouncingScrollPhysics(),
+ itemBuilder: (context, index) =>
+ CompactCardFilm(film: controller.films[index]),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _scrollController.removeListener(_scrollListener);
+ _scrollController.dispose();
+ super.dispose();
+ }
+}
diff --git a/lib/app/modules/home/home_controller.dart b/lib/app/modules/home/home_controller.dart
new file mode 100644
index 0000000..aa43f7a
--- /dev/null
+++ b/lib/app/modules/home/home_controller.dart
@@ -0,0 +1,12 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:mobx/mobx.dart';
+
+part 'home_controller.g.dart';
+
+class HomeController = _HomeControllerBase with _$HomeController;
+
+abstract class _HomeControllerBase with Store {
+ final AppController appController;
+
+ _HomeControllerBase(this.appController);
+}
diff --git a/lib/app/modules/home/home_controller.g.dart b/lib/app/modules/home/home_controller.g.dart
new file mode 100644
index 0000000..bfe4b41
--- /dev/null
+++ b/lib/app/modules/home/home_controller.g.dart
@@ -0,0 +1,18 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'home_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$HomeController on _HomeControllerBase, Store {
+ @override
+ String toString() {
+ return '''
+
+ ''';
+ }
+}
diff --git a/lib/app/modules/home/home_module.dart b/lib/app/modules/home/home_module.dart
new file mode 100644
index 0000000..a70092b
--- /dev/null
+++ b/lib/app/modules/home/home_module.dart
@@ -0,0 +1,19 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+
+import 'home_controller.dart';
+import 'home_page.dart';
+
+class HomeModule extends ChildModule {
+ @override
+ List get binds => [
+ Bind((i) => HomeController(i.get())),
+ ];
+
+ @override
+ List get routers => [
+ ModularRouter(Modular.initialRoute, child: (_, args) => HomePage()),
+ ];
+
+ static Inject get to => Inject.of();
+}
diff --git a/lib/app/modules/home/home_page.dart b/lib/app/modules/home/home_page.dart
new file mode 100644
index 0000000..5df0c84
--- /dev/null
+++ b/lib/app/modules/home/home_page.dart
@@ -0,0 +1,68 @@
+import 'package:yshare/app/modules/home/widgets/chips_lists.dart';
+import 'package:yshare/app/modules/home/widgets/favourite_actor_list.dart';
+import 'package:yshare/app/modules/home/widgets/favourite_film_list.dart';
+import 'package:yshare/app/modules/home/widgets/form_search_field.dart';
+import 'package:yshare/app/modules/home/widgets/home_app_bar.dart';
+import 'package:yshare/app/modules/home/widgets/popular_list.dart';
+import 'package:yshare/app/modules/home/widgets/top_rated_list.dart';
+import 'package:yshare/app/modules/home/widgets/trending_films_list.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+
+import 'home_controller.dart';
+
+class HomePage extends StatefulWidget {
+ final String title;
+
+ const HomePage({Key key, this.title = 'Home'}) : super(key: key);
+
+ @override
+ _HomePageState createState() => _HomePageState();
+}
+
+class _HomePageState extends ModularState {
+ //use 'controller' variable to access controller
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ drawer: Drawer(),
+ body: Observer(
+ builder: (_) {
+ return Stack(children: [
+ CustomScrollView(
+ slivers: [
+ HomeAppBar(),
+ FormSearchField(),
+ TrendingFilmList(
+ color: Colors.purple[300],
+ ),
+ FavouriteFilmList(
+ color: Colors.green[800],
+ filmsId: controller.appController.favouriteFilms),
+ FavouriteActorList(
+ actorsId: controller.appController.subscribedActors,
+ color: Colors.blue[400],
+ ),
+ ChipList(),
+ PopularList(
+ color: Colors.orange,
+ ),
+ TopRatedList(
+ color: Colors.pink[400],
+ ),
+ SliverToBoxAdapter(
+ child: Padding(
+ padding: const EdgeInsets.all(20),
+ ),
+ )
+ ],
+ physics: BouncingScrollPhysics(),
+ ),
+ ]);
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/card_film_list.dart b/lib/app/modules/home/widgets/card_film_list.dart
new file mode 100644
index 0000000..faeaa4c
--- /dev/null
+++ b/lib/app/modules/home/widgets/card_film_list.dart
@@ -0,0 +1,85 @@
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CardFilmList extends StatelessWidget {
+ final List actors;
+ final Color color;
+
+ const CardFilmList({Key key, @required this.actors, this.color})
+ : super(key: key);
+ @override
+ Widget build(BuildContext context) {
+ return ListView.builder(
+ shrinkWrap: true,
+ itemCount: actors.length,
+ itemBuilder: (context, index) {
+ return FutureBuilder(
+ future: Api().getActorDetails(actors[index].toString()),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return SliverToBoxAdapter(child: Container());
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return SliverToBoxAdapter(child: CircularProgressIndicator());
+ break;
+ case ConnectionState.done:
+ return SliverToBoxAdapter(
+ child: Container(
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+ children: [
+ InkWell(
+ onTap: () => Modular.to.pushNamed(
+ '/actorPage/${snapshot.data.id}',
+ ),
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${snapshot.data.profilePath}',
+ fit: BoxFit.cover,
+ height: 100,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${snapshot.data.name}',
+ style: TextStyle(
+ fontSize: 10,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ break;
+ default:
+ return SliverToBoxAdapter(child: Container());
+ }
+ },
+ );
+ },
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/chips_lists.dart b/lib/app/modules/home/widgets/chips_lists.dart
new file mode 100644
index 0000000..e6cb73c
--- /dev/null
+++ b/lib/app/modules/home/widgets/chips_lists.dart
@@ -0,0 +1,98 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import '../../../../provider/constants.dart';
+
+class ChipList extends StatelessWidget {
+ @override
+ Widget build(BuildContext context) {
+ return SliverList(
+ delegate: SliverChildListDelegate([
+ Padding(
+ padding:
+ const EdgeInsets.only(left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text(
+ 'Genres',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily, fontSize: 20),
+ ),
+ ),
+ Center(
+ child: Container(
+ height: 70,
+ padding: EdgeInsets.symmetric(vertical: 5),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: 6,
+ padding: const EdgeInsets.symmetric(horizontal: 10),
+ itemBuilder: (context, index) => Container(
+ padding: const EdgeInsets.symmetric(horizontal: 5),
+ child: InkWell(
+ onTap: () =>
+ Modular.to.pushNamed('/genrePage/${GENRES[index]['id']}'),
+ child: Chip(
+ elevation: 6,
+ padding: const EdgeInsets.symmetric(
+ horizontal: 20, vertical: 10),
+ label: Text(GENRES[index]['name'],
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily))),
+ ),
+ ),
+ ),
+ ),
+ ),
+ Container(
+ height: 70,
+ padding: EdgeInsets.symmetric(vertical: 5),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: 6,
+ padding: const EdgeInsets.symmetric(horizontal: 10),
+ itemBuilder: (context, index) => Container(
+ padding: const EdgeInsets.symmetric(horizontal: 5),
+ child: InkWell(
+ onTap: () => Modular.to
+ .pushNamed('/genrePage/${GENRES[index + 6]['id']}'),
+ child: Chip(
+ elevation: 6,
+ padding: const EdgeInsets.symmetric(
+ horizontal: 20, vertical: 10),
+ label: Text(GENRES[index + 6]['name'],
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily))),
+ ),
+ ),
+ ),
+ ),
+ Container(
+ height: 70,
+ padding: EdgeInsets.symmetric(vertical: 5),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: 6,
+ padding: const EdgeInsets.symmetric(horizontal: 10),
+ itemBuilder: (context, index) => Container(
+ padding: const EdgeInsets.symmetric(horizontal: 5),
+ child: InkWell(
+ onTap: () => Modular.to
+ .pushNamed('/genrePage/${GENRES[index + 12]['id']}'),
+ child: Chip(
+ elevation: 6,
+ padding: const EdgeInsets.symmetric(
+ horizontal: 20, vertical: 10),
+ label: Text(GENRES[index + 12]['name'],
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily))),
+ ),
+ ),
+ ),
+ ),
+ ]),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/favourite_actor_list.dart b/lib/app/modules/home/widgets/favourite_actor_list.dart
new file mode 100644
index 0000000..e30c863
--- /dev/null
+++ b/lib/app/modules/home/widgets/favourite_actor_list.dart
@@ -0,0 +1,63 @@
+import 'package:yshare/app/modules/home/widgets/person_favourite_card.dart';
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class FavouriteActorList extends StatelessWidget {
+ final Color color;
+ final List actorsId;
+
+ const FavouriteActorList({
+ Key key,
+ @required this.color,
+ @required this.actorsId,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ actorsId.isNotEmpty
+ ? Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text('Favourites Actors',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ )
+ : Container(),
+ Container(
+ height: actorsId.isEmpty ? 0 : 250,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: actorsId.length,
+ itemBuilder: (context, index) {
+ var id = actorsId[index];
+ return FutureBuilder(
+ future: Api().getActorDetails(id.toString()),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ if (snapshot.data.profilePath == null) {
+ return Container();
+ } else {
+ return PersonFavouriteCard(
+ actorDetails: snapshot.data);
+ }
+ } else {
+ return CircularProgressIndicator();
+ }
+ });
+ }),
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/favourite_film_list.dart b/lib/app/modules/home/widgets/favourite_film_list.dart
new file mode 100644
index 0000000..f719b43
--- /dev/null
+++ b/lib/app/modules/home/widgets/favourite_film_list.dart
@@ -0,0 +1,63 @@
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import '../../../../components/card_film.dart';
+
+class FavouriteFilmList extends StatelessWidget {
+ final List filmsId;
+ final Color color;
+ const FavouriteFilmList({
+ Key key,
+ @required this.filmsId,
+ @required this.color,
+ }) : super(key: key);
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Column(
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ filmsId.isNotEmpty
+ ? Padding(
+ padding: const EdgeInsets.all(12.0),
+ child: Text('Favourites Films',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20,
+ )),
+ )
+ : Container(),
+ Container(
+ height: filmsId.isEmpty ? 0 : 250,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.all(Radius.circular(100)),
+ color: color),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: filmsId.length,
+ itemBuilder: (context, index) {
+ var id = filmsId[index];
+ return FutureBuilder(
+ future: Api().getFilmById(id.toString()),
+ builder: (context, snapshot) {
+ if (snapshot.hasData) {
+ if (snapshot.data.posterPath == null) {
+ return Container();
+ } else {
+ return CardFilm(film: snapshot.data);
+ }
+ } else {
+ return CircularProgressIndicator();
+ }
+ });
+ },
+ ),
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/film_horizontal_list.dart b/lib/app/modules/home/widgets/film_horizontal_list.dart
new file mode 100644
index 0000000..ff8ee62
--- /dev/null
+++ b/lib/app/modules/home/widgets/film_horizontal_list.dart
@@ -0,0 +1,34 @@
+import 'package:yshare/components/card_film.dart';
+import 'package:yshare/model/film.dart';
+import 'package:flutter/material.dart';
+
+class FilmHorizontalList extends StatelessWidget {
+ const FilmHorizontalList({
+ Key key,
+ @required this.films,
+ @required this.color,
+ }) : super(key: key);
+
+ final Color color;
+ final List films;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ height: 250,
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.all(
+ Radius.circular(100),
+ ),
+ color: color,
+ ),
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: films.length,
+ itemBuilder: (context, index) {
+ return CardFilm(film: films[index]);
+ }),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/form_search_field.dart b/lib/app/modules/home/widgets/form_search_field.dart
new file mode 100644
index 0000000..7acd153
--- /dev/null
+++ b/lib/app/modules/home/widgets/form_search_field.dart
@@ -0,0 +1,42 @@
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class FormSearchField extends StatelessWidget {
+ final TextEditingController _controller = TextEditingController();
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: Form(
+ child: Padding(
+ padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 20),
+ child: TextFormField(
+ controller: _controller,
+ onFieldSubmitted: (value) =>
+ Modular.to.pushNamed('/searchFilmPage/$value'),
+ style: TextStyle(fontFamily: GoogleFonts.poppins().fontFamily),
+ cursorColor: Colors.grey,
+ decoration: InputDecoration(
+ filled: true,
+ fillColor: Colors.black45,
+ contentPadding: EdgeInsets.all(14),
+ border: OutlineInputBorder(
+ borderSide: BorderSide.none,
+ gapPadding: 12,
+ borderRadius: BorderRadius.circular(20),
+ ),
+ labelText: 'Search movies / tv series',
+ labelStyle: TextStyle(color: Colors.white),
+ floatingLabelBehavior: FloatingLabelBehavior.never,
+ suffixIcon: IconButton(
+ icon: Icon(EvaIcons.search),
+ onPressed: () =>
+ Modular.to.pushNamed('/searchFilmPage/${_controller.text}'),
+ ),
+ ),
+ ),
+ ),
+ ));
+ }
+}
diff --git a/lib/app/modules/home/widgets/home_app_bar.dart b/lib/app/modules/home/widgets/home_app_bar.dart
new file mode 100644
index 0000000..57d8473
--- /dev/null
+++ b/lib/app/modules/home/widgets/home_app_bar.dart
@@ -0,0 +1,49 @@
+import 'package:yshare/app/modules/home/home_controller.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class HomeAppBar extends StatefulWidget {
+ @override
+ _HomeAppBarState createState() => _HomeAppBarState();
+}
+
+class _HomeAppBarState extends ModularState {
+ @override
+ Widget build(BuildContext context) {
+ return SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text('What would you like to watch today ?',
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.only(bottomLeft: Radius.circular(50))),
+ leading: IconButton(
+ icon: Icon(EvaIcons.menu2Outline),
+ onPressed: () {},
+ ),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(EvaIcons.sun)
+ : Icon(EvaIcons.moon),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/person_favourite_card.dart b/lib/app/modules/home/widgets/person_favourite_card.dart
new file mode 100644
index 0000000..7ea854d
--- /dev/null
+++ b/lib/app/modules/home/widgets/person_favourite_card.dart
@@ -0,0 +1,60 @@
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class PersonFavouriteCard extends StatelessWidget {
+ const PersonFavouriteCard({
+ Key key,
+ @required this.actorDetails,
+ }) : super(key: key);
+
+ final ActorDetails actorDetails;
+
+ @override
+ Widget build(BuildContext context) {
+ return Container(
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ InkWell(
+ onTap: () => Modular.to.pushNamed(
+ '/actorPage/${actorDetails.id}',
+ ),
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${actorDetails.profilePath}',
+ fit: BoxFit.cover,
+ height: 150,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.symmetric(vertical: 12.0),
+ child: Text(
+ '${actorDetails.name}',
+ style: TextStyle(
+ fontSize: 12,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/home/widgets/popular_list.dart b/lib/app/modules/home/widgets/popular_list.dart
new file mode 100644
index 0000000..2b44f7e
--- /dev/null
+++ b/lib/app/modules/home/widgets/popular_list.dart
@@ -0,0 +1,77 @@
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import 'film_horizontal_list.dart';
+
+class PopularList extends StatelessWidget {
+ final Color color;
+
+ const PopularList({Key key, @required this.color}) : super(key: key);
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder>(
+ future: Api().getPopular(),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is List) {
+ return Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('Popular',
+ style: TextStyle(
+ fontFamily:
+ GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ InkWell(
+ splashColor: Colors.pink.withOpacity(0.5),
+ onTap: () =>
+ Modular.to.pushNamed('/popularFilms'),
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('See More',
+ style: TextStyle(
+ fontFamily:
+ GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ ),
+ ],
+ ),
+ FilmHorizontalList(
+ films: snapshot.data,
+ color: color,
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ }));
+ }
+}
diff --git a/lib/app/modules/home/widgets/top_rated_list.dart b/lib/app/modules/home/widgets/top_rated_list.dart
new file mode 100644
index 0000000..fd19514
--- /dev/null
+++ b/lib/app/modules/home/widgets/top_rated_list.dart
@@ -0,0 +1,79 @@
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import 'film_horizontal_list.dart';
+
+class TopRatedList extends StatelessWidget {
+ final Color color;
+
+ const TopRatedList({
+ Key key,
+ @required this.color,
+ }) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder>(
+ future: Api().getTopRated(),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is List) {
+ return Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('Top Rated',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ InkWell(
+ splashColor: Colors.pink.withOpacity(0.5),
+ onTap: () => Modular.to.pushNamed('topRatedFilms'),
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('See More',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ ),
+ ],
+ ),
+ FilmHorizontalList(
+ films: snapshot.data,
+ color: color,
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ },
+ ));
+ }
+}
diff --git a/lib/app/modules/home/widgets/trending_films_list.dart b/lib/app/modules/home/widgets/trending_films_list.dart
new file mode 100644
index 0000000..edbadc8
--- /dev/null
+++ b/lib/app/modules/home/widgets/trending_films_list.dart
@@ -0,0 +1,75 @@
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import 'film_horizontal_list.dart';
+
+class TrendingFilmList extends StatelessWidget {
+ final Color color;
+ const TrendingFilmList({Key key, @required this.color}) : super(key: key);
+
+ @override
+ Widget build(BuildContext context) {
+ return SliverToBoxAdapter(
+ child: FutureBuilder>(
+ future: Api().getTrendingFilms(),
+ builder: (context, snapshot) {
+ switch (snapshot.connectionState) {
+ case ConnectionState.none:
+ return Container();
+ break;
+ case ConnectionState.active:
+ case ConnectionState.waiting:
+ return Center(
+ child: CircularProgressIndicator(),
+ );
+ break;
+ case ConnectionState.done:
+ if (snapshot.data is List) {
+ return Column(
+ children: [
+ Row(
+ crossAxisAlignment: CrossAxisAlignment.center,
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('Trending',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ InkWell(
+ splashColor: Colors.pink.withOpacity(0.5),
+ onTap: () => Modular.to.pushNamed('/trendingFilms'),
+ child: Padding(
+ padding: const EdgeInsets.only(
+ left: 20.0, top: 10, right: 20, bottom: 10),
+ child: Text('See More',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 20)),
+ ),
+ ),
+ ],
+ ),
+ FilmHorizontalList(
+ films: snapshot.data,
+ color: color,
+ )
+ ],
+ );
+ } else {
+ return Container();
+ }
+ break;
+ default:
+ return Container();
+ }
+ },
+ ));
+ }
+}
diff --git a/lib/app/modules/popular_page/popular_page_controller.dart b/lib/app/modules/popular_page/popular_page_controller.dart
new file mode 100644
index 0000000..dc0a680
--- /dev/null
+++ b/lib/app/modules/popular_page/popular_page_controller.dart
@@ -0,0 +1,33 @@
+import 'package:mobx/mobx.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+
+part 'popular_page_controller.g.dart';
+
+class PopularPageController = _PopularPageControllerBase
+ with _$PopularPageController;
+
+abstract class _PopularPageControllerBase with Store {
+ final AppController appController;
+ _PopularPageControllerBase(this.appController);
+
+ @observable
+ ObservableList films = ObservableList();
+
+ final Api api = Api();
+
+ @observable
+ int actualPage = 1;
+
+ @action
+ void setActualPage(actualPage) => this.actualPage = actualPage;
+
+ @action
+ Future fetchPopularFilms() async {
+ var response = await api.getPopular(actualPage);
+ for (var film in response) {
+ films.add(film);
+ }
+ }
+}
diff --git a/lib/app/modules/popular_page/popular_page_controller.g.dart b/lib/app/modules/popular_page/popular_page_controller.g.dart
new file mode 100644
index 0000000..5384315
--- /dev/null
+++ b/lib/app/modules/popular_page/popular_page_controller.g.dart
@@ -0,0 +1,71 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'popular_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$PopularPageController on _PopularPageControllerBase, Store {
+ final _$filmsAtom = Atom(name: '_PopularPageControllerBase.films');
+
+ @override
+ ObservableList get films {
+ _$filmsAtom.reportRead();
+ return super.films;
+ }
+
+ @override
+ set films(ObservableList value) {
+ _$filmsAtom.reportWrite(value, super.films, () {
+ super.films = value;
+ });
+ }
+
+ final _$actualPageAtom = Atom(name: '_PopularPageControllerBase.actualPage');
+
+ @override
+ int get actualPage {
+ _$actualPageAtom.reportRead();
+ return super.actualPage;
+ }
+
+ @override
+ set actualPage(int value) {
+ _$actualPageAtom.reportWrite(value, super.actualPage, () {
+ super.actualPage = value;
+ });
+ }
+
+ final _$fetchPopularFilmsAsyncAction =
+ AsyncAction('_PopularPageControllerBase.fetchPopularFilms');
+
+ @override
+ Future fetchPopularFilms() {
+ return _$fetchPopularFilmsAsyncAction.run(() => super.fetchPopularFilms());
+ }
+
+ final _$_PopularPageControllerBaseActionController =
+ ActionController(name: '_PopularPageControllerBase');
+
+ @override
+ void setActualPage(dynamic actualPage) {
+ final _$actionInfo = _$_PopularPageControllerBaseActionController
+ .startAction(name: '_PopularPageControllerBase.setActualPage');
+ try {
+ return super.setActualPage(actualPage);
+ } finally {
+ _$_PopularPageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+films: ${films},
+actualPage: ${actualPage}
+ ''';
+ }
+}
diff --git a/lib/app/modules/popular_page/popular_page_page.dart b/lib/app/modules/popular_page/popular_page_page.dart
new file mode 100644
index 0000000..8f06827
--- /dev/null
+++ b/lib/app/modules/popular_page/popular_page_page.dart
@@ -0,0 +1,108 @@
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/components/compact_card_film.dart';
+import 'popular_page_controller.dart';
+
+class PopularPagePage extends StatefulWidget {
+ final AppController controller;
+ final String title;
+ const PopularPagePage({Key key, this.title = 'PopularPage', this.controller})
+ : super(key: key);
+
+ @override
+ _PopularPagePageState createState() => _PopularPagePageState();
+}
+
+class _PopularPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+ final ScrollController _scrollController = ScrollController();
+
+ void _scrollListener() {
+ if (_scrollController.offset >=
+ _scrollController.position.maxScrollExtent &&
+ !_scrollController.position.outOfRange) {
+ controller.setActualPage(controller.actualPage + 1);
+ controller.fetchPopularFilms();
+ }
+ }
+
+ @override
+ void initState() {
+ controller.fetchPopularFilms();
+ _scrollController.addListener(_scrollListener);
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Observer(
+ builder: (_) => CustomScrollView(
+ controller: _scrollController,
+ slivers: [
+ SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ floating: false,
+ pinned: true,
+ snap: false,
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text('Popular',
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(50))),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(
+ EvaIcons.sun,
+ color: Colors.white,
+ )
+ : Icon(EvaIcons.moon, color: Colors.white),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ ),
+ SliverToBoxAdapter(
+ child: GridView.builder(
+ shrinkWrap: true,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ childAspectRatio: 0.6,
+ ),
+ itemCount: controller.films.length,
+ physics: BouncingScrollPhysics(),
+ itemBuilder: (context, index) =>
+ CompactCardFilm(film: controller.films[index]),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _scrollController.removeListener(_scrollListener);
+ _scrollController.dispose();
+ super.dispose();
+ }
+}
diff --git a/lib/app/modules/search_page/search_page_controller.dart b/lib/app/modules/search_page/search_page_controller.dart
new file mode 100644
index 0000000..26ec558
--- /dev/null
+++ b/lib/app/modules/search_page/search_page_controller.dart
@@ -0,0 +1,40 @@
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:mobx/mobx.dart';
+
+part 'search_page_controller.g.dart';
+
+class SearchPageController = _SearchPageControllerBase
+ with _$SearchPageController;
+
+abstract class _SearchPageControllerBase with Store {
+ final AppController appController;
+
+ _SearchPageControllerBase(this.appController);
+
+ @observable
+ String searchName;
+
+ @observable
+ ObservableList films = ObservableList();
+
+ final Api api = Api();
+
+ @observable
+ int actualPage = 1;
+
+ @action
+ void setSearchName(String searchName) => this.searchName = searchName;
+
+ @action
+ void setActualPage(actualPage) => this.actualPage = actualPage;
+
+ @action
+ Future fetchFilms() async {
+ var response = await api.searchFilm(searchName, actualPage);
+ for (var film in response) {
+ films.add(film);
+ }
+ }
+}
diff --git a/lib/app/modules/search_page/search_page_controller.g.dart b/lib/app/modules/search_page/search_page_controller.g.dart
new file mode 100644
index 0000000..0b8fd20
--- /dev/null
+++ b/lib/app/modules/search_page/search_page_controller.g.dart
@@ -0,0 +1,98 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'search_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$SearchPageController on _SearchPageControllerBase, Store {
+ final _$searchNameAtom = Atom(name: '_SearchPageControllerBase.searchName');
+
+ @override
+ String get searchName {
+ _$searchNameAtom.reportRead();
+ return super.searchName;
+ }
+
+ @override
+ set searchName(String value) {
+ _$searchNameAtom.reportWrite(value, super.searchName, () {
+ super.searchName = value;
+ });
+ }
+
+ final _$filmsAtom = Atom(name: '_SearchPageControllerBase.films');
+
+ @override
+ ObservableList get films {
+ _$filmsAtom.reportRead();
+ return super.films;
+ }
+
+ @override
+ set films(ObservableList value) {
+ _$filmsAtom.reportWrite(value, super.films, () {
+ super.films = value;
+ });
+ }
+
+ final _$actualPageAtom = Atom(name: '_SearchPageControllerBase.actualPage');
+
+ @override
+ int get actualPage {
+ _$actualPageAtom.reportRead();
+ return super.actualPage;
+ }
+
+ @override
+ set actualPage(int value) {
+ _$actualPageAtom.reportWrite(value, super.actualPage, () {
+ super.actualPage = value;
+ });
+ }
+
+ final _$fetchFilmsAsyncAction =
+ AsyncAction('_SearchPageControllerBase.fetchFilms');
+
+ @override
+ Future fetchFilms() {
+ return _$fetchFilmsAsyncAction.run(() => super.fetchFilms());
+ }
+
+ final _$_SearchPageControllerBaseActionController =
+ ActionController(name: '_SearchPageControllerBase');
+
+ @override
+ void setSearchName(String searchName) {
+ final _$actionInfo = _$_SearchPageControllerBaseActionController
+ .startAction(name: '_SearchPageControllerBase.setSearchName');
+ try {
+ return super.setSearchName(searchName);
+ } finally {
+ _$_SearchPageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ void setActualPage(dynamic actualPage) {
+ final _$actionInfo = _$_SearchPageControllerBaseActionController
+ .startAction(name: '_SearchPageControllerBase.setActualPage');
+ try {
+ return super.setActualPage(actualPage);
+ } finally {
+ _$_SearchPageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+searchName: ${searchName},
+films: ${films},
+actualPage: ${actualPage}
+ ''';
+ }
+}
diff --git a/lib/app/modules/search_page/search_page_page.dart b/lib/app/modules/search_page/search_page_page.dart
new file mode 100644
index 0000000..ce69171
--- /dev/null
+++ b/lib/app/modules/search_page/search_page_page.dart
@@ -0,0 +1,108 @@
+import 'package:yshare/components/compact_card_film.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+import 'search_page_controller.dart';
+
+class SearchPagePage extends StatefulWidget {
+ final String title;
+ final String name;
+ const SearchPagePage({Key key, this.title = 'SearchPage', this.name})
+ : super(key: key);
+
+ @override
+ _SearchPagePageState createState() => _SearchPagePageState();
+}
+
+class _SearchPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+
+ final ScrollController _scrollController = ScrollController();
+
+ void _scrollListener() {
+ if (_scrollController.offset >=
+ _scrollController.position.maxScrollExtent &&
+ !_scrollController.position.outOfRange) {
+ controller.setActualPage(controller.actualPage + 1);
+ controller.fetchFilms();
+ }
+ }
+
+ @override
+ void dispose() {
+ _scrollController.removeListener(_scrollListener);
+ _scrollController.dispose();
+ super.dispose();
+ }
+
+ @override
+ void initState() {
+ super.initState();
+ controller.setSearchName(widget.name);
+ controller.fetchFilms();
+ _scrollController.addListener(_scrollListener);
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Observer(
+ builder: (_) => CustomScrollView(
+ controller: _scrollController,
+ slivers: [
+ SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ floating: false,
+ pinned: false,
+ snap: false,
+ iconTheme: IconTheme.of(context),
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text(controller.searchName,
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(50))),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(EvaIcons.sun)
+ : Icon(EvaIcons.moon),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ ),
+ SliverToBoxAdapter(
+ child: GridView.builder(
+ shrinkWrap: true,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ childAspectRatio: 0.6,
+ ),
+ itemCount: controller.films.length,
+ physics: BouncingScrollPhysics(),
+ itemBuilder: (context, index) =>
+ CompactCardFilm(film: controller.films[index]),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/app/modules/top_rated_page/top_rated_page_controller.dart b/lib/app/modules/top_rated_page/top_rated_page_controller.dart
new file mode 100644
index 0000000..68b32e6
--- /dev/null
+++ b/lib/app/modules/top_rated_page/top_rated_page_controller.dart
@@ -0,0 +1,34 @@
+import 'package:mobx/mobx.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+
+part 'top_rated_page_controller.g.dart';
+
+class TopRatedPageController = _TopRatedPageControllerBase
+ with _$TopRatedPageController;
+
+abstract class _TopRatedPageControllerBase with Store {
+ final AppController appController;
+
+ _TopRatedPageControllerBase(this.appController);
+
+ @observable
+ ObservableList films = ObservableList();
+
+ final Api api = Api();
+
+ @observable
+ int actualPage = 1;
+
+ @action
+ void setActualPage(actualPage) => this.actualPage = actualPage;
+
+ @action
+ Future fetchTopRated() async {
+ var response = await api.getPopular(actualPage);
+ for (var film in response) {
+ films.add(film);
+ }
+ }
+}
diff --git a/lib/app/modules/top_rated_page/top_rated_page_controller.g.dart b/lib/app/modules/top_rated_page/top_rated_page_controller.g.dart
new file mode 100644
index 0000000..a93db1d
--- /dev/null
+++ b/lib/app/modules/top_rated_page/top_rated_page_controller.g.dart
@@ -0,0 +1,71 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'top_rated_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$TopRatedPageController on _TopRatedPageControllerBase, Store {
+ final _$filmsAtom = Atom(name: '_TopRatedPageControllerBase.films');
+
+ @override
+ ObservableList get films {
+ _$filmsAtom.reportRead();
+ return super.films;
+ }
+
+ @override
+ set films(ObservableList value) {
+ _$filmsAtom.reportWrite(value, super.films, () {
+ super.films = value;
+ });
+ }
+
+ final _$actualPageAtom = Atom(name: '_TopRatedPageControllerBase.actualPage');
+
+ @override
+ int get actualPage {
+ _$actualPageAtom.reportRead();
+ return super.actualPage;
+ }
+
+ @override
+ set actualPage(int value) {
+ _$actualPageAtom.reportWrite(value, super.actualPage, () {
+ super.actualPage = value;
+ });
+ }
+
+ final _$fetchTopRatedAsyncAction =
+ AsyncAction('_TopRatedPageControllerBase.fetchTopRated');
+
+ @override
+ Future fetchTopRated() {
+ return _$fetchTopRatedAsyncAction.run(() => super.fetchTopRated());
+ }
+
+ final _$_TopRatedPageControllerBaseActionController =
+ ActionController(name: '_TopRatedPageControllerBase');
+
+ @override
+ void setActualPage(dynamic actualPage) {
+ final _$actionInfo = _$_TopRatedPageControllerBaseActionController
+ .startAction(name: '_TopRatedPageControllerBase.setActualPage');
+ try {
+ return super.setActualPage(actualPage);
+ } finally {
+ _$_TopRatedPageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+films: ${films},
+actualPage: ${actualPage}
+ ''';
+ }
+}
diff --git a/lib/app/modules/top_rated_page/top_rated_page_page.dart b/lib/app/modules/top_rated_page/top_rated_page_page.dart
new file mode 100644
index 0000000..21ecf60
--- /dev/null
+++ b/lib/app/modules/top_rated_page/top_rated_page_page.dart
@@ -0,0 +1,110 @@
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/components/compact_card_film.dart';
+import 'top_rated_page_controller.dart';
+
+class TopRatedPagePage extends StatefulWidget {
+ final AppController controller;
+ final String title;
+ const TopRatedPagePage(
+ {Key key, this.title = 'TopRatedPage', this.controller})
+ : super(key: key);
+
+ @override
+ _TopRatedPagePageState createState() => _TopRatedPagePageState();
+}
+
+class _TopRatedPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+
+ final ScrollController _scrollController = ScrollController();
+
+ void _scrollListener() {
+ if (_scrollController.offset >=
+ _scrollController.position.maxScrollExtent &&
+ !_scrollController.position.outOfRange) {
+ controller.setActualPage(controller.actualPage + 1);
+ controller.fetchTopRated();
+ }
+ }
+
+ @override
+ void initState() {
+ controller.fetchTopRated();
+ _scrollController.addListener(_scrollListener);
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Observer(
+ builder: (_) => CustomScrollView(
+ controller: _scrollController,
+ slivers: [
+ SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ floating: false,
+ pinned: true,
+ snap: false,
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text('Top Rated',
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(50))),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(
+ EvaIcons.sun,
+ color: Colors.white,
+ )
+ : Icon(EvaIcons.moon, color: Colors.white),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ ),
+ SliverToBoxAdapter(
+ child: GridView.builder(
+ shrinkWrap: true,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ childAspectRatio: 0.6,
+ ),
+ itemCount: controller.films.length,
+ physics: BouncingScrollPhysics(),
+ itemBuilder: (context, index) =>
+ CompactCardFilm(film: controller.films[index]),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _scrollController.removeListener(_scrollListener);
+ _scrollController.dispose();
+ super.dispose();
+ }
+}
diff --git a/lib/app/modules/trending_page/trending_page_controller.dart b/lib/app/modules/trending_page/trending_page_controller.dart
new file mode 100644
index 0000000..a885838
--- /dev/null
+++ b/lib/app/modules/trending_page/trending_page_controller.dart
@@ -0,0 +1,34 @@
+import 'package:mobx/mobx.dart';
+import 'package:yshare/app/app_controller.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/api.dart';
+
+part 'trending_page_controller.g.dart';
+
+class TrendingPageController = _TrendingPageControllerBase
+ with _$TrendingPageController;
+
+abstract class _TrendingPageControllerBase with Store {
+ final AppController appController;
+
+ _TrendingPageControllerBase(this.appController);
+
+ @observable
+ ObservableList films = ObservableList();
+
+ final Api api = Api();
+
+ @observable
+ int actualPage = 1;
+
+ @action
+ void setActualPage(actualPage) => this.actualPage = actualPage;
+
+ @action
+ Future fetchTredingFilms() async {
+ var response = await api.getTrendingFilms(actualPage);
+ for (var film in response) {
+ films.add(film);
+ }
+ }
+}
diff --git a/lib/app/modules/trending_page/trending_page_controller.g.dart b/lib/app/modules/trending_page/trending_page_controller.g.dart
new file mode 100644
index 0000000..214611c
--- /dev/null
+++ b/lib/app/modules/trending_page/trending_page_controller.g.dart
@@ -0,0 +1,71 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'trending_page_controller.dart';
+
+// **************************************************************************
+// StoreGenerator
+// **************************************************************************
+
+// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic
+
+mixin _$TrendingPageController on _TrendingPageControllerBase, Store {
+ final _$filmsAtom = Atom(name: '_TrendingPageControllerBase.films');
+
+ @override
+ ObservableList get films {
+ _$filmsAtom.reportRead();
+ return super.films;
+ }
+
+ @override
+ set films(ObservableList value) {
+ _$filmsAtom.reportWrite(value, super.films, () {
+ super.films = value;
+ });
+ }
+
+ final _$actualPageAtom = Atom(name: '_TrendingPageControllerBase.actualPage');
+
+ @override
+ int get actualPage {
+ _$actualPageAtom.reportRead();
+ return super.actualPage;
+ }
+
+ @override
+ set actualPage(int value) {
+ _$actualPageAtom.reportWrite(value, super.actualPage, () {
+ super.actualPage = value;
+ });
+ }
+
+ final _$fetchTredingFilmsAsyncAction =
+ AsyncAction('_TrendingPageControllerBase.fetchTredingFilms');
+
+ @override
+ Future fetchTredingFilms() {
+ return _$fetchTredingFilmsAsyncAction.run(() => super.fetchTredingFilms());
+ }
+
+ final _$_TrendingPageControllerBaseActionController =
+ ActionController(name: '_TrendingPageControllerBase');
+
+ @override
+ void setActualPage(dynamic actualPage) {
+ final _$actionInfo = _$_TrendingPageControllerBaseActionController
+ .startAction(name: '_TrendingPageControllerBase.setActualPage');
+ try {
+ return super.setActualPage(actualPage);
+ } finally {
+ _$_TrendingPageControllerBaseActionController.endAction(_$actionInfo);
+ }
+ }
+
+ @override
+ String toString() {
+ return '''
+films: ${films},
+actualPage: ${actualPage}
+ ''';
+ }
+}
diff --git a/lib/app/modules/trending_page/trending_page_page.dart b/lib/app/modules/trending_page/trending_page_page.dart
new file mode 100644
index 0000000..523acc9
--- /dev/null
+++ b/lib/app/modules/trending_page/trending_page_page.dart
@@ -0,0 +1,109 @@
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_mobx/flutter_mobx.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+import 'package:yshare/components/compact_card_film.dart';
+import 'trending_page_controller.dart';
+
+class TrendingPagePage extends StatefulWidget {
+ final String title;
+ const TrendingPagePage({
+ Key key,
+ this.title = 'TrendingPage',
+ }) : super(key: key);
+
+ @override
+ _TrendingPagePageState createState() => _TrendingPagePageState();
+}
+
+class _TrendingPagePageState
+ extends ModularState {
+ //use 'controller' variable to access controller
+
+ final ScrollController _scrollController = ScrollController();
+
+ void _scrollListener() {
+ if (_scrollController.offset >=
+ _scrollController.position.maxScrollExtent &&
+ !_scrollController.position.outOfRange) {
+ controller.setActualPage(controller.actualPage + 1);
+ controller.fetchTredingFilms();
+ }
+ }
+
+ @override
+ void initState() {
+ controller.fetchTredingFilms();
+ _scrollController.addListener(_scrollListener);
+ super.initState();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Scaffold(
+ body: Observer(
+ builder: (_) => CustomScrollView(
+ controller: _scrollController,
+ slivers: [
+ SliverAppBar(
+ backgroundColor: Colors.black87,
+ elevation: 10,
+ expandedHeight: 150,
+ titleSpacing: 10,
+ floating: false,
+ pinned: true,
+ snap: false,
+ flexibleSpace: FlexibleSpaceBar(
+ title: Text('Trending',
+ style: TextStyle(
+ color: Colors.grey[200],
+ fontSize: 16,
+ fontFamily: GoogleFonts.poppins().fontFamily)),
+ ),
+ shape: RoundedRectangleBorder(
+ borderRadius:
+ BorderRadius.only(bottomLeft: Radius.circular(50))),
+ actions: [
+ Observer(
+ builder: (_) {
+ return IconButton(
+ icon: controller.appController.isDark
+ ? Icon(
+ EvaIcons.sun,
+ color: Colors.white,
+ )
+ : Icon(EvaIcons.moon, color: Colors.white),
+ onPressed: () {
+ controller.appController.changeTheme();
+ });
+ },
+ )
+ ],
+ ),
+ SliverToBoxAdapter(
+ child: GridView.builder(
+ shrinkWrap: true,
+ gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
+ maxCrossAxisExtent: 200,
+ childAspectRatio: 0.6,
+ ),
+ itemCount: controller.films.length,
+ physics: BouncingScrollPhysics(),
+ itemBuilder: (context, index) =>
+ CompactCardFilm(film: controller.films[index]),
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+
+ @override
+ void dispose() {
+ _scrollController.removeListener(_scrollListener);
+ _scrollController.dispose();
+ super.dispose();
+ }
+}
diff --git a/lib/components/card_film.dart b/lib/components/card_film.dart
new file mode 100644
index 0000000..6ab714f
--- /dev/null
+++ b/lib/components/card_film.dart
@@ -0,0 +1,77 @@
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CardFilm extends StatelessWidget {
+ const CardFilm({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ if (film.posterPath == null) {
+ return Container();
+ }
+ return Container(
+ margin: const EdgeInsets.all(4),
+ width: 140,
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.spaceAround,
+ children: [
+ InkWell(
+ onTap: () => Modular.to.pushNamed('/filmPage/${film.id}'),
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${film.posterPath}',
+ fit: BoxFit.cover,
+ height: 160,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${film.title}',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ EvaIcons.star,
+ color: Colors.yellow.shade800,
+ size: 14,
+ ),
+ Text(
+ '${film.voteAverage.toStringAsFixed(2)}/10',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily, fontSize: 12),
+ )
+ ],
+ )
+ ],
+ ),
+ );
+ }
+}
diff --git a/lib/components/cast_horizontal_list.dart b/lib/components/cast_horizontal_list.dart
new file mode 100644
index 0000000..3659a2d
--- /dev/null
+++ b/lib/components/cast_horizontal_list.dart
@@ -0,0 +1,64 @@
+import 'package:yshare/app/modules/film_page/widgets/person_cast_card.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/model/film_credit.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CastHorizontalList extends StatelessWidget {
+ const CastHorizontalList({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder(
+ future: Api().getFilmCredits(film.id.toString()),
+ builder: (context, snapshot) {
+ var filmCredit = snapshot.data;
+ if (snapshot.hasData) {
+ return SliverToBoxAdapter(
+ child: Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ crossAxisAlignment: CrossAxisAlignment.start,
+ children: [
+ Padding(
+ padding:
+ const EdgeInsets.only(left: 12.0, top: 10, bottom: 12),
+ child: Text('Casting',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 18)),
+ ),
+ Container(
+ height: 140,
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: filmCredit.cast.length,
+ itemBuilder: (context, index) {
+ var cast = filmCredit.cast[index];
+ if (cast.profilePath == '' ||
+ cast.profilePath == null) {
+ return Container();
+ } else {
+ return PersonCastCard(cast: cast);
+ }
+ }),
+ ),
+ ],
+ ),
+ );
+ } else {
+ return SliverToBoxAdapter(
+ child: Center(
+ child: CircularProgressIndicator(),
+ ));
+ }
+ },
+ );
+ }
+}
diff --git a/lib/components/compact_card_film.dart b/lib/components/compact_card_film.dart
new file mode 100644
index 0000000..6147366
--- /dev/null
+++ b/lib/components/compact_card_film.dart
@@ -0,0 +1,79 @@
+import 'package:yshare/model/film.dart';
+import 'package:yshare/provider/constants.dart';
+import 'package:eva_icons_flutter/eva_icons_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CompactCardFilm extends StatelessWidget {
+ const CompactCardFilm({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ if (film.posterPath == null) {
+ return FlutterLogo();
+ } else {
+ return Column(
+ mainAxisAlignment: MainAxisAlignment.start,
+ children: [
+ InkWell(
+ onTap: () {
+ Modular.to.pushNamed(
+ '/filmPage/${film.id}',
+ );
+ },
+ child: Card(
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(20)),
+ borderOnForeground: false,
+ elevation: 10,
+ clipBehavior: Clip.antiAlias,
+ child: ClipRRect(
+ borderRadius: BorderRadius.circular(20),
+ child: Image.network(
+ '$IMAGE_BASE_URL${film.posterPath}',
+ fit: BoxFit.cover,
+ height: 180,
+ ),
+ ),
+ ),
+ ),
+ Padding(
+ padding: const EdgeInsets.only(top: 2.0),
+ child: Text(
+ '${film.title}',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontWeight: FontWeight.bold,
+ ),
+ overflow: TextOverflow.fade,
+ maxLines: 2,
+ softWrap: true,
+ textScaleFactor: 0.9,
+ ),
+ ),
+ Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: [
+ Icon(
+ EvaIcons.star,
+ color: Colors.yellow.shade800,
+ size: 14,
+ ),
+ Text(
+ '${film.voteAverage.toStringAsFixed(2)}/10',
+ style: TextStyle(
+ fontFamily: GoogleFonts.poppins().fontFamily, fontSize: 12),
+ )
+ ],
+ )
+ ],
+ );
+ }
+ }
+}
diff --git a/lib/components/crew_horizontal_list.dart b/lib/components/crew_horizontal_list.dart
new file mode 100644
index 0000000..0987d65
--- /dev/null
+++ b/lib/components/crew_horizontal_list.dart
@@ -0,0 +1,66 @@
+import 'package:yshare/app/modules/film_page/widgets/person_crew_card.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/model/film_credit.dart';
+import 'package:yshare/provider/api.dart';
+import 'package:flutter/material.dart';
+import 'package:google_fonts/google_fonts.dart';
+
+class CrewHorizontalList extends StatelessWidget {
+ const CrewHorizontalList({
+ Key key,
+ @required this.film,
+ }) : super(key: key);
+
+ final Film film;
+
+ @override
+ Widget build(BuildContext context) {
+ return FutureBuilder(
+ future: Api().getFilmCredits(film.id.toString()),
+ builder: (context, snapshot) {
+ var filmCredit = snapshot.data;
+ if (snapshot.hasData) {
+ if (filmCredit.crew != null && filmCredit.crew.isNotEmpty) {
+ return SliverToBoxAdapter(
+ child: Column(
+ children: [
+ Padding(
+ padding:
+ const EdgeInsets.only(left: 12.0, top: 10, bottom: 12),
+ child: Text('Crew',
+ style: TextStyle(
+ color: Colors.black87,
+ fontFamily: GoogleFonts.poppins().fontFamily,
+ fontSize: 18)),
+ ),
+ Container(
+ height: 140,
+ child: ListView.builder(
+ physics: BouncingScrollPhysics(),
+ scrollDirection: Axis.horizontal,
+ itemCount: filmCredit.crew.length,
+ itemBuilder: (context, index) {
+ var crew = filmCredit.crew[index];
+ return PersonCrewCard(crew: crew);
+ }),
+ ),
+ ],
+ ),
+ );
+ } else {
+ return Container(
+ child: Center(
+ child: Text('No'),
+ ),
+ );
+ }
+ } else {
+ return SliverToBoxAdapter(
+ child: Center(
+ child: CircularProgressIndicator(),
+ ));
+ }
+ },
+ );
+ }
+}
diff --git a/lib/main.dart b/lib/main.dart
new file mode 100644
index 0000000..f076668
--- /dev/null
+++ b/lib/main.dart
@@ -0,0 +1,7 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_modular/flutter_modular.dart';
+
+void main() => runApp(
+ ModularApp(module: AppModule()),
+ );
diff --git a/lib/model/actor_details.dart b/lib/model/actor_details.dart
new file mode 100644
index 0000000..321f026
--- /dev/null
+++ b/lib/model/actor_details.dart
@@ -0,0 +1,51 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'actor_details.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class ActorDetails {
+ String birthday;
+ @JsonKey(name: 'known_for_department')
+ String knownForDepartment;
+ String deathday;
+ int id;
+ String name;
+ @JsonKey(name: 'also_known_as')
+ List alsoKnownAs;
+ int gender;
+ String biography;
+ num popularity;
+ @JsonKey(name: 'place_of_birth')
+ String placeOfBirth;
+ @JsonKey(name: 'profile_path')
+ String profilePath;
+ bool adult;
+ @JsonKey(name: 'imdb_id')
+ String imdbId;
+ String homepage;
+
+ ActorDetails(
+ {this.birthday,
+ this.knownForDepartment,
+ this.deathday,
+ this.id,
+ this.name,
+ this.alsoKnownAs,
+ this.gender,
+ this.biography,
+ this.popularity,
+ this.placeOfBirth,
+ this.profilePath,
+ this.adult,
+ this.imdbId,
+ this.homepage});
+
+ factory ActorDetails.fromJson(Map json) =>
+ _$ActorDetailsFromJson(json);
+ Map toJson() => _$ActorDetailsToJson(this);
+
+ @override
+ String toString() {
+ return 'ActorDetails(birthday: $birthday, knownForDepartment: $knownForDepartment, deathday: $deathday, id: $id, name: $name, alsoKnownAs: $alsoKnownAs, gender: $gender, biography: $biography, popularity: $popularity, placeOfBirth: $placeOfBirth, profilePath: $profilePath, adult: $adult, imdbId: $imdbId, homepage: $homepage)';
+ }
+}
diff --git a/lib/model/actor_details.g.dart b/lib/model/actor_details.g.dart
new file mode 100644
index 0000000..d413d02
--- /dev/null
+++ b/lib/model/actor_details.g.dart
@@ -0,0 +1,45 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'actor_details.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ActorDetails _$ActorDetailsFromJson(Map json) {
+ return ActorDetails(
+ birthday: json['birthday'] as String,
+ knownForDepartment: json['known_for_department'] as String,
+ deathday: json['deathday'] as String,
+ id: json['id'] as int,
+ name: json['name'] as String,
+ alsoKnownAs:
+ (json['also_known_as'] as List)?.map((e) => e as String)?.toList(),
+ gender: json['gender'] as int,
+ biography: json['biography'] as String,
+ popularity: json['popularity'] as num,
+ placeOfBirth: json['place_of_birth'] as String,
+ profilePath: json['profile_path'] as String,
+ adult: json['adult'] as bool,
+ imdbId: json['imdb_id'] as String,
+ homepage: json['homepage'] as String,
+ );
+}
+
+Map _$ActorDetailsToJson(ActorDetails instance) =>
+ {
+ 'birthday': instance.birthday,
+ 'known_for_department': instance.knownForDepartment,
+ 'deathday': instance.deathday,
+ 'id': instance.id,
+ 'name': instance.name,
+ 'also_known_as': instance.alsoKnownAs,
+ 'gender': instance.gender,
+ 'biography': instance.biography,
+ 'popularity': instance.popularity,
+ 'place_of_birth': instance.placeOfBirth,
+ 'profile_path': instance.profilePath,
+ 'adult': instance.adult,
+ 'imdb_id': instance.imdbId,
+ 'homepage': instance.homepage,
+ };
diff --git a/lib/model/actor_participation.dart b/lib/model/actor_participation.dart
new file mode 100644
index 0000000..14c1415
--- /dev/null
+++ b/lib/model/actor_participation.dart
@@ -0,0 +1,19 @@
+import 'package:yshare/model/film.dart';
+import 'package:json_annotation/json_annotation.dart';
+
+part 'actor_participation.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class ActorParticipation {
+ List cast;
+ List crew;
+ int id;
+ ActorParticipation({this.cast, this.crew, this.id});
+
+ factory ActorParticipation.fromJson(Map json) =>
+ _$ActorParticipationFromJson(json);
+ Map toJson() => _$ActorParticipationToJson(this);
+
+ @override
+ String toString() => 'ActorParticipation(cast: $cast, crew: $crew, id: $id)';
+}
diff --git a/lib/model/actor_participation.g.dart b/lib/model/actor_participation.g.dart
new file mode 100644
index 0000000..577a471
--- /dev/null
+++ b/lib/model/actor_participation.g.dart
@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'actor_participation.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ActorParticipation _$ActorParticipationFromJson(Map json) {
+ return ActorParticipation(
+ cast: (json['cast'] as List)
+ ?.map(
+ (e) => e == null ? null : Film.fromJson(e as Map))
+ ?.toList(),
+ crew: (json['crew'] as List)
+ ?.map(
+ (e) => e == null ? null : Film.fromJson(e as Map))
+ ?.toList(),
+ id: json['id'] as int,
+ );
+}
+
+Map _$ActorParticipationToJson(ActorParticipation instance) =>
+ {
+ 'cast': instance.cast,
+ 'crew': instance.crew,
+ 'id': instance.id,
+ };
diff --git a/lib/model/cast.dart b/lib/model/cast.dart
new file mode 100644
index 0000000..19a1b82
--- /dev/null
+++ b/lib/model/cast.dart
@@ -0,0 +1,36 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'cast.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class Cast {
+ @JsonKey(name: 'cast_id')
+ int castId;
+ String character;
+ @JsonKey(name: 'credit_key')
+ String creditId;
+ int gender;
+ int id;
+ String name;
+ int order;
+ @JsonKey(name: 'profile_path')
+ String profilePath;
+
+ Cast(
+ {this.castId,
+ this.character,
+ this.creditId,
+ this.gender,
+ this.id,
+ this.name,
+ this.order,
+ this.profilePath});
+
+ factory Cast.fromJson(Map json) => _$CastFromJson(json);
+ Map toJson() => _$CastToJson(this);
+
+ @override
+ String toString() {
+ return 'Cast(castId: $castId, character: $character, creditId: $creditId, gender: $gender, id: $id, name: $name, order: $order, profilePath: $profilePath)';
+ }
+}
diff --git a/lib/model/cast.g.dart b/lib/model/cast.g.dart
new file mode 100644
index 0000000..87e4fb4
--- /dev/null
+++ b/lib/model/cast.g.dart
@@ -0,0 +1,31 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'cast.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+Cast _$CastFromJson(Map json) {
+ return Cast(
+ castId: json['cast_id'] as int,
+ character: json['character'] as String,
+ creditId: json['credit_key'] as String,
+ gender: json['gender'] as int,
+ id: json['id'] as int,
+ name: json['name'] as String,
+ order: json['order'] as int,
+ profilePath: json['profile_path'] as String,
+ );
+}
+
+Map _$CastToJson(Cast instance) => {
+ 'cast_id': instance.castId,
+ 'character': instance.character,
+ 'credit_key': instance.creditId,
+ 'gender': instance.gender,
+ 'id': instance.id,
+ 'name': instance.name,
+ 'order': instance.order,
+ 'profile_path': instance.profilePath,
+ };
diff --git a/lib/model/crew.dart b/lib/model/crew.dart
new file mode 100644
index 0000000..1f3c39b
--- /dev/null
+++ b/lib/model/crew.dart
@@ -0,0 +1,33 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'crew.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class Crew {
+ @JsonKey(name: 'credit_id')
+ String creditId;
+ String department;
+ int gender;
+ int id;
+ String job;
+ String name;
+ @JsonKey(name: 'profile_path')
+ String profilePath;
+
+ Crew(
+ {this.creditId,
+ this.department,
+ this.gender,
+ this.id,
+ this.job,
+ this.name,
+ this.profilePath});
+
+ factory Crew.fromJson(Map json) => _$CrewFromJson(json);
+ Map toJson() => _$CrewToJson(this);
+
+ @override
+ String toString() {
+ return 'Crew(creditId: $creditId, department: $department, gender: $gender, id: $id, job: $job, name: $name, profilePath: $profilePath)';
+ }
+}
diff --git a/lib/model/crew.g.dart b/lib/model/crew.g.dart
new file mode 100644
index 0000000..3aaf8a0
--- /dev/null
+++ b/lib/model/crew.g.dart
@@ -0,0 +1,29 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'crew.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+Crew _$CrewFromJson(Map json) {
+ return Crew(
+ creditId: json['credit_id'] as String,
+ department: json['department'] as String,
+ gender: json['gender'] as int,
+ id: json['id'] as int,
+ job: json['job'] as String,
+ name: json['name'] as String,
+ profilePath: json['profile_path'] as String,
+ );
+}
+
+Map _$CrewToJson(Crew instance) => {
+ 'credit_id': instance.creditId,
+ 'department': instance.department,
+ 'gender': instance.gender,
+ 'id': instance.id,
+ 'job': instance.job,
+ 'name': instance.name,
+ 'profile_path': instance.profilePath,
+ };
diff --git a/lib/model/film.dart b/lib/model/film.dart
new file mode 100644
index 0000000..f97e282
--- /dev/null
+++ b/lib/model/film.dart
@@ -0,0 +1,72 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import 'genre.dart';
+import 'production_companies.dart';
+import 'production_countries.dart';
+
+part 'film.g.dart';
+
+@JsonSerializable(
+ createFactory: true,
+ createToJson: true,
+)
+class Film {
+ int id;
+ bool video;
+ @JsonKey(name: 'vote_count')
+ int voteCount;
+ @JsonKey(name: 'vote_average')
+ double voteAverage;
+ String title;
+ @JsonKey(name: 'release_date')
+ String releaseDate;
+ @JsonKey(name: 'original_language')
+ String originalLanguage;
+ @JsonKey(name: 'original_title')
+ String originalTitle;
+ @JsonKey(name: 'genres')
+ List genreIds;
+ @JsonKey(name: 'backdrop_path')
+ String backdropPath;
+ bool adult;
+ String overview;
+ @JsonKey(name: 'poster_path')
+ String posterPath;
+ String tagline;
+ int revenue;
+ int runtime;
+ double popularity;
+ @JsonKey(name: 'media_type')
+ String mediaType;
+ @JsonKey(name: 'production_companies')
+ List productionCompanies;
+ @JsonKey(name: 'production_countries')
+ List productionCountries;
+ Film(
+ {this.id,
+ this.video,
+ this.voteCount,
+ this.voteAverage,
+ this.title,
+ this.releaseDate,
+ this.originalLanguage,
+ this.originalTitle,
+ this.genreIds,
+ this.backdropPath,
+ this.adult,
+ this.overview,
+ this.posterPath,
+ this.popularity,
+ this.mediaType,
+ this.tagline,
+ this.revenue,
+ this.runtime});
+
+ factory Film.fromJson(Map json) => _$FilmFromJson(json);
+ Map toJson() => _$FilmToJson(this);
+
+ @override
+ String toString() {
+ return 'Film(id: $id, video: $video, voteCount: $voteCount, voteAverage: $voteAverage, title: $title, releaseDate: $releaseDate, originalLanguage: $originalLanguage, originalTitle: $originalTitle, genreIds: $genreIds, backdropPath: $backdropPath, adult: $adult, overview: $overview, posterPath: $posterPath, tagline: $tagline, revenue: $revenue, runtime: $runtime, popularity: $popularity, mediaType: $mediaType, productionCompanies: $productionCompanies, productionCountries: $productionCountries)';
+ }
+}
diff --git a/lib/model/film.g.dart b/lib/model/film.g.dart
new file mode 100644
index 0000000..c874949
--- /dev/null
+++ b/lib/model/film.g.dart
@@ -0,0 +1,66 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'film.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+Film _$FilmFromJson(Map json) {
+ return Film(
+ id: json['id'] as int,
+ video: json['video'] as bool,
+ voteCount: json['vote_count'] as int,
+ voteAverage: (json['vote_average'] as num)?.toDouble(),
+ title: json['title'] as String,
+ releaseDate: json['release_date'] as String,
+ originalLanguage: json['original_language'] as String,
+ originalTitle: json['original_title'] as String,
+ genreIds: (json['genres'] as List)
+ ?.map(
+ (e) => e == null ? null : Genre.fromJson(e as Map))
+ ?.toList(),
+ backdropPath: json['backdrop_path'] as String,
+ adult: json['adult'] as bool,
+ overview: json['overview'] as String,
+ posterPath: json['poster_path'] as String,
+ popularity: (json['popularity'] as num)?.toDouble(),
+ mediaType: json['media_type'] as String,
+ tagline: json['tagline'] as String,
+ revenue: json['revenue'] as int,
+ runtime: json['runtime'] as int,
+ )
+ ..productionCompanies = (json['production_companies'] as List)
+ ?.map((e) => e == null
+ ? null
+ : ProductionCompanies.fromJson(e as Map))
+ ?.toList()
+ ..productionCountries = (json['production_countries'] as List)
+ ?.map((e) => e == null
+ ? null
+ : ProductionCountries.fromJson(e as Map))
+ ?.toList();
+}
+
+Map _$FilmToJson(Film instance) => {
+ 'id': instance.id,
+ 'video': instance.video,
+ 'vote_count': instance.voteCount,
+ 'vote_average': instance.voteAverage,
+ 'title': instance.title,
+ 'release_date': instance.releaseDate,
+ 'original_language': instance.originalLanguage,
+ 'original_title': instance.originalTitle,
+ 'genres': instance.genreIds,
+ 'backdrop_path': instance.backdropPath,
+ 'adult': instance.adult,
+ 'overview': instance.overview,
+ 'poster_path': instance.posterPath,
+ 'tagline': instance.tagline,
+ 'revenue': instance.revenue,
+ 'runtime': instance.runtime,
+ 'popularity': instance.popularity,
+ 'media_type': instance.mediaType,
+ 'production_companies': instance.productionCompanies,
+ 'production_countries': instance.productionCountries,
+ };
diff --git a/lib/model/film_credit.dart b/lib/model/film_credit.dart
new file mode 100644
index 0000000..71da91a
--- /dev/null
+++ b/lib/model/film_credit.dart
@@ -0,0 +1,22 @@
+import 'package:json_annotation/json_annotation.dart';
+
+import 'cast.dart';
+import 'crew.dart';
+
+part 'film_credit.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class FilmCredit {
+ int id;
+ List cast;
+ List crew;
+
+ FilmCredit({this.id, this.cast, this.crew});
+
+ factory FilmCredit.fromJson(Map json) =>
+ _$FilmCreditFromJson(json);
+ Map toJson() => _$FilmCreditToJson(this);
+
+ @override
+ String toString() => 'FilmCredit(id: $id, cast: $cast, crew: $crew)';
+}
diff --git a/lib/model/film_credit.g.dart b/lib/model/film_credit.g.dart
new file mode 100644
index 0000000..0ce1631
--- /dev/null
+++ b/lib/model/film_credit.g.dart
@@ -0,0 +1,28 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'film_credit.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+FilmCredit _$FilmCreditFromJson(Map json) {
+ return FilmCredit(
+ id: json['id'] as int,
+ cast: (json['cast'] as List)
+ ?.map(
+ (e) => e == null ? null : Cast.fromJson(e as Map))
+ ?.toList(),
+ crew: (json['crew'] as List)
+ ?.map(
+ (e) => e == null ? null : Crew.fromJson(e as Map))
+ ?.toList(),
+ );
+}
+
+Map _$FilmCreditToJson(FilmCredit instance) =>
+ {
+ 'id': instance.id,
+ 'cast': instance.cast,
+ 'crew': instance.crew,
+ };
diff --git a/lib/model/genre.dart b/lib/model/genre.dart
new file mode 100644
index 0000000..55fce18
--- /dev/null
+++ b/lib/model/genre.dart
@@ -0,0 +1,16 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'genre.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class Genre {
+ int id;
+ String name;
+ Genre({this.id, this.name});
+
+ factory Genre.fromJson(Map json) => _$GenreFromJson(json);
+ Map toJson() => _$GenreToJson(this);
+
+ @override
+ String toString() => 'Genre(id: $id, name: $name)';
+}
diff --git a/lib/model/genre.g.dart b/lib/model/genre.g.dart
new file mode 100644
index 0000000..d21605b
--- /dev/null
+++ b/lib/model/genre.g.dart
@@ -0,0 +1,19 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'genre.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+Genre _$GenreFromJson(Map json) {
+ return Genre(
+ id: json['id'] as int,
+ name: json['name'] as String,
+ );
+}
+
+Map _$GenreToJson(Genre instance) => {
+ 'id': instance.id,
+ 'name': instance.name,
+ };
diff --git a/lib/model/production_companies.dart b/lib/model/production_companies.dart
new file mode 100644
index 0000000..0cc33d4
--- /dev/null
+++ b/lib/model/production_companies.dart
@@ -0,0 +1,21 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'production_companies.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class ProductionCompanies {
+ int id;
+ String logoPath;
+ String name;
+ String originCountry;
+ ProductionCompanies({this.id, this.logoPath, this.name, this.originCountry});
+
+ factory ProductionCompanies.fromJson(Map json) =>
+ _$ProductionCompaniesFromJson(json);
+ Map toJson() => _$ProductionCompaniesToJson(this);
+
+ @override
+ String toString() {
+ return 'ProductionCompanies(id: $id, logoPath: $logoPath, name: $name, originCountry: $originCountry)';
+ }
+}
diff --git a/lib/model/production_companies.g.dart b/lib/model/production_companies.g.dart
new file mode 100644
index 0000000..374f05f
--- /dev/null
+++ b/lib/model/production_companies.g.dart
@@ -0,0 +1,25 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'production_companies.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ProductionCompanies _$ProductionCompaniesFromJson(Map json) {
+ return ProductionCompanies(
+ id: json['id'] as int,
+ logoPath: json['logoPath'] as String,
+ name: json['name'] as String,
+ originCountry: json['originCountry'] as String,
+ );
+}
+
+Map _$ProductionCompaniesToJson(
+ ProductionCompanies instance) =>
+ {
+ 'id': instance.id,
+ 'logoPath': instance.logoPath,
+ 'name': instance.name,
+ 'originCountry': instance.originCountry,
+ };
diff --git a/lib/model/production_countries.dart b/lib/model/production_countries.dart
new file mode 100644
index 0000000..a0bb3b5
--- /dev/null
+++ b/lib/model/production_countries.dart
@@ -0,0 +1,17 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'production_countries.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class ProductionCountries {
+ String iso31661;
+ String name;
+ ProductionCountries({this.iso31661, this.name});
+
+ factory ProductionCountries.fromJson(Map json) =>
+ _$ProductionCountriesFromJson(json);
+ Map toJson() => _$ProductionCountriesToJson(this);
+
+ @override
+ String toString() => 'ProductionCountries(iso31661: $iso31661, name: $name)';
+}
diff --git a/lib/model/production_countries.g.dart b/lib/model/production_countries.g.dart
new file mode 100644
index 0000000..df7444a
--- /dev/null
+++ b/lib/model/production_countries.g.dart
@@ -0,0 +1,21 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'production_countries.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+ProductionCountries _$ProductionCountriesFromJson(Map json) {
+ return ProductionCountries(
+ iso31661: json['iso31661'] as String,
+ name: json['name'] as String,
+ );
+}
+
+Map _$ProductionCountriesToJson(
+ ProductionCountries instance) =>
+ {
+ 'iso31661': instance.iso31661,
+ 'name': instance.name,
+ };
diff --git a/lib/model/spoken_languages.dart b/lib/model/spoken_languages.dart
new file mode 100644
index 0000000..52ddc60
--- /dev/null
+++ b/lib/model/spoken_languages.dart
@@ -0,0 +1,17 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'spoken_languages.g.dart';
+
+@JsonSerializable(createFactory: true, createToJson: true)
+class SpokenLanguages {
+ String iso6391;
+ String name;
+ SpokenLanguages({this.iso6391, this.name});
+
+ factory SpokenLanguages.fromJson(Map json) =>
+ _$SpokenLanguagesFromJson(json);
+ Map toJson() => _$SpokenLanguagesToJson(this);
+
+ @override
+ String toString() => 'SpokenLanguages(iso6391: $iso6391, name: $name)';
+}
diff --git a/lib/model/spoken_languages.g.dart b/lib/model/spoken_languages.g.dart
new file mode 100644
index 0000000..59464f4
--- /dev/null
+++ b/lib/model/spoken_languages.g.dart
@@ -0,0 +1,20 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'spoken_languages.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+SpokenLanguages _$SpokenLanguagesFromJson(Map json) {
+ return SpokenLanguages(
+ iso6391: json['iso6391'] as String,
+ name: json['name'] as String,
+ );
+}
+
+Map _$SpokenLanguagesToJson(SpokenLanguages instance) =>
+ {
+ 'iso6391': instance.iso6391,
+ 'name': instance.name,
+ };
diff --git a/lib/model/tv_participation.dart b/lib/model/tv_participation.dart
new file mode 100644
index 0000000..24d6270
--- /dev/null
+++ b/lib/model/tv_participation.dart
@@ -0,0 +1,65 @@
+import 'package:json_annotation/json_annotation.dart';
+
+part 'tv_participation.g.dart';
+
+@JsonSerializable(
+ createFactory: true,
+ createToJson: true,
+)
+class TvParticipation {
+ @JsonKey(name: 'credit_id')
+ String creditId;
+ @JsonKey(name: 'original_name')
+ String originalName;
+ int id;
+ @JsonKey(name: 'genre_ids')
+ List genreIds;
+ String character;
+ String name;
+ @JsonKey(name: 'poster_path')
+ String posterPath;
+ @JsonKey(name: 'vote_count')
+ int voteCount;
+ @JsonKey(name: 'vote_average')
+ double voteAverage;
+ double popularity;
+ @JsonKey(name: 'episode_count')
+ int episodeCount;
+ @JsonKey(name: 'original_language')
+ String originalLanguage;
+ @JsonKey(name: 'first_air_date')
+ String firstAirDate;
+ @JsonKey(name: 'backdrop_path')
+ String backdropPath;
+ String overview;
+ @JsonKey(name: 'origin_country')
+ List originCountry;
+
+ TvParticipation({
+ this.creditId,
+ this.originalName,
+ this.id,
+ this.genreIds,
+ this.character,
+ this.name,
+ this.posterPath,
+ this.voteCount,
+ this.voteAverage,
+ this.popularity,
+ this.episodeCount,
+ this.originalLanguage,
+ this.firstAirDate,
+ this.backdropPath,
+ this.overview,
+ this.originCountry,
+ });
+
+ factory TvParticipation.fromJson(Map json) =>
+ _$TvParticipationFromJson(json);
+ Map toJson() => _$TvParticipationToJson(this);
+
+ @override
+ String toString() {
+ return 'TvParticipation(creditId: $creditId, originalName: $originalName, id: $id, genreIds: $genreIds, character: $character, name: $name, posterPath: $posterPath, voteCount: $voteCount, voteAverage: $voteAverage, popularity: $popularity, episodeCount: $episodeCount, originalLanguage: $originalLanguage, firstAirDate: $firstAirDate, backdropPath: $backdropPath, overview: $overview, originCountry: $originCountry)';
+ }
+}
diff --git a/lib/model/tv_participation.g.dart b/lib/model/tv_participation.g.dart
new file mode 100644
index 0000000..affad8f
--- /dev/null
+++ b/lib/model/tv_participation.g.dart
@@ -0,0 +1,49 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'tv_participation.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+TvParticipation _$TvParticipationFromJson(Map json) {
+ return TvParticipation(
+ creditId: json['credit_id'] as String,
+ originalName: json['original_name'] as String,
+ id: json['id'] as int,
+ genreIds: (json['genre_ids'] as List)?.map((e) => e as int)?.toList(),
+ character: json['character'] as String,
+ name: json['name'] as String,
+ posterPath: json['poster_path'] as String,
+ voteCount: json['vote_count'] as int,
+ voteAverage: (json['vote_average'] as num)?.toDouble(),
+ popularity: (json['popularity'] as num)?.toDouble(),
+ episodeCount: json['episode_count'] as int,
+ originalLanguage: json['original_language'] as String,
+ firstAirDate: json['first_air_date'] as String,
+ backdropPath: json['backdrop_path'] as String,
+ overview: json['overview'] as String,
+ originCountry:
+ (json['origin_country'] as List)?.map((e) => e as String)?.toList(),
+ );
+}
+
+Map _$TvParticipationToJson(TvParticipation instance) =>
+ {
+ 'credit_id': instance.creditId,
+ 'original_name': instance.originalName,
+ 'id': instance.id,
+ 'genre_ids': instance.genreIds,
+ 'character': instance.character,
+ 'name': instance.name,
+ 'poster_path': instance.posterPath,
+ 'vote_count': instance.voteCount,
+ 'vote_average': instance.voteAverage,
+ 'popularity': instance.popularity,
+ 'episode_count': instance.episodeCount,
+ 'original_language': instance.originalLanguage,
+ 'first_air_date': instance.firstAirDate,
+ 'backdrop_path': instance.backdropPath,
+ 'overview': instance.overview,
+ 'origin_country': instance.originCountry,
+ };
diff --git a/lib/provider/api.dart b/lib/provider/api.dart
new file mode 100644
index 0000000..22a9842
--- /dev/null
+++ b/lib/provider/api.dart
@@ -0,0 +1,131 @@
+import 'package:dio/dio.dart';
+import 'package:yshare/model/actor_details.dart';
+import 'package:yshare/model/actor_participation.dart';
+import 'package:yshare/model/film.dart';
+import 'package:yshare/model/film_credit.dart';
+import 'package:yshare/model/tv_participation.dart';
+import 'package:yshare/provider/constants.dart';
+
+class Api {
+ final Dio _client = Dio();
+
+ Future getFilmById(String id) async {
+ final _endpoint = '$MOVIE_BASE_URL$id$API_KEY';
+ final response = await _client.get(_endpoint);
+ return Film.fromJson(response.data);
+ }
+
+ Future> getTrendingFilms([page = 1]) async {
+ final _endpoint = '$TRENDING_MOVIE$API_KEY$PAGE$page';
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ final film = Film.fromJson(json);
+ films.add(film);
+ }
+
+ return films;
+ }
+
+ Future> getFilmByGenre(String genreId, [page = 1]) async {
+ final _endpoint = '$GENRE_SEARCH$genreId$PAGE$page';
+
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ final film = Film.fromJson(json);
+ films.add(film);
+ }
+
+ return films;
+ }
+
+ Future> getRecommendations(String filmId, [page = 1]) async {
+ final _endpoint =
+ 'https://api.themoviedb.org/3/movie/$filmId/recommendations?api_key=ab319f50a3792c49e23a3336df9f0d80&language=en-US&page=$page';
+
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ final film = Film.fromJson(json);
+ films.add(film);
+ }
+ return films;
+ }
+
+ Future getFilmCredits(String filmId) async {
+ final _endpoint =
+ 'https://api.themoviedb.org/3/movie/$filmId/credits$API_KEY$LANGUAGE';
+ final response = await _client.request(_endpoint);
+ return FilmCredit.fromJson(response.data);
+ }
+
+ Future getActorDetails(String actorId) async {
+ final _endpoint =
+ 'https://api.themoviedb.org/3/person/$actorId?api_key=ab319f50a3792c49e23a3336df9f0d80&language=en-US';
+ final response = await _client.request(_endpoint);
+ return ActorDetails.fromJson(response.data);
+ }
+
+ Future getActorParticipation(String actorId) async {
+ final _endpoint =
+ 'https://api.themoviedb.org/3/person/$actorId/movie_credits?api_key=ab319f50a3792c49e23a3336df9f0d80&language=en-US';
+
+ final response = await _client.request(_endpoint);
+
+ return ActorParticipation.fromJson(response.data);
+ }
+
+ Future> searchFilm(String searchParam, [page = 1]) async {
+ final _endpoint = '$SEARCH_MOVIE$API_KEY$QUERY$searchParam$PAGE$page';
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ var film = Film.fromJson(json);
+ films.add(film);
+ }
+
+ return films;
+ }
+
+ Future> getPopular([page = 1]) async {
+ final _endpoint = '$POPULAR_MOVIE$API_KEY$PAGE$page';
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ final film = Film.fromJson(json);
+ films.add(film);
+ }
+ return films;
+ }
+
+ Future> getTopRated([page = 1]) async {
+ final _endpoint = '$TOP_RATED$API_KEY$PAGE$page';
+ final response = await _client.request(_endpoint);
+ final films = [];
+
+ for (Map json in response.data['results']) {
+ final film = Film.fromJson(json);
+ films.add(film);
+ }
+ return films;
+ }
+
+ Future> getPersonTvParticipations(
+ String personId) async {
+ final _endpoint = '$PERSON_ENDPOINT$personId/tv_credits$API_KEY$LANGUAGE';
+ final response = await _client.request(_endpoint);
+ final tvParticipations = [];
+
+ for (Map json in response.data['cast']) {
+ var tv = TvParticipation.fromJson(json);
+ tvParticipations.add(tv);
+ }
+ return tvParticipations;
+ }
+}
diff --git a/lib/provider/constants.dart b/lib/provider/constants.dart
new file mode 100644
index 0000000..08498b6
--- /dev/null
+++ b/lib/provider/constants.dart
@@ -0,0 +1,39 @@
+const IMAGE_BASE_URL = 'https://image.tmdb.org/t/p/w500';
+const MOVIE_BASE_URL = 'https://api.themoviedb.org/3/movie/';
+const SERIE_BASE_URL = 'https://api.themoviedb.org/3/tv/';
+const API_KEY = '?api_key=ab319f50a3792c49e23a3336df9f0d80';
+const TRENDING_MOVIE = 'https://api.themoviedb.org/3/trending/movie/day';
+const SEARCH_MOVIE = 'https://api.themoviedb.org/3/search/movie';
+const GENRE_SEARCH =
+ 'https://api.themoviedb.org/3/discover/movie?api_key=ab319f50a3792c49e23a3336df9f0d80&language=en-US&sort_by=popularity.desc&with_genres=';
+const QUERY = '&query=';
+
+const POPULAR_MOVIE = 'https://api.themoviedb.org/3/movie/popular';
+const PAGE = '&page=';
+const TOP_RATED = 'https://api.themoviedb.org/3/movie/top_rated';
+const PERSON_TV_PARTICIPATIONS =
+ 'https://api.themoviedb.org/3/person/83002/tv_credits';
+const PERSON_ENDPOINT = 'https://api.themoviedb.org/3/person/';
+const LANGUAGE = '&language=en-US';
+
+const GENRES = [
+ {'id': 28, 'name': 'Action'},
+ {'id': 12, 'name': 'Adventure'},
+ {'id': 16, 'name': 'Animation'},
+ {'id': 35, 'name': 'Comedy'},
+ {'id': 80, 'name': 'Crime'},
+ {'id': 99, 'name': 'Documentary'},
+ {'id': 18, 'name': 'Drama'},
+ {'id': 10751, 'name': 'Family'},
+ {'id': 14, 'name': 'Fantasy'},
+ {'id': 36, 'name': 'History'},
+ {'id': 27, 'name': 'Horror'},
+ {'id': 10402, 'name': 'Music'},
+ {'id': 9648, 'name': 'Mystery'},
+ {'id': 10749, 'name': 'Romance'},
+ {'id': 878, 'name': 'Science Fiction'},
+ {'id': 10770, 'name': 'TV Movie'},
+ {'id': 53, 'name': 'Thriller'},
+ {'id': 10752, 'name': 'War'},
+ {'id': 37, 'name': 'Western'}
+];
diff --git a/pubspec.lock b/pubspec.lock
new file mode 100644
index 0000000..2397e33
--- /dev/null
+++ b/pubspec.lock
@@ -0,0 +1,649 @@
+# Generated by pub
+# See https://dart.dev/tools/pub/glossary#lockfile
+packages:
+ _fe_analyzer_shared:
+ dependency: transitive
+ description:
+ name: _fe_analyzer_shared
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "7.0.0"
+ analyzer:
+ dependency: transitive
+ description:
+ name: analyzer
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.39.17"
+ args:
+ dependency: transitive
+ description:
+ name: args
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.6.0"
+ async:
+ dependency: transitive
+ description:
+ name: async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.5.0-nullsafety"
+ boolean_selector:
+ dependency: transitive
+ description:
+ name: boolean_selector
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0-nullsafety"
+ bot_toast:
+ dependency: "direct main"
+ description:
+ name: bot_toast
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.4"
+ build:
+ dependency: transitive
+ description:
+ name: build
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.0"
+ build_config:
+ dependency: transitive
+ description:
+ name: build_config
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.4.2"
+ build_daemon:
+ dependency: transitive
+ description:
+ name: build_daemon
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.4"
+ build_resolvers:
+ dependency: transitive
+ description:
+ name: build_resolvers
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.11"
+ build_runner:
+ dependency: "direct dev"
+ description:
+ name: build_runner
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.10.2"
+ build_runner_core:
+ dependency: transitive
+ description:
+ name: build_runner_core
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "6.0.1"
+ built_collection:
+ dependency: transitive
+ description:
+ name: built_collection
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.3.2"
+ built_value:
+ dependency: transitive
+ description:
+ name: built_value
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "7.1.0"
+ characters:
+ dependency: transitive
+ description:
+ name: characters
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0-nullsafety.2"
+ charcode:
+ dependency: transitive
+ description:
+ name: charcode
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0-nullsafety"
+ checked_yaml:
+ dependency: transitive
+ description:
+ name: checked_yaml
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.2"
+ cli_util:
+ dependency: transitive
+ description:
+ name: cli_util
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.0"
+ clock:
+ dependency: transitive
+ description:
+ name: clock
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0-nullsafety"
+ code_builder:
+ dependency: transitive
+ description:
+ name: code_builder
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.4.1"
+ collection:
+ dependency: transitive
+ description:
+ name: collection
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.15.0-nullsafety.2"
+ convert:
+ dependency: transitive
+ description:
+ name: convert
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.1"
+ crypto:
+ dependency: transitive
+ description:
+ name: crypto
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.5"
+ csslib:
+ dependency: transitive
+ description:
+ name: csslib
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.16.2"
+ dart_style:
+ dependency: transitive
+ description:
+ name: dart_style
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.6"
+ dio:
+ dependency: "direct main"
+ description:
+ name: dio
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.10"
+ eva_icons_flutter:
+ dependency: "direct main"
+ description:
+ name: eva_icons_flutter
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.1"
+ fake_async:
+ dependency: transitive
+ description:
+ name: fake_async
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0-nullsafety"
+ file:
+ dependency: transitive
+ description:
+ name: file
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "5.2.1"
+ fixnum:
+ dependency: transitive
+ description:
+ name: fixnum
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.10.11"
+ flutter:
+ dependency: "direct main"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_mobx:
+ dependency: "direct main"
+ description:
+ name: flutter_mobx
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0+2"
+ flutter_modular:
+ dependency: "direct main"
+ description:
+ name: flutter_modular
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.0.0+1"
+ flutter_test:
+ dependency: "direct dev"
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ flutter_web_plugins:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.0"
+ glob:
+ dependency: transitive
+ description:
+ name: glob
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
+ google_fonts:
+ dependency: "direct main"
+ description:
+ name: google_fonts
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ graphs:
+ dependency: transitive
+ description:
+ name: graphs
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.0"
+ html:
+ dependency: transitive
+ description:
+ name: html
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.14.0+3"
+ http:
+ dependency: transitive
+ description:
+ name: http
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.2"
+ http_multi_server:
+ dependency: transitive
+ description:
+ name: http_multi_server
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.2.0"
+ http_parser:
+ dependency: transitive
+ description:
+ name: http_parser
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.1.4"
+ intl:
+ dependency: "direct main"
+ description:
+ name: intl
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.16.1"
+ io:
+ dependency: transitive
+ description:
+ name: io
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.3.4"
+ js:
+ dependency: transitive
+ description:
+ name: js
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.6.2"
+ json_annotation:
+ dependency: "direct main"
+ description:
+ name: json_annotation
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.1"
+ json_serializable:
+ dependency: "direct dev"
+ description:
+ name: json_serializable
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.4.0"
+ logging:
+ dependency: transitive
+ description:
+ name: logging
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.11.4"
+ matcher:
+ dependency: transitive
+ description:
+ name: matcher
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.12.10-nullsafety"
+ meta:
+ dependency: transitive
+ description:
+ name: meta
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.0-nullsafety.2"
+ mime:
+ dependency: transitive
+ description:
+ name: mime
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.9.7"
+ mobx:
+ dependency: "direct main"
+ description:
+ name: mobx
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.1+2"
+ mobx_codegen:
+ dependency: "direct dev"
+ description:
+ name: mobx_codegen
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0+1"
+ mockito:
+ dependency: "direct dev"
+ description:
+ name: mockito
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "4.1.1"
+ node_interop:
+ dependency: transitive
+ description:
+ name: node_interop
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.1"
+ node_io:
+ dependency: transitive
+ description:
+ name: node_io
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.1"
+ package_config:
+ dependency: transitive
+ description:
+ name: package_config
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.9.3"
+ path:
+ dependency: transitive
+ description:
+ name: path
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.8.0-nullsafety"
+ path_provider:
+ dependency: transitive
+ description:
+ name: path_provider
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.6.14"
+ path_provider_linux:
+ dependency: transitive
+ description:
+ name: path_provider_linux
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.0.1+2"
+ path_provider_macos:
+ dependency: transitive
+ description:
+ name: path_provider_macos
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.0.4+3"
+ path_provider_platform_interface:
+ dependency: transitive
+ description:
+ name: path_provider_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.3"
+ pedantic:
+ dependency: transitive
+ description:
+ name: pedantic
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.9.2"
+ platform:
+ dependency: transitive
+ description:
+ name: platform
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.2.1"
+ plugin_platform_interface:
+ dependency: transitive
+ description:
+ name: plugin_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.2"
+ pool:
+ dependency: transitive
+ description:
+ name: pool
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.4.0"
+ process:
+ dependency: transitive
+ description:
+ name: process
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "3.0.13"
+ pub_semver:
+ dependency: transitive
+ description:
+ name: pub_semver
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.4.4"
+ pubspec_parse:
+ dependency: transitive
+ description:
+ name: pubspec_parse
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.5"
+ quiver:
+ dependency: transitive
+ description:
+ name: quiver
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.3"
+ shared_preferences:
+ dependency: "direct main"
+ description:
+ name: shared_preferences
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.5.10"
+ shared_preferences_linux:
+ dependency: transitive
+ description:
+ name: shared_preferences_linux
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.0.2+2"
+ shared_preferences_macos:
+ dependency: transitive
+ description:
+ name: shared_preferences_macos
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.0.1+10"
+ shared_preferences_platform_interface:
+ dependency: transitive
+ description:
+ name: shared_preferences_platform_interface
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.0.4"
+ shared_preferences_web:
+ dependency: transitive
+ description:
+ name: shared_preferences_web
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.2+7"
+ shelf:
+ dependency: transitive
+ description:
+ name: shelf
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.7.9"
+ shelf_web_socket:
+ dependency: transitive
+ description:
+ name: shelf_web_socket
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.3"
+ sky_engine:
+ dependency: transitive
+ description: flutter
+ source: sdk
+ version: "0.0.99"
+ source_gen:
+ dependency: transitive
+ description:
+ name: source_gen
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.9.6"
+ source_span:
+ dependency: transitive
+ description:
+ name: source_span
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.8.0-nullsafety"
+ stack_trace:
+ dependency: transitive
+ description:
+ name: stack_trace
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.10.0-nullsafety"
+ stream_channel:
+ dependency: transitive
+ description:
+ name: stream_channel
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0-nullsafety"
+ stream_transform:
+ dependency: transitive
+ description:
+ name: stream_transform
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0"
+ string_scanner:
+ dependency: transitive
+ description:
+ name: string_scanner
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0-nullsafety"
+ term_glyph:
+ dependency: transitive
+ description:
+ name: term_glyph
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.2.0-nullsafety"
+ test_api:
+ dependency: transitive
+ description:
+ name: test_api
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.2.19-nullsafety"
+ timing:
+ dependency: transitive
+ description:
+ name: timing
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.1+2"
+ typed_data:
+ dependency: transitive
+ description:
+ name: typed_data
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.3.0-nullsafety.2"
+ vector_math:
+ dependency: transitive
+ description:
+ name: vector_math
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.1.0-nullsafety.2"
+ watcher:
+ dependency: transitive
+ description:
+ name: watcher
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.9.7+15"
+ web_socket_channel:
+ dependency: transitive
+ description:
+ name: web_socket_channel
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "1.1.0"
+ xdg_directories:
+ dependency: transitive
+ description:
+ name: xdg_directories
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "0.1.2"
+ yaml:
+ dependency: transitive
+ description:
+ name: yaml
+ url: "https://pub.dartlang.org"
+ source: hosted
+ version: "2.2.1"
+sdks:
+ dart: ">=2.10.0-0.0.dev <2.10.0"
+ flutter: ">=1.17.0 <2.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
new file mode 100644
index 0000000..40afab2
--- /dev/null
+++ b/pubspec.yaml
@@ -0,0 +1,81 @@
+name: yshare
+description: A new Flutter project.
+
+# The following defines the version and build number for your application.
+# A version number is three numbers separated by dots, like 1.2.43
+# followed by an optional build number separated by a +.
+# Both the version and the builder number may be overridden in flutter
+# build by specifying --build-name and --build-number, respectively.
+# In Android, build-name is used as versionName while build-number used as versionCode.
+# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
+# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
+# Read more about iOS versioning at
+# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
+version: 1.0.0+1
+
+environment:
+ sdk: ">=2.2.2 <3.0.0"
+
+dependencies:
+ bot_toast: ^3.0.4
+ flutter:
+ sdk: flutter
+ intl: ^0.16.1
+ json_annotation: null
+ dio: ^3.0.10
+ flutter_mobx: ^1.1.0+2
+ mobx: ^1.2.1+2
+ flutter_modular: ^2.0.0+1
+ eva_icons_flutter: 2.0.1
+ google_fonts: 1.1.0
+ shared_preferences: ^0.5.10
+ # The following adds the Cupertino Icons font to your application.
+ # Use with the CupertinoIcons class for iOS style icons.
+dev_dependencies:
+ mockito: ^4.1.1
+ mobx_codegen: ^1.1.0+1
+ build_runner:
+ json_serializable:
+
+ flutter_test:
+ sdk: flutter
+
+# For information on the generic Dart part of this file, see the
+# following page: https://dart.dev/tools/pub/pubspec
+# The following section is specific to Flutter.
+flutter:
+ # The following line ensures that the Material Icons font is
+ # included with your application, so that you can use the icons in
+ # the material Icons class.
+ uses-material-design: true
+ # To add assets to your application, add an assets section, like this:
+ assets:
+ - assets/images/female_placeholder.jpg
+ - assets/images/male_placeholder.jpg
+ # An image asset can refer to one or more resolution-specific "variants", see
+ # https://flutter.dev/assets-and-images/#resolution-aware.
+ # For details regarding adding assets from package dependencies, see
+ # https://flutter.dev/assets-and-images/#from-packages
+ # To add custom fonts to your application, add a fonts section here,
+ # in this "flutter" section. Each entry in this list should have a
+ # "family" key with the font family name, and a "fonts" key with a
+ # list giving the asset and other descriptors for the font. For
+ # example:
+ # fonts:
+ # - family: Schyler
+ # fonts:
+ # - asset: fonts/Schyler-Regular.ttf
+ # - asset: fonts/Schyler-Italic.ttf
+ # style: italic
+ # - family: Trajan Pro
+ # fonts:
+ # - asset: fonts/TrajanPro.ttf
+ # - asset: fonts/TrajanPro_Bold.ttf
+ # weight: 700
+ #
+ # For details regarding fonts from package dependencies,
+ # see https://flutter.dev/custom-fonts/#from-packages
+
+scripts:
+ build: flutter pub run build_runner build --delete-conflicting-outputs
+
diff --git a/test/app/app/modules/film_page/film_page_page_test.dart b/test/app/app/modules/film_page/film_page_page_test.dart
new file mode 100644
index 0000000..2b69e3f
--- /dev/null
+++ b/test/app/app/modules/film_page/film_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('FilmPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(FilmPagePage(title: 'FilmPage')));
+ // final titleFinder = find.text('FilmPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/app_controller_test.dart b/test/app/app_controller_test.dart
new file mode 100644
index 0000000..691481b
--- /dev/null
+++ b/test/app/app_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // AppController app;
+ //
+ setUp(() {
+ // app = AppModule.to.get();
+ });
+
+ group('AppController Test', () {
+ // test("First Test", () {
+ // expect(app, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(app.value, equals(0));
+ // app.increment();
+ // expect(app.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/film_page/film_page_controller_test.dart b/test/app/film_page/film_page_controller_test.dart
new file mode 100644
index 0000000..62272b0
--- /dev/null
+++ b/test/app/film_page/film_page_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // FilmPageController filmpage;
+ //
+ setUp(() {
+ // filmpage = AppModule.to.get();
+ });
+
+ group('FilmPageController Test', () {
+ // test("First Test", () {
+ // expect(filmpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(filmpage.value, equals(0));
+ // filmpage.increment();
+ // expect(filmpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/film_page/film_page_page_test.dart b/test/app/film_page/film_page_page_test.dart
new file mode 100644
index 0000000..2b69e3f
--- /dev/null
+++ b/test/app/film_page/film_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('FilmPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(FilmPagePage(title: 'FilmPage')));
+ // final titleFinder = find.text('FilmPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/actor_page/actor_page_controller_test.dart b/test/app/modules/actor_page/actor_page_controller_test.dart
new file mode 100644
index 0000000..a743d9c
--- /dev/null
+++ b/test/app/modules/actor_page/actor_page_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // ActorPageController actorpage;
+ //
+ setUp(() {
+ // actorpage = AppModule.to.get();
+ });
+
+ group('ActorPageController Test', () {
+ // test("First Test", () {
+ // expect(actorpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(actorpage.value, equals(0));
+ // actorpage.increment();
+ // expect(actorpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/actor_page/actor_page_page_test.dart b/test/app/modules/actor_page/actor_page_page_test.dart
new file mode 100644
index 0000000..79e55e0
--- /dev/null
+++ b/test/app/modules/actor_page/actor_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('ActorPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(ActorPagePage(title: 'ActorPage')));
+ // final titleFinder = find.text('ActorPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/film_page/film_page_controller_test.dart b/test/app/modules/film_page/film_page_controller_test.dart
new file mode 100644
index 0000000..62272b0
--- /dev/null
+++ b/test/app/modules/film_page/film_page_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // FilmPageController filmpage;
+ //
+ setUp(() {
+ // filmpage = AppModule.to.get();
+ });
+
+ group('FilmPageController Test', () {
+ // test("First Test", () {
+ // expect(filmpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(filmpage.value, equals(0));
+ // filmpage.increment();
+ // expect(filmpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/film_page/film_page_page_test.dart b/test/app/modules/film_page/film_page_page_test.dart
new file mode 100644
index 0000000..2b69e3f
--- /dev/null
+++ b/test/app/modules/film_page/film_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('FilmPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(FilmPagePage(title: 'FilmPage')));
+ // final titleFinder = find.text('FilmPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/genre_page/genre_page_controller_test.dart b/test/app/modules/genre_page/genre_page_controller_test.dart
new file mode 100644
index 0000000..373c602
--- /dev/null
+++ b/test/app/modules/genre_page/genre_page_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // GenrePageController genrepage;
+ //
+ setUp(() {
+ // genrepage = AppModule.to.get();
+ });
+
+ group('GenrePageController Test', () {
+ // test("First Test", () {
+ // expect(genrepage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(genrepage.value, equals(0));
+ // genrepage.increment();
+ // expect(genrepage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/genre_page/genre_page_page_test.dart b/test/app/modules/genre_page/genre_page_page_test.dart
new file mode 100644
index 0000000..38e5a10
--- /dev/null
+++ b/test/app/modules/genre_page/genre_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('GenrePagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(GenrePagePage(title: 'GenrePage')));
+ // final titleFinder = find.text('GenrePage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/home/home_controller_test.dart b/test/app/modules/home/home_controller_test.dart
new file mode 100644
index 0000000..2bcfe69
--- /dev/null
+++ b/test/app/modules/home/home_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/modules/home/home_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(HomeModule());
+ // HomeController home;
+ //
+ setUp(() {
+ // home = HomeModule.to.get();
+ });
+
+ group('HomeController Test', () {
+ // test("First Test", () {
+ // expect(home, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(home.value, equals(0));
+ // home.increment();
+ // expect(home.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/home/home_page_test.dart b/test/app/modules/home/home_page_test.dart
new file mode 100644
index 0000000..3ec1fb2
--- /dev/null
+++ b/test/app/modules/home/home_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('HomePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(HomePage(title: 'Home')));
+ // final titleFinder = find.text('Home');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/popular_page/popular_page_controller_test.dart b/test/app/modules/popular_page/popular_page_controller_test.dart
new file mode 100644
index 0000000..2a45034
--- /dev/null
+++ b/test/app/modules/popular_page/popular_page_controller_test.dart
@@ -0,0 +1,25 @@
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:yshare/app/app_module.dart';
+
+void main() {
+ initModule(AppModule());
+ // PopularPageController popularpage;
+ //
+ setUp(() {
+ // popularpage = AppModule.to.get();
+ });
+
+ group('PopularPageController Test', () {
+ // test("First Test", () {
+ // expect(popularpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(popularpage.value, equals(0));
+ // popularpage.increment();
+ // expect(popularpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/popular_page/popular_page_page_test.dart b/test/app/modules/popular_page/popular_page_page_test.dart
new file mode 100644
index 0000000..d3c4c93
--- /dev/null
+++ b/test/app/modules/popular_page/popular_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('PopularPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(PopularPagePage(title: 'PopularPage')));
+ // final titleFinder = find.text('PopularPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/search_page/search_page_controller_test.dart b/test/app/modules/search_page/search_page_controller_test.dart
new file mode 100644
index 0000000..5cf4480
--- /dev/null
+++ b/test/app/modules/search_page/search_page_controller_test.dart
@@ -0,0 +1,24 @@
+import 'package:yshare/app/app_module.dart';
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ initModule(AppModule());
+ // SearchPageController searchpage;
+ //
+ setUp(() {
+ // searchpage = AppModule.to.get();
+ });
+
+ group('SearchPageController Test', () {
+ // test("First Test", () {
+ // expect(searchpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(searchpage.value, equals(0));
+ // searchpage.increment();
+ // expect(searchpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/search_page/search_page_page_test.dart b/test/app/modules/search_page/search_page_page_test.dart
new file mode 100644
index 0000000..786e475
--- /dev/null
+++ b/test/app/modules/search_page/search_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('SearchPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(SearchPagePage(title: 'SearchPage')));
+ // final titleFinder = find.text('SearchPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/top_rated_page/top_rated_page_controller_test.dart b/test/app/modules/top_rated_page/top_rated_page_controller_test.dart
new file mode 100644
index 0000000..90362fd
--- /dev/null
+++ b/test/app/modules/top_rated_page/top_rated_page_controller_test.dart
@@ -0,0 +1,25 @@
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:yshare/app/app_module.dart';
+
+void main() {
+ initModule(AppModule());
+ // TopRatedPageController topratedpage;
+ //
+ setUp(() {
+ // topratedpage = AppModule.to.get();
+ });
+
+ group('TopRatedPageController Test', () {
+ // test("First Test", () {
+ // expect(topratedpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(topratedpage.value, equals(0));
+ // topratedpage.increment();
+ // expect(topratedpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/top_rated_page/top_rated_page_page_test.dart b/test/app/modules/top_rated_page/top_rated_page_page_test.dart
new file mode 100644
index 0000000..e45fa86
--- /dev/null
+++ b/test/app/modules/top_rated_page/top_rated_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('TopRatedPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(TopRatedPagePage(title: 'TopRatedPage')));
+ // final titleFinder = find.text('TopRatedPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/test/app/modules/trending_page/trending_page_controller_test.dart b/test/app/modules/trending_page/trending_page_controller_test.dart
new file mode 100644
index 0000000..47c5e5e
--- /dev/null
+++ b/test/app/modules/trending_page/trending_page_controller_test.dart
@@ -0,0 +1,25 @@
+import 'package:flutter_modular/flutter_modular_test.dart';
+import 'package:flutter_test/flutter_test.dart';
+
+import 'package:yshare/app/app_module.dart';
+
+void main() {
+ initModule(AppModule());
+ // TrendingPageController trendingpage;
+ //
+ setUp(() {
+ // trendingpage = AppModule.to.get();
+ });
+
+ group('TrendingPageController Test', () {
+ // test("First Test", () {
+ // expect(trendingpage, isInstanceOf());
+ // });
+
+ // test("Set Value", () {
+ // expect(trendingpage.value, equals(0));
+ // trendingpage.increment();
+ // expect(trendingpage.value, equals(1));
+ // });
+ });
+}
diff --git a/test/app/modules/trending_page/trending_page_page_test.dart b/test/app/modules/trending_page/trending_page_page_test.dart
new file mode 100644
index 0000000..55a4f68
--- /dev/null
+++ b/test/app/modules/trending_page/trending_page_page_test.dart
@@ -0,0 +1,9 @@
+import 'package:flutter_test/flutter_test.dart';
+
+void main() {
+ testWidgets('TrendingPagePage has title', (tester) async {
+ // await tester.pumpWidget(buildTestableWidget(TrendingPagePage(title: 'TrendingPage')));
+ // final titleFinder = find.text('TrendingPage');
+ // expect(titleFinder, findsOneWidget);
+ });
+}
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000..310c7ad
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+ yshare
+
+
+
+
+