diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..508a40e4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,65 @@ +# Mac OSx +.*.swp +._* +.DS_Store + +# Code versioner +.hg +.lock-wscript +.svn +.wafpickle-* +CVS + +# Eclipse +.project +.classpath +.settings + +# IDEA/Android Studio project files, because +# the project can be imported from settings.gradle +.idea/* +*.iml + +# Forçando a inclusão de arquivos que quero propagar +!\.idea/dictionaries +!\.idea/codeStyleSettings.xml + +# Old-style IDEA project files +*.ipr +*.iws + +# built application files +*.apk +*.ap_ + +# files for the dex VM +*.dex + +# Java class files +*.class + +# generated files +bin/ +gen/ +out/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Windows thumbnail db +thumbs.db + +# Gradle cache +.gradle + +#Maven +target +release.properties +pom.xml.* + +# Sandbox stuff +_sandbox + +session_analytics.tap +session_analytics_to_send/ \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 00000000..0d424716 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,342 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..958306a1 --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,358 @@ + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 00000000..79ee123c --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/dictionaries/ProjectDictionary.xml b/.idea/dictionaries/ProjectDictionary.xml new file mode 100644 index 00000000..c2d2a403 --- /dev/null +++ b/.idea/dictionaries/ProjectDictionary.xml @@ -0,0 +1,7 @@ + + + + crashlytics + + + \ No newline at end of file diff --git a/app-main/build.gradle b/app-main/build.gradle new file mode 100644 index 00000000..0e315152 --- /dev/null +++ b/app-main/build.gradle @@ -0,0 +1,115 @@ +apply plugin: 'com.android.application' +apply plugin: 'io.fabric' + +android { + compileSdkVersion Integer.parseInt(compile_sdk_version) + buildToolsVersion "${build_tools_version}" + + compileOptions { + sourceCompatibility "${java_source_compatibility}" + targetCompatibility "${java_target_compatibility}" + } + + dataBinding { + enabled = true + } + + testOptions { + unitTests { + includeAndroidResources = true + } + } + + defaultConfig { + applicationId "net.hugonardo.gjp" + minSdkVersion Integer.parseInt(min_sdk_version) + targetSdkVersion Integer.parseInt(target_sdk_version) + versionCode Integer.parseInt(app_version_code) + versionName "${app_version_code}" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + vectorDrawables.useSupportLibrary = true + } + + signingConfigs { + debug { + storeFile file("../keystores/debug.keystore") + storePassword "android" + keyAlias "androiddebugkey" + keyPassword "android" + } + release { + storeFile file(releaseStoreFile) + storePassword releaseStorePassword + keyAlias releaseKeyAlias + keyPassword releaseKeyPassword + } + } + + buildTypes { + debug { + debuggable true + signingConfig signingConfigs.debug + applicationIdSuffix ".debug" + versionNameSuffix "-debug" + ext.enableCrashlytics = false + ext.alwaysUpdateBuildId = false + } + release { + minifyEnabled true + zipAlignEnabled true + signingConfig signingConfigs.release + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +// Isto foi incluído aqui para funcionar injeção de dependência com Dagger 2 no teste unitário. +// Mais informações: https://stackoverflow.com/questions/42793505/dagger-2-generated-test-component-not-recognized +android.applicationVariants.all { + def aptOutputDir = new File(buildDir, "generated/source/apt/${it.unitTestVariant.dirName}") + it.unitTestVariant.addJavaSourceFoldersToModel(aptOutputDir) +} + +dependencies { + implementation "com.android.support:appcompat-v7:${android_support_version}" + implementation "com.android.support:design:${android_support_version}" + implementation "com.android.support:recyclerview-v7:${android_support_version}" + implementation "com.android.support.constraint:constraint-layout:${constraint_layout_version}" + implementation "com.jude:easyrecyclerview:${easy_recyclerview_version}" + implementation "com.yqritc:recyclerview-flexibledivider:${recycler_view_flexible_divider_version}" + implementation("com.crashlytics.sdk.android:crashlytics:${crashlytics_version}@aar") { transitive = true } + implementation "com.jakewharton.timber:timber:${timber_version}" + + debugImplementation "com.squareup.leakcanary:leakcanary-android:${leakcanary_version}" + releaseImplementation "com.squareup.leakcanary:leakcanary-android-no-op:${leakcanary_version}" + + implementation project(':repository') + implementation project(':commons-android') + implementation project(':commons-java') + + compileOnly "org.projectlombok:lombok:${lombok_version}" + annotationProcessor "org.projectlombok:lombok:${lombok_version}" + + compileOnly "javax.annotation:jsr250-api:${jsr250_version}" + implementation "com.google.dagger:dagger:${dagger_version}" + annotationProcessor "com.google.dagger:dagger-compiler:${dagger_version}" + testAnnotationProcessor "com.google.dagger:dagger-compiler:${dagger_version}" + + implementation "com.google.dagger:dagger-android-support:${dagger_version}" + annotationProcessor "com.google.dagger:dagger-android-processor:${dagger_version}" + testAnnotationProcessor "com.google.dagger:dagger-android-processor:${dagger_version}" + + implementation "org.parceler:parceler-api:${parceler_version}" + annotationProcessor "org.parceler:parceler:${parceler_version}" + + testImplementation "org.robolectric:robolectric:${robolectric_version}" + testImplementation "com.squareup.okhttp3:mockwebserver:${mockwebserver_version}" + testImplementation "org.mockito:mockito-core:${mockito_version}" + testImplementation "junit:junit:${junit_version}" + testImplementation "org.hamcrest:hamcrest-junit:${hamcrest_version}" + + androidTestImplementation("com.android.support.test.espresso:espresso-core:${espresso_version}", { + exclude group: 'com.android.support', module: 'support-annotations' + exclude group: 'com.google.code.findbugs', module: 'jsr305' + }) +} diff --git a/app-main/proguard-rules.pro b/app-main/proguard-rules.pro new file mode 100644 index 00000000..e3bf336a --- /dev/null +++ b/app-main/proguard-rules.pro @@ -0,0 +1,57 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 + +#### Retrofit #### +# Platform calls Class.forName on types which do not exist on Android to determine platform. +-dontnote retrofit2.Platform +# Platform used when running on RoboVM on iOS. Will not be used at runtime. +-dontnote retrofit2.Platform$IOS$MainThreadExecutor +# Platform used when running on Java 8 VMs. Will not be used at runtime. +-dontwarn retrofit2.Platform$Java8 +# Retain generic type information for use by reflection by converters and adapters. +-keepattributes Signature +# Retain declared checked exceptions for use by a Proxy instance. +-keepattributes Exceptions + +# OkHttp +-keepattributes Signature +-keepattributes *Annotation* +-keep class okhttp3.** { *; } +-keep interface okhttp3.** { *; } +-dontwarn okhttp3.** +-dontwarn okio.** + +# Crashlytics +-keep class com.crashlytics.** { *; } +-dontwarn com.crashlytics.** +-keepattributes SourceFile,LineNumberTable +-keep public class * extends java.lang.Exception + +# Para as notas de classes duplicadas em Apache HTTP +# https://stackoverflow.com/questions/33047806/proguard-duplicate-definition-of-library-class +-dontnote android.net.http.* +-dontnote org.apache.commons.codec.** +-dontnote org.apache.http.** + +# Em razão de anotações internas do Dagger 2 +# https://github.com/google/dagger/issues/645 +-dontwarn com.google.errorprone.annotations.* diff --git a/app-main/src/debug/ic_launcher-web.png b/app-main/src/debug/ic_launcher-web.png new file mode 100644 index 00000000..b948c6ea Binary files /dev/null and b/app-main/src/debug/ic_launcher-web.png differ diff --git a/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml b/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/app-main/src/debug/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app-main/src/debug/res/mipmap-hdpi/ic_launcher.png b/app-main/src/debug/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..03321d34 Binary files /dev/null and b/app-main/src/debug/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app-main/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png b/app-main/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..5e23228a Binary files /dev/null and b/app-main/src/debug/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/debug/res/mipmap-mdpi/ic_launcher.png b/app-main/src/debug/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..ac26e636 Binary files /dev/null and b/app-main/src/debug/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app-main/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png b/app-main/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..6d48e400 Binary files /dev/null and b/app-main/src/debug/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/debug/res/mipmap-xhdpi/ic_launcher.png b/app-main/src/debug/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..d0c2849e Binary files /dev/null and b/app-main/src/debug/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app-main/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png b/app-main/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..9a80aa9e Binary files /dev/null and b/app-main/src/debug/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher.png b/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..51d360c6 Binary files /dev/null and b/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..73a5e8e9 Binary files /dev/null and b/app-main/src/debug/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher.png b/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..5766f7e9 Binary files /dev/null and b/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..b64f9fb2 Binary files /dev/null and b/app-main/src/debug/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/debug/res/values/ic_launcher_background.xml b/app-main/src/debug/res/values/ic_launcher_background.xml new file mode 100644 index 00000000..9f09648d --- /dev/null +++ b/app-main/src/debug/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #4B4B4B + \ No newline at end of file diff --git a/app-main/src/debug/res/values/strings.xml b/app-main/src/debug/res/values/strings.xml new file mode 100644 index 00000000..0e17aaea --- /dev/null +++ b/app-main/src/debug/res/values/strings.xml @@ -0,0 +1,4 @@ + + + JavaPop in GitHub DEBUG + \ No newline at end of file diff --git a/app-main/src/main/AndroidManifest.xml b/app-main/src/main/AndroidManifest.xml new file mode 100644 index 00000000..ae2c8303 --- /dev/null +++ b/app-main/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/app-main/src/main/ic_launcher-web.png b/app-main/src/main/ic_launcher-web.png new file mode 100644 index 00000000..a9a11296 Binary files /dev/null and b/app-main/src/main/ic_launcher-web.png differ diff --git a/app-main/src/main/java/net/hugonardo/gjp/GjpApplication.java b/app-main/src/main/java/net/hugonardo/gjp/GjpApplication.java new file mode 100644 index 00000000..faa7f580 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/GjpApplication.java @@ -0,0 +1,31 @@ +package net.hugonardo.gjp; + +import com.squareup.leakcanary.LeakCanary; + +import net.hugonardo.gjp.di.DaggerApplicationInjector; +import net.hugonardo.gjp.tools.CrashlyticsTree; + +import dagger.android.AndroidInjector; +import timber.log.Timber; + +public class GjpApplication extends GjpFabricApplication { + + @Override protected AndroidInjector applicationInjector() { + return DaggerApplicationInjector.builder().create(this); + } + + @Override public void onCreate() { + super.onCreate(); + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return; + } + LeakCanary.install(this); + if (BuildConfig.DEBUG) { + Timber.plant(new Timber.DebugTree()); + } else { + Timber.plant(new CrashlyticsTree()); + } + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/GjpFabricApplication.java b/app-main/src/main/java/net/hugonardo/gjp/GjpFabricApplication.java new file mode 100644 index 00000000..fda8aabf --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/GjpFabricApplication.java @@ -0,0 +1,25 @@ +package net.hugonardo.gjp; + +import android.support.annotation.CallSuper; + +import com.crashlytics.android.Crashlytics; +import com.crashlytics.android.core.CrashlyticsCore; + +import dagger.android.support.DaggerApplication; +import io.fabric.sdk.android.Fabric; + +public abstract class GjpFabricApplication extends DaggerApplication { + + @CallSuper @Override public void onCreate() { + super.onCreate(); + setupFabricKits(); + } + + private void setupFabricKits() { + Crashlytics crashlytics = new Crashlytics.Builder() + .core(new CrashlyticsCore.Builder().disabled(BuildConfig.DEBUG).build()) + .build(); + + Fabric.with(this, crashlytics); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationInjector.java b/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationInjector.java new file mode 100644 index 00000000..fd7ed340 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationInjector.java @@ -0,0 +1,25 @@ +package net.hugonardo.gjp.di; + +import net.hugonardo.gjp.GjpApplication; +import net.hugonardo.gjp.api.infra.di.ApiClientModule; + +import javax.inject.Singleton; + +import dagger.Component; +import dagger.android.AndroidInjector; +import dagger.android.support.AndroidSupportInjectionModule; + +@Singleton +@Component(modules = { + AndroidSupportInjectionModule.class, + ContributorsModule.class, + ApplicationModule.class, + ApiClientModule.class, +}) +public interface ApplicationInjector extends AndroidInjector { + + @Component.Builder + abstract class Builder extends AndroidInjector.Builder { + @Override public abstract ApplicationInjector build(); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationModule.java b/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationModule.java new file mode 100644 index 00000000..526d6fe0 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/di/ApplicationModule.java @@ -0,0 +1,23 @@ +package net.hugonardo.gjp.di; + +import android.content.Context; + +import net.hugonardo.gjp.BuildConfig; +import net.hugonardo.gjp.GjpApplication; +import net.hugonardo.gjp.api.infra.Host; +import net.hugonardo.gjp.api.infra.di.BaseUrl; + +import javax.inject.Singleton; + +import dagger.Module; +import dagger.Provides; + +@Module +class ApplicationModule { + @Provides Context context(GjpApplication application) { + return application; + } + @Provides @Singleton @BaseUrl String baseUrl() { + return Host.fromBuildType(BuildConfig.BUILD_TYPE).getBaseUrl(); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/di/ContributorsModule.java b/app-main/src/main/java/net/hugonardo/gjp/di/ContributorsModule.java new file mode 100644 index 00000000..41996e8b --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/di/ContributorsModule.java @@ -0,0 +1,12 @@ +package net.hugonardo.gjp.di; + +import net.hugonardo.gjp.main.MainContributorsModule; +import net.hugonardo.gjp.repos.RepoContributorsModule; + +import dagger.Module; + +@Module(includes = { + MainContributorsModule.class, + RepoContributorsModule.class, +}) +abstract class ContributorsModule {} diff --git a/app-main/src/main/java/net/hugonardo/gjp/main/MainActivity.java b/app-main/src/main/java/net/hugonardo/gjp/main/MainActivity.java new file mode 100644 index 00000000..114f4885 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/main/MainActivity.java @@ -0,0 +1,28 @@ +package net.hugonardo.gjp.main; + +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.design.widget.Snackbar; +import android.view.View; + +import net.hugonardo.gjp.R; +import net.hugonardo.gjp.databinding.MainActivityBinding; +import net.hugonardo.gjp.tools.base.BaseActivity; + +public class MainActivity extends BaseActivity { + + private MainActivityBinding mBinding; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mBinding = DataBindingUtil.setContentView(this, R.layout.main_activity); + mBinding.setHandler(this); + setSupportActionBar(mBinding.toolbar); + } + + public void onClickFab(View view) { + Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) + .setAction("Action", null).show(); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/main/MainContributorsModule.java b/app-main/src/main/java/net/hugonardo/gjp/main/MainContributorsModule.java new file mode 100644 index 00000000..86e6d677 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/main/MainContributorsModule.java @@ -0,0 +1,9 @@ +package net.hugonardo.gjp.main; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; + +@Module +public abstract class MainContributorsModule { + @ContributesAndroidInjector abstract MainActivity contributesMainActivity(); +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoActivity.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoActivity.java new file mode 100644 index 00000000..223527a5 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoActivity.java @@ -0,0 +1,16 @@ +package net.hugonardo.gjp.repos; + +import android.os.Bundle; + +import net.hugonardo.gjp.R; +import net.hugonardo.gjp.tools.base.BaseActivity; + +public class RepoActivity extends BaseActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.repo_activity); + } + +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoContributorsModule.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoContributorsModule.java new file mode 100644 index 00000000..46da9cd7 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoContributorsModule.java @@ -0,0 +1,10 @@ +package net.hugonardo.gjp.repos; + +import dagger.Module; +import dagger.android.ContributesAndroidInjector; + +@Module +public abstract class RepoContributorsModule { + @ContributesAndroidInjector abstract RepoActivity contributesMainActivity(); + @ContributesAndroidInjector abstract RepoListFragment contributesRepoListFragment(); +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListAdapter.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListAdapter.java new file mode 100644 index 00000000..94c9a316 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListAdapter.java @@ -0,0 +1,55 @@ +package net.hugonardo.gjp.repos; + +import android.databinding.DataBindingUtil; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import com.jude.easyrecyclerview.adapter.BaseViewHolder; +import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; + +import net.hugonardo.gjp.R; +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.databinding.RepoListItemBinding; + +import java.util.List; + +public class RepoListAdapter extends RecyclerArrayAdapter { + + private final Object mLocker = new Object(); + private final LayoutInflater mLayoutInflater; + private final EventHandler mEventHandler; + + public interface EventHandler { + void onItemClick(Repo repo); + } + + RepoListAdapter(LayoutInflater layoutInflater, EventHandler eventHandler) { + super(null); + mLayoutInflater = layoutInflater; + mEventHandler = eventHandler; + } + + void swapData(List newDataset) { + if (mEventDelegate != null) { + if (newDataset != null && !newDataset.isEmpty() && ((newDataset.size() - getCount()) > 0)) { + mEventDelegate.addData(newDataset.size() - getCount()); + } + } + + if (newDataset != null && newDataset.size() != 0) { + synchronized (mLocker) { + mObjects = newDataset; + } + notifyDataSetChanged(); + } else { + clear(); + } + } + + @Override public BaseViewHolder OnCreateViewHolder(ViewGroup parent, int viewType) { + RepoListItemBinding binding = DataBindingUtil.inflate(mLayoutInflater, + R.layout.repo_list_item, parent, false); + binding.setHandler(mEventHandler); + return new RepoViewHolder(binding); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListFragment.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListFragment.java new file mode 100644 index 00000000..689143a3 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListFragment.java @@ -0,0 +1,102 @@ +package net.hugonardo.gjp.repos; + +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; +import android.support.v4.app.LoaderManager; +import android.support.v4.content.Loader; +import android.support.v7.widget.LinearLayoutManager; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import com.jude.easyrecyclerview.EasyRecyclerView; +import com.jude.easyrecyclerview.adapter.RecyclerArrayAdapter; +import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration; + +import net.hugonardo.gjp.R; +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.tools.base.BaseFragment; + +import java.util.List; + +public class RepoListFragment extends BaseFragment + implements LoaderManager.LoaderCallbacks>, + RecyclerArrayAdapter.OnMoreListener, + RepoListAdapter.EventHandler { + + private static final int REPOSITORY_LOADER_ID = 0; + + private RepoListAdapter mAdapter; + private EasyRecyclerView mEasyRecyclerView; + + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.repo_list_fragment, container, false); + } + + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setupListView(view); + setupAdapter(); + } + + private void setupListView(View view) { + mEasyRecyclerView = view.findViewById(R.id.easyRecycler); + mEasyRecyclerView.getRecyclerView().setLayoutManager(new LinearLayoutManager(getContext())); + mEasyRecyclerView.getRecyclerView().setHasFixedSize(true); + HorizontalDividerItemDecoration divider = new HorizontalDividerItemDecoration + .Builder(getContext()) + .marginResId(R.dimen.list_divider_vertical_margin_start, R.dimen.list_divider_vertical_margin_end) + .build(); + mEasyRecyclerView.getRecyclerView().addItemDecoration(divider); + } + + private void setupAdapter() { + mAdapter = new RepoListAdapter(LayoutInflater.from(getContext()), this); + mAdapter.setMore(R.layout.list_item_loading_more, this); + mEasyRecyclerView.setAdapterWithProgress(mAdapter); + } + + @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + getLoaderManager().initLoader(REPOSITORY_LOADER_ID, null, this); + } + + @Override public void onMoreShow() { + if (isAdded()) { + final RepoLoader loader = repositoryLoader(); + + if (loader == null || !loader.hasMoreResults()) { + mAdapter.stopMore(); + return; + } + + loader.loadMoreResults(); + } + } + + @Override public void onMoreClick() {} + + private RepoLoader repositoryLoader() { + return (RepoLoader) getLoaderManager().>getLoader(REPOSITORY_LOADER_ID); + } + + @Override public Loader> onCreateLoader(int id, Bundle args) { + return new RepoLoader(getContext()); + } + + @Override public void onLoadFinished(Loader> loader, List data) { + mAdapter.swapData(data); + } + + @Override public void onLoaderReset(Loader> loader) { + mAdapter.clear(); + } + + @Override public void onItemClick(Repo repo) { + Snackbar.make(mEasyRecyclerView, String.format("Clicou em %s", repo.name()), Snackbar.LENGTH_SHORT).show(); + //Bundle args = PullRequestActivity.getLauncherBundle(mModel); + //getFrameworkTools().navigator().forwardTo(PullRequestActivity.class, args); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListItemViewModel.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListItemViewModel.java new file mode 100644 index 00000000..8084da81 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoListItemViewModel.java @@ -0,0 +1,54 @@ +package net.hugonardo.gjp.repos; + +import android.databinding.BaseObservable; +import android.databinding.Bindable; + +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.api.user.User; + +import org.parceler.Parcel; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Parcel +@NoArgsConstructor +public class RepoListItemViewModel extends BaseObservable { + + @Getter Repo mModel; + + void setModel(Repo model) { + mModel = model; + notifyChange(); + } + + @Bindable public String getName() { + return mModel != null ? mModel.name() : null; + } + + @Bindable public String getDescription() { + return mModel != null ? mModel.description() : null; + } + + @Bindable public String getForksCount() { + return ((mModel != null) && (mModel.forksCount() != null)) + ? mModel.forksCount().toString() : null; + } + + @Bindable public String getStarsCount() { + return ((mModel != null) && (mModel.starsCount() != null)) + ? mModel.starsCount().toString() : null; + } + + @Bindable public String getOwnerLogin() { + return getOwner() != null ? getOwner().login() : null; + } + + @Bindable public String getOwnerName() { + return getOwner() != null ? getOwner().name() : null; + } + + @Bindable private User getOwner() { + return mModel != null ? mModel.owner() : null; + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoLoader.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoLoader.java new file mode 100644 index 00000000..7642876f --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoLoader.java @@ -0,0 +1,117 @@ +package net.hugonardo.gjp.repos; + +import android.content.Context; +import android.support.v4.content.AsyncTaskLoader; + +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.tools.dummy.DummyRepositories; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +class RepoLoader extends AsyncTaskLoader> { + + private List mData; + private Integer mNextPageToken; + private boolean mIsLoading; + + private boolean mHasError; + + RepoLoader(Context context) { + super(context); + init(); + } + + private void init() { + mHasError = false; + mNextPageToken = 1; + mIsLoading = true; + mData = null; + } + + @Override + protected void onStartLoading() { + if (mData != null) { + // If we already have results and are starting up, deliver what we already have. + deliverResult(null); + } else { + forceLoad(); + } + } + + @Override + public List loadInBackground() { + mIsLoading = true; + List data = null; + + try { + Thread.sleep(1000); + data = DummyRepositories.getPage(mNextPageToken); + if (mData == null) { + mData = Collections.synchronizedList(new ArrayList()); + } + mData.addAll(data); + mHasError = false; + mNextPageToken = DummyRepositories.getNextPageToken(mNextPageToken); + } catch (IndexOutOfBoundsException | InterruptedException e) { + e.printStackTrace(); + mHasError = true; + mNextPageToken = null; + } + + return data; + } + + @Override + public void onCanceled(List data) { + if (data != null) { + deliverResult(data); + } + } + + @Override + public void deliverResult(List data) { + mIsLoading = false; + if (isStarted()) { + // Need to return new ArrayList for some reason or onLoadFinished() is not called + super.deliverResult(mData == null ? null : new ArrayList<>(mData)); + } + } + + @Override + protected void onStopLoading() { + mIsLoading = false; + cancelLoad(); + } + + @Override + protected void onReset() { + super.onReset(); + onStopLoading(); + mData = null; + } + + void loadMoreResults() { + if (!isLoading() && hasMoreResults()) { + forceLoad(); + } + } + + boolean isLoading() { + return mIsLoading; + } + + boolean hasMoreResults() { + return mNextPageToken != null; + } + + boolean hasError() { + return mHasError; + } + + void refresh() { + reset(); + startLoading(); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/repos/RepoViewHolder.java b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoViewHolder.java new file mode 100644 index 00000000..be0770b9 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/repos/RepoViewHolder.java @@ -0,0 +1,23 @@ +package net.hugonardo.gjp.repos; + +import com.jude.easyrecyclerview.adapter.BaseViewHolder; + +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.databinding.RepoListItemBinding; + +class RepoViewHolder extends BaseViewHolder { + + private final RepoListItemBinding mBinding; + + RepoViewHolder(RepoListItemBinding binding) { + super(binding.getRoot()); + mBinding = binding; + binding.setViewModel(new RepoListItemViewModel()); + } + + @Override + public void setData(Repo data) { + mBinding.getViewModel().setModel(data); + mBinding.executePendingBindings(); + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/tools/CrashlyticsTree.java b/app-main/src/main/java/net/hugonardo/gjp/tools/CrashlyticsTree.java new file mode 100644 index 00000000..b55a48df --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/tools/CrashlyticsTree.java @@ -0,0 +1,23 @@ +package net.hugonardo.gjp.tools; + +import com.crashlytics.android.Crashlytics; + +import lombok.RequiredArgsConstructor; +import timber.log.Timber; + +import static android.util.Log.WARN; + +@RequiredArgsConstructor +public class CrashlyticsTree extends Timber.Tree { + + @Override protected boolean isLoggable(String tag, int priority) { + return priority >= WARN; + } + + @Override protected void log(int priority, String tag, String message, Throwable t) { + Crashlytics.log(message); + if (t != null) { + Crashlytics.logException(t); + } + } +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseActivity.java b/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseActivity.java new file mode 100644 index 00000000..f1fc0130 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseActivity.java @@ -0,0 +1,6 @@ +package net.hugonardo.gjp.tools.base; + +import dagger.android.support.DaggerAppCompatActivity; + +public abstract class BaseActivity extends DaggerAppCompatActivity { +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseFragment.java b/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseFragment.java new file mode 100644 index 00000000..8334af47 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/tools/base/BaseFragment.java @@ -0,0 +1,6 @@ +package net.hugonardo.gjp.tools.base; + +import dagger.android.support.DaggerFragment; + +public class BaseFragment extends DaggerFragment { +} diff --git a/app-main/src/main/java/net/hugonardo/gjp/tools/dummy/DummyRepositories.java b/app-main/src/main/java/net/hugonardo/gjp/tools/dummy/DummyRepositories.java new file mode 100644 index 00000000..92a939a1 --- /dev/null +++ b/app-main/src/main/java/net/hugonardo/gjp/tools/dummy/DummyRepositories.java @@ -0,0 +1,79 @@ +package net.hugonardo.gjp.tools.dummy; + +import android.support.v4.util.LongSparseArray; + +import net.hugonardo.gjp.api.repo.Repo; +import net.hugonardo.gjp.api.user.User; + +import java.util.ArrayList; +import java.util.List; + +/** + * Helper class for providing sample content for user interfaces created by + * Android template wizards. + *

+ * TODO: Replace all uses of this class before publishing your app. + */ +public class DummyRepositories { + + /** + * An array of sample (dummy) items. + */ + private static final List ITEMS = new ArrayList<>(); + + /** + * A map of sample (dummy) items, by ID. + */ + private static final LongSparseArray ITEM_MAP = new LongSparseArray<>(); + + private static final int COUNT = 38; + private static final int PER_PAGE = 10; + private static final int PAGES = COUNT / PER_PAGE; + + static { + // Add some sample items. + for (int i = 1; i <= COUNT; i++) { + addItem(createRepo(i)); + } + } + + public static List getPage(int page) { + if (page > PAGES) { + throw new IndexOutOfBoundsException(); + } + + int first = (page - 1) * PER_PAGE; + int last = first + PER_PAGE; + return ITEMS.subList(first, last); + } + + public static Integer getNextPageToken(Integer currentPage) { + return currentPage < PAGES ? (currentPage + 1) : null; + } + + private static void addItem(Repo item) { + ITEMS.add(item); + ITEM_MAP.put(item.id(), item); + } + + private static Repo createRepo(int position) { + Long positionLong = (long) position; + return Repo.builder() + .id(positionLong) + .name("Repositório " + position) + .description(makeDetails(position)) + .forksCount(positionLong) + .starsCount(positionLong) + .owner(User.builder().id(positionLong).login("user" + position).name("User Name " + position).build()) + .build(); + } + + private static String makeDetails(int position) { + StringBuilder builder = new StringBuilder(); + builder.append("Details about Item: ").append(position); + for (int i = 0; i < position; i++) { + builder.append("\nMore details information here."); + } + return builder.toString(); + } +} diff --git a/app-main/src/main/res/drawable/ic_branch.xml b/app-main/src/main/res/drawable/ic_branch.xml new file mode 100644 index 00000000..ca9a5e36 --- /dev/null +++ b/app-main/src/main/res/drawable/ic_branch.xml @@ -0,0 +1,9 @@ + + + diff --git a/app-main/src/main/res/drawable/ic_launcher_background.xml b/app-main/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..0e42f795 --- /dev/null +++ b/app-main/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app-main/src/main/res/drawable/ic_pull_request.xml b/app-main/src/main/res/drawable/ic_pull_request.xml new file mode 100644 index 00000000..4fd2a3f7 --- /dev/null +++ b/app-main/src/main/res/drawable/ic_pull_request.xml @@ -0,0 +1,10 @@ + + + diff --git a/app-main/src/main/res/drawable/ic_star.xml b/app-main/src/main/res/drawable/ic_star.xml new file mode 100644 index 00000000..a87ca098 --- /dev/null +++ b/app-main/src/main/res/drawable/ic_star.xml @@ -0,0 +1,9 @@ + + + diff --git a/app-main/src/main/res/layout/list_empty.xml b/app-main/src/main/res/layout/list_empty.xml new file mode 100644 index 00000000..f8515f05 --- /dev/null +++ b/app-main/src/main/res/layout/list_empty.xml @@ -0,0 +1,7 @@ + + \ No newline at end of file diff --git a/app-main/src/main/res/layout/list_item_loading_more.xml b/app-main/src/main/res/layout/list_item_loading_more.xml new file mode 100644 index 00000000..4ea95767 --- /dev/null +++ b/app-main/src/main/res/layout/list_item_loading_more.xml @@ -0,0 +1,22 @@ + + + + + + + \ No newline at end of file diff --git a/app-main/src/main/res/layout/list_progress.xml b/app-main/src/main/res/layout/list_progress.xml new file mode 100644 index 00000000..47ce3e5f --- /dev/null +++ b/app-main/src/main/res/layout/list_progress.xml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/app-main/src/main/res/layout/main_activity.xml b/app-main/src/main/res/layout/main_activity.xml new file mode 100644 index 00000000..38fc4b5b --- /dev/null +++ b/app-main/src/main/res/layout/main_activity.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app-main/src/main/res/layout/main_activity_content.xml b/app-main/src/main/res/layout/main_activity_content.xml new file mode 100644 index 00000000..4ded270a --- /dev/null +++ b/app-main/src/main/res/layout/main_activity_content.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + diff --git a/app-main/src/main/res/layout/repo_activity.xml b/app-main/src/main/res/layout/repo_activity.xml new file mode 100644 index 00000000..5189088c --- /dev/null +++ b/app-main/src/main/res/layout/repo_activity.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/app-main/src/main/res/layout/repo_list_fragment.xml b/app-main/src/main/res/layout/repo_list_fragment.xml new file mode 100644 index 00000000..1b24231e --- /dev/null +++ b/app-main/src/main/res/layout/repo_list_fragment.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app-main/src/main/res/layout/repo_list_item.xml b/app-main/src/main/res/layout/repo_list_item.xml new file mode 100644 index 00000000..6fb9aa80 --- /dev/null +++ b/app-main/src/main/res/layout/repo_list_item.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..036d09bc --- /dev/null +++ b/app-main/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app-main/src/main/res/mipmap-hdpi/ic_launcher.png b/app-main/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..1220fc36 Binary files /dev/null and b/app-main/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app-main/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app-main/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..a63fd0f2 Binary files /dev/null and b/app-main/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app-main/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..8fab6a3a Binary files /dev/null and b/app-main/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app-main/src/main/res/mipmap-mdpi/ic_launcher.png b/app-main/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..b4b498f4 Binary files /dev/null and b/app-main/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app-main/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app-main/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..cd6c5506 Binary files /dev/null and b/app-main/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app-main/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..1eecc0e7 Binary files /dev/null and b/app-main/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app-main/src/main/res/mipmap-xhdpi/ic_launcher.png b/app-main/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..df382c98 Binary files /dev/null and b/app-main/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app-main/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app-main/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..3b7b0e1b Binary files /dev/null and b/app-main/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app-main/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..05ca079c Binary files /dev/null and b/app-main/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app-main/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..ab55d3f4 Binary files /dev/null and b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..4de701f7 Binary files /dev/null and b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..8bac0f27 Binary files /dev/null and b/app-main/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..4dc89066 Binary files /dev/null and b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 00000000..223a3f0f Binary files /dev/null and b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..bacd3e75 Binary files /dev/null and b/app-main/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app-main/src/main/res/values/colors.xml b/app-main/src/main/res/values/colors.xml new file mode 100644 index 00000000..3cc780e8 --- /dev/null +++ b/app-main/src/main/res/values/colors.xml @@ -0,0 +1,7 @@ + + + #343438 + #343438 + #3B7BAE + #e4e4e4 + diff --git a/app-main/src/main/res/values/dimens.xml b/app-main/src/main/res/values/dimens.xml new file mode 100644 index 00000000..7ac718b1 --- /dev/null +++ b/app-main/src/main/res/values/dimens.xml @@ -0,0 +1,13 @@ + + 16dp + 16dp + 16dp + 16dp + + 16dp + 8dp + 0dp + 0dp + 38dp + 4dp + diff --git a/app-main/src/main/res/values/ic_launcher_background.xml b/app-main/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 00000000..9f09648d --- /dev/null +++ b/app-main/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #4B4B4B + \ No newline at end of file diff --git a/app-main/src/main/res/values/strings.xml b/app-main/src/main/res/values/strings.xml new file mode 100644 index 00000000..fb3d20fe --- /dev/null +++ b/app-main/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + + JavaPop in GitHub + Carregando… + Nenhum item para exibir + + Popular Java in GitHub + + Popular Java in GitHub + diff --git a/app-main/src/main/res/values/styles.xml b/app-main/src/main/res/values/styles.xml new file mode 100644 index 00000000..976ff2d2 --- /dev/null +++ b/app-main/src/main/res/values/styles.xml @@ -0,0 +1,13 @@ + + + + +