Skip to content

Commit

Permalink
fix api version, add basic architecture structure
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Jul 23, 2023
1 parent 7be7e66 commit 1ae1c57
Show file tree
Hide file tree
Showing 14 changed files with 132 additions and 47 deletions.
3 changes: 3 additions & 0 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ val key = properties["API_KEY"]?.toString()
?: throw IllegalStateException("API_KEY")
val apiHost = properties["API_SERVER_HOST"]?.toString()
?: throw IllegalStateException("API_SERVER_HOST")
val apiVersion = properties["API_VERSION"]?.toString()
?: throw IllegalStateException("API_VERSION")

android {
defaultConfig {
buildConfigField("String", "API_KEY", key)
buildConfigField("String", "API_SERVER_HOST", apiHost)
buildConfigField("String", "API_VERSION", apiVersion)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import io.ktor.client.plugins.logging.DEFAULT
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logger
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.bearerAuth
import io.ktor.http.URLProtocol
import io.ktor.http.encodedPath
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
Expand Down Expand Up @@ -43,21 +45,11 @@ class NetworkClientImpl : NetworkClient {
get() = client.config {
defaultRequest {
url {
host = "${BuildConfig.API_SERVER_HOST}$HOST_API_URL"
host = BuildConfig.API_SERVER_HOST
encodedPath = BuildConfig.API_VERSION
protocol = URLProtocol.HTTP
}
// headers {
// append(
// HEADER_AUTH,
// "$HEADER_AUTH_FIELD ${BuildConfig.API_KEY}"
// )
// }
bearerAuth(BuildConfig.API_KEY)
}
}

companion object {
private const val HOST_API_URL = "/api/v1"
private const val HEADER_AUTH = "Authorization"
private const val HEADER_AUTH_FIELD = "Client-ID"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.aproselection.core.network.clients.auth

import com.stslex.aproselection.core.network.clients.auth.model.HelloRequestModel

interface AuthNetworkClient {

suspend fun getHello(): HelloRequestModel
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.stslex.aproselection.core.network.clients.auth

import com.stslex.aproselection.core.network.client.NetworkClient
import com.stslex.aproselection.core.network.clients.auth.model.HelloRequestModel
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.http.appendPathSegments

class AuthNetworkClientImpl(
private val networkClient: NetworkClient
) : AuthNetworkClient {

override suspend fun getHello(): HelloRequestModel = networkClient
.apiClient
.get {
url.appendPathSegments("hello")
}
.body()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.stslex.aproselection.core.network.clients.auth.model

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class HelloRequestModel(
@SerialName("text")
val text: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package com.stslex.aproselection.core.network.di

import com.stslex.aproselection.core.network.client.NetworkClient
import com.stslex.aproselection.core.network.client.NetworkClientImpl
import com.stslex.aproselection.core.network.clients.auth.AuthNetworkClient
import com.stslex.aproselection.core.network.clients.auth.AuthNetworkClientImpl
import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module
Expand All @@ -10,5 +12,6 @@ object ModuleCoreNetwork {

val moduleCoreNetwork = module {
singleOf(::NetworkClientImpl) { bind<NetworkClient>() }
singleOf(::AuthNetworkClientImpl) { bind<AuthNetworkClient>() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.stslex.aproselection.core.ui.base

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn

open class BaseViewModel : ViewModel() {

fun <T> Flow<T>.stateIn(
initialValue: T
): StateFlow<T> = this.stateIn(
scope = viewModelScope,
started = SharingStarted.Lazily,
initialValue = initialValue
)

fun handleError(throwable: Throwable) {
Log.e(javaClass.simpleName, throwable.message, throwable)
}
}
3 changes: 0 additions & 3 deletions feature/auth/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
plugins {
id("aproselection.android.library")
id("aproselection.android.library.compose")
kotlin("plugin.serialization")
}

dependencies {
implementation(project(":core:ui"))
implementation(project(":core:network"))
implementation(libs.bundles.ktor)
implementation(libs.bundles.okhttp)
}

android.namespace = "com.stslex.aproselection.feature.auth"
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.aproselection.feature.auth.data.repository

import kotlinx.coroutines.flow.Flow

interface AuthRepository {

val hello: Flow<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.stslex.aproselection.feature.auth.data.repository

import com.stslex.aproselection.core.network.clients.auth.AuthNetworkClient
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

class AuthRepositoryImpl(
private val networkClient: AuthNetworkClient
) : AuthRepository {

override val hello: Flow<String> = flow {
val helloResponse = networkClient.getHello().text
emit(helloResponse)
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
package com.stslex.aproselection.feature.auth.di

import com.stslex.aproselection.feature.auth.data.repository.AuthRepository
import com.stslex.aproselection.feature.auth.data.repository.AuthRepositoryImpl
import com.stslex.aproselection.feature.auth.domain.interactor.AuthInteractor
import com.stslex.aproselection.feature.auth.domain.interactor.AuthInteractorImpl
import com.stslex.aproselection.feature.auth.ui.AuthViewModel
import org.koin.androidx.viewmodel.dsl.viewModelOf
import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.factoryOf
import org.koin.dsl.module

object ModuleFeatureAuth {

val moduleFeatureAuth = module {
viewModelOf(::AuthViewModel)
factoryOf(::AuthInteractorImpl) { bind<AuthInteractor>() }
factoryOf(::AuthRepositoryImpl) { bind<AuthRepository>() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.stslex.aproselection.feature.auth.domain.interactor

import kotlinx.coroutines.flow.Flow

interface AuthInteractor {

val hello: Flow<String>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.stslex.aproselection.feature.auth.domain.interactor

import com.stslex.aproselection.feature.auth.data.repository.AuthRepository
import kotlinx.coroutines.flow.Flow

class AuthInteractorImpl(
private val repository: AuthRepository
) : AuthInteractor {

override val hello: Flow<String>
get() = repository.hello
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@
package com.stslex.aproselection.feature.auth.ui

import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.stslex.aproselection.core.network.client.NetworkClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.http.appendPathSegments
import kotlinx.coroutines.flow.SharingStarted
import com.stslex.aproselection.core.ui.base.BaseViewModel
import com.stslex.aproselection.feature.auth.domain.interactor.AuthInteractor
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

class AuthViewModel(
private val networkClient: NetworkClient
) : ViewModel() {
private val interactor: AuthInteractor
) : BaseViewModel() {

val text: StateFlow<String>
get() = flow {
val result = networkClient.apiClient.get {
url.appendPathSegments("hello")
get() = interactor
.hello
.catch { throwable ->
handleError(throwable)
}
.body<HelloRequest>()
.hello
emit(result)
}
.catch {
Log.e(javaClass.simpleName, it.message, it)
}
.stateIn(viewModelScope, SharingStarted.Lazily, "")
.stateIn("")
}

@Serializable
data class HelloRequest(
@SerialName("text")
val hello: String
)

0 comments on commit 1ae1c57

Please sign in to comment.