├── .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 |
--------------------------------------------------------------------------------