├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── drawable-xhdpi │ │ │ ├── sort.png │ │ │ ├── star.png │ │ │ ├── share.png │ │ │ ├── arrow_left.png │ │ │ └── star_outline.png │ │ ├── drawable-xxhdpi │ │ │ ├── share.png │ │ │ ├── sort.png │ │ │ ├── star.png │ │ │ ├── arrow_left.png │ │ │ └── star_outline.png │ │ ├── mipmap-hdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ │ └── ic_launcher.png │ │ ├── values-w1280dp │ │ │ └── dimens.xml │ │ ├── values-w840dp │ │ │ └── dimens.xml │ │ ├── mipmap-xxhdpi │ │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ │ └── ic_launcher.png │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── styles.xml │ │ │ ├── strings.xml │ │ │ └── dimens.xml │ │ ├── layout │ │ │ ├── activity_review.xml │ │ │ ├── activity_movie_details.xml │ │ │ ├── movie_list_item.xml │ │ │ ├── activity_movies.xml │ │ │ ├── video.xml │ │ │ ├── fragment_movies.xml │ │ │ ├── fragment_movie_details.xml │ │ │ ├── review.xml │ │ │ ├── fragment_review.xml │ │ │ └── fragment_movie_details_content.xml │ │ ├── values-v21 │ │ │ └── styles.xml │ │ ├── drawable │ │ │ └── divider_margin_default.xml │ │ ├── values-w820dp │ │ │ └── dimens.xml │ │ ├── values-w600dp │ │ │ └── dimens.xml │ │ ├── menu │ │ │ ├── menu_movie_details.xml │ │ │ └── menu_movies.xml │ │ └── layout-w600dp │ │ │ └── activity_movies.xml │ │ ├── java │ │ └── me │ │ │ └── vickychijwani │ │ │ └── popularmovies │ │ │ ├── event │ │ │ ├── events │ │ │ │ ├── CancelAllEvent.java │ │ │ │ ├── ApiEvent.java │ │ │ │ ├── LoadMovieEvent.java │ │ │ │ ├── UpdateMovieEvent.java │ │ │ │ ├── MovieLoadedEvent.java │ │ │ │ ├── MovieUpdatedEvent.java │ │ │ │ ├── LoadMoviesEvent.java │ │ │ │ ├── ApiErrorEvent.java │ │ │ │ └── MoviesLoadedEvent.java │ │ │ └── DataBusProvider.java │ │ │ ├── entity │ │ │ ├── RealmListParcelConverter.java │ │ │ ├── MovieResults.java │ │ │ ├── Results.java │ │ │ ├── Review.java │ │ │ ├── Video.java │ │ │ └── Movie.java │ │ │ ├── ui │ │ │ ├── BundleKeys.java │ │ │ ├── BaseFragment.java │ │ │ ├── MovieDetailsActivity.java │ │ │ ├── ReviewActivity.java │ │ │ ├── ReviewFragment.java │ │ │ ├── BaseActivity.java │ │ │ ├── PaletteTransformation.java │ │ │ ├── MoviesAdapter.java │ │ │ ├── MoviesActivity.java │ │ │ ├── MoviesFragment.java │ │ │ └── MovieDetailsFragment.java │ │ │ ├── model │ │ │ ├── RealmExclusionStrategy.java │ │ │ ├── MovieDBApiService.java │ │ │ ├── VideoRealmListDeserializer.java │ │ │ ├── ReviewRealmListDeserializer.java │ │ │ ├── DateDeserializer.java │ │ │ ├── Database.java │ │ │ └── Model.java │ │ │ ├── util │ │ │ ├── DeviceUtil.java │ │ │ ├── TMDbUtil.java │ │ │ └── AppUtil.java │ │ │ └── PopularMoviesApplication.java │ │ └── AndroidManifest.xml ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── demo.gif ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── README.md ├── gradle.properties ├── LICENSE ├── gradlew.bat ├── gradlew └── fragment_movie_details.xml /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/demo.gif -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xhdpi/sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xhdpi/star.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xhdpi/share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/share.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xxhdpi/share.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xxhdpi/sort.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xxhdpi/star.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w1280dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 450dp 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values-w840dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 300dp 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xhdpi/arrow_left.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/arrow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xxhdpi/arrow_left.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/star_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xhdpi/star_outline.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/star_outline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vickychijwani/udacity-p1-p2-popular-movies/HEAD/app/src/main/res/drawable-xxhdpi/star_outline.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | NOTES.md 10 | /.idea/ 11 | /api_key.properties 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/CancelAllEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | public class CancelAllEvent implements ApiEvent { 4 | } 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # udacity-p1-p2-popular-movies 2 | 3 | **This app uses a simple event-based architecture, described in this blog post: http://vickychijwani.me/udacity-android-nanodegree-weeks-3-7/** 4 | 5 | ![Demo GIF](/demo.gif) 6 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/ApiEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | // marker interface for all API call-related events 4 | public interface ApiEvent { 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_review.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-v21/styles.xml: -------------------------------------------------------------------------------- 1 | > 2 | 3 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/divider_margin_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/LoadMovieEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | public class LoadMovieEvent implements ApiEvent { 4 | 5 | public final int id; 6 | 7 | public LoadMovieEvent(int id) { 8 | this.id = id; 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/UpdateMovieEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | import me.vickychijwani.popularmovies.entity.Movie; 4 | 5 | public class UpdateMovieEvent { 6 | 7 | public final Movie movie; 8 | 9 | public UpdateMovieEvent(Movie movie) { 10 | this.movie = movie; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values-w600dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 150dp 4 | 5 | 6 | 150 7 | 75 8 | 0 9 | true 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/MovieLoadedEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import me.vickychijwani.popularmovies.entity.Movie; 6 | 7 | public class MovieLoadedEvent { 8 | 9 | public final Movie movie; 10 | 11 | public MovieLoadedEvent(@NonNull Movie movie) { 12 | this.movie = movie; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_movie_details.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/MovieUpdatedEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | import android.support.annotation.NonNull; 4 | 5 | import me.vickychijwani.popularmovies.entity.Movie; 6 | 7 | public final class MovieUpdatedEvent { 8 | 9 | public final Movie movie; 10 | 11 | public MovieUpdatedEvent(@NonNull Movie movie) { 12 | this.movie = movie; 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/LoadMoviesEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | import me.vickychijwani.popularmovies.entity.MovieResults; 4 | 5 | public final class LoadMoviesEvent implements ApiEvent { 6 | 7 | public final MovieResults.SortCriteria sortCriteria; 8 | 9 | public LoadMoviesEvent(MovieResults.SortCriteria sortCriteria) { 10 | this.sortCriteria = sortCriteria; 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/res/menu/menu_movie_details.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/ApiErrorEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | // represents a network / API related error 4 | public final class ApiErrorEvent implements ApiEvent { 5 | 6 | public final ApiEvent sourceEvent; 7 | public final Throwable throwable; 8 | 9 | public ApiErrorEvent(ApiEvent sourceEvent, Throwable throwable) { 10 | this.sourceEvent = sourceEvent; 11 | this.throwable = throwable; 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/entity/RealmListParcelConverter.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.entity; 2 | 3 | import org.parceler.converter.CollectionParcelConverter; 4 | 5 | import io.realm.RealmList; 6 | import io.realm.RealmObject; 7 | 8 | abstract class RealmListParcelConverter 9 | extends CollectionParcelConverter> { 10 | 11 | @Override 12 | public RealmList createCollection() { 13 | return new RealmList<>(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/ui/BundleKeys.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.ui; 2 | 3 | public abstract class BundleKeys { 4 | 5 | public static final String MOVIE = "movie"; 6 | public static final String REVIEW = "review"; 7 | 8 | public static final String TWO_PANE = "two_pane"; 9 | 10 | public static final String COLOR_PRIMARY = "color_primary"; 11 | public static final String COLOR_PRIMARY_DARK = "color_primary_dark"; 12 | public static final String COLOR_TEXT_TITLE = "color_text_title"; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/movie_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_movies.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/model/RealmExclusionStrategy.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.model; 2 | 3 | import com.google.gson.ExclusionStrategy; 4 | import com.google.gson.FieldAttributes; 5 | 6 | import io.realm.RealmObject; 7 | 8 | class RealmExclusionStrategy implements ExclusionStrategy { 9 | 10 | @Override 11 | public boolean shouldSkipField(FieldAttributes f) { 12 | return f.getDeclaringClass().equals(RealmObject.class); 13 | } 14 | 15 | @Override 16 | public boolean shouldSkipClass(Class clazz) { 17 | return false; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/entity/MovieResults.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.entity; 2 | 3 | public class MovieResults extends Results { 4 | 5 | public enum SortCriteria { 6 | POPULARITY("popularity.desc"), RATING("vote_average.desc"), FAVORITES("favorites"); 7 | public final String str; 8 | SortCriteria(String str) { 9 | this.str = str; 10 | } 11 | public int getId() { 12 | return this.str.hashCode(); 13 | } 14 | public String toString() { 15 | return this.str; 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/res/layout/video.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/event/events/MoviesLoadedEvent.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.event.events; 2 | 3 | import java.util.List; 4 | 5 | import me.vickychijwani.popularmovies.entity.Movie; 6 | import me.vickychijwani.popularmovies.entity.MovieResults; 7 | 8 | public final class MoviesLoadedEvent { 9 | 10 | public final List movies; 11 | public final MovieResults.SortCriteria sortCriteria; 12 | 13 | public MoviesLoadedEvent(List movies, MovieResults.SortCriteria sortCriteria) { 14 | this.movies = movies; 15 | this.sortCriteria = sortCriteria; 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/util/DeviceUtil.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.util; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.util.DisplayMetrics; 6 | import android.view.WindowManager; 7 | 8 | public class DeviceUtil { 9 | 10 | public static int getScreenWidth(@NonNull Context context) { 11 | DisplayMetrics displayMetrics = new DisplayMetrics(); 12 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 13 | wm.getDefaultDisplay().getMetrics(displayMetrics); 14 | return displayMetrics.widthPixels; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/model/MovieDBApiService.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.model; 2 | 3 | import me.vickychijwani.popularmovies.entity.Movie; 4 | import me.vickychijwani.popularmovies.entity.MovieResults; 5 | import retrofit.Call; 6 | import retrofit.http.GET; 7 | import retrofit.http.Path; 8 | import retrofit.http.Query; 9 | 10 | interface MovieDBApiService { 11 | 12 | @GET("discover/movie?vote_count.gte=250") 13 | Call fetchMovies(@Query("api_key") String apiKey, @Query("sort_by") String sortBy); 14 | 15 | @GET("movie/{id}?append_to_response=videos,reviews") 16 | Call fetchMovie(@Path("id") int id, @Query("api_key") String apiKey); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /opt/android-sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/java/me/vickychijwani/popularmovies/entity/Results.java: -------------------------------------------------------------------------------- 1 | package me.vickychijwani.popularmovies.entity; 2 | 3 | import java.util.List; 4 | 5 | // wrapper class needed by Retrofit to parse API responses from the Movie DB API 6 | // response is of the form: { "page": 1, "results": [...] } 7 | class Results { 8 | 9 | private int page; 10 | private List results; 11 | 12 | public int getPage() { 13 | return page; 14 | } 15 | 16 | public void setPage(int page) { 17 | this.page = page; 18 | } 19 | 20 | public List getResults() { 21 | return results; 22 | } 23 | 24 | public void setResults(List results) { 25 | this.results = results; 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 15 | 16 |