Skip to content

Commit

Permalink
init hello get
Browse files Browse the repository at this point in the history
  • Loading branch information
stslex committed Jul 23, 2023
1 parent 1dd73dc commit 7be7e66
Show file tree
Hide file tree
Showing 12 changed files with 173 additions and 24 deletions.
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

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

<application
android:name=".SelectApplication"
android:allowBackup="true"
Expand All @@ -12,6 +14,7 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.AProSelection"
android:usesCleartextTraffic="true"
tools:targetApi="31">
<activity
android:name=".ui.MainActivity"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.stslex.aproselection

import android.app.Application
import com.stslex.aproselection.core.network.di.ModuleCoreNetwork.moduleCoreNetwork
import com.stslex.aproselection.feature.auth.di.ModuleFeatureAuth.moduleFeatureAuth
import org.koin.android.ext.koin.androidContext
import org.koin.android.ext.koin.androidLogger
import org.koin.core.context.startKoin

class SelectApplication : Application() {

override fun onCreate() {
super.onCreate()
startKoin {
androidLogger()
androidContext(applicationContext)
modules(moduleFeatureAuth)
modules(
moduleFeatureAuth,
moduleCoreNetwork
)
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.stslex.aproselection

import android.content.Context
import com.stslex.aproselection.core.network.di.ModuleCoreNetwork
import com.stslex.aproselection.core.network.di.ModuleCoreNetwork.moduleCoreNetwork
import com.stslex.aproselection.feature.auth.di.ModuleFeatureAuth.moduleFeatureAuth
import org.junit.Test
import org.koin.android.ext.koin.androidContext
Expand All @@ -15,7 +17,10 @@ class DiKoinModuleTest : KoinTest {
fun checkKoinModules() {
koinApplication {
androidContext(Mockito.mock(Context::class.java))
modules(moduleFeatureAuth)
modules(
moduleFeatureAuth,
moduleCoreNetwork
)
checkModules()
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.stslex.aproselection

import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.DefaultConfig
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.artifacts.VersionCatalogsExtension
Expand All @@ -27,7 +25,6 @@ internal fun Project.configureKotlinAndroid(
defaultConfig {
minSdk = 28
buildFeatures.buildConfig = true
setLocalProperty(project.rootProject)
}

compileOptions {
Expand Down Expand Up @@ -102,13 +99,3 @@ private fun Project.configureKotlin() {
}
}
}


fun DefaultConfig.setLocalProperty(
dir: Project
) {
val key = gradleLocalProperties(dir.projectDir)["API_KEY"]
?.toString()
?: throw IllegalStateException("API_KEY should be initialised")
buildConfigField("String", "API_KEY", key)
}

This file was deleted.

15 changes: 15 additions & 0 deletions core/network/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties

plugins {
id("aproselection.android.library")
kotlin("plugin.serialization")
Expand All @@ -9,3 +11,16 @@ dependencies {
}

android.namespace = "com.stslex.aproselection.core.network"

val properties = gradleLocalProperties(rootDir)
val key = properties["API_KEY"]?.toString()
?: throw IllegalStateException("API_KEY")
val apiHost = properties["API_SERVER_HOST"]?.toString()
?: throw IllegalStateException("API_SERVER_HOST")

android {
defaultConfig {
buildConfigField("String", "API_KEY", key)
buildConfigField("String", "API_SERVER_HOST", apiHost)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.stslex.aproselection.core.network.client

import io.ktor.client.HttpClient

interface NetworkClient {

val client: HttpClient

val apiClient: HttpClient
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package com.stslex.aproselection.core.network.client

import com.stslex.aproselection.core.network.BuildConfig
import io.ktor.client.HttpClient
import io.ktor.client.engine.android.Android
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.defaultRequest
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.http.URLProtocol
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json

class NetworkClientImpl : NetworkClient {

@OptIn(ExperimentalSerializationApi::class)
override val client: HttpClient
get() = HttpClient(Android) {

expectSuccess = true

install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}

install(ContentNegotiation) {
json(
Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
explicitNulls = false
}
)
}
}

override val apiClient: HttpClient
get() = client.config {
defaultRequest {
url {
host = "${BuildConfig.API_SERVER_HOST}$HOST_API_URL"
protocol = URLProtocol.HTTP
}
// headers {
// append(
// HEADER_AUTH,
// "$HEADER_AUTH_FIELD ${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,14 @@
package com.stslex.aproselection.core.network.di

import com.stslex.aproselection.core.network.client.NetworkClient
import com.stslex.aproselection.core.network.client.NetworkClientImpl
import org.koin.core.module.dsl.bind
import org.koin.core.module.dsl.singleOf
import org.koin.dsl.module

object ModuleCoreNetwork {

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

import android.content.Context
import com.stslex.aproselection.core.network.di.ModuleCoreNetwork.moduleCoreNetwork
import org.junit.Test
import org.koin.android.ext.koin.androidContext
import org.koin.dsl.koinApplication
import org.koin.test.KoinTest
import org.koin.test.check.checkModules
import org.mockito.Mockito

class DiKoinModuleTest : KoinTest {

@Test
fun checkKoinModules() {
koinApplication {
androidContext(Mockito.mock(Context::class.java))
modules(moduleCoreNetwork)
checkModules()
}
}
}
3 changes: 3 additions & 0 deletions feature/auth/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
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
@@ -1,15 +1,41 @@
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 kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flowOf
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 : ViewModel() {
class AuthViewModel(
private val networkClient: NetworkClient
) : ViewModel() {

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

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

0 comments on commit 7be7e66

Please sign in to comment.