Move the credential manager into its own dependency module

This commit is contained in:
Z. Charles Dziura 2025-03-27 10:19:46 -04:00
parent 582e7015a9
commit 99c139d1ac
12 changed files with 71 additions and 40 deletions

View file

@ -32,11 +32,11 @@ import ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login.LoginS
import ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.register.RegistrationScreen
import ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.register.RegistrationScreenViewModel
import ing.bikeshedengineer.debtpirate.app.screen.home.presentation.overview.OverviewScreen
import ing.bikeshedengineer.debtpirate.domain.navigation.Destination
import ing.bikeshedengineer.debtpirate.domain.navigation.NavigationAction
import ing.bikeshedengineer.debtpirate.domain.navigation.Navigator
import ing.bikeshedengineer.debtpirate.domain.usecase.GetStoredTokensUseCase
import ing.bikeshedengineer.debtpirate.domain.usecase.StoreCredentialsUseCase
import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.NavigationAction
import ing.bikeshedengineer.debtpirate.navigation.Navigator
import ing.bikeshedengineer.debtpirate.theme.DebtPirateTheme
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
@ -63,7 +63,7 @@ class MainActivity : ComponentActivity() {
enableEdgeToEdge()
setContent {
val navController = rememberNavController()
ObserveAsEvents(navigator.navigationActions) { action ->
when (action) {

View file

@ -7,7 +7,7 @@ import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import ing.bikeshedengineer.debtpirate.AppDataStore
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitNewUserVerificationRequestUseCase
import ing.bikeshedengineer.debtpirate.navigation.Navigator
import ing.bikeshedengineer.debtpirate.domain.navigation.Navigator
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

View file

@ -12,9 +12,9 @@ import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.LoginCredentialsV
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.UserNotFoundException
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.domain.navigation.Destination
import ing.bikeshedengineer.debtpirate.domain.navigation.Navigator
import ing.bikeshedengineer.debtpirate.domain.usecase.UpdateStoreDataUseCase
import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.Navigator
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChangedBy

View file

@ -7,9 +7,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.NewAccountRegistrationValidationResult
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitAccountRegistrationRequestUseCase
import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateNewAccountRegistrationUseCase
import ing.bikeshedengineer.debtpirate.domain.navigation.Destination
import ing.bikeshedengineer.debtpirate.domain.navigation.Navigator
import ing.bikeshedengineer.debtpirate.domain.usecase.UpdateStoreDataUseCase
import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.Navigator
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow

View file

@ -1,19 +0,0 @@
package ing.bikeshedengineer.debtpirate.di
import android.content.Context
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
import ing.bikeshedengineer.debtpirate.domain.usecase.StoreCredentialsUseCase
@Module
@InstallIn(ActivityComponent::class)
object AppCredentialsModule {
@Provides
@ActivityScoped
fun provideStoreCredentialsUseCase(@ActivityContext context: Context) = StoreCredentialsUseCase(context)
}

View file

@ -4,8 +4,8 @@ import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import ing.bikeshedengineer.debtpirate.navigation.Navigator
import ing.bikeshedengineer.debtpirate.navigation.NavigatorImpl
import ing.bikeshedengineer.debtpirate.domain.navigation.Navigator
import ing.bikeshedengineer.debtpirate.domain.navigation.NavigatorImpl
import javax.inject.Singleton
@Module

View file

@ -0,0 +1,42 @@
package ing.bikeshedengineer.debtpirate.domain.credential
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.receiveAsFlow
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
object CredentialManagerModule {
@Provides
@Singleton
fun provideCredentialManager(): CredentialManager = CredentialManagerImpl()
}
sealed interface CredentialManagerRequest {
data object GetCredentials : CredentialManagerRequest
}
sealed interface CredentialManagerResponse {
data object NoCredentials : CredentialManagerResponse
}
interface CredentialManager {
val credentialRequests: Flow<CredentialManagerRequest>
suspend fun getCredentials()
}
class CredentialManagerImpl() : CredentialManager {
private val _credentialRequests = Channel<CredentialManagerRequest>()
override val credentialRequests = _credentialRequests.receiveAsFlow()
override suspend fun getCredentials() {
this._credentialRequests.send(CredentialManagerRequest.GetCredentials)
}
}

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.navigation
package ing.bikeshedengineer.debtpirate.domain.navigation
import kotlinx.serialization.Serializable

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.navigation
package ing.bikeshedengineer.debtpirate.domain.navigation
import androidx.navigation.NavOptionsBuilder

View file

@ -1,10 +1,9 @@
package ing.bikeshedengineer.debtpirate.navigation
package ing.bikeshedengineer.debtpirate.domain.navigation
import androidx.navigation.NavOptionsBuilder
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.receiveAsFlow
import javax.inject.Inject
interface Navigator {
val startDestination: Destination

View file

@ -5,6 +5,21 @@ import android.util.Log
import androidx.credentials.CreatePasswordRequest
import androidx.credentials.CredentialManager
import androidx.credentials.exceptions.CreateCredentialException
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ActivityComponent
import dagger.hilt.android.qualifiers.ActivityContext
import dagger.hilt.android.scopes.ActivityScoped
@Module
@InstallIn(ActivityComponent::class)
object StoreCredentialsUseCaseModule {
@Provides
@ActivityScoped
fun provideStoreCredentialsUseCase(@ActivityContext context: Context) = StoreCredentialsUseCase(context)
}
class StoreCredentialsUseCase(val context: Context) {
suspend operator fun invoke(username: String, password: String) {

View file

@ -1,6 +0,0 @@
package ing.bikeshedengineer.debtpirate.types
sealed class Either<out A, out B> {
class Left<A>(val value: A) : Either<A, Nothing>()
class Right<B>(val value: B) : Either<Nothing, B>()
}