├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── raqun │ │ └── dctracker │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── raqun │ │ │ └── dctracker │ │ │ ├── Constants.kt │ │ │ ├── DcTrackerApp.kt │ │ │ ├── api │ │ │ ├── ApiConstants.kt │ │ │ ├── DefaultRequestInterceptor.kt │ │ │ └── TrackerServices.kt │ │ │ ├── binding │ │ │ └── BindingConversion.kt │ │ │ ├── data │ │ │ ├── DataBean.kt │ │ │ ├── DataState.kt │ │ │ ├── Error.kt │ │ │ └── source │ │ │ │ ├── DiffDataSource.kt │ │ │ │ └── remote │ │ │ │ └── DiffRemoteDataSource.kt │ │ │ ├── di │ │ │ ├── ActivityModule.kt │ │ │ ├── ActivityScope.kt │ │ │ ├── ApiModule.kt │ │ │ ├── AppComponent.kt │ │ │ ├── AppModule.kt │ │ │ ├── FragmentBuildersModule.kt │ │ │ ├── FragmentScope.kt │ │ │ ├── ViewModelKey.kt │ │ │ └── ViewModelModule.kt │ │ │ ├── ext │ │ │ ├── ActivityExt.kt │ │ │ ├── FragmentManagerExt.kt │ │ │ └── RecyclerViewExt.kt │ │ │ ├── model │ │ │ ├── DefaultResponse.kt │ │ │ ├── Diff.kt │ │ │ └── UiDataBean.kt │ │ │ ├── ui │ │ │ ├── BaseActivity.kt │ │ │ ├── BaseFragment.kt │ │ │ ├── BaseView.kt │ │ │ ├── BinderFragment.kt │ │ │ ├── NavigationController.kt │ │ │ └── home │ │ │ │ ├── DiffsAdapter.kt │ │ │ │ ├── HomeActivity.kt │ │ │ │ ├── HomeFragment.kt │ │ │ │ └── HomeViewModel.kt │ │ │ └── viewmodel │ │ │ └── VMFactory.kt │ └── res │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_home.xml │ │ ├── fragment_home.xml │ │ └── item_diff.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── raqun │ └── dctracker │ └── ExampleUnitTest.kt ├── build.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | gradle.properties 11 | gradlew 12 | gradlew.bat 13 | .idea 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # digital-currency-tracker 2 | Digital Currency tracker application
3 | 4 | ## An example implementation of latest Android Trends with Kotlin 5 | - MVVM 6 | - Dagger 2.11 7 | - Data Binding 8 | - LiveData 9 | - ViewModel 10 | - Retrofit 2.0 11 | - RxKotlin 12 | - Repository 13 | 14 | ##  Can be implemented in future 15 | - Clean Arch. 16 | - Room 17 | - Realm 18 | - Espresso 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | 7 | android { 8 | compileSdkVersion 26 9 | buildToolsVersion "25.0.2" 10 | defaultConfig { 11 | applicationId "com.raqun.dctracker" 12 | minSdkVersion 17 13 | targetSdkVersion 26 14 | versionCode 1 15 | versionName "1.0.0" 16 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 17 | } 18 | 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | dataBinding { 27 | enabled = true 28 | } 29 | 30 | packagingOptions { 31 | exclude 'META-INF/rxjava.properties' 32 | } 33 | } 34 | 35 | kapt { 36 | generateStubs = true 37 | } 38 | 39 | dependencies { 40 | implementation fileTree(dir: 'libs', include: ['*.jar']) 41 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', { 42 | exclude group: 'com.android.support', module: 'support-annotations' 43 | }) 44 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" 45 | implementation "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion" 46 | testImplementation 'junit:junit:4.12' 47 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 48 | compile "com.android.support:design:$rootProject.ext.supportLibraryVersion" 49 | compile "com.android.support:recyclerview-v7:$rootProject.ext.supportLibraryVersion" 50 | compile "com.android.support:cardview-v7:$rootProject.ext.supportLibraryVersion" 51 | 52 | // Retrofit 53 | compile "com.squareup.retrofit2:retrofit:$rootProject.ext.retrofitVersion" 54 | compile "com.squareup.okhttp3:logging-interceptor:$rootProject.ext.loggingInterceptorVersion" 55 | compile "com.squareup.retrofit2:converter-gson:$rootProject.ext.gsonVersion" 56 | compile "com.squareup.retrofit2:adapter-rxjava2:$rootProject.ext.retrofitVersion" 57 | compile 'com.squareup.okhttp3:okhttp:3.8.0' 58 | 59 | // Dagger 60 | compile "com.google.dagger:dagger-android-support:$rootProject.ext.daggerVersion" 61 | kapt "com.google.dagger:dagger-compiler:$rootProject.ext.daggerVersion" 62 | kapt "com.google.dagger:dagger-android-processor:$rootProject.ext.daggerVersion" 63 | 64 | // Arch Components 65 | compile "android.arch.lifecycle:runtime:$rootProject.ext.archVersion" 66 | compile "android.arch.lifecycle:extensions:$rootProject.ext.archVersion" 67 | 68 | // Rx 69 | compile "io.reactivex.rxjava2:rxandroid:2.0.1" 70 | compile "io.reactivex.rxjava2:rxkotlin:$rootProject.ext.rxKotlinVersion" 71 | 72 | // Data Binding 73 | kapt "com.android.databinding:compiler:$rootProject.ext.dataBindingCompilerVersion" 74 | } 75 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/tyln/Documents/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/raqun/dctracker/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.raqun.dctracker", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/Constants.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker 2 | 3 | /** 4 | * Created by tyln on 12/09/2017. 5 | */ 6 | class Constants private constructor() { 7 | 8 | companion object { 9 | val NO_RES = 0 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/DcTrackerApp.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker 2 | 3 | import android.app.Activity 4 | import android.app.Application 5 | import com.raqun.dctracker.di.DaggerAppComponent 6 | import dagger.android.AndroidInjector 7 | import dagger.android.DispatchingAndroidInjector 8 | import dagger.android.HasActivityInjector 9 | import javax.inject.Inject 10 | 11 | /** 12 | * Created by tyln on 12/09/2017. 13 | */ 14 | class DcTrackerApp : Application(), HasActivityInjector { 15 | 16 | @Inject lateinit var dispachingAndroidInjector: DispatchingAndroidInjector 17 | 18 | override fun onCreate() { 19 | super.onCreate() 20 | DaggerAppComponent.builder() 21 | .application(this) 22 | .build() 23 | .inject(this) 24 | } 25 | 26 | override fun activityInjector() = dispachingAndroidInjector 27 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/api/ApiConstants.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.api 2 | 3 | /** 4 | * Created by tyln on 12/09/2017. 5 | */ 6 | class ApiConstants private constructor() { 7 | 8 | companion object { 9 | val TIMEOUT_INMILIS = 15000L 10 | val ERROR_CODE_AUTH = 401 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/api/DefaultRequestInterceptor.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.api 2 | 3 | import okhttp3.Interceptor 4 | import okhttp3.Response 5 | import javax.inject.Inject 6 | import javax.inject.Named 7 | 8 | /** 9 | * Created by tyln on 12/09/2017. 10 | */ 11 | class DefaultRequestInterceptor @Inject constructor() : Interceptor { 12 | 13 | override fun intercept(chain: Interceptor.Chain?): Response? { 14 | chain?.let { 15 | return chain.proceed(with(chain.request().newBuilder()) { 16 | addHeader("Content-Type", "application/json") 17 | // Some other headers... 18 | build() 19 | }) 20 | } 21 | 22 | return null 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/api/TrackerServices.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.api 2 | 3 | import com.raqun.dctracker.model.DefaultResponse 4 | import com.raqun.dctracker.model.Diff 5 | import io.reactivex.Single 6 | import retrofit2.http.Body 7 | import retrofit2.http.FormUrlEncoded 8 | import retrofit2.http.GET 9 | import retrofit2.http.POST 10 | 11 | /** 12 | * Created by tyln on 12/09/2017. 13 | */ 14 | interface TrackerServices { 15 | @GET("money") 16 | fun getDiffs(): Single> 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/binding/BindingConversion.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.binding 2 | 3 | import android.view.View 4 | import com.raqun.dctracker.data.DataBean 5 | import com.raqun.dctracker.data.DataState 6 | import android.databinding.BindingConversion 7 | 8 | /** 9 | * Created by tyln on 12/09/2017. 10 | */ 11 | object BindingConversion { 12 | 13 | @JvmStatic 14 | @BindingConversion 15 | fun bindBeanToProgress(bean: DataBean?): Int 16 | = if (bean?.getState() == DataState.FETCHING && bean.getData() == null) View.VISIBLE else View.GONE 17 | 18 | @JvmStatic 19 | @BindingConversion 20 | fun bindBooleanToVisiblity(isVisible: Boolean): Int 21 | = if (isVisible) View.VISIBLE else View.GONE 22 | 23 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/data/DataBean.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.data 2 | 3 | /** 4 | * Created by tyln on 12/09/2017. 5 | */ 6 | interface DataBean { 7 | fun getData(): T? 8 | 9 | fun getState(): DataState 10 | 11 | fun hasError(): Boolean 12 | 13 | fun getError(): Error? 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/data/DataState.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.data 2 | 3 | /** 4 | * Created by tyln on 12/09/2017. 5 | */ 6 | enum class DataState { 7 | FETCHING, 8 | SUCCESS, 9 | ERROR 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/data/Error.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.data 2 | 3 | /** 4 | * Created by tyln on 12/09/2017. 5 | */ 6 | data class Error constructor(val code: Int, val message: String) -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/data/source/DiffDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.data.source 2 | 3 | import com.raqun.dctracker.model.Diff 4 | import io.reactivex.Single 5 | 6 | /** 7 | * Created by tyln on 12/09/2017. 8 | */ 9 | interface DiffDataSource { 10 | fun getDiffs(): Single> 11 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/data/source/remote/DiffRemoteDataSource.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.data.source.remote 2 | 3 | import com.raqun.dctracker.api.TrackerServices 4 | import com.raqun.dctracker.data.source.DiffDataSource 5 | import com.raqun.dctracker.model.Diff 6 | import io.reactivex.Single 7 | import javax.inject.Inject 8 | 9 | /** 10 | * Created by tyln on 12/09/2017. 11 | */ 12 | class DiffRemoteDataSource @Inject constructor(private val trackerServices: TrackerServices) 13 | : DiffDataSource { 14 | 15 | override fun getDiffs(): Single> = trackerServices.getDiffs() 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/ActivityModule.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import com.raqun.dctracker.ui.home.HomeActivity 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by tyln on 12/09/2017. 9 | */ 10 | @Module 11 | internal abstract class ActivityModule { 12 | 13 | @ContributesAndroidInjector(modules = arrayOf(FragmentBuildersModule::class)) 14 | @ActivityScope 15 | abstract fun provideHomeActivityContributor(): HomeActivity 16 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/ActivityScope.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import javax.inject.Scope 4 | 5 | /** 6 | * Created by tyln on 12/09/2017. 7 | */ 8 | @Scope 9 | @Retention(AnnotationRetention.RUNTIME) 10 | internal annotation class ActivityScope -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/ApiModule.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import com.raqun.dctracker.BuildConfig 4 | import com.raqun.dctracker.api.ApiConstants 5 | import com.raqun.dctracker.api.DefaultRequestInterceptor 6 | import com.raqun.dctracker.api.TrackerServices 7 | import dagger.Module 8 | import dagger.Provides 9 | import okhttp3.Interceptor 10 | import okhttp3.OkHttpClient 11 | import okhttp3.logging.HttpLoggingInterceptor 12 | import retrofit2.Retrofit 13 | import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory 14 | import retrofit2.converter.gson.GsonConverterFactory 15 | import java.util.concurrent.TimeUnit 16 | import javax.inject.Named 17 | import javax.inject.Singleton 18 | 19 | /** 20 | * Created by tyln on 12/09/2017. 21 | */ 22 | @Module 23 | internal class ApiModule { 24 | 25 | @Provides @Singleton @Named("url") fun provideBaseUrl(): String = "www.example.com" 26 | 27 | @Provides @Singleton fun provideRequestInterceptor(): Interceptor 28 | = DefaultRequestInterceptor() 29 | 30 | @Provides @Singleton fun provideLoggingInterceptor(): HttpLoggingInterceptor { 31 | return HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BODY } 32 | } 33 | 34 | @Provides @Singleton fun provideOkHttpClient(requestInterceptor: DefaultRequestInterceptor, 35 | loggingInterceptor: HttpLoggingInterceptor): OkHttpClient { 36 | return with(OkHttpClient.Builder()) { 37 | addInterceptor(requestInterceptor) 38 | if (BuildConfig.DEBUG) addInterceptor(loggingInterceptor) 39 | connectTimeout(ApiConstants.TIMEOUT_INMILIS, TimeUnit.MILLISECONDS) 40 | build() 41 | } 42 | } 43 | 44 | @Provides @Singleton fun provideRetrofit(@Named("url") baseUrl: String, client: OkHttpClient): Retrofit { 45 | return Retrofit.Builder() 46 | .baseUrl(baseUrl) 47 | .client(client) 48 | .addConverterFactory(GsonConverterFactory.create()) 49 | .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) 50 | .build() 51 | } 52 | 53 | @Provides @Singleton fun provideApiServices(retrofit: Retrofit): TrackerServices 54 | = retrofit.create(TrackerServices::class.java) 55 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/AppComponent.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import com.raqun.dctracker.DcTrackerApp 4 | import dagger.BindsInstance 5 | import dagger.Component 6 | import dagger.android.AndroidInjectionModule 7 | import javax.inject.Singleton 8 | 9 | /** 10 | * Created by tyln on 12/09/2017. 11 | */ 12 | @Singleton 13 | @Component(modules = arrayOf( 14 | AndroidInjectionModule::class, 15 | AppModule::class, 16 | ApiModule::class, 17 | ActivityModule::class 18 | )) 19 | interface AppComponent { 20 | 21 | @Component.Builder 22 | interface Builder { 23 | @BindsInstance 24 | fun application(application: DcTrackerApp): Builder 25 | 26 | fun build(): AppComponent 27 | } 28 | 29 | fun inject(application: DcTrackerApp) 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/AppModule.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import com.raqun.dctracker.DcTrackerApp 4 | import com.raqun.dctracker.api.TrackerServices 5 | import com.raqun.dctracker.data.source.remote.DiffRemoteDataSource 6 | import dagger.Module 7 | import dagger.Provides 8 | import javax.inject.Singleton 9 | 10 | /** 11 | * Created by tyln on 12/09/2017. 12 | */ 13 | @Module(includes = arrayOf(ViewModelModule::class)) 14 | internal class AppModule { 15 | 16 | @Provides @Singleton fun provideApplicationContext(app: DcTrackerApp) 17 | = app.applicationContext 18 | 19 | @Provides @Singleton fun provideProductRemoteDataSource(trackerServices: TrackerServices): DiffRemoteDataSource 20 | = DiffRemoteDataSource(trackerServices) 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/FragmentBuildersModule.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import com.raqun.dctracker.ui.home.HomeFragment 4 | import dagger.Module 5 | import dagger.android.ContributesAndroidInjector 6 | 7 | /** 8 | * Created by tyln on 12/09/2017. 9 | */ 10 | @Module 11 | internal abstract class FragmentBuildersModule { 12 | @ContributesAndroidInjector @FragmentScope abstract fun contributeHomeFragment(): HomeFragment 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/FragmentScope.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import javax.inject.Scope 4 | 5 | /** 6 | * Created by tyln on 12/09/2017. 7 | */ 8 | @Scope 9 | @Retention(AnnotationRetention.RUNTIME) 10 | internal annotation class FragmentScope -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/ViewModelKey.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import android.arch.lifecycle.ViewModel 4 | import dagger.MapKey 5 | import kotlin.reflect.KClass 6 | 7 | /** 8 | * Created by tyln on 12/09/2017. 9 | */ 10 | @Retention(AnnotationRetention.RUNTIME) 11 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) 12 | @MapKey 13 | internal annotation class ViewModelKey(val value: KClass) -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/di/ViewModelModule.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.di 2 | 3 | import android.arch.lifecycle.ViewModel 4 | import android.arch.lifecycle.ViewModelProvider 5 | import android.view.View 6 | import com.raqun.dctracker.ui.home.HomeViewModel 7 | import com.raqun.dctracker.viewmodel.VMFactory 8 | import dagger.Binds 9 | import dagger.Module 10 | import dagger.multibindings.IntoMap 11 | 12 | /** 13 | * Created by tyln on 12/09/2017. 14 | */ 15 | @Module 16 | internal abstract class ViewModelModule { 17 | 18 | @Binds 19 | @IntoMap 20 | @ViewModelKey(HomeViewModel::class) 21 | abstract fun bindHomeViewModel(homeViewModel: HomeViewModel): ViewModel 22 | 23 | // Factory 24 | @Binds abstract fun bindViewModelFactory(vmFactory: VMFactory): ViewModelProvider.Factory 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ext/ActivityExt.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ext 2 | 3 | import android.os.Bundle 4 | import android.support.v4.app.Fragment 5 | import android.support.v7.app.AppCompatActivity 6 | import com.raqun.dctracker.R 7 | 8 | /** 9 | * Created by tyln on 26/09/2017. 10 | */ 11 | fun AppCompatActivity.init(savedInstanceState: Bundle?, fragment: Fragment) { 12 | if (savedInstanceState == null) { 13 | this.supportFragmentManager 14 | .beginTransaction() 15 | .replace(R.id.framelayout_main, fragment) 16 | .commit() 17 | } 18 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ext/FragmentManagerExt.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ext 2 | 3 | import android.support.annotation.IdRes 4 | import android.support.v4.app.Fragment 5 | import android.support.v4.app.FragmentManager 6 | import android.support.v4.app.FragmentTransaction 7 | 8 | /** 9 | * Created by tyln on 26/09/2017. 10 | */ 11 | inline fun FragmentManager.navigate(func: FragmentTransaction.() -> FragmentTransaction) { 12 | beginTransaction().func().commit() 13 | } 14 | 15 | fun FragmentManager.openFragment(@IdRes flId: Int, fragment: Fragment) { 16 | beginTransaction() 17 | .replace(flId, fragment) 18 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) 19 | .commit() 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ext/RecyclerViewExt.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ext 2 | 3 | import android.content.Context 4 | import android.support.v7.widget.LinearLayoutManager 5 | import android.support.v7.widget.RecyclerView 6 | 7 | /** 8 | * Created by tyln on 26/09/2017. 9 | */ 10 | fun RecyclerView.setup(context: Context) { 11 | val layoutManager = LinearLayoutManager(context) 12 | layoutManager.orientation = LinearLayoutManager.HORIZONTAL 13 | this.layoutManager = layoutManager 14 | this.setHasFixedSize(true) 15 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/model/DefaultResponse.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by tyln on 12/09/2017. 7 | */ 8 | data class DefaultResponse( 9 | @SerializedName("response_code") val code: Int, 10 | @SerializedName("response_text") val message: String, 11 | @SerializedName("response_data") val data: T 12 | ) -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/model/Diff.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.model 2 | 3 | import com.google.gson.annotations.SerializedName 4 | 5 | /** 6 | * Created by tyln on 12/09/2017. 7 | */ 8 | data class Diff(@SerializedName("id") val id: Int?, 9 | @SerializedName("name") val name: String?, 10 | @SerializedName("tl_buy_rate") val buyRate: Double?, 11 | @SerializedName("tl_sell_rate") val sellRate: Double?) -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/model/UiDataBean.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.model 2 | 3 | import com.raqun.dctracker.data.DataBean 4 | import com.raqun.dctracker.data.DataState 5 | import com.raqun.dctracker.data.Error 6 | 7 | /** 8 | * Created by tyln on 12/09/2017. 9 | */ 10 | class UiDataBean private constructor(private val dataState: DataState, 11 | private val beanData: T?, 12 | private val error: Error?) : DataBean { 13 | 14 | companion object { 15 | fun success(data: T?) = UiDataBean(DataState.SUCCESS, data, null) 16 | 17 | fun error(data: T?, error: Error?) = UiDataBean(DataState.ERROR, data, error) 18 | 19 | fun fetching(data: T?) = UiDataBean(DataState.FETCHING, data, null) 20 | } 21 | 22 | override fun getData(): T? = beanData 23 | 24 | override fun getState(): DataState = dataState 25 | 26 | override fun hasError(): Boolean = error != null 27 | 28 | override fun getError(): Error? = error 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/BaseActivity.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui 2 | 3 | import android.os.Bundle 4 | import android.support.annotation.LayoutRes 5 | import android.support.annotation.MenuRes 6 | import android.support.annotation.StringRes 7 | import android.support.v4.app.Fragment 8 | import android.support.v7.app.AppCompatActivity 9 | import android.view.Menu 10 | import android.view.MenuItem 11 | import com.raqun.dctracker.Constants 12 | import com.raqun.dctracker.R 13 | import dagger.android.AndroidInjection 14 | import dagger.android.AndroidInjector 15 | import dagger.android.DispatchingAndroidInjector 16 | import dagger.android.support.HasSupportFragmentInjector 17 | import javax.inject.Inject 18 | 19 | /** 20 | * Created by tyln on 12/09/2017. 21 | */ 22 | abstract class BaseActivity : AppCompatActivity(), HasSupportFragmentInjector { 23 | 24 | protected val NAV_TYPE_BACK = 0; 25 | protected val NAV_TYPE_ROOT = 1; 26 | 27 | @Inject lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector 28 | 29 | @LayoutRes abstract fun getLayoutRes(): Int 30 | 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | AndroidInjection.inject(this) 33 | super.onCreate(savedInstanceState) 34 | setContentView(getLayoutRes()) 35 | 36 | // TODO improve this impl 37 | when (getNavigationType()) { 38 | NAV_TYPE_BACK -> supportActionBar?.setDisplayHomeAsUpEnabled(true) 39 | NAV_TYPE_ROOT -> supportActionBar?.setDisplayHomeAsUpEnabled(false) 40 | } 41 | 42 | supportActionBar?.title = getString(getScreenTitle()) 43 | } 44 | 45 | override fun onCreateOptionsMenu(menu: Menu?): Boolean { 46 | if (getMenuRes() != Constants.NO_RES) { 47 | menuInflater.inflate(getMenuRes(), menu) 48 | return true 49 | } 50 | 51 | return super.onCreateOptionsMenu(menu) 52 | } 53 | 54 | override fun onOptionsItemSelected(item: MenuItem?): Boolean { 55 | when (item?.itemId) { 56 | android.R.id.home -> onBackPressed() 57 | } 58 | 59 | return super.onOptionsItemSelected(item) 60 | } 61 | 62 | @StringRes protected open fun getScreenTitle() = R.string.app_name 63 | 64 | @MenuRes protected open fun getMenuRes(): Int = Constants.NO_RES 65 | 66 | protected open fun getNavigationType(): Int = NAV_TYPE_BACK 67 | 68 | override fun supportFragmentInjector(): AndroidInjector = dispatchingAndroidInjector 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/BaseFragment.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui 2 | 3 | import android.app.Application 4 | import android.arch.lifecycle.LifecycleRegistry 5 | import android.arch.lifecycle.LifecycleRegistryOwner 6 | import android.content.Context 7 | import android.os.Bundle 8 | import android.support.annotation.LayoutRes 9 | import android.support.annotation.MenuRes 10 | import android.support.v4.app.Fragment 11 | import android.text.TextUtils 12 | import android.view.* 13 | import android.widget.Toast 14 | import com.raqun.dctracker.Constants 15 | import com.raqun.dctracker.R 16 | import com.raqun.dctracker.api.ApiConstants 17 | import dagger.android.support.AndroidSupportInjection 18 | import dagger.android.support.HasSupportFragmentInjector 19 | import com.raqun.dctracker.data.Error 20 | 21 | /** 22 | * Created by tyln on 12/09/2017. 23 | */ 24 | abstract class BaseFragment : Fragment(), BaseView, LifecycleRegistryOwner { 25 | 26 | protected val lifecycleRegistry: LifecycleRegistry = LifecycleRegistry(this) 27 | protected var navigationController: NavigationController? = null 28 | 29 | @LayoutRes protected abstract fun getLayoutRes(): Int 30 | 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | if (activity is HasSupportFragmentInjector) { 33 | AndroidSupportInjection.inject(this) 34 | } 35 | super.onCreate(savedInstanceState) 36 | navigationController = NavigationController(activity) 37 | } 38 | 39 | override fun onCreateOptionsMenu(menu: Menu?, inflater: MenuInflater?) { 40 | super.onCreateOptionsMenu(menu, inflater) 41 | if (getMenuRes() != Constants.NO_RES) { 42 | inflater?.inflate(getMenuRes(), menu) 43 | } 44 | } 45 | 46 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { 47 | return inflater?.inflate(getLayoutRes(), null, false) 48 | } 49 | 50 | override fun onDestroyView() { 51 | navigationController = null 52 | super.onDestroyView() 53 | } 54 | 55 | override fun onError(e: Error?) { 56 | e?.let { 57 | when (e.code) { 58 | ApiConstants.ERROR_CODE_AUTH -> navigationController?.close() 59 | else -> defaultErrorBehavior(e) 60 | } 61 | } ?: defaultErrorBehavior(e) 62 | } 63 | 64 | private fun defaultErrorBehavior(e: Error?) { 65 | val message: String 66 | if (e != null && !TextUtils.isEmpty(e.message)) message = e.message else message = getString(R.string.error_message_unknown) 67 | alert(message) 68 | } 69 | 70 | protected fun alert(message: String) { 71 | Toast.makeText(context, message, Toast.LENGTH_SHORT).show() 72 | } 73 | 74 | override fun getLifecycle(): LifecycleRegistry = lifecycleRegistry 75 | 76 | @MenuRes protected open fun getMenuRes(): Int = Constants.NO_RES 77 | 78 | fun getApplication(): Application = activity.application 79 | 80 | fun getApplicationContext(): Context = getApplication().applicationContext 81 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/BaseView.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui 2 | import com.raqun.dctracker.data.Error 3 | 4 | /** 5 | * Created by tyln on 12/09/2017. 6 | */ 7 | interface BaseView { 8 | fun onError(e: Error?) 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/BinderFragment.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui 2 | 3 | import android.arch.lifecycle.ViewModel 4 | import android.arch.lifecycle.ViewModelProvider 5 | import android.arch.lifecycle.ViewModelProviders 6 | import android.databinding.DataBindingUtil 7 | import android.databinding.ViewDataBinding 8 | import android.os.Bundle 9 | import android.view.LayoutInflater 10 | import android.view.View 11 | import android.view.ViewGroup 12 | import javax.inject.Inject 13 | 14 | /** 15 | * Created by tyln on 12/09/2017. 16 | */ 17 | abstract class BinderFragment : BaseFragment() { 18 | 19 | @Inject protected lateinit var vmFactory: ViewModelProvider.Factory 20 | protected lateinit var binding: VB 21 | protected lateinit var viewModel: VM 22 | 23 | // TODO improve this impl 24 | abstract fun getModelClass(): Class 25 | 26 | override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? { 27 | binding = DataBindingUtil.inflate(inflater, getLayoutRes(), container, false) 28 | initView() 29 | return binding.root 30 | } 31 | 32 | override fun onActivityCreated(savedInstanceState: Bundle?) { 33 | super.onActivityCreated(savedInstanceState) 34 | viewModel = ViewModelProviders.of(this, vmFactory).get(getModelClass()) 35 | } 36 | 37 | open protected fun initView() { 38 | // Can be overridden from subclasses 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/NavigationController.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui 2 | 3 | import android.app.Activity 4 | import android.content.Intent 5 | import com.raqun.dctracker.ui.home.HomeActivity 6 | 7 | /** 8 | * Created by tyln on 12/09/2017. 9 | */ 10 | class NavigationController(private val activity: Activity) { 11 | 12 | fun close() { 13 | activity.finish() 14 | } 15 | 16 | fun navigteToHome() { 17 | HomeActivity.newIntent(activity).apply { 18 | addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 19 | addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) 20 | }.also { 21 | activity.startActivity(it) 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/home/DiffsAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui.home 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import com.raqun.dctracker.databinding.ItemDiffBinding 7 | import com.raqun.dctracker.model.Diff 8 | 9 | /** 10 | * Created by tyln on 12/09/2017. 11 | */ 12 | class DiffsAdapter(private val products: List) : RecyclerView.Adapter() { 13 | 14 | override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder { 15 | val layoutInflater = LayoutInflater.from(parent?.context) 16 | return ViewHolder(ItemDiffBinding.inflate(layoutInflater, parent, false)) 17 | } 18 | 19 | override fun onBindViewHolder(holder: ViewHolder?, position: Int) { 20 | holder?.let { 21 | val product = products[position] 22 | it.bind(product) 23 | } 24 | } 25 | 26 | override fun getItemCount(): Int = products.size 27 | 28 | class ViewHolder(private val itemBinding: ItemDiffBinding) 29 | : RecyclerView.ViewHolder(itemBinding.root) { 30 | 31 | fun bind(diff: Diff) { 32 | itemBinding.diff = diff 33 | itemBinding.executePendingBindings() 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/home/HomeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui.home 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.support.annotation.LayoutRes 7 | import com.raqun.dctracker.R 8 | import com.raqun.dctracker.ext.init 9 | import com.raqun.dctracker.ui.BaseActivity 10 | 11 | /** 12 | * Created by tyln on 12/09/2017. 13 | */ 14 | class HomeActivity : BaseActivity() { 15 | 16 | @LayoutRes override fun getLayoutRes(): Int = R.layout.activity_home 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | 21 | init(savedInstanceState, HomeFragment.newInstance()) 22 | } 23 | 24 | override fun getNavigationType(): Int = NAV_TYPE_ROOT 25 | 26 | companion object { 27 | fun newIntent(context: Context) = Intent(context, HomeActivity::class.java) 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/home/HomeFragment.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui.home 2 | 3 | import android.arch.lifecycle.Observer 4 | import android.content.Context 5 | import android.os.Bundle 6 | import android.support.v7.widget.LinearLayoutManager 7 | import android.support.v7.widget.RecyclerView 8 | import android.view.View 9 | import com.raqun.dctracker.R 10 | import com.raqun.dctracker.data.DataBean 11 | import com.raqun.dctracker.databinding.FragmentHomeBinding 12 | import com.raqun.dctracker.ext.setup 13 | import com.raqun.dctracker.model.Diff 14 | import com.raqun.dctracker.model.UiDataBean 15 | import com.raqun.dctracker.ui.BinderFragment 16 | 17 | /** 18 | * Created by tyln on 12/09/2017. 19 | */ 20 | 21 | class HomeFragment : BinderFragment() { 22 | 23 | override fun getModelClass() = HomeViewModel::class.java 24 | 25 | override fun getLayoutRes() = R.layout.fragment_home 26 | 27 | override fun onActivityCreated(savedInstanceState: Bundle?) { 28 | super.onActivityCreated(savedInstanceState) 29 | viewModel.getDiffsLiveData().observe(this, Observer { 30 | bean: DataBean>? -> 31 | bean?.let { 32 | binding.diffBean = bean 33 | } 34 | }) 35 | } 36 | 37 | override fun initView() { 38 | binding.diffs.setup(activity) 39 | } 40 | 41 | companion object { 42 | fun newInstance() = HomeFragment() 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/ui/home/HomeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.ui.home 2 | 3 | import android.arch.lifecycle.MutableLiveData 4 | import android.arch.lifecycle.ViewModel 5 | import com.raqun.dctracker.data.DataBean 6 | import com.raqun.dctracker.data.source.remote.DiffRemoteDataSource 7 | import com.raqun.dctracker.model.Diff 8 | import com.raqun.dctracker.model.UiDataBean 9 | import io.reactivex.android.schedulers.AndroidSchedulers 10 | import io.reactivex.schedulers.Schedulers 11 | import javax.inject.Inject 12 | import com.raqun.dctracker.data.Error 13 | import io.reactivex.rxkotlin.subscribeBy 14 | 15 | /** 16 | * Created by tyln on 12/09/2017. 17 | */ 18 | class HomeViewModel @Inject constructor(private val diffRemoteDataSource: DiffRemoteDataSource) 19 | : ViewModel() { 20 | 21 | private val diffsLiveData = MutableLiveData>>() 22 | 23 | init { 24 | getDiffs() 25 | } 26 | 27 | fun getDiffsLiveData() = diffsLiveData 28 | 29 | private fun getDiffs() { 30 | diffsLiveData.value = UiDataBean.fetching(null) 31 | diffRemoteDataSource.getDiffs() 32 | .subscribeOn(Schedulers.io()) 33 | .observeOn(AndroidSchedulers.mainThread()) 34 | .subscribeBy( 35 | onSuccess = { diffsLiveData.value = UiDataBean.success(it) }, 36 | onError = { diffsLiveData.value = UiDataBean.error(null, Error(0, it.localizedMessage)) }) 37 | } 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/raqun/dctracker/viewmodel/VMFactory.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker.viewmodel 2 | 3 | import android.arch.lifecycle.ViewModel 4 | import android.arch.lifecycle.ViewModelProvider 5 | import javax.inject.Inject 6 | import javax.inject.Provider 7 | import javax.inject.Singleton 8 | 9 | /** 10 | * Created by tyln on 12/09/2017. 11 | */ 12 | @Singleton 13 | class VMFactory @Inject constructor(private val creators: Map, @JvmSuppressWildcards Provider>) 14 | : ViewModelProvider.Factory { 15 | 16 | @SuppressWarnings("Unchecked") 17 | override fun create(modelClass: Class): T { 18 | var creator = creators[modelClass] 19 | 20 | if (creator == null) { 21 | for (entry in creators) { 22 | if (modelClass.isAssignableFrom(entry.key)) { 23 | creator = entry.value 24 | break 25 | } 26 | } 27 | } 28 | 29 | if (creator == null) throw IllegalArgumentException("Unknown model class" + modelClass) 30 | 31 | try { 32 | return creator.get() as T 33 | } catch (e: Exception) { 34 | throw RuntimeException(e) 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 12 | 17 | 22 | 27 | 32 | 37 | 42 | 47 | 52 | 57 | 62 | 67 | 72 | 77 | 82 | 87 | 92 | 97 | 102 | 107 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_home.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_diff.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 16 | 17 | 21 | 22 | 26 | 27 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DcTracker 3 | 4 | 5 | An unknown error occurred! 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/raqun/dctracker/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.raqun.dctracker 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext.kotlin_version = '1.1.4' 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.0.0-alpha7' 11 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | mavenCentral() 23 | maven { url 'https://maven.fabric.io/public' } 24 | } 25 | } 26 | 27 | task clean(type: Delete) { 28 | delete rootProject.buildDir 29 | } 30 | 31 | ext { 32 | supportLibraryVersion = '26.0.1' 33 | retrofitVersion = '2.3.0' 34 | loggingInterceptorVersion = '3.8.0' 35 | archVersion = '1.0.0-alpha8' 36 | daggerVersion = '2.11' 37 | gsonVersion = '2.0.2' 38 | rxKotlinVersion = '2.1.0' 39 | dataBindingCompilerVersion = '2.3.1' 40 | } 41 | 42 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/savepopulation/digital-currency-tracker/11eb67127bc208985868be2d32c5fbbf7cacf473/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Sep 12 22:20:01 EET 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-milestone-1-all.zip 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------