From f9b3e35939d6221fb2c1fab0971a422128bdb393 Mon Sep 17 00:00:00 2001 From: "Z. Charles Dziura" Date: Sat, 26 Oct 2024 22:32:08 -0400 Subject: [PATCH] Finally set up proper dependency injection --- app/app/build.gradle.kts | 9 +++++ app/app/src/main/AndroidManifest.xml | 4 +- .../ing/bikeshedengineer/debtpirate/Store.kt | 30 -------------- .../app/android/DebtPirateApplication.kt | 8 ++++ .../debtpirate/{ => app/host}/MainActivity.kt | 16 ++++---- .../data/pref/PreferencesDataStore.kt | 31 ++++++++++++++ .../data/remote/client/AuthEndpointClient.kt | 4 ++ .../data/remote/endpoint/AuthEndpoint.kt | 13 ++++++ .../data/remote/model/ApiResponse.kt | 3 ++ .../remote/model/auth}/AuthLoginRequest.kt | 2 +- .../remote/model/auth/AuthLoginResponse.kt | 5 +++ .../data/remote/repository/AuthRepository.kt | 9 +++++ .../di/modules/AuthRepositoryModule.kt | 40 +++++++++++++++++++ .../debtpirate/domain/model/Token.kt | 8 ++++ .../domain/repository/AuthRepositoryImpl.kt | 29 ++++++++++++++ .../debtpirate/http/ApiResponse.kt | 3 -- .../debtpirate/http/HttpClientService.kt | 19 --------- .../{ui => presentation}/theme/Color.kt | 2 +- .../{ui => presentation}/theme/Theme.kt | 2 +- .../{ui => presentation}/theme/Type.kt | 2 +- .../ui}/auth/AuthScreen.kt | 6 +-- .../ui}/auth/AuthScreenViewModel.kt | 29 +++++++------- .../repositories/auth/AuthRemoteDataSource.kt | 21 ---------- .../repositories/auth/AuthRepository.kt | 14 ------- .../auth/models/AuthLoginResponse.kt | 13 ------ .../users/UsersRemoteDataSource.kt | 3 -- .../repositories/users/UsersRepository.kt | 10 ----- .../screens/auth/usecases/LoginUsecase.kt | 20 ---------- .../usecases/RegisterNewAccountUseCase.kt | 3 -- .../{store.proto => prefs_data_store.proto} | 2 +- app/build.gradle.kts | 1 + app/gradle/libs.versions.toml | 16 +++++--- 32 files changed, 203 insertions(+), 174 deletions(-) delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/Store.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/android/DebtPirateApplication.kt rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{ => app/host}/MainActivity.kt (66%) create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/pref/PreferencesDataStore.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/client/AuthEndpointClient.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/endpoint/AuthEndpoint.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/ApiResponse.kt rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{repositories/auth/models => data/remote/model/auth}/AuthLoginRequest.kt (52%) create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginResponse.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/repository/AuthRepository.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/di/modules/AuthRepositoryModule.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/model/Token.kt create mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/repository/AuthRepositoryImpl.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/ApiResponse.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/HttpClientService.kt rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{ui => presentation}/theme/Color.kt (70%) rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{ui => presentation}/theme/Theme.kt (96%) rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{ui => presentation}/theme/Type.kt (94%) rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{screens => presentation/ui}/auth/AuthScreen.kt (97%) rename app/app/src/main/java/ing/bikeshedengineer/debtpirate/{screens => presentation/ui}/auth/AuthScreenViewModel.kt (53%) delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRemoteDataSource.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRepository.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginResponse.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRemoteDataSource.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRepository.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/LoginUsecase.kt delete mode 100644 app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/RegisterNewAccountUseCase.kt rename app/app/src/main/proto/{store.proto => prefs_data_store.proto} (90%) diff --git a/app/app/build.gradle.kts b/app/app/build.gradle.kts index 66015a4..da9ea33 100644 --- a/app/app/build.gradle.kts +++ b/app/app/build.gradle.kts @@ -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) diff --git a/app/app/src/main/AndroidManifest.xml b/app/app/src/main/AndroidManifest.xml index 8786aa9..fa37ffe 100644 --- a/app/app/src/main/AndroidManifest.xml +++ b/app/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/Store.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/Store.kt deleted file mode 100644 index a0157e5..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/Store.kt +++ /dev/null @@ -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 { - 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 by dataStore( - fileName = "store.proto", - serializer = StoreSerializer -) \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/android/DebtPirateApplication.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/android/DebtPirateApplication.kt new file mode 100644 index 0000000..a1535c3 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/android/DebtPirateApplication.kt @@ -0,0 +1,8 @@ +package ing.bikeshedengineer.debtpirate.app.android + +import android.app.Application +import dagger.hilt.android.HiltAndroidApp + +@HiltAndroidApp +class DebtPirateApplication : Application() { +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/MainActivity.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/host/MainActivity.kt similarity index 66% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/MainActivity.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/host/MainActivity.kt index b954337..2b20eff 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/MainActivity.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/app/host/MainActivity.kt @@ -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 { - AuthScreen( - viewModel = viewModel() - ) + AuthScreen( ) } } } diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/pref/PreferencesDataStore.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/pref/PreferencesDataStore.kt new file mode 100644 index 0000000..a065276 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/pref/PreferencesDataStore.kt @@ -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 { + 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 by dataStore( + fileName = "prefs_data_store.proto", + serializer = PrefsDataStoreSerializer +) \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/client/AuthEndpointClient.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/client/AuthEndpointClient.kt new file mode 100644 index 0000000..dd34572 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/client/AuthEndpointClient.kt @@ -0,0 +1,4 @@ +package ing.bikeshedengineer.debtpirate.data.remote.client + +class AuthEndpointClient { +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/endpoint/AuthEndpoint.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/endpoint/AuthEndpoint.kt new file mode 100644 index 0000000..34d4fc4 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/endpoint/AuthEndpoint.kt @@ -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> +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/ApiResponse.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/ApiResponse.kt new file mode 100644 index 0000000..3d144b2 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/ApiResponse.kt @@ -0,0 +1,3 @@ +package ing.bikeshedengineer.debtpirate.data.remote.model + +data class ApiResponse(val data: T?, val err: Any?) diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginRequest.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginRequest.kt similarity index 52% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginRequest.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginRequest.kt index 77e75d8..d5819c8 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginRequest.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginRequest.kt @@ -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) diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginResponse.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginResponse.kt new file mode 100644 index 0000000..d4ac892 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/model/auth/AuthLoginResponse.kt @@ -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) diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/repository/AuthRepository.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/repository/AuthRepository.kt new file mode 100644 index 0000000..29d7202 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/data/remote/repository/AuthRepository.kt @@ -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 +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/di/modules/AuthRepositoryModule.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/di/modules/AuthRepositoryModule.kt new file mode 100644 index 0000000..bcf0a99 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/di/modules/AuthRepositoryModule.kt @@ -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) + } +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/model/Token.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/model/Token.kt new file mode 100644 index 0000000..e585916 --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/model/Token.kt @@ -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)) +} diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/repository/AuthRepositoryImpl.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/repository/AuthRepositoryImpl.kt new file mode 100644 index 0000000..4c1ed7a --- /dev/null +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/domain/repository/AuthRepositoryImpl.kt @@ -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 { + 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())) + } + } + } +} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/ApiResponse.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/ApiResponse.kt deleted file mode 100644 index 3657da6..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/ApiResponse.kt +++ /dev/null @@ -1,3 +0,0 @@ -package ing.bikeshedengineer.debtpirate.http - -data class ApiResponse(val data: T, val err: Any) diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/HttpClientService.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/HttpClientService.kt deleted file mode 100644 index 866df19..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/http/HttpClientService.kt +++ /dev/null @@ -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() diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Color.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Color.kt similarity index 70% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Color.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Color.kt index a27d65d..cf357a0 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Color.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Color.kt @@ -1,4 +1,4 @@ -package ing.bikeshedengineer.debtpirate.ui.theme +package ing.bikeshedengineer.debtpirate.presentation.theme import androidx.compose.ui.graphics.Color diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Theme.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Theme.kt similarity index 96% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Theme.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Theme.kt index 89872f5..773a663 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Theme.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Theme.kt @@ -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 diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Type.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Type.kt similarity index 94% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Type.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Type.kt index 9dfaba3..230a080 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/ui/theme/Type.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/theme/Type.kt @@ -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 diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreen.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreen.kt similarity index 97% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreen.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreen.kt index ccfac92..c58dda1 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreen.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreen.kt @@ -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() ) { Scaffold( modifier = Modifier.fillMaxSize() diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreenViewModel.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreenViewModel.kt similarity index 53% rename from app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreenViewModel.kt rename to app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreenViewModel.kt index 03296ce..86376e1 100644 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/AuthScreenViewModel.kt +++ b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/presentation/ui/auth/AuthScreenViewModel.kt @@ -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!!) } } } diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRemoteDataSource.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRemoteDataSource.kt deleted file mode 100644 index b38c88f..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRemoteDataSource.kt +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRepository.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRepository.kt deleted file mode 100644 index d79d1aa..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/AuthRepository.kt +++ /dev/null @@ -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 { - return remoteDataSource.submitLoginRequest(credentials) - } -} diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginResponse.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginResponse.kt deleted file mode 100644 index 1386d00..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/auth/models/AuthLoginResponse.kt +++ /dev/null @@ -1,13 +0,0 @@ -package ing.bikeshedengineer.debtpirate.repositories.auth.models - -import ing.bikeshedengineer.debtpirate.http.ApiResponse - -typealias AuthLoginResponse = ApiResponse - -data class AuthLoginResponseData( - val userId: Number, - val session: AuthLoginResponseTokenData, - val auth: AuthLoginResponseTokenData -) - -data class AuthLoginResponseTokenData(val token: String, val expiresAt: String) \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRemoteDataSource.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRemoteDataSource.kt deleted file mode 100644 index 3412fe9..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRemoteDataSource.kt +++ /dev/null @@ -1,3 +0,0 @@ -package ing.bikeshedengineer.debtpirate.repositories.users - -class UsersRemoteDataSource \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRepository.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRepository.kt deleted file mode 100644 index 1ee7a82..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/repositories/users/UsersRepository.kt +++ /dev/null @@ -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) \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/LoginUsecase.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/LoginUsecase.kt deleted file mode 100644 index 0bbdbae..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/LoginUsecase.kt +++ /dev/null @@ -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 = - withContext(defaultDispatcher) { - val response = authRepository.submitLoginRequest(credentials) - response - } -} \ No newline at end of file diff --git a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/RegisterNewAccountUseCase.kt b/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/RegisterNewAccountUseCase.kt deleted file mode 100644 index fe7b120..0000000 --- a/app/app/src/main/java/ing/bikeshedengineer/debtpirate/screens/auth/usecases/RegisterNewAccountUseCase.kt +++ /dev/null @@ -1,3 +0,0 @@ -package ing.bikeshedengineer.debtpirate.screens.auth.usecases - -class RegisterNewAccountUseCase \ No newline at end of file diff --git a/app/app/src/main/proto/store.proto b/app/app/src/main/proto/prefs_data_store.proto similarity index 90% rename from app/app/src/main/proto/store.proto rename to app/app/src/main/proto/prefs_data_store.proto index 7a4eafb..43bbd9f 100644 --- a/app/app/src/main/proto/store.proto +++ b/app/app/src/main/proto/prefs_data_store.proto @@ -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; diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a5cb1bf..b487718 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -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 } diff --git a/app/gradle/libs.versions.toml b/app/gradle/libs.versions.toml index 47832a0..60d13be 100644 --- a/app/gradle/libs.versions.toml +++ b/app/gradle/libs.versions.toml @@ -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" } \ No newline at end of file +protobuf = { id = "com.google.protobuf", version.ref = "protobuf" } +hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } \ No newline at end of file