Finally set up proper dependency injection
This commit is contained in:
parent
5b8179ade1
commit
f9b3e35939
32 changed files with 203 additions and 174 deletions
|
@ -6,6 +6,8 @@ plugins {
|
|||
alias(libs.plugins.compose.compiler)
|
||||
alias(libs.plugins.serialization)
|
||||
alias(libs.plugins.protobuf)
|
||||
id("kotlin-kapt")
|
||||
alias(libs.plugins.hilt)
|
||||
}
|
||||
|
||||
protobuf {
|
||||
|
@ -76,6 +78,10 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
kapt {
|
||||
correctErrorTypes = true
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.appcompat)
|
||||
|
@ -100,6 +106,9 @@ dependencies {
|
|||
implementation(libs.okhttp.logging.interceptor)
|
||||
implementation(libs.protobuf.javalite)
|
||||
implementation(libs.protobuf.kotlinlite)
|
||||
implementation(libs.hilt)
|
||||
kapt(libs.hilt.kapt)
|
||||
implementation(libs.hilt.compose)
|
||||
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name=".app.android.DebtPirateApplication"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
|
@ -15,9 +16,8 @@
|
|||
android:theme="@style/Theme.DebtPirate"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name=".app.host.MainActivity"
|
||||
android:exported="true"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/Theme.DebtPirate">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.CorruptionException
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.core.Serializer
|
||||
import androidx.datastore.dataStore
|
||||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
object StoreSerializer : Serializer<Store> {
|
||||
override val defaultValue: Store
|
||||
get() = Store.getDefaultInstance()
|
||||
|
||||
override suspend fun readFrom(input: InputStream): Store {
|
||||
try {
|
||||
return Store.parseFrom(input)
|
||||
} catch (exception: InvalidProtocolBufferException) {
|
||||
throw CorruptionException("Cannot read proto file.", exception)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun writeTo(t: Store, output: OutputStream) = t.writeTo(output)
|
||||
}
|
||||
|
||||
val Context.dataStore: DataStore<Store> by dataStore(
|
||||
fileName = "store.proto",
|
||||
serializer = StoreSerializer
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
package ing.bikeshedengineer.debtpirate.app.android
|
||||
|
||||
import android.app.Application
|
||||
import dagger.hilt.android.HiltAndroidApp
|
||||
|
||||
@HiltAndroidApp
|
||||
class DebtPirateApplication : Application() {
|
||||
}
|
|
@ -1,35 +1,33 @@
|
|||
package ing.bikeshedengineer.debtpirate
|
||||
package ing.bikeshedengineer.debtpirate.app.host
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import ing.bikeshedengineer.debtpirate.screens.auth.AuthScreen
|
||||
import ing.bikeshedengineer.debtpirate.screens.auth.AuthScreenViewModel
|
||||
import ing.bikeshedengineer.debtpirate.ui.theme.DebtPirateTheme
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import ing.bikeshedengineer.debtpirate.presentation.ui.auth.AuthScreen
|
||||
import ing.bikeshedengineer.debtpirate.presentation.theme.DebtPirateTheme
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
object AuthRoute
|
||||
|
||||
|
||||
@AndroidEntryPoint
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
enableEdgeToEdge()
|
||||
|
||||
setContent {
|
||||
val navController = rememberNavController()
|
||||
|
||||
DebtPirateTheme {
|
||||
NavHost(navController = navController, startDestination = AuthRoute) {
|
||||
composable<AuthRoute> {
|
||||
AuthScreen(
|
||||
viewModel = viewModel<AuthScreenViewModel>()
|
||||
)
|
||||
AuthScreen( )
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.pref
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.CorruptionException
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.core.Serializer
|
||||
import androidx.datastore.dataStore
|
||||
import com.google.protobuf.InvalidProtocolBufferException
|
||||
import ing.bikeshedengineer.debtpirate.PrefsDataStore
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
|
||||
object PrefsDataStoreSerializer : Serializer<PrefsDataStore> {
|
||||
override val defaultValue: PrefsDataStore
|
||||
get() = PrefsDataStore.getDefaultInstance()
|
||||
|
||||
override suspend fun readFrom(input: InputStream): PrefsDataStore {
|
||||
try {
|
||||
return PrefsDataStore.parseFrom(input)
|
||||
} catch (exception: InvalidProtocolBufferException) {
|
||||
throw CorruptionException("Cannot read proto file.", exception)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun writeTo(t: PrefsDataStore, output: OutputStream) = t.writeTo(output)
|
||||
}
|
||||
|
||||
val Context.dataStore: DataStore<PrefsDataStore> by dataStore(
|
||||
fileName = "prefs_data_store.proto",
|
||||
serializer = PrefsDataStoreSerializer
|
||||
)
|
|
@ -0,0 +1,4 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.remote.client
|
||||
|
||||
class AuthEndpointClient {
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.remote.endpoint
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.ApiResponse
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginResponse
|
||||
import retrofit2.http.POST
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
|
||||
interface AuthEndpoint {
|
||||
@POST("auth/login")
|
||||
suspend fun submitLoginRequest(@Body credentials: AuthLoginRequest): Response<ApiResponse<AuthLoginResponse>>
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.remote.model
|
||||
|
||||
data class ApiResponse<T>(val data: T?, val err: Any?)
|
|
@ -1,3 +1,3 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.auth.models
|
||||
package ing.bikeshedengineer.debtpirate.data.remote.model.auth
|
||||
|
||||
data class AuthLoginRequest(val username: String, val password: String)
|
|
@ -0,0 +1,5 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.remote.model.auth
|
||||
|
||||
data class AuthLoginResponse(val userId: Int, val session: AuthLoginTokenData, val auth: AuthLoginTokenData)
|
||||
|
||||
data class AuthLoginTokenData(val token: String, val expiresAt: String)
|
|
@ -0,0 +1,9 @@
|
|||
package ing.bikeshedengineer.debtpirate.data.remote.repository
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.ApiResponse
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginResponse
|
||||
|
||||
interface AuthRepository {
|
||||
suspend fun submitLoginRequest(credentials: AuthLoginRequest): Result<AuthLoginResponse>
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package ing.bikeshedengineer.debtpirate.di.modules
|
||||
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import ing.bikeshedengineer.debtpirate.BuildConfig
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.repository.AuthRepository
|
||||
import ing.bikeshedengineer.debtpirate.domain.repository.AuthRepositoryImpl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
import javax.inject.Singleton
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
object AuthRepositoryModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideHttpClient(): Retrofit {
|
||||
return Retrofit.Builder()
|
||||
.baseUrl(BuildConfig.API_BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(OkHttpClient.Builder()
|
||||
.addInterceptor(HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
})
|
||||
.build()
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideAuthRepository(httpClient: Retrofit): AuthRepository {
|
||||
return AuthRepositoryImpl(httpClient)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package ing.bikeshedengineer.debtpirate.domain.model
|
||||
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter.ISO_INSTANT
|
||||
|
||||
data class Token(val token: String, val expiresAt: ZonedDateTime) {
|
||||
constructor(token: String, expiresAtStr: String): this(token, ZonedDateTime.parse(expiresAtStr, ISO_INSTANT))
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package ing.bikeshedengineer.debtpirate.domain.repository
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.endpoint.AuthEndpoint
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.ApiResponse
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginResponse
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.repository.AuthRepository
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.Retrofit
|
||||
import kotlin.Result
|
||||
|
||||
class AuthRepositoryImpl constructor(private val httpClient: Retrofit): AuthRepository {
|
||||
private val authEndpoint: AuthEndpoint = this.httpClient.create(AuthEndpoint::class.java)
|
||||
|
||||
override suspend fun submitLoginRequest(credentials: AuthLoginRequest): Result<AuthLoginResponse> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
val response = authEndpoint.submitLoginRequest(credentials)
|
||||
|
||||
if (response.isSuccessful) {
|
||||
val body = response.body()
|
||||
return@withContext Result.success(body?.data!!)
|
||||
} else {
|
||||
val error = response.errorBody()
|
||||
return@withContext Result.failure(Throwable(error.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.http
|
||||
|
||||
data class ApiResponse<T>(val data: T, val err: Any)
|
|
@ -1,19 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.http
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.BuildConfig
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
private val okHttpClient = OkHttpClient.Builder()
|
||||
.addInterceptor(HttpLoggingInterceptor().apply {
|
||||
level = HttpLoggingInterceptor.Level.BODY
|
||||
})
|
||||
.build()
|
||||
|
||||
val httpClientService = Retrofit.Builder()
|
||||
.baseUrl(BuildConfig.API_BASE_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(okHttpClient)
|
||||
.build()
|
|
@ -1,4 +1,4 @@
|
|||
package ing.bikeshedengineer.debtpirate.ui.theme
|
||||
package ing.bikeshedengineer.debtpirate.presentation.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package ing.bikeshedengineer.debtpirate.ui.theme
|
||||
package ing.bikeshedengineer.debtpirate.presentation.theme
|
||||
|
||||
import android.os.Build
|
||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
@ -1,4 +1,4 @@
|
|||
package ing.bikeshedengineer.debtpirate.ui.theme
|
||||
package ing.bikeshedengineer.debtpirate.presentation.theme
|
||||
|
||||
import androidx.compose.material3.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
|
@ -1,4 +1,4 @@
|
|||
package ing.bikeshedengineer.debtpirate.screens.auth
|
||||
package ing.bikeshedengineer.debtpirate.presentation.ui.auth
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.foundation.background
|
||||
|
@ -35,14 +35,14 @@ import androidx.compose.ui.text.input.ImeAction
|
|||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
|
||||
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
|
||||
@Composable
|
||||
fun AuthScreen(
|
||||
viewModel: AuthScreenViewModel
|
||||
viewModel: AuthScreenViewModel = hiltViewModel<AuthScreenViewModel>()
|
||||
) {
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize()
|
|
@ -1,21 +1,25 @@
|
|||
package ing.bikeshedengineer.debtpirate.screens.auth
|
||||
package ing.bikeshedengineer.debtpirate.presentation.ui.auth
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.screens.auth.usecases.LoginUsecase
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.data.remote.repository.AuthRepository
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
class AuthScreenViewModel(private val loginRequest: LoginUsecase = LoginUsecase()) :
|
||||
ViewModel() {
|
||||
@HiltViewModel
|
||||
class AuthScreenViewModel @Inject constructor(private val authRepository: AuthRepository) : ViewModel() {
|
||||
private val tag: String
|
||||
get() {
|
||||
return javaClass.simpleName
|
||||
}
|
||||
|
||||
// private val storeLoginData = StoreLoginDataUseCase(dataStore)
|
||||
|
||||
private val _username = MutableStateFlow("")
|
||||
val username = _username.asStateFlow()
|
||||
|
||||
|
@ -33,15 +37,12 @@ class AuthScreenViewModel(private val loginRequest: LoginUsecase = LoginUsecase(
|
|||
fun submitLoginRequest() {
|
||||
val credentials = AuthLoginRequest(this._username.value, this._password.value)
|
||||
viewModelScope.launch {
|
||||
val response = loginRequest(credentials)
|
||||
when (response.isSuccessful) {
|
||||
true -> {
|
||||
Log.i(tag, "Login successful! ${response.body()}")
|
||||
}
|
||||
|
||||
false -> {
|
||||
Log.e(tag, "Login unsuccessful! ${response.body()}")
|
||||
}
|
||||
try {
|
||||
val response = authRepository.submitLoginRequest(credentials)
|
||||
Log.i(tag, "Login successful! $response")
|
||||
} catch (err: Throwable) {
|
||||
// TODO...
|
||||
Log.e(tag, err.message!!)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.auth
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.http.httpClientService
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginResponse
|
||||
import retrofit2.Response
|
||||
import retrofit2.http.Body
|
||||
import retrofit2.http.POST
|
||||
|
||||
class AuthRemoteDataSource(
|
||||
private val authApi: AuthApi = httpClientService.create(AuthApi::class.java)
|
||||
) {
|
||||
suspend fun submitLoginRequest(credentials: AuthLoginRequest) =
|
||||
authApi.submitLoginRequest(credentials)
|
||||
}
|
||||
|
||||
|
||||
interface AuthApi {
|
||||
@POST("auth/login")
|
||||
suspend fun submitLoginRequest(@Body credentials: AuthLoginRequest): Response<AuthLoginResponse>
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.auth
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginResponse
|
||||
import retrofit2.Response
|
||||
|
||||
class AuthRepository(
|
||||
private val remoteDataSource: AuthRemoteDataSource = AuthRemoteDataSource()
|
||||
) {
|
||||
|
||||
suspend fun submitLoginRequest(credentials: AuthLoginRequest): Response<AuthLoginResponse> {
|
||||
return remoteDataSource.submitLoginRequest(credentials)
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.auth.models
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.http.ApiResponse
|
||||
|
||||
typealias AuthLoginResponse = ApiResponse<AuthLoginResponseData>
|
||||
|
||||
data class AuthLoginResponseData(
|
||||
val userId: Number,
|
||||
val session: AuthLoginResponseTokenData,
|
||||
val auth: AuthLoginResponseTokenData
|
||||
)
|
||||
|
||||
data class AuthLoginResponseTokenData(val token: String, val expiresAt: String)
|
|
@ -1,3 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.users
|
||||
|
||||
class UsersRemoteDataSource
|
|
@ -1,10 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.repositories.users
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
class UsersRepository(private val usersRemoteDataSource: UsersRemoteDataSource = UsersRemoteDataSource()) {
|
||||
fun insertUser(newUser: NewUser) {}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class NewUser(val displayName: String, val emailAddress: String)
|
|
@ -1,20 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.screens.auth.usecases
|
||||
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.AuthRepository
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginRequest
|
||||
import ing.bikeshedengineer.debtpirate.repositories.auth.models.AuthLoginResponse
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import retrofit2.Response
|
||||
|
||||
class LoginUsecase(
|
||||
private val authRepository: AuthRepository = AuthRepository(),
|
||||
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||
) {
|
||||
suspend operator fun invoke(credentials: AuthLoginRequest): Response<AuthLoginResponse> =
|
||||
withContext(defaultDispatcher) {
|
||||
val response = authRepository.submitLoginRequest(credentials)
|
||||
response
|
||||
}
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
package ing.bikeshedengineer.debtpirate.screens.auth.usecases
|
||||
|
||||
class RegisterNewAccountUseCase
|
|
@ -8,7 +8,7 @@ message Token {
|
|||
int64 expires_at = 2;
|
||||
}
|
||||
|
||||
message Store {
|
||||
message PrefsDataStore {
|
||||
int32 user_id = 1;
|
||||
Token auth_token = 2;
|
||||
Token session_token = 3;
|
|
@ -5,4 +5,5 @@ plugins {
|
|||
alias(libs.plugins.compose.compiler) apply false
|
||||
alias(libs.plugins.serialization) apply false
|
||||
alias(libs.plugins.protobuf) apply false
|
||||
alias(libs.plugins.hilt) apply false
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
[versions]
|
||||
activityCompose = "1.9.2"
|
||||
agp = "8.7.0"
|
||||
activityCompose = "1.9.3"
|
||||
agp = "8.7.1"
|
||||
appcompat = "1.7.0"
|
||||
composeBom = "2024.09.03"
|
||||
composeBom = "2024.10.00"
|
||||
coreKtx = "1.13.1"
|
||||
datastore = "1.1.1"
|
||||
espressoCore = "3.6.1"
|
||||
hilt = "2.51.1"
|
||||
iconsExtended = "1.7.3"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.2.1"
|
||||
|
@ -17,11 +18,12 @@ lifecycleViewModelKtx = "2.8.6"
|
|||
lifecycleViewmodelCompose = "2.8.6"
|
||||
material = "1.12.0"
|
||||
material3 = "1.3.0"
|
||||
navigation = "2.8.2"
|
||||
navigation = "2.8.3"
|
||||
protobuf = "0.9.4"
|
||||
protoLite = "3.21.11"
|
||||
okhttp = "4.10.0"
|
||||
retrofit = "2.9.0"
|
||||
hiltNavigationCompose = "1.2.0"
|
||||
|
||||
[libraries]
|
||||
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||
|
@ -54,10 +56,14 @@ okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhtt
|
|||
okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
|
||||
protobuf-javalite = { group = "com.google.protobuf", name = "protobuf-javalite", version.ref = "protoLite" }
|
||||
protobuf-kotlinlite = { group = "com.google.protobuf", name = "protobuf-kotlin-lite", version.ref = "protoLite" }
|
||||
hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
|
||||
hilt-kapt = { group = "com.google.dagger", name = "hilt-android-compiler", version.ref = "hilt" }
|
||||
hilt-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationCompose" }
|
||||
|
||||
[plugins]
|
||||
android-application = { id = "com.android.application", version.ref = "agp" }
|
||||
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
|
||||
protobuf = { id = "com.google.protobuf", version.ref = "protobuf" }
|
||||
protobuf = { id = "com.google.protobuf", version.ref = "protobuf" }
|
||||
hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" }
|
Loading…
Add table
Reference in a new issue