Adding Authentication with AllIn API
continuous-integration/drone/push Build is passing Details

pull/3/head
Arthur VALIN 1 year ago
parent 7dfe35caeb
commit b7337e679a

@ -5,7 +5,18 @@ plugins {
id "dagger.hilt.android.plugin" id "dagger.hilt.android.plugin"
} }
def keystorePropertiesFile = rootProject.file("app/keys/keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android { android {
signingConfigs {
release {
storeFile file(keystoreProperties['store'])
storePassword keystoreProperties['password']
keyPassword keystoreProperties['password']
}
}
namespace 'fr.iut.alldev.allin' namespace 'fr.iut.alldev.allin'
compileSdk 34 compileSdk 34
@ -24,8 +35,15 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
debug {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
} }
} }
compileOptions { compileOptions {

Binary file not shown.

Binary file not shown.

@ -0,0 +1,2 @@
store=keys/keystore.jks
password=placeYourBets

Binary file not shown.

Binary file not shown.

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name" translatable="false">Allin_DEBUG</string>
</resources>

@ -2,6 +2,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"> xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<application <application
android:name=".AllInApplication" android:name=".AllInApplication"
android:allowBackup="true" android:allowBackup="true"

@ -37,7 +37,6 @@ class MainActivity : ComponentActivity() {
} }
} }
} }
AllInNavHost() AllInNavHost()
} }
} }

@ -0,0 +1,71 @@
package fr.iut.alldev.allin.ui.core
import android.content.res.Configuration
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.sp
import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.theme.AllInTheme
@Composable
fun AllInAlertDialog(
enabled: Boolean = true,
title: String,
text: String,
confirmText: String = stringResource(id = R.string.Ok),
onDismiss: ()->Unit,
onConfirm: ()->Unit = onDismiss
) {
if(enabled) {
AlertDialog(
title = {
Text(
text = title,
fontSize = 20.sp,
style = AllInTheme.typography.h1
)
},
text = {
Text(
text = text,
style = AllInTheme.typography.r
)
},
confirmButton = {
TextButton(
onClick = onConfirm
) {
Text(
text = confirmText,
fontSize = 15.sp,
style = AllInTheme.typography.h1.copy(
brush = AllInTheme.colors.allIn_MainGradient
)
)
}
},
onDismissRequest = onDismiss,
containerColor = AllInTheme.themeColors.main_surface,
titleContentColor = AllInTheme.themeColors.on_main_surface,
textContentColor = AllInTheme.themeColors.on_background_2,
)
}
}
@Preview
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
@Composable
private fun AllInAlertDialogPreview() {
AllInTheme {
AllInAlertDialog(
title = "Titre",
text = "Lorem Ipsum",
onDismiss = {}
)
}
}

@ -1,12 +1,19 @@
package fr.iut.alldev.allin.ui.login package fr.iut.alldev.allin.ui.login
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.* import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.BringIntoViewRequester
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.ClickableText import androidx.compose.foundation.text.ClickableText
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.* import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
@ -17,13 +24,10 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.core.AllInGradientButton import fr.iut.alldev.allin.ui.core.*
import fr.iut.alldev.allin.ui.core.AllInLoading
import fr.iut.alldev.allin.ui.core.AllInPasswordField
import fr.iut.alldev.allin.ui.core.AllInTextField
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class, ExperimentalMaterial3Api::class)
@Composable @Composable
fun LoginScreen( fun LoginScreen(
navigateToDashboard: ()->Unit, navigateToDashboard: ()->Unit,
@ -33,6 +37,10 @@ fun LoginScreen(
val bringIntoViewRequester = BringIntoViewRequester() val bringIntoViewRequester = BringIntoViewRequester()
val loading by remember{ loginViewModel.loading } val loading by remember{ loginViewModel.loading }
var hasLoginError by remember{ loginViewModel.hasError }
val (username, setUsername) = remember{ loginViewModel.username }
val (password, setPassword) = remember{ loginViewModel.password }
Box( Box(
Modifier Modifier
@ -68,15 +76,15 @@ fun LoginScreen(
AllInTextField( AllInTextField(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
placeholder = stringResource(id = R.string.username), placeholder = stringResource(id = R.string.username),
value = "", value = username,
onValueChange = { }, onValueChange = setUsername,
bringIntoViewRequester = bringIntoViewRequester bringIntoViewRequester = bringIntoViewRequester
) )
AllInPasswordField( AllInPasswordField(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
placeholder = stringResource(id = R.string.password), placeholder = stringResource(id = R.string.password),
value = "", value = password,
onValueChange = { }, onValueChange = setPassword,
bringIntoViewRequester = bringIntoViewRequester bringIntoViewRequester = bringIntoViewRequester
) )
} }
@ -135,4 +143,10 @@ fun LoginScreen(
AnimatedVisibility(visible = loading) { AnimatedVisibility(visible = loading) {
AllInLoading() AllInLoading()
} }
AllInAlertDialog(
enabled = hasLoginError,
title = stringResource(id = R.string.Login_Error_Title),
text = stringResource(id = R.string.Login_Error_Content),
onDismiss = { hasLoginError = false }
)
} }

@ -4,6 +4,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import fr.iut.alldev.allin.data.repository.UserRepository
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
@ -11,18 +12,30 @@ import javax.inject.Inject
@HiltViewModel @HiltViewModel
class LoginViewModel @Inject constructor( class LoginViewModel @Inject constructor(
private val userRepository: UserRepository
) : ViewModel() { ) : ViewModel() {
var loading = mutableStateOf(false) var loading = mutableStateOf(false)
var hasError = mutableStateOf(false)
val username = mutableStateOf("")
val password = mutableStateOf("")
fun onLogin( fun onLogin(
navigateToDashboard: ()->Unit navigateToDashboard: ()->Unit
){ ){
viewModelScope.launch { viewModelScope.launch {
loading.value = true loading.value = true
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
Thread.sleep(3000) try{
userRepository.login(username.value, password.value)
} catch (e: retrofit2.HttpException){
hasError.value = true
}
}
if(!hasError.value){
navigateToDashboard()
} }
navigateToDashboard()
loading.value = false loading.value = false
} }
} }

@ -1,5 +1,6 @@
package fr.iut.alldev.allin.ui.register package fr.iut.alldev.allin.ui.register
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.* import androidx.compose.foundation.*
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.relocation.BringIntoViewRequester import androidx.compose.foundation.relocation.BringIntoViewRequester
@ -19,6 +20,7 @@ import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import fr.iut.alldev.allin.R import fr.iut.alldev.allin.R
import fr.iut.alldev.allin.ui.core.AllInGradientButton import fr.iut.alldev.allin.ui.core.AllInGradientButton
import fr.iut.alldev.allin.ui.core.AllInLoading
import fr.iut.alldev.allin.ui.core.AllInPasswordField import fr.iut.alldev.allin.ui.core.AllInPasswordField
import fr.iut.alldev.allin.ui.core.AllInTextField import fr.iut.alldev.allin.ui.core.AllInTextField
import fr.iut.alldev.allin.ui.theme.AllInTheme import fr.iut.alldev.allin.ui.theme.AllInTheme
@ -30,6 +32,8 @@ fun RegisterScreen(
navigateToLogin: () -> Unit, navigateToLogin: () -> Unit,
registerViewModel: RegisterViewModel = hiltViewModel(), registerViewModel: RegisterViewModel = hiltViewModel(),
) { ) {
val loading by remember{ registerViewModel.loading }
val (username, setUsername) = remember{ registerViewModel.username } val (username, setUsername) = remember{ registerViewModel.username }
val (email, setEmail) = remember{ registerViewModel.email } val (email, setEmail) = remember{ registerViewModel.email }
val (password, setPassword) = remember{ registerViewModel.password } val (password, setPassword) = remember{ registerViewModel.password }
@ -118,7 +122,9 @@ fun RegisterScreen(
) { ) {
AllInGradientButton( AllInGradientButton(
text = stringResource(id = R.string.Register), text = stringResource(id = R.string.Register),
onClick = navigateToDashboard onClick = {
registerViewModel.onRegister(navigateToDashboard)
}
) )
Spacer(modifier = Modifier.height(30.dp)) Spacer(modifier = Modifier.height(30.dp))
Row( Row(
@ -145,4 +151,7 @@ fun RegisterScreen(
} }
} }
} }
AnimatedVisibility(visible = loading) {
AllInLoading()
}
} }

@ -2,8 +2,12 @@ package fr.iut.alldev.allin.ui.register
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import fr.iut.alldev.allin.data.repository.UserRepository import fr.iut.alldev.allin.data.repository.UserRepository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
@HiltViewModel @HiltViewModel
@ -11,8 +15,28 @@ class RegisterViewModel @Inject constructor(
val userRepository: UserRepository val userRepository: UserRepository
) : ViewModel() { ) : ViewModel() {
var loading = mutableStateOf(false)
val username = mutableStateOf("") val username = mutableStateOf("")
val email = mutableStateOf("") val email = mutableStateOf("")
val password = mutableStateOf("") val password = mutableStateOf("")
val passwordValidation = mutableStateOf("") val passwordValidation = mutableStateOf("")
fun onRegister(
navigateToDashboard: ()->Unit
){
viewModelScope.launch {
loading.value = true
withContext(Dispatchers.IO) {
userRepository.register(
username.value,
email.value,
password.value
)
}
navigateToDashboard()
loading.value = false
}
}
} }

@ -11,6 +11,7 @@
<string name="Register">S\'inscrire</string> <string name="Register">S\'inscrire</string>
<string name="Validate">Valider</string> <string name="Validate">Valider</string>
<string name="Cancel">Annuler</string> <string name="Cancel">Annuler</string>
<string name="Ok">OK</string>
<!--Drawer--> <!--Drawer-->
<string name="bets">Bets</string> <string name="bets">Bets</string>
@ -36,6 +37,8 @@
<!--Login Page--> <!--Login Page-->
<string name="Login_title">Te revoilà !</string> <string name="Login_title">Te revoilà !</string>
<string name="Login_subtitle">Bon retour parmis nous tu nous as manqué !</string> <string name="Login_subtitle">Bon retour parmis nous tu nous as manqué !</string>
<string name="Login_Error_Title">Erreur de connexion</string>
<string name="Login_Error_Content">La connexion a échoué\nVeuillez réessayer.</string>
<!--Bet Creation Page--> <!--Bet Creation Page-->
<string name="Theme_tooltip">Le sujet du bet.</string> <string name="Theme_tooltip">Le sujet du bet.</string>
<string name="Phrase_tooltip">Généralement la question à laquelle les participants devront répondre.</string> <string name="Phrase_tooltip">Généralement la question à laquelle les participants devront répondre.</string>

@ -14,6 +14,7 @@
<string name="Register">Register</string> <string name="Register">Register</string>
<string name="Validate">Validate</string> <string name="Validate">Validate</string>
<string name="Cancel">Cancel</string> <string name="Cancel">Cancel</string>
<string name="Ok">OK</string>
<!--Drawer--> <!--Drawer-->
<string name="bets">Bets</string> <string name="bets">Bets</string>
@ -40,6 +41,8 @@
<!--Login Page--> <!--Login Page-->
<string name="Login_title">Welcome back !</string> <string name="Login_title">Welcome back !</string>
<string name="Login_subtitle">We missed you.</string> <string name="Login_subtitle">We missed you.</string>
<string name="Login_Error_Title">Connection error</string>
<string name="Login_Error_Content">Failed to login\nPlease try again.</string>
<!--Bet Creation Page--> <!--Bet Creation Page-->
<string name="Question">Question</string> <string name="Question">Question</string>
<string name="Answer">Answer</string> <string name="Answer">Answer</string>

@ -4,11 +4,13 @@ buildscript {
accompanist_version = '0.25.1' accompanist_version = '0.25.1'
hilt_version = "2.45" hilt_version = "2.45"
} }
}// Top-level build file where you can add configuration options common to all sub-projects/modules. }// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins { plugins {
id 'com.android.application' version '7.4.2' apply false id 'com.android.application' version '7.4.2' apply false
id 'com.android.library' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false
id 'org.jetbrains.kotlin.android' version '1.7.0' apply false id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
id("com.google.dagger.hilt.android") version "$hilt_version" apply false id 'com.google.dagger.hilt.android' version "$hilt_version" apply false
id 'org.jetbrains.kotlin.plugin.serialization' version '1.7.0' apply false
}
}

@ -2,9 +2,21 @@ plugins {
id 'com.android.library' id 'com.android.library'
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
id "kotlin-kapt" id "kotlin-kapt"
id "kotlinx-serialization"
} }
def keystorePropertiesFile = rootProject.file("app/keys/keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android { android {
signingConfigs {
release {
storeFile file(keystoreProperties['store'])
storePassword keystoreProperties['password']
keyPassword keystoreProperties['password']
}
}
namespace 'fr.iut.alldev.allin.data' namespace 'fr.iut.alldev.allin.data'
compileSdk 34 compileSdk 34
@ -18,8 +30,15 @@ android {
buildTypes { buildTypes {
release { release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
}
debug {
minifyEnabled false minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.debug
} }
} }
compileOptions { compileOptions {
@ -43,4 +62,11 @@ dependencies {
//Hilt //Hilt
implementation "com.google.dagger:hilt-android:$hilt_version" implementation "com.google.dagger:hilt-android:$hilt_version"
kapt "com.google.dagger:hilt-android-compiler:$hilt_version" kapt "com.google.dagger:hilt-android-compiler:$hilt_version"
// Retrofit
api "com.squareup.retrofit2:retrofit:2.9.0"
implementation "com.squareup.okhttp3:okhttp:4.11.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.11.0"
api "org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1"
implementation "com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0"
} }

@ -0,0 +1,9 @@
package fr.iut.alldev.allin.data.di
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module(includes = [DebugNetworkModule::class])
@InstallIn(SingletonComponent::class)
object DebugModule

@ -0,0 +1,25 @@
package fr.iut.alldev.allin.data.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object DebugNetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient =
OkHttpClient.Builder()
.addInterceptor(
HttpLoggingInterceptor().apply {
level = HttpLoggingInterceptor.Level.BODY
}
)
.build()
}

@ -0,0 +1,19 @@
package fr.iut.alldev.allin.data.api
import fr.iut.alldev.allin.data.api.model.CheckUser
import fr.iut.alldev.allin.data.api.model.ResponseUser
import retrofit2.http.Body
import retrofit2.http.POST
interface AllInApi {
@POST("users/login")
suspend fun login(
@Body body: CheckUser
): ResponseUser
@POST("users/register")
suspend fun register(
@Body body: ResponseUser
): ResponseUser
}

@ -0,0 +1,20 @@
package fr.iut.alldev.allin.data.api.model
import androidx.annotation.Keep
import kotlinx.serialization.Serializable
@Keep
@Serializable
data class ResponseUser(
val username: String,
val email: String,
val password: String,
var nbCoins: Int,
)
@Keep
@Serializable
data class CheckUser(
val username: String,
val password: String,
)

@ -0,0 +1,23 @@
package fr.iut.alldev.allin.data.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import fr.iut.alldev.allin.data.api.AllInApi
import fr.iut.alldev.allin.data.di.NetworkModule.createRetrofit
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
class ApiModule {
@Provides
@Singleton
fun provideAllInApi(@AllInUrl url: HttpUrl, okHttpClient: OkHttpClient): AllInApi {
val retrofit = createRetrofit(url = url, okHttpClient = okHttpClient)
return retrofit.create(AllInApi::class.java)
}
}

@ -0,0 +1,41 @@
package fr.iut.alldev.allin.data.di
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.serialization.json.Json
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import javax.inject.Qualifier
internal val json by lazy {
Json {
ignoreUnknownKeys = true
encodeDefaults = false
}
}
@Qualifier
@Retention(AnnotationRetention.BINARY)
annotation class AllInUrl
@Module
@InstallIn(SingletonComponent::class)
internal object NetworkModule {
@AllInUrl
@Provides
fun provideUrl(): HttpUrl = "https://codefirst.iut.uca.fr/containers/AllDev-api/".toHttpUrl()
fun createRetrofit(url: HttpUrl, okHttpClient: OkHttpClient): Retrofit =
Retrofit.Builder()
.client(okHttpClient)
.addConverterFactory(json.asConverterFactory("application/json".toMediaType()))
.baseUrl(url)
.build()
}

@ -1,4 +1,13 @@
package fr.iut.alldev.allin.data.repository package fr.iut.alldev.allin.data.repository
abstract class UserRepository { abstract class UserRepository {
abstract suspend fun login(
username: String,
password: String
)
abstract suspend fun register(
username: String,
email: String,
password: String
)
} }

@ -1,10 +1,32 @@
package fr.iut.alldev.allin.data.repository.impl package fr.iut.alldev.allin.data.repository.impl
import fr.iut.alldev.allin.data.api.AllInApi
import fr.iut.alldev.allin.data.api.model.CheckUser
import fr.iut.alldev.allin.data.api.model.ResponseUser
import fr.iut.alldev.allin.data.repository.UserRepository import fr.iut.alldev.allin.data.repository.UserRepository
import javax.inject.Inject import javax.inject.Inject
class UserRepositoryImpl @Inject constructor( class UserRepositoryImpl @Inject constructor(
private val api: AllInApi,
) : UserRepository() { ) : UserRepository() {
override suspend fun login(username: String, password: String) {
api.login(
CheckUser(
username = username,
password = password
)
)
}
override suspend fun register(username: String, email: String, password: String) {
api.register(
ResponseUser(
username = username,
email = email,
password = password,
nbCoins = 0
)
)
}
} }

@ -0,0 +1,13 @@
package fr.iut.alldev.allin.data.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Singleton
@Module(includes = [ReleaseNetworkModule::class])
@InstallIn(SingletonComponent::class)
object ReleaseModule

@ -0,0 +1,20 @@
package fr.iut.alldev.allin.data.di
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal object ReleaseNetworkModule {
@Provides
@Singleton
fun provideOkHttpClient(): OkHttpClient =
OkHttpClient.Builder()
.build()
}
Loading…
Cancel
Save