Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migration/gson to kotlinx.serialization #141

Closed
wants to merge 34 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
386d121
add koin dependency
trOnk12 Sep 21, 2023
42f163b
create data source and network modules
trOnk12 Sep 21, 2023
dbab4de
revert the data soource and network modules hilt providers
trOnk12 Sep 21, 2023
f811815
rebase
trOnk12 Sep 25, 2023
b7cdb4a
add viewmodelmodule, use singleOf instead of single for simple injection
trOnk12 Sep 22, 2023
05b9baf
use koinViewModel and create ViewModelModule
trOnk12 Sep 22, 2023
cad6595
rebase
trOnk12 Sep 25, 2023
e899247
pass modules to koin
trOnk12 Sep 22, 2023
2b4780d
change names
trOnk12 Sep 22, 2023
2828975
add check modules tests
trOnk12 Sep 22, 2023
0786d3a
exclude viewmodel from test modules
trOnk12 Sep 22, 2023
e6b070c
mock sharedprefs
trOnk12 Sep 22, 2023
5549d8c
inject with koin remaining dependencies
trOnk12 Sep 25, 2023
688d65f
remove hilt dependencies
trOnk12 Sep 25, 2023
77d1871
remove hilt imports
trOnk12 Sep 25, 2023
53637a4
remove unnucessary hilt imports
trOnk12 Sep 25, 2023
345e012
remove unused imports
trOnk12 Sep 26, 2023
b6b5b44
remove gson from gradle
nowakweronika Sep 27, 2023
9afa456
Merge branch 'koin/migrate_network' into migration/gson_to_kotlinx.se…
nowakweronika Sep 27, 2023
d1e9f1b
auth kotlinx serialization implementation
nowakweronika Sep 28, 2023
7d2742a
add logs
nowakweronika Oct 9, 2023
80ad1e9
Merge branch 'develop' into migration/gson_to_kotlinx.serialization
nowakweronika Oct 9, 2023
3d8507e
add LocalDateTime formatter
nowakweronika Oct 12, 2023
222b505
[MegaLinter] Apply linters fixes
nowakweronika Oct 12, 2023
1ce1a0f
adjust tests
nowakweronika Oct 16, 2023
a49c57c
Merge remote-tracking branch 'origin/migration/gson_to_kotlinx.serial…
nowakweronika Oct 16, 2023
f7b23e2
[MegaLinter] Apply linters fixes
nowakweronika Oct 16, 2023
2444049
adjust tests
nowakweronika Oct 18, 2023
5f5a8eb
adjust tests
nowakweronika Oct 18, 2023
6e9c0d6
cleanup
nowakweronika Oct 18, 2023
d181b39
LocalDateTime -> Instant
nowakweronika Oct 19, 2023
6dd4e04
adjust tests
nowakweronika Oct 19, 2023
584ad31
Merge branch 'develop' into migration/gson_to_kotlinx.serialization
nowakweronika Oct 19, 2023
b4722e2
[MegaLinter] Apply linters fixes
nowakweronika Oct 19, 2023
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
16 changes: 14 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ plugins {
id 'org.jetbrains.kotlin.android'
id 'com.google.dagger.hilt.android'
id 'org.jlleitschuh.gradle.ktlint' version '11.2.0'
id 'org.jetbrains.kotlin.plugin.serialization' version '1.8.10'
}

android {
Expand Down Expand Up @@ -133,15 +134,26 @@ dependencies {
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-client-okhttp:$ktor_version"
implementation "io.ktor:ktor-client-content-negotiation:$ktor_version"
implementation "io.ktor:ktor-serialization-gson:$ktor_version"
implementation "io.ktor:ktor-serialization-kotlinx-json:$ktor_version"
testImplementation("io.ktor:ktor-client-mock:$ktor_version")

implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1")
testImplementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1")


//retrofit & okhttp
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.10.0'

//gson
implementation 'com.google.code.gson:gson:2.10.1'
implementation "io.ktor:ktor-serialization-gson:2.3.4"

// koin
implementation "io.insert-koin:koin-androidx-compose:$koin_version"
implementation "io.insert-koin:koin-android:$koin_version"
implementation "io.insert-koin:koin-core:$koin_version"
testImplementation "io.insert-koin:koin-test:$koin_version"

testImplementation project(":app-shared-tests")
androidTestImplementation(project(":app-shared-tests")) {
Expand Down
31 changes: 28 additions & 3 deletions app/src/main/java/com/appunite/loudius/LoudiusApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,32 @@
package com.appunite.loudius

import android.app.Application
import dagger.hilt.android.HiltAndroidApp
import com.appunite.loudius.di.dataSourceModule
import com.appunite.loudius.di.dispatcherModule
import com.appunite.loudius.di.githubHelperModule
import com.appunite.loudius.di.networkModule
import com.appunite.loudius.di.repositoryModule
import com.appunite.loudius.di.serviceModule
import com.appunite.loudius.di.viewModelModule
import org.koin.android.ext.koin.androidContext
import org.koin.core.context.GlobalContext.startKoin

@HiltAndroidApp
class LoudiusApplication : Application()
class LoudiusApplication : Application() {
override fun onCreate() {
super.onCreate()

startKoin {
androidContext(this@LoudiusApplication)

modules(
dataSourceModule,
dispatcherModule,
githubHelperModule,
networkModule,
repositoryModule,
serviceModule,
viewModelModule,
)
}
}
}
6 changes: 2 additions & 4 deletions app/src/main/java/com/appunite/loudius/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
Expand All @@ -37,12 +36,11 @@ import com.appunite.loudius.ui.authenticating.AuthenticatingScreen
import com.appunite.loudius.ui.login.LoginScreen
import com.appunite.loudius.ui.pullrequests.PullRequestsScreen
import com.appunite.loudius.ui.reviewers.ReviewersScreen
import dagger.hilt.android.AndroidEntryPoint
import org.koin.androidx.viewmodel.ext.android.viewModel

@AndroidEntryPoint
class MainActivity : ComponentActivity() {

private val viewModel: MainViewModel by viewModels()
private val viewModel by viewModel<MainViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Expand Down
9 changes: 4 additions & 5 deletions app/src/main/java/com/appunite/loudius/common/Screen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import androidx.navigation.NavDeepLink
import androidx.navigation.NavType
import androidx.navigation.navArgument
import androidx.navigation.navDeepLink
import java.time.LocalDateTime
import kotlinx.datetime.Instant
import kotlinx.datetime.toInstant

sealed class Screen(val route: String) {
open val arguments: List<NamedNavArgument> = emptyList()
Expand Down Expand Up @@ -76,16 +77,14 @@ sealed class Screen(val route: String) {
owner = checkNotNull(savedStateHandle[ownerArg]),
repo = checkNotNull(savedStateHandle[repoArg]),
pullRequestNumber = checkNotNull(savedStateHandle[pullRequestNumberArg]),
submissionTime = checkNotNull(
LocalDateTime.parse(savedStateHandle[submissionDateArg]),
),
submissionTime = checkNotNull((savedStateHandle[submissionDateArg] ?: "").toInstant()),
)

data class ReviewersInitialValues(
val owner: String,
val repo: String,
val pullRequestNumber: String,
val submissionTime: LocalDateTime,
val submissionTime: Instant,
)
}
}
27 changes: 0 additions & 27 deletions app/src/main/java/com/appunite/loudius/di/APIQualifiers.kt

This file was deleted.

44 changes: 8 additions & 36 deletions app/src/main/java/com/appunite/loudius/di/DataSourceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@

package com.appunite.loudius.di

import android.content.Context
import com.appunite.loudius.domain.store.UserLocalDataSource
import com.appunite.loudius.domain.store.UserLocalDataSourceImpl
import com.appunite.loudius.network.datasource.AuthDataSource
Expand All @@ -25,40 +24,13 @@ import com.appunite.loudius.network.datasource.PullRequestDataSource
import com.appunite.loudius.network.datasource.PullRequestsDataSourceImpl
import com.appunite.loudius.network.datasource.UserDataSource
import com.appunite.loudius.network.datasource.UserDataSourceImpl
import com.appunite.loudius.network.services.AuthService
import com.appunite.loudius.network.services.PullRequestsService
import com.appunite.loudius.network.services.UserService
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

@InstallIn(SingletonComponent::class)
@Module
object DataSourceModule {

@Provides
@Singleton
fun providePullRequestNetworkDataSource(
service: PullRequestsService,
): PullRequestDataSource = PullRequestsDataSourceImpl(service)

@Provides
@Singleton
fun provideUserDataSource(
userService: UserService,
): UserDataSource = UserDataSourceImpl(userService)

@Singleton
@Provides
fun provideUserLocalDataSource(@ApplicationContext context: Context): UserLocalDataSource =
UserLocalDataSourceImpl(context)

@Singleton
@Provides
fun provideAuthDataSource(
service: AuthService,
): AuthDataSource = AuthDataSourceImpl(service)
val dataSourceModule = module {
singleOf(::UserDataSourceImpl) { bind<UserDataSource>() }
singleOf(::UserLocalDataSourceImpl) { bind<UserLocalDataSource>() }
singleOf(::AuthDataSourceImpl) { bind<AuthDataSource>() }
singleOf(::PullRequestsDataSourceImpl) { bind<PullRequestDataSource>() }
}
13 changes: 3 additions & 10 deletions app/src/main/java/com/appunite/loudius/di/DispatchersModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,10 @@

package com.appunite.loudius.di

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import org.koin.dsl.module

@InstallIn(SingletonComponent::class)
@Module
object DispatchersModule {

@Provides
fun provideDefaultDispatcher(): CoroutineDispatcher = Dispatchers.Default
val dispatcherModule = module {
factory<CoroutineDispatcher> { Dispatchers.Default }
}
18 changes: 4 additions & 14 deletions app/src/main/java/com/appunite/loudius/di/GithubHelperModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,10 @@

package com.appunite.loudius.di

import android.content.Context
import com.appunite.loudius.ui.login.GithubHelper
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

@InstallIn(SingletonComponent::class)
@Module
object GithubHelperModule {
@Provides
@Singleton
fun providePullRequestNetworkDataSource(@ApplicationContext context: Context): GithubHelper =
GithubHelper(context)
val githubHelperModule = module {
singleOf(::GithubHelper)
}
116 changes: 44 additions & 72 deletions app/src/main/java/com/appunite/loudius/di/NetworkModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,91 +20,63 @@ import com.appunite.loudius.common.Constants
import com.appunite.loudius.network.intercept.AuthFailureInterceptor
import com.appunite.loudius.network.intercept.AuthInterceptor
import com.appunite.loudius.network.utils.AuthFailureHandler
import com.appunite.loudius.network.utils.LocalDateTimeDeserializer
import com.google.gson.FieldNamingPolicy
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.ktor.client.HttpClient
import io.ktor.client.engine.okhttp.OkHttp
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
import io.ktor.http.ContentType
import io.ktor.serialization.gson.GsonConverter
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import okhttp3.logging.HttpLoggingInterceptor
import java.time.LocalDateTime
import javax.inject.Singleton
import org.koin.core.module.dsl.singleOf
import org.koin.core.qualifier.named
import org.koin.dsl.module

@InstallIn(SingletonComponent::class)
@Module
object NetworkModule {
@Provides
@Singleton
fun provideLoggingInterceptor(): HttpLoggingInterceptor = HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BASIC
val networkModule = module {
single {
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BASIC
}
}

@Provides
@AuthAPI
fun provideBaseAuthUrl() = Constants.AUTH_API_URL

@Provides
@BaseAPI
fun provideBaseAPIUrl() = Constants.BASE_API_URL

@Provides
@Singleton
@AuthAPI
fun provideAuthHttpClient(
gson: Gson,
@AuthAPI baseUrl: String,
loggingInterceptor: HttpLoggingInterceptor,
): HttpClient = HttpClient(OkHttp) {
expectSuccess = true
engine {
addInterceptor(TestInterceptor)
addInterceptor(loggingInterceptor)
}
defaultRequest {
url(baseUrl)
}
install(ContentNegotiation) {
register(ContentType.Application.Json, GsonConverter(gson))
single(named("auth")) {
HttpClient(OkHttp) {
expectSuccess = true
engine {
addInterceptor(TestInterceptor)
addInterceptor(get<HttpLoggingInterceptor>())
}
defaultRequest {
url(Constants.AUTH_API_URL)
}
install(ContentNegotiation) {
json(get())
}
}
}

@Provides
@Singleton
@BaseAPI
fun provideBaseHttpClient(
gson: Gson,
@BaseAPI baseUrl: String,
loggingInterceptor: HttpLoggingInterceptor,
authInterceptor: AuthInterceptor,
authFailureHandler: AuthFailureHandler,
): HttpClient = HttpClient(OkHttp) {
expectSuccess = true
engine {
addInterceptor(authInterceptor)
addInterceptor(TestInterceptor)
addInterceptor(AuthFailureInterceptor(authFailureHandler))
addInterceptor(loggingInterceptor)
}
defaultRequest {
url(baseUrl)
single(named("base")) {
HttpClient(OkHttp) {
expectSuccess = true
engine {
addInterceptor(TestInterceptor)
addInterceptor(get<HttpLoggingInterceptor>())
addInterceptor(AuthFailureInterceptor(get()))
addInterceptor(AuthInterceptor(get()))
}
defaultRequest {
url(Constants.BASE_API_URL)
}
install(ContentNegotiation) {
json(get())
}
}
install(ContentNegotiation) {
register(ContentType.Application.Json, GsonConverter(gson))
}

single {
Json {
ignoreUnknownKeys = true
}
}

@Provides
@Singleton
fun provideGson(): Gson =
GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(LocalDateTime::class.java, LocalDateTimeDeserializer())
.create()
singleOf(::AuthFailureHandler)
}
Loading
Loading