diff --git a/DesafioAppProva/.gitignore b/DesafioAppProva/.gitignore
new file mode 100644
index 00000000..0a002ee4
--- /dev/null
+++ b/DesafioAppProva/.gitignore
@@ -0,0 +1,11 @@
+*.iml
+.gradle
+/local.properties\
+*/.idea
+gradlew.bat
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+libs/
+src/main/res/drawable/
diff --git a/DesafioAppProva/app/.gitignore b/DesafioAppProva/app/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/DesafioAppProva/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/DesafioAppProva/app/build.gradle b/DesafioAppProva/app/build.gradle
new file mode 100644
index 00000000..0d00272c
--- /dev/null
+++ b/DesafioAppProva/app/build.gradle
@@ -0,0 +1,67 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 26
+ buildToolsVersion "26.0.2"
+ defaultConfig {
+ applicationId "com.felipemiranda.desafioappprova"
+ minSdkVersion 19
+ targetSdkVersion 26
+ versionCode 1
+ versionName "1.0"
+ testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
+ vectorDrawables.useSupportLibrary true
+ }
+ buildTypes {
+ release {
+ minifyEnabled true
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+def SupportLibrary = '26.1.0'
+def ButterKnife = '8.8.1'
+def JUNIT = '4.12'
+def EspressoCore = '3.0.1'
+def Glide = '4.2.0'
+def Gson = '2.8.2'
+def GsonConverter = '2.3.0'
+def Retrofit = '2.3.0'
+def MultiDex = '1.0.2'
+def Okhttp = '3.8.1'
+def OkhttpInterceptor = '3.8.1'
+def Fresco = '1.3.0'
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "com.android.support:appcompat-v7:${SupportLibrary}"
+ implementation "com.android.support:support-v4:${SupportLibrary}"
+ implementation "com.android.support:design:${SupportLibrary}"
+ implementation "com.android.support:support-v4:${SupportLibrary}"
+ implementation "com.android.support:multidex:${MultiDex}"
+
+ compile "com.jakewharton:butterknife:${ButterKnife}"
+ annotationProcessor "com.jakewharton:butterknife-compiler:${ButterKnife}"
+
+ compile "com.google.code.gson:gson:${Gson}"
+ compile "com.squareup.retrofit2:converter-gson:${GsonConverter}"
+
+ compile "com.github.bumptech.glide:glide:${Glide}"
+
+ compile "com.squareup.retrofit2:retrofit:${Retrofit}"
+
+ compile "com.squareup.okhttp3:okhttp:${Okhttp}"
+ compile "com.squareup.okhttp3:logging-interceptor:${OkhttpInterceptor}"
+
+ compile "com.facebook.fresco:fresco:${Fresco}"
+
+ testImplementation "junit:junit:${JUNIT}"
+ androidTestImplementation("com.android.support.test.espresso:espresso-core:${EspressoCore}", {
+ exclude group: 'com.android.support', module: 'support-annotations'
+ })
+}
\ No newline at end of file
diff --git a/DesafioAppProva/app/proguard-rules.pro b/DesafioAppProva/app/proguard-rules.pro
new file mode 100644
index 00000000..c06e4243
--- /dev/null
+++ b/DesafioAppProva/app/proguard-rules.pro
@@ -0,0 +1,25 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /Users/felipemiranda/Library/Android/sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/DesafioAppProva/app/src/androidTest/java/com/felipemiranda/desafioappprova/ExampleInstrumentedTest.java b/DesafioAppProva/app/src/androidTest/java/com/felipemiranda/desafioappprova/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..7ac77591
--- /dev/null
+++ b/DesafioAppProva/app/src/androidTest/java/com/felipemiranda/desafioappprova/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.felipemiranda.desafioappprova;
+
+import android.content.Context;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumentation test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() throws Exception {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getTargetContext();
+
+ assertEquals("com.felipemiranda.desafioappprova", appContext.getPackageName());
+ }
+}
diff --git a/DesafioAppProva/app/src/main/AndroidManifest.xml b/DesafioAppProva/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..e8d35f69
--- /dev/null
+++ b/DesafioAppProva/app/src/main/AndroidManifest.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/AppProvaApplication.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/AppProvaApplication.java
new file mode 100644
index 00000000..8083aae1
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/AppProvaApplication.java
@@ -0,0 +1,41 @@
+package com.felipemiranda.desafioappprova;
+
+import android.app.Application;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.support.multidex.MultiDex;
+
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.felipemiranda.desafioappprova.network.InternetConnection;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class AppProvaApplication extends Application implements InternetConnection {
+
+ private static AppProvaApplication mInstance;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ Fresco.initialize(this);
+
+ MultiDex.install(this);
+
+ mInstance = this;
+ }
+
+ public static AppProvaApplication getInstance() {
+ return mInstance;
+ }
+
+ @Override
+ public boolean isOnline() {
+ ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+ NetworkInfo netInfo = cm != null ? cm.getActiveNetworkInfo() : null;
+ return netInfo != null && netInfo.isConnectedOrConnecting();
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/SplashActivity.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/SplashActivity.java
new file mode 100644
index 00000000..dbc4f723
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/SplashActivity.java
@@ -0,0 +1,37 @@
+package com.felipemiranda.desafioappprova;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.ImageView;
+
+import com.felipemiranda.desafioappprova.ui.home.HomeActivity;
+import com.felipemiranda.desafioappprova.utils.Utils;
+
+import butterknife.BindView;
+
+/**
+ * Created by felipemiranda on 27/10/17.
+ */
+
+public class SplashActivity extends AppCompatActivity {
+
+ private static final long DELAY = 1500;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_splash);
+
+ new Handler().postDelayed(this::openHomeActivity, DELAY);
+ }
+
+ private void openHomeActivity() {
+ Intent intent = new Intent(this, HomeActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ startActivity(intent);
+ overridePendingTransition(0, 0);
+ finish();
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Item.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Item.java
new file mode 100644
index 00000000..ec811455
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Item.java
@@ -0,0 +1,81 @@
+package com.felipemiranda.desafioappprova.model;
+
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class Item implements Serializable {
+
+ private String name;
+ @SerializedName("full_name")
+ private String full_name;
+ private Owner owner;
+ private String description;
+ @SerializedName("stargazers_count")
+ private Integer stargazers_count;
+ @SerializedName("forks_count")
+ private Integer forks_count;
+ @SerializedName("pulls_url")
+ private String pulls_url;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getFull_name() {
+ return full_name;
+ }
+
+ public void setFull_name(String full_name) {
+ this.full_name = full_name;
+ }
+
+ public Owner getOwner() {
+ return owner;
+ }
+
+ public void setOwner(Owner owner) {
+ this.owner = owner;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Integer getStargazers_count() {
+ return stargazers_count;
+ }
+
+ public void setStargazers_count(Integer stargazers_count) {
+ this.stargazers_count = stargazers_count;
+ }
+
+ public Integer getForks_count() {
+ return forks_count;
+ }
+
+ public void setForks_count(Integer forks_count) {
+ this.forks_count = forks_count;
+ }
+
+ public String getPulls_url() {
+ return pulls_url;
+ }
+
+ public void setPulls_url(String pulls_url) {
+ this.pulls_url = pulls_url;
+ }
+}
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/ItemDetail.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/ItemDetail.java
new file mode 100644
index 00000000..548ac5c1
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/ItemDetail.java
@@ -0,0 +1,60 @@
+package com.felipemiranda.desafioappprova.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+/**
+ * Created by felipemiranda on 27/10/17.
+ */
+
+public class ItemDetail implements Serializable {
+
+ private String title;
+ private Owner user;
+ @SerializedName("created_at")
+ private String created_at;
+ private String body;
+ @SerializedName("html_url")
+ private String html_url;
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Owner getUser() {
+ return user;
+ }
+
+ public void setUser(Owner user) {
+ this.user = user;
+ }
+
+ public String getCreated_at() {
+ return created_at;
+ }
+
+ public void setCreated_at(String created_at) {
+ this.created_at = created_at;
+ }
+
+ public String getBody() {
+ return body;
+ }
+
+ public void setBody(String body) {
+ this.body = body;
+ }
+
+ public String getHtml_url() {
+ return html_url;
+ }
+
+ public void setHtml_url(String html_url) {
+ this.html_url = html_url;
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Owner.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Owner.java
new file mode 100644
index 00000000..7899ac9a
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/Owner.java
@@ -0,0 +1,60 @@
+package com.felipemiranda.desafioappprova.model;
+
+import com.google.gson.annotations.SerializedName;
+
+import java.io.Serializable;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class Owner implements Serializable {
+
+ private String login;
+ private Integer id;
+ @SerializedName("avatar_url")
+ private String avatar_url;
+ @SerializedName("gravatar_id")
+ private String gravatar_id;
+ private String url;
+
+ public String getLogin() {
+ return login;
+ }
+
+ public void setLogin(String login) {
+ this.login = login;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getAvatar_url() {
+ return avatar_url;
+ }
+
+ public void setAvatar_url(String avatar_url) {
+ this.avatar_url = avatar_url;
+ }
+
+ public String getGravatar_id() {
+ return gravatar_id;
+ }
+
+ public void setGravatar_id(String gravatar_id) {
+ this.gravatar_id = gravatar_id;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/GenericErrorResponse.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/GenericErrorResponse.java
new file mode 100644
index 00000000..40871ea4
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/GenericErrorResponse.java
@@ -0,0 +1,75 @@
+package com.felipemiranda.desafioappprova.model.response;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.google.gson.Gson;
+
+import okhttp3.ResponseBody;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class GenericErrorResponse implements Parcelable {
+
+ private String message;
+
+ public GenericErrorResponse() {}
+
+ protected GenericErrorResponse(Parcel in) {
+ message = in.readString();
+ }
+
+ public static final Creator CREATOR = new Creator() {
+ @Override
+ public GenericErrorResponse createFromParcel(Parcel in) {
+ return new GenericErrorResponse(in);
+ }
+
+ @Override
+ public GenericErrorResponse[] newArray(int size) {
+ return new GenericErrorResponse[size];
+ }
+ };
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public static GenericErrorResponse getResponseError(final ResponseBody responseBody) {
+ GenericErrorResponse error;
+ try {
+ error = new Gson().fromJson(responseBody.string(), GenericErrorResponse.class);
+ } catch (Exception e) {
+ error = getExceptionError();
+ }
+ return error;
+ }
+
+ public static GenericErrorResponse getExceptionError() {
+ final GenericErrorResponse error = new GenericErrorResponse();
+ error.setMessage("Desculpe-nos, não foi possível processar a sua solicitação no momento.");
+ return error;
+ }
+
+ public static GenericErrorResponse getConnectionError() {
+ final GenericErrorResponse error = new GenericErrorResponse();
+ error.setMessage("Você não está conectado, por favor tente novamente mais tarde.");
+ return error;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeString(message);
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/SearchResponse.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/SearchResponse.java
new file mode 100644
index 00000000..e1532a68
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/model/response/SearchResponse.java
@@ -0,0 +1,41 @@
+package com.felipemiranda.desafioappprova.model.response;
+
+import com.felipemiranda.desafioappprova.model.Item;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class SearchResponse implements Serializable {
+
+ private Integer totalCount;
+ private Boolean incompleteResults;
+ private ArrayList- items;
+
+ public Integer getTotalCount() {
+ return totalCount;
+ }
+
+ public void setTotalCount(Integer totalCount) {
+ this.totalCount = totalCount;
+ }
+
+ public Boolean getIncompleteResults() {
+ return incompleteResults;
+ }
+
+ public void setIncompleteResults(Boolean incompleteResults) {
+ this.incompleteResults = incompleteResults;
+ }
+
+ public ArrayList
- getItems() {
+ return items;
+ }
+
+ public void setItems(ArrayList
- items) {
+ this.items = items;
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/ApiCreator.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/ApiCreator.java
new file mode 100644
index 00000000..a5a1b1d6
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/ApiCreator.java
@@ -0,0 +1,26 @@
+package com.felipemiranda.desafioappprova.network;
+
+import okhttp3.OkHttpClient;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class ApiCreator {
+
+ private static final String API_BASE_URL = "https://api.github.com/";
+
+ private static OkHttpClient httpClient = NetworkSetup.getClient();
+
+ private static Retrofit.Builder builder = new Retrofit.Builder()
+ .baseUrl(API_BASE_URL)
+ .addConverterFactory(GsonConverterFactory.create());
+
+
+ public static
S createService(Class serviceClass) {
+ Retrofit retrofit = builder.client(httpClient).build();
+ return retrofit.create(serviceClass);
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/InternetConnection.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/InternetConnection.java
new file mode 100644
index 00000000..5329897a
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/InternetConnection.java
@@ -0,0 +1,9 @@
+package com.felipemiranda.desafioappprova.network;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public interface InternetConnection {
+ boolean isOnline();
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/NetworkSetup.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/NetworkSetup.java
new file mode 100644
index 00000000..cb5a2fde
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/NetworkSetup.java
@@ -0,0 +1,37 @@
+package com.felipemiranda.desafioappprova.network;
+
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Dispatcher;
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class NetworkSetup {
+
+ public static OkHttpClient getClient() {
+ return new OkHttpClient()
+ .newBuilder()
+ .addInterceptor(getLoggingCapableHttpClient())
+ .dispatcher(buildDispatcher())
+ .connectTimeout(60, TimeUnit.SECONDS)
+ .readTimeout(60, TimeUnit.SECONDS)
+ .build();
+ }
+
+ private static HttpLoggingInterceptor getLoggingCapableHttpClient() {
+ HttpLoggingInterceptor mLogging = new HttpLoggingInterceptor();
+ mLogging.setLevel(HttpLoggingInterceptor.Level.BODY);
+
+ return mLogging;
+ }
+
+ private static Dispatcher buildDispatcher() {
+ Dispatcher dispatcher = new Dispatcher();
+ dispatcher.setMaxRequestsPerHost(20);
+ return dispatcher;
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/RestCallback.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/RestCallback.java
new file mode 100644
index 00000000..8ef4a470
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/RestCallback.java
@@ -0,0 +1,40 @@
+package com.felipemiranda.desafioappprova.network;
+
+import com.felipemiranda.desafioappprova.AppProvaApplication;
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public abstract class RestCallback implements Callback {
+
+ public abstract void onSuccess(T response);
+
+ public abstract void onError(GenericErrorResponse error);
+
+ @Override
+ public void onResponse(Call call, Response response) {
+ if (response.isSuccessful())
+ onSuccess(response.body());
+ else {
+ GenericErrorResponse error = GenericErrorResponse.getResponseError(response.errorBody());
+ if (error == null || error.getMessage() == null)
+ error = GenericErrorResponse.getExceptionError();
+
+ onError(error);
+ }
+ }
+
+ @Override
+ public void onFailure(Call call, Throwable t) {
+ if (!AppProvaApplication.getInstance().isOnline())
+ onError(GenericErrorResponse.getConnectionError());
+ else
+ onError(GenericErrorResponse.getExceptionError());
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/api/SearchApi.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/api/SearchApi.java
new file mode 100644
index 00000000..6e41915e
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/network/api/SearchApi.java
@@ -0,0 +1,23 @@
+package com.felipemiranda.desafioappprova.network.api;
+
+import com.felipemiranda.desafioappprova.model.ItemDetail;
+import com.felipemiranda.desafioappprova.model.response.SearchResponse;
+
+import java.util.ArrayList;
+
+import retrofit2.Call;
+import retrofit2.http.GET;
+import retrofit2.http.Url;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public interface SearchApi {
+
+ @GET("search/repositories?q=language:Java&sort=stars&page=1")
+ Call requestSearch();
+
+ @GET
+ Call> requestItemDetail(@Url String url);
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeActivity.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeActivity.java
new file mode 100644
index 00000000..3b609f43
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeActivity.java
@@ -0,0 +1,60 @@
+package com.felipemiranda.desafioappprova.ui.home;
+
+import android.support.annotation.AnimRes;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentTransaction;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ProgressBar;
+
+import com.felipemiranda.desafioappprova.R;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class HomeActivity extends AppCompatActivity {
+
+ @BindView(R.id.progress)
+ ProgressBar progressBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_home);
+
+ setTitle(getString(R.string.github_java));
+
+ ButterKnife.bind(this);
+
+ getSupportFragmentManager()
+ .beginTransaction()
+ .add(R.id.content, HomeFragment.newInstance(), HomeFragment.TAG)
+ .commit();
+ }
+
+ public void showLoading(){
+ progressBar.setVisibility(View.VISIBLE);
+ }
+
+ public void hideLoading(){
+ progressBar.setVisibility(View.GONE);
+ }
+
+ public void addFragmentDefaultAnim(Fragment fragment, String tag, String tagBackStack) {
+ addFragment(fragment, tag, R.anim.slide_from_right, R.anim.slide_to_left, R.anim.slide_from_left, R.anim.slide_to_right, tagBackStack);
+ }
+
+ private void addFragment(Fragment fragment, String tag,
+ @AnimRes int enter, @AnimRes int exit,
+ @AnimRes int popEnter, @AnimRes int popExit,
+ String tagBackStack) {
+ FragmentTransaction transaction = getSupportFragmentManager()
+ .beginTransaction();
+
+ transaction.setCustomAnimations(enter, exit, popEnter, popExit);
+ transaction.replace(R.id.content, fragment, tag);
+ transaction.addToBackStack(tagBackStack);
+ transaction.commit();
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeFragment.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeFragment.java
new file mode 100644
index 00000000..c7078558
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeFragment.java
@@ -0,0 +1,80 @@
+package com.felipemiranda.desafioappprova.ui.home;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.felipemiranda.desafioappprova.R;
+import com.felipemiranda.desafioappprova.model.response.SearchResponse;
+import com.felipemiranda.desafioappprova.ui.home.adapter.ListItemsAdapter;
+import com.felipemiranda.desafioappprova.ui.main.BaseFragment;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingPresenter;
+import com.felipemiranda.desafioappprova.ui.search.ItemDetailFragment;
+import com.felipemiranda.desafioappprova.utils.Utils;
+
+import butterknife.BindView;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class HomeFragment extends BaseFragment implements HomeView, ListItemsAdapter.OnClickItem {
+
+ public static final String TAG = HomeFragment.class.getSimpleName();
+
+ @BindView(R.id.rv_list_items)
+ RecyclerView rvListItems;
+
+ private HomePresenter mHomePresenter;
+
+ public static HomeFragment newInstance() {
+ Bundle args = new Bundle();
+ HomeFragment fragment = new HomeFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public View onCreateViewBinder(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_home, container, false);
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mHomePresenter = new HomePresenter();
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ getActivity().setTitle(getString(R.string.github_java));
+ mHomePresenter.requestSearch();
+ }
+
+ @Override
+ public BaseLoadingPresenter getPresenter() {
+ return mHomePresenter;
+ }
+
+ @Override
+ public void successSearch(SearchResponse response) {
+ if (response != null && response.getItems() != null && !response.getItems().isEmpty()) {
+ ListItemsAdapter listItemsAdapter = new ListItemsAdapter(response.getItems(), this);
+ rvListItems.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
+ rvListItems.setAdapter(listItemsAdapter);
+ Utils.recyclerViewAnimationEntrance(rvListItems);
+ }
+ }
+
+ @Override
+ public void onClickItem(String url, String name) {
+ setFragmentContent(ItemDetailFragment.newInstance(url, name), TAG);
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomePresenter.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomePresenter.java
new file mode 100644
index 00000000..a1ddcae1
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomePresenter.java
@@ -0,0 +1,38 @@
+package com.felipemiranda.desafioappprova.ui.home;
+
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+import com.felipemiranda.desafioappprova.model.response.SearchResponse;
+import com.felipemiranda.desafioappprova.network.ApiCreator;
+import com.felipemiranda.desafioappprova.network.RestCallback;
+import com.felipemiranda.desafioappprova.network.api.SearchApi;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingPresenter;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class HomePresenter extends BaseLoadingPresenter {
+
+ @Override
+ public void bindView(HomeView view) {
+ this.mView = view;
+ }
+
+ public void requestSearch() {
+ addRequest(ApiCreator
+ .createService(SearchApi.class)
+ .requestSearch(),
+
+ new RestCallback() {
+ @Override
+ public void onSuccess(SearchResponse response) {
+ mView.successSearch(response);
+ }
+
+ @Override
+ public void onError(GenericErrorResponse error) {
+ mView.notifyError(error);
+ }
+ });
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeView.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeView.java
new file mode 100644
index 00000000..b5468a75
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/HomeView.java
@@ -0,0 +1,13 @@
+package com.felipemiranda.desafioappprova.ui.home;
+
+import com.felipemiranda.desafioappprova.model.response.SearchResponse;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingView;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public interface HomeView extends BaseLoadingView {
+
+ void successSearch(SearchResponse response);
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/adapter/ListItemsAdapter.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/adapter/ListItemsAdapter.java
new file mode 100644
index 00000000..90fde9ba
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/home/adapter/ListItemsAdapter.java
@@ -0,0 +1,115 @@
+package com.felipemiranda.desafioappprova.ui.home.adapter;
+
+import android.net.Uri;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.drawee.view.SimpleDraweeView;
+import com.facebook.imagepipeline.common.ResizeOptions;
+import com.facebook.imagepipeline.request.ImageRequest;
+import com.facebook.imagepipeline.request.ImageRequestBuilder;
+import com.felipemiranda.desafioappprova.R;
+import com.felipemiranda.desafioappprova.model.Item;
+
+import java.util.ArrayList;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class ListItemsAdapter extends RecyclerView.Adapter {
+
+ private ArrayList- mItems;
+ private OnClickItem mOnClickItem;
+
+ public ListItemsAdapter(ArrayList
- mSearchResponses, OnClickItem onClickItem) {
+ this.mItems = mSearchResponses;
+ this.mOnClickItem = onClickItem;
+ }
+
+ public interface OnClickItem {
+ void onClickItem(String url, String name);
+ }
+
+ @Override
+ public AppViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);
+ return new ItemViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(AppViewHolder holder, int position) {
+ final Item item = mItems.get(holder.getAdapterPosition());
+ ItemViewHolder holderItem = (ItemViewHolder) holder;
+
+ holderItem.item.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mOnClickItem.onClickItem(item.getPulls_url(), item.getName());
+ }
+ });
+
+ holderItem.tvName.setText(item.getName() != null ? item.getName() : "");
+ holderItem.tvDescription.setText(item.getDescription() != null ? item.getDescription() : "");
+ holderItem.tvFork.setText(item.getForks_count() != null ? String.valueOf(item.getForks_count()) : "0");
+ holderItem.tvStar.setText(item.getStargazers_count() != null ? String.valueOf(item.getStargazers_count()) : "0");
+ holderItem.tvUsername.setText(item.getOwner().getLogin() != null ? item.getOwner().getLogin() : "");
+ holderItem.tvUserFullName.setText(item.getFull_name() != null ? item.getFull_name() : "");
+
+ if (mItems.get(position).getOwner().getAvatar_url() != null) {
+ final int patternSizeImg = 420;
+ ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(mItems.get(position).getOwner().getAvatar_url()))
+ .setResizeOptions(new ResizeOptions(patternSizeImg, patternSizeImg))
+ .build();
+ holderItem.ivUser.setController(
+ Fresco.newDraweeControllerBuilder()
+ .setOldController(holderItem.ivUser.getController())
+ .setImageRequest(request)
+ .build());
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItems.size();
+ }
+
+ public class AppViewHolder extends RecyclerView.ViewHolder {
+ public AppViewHolder(View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ }
+ }
+
+ public class ItemViewHolder extends AppViewHolder {
+
+ @BindView(R.id.tv_name)
+ TextView tvName;
+ @BindView(R.id.tv_description)
+ TextView tvDescription;
+ @BindView(R.id.tv_fork)
+ TextView tvFork;
+ @BindView(R.id.tv_star)
+ TextView tvStar;
+ @BindView(R.id.iv_user)
+ SimpleDraweeView ivUser;
+ @BindView(R.id.tv_username)
+ TextView tvUsername;
+ @BindView(R.id.tv_user_fullname)
+ TextView tvUserFullName;
+ @BindView(R.id.item)
+ LinearLayout item;
+
+ public ItemViewHolder(View itemView) {
+ super(itemView);
+ }
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseFragment.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseFragment.java
new file mode 100644
index 00000000..7951c1b4
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseFragment.java
@@ -0,0 +1,72 @@
+package com.felipemiranda.desafioappprova.ui.main;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import com.felipemiranda.desafioappprova.R;
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+import com.felipemiranda.desafioappprova.ui.home.HomeActivity;
+
+import butterknife.ButterKnife;
+import butterknife.Unbinder;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public abstract class BaseFragment extends Fragment implements BaseLoadingView {
+
+ public abstract BaseLoadingPresenter getPresenter();
+
+ private Unbinder mUnbinder;
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = onCreateViewBinder(inflater, container, savedInstanceState);
+ mUnbinder = ButterKnife.bind(this, view);
+ getPresenter().bindView(this);
+ return view;
+ }
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (mUnbinder != null)
+ mUnbinder.unbind();
+ }
+
+ public void setFragmentContent(Fragment fragment, String tagBackStack) {
+
+ ((HomeActivity) getActivity()).addFragmentDefaultAnim(fragment, fragment.getClass().getName(), tagBackStack);
+ }
+
+ @Override
+ public void showLoading() {
+ ((HomeActivity) getActivity()).showLoading();
+ }
+
+ @Override
+ public void hideLoading() {
+ ((HomeActivity) getActivity()).hideLoading();
+ }
+
+ @Override
+ public void notifyError(GenericErrorResponse error) {
+ if (error != null) {
+ Toast.makeText(getActivity(), error.getMessage(), Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(getActivity(), getString(R.string.sorry_unable_to_process), Toast.LENGTH_LONG).show();
+ }
+ }
+
+ @Override
+ public void retryLastRequest() {
+ getPresenter().retryLastRequest();
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingPresenter.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingPresenter.java
new file mode 100644
index 00000000..71af0d51
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingPresenter.java
@@ -0,0 +1,73 @@
+package com.felipemiranda.desafioappprova.ui.main;
+
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+import com.felipemiranda.desafioappprova.network.RestCallback;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import retrofit2.Call;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public abstract class BaseLoadingPresenter {
+
+ public T mView;
+ private List mCalls;
+ private Request mLastRequest;
+
+ public abstract void bindView(T view);
+
+ public void retryLastRequest() {
+ if (mLastRequest != null)
+ doRequest(mLastRequest.mCall.clone(), mLastRequest.mRestCallback);
+ }
+
+ public void addRequest(final Call call, final RestCallback restCallback) {
+ doRequest(call, restCallback);
+ }
+
+ private void doRequest(final Call call, final RestCallback restCallback) {
+ mLastRequest = new Request(call, restCallback);
+
+ if (mView == null) return;
+
+ mView.showLoading();
+
+ if (mCalls == null)
+ mCalls = new ArrayList<>();
+
+ mCalls.add(call);
+ call.enqueue(new RestCallback() {
+ @Override
+ public void onSuccess(T response) {
+ mCalls.remove(call);
+ if (mView != null) {
+ mView.hideLoading();
+ restCallback.onSuccess(response);
+ }
+ }
+
+ @Override
+ public void onError(GenericErrorResponse error) {
+ mCalls.remove(call);
+ if (mView != null) {
+ mView.hideLoading();
+ restCallback.onError(error);
+ }
+ }
+ });
+ }
+
+ class Request {
+ Call mCall;
+ RestCallback mRestCallback;
+
+ private Request(Call mCall, RestCallback mRestCallback) {
+ this.mCall = mCall;
+ this.mRestCallback = mRestCallback;
+ }
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingView.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingView.java
new file mode 100644
index 00000000..7525e622
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/BaseLoadingView.java
@@ -0,0 +1,18 @@
+package com.felipemiranda.desafioappprova.ui.main;
+
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public interface BaseLoadingView extends FragmentViewBinder {
+
+ void showLoading();
+
+ void hideLoading();
+
+ void notifyError(GenericErrorResponse error);
+
+ void retryLastRequest();
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/FragmentViewBinder.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/FragmentViewBinder.java
new file mode 100644
index 00000000..45ea94a5
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/main/FragmentViewBinder.java
@@ -0,0 +1,15 @@
+package com.felipemiranda.desafioappprova.ui.main;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * Created by felipemiranda on 27/10/17.
+ */
+
+public interface FragmentViewBinder {
+ View onCreateViewBinder(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState);
+}
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailFragment.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailFragment.java
new file mode 100644
index 00000000..c94c4d06
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailFragment.java
@@ -0,0 +1,98 @@
+package com.felipemiranda.desafioappprova.ui.search;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Toast;
+
+import com.felipemiranda.desafioappprova.R;
+import com.felipemiranda.desafioappprova.model.ItemDetail;
+import com.felipemiranda.desafioappprova.ui.main.BaseFragment;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingPresenter;
+import com.felipemiranda.desafioappprova.ui.search.adapter.ItemDetailAdapter;
+import com.felipemiranda.desafioappprova.utils.Utils;
+
+import java.util.ArrayList;
+
+import butterknife.BindView;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class ItemDetailFragment extends BaseFragment implements ItemDetailView, ItemDetailAdapter.OnClickItem {
+
+ @BindView(R.id.rv_list_items)
+ RecyclerView rvListItems;
+
+ private static final String URL = "URL";
+ private static final String NAME = "NAME";
+
+ private ItemDetailPresenter mItemDetailPresenter;
+
+ public static ItemDetailFragment newInstance(String url, String name) {
+ Bundle args = new Bundle();
+ args.putString(URL, url);
+ args.putString(NAME, name);
+ ItemDetailFragment fragment = new ItemDetailFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mItemDetailPresenter = new ItemDetailPresenter();
+ }
+
+ @Override
+ public View onCreateViewBinder(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.fragment_item_detail, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ String url = getArguments().getString(URL);
+ url = url.substring(0, url.length() - 9);
+
+ mItemDetailPresenter.requestItemDetail(url);
+ }
+
+ @Override
+ public BaseLoadingPresenter getPresenter() {
+ return mItemDetailPresenter;
+ }
+
+ @Override
+ public void successItemDetail(ArrayList response) {
+ if (response != null && !response.isEmpty()) {
+ getActivity().setTitle(getArguments().getString(NAME));
+ ItemDetailAdapter itemDetailAdapter = new ItemDetailAdapter(response, this);
+ rvListItems.setLayoutManager(new LinearLayoutManager(getActivity(), LinearLayoutManager.VERTICAL, false));
+ rvListItems.setAdapter(itemDetailAdapter);
+ Utils.recyclerViewAnimationEntrance(rvListItems);
+ } else {
+ getActivity().onBackPressed();
+ Toast.makeText(getActivity(), getString(R.string.not_pull), Toast.LENGTH_LONG).show();
+ }
+ }
+
+ @Override
+ public void onClickItem(String url) {
+ try {
+ Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
+ startActivity(browserIntent);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailPresenter.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailPresenter.java
new file mode 100644
index 00000000..87b14d28
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailPresenter.java
@@ -0,0 +1,40 @@
+package com.felipemiranda.desafioappprova.ui.search;
+
+import com.felipemiranda.desafioappprova.model.ItemDetail;
+import com.felipemiranda.desafioappprova.model.response.GenericErrorResponse;
+import com.felipemiranda.desafioappprova.network.ApiCreator;
+import com.felipemiranda.desafioappprova.network.RestCallback;
+import com.felipemiranda.desafioappprova.network.api.SearchApi;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingPresenter;
+
+import java.util.ArrayList;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class ItemDetailPresenter extends BaseLoadingPresenter {
+
+ @Override
+ public void bindView(ItemDetailView view) {
+ this.mView = view;
+ }
+
+ public void requestItemDetail(String url) {
+ addRequest(ApiCreator
+ .createService(SearchApi.class)
+ .requestItemDetail(url),
+
+ new RestCallback>() {
+ @Override
+ public void onSuccess(ArrayList response) {
+ mView.successItemDetail(response);
+ }
+
+ @Override
+ public void onError(GenericErrorResponse error) {
+ mView.notifyError(error);
+ }
+ });
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailView.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailView.java
new file mode 100644
index 00000000..e205734d
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/ItemDetailView.java
@@ -0,0 +1,15 @@
+package com.felipemiranda.desafioappprova.ui.search;
+
+import com.felipemiranda.desafioappprova.model.ItemDetail;
+import com.felipemiranda.desafioappprova.ui.main.BaseLoadingView;
+
+import java.util.ArrayList;
+
+/**
+ * Created by felipemiranda on 27/10/17.
+ */
+
+public interface ItemDetailView extends BaseLoadingView {
+
+ void successItemDetail(ArrayList response);
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/adapter/ItemDetailAdapter.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/adapter/ItemDetailAdapter.java
new file mode 100644
index 00000000..88a1b9b9
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/ui/search/adapter/ItemDetailAdapter.java
@@ -0,0 +1,127 @@
+package com.felipemiranda.desafioappprova.ui.search.adapter;
+
+import android.annotation.SuppressLint;
+import android.net.Uri;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.facebook.drawee.backends.pipeline.Fresco;
+import com.facebook.drawee.view.SimpleDraweeView;
+import com.facebook.imagepipeline.common.ResizeOptions;
+import com.facebook.imagepipeline.request.ImageRequest;
+import com.facebook.imagepipeline.request.ImageRequestBuilder;
+import com.felipemiranda.desafioappprova.R;
+import com.felipemiranda.desafioappprova.model.ItemDetail;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * Created by felipemiranda on 26/10/17.
+ */
+
+public class ItemDetailAdapter extends RecyclerView.Adapter {
+
+ private ArrayList mItems;
+ private OnClickItem mOnClickItem;
+
+ public ItemDetailAdapter(ArrayList itemDetails, OnClickItem onClickItem) {
+ this.mItems = itemDetails;
+ this.mOnClickItem = onClickItem;
+ }
+
+ public interface OnClickItem {
+ void onClickItem(String url);
+ }
+
+ @Override
+ public AppViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_detail, parent, false);
+ return new ItemViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(AppViewHolder holder, int position) {
+ final ItemDetail item = mItems.get(holder.getAdapterPosition());
+ ItemViewHolder holderItem = (ItemViewHolder) holder;
+
+ holderItem.item.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mOnClickItem.onClickItem(item.getHtml_url());
+ }
+ });
+
+ if(item.getCreated_at() != null) {
+ @SuppressLint("SimpleDateFormat")
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
+ SimpleDateFormat output = new SimpleDateFormat("dd/MM/yyyy HH:mm");
+ String formattedTime = "";
+
+ try {
+ Date date = sdf.parse(item.getCreated_at());
+ formattedTime = output.format(date);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ }
+
+ holderItem.tvDate.setText(formattedTime);
+ }
+ holderItem.tvUsername.setText(item.getUser().getLogin() != null ? item.getUser().getLogin() : "");
+ holderItem.tvName.setText(item.getTitle() != null ? item.getTitle() : "");
+ holderItem.tvDescription.setText(item.getBody() != null ? item.getBody() : "");
+
+ if (mItems.get(position).getUser().getAvatar_url() != null) {
+ final int patternSizeImg = 420;
+ ImageRequest request = ImageRequestBuilder.newBuilderWithSource(Uri.parse(mItems.get(position).getUser().getAvatar_url()))
+ .setResizeOptions(new ResizeOptions(patternSizeImg, patternSizeImg))
+ .build();
+ holderItem.ivUser.setController(
+ Fresco.newDraweeControllerBuilder()
+ .setOldController(holderItem.ivUser.getController())
+ .setImageRequest(request)
+ .build());
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mItems.size();
+ }
+
+ public class AppViewHolder extends RecyclerView.ViewHolder {
+ public AppViewHolder(View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ }
+ }
+
+ public class ItemViewHolder extends AppViewHolder {
+
+ @BindView(R.id.tv_name)
+ TextView tvName;
+ @BindView(R.id.tv_date)
+ TextView tvDate;
+ @BindView(R.id.tv_description)
+ TextView tvDescription;
+ @BindView(R.id.iv_user)
+ SimpleDraweeView ivUser;
+ @BindView(R.id.tv_username)
+ TextView tvUsername;
+ @BindView(R.id.item)
+ LinearLayout item;
+
+ public ItemViewHolder(View itemView) {
+ super(itemView);
+ }
+ }
+}
diff --git a/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/utils/Utils.java b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/utils/Utils.java
new file mode 100644
index 00000000..733bc623
--- /dev/null
+++ b/DesafioAppProva/app/src/main/java/com/felipemiranda/desafioappprova/utils/Utils.java
@@ -0,0 +1,42 @@
+package com.felipemiranda.desafioappprova.utils;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.LayoutAnimationController;
+import android.view.animation.TranslateAnimation;
+
+/**
+ * Created by felipemiranda on 27/10/17.
+ */
+
+public class Utils {
+
+ public static void recyclerViewAnimationEntrance(RecyclerView recyclerView) {
+ AnimationSet set = new AnimationSet(true);
+ Animation animation = new AlphaAnimation(0.0f, 1.0f);
+ animation.setDuration(1000);
+ set.addAnimation(animation);
+
+ animation = new TranslateAnimation(
+ Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f,
+ Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f
+ );
+ animation.setDuration(500);
+ set.addAnimation(animation);
+
+ LayoutAnimationController controller = new LayoutAnimationController(set, 0.1f);
+ controller.setInterpolator(new AccelerateInterpolator());
+ recyclerView.setLayoutAnimation(controller);
+ }
+
+ public static AlphaAnimation alphaAnimation(float fromAlpha, float toAlpha, int duration){
+ AlphaAnimation alphaAnimation = new AlphaAnimation(fromAlpha, toAlpha);
+ alphaAnimation.setDuration(duration);
+ alphaAnimation.setFillAfter(true);
+
+ return alphaAnimation;
+ }
+}
diff --git a/DesafioAppProva/app/src/main/res/anim/slide_from_left.xml b/DesafioAppProva/app/src/main/res/anim/slide_from_left.xml
new file mode 100644
index 00000000..3db834fd
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/anim/slide_from_left.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/anim/slide_from_right.xml b/DesafioAppProva/app/src/main/res/anim/slide_from_right.xml
new file mode 100644
index 00000000..5f6f19e6
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/anim/slide_from_right.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/anim/slide_to_left.xml b/DesafioAppProva/app/src/main/res/anim/slide_to_left.xml
new file mode 100644
index 00000000..9b061f62
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/anim/slide_to_left.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/anim/slide_to_right.xml b/DesafioAppProva/app/src/main/res/anim/slide_to_right.xml
new file mode 100644
index 00000000..c14a1a59
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/anim/slide_to_right.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/drawable/appprova.png b/DesafioAppProva/app/src/main/res/drawable/appprova.png
new file mode 100644
index 00000000..da2f7fe1
Binary files /dev/null and b/DesafioAppProva/app/src/main/res/drawable/appprova.png differ
diff --git a/DesafioAppProva/app/src/main/res/drawable/icon_fork.png b/DesafioAppProva/app/src/main/res/drawable/icon_fork.png
new file mode 100644
index 00000000..a2f002f3
Binary files /dev/null and b/DesafioAppProva/app/src/main/res/drawable/icon_fork.png differ
diff --git a/DesafioAppProva/app/src/main/res/drawable/icon_star.xml b/DesafioAppProva/app/src/main/res/drawable/icon_star.xml
new file mode 100644
index 00000000..850f2619
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/drawable/icon_star.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/drawable/progress.xml b/DesafioAppProva/app/src/main/res/drawable/progress.xml
new file mode 100644
index 00000000..c2ec8e12
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/drawable/progress.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/layout/activity_home.xml b/DesafioAppProva/app/src/main/res/layout/activity_home.xml
new file mode 100644
index 00000000..804d5fe9
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/activity_home.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/layout/activity_splash.xml b/DesafioAppProva/app/src/main/res/layout/activity_splash.xml
new file mode 100644
index 00000000..4ad3e7c4
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/activity_splash.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/layout/fragment_home.xml b/DesafioAppProva/app/src/main/res/layout/fragment_home.xml
new file mode 100644
index 00000000..900157e9
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/fragment_home.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/layout/fragment_item_detail.xml b/DesafioAppProva/app/src/main/res/layout/fragment_item_detail.xml
new file mode 100644
index 00000000..644b738b
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/fragment_item_detail.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/layout/item_detail.xml b/DesafioAppProva/app/src/main/res/layout/item_detail.xml
new file mode 100644
index 00000000..1390fc01
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/item_detail.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DesafioAppProva/app/src/main/res/layout/item_list.xml b/DesafioAppProva/app/src/main/res/layout/item_list.xml
new file mode 100644
index 00000000..e260353f
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/layout/item_list.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DesafioAppProva/app/src/main/res/mipmap-xhdpi/appprova.png b/DesafioAppProva/app/src/main/res/mipmap-xhdpi/appprova.png
new file mode 100644
index 00000000..3d573ed8
Binary files /dev/null and b/DesafioAppProva/app/src/main/res/mipmap-xhdpi/appprova.png differ
diff --git a/DesafioAppProva/app/src/main/res/values/colors.xml b/DesafioAppProva/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..4a7a34c8
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #343438
+ #343438
+ #000
+
diff --git a/DesafioAppProva/app/src/main/res/values/strings.xml b/DesafioAppProva/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..19467b2a
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/values/strings.xml
@@ -0,0 +1,10 @@
+
+ Desafio AppProva
+
+ Desculpe-nos, não foi possível processar a sua solicitação no momento.
+ Você não está conectado, por favor tente novamente mais tarde.
+ Esse repositório não possui Pull request no momento.
+ Github Java
+ Felipe Miranda
+ \@felipemirandareis
+
diff --git a/DesafioAppProva/app/src/main/res/values/styles.xml b/DesafioAppProva/app/src/main/res/values/styles.xml
new file mode 100644
index 00000000..5885930d
--- /dev/null
+++ b/DesafioAppProva/app/src/main/res/values/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/DesafioAppProva/app/src/test/java/com/felipemiranda/desafioappprova/ExampleUnitTest.java b/DesafioAppProva/app/src/test/java/com/felipemiranda/desafioappprova/ExampleUnitTest.java
new file mode 100644
index 00000000..e792cc92
--- /dev/null
+++ b/DesafioAppProva/app/src/test/java/com/felipemiranda/desafioappprova/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.felipemiranda.desafioappprova;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/DesafioAppProva/build.gradle b/DesafioAppProva/build.gradle
new file mode 100644
index 00000000..f5ee59d3
--- /dev/null
+++ b/DesafioAppProva/build.gradle
@@ -0,0 +1,31 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ maven {
+ url 'https://maven.google.com/'
+ name 'Google'
+ }
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.0.0-rc2'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ maven {
+ url 'https://maven.google.com/'
+ name 'Google'
+ }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/DesafioAppProva/gradle.properties b/DesafioAppProva/gradle.properties
new file mode 100644
index 00000000..aac7c9b4
--- /dev/null
+++ b/DesafioAppProva/gradle.properties
@@ -0,0 +1,17 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
diff --git a/DesafioAppProva/gradle/wrapper/gradle-wrapper.jar b/DesafioAppProva/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..13372aef
Binary files /dev/null and b/DesafioAppProva/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/DesafioAppProva/gradle/wrapper/gradle-wrapper.properties b/DesafioAppProva/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..d2b931c7
--- /dev/null
+++ b/DesafioAppProva/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Thu Oct 26 19:54:05 BRST 2017
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
diff --git a/DesafioAppProva/gradlew b/DesafioAppProva/gradlew
new file mode 100755
index 00000000..9d82f789
--- /dev/null
+++ b/DesafioAppProva/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/DesafioAppProva/gradlew.bat b/DesafioAppProva/gradlew.bat
new file mode 100644
index 00000000..8a0b282a
--- /dev/null
+++ b/DesafioAppProva/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/DesafioAppProva/settings.gradle b/DesafioAppProva/settings.gradle
new file mode 100644
index 00000000..e7b4def4
--- /dev/null
+++ b/DesafioAppProva/settings.gradle
@@ -0,0 +1 @@
+include ':app'
diff --git a/README.md b/README.md
index 80966847..f95733f1 100644
--- a/README.md
+++ b/README.md
@@ -4,54 +4,60 @@ A ideia deste desafio é nos permitir avaliar melhor as habilidades de candidato
Este desafio deve ser feito por você em sua casa. Gaste o tempo que você quiser, porém normalmente você não deve precisar de mais do que algumas horas.
-## Instruções de entrega do desafio
-1. Primeiro, faça um fork deste projeto para sua conta no GitHub (crie uma se você não possuir).
-1. Em seguida, implemente o projeto tal qual descrito abaixo, em seu próprio fork.
-1. Por fim, empurre todas as suas alterações para o seu fork no GitHub e envie um pull request para este repositório original. Se você já entrou em contato com alguém da AppProva sobre uma vaga, avise também essa pessoa por email, incluindo no email o seu usuário no GitHub.
+## Ferramentas
-## Descrição do projeto
+Android Studio 3.0 RC2
-Você deve criar um aplicativo que irá listar os repositórios públicos mais populares relacionados a Java no GitHub, usando a [API do GitHub](https://developer.github.com/v3/) para buscar os dados necessários.
+Android SDK
-O aplicativo deve exibir inicialmente uma lista paginada dos repositórios, ordenados por popularidade decrescente (exemplo de chamada da API: `https://api.github.com/search/repositories?q=language:Java&sort=stars&page=1`).
-Cada repositório deve exibir Nome do repositório, Descrição do Repositório, Nome / Foto do autor, Número de Stars, Número de Forks.
+Utilizei os seguintes padrões:
-Ao tocar em um item, deve levar a lista de Pull Requests do repositório. Cada item da lista deve exibir Nome / Foto do autor do PR, Título do PR, Data do PR e Body do PR.
+Delimitador de fim de linha: UNIX (LF ou \n)
-Ao tocar em um item, deve abrir no browser a página do Pull Request em questão.
+Codificação de arquivos: UTF-8
-Você pode se basear neste mockup para criar as telas:
+Indentação: 4 espaços
-
-Sua aplicação deve:
+## Referência API
-- usar um sistema de build. Ex: Gradle
-- fazer mapeamento json -> Objeto . Ex: GSON / Jackson / Moshi / etc
-- usar um arquivo .gitignore no seu repositório
-- usar Material Design
-- usar o padrão MVP ou MVVM
-- possuir boa cobertura de testes unitários no projeto.
+https://developer.github.com/v3/
-Você ganha mais pontos se:
-- criar testes funcionais
-- fazer cache de imagens
-- utilizar Kotlin
-- utilizar RxJava ou RxKotlin
-- utilizar os Android Architecture Components
-- suportar mudanças de orientação das telas sem perder estado (Sem utilizar o configChanges)
+## Arquitetura
-As sugestões de bibliotecas fornecidas são só um guideline, sinta-se a vontade para usar soluções diferentes e nos surpreender. O importante de fato é que os objetivos macros sejam atingidos.
+com.felipemiranda.desafioappprova
-## Avaliação
+MVP
-Seu projeto será avaliado de acordo com os seguintes critérios.
-1. Sua aplicação preenche os requerimentos básicos?
-1. Você documentou a maneira de configurar o ambiente e rodar sua aplicação?
-1. Você seguiu as instruções de envio do desafio?
+## Dependências
-Adicionalmente, tentaremos verificar a sua familiarização com as bibliotecas padrões (standard libs), bem como sua experiência com programação orientada a objetos a partir da estrutura de seu projeto.
+ButterKnife 8.8.1
+
+Facilita o trabalho de encontrar e ligar Views com membros de uma classe, sem a necessidade de se fazer casts e findViewById(int), utilizando anotações.
+
+Gson 2.8.2
+
+Serialização e desserialização de POJOs em formato JSON.
+
+Retrofit 2.3.0
+
+Um cliente HTTP para Java e Android que facilita a escrita de chamadas de APIs RESTful.
+
+Android Support 26.1.0
+
+Bibliotecas da Google que oferecem retrocompatibilidade de versões do Android. Neste projeto, estamos utilizando:
+
+MultiDex 1.0.2
+
+Okhttp 3.8.1
+
+Fresco 1.3.0
+
+
+*build.gradle*
+
+Observe que utilizei o build.gradle para gerenciar o número de versão de algumas dependências, como as bibliotecas android-support e play-services. Isso nos ajuda a manter todas as dependências nas versões corretas.