Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions .idea/kotlinScripting.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 0 additions & 12 deletions .idea/runConfigurations.xml

This file was deleted.

35 changes: 0 additions & 35 deletions app/build.gradle

This file was deleted.

62 changes: 62 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
plugins {
id("com.android.application")
kotlin("android")
kotlin("kapt")
id("kotlin-parcelize")
id("kotlin-android")
}

android {
compileSdkVersion(Versions.compileSdk)

defaultConfig {
minSdkVersion(Versions.minSdk)
targetSdkVersion(Versions.targetSdk)

applicationId = Versions.applicationId
versionCode = Versions.versionCode
versionName = Versions.versionName

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
getByName("release") {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android.txt"),
"proguard-rules.pro"
)
}
}

buildFeatures {
dataBinding = true
viewBinding = true
}
}

dependencies {
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar"))))

implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}")
implementation("androidx.appcompat:appcompat:${Versions.appCompat}")
implementation("androidx.constraintlayout:constraintlayout:${Versions.constraintLayout}")
implementation("androidx.core:core-ktx:${Versions.corektx}")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.coroutines}")
implementation("com.github.bumptech.glide:glide:${Versions.glide}")
implementation("com.google.code.gson:gson:${Versions.gson}")
implementation("org.koin:koin-core:${Versions.koin}")
implementation("org.koin:koin-android:${Versions.koin}")
implementation("org.koin:koin-androidx-viewmodel:${Versions.koin}")
implementation("com.google.android.material:material:${Versions.material}")
implementation("androidx.multidex:multidex:${Versions.multidex}")
implementation("com.squareup.retrofit2:retrofit:${Versions.retrofit}")
implementation("com.squareup.retrofit2:converter-gson:${Versions.retrofitConverterGson}")

testImplementation("androidx.arch.core:core-testing:${Versions.androidCoreTesting}")
testImplementation("junit:junit:${Versions.junit}")
testImplementation("io.mockk:mockk:${Versions.mockk}")
androidTestImplementation("androidx.test:runner:${Versions.testRunner}")
androidTestImplementation("androidx.test.espresso:espresso-core:${Versions.espresso}")
}

This file was deleted.

11 changes: 9 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.com.aisdigital.androidchallenge">

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
android:theme="@style/AppTheme"
android:name=".view.base.BaseApplication">
<activity android:name=".view.login.LoginActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".view.home.HomeActivity"
android:exported="true" />
</application>

</manifest>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package br.com.aisdigital.androidchallenge.di

import br.com.aisdigital.androidchallenge.domain.model.error.ErrorHandler
import br.com.aisdigital.androidchallenge.domain.repository.*
import br.com.aisdigital.androidchallenge.domain.repository.interactor.AuthInteractor
import br.com.aisdigital.androidchallenge.domain.repository.interactor.LoginInteractor
import br.com.aisdigital.androidchallenge.domain.repository.interactor.TeamsInteractor
import br.com.aisdigital.androidchallenge.domain.repository.remote.API
import br.com.aisdigital.androidchallenge.domain.repository.remote.RetrofitClient
import br.com.aisdigital.androidchallenge.viewmodel.home.HomeViewModel
import br.com.aisdigital.androidchallenge.viewmodel.login.LoginViewModel
import org.koin.android.ext.koin.androidApplication
import org.koin.android.ext.koin.androidContext
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.loadKoinModules
import org.koin.dsl.module

fun loadKoinModules() {
loadKoinModules(
listOf(
interactorModule,
viewModelModule,
routerModule,
networkModule,
errorHandlerModule,
resourcesModule
)
)
}

private val interactorModule = module {
factory {
AuthInteractor(
repository = get(),
errorHandler = get()
)
}
factory {
LoginInteractor(
repository = get(),
errorHandler = get()
)
}
factory {
TeamsInteractor(
repository = get(),
errorHandler = get()
)
}
}

private val viewModelModule = module {
viewModel {
LoginViewModel(
router = get(),
authInteractor = get(),
loginInteractor = get(),
resources = get()
)
}
viewModel {
HomeViewModel(
teamsInteractor = get(),
resources = get()
)
}
}

private val routerModule = module {
factory {
Router(androidApplication())
}
}

private val networkModule = module {
factory<Repository> {
RemoteDataSource(api = get())
}

single(override = true) {
RetrofitClient.createService(API::class.java)
}
}

private val errorHandlerModule = module(override = true) {
single { ErrorHandler(get()) }
}

private val resourcesModule = module(override = true) {
single { androidContext().resources }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package br.com.aisdigital.androidchallenge.domain.model

import br.com.aisdigital.androidchallenge.domain.model.error.ErrorResponse

sealed class RequestState<out T> {
object Idle : RequestState<Nothing>()
object Loading: RequestState<Nothing>()
data class Error(val error: ErrorResponse? = null) : RequestState<Nothing>()
data class Success<T>(val result: T) : RequestState<T>()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package br.com.aisdigital.androidchallenge.domain.model.auth

import com.google.gson.annotations.SerializedName

data class AuthResponse(@SerializedName("token") val token: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package br.com.aisdigital.androidchallenge.domain.model.error

import android.content.res.Resources
import br.com.aisdigital.androidchallenge.R
import com.google.gson.Gson
import retrofit2.HttpException

class ErrorHandler(private val resources: Resources, private val gson: Gson = Gson()) {

companion object {
private const val UNEXPECTED_ERROR_NAME = "NO-NAME"
}

fun buildErrorResponse(e: Exception? = null) = if (e is HttpException) {
parseToError(e.response()?.errorBody()?.string())
} else {
buildGenericErrorResponse()
}

private fun parseToError(backendErrorString: String?): ErrorResponse {
return try {
return gson.fromJson(backendErrorString.orEmpty(), ErrorResponse::class.java)
} catch (ex: Exception) {
buildGenericErrorResponse()
}
}

private fun buildGenericErrorResponse(): ErrorResponse {
return ErrorResponse(
ErrorBody(
UNEXPECTED_ERROR_NAME,
resources.getString(R.string.generic_error_message),
null,
)
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package br.com.aisdigital.androidchallenge.domain.model.error

import com.google.gson.annotations.SerializedName

data class ErrorResponse(
@SerializedName("error") val error: ErrorBody
)

data class ErrorBody(
@SerializedName("name") val name: String?,
@SerializedName("message") val message: String?,
@SerializedName("header") val header: String?
)
Loading