commit
c0bc4c24ae
8 changed files with 105 additions and 6 deletions
|
@ -9,6 +9,7 @@ import androidx.compose.material.Text
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Email
|
import androidx.compose.material.icons.filled.Email
|
||||||
import androidx.compose.material.icons.filled.Lock
|
import androidx.compose.material.icons.filled.Lock
|
||||||
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import be.ugent.sel.studeez.R.string as AppText
|
import be.ugent.sel.studeez.R.string as AppText
|
||||||
import be.ugent.sel.studeez.R.drawable as AppIcon
|
import be.ugent.sel.studeez.R.drawable as AppIcon
|
||||||
|
@ -35,6 +36,22 @@ fun BasicField(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun UsernameField(
|
||||||
|
value: String,
|
||||||
|
onNewValue: (String) -> Unit,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
OutlinedTextField(
|
||||||
|
singleLine = true,
|
||||||
|
modifier = modifier,
|
||||||
|
value = value,
|
||||||
|
onValueChange = { onNewValue(it) },
|
||||||
|
placeholder = { Text(stringResource(AppText.username)) },
|
||||||
|
leadingIcon = { Icon(imageVector = Icons.Default.Person, contentDescription = "Username") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun EmailField(
|
fun EmailField(
|
||||||
value: String,
|
value: String,
|
||||||
|
|
|
@ -2,7 +2,9 @@ package be.ugent.sel.studeez.di
|
||||||
|
|
||||||
import be.ugent.sel.studeez.domain.AccountDAO
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
|
import be.ugent.sel.studeez.domain.UserDAO
|
||||||
import be.ugent.sel.studeez.domain.implementation.FirebaseAccountDAO
|
import be.ugent.sel.studeez.domain.implementation.FirebaseAccountDAO
|
||||||
|
import be.ugent.sel.studeez.domain.implementation.FirebaseUserDAO
|
||||||
import be.ugent.sel.studeez.domain.implementation.LogServiceImpl
|
import be.ugent.sel.studeez.domain.implementation.LogServiceImpl
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
|
@ -14,6 +16,8 @@ import dagger.hilt.components.SingletonComponent
|
||||||
abstract class DatabaseModule {
|
abstract class DatabaseModule {
|
||||||
@Binds abstract fun provideAccountDAO(impl: FirebaseAccountDAO): AccountDAO
|
@Binds abstract fun provideAccountDAO(impl: FirebaseAccountDAO): AccountDAO
|
||||||
|
|
||||||
|
@Binds abstract fun provideUserDAO(impl: FirebaseUserDAO): UserDAO
|
||||||
|
|
||||||
@Binds abstract fun provideLogService(impl: LogServiceImpl): LogService
|
@Binds abstract fun provideLogService(impl: LogServiceImpl): LogService
|
||||||
|
|
||||||
}
|
}
|
10
app/src/main/java/be/ugent/sel/studeez/domain/UserDAO.kt
Normal file
10
app/src/main/java/be/ugent/sel/studeez/domain/UserDAO.kt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package be.ugent.sel.studeez.domain
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
interface UserDAO {
|
||||||
|
|
||||||
|
suspend fun getUserName(): String?
|
||||||
|
|
||||||
|
suspend fun save(newUsername: String)
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package be.ugent.sel.studeez.domain.implementation
|
||||||
|
|
||||||
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
|
import be.ugent.sel.studeez.domain.UserDAO
|
||||||
|
import com.google.firebase.firestore.DocumentReference
|
||||||
|
import com.google.firebase.firestore.FirebaseFirestore
|
||||||
|
import kotlinx.coroutines.tasks.await
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class FirebaseUserDAO @Inject constructor(
|
||||||
|
private val firestore: FirebaseFirestore,
|
||||||
|
private val auth: AccountDAO
|
||||||
|
) : UserDAO {
|
||||||
|
|
||||||
|
override suspend fun getUserName(): String? {
|
||||||
|
return currentUserDocument().get().await().getString("username")
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun save(newUsername: String) {
|
||||||
|
currentUserDocument().set(mapOf("username" to newUsername))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun currentUserDocument(): DocumentReference =
|
||||||
|
firestore.collection(USER_COLLECTION).document(auth.currentUserId)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val USER_COLLECTION = "users"
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,8 @@ import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Person
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
|
@ -36,9 +38,30 @@ fun SignUpScreen(
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
EmailField(uiState.email, viewModel::onEmailChange, fieldModifier)
|
|
||||||
PasswordField(uiState.password, viewModel::onPasswordChange, fieldModifier)
|
UsernameField(
|
||||||
RepeatPasswordField(uiState.repeatPassword, viewModel::onRepeatPasswordChange, fieldModifier)
|
uiState.username,
|
||||||
|
viewModel::onUsernameChange,
|
||||||
|
fieldModifier
|
||||||
|
)
|
||||||
|
|
||||||
|
EmailField(
|
||||||
|
uiState.email,
|
||||||
|
viewModel::onEmailChange,
|
||||||
|
fieldModifier
|
||||||
|
)
|
||||||
|
|
||||||
|
PasswordField(
|
||||||
|
uiState.password,
|
||||||
|
viewModel::onPasswordChange,
|
||||||
|
fieldModifier
|
||||||
|
)
|
||||||
|
|
||||||
|
RepeatPasswordField(
|
||||||
|
uiState.repeatPassword,
|
||||||
|
viewModel::onRepeatPasswordChange,
|
||||||
|
fieldModifier
|
||||||
|
)
|
||||||
|
|
||||||
BasicButton(AppText.create_account, Modifier.basicButton()) {
|
BasicButton(AppText.create_account, Modifier.basicButton()) {
|
||||||
viewModel.onSignUpClick(openAndPopUp)
|
viewModel.onSignUpClick(openAndPopUp)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package be.ugent.sel.studeez.screens.sign_up
|
package be.ugent.sel.studeez.screens.sign_up
|
||||||
|
|
||||||
data class SignUpUiState(
|
data class SignUpUiState(
|
||||||
|
val username: String = "",
|
||||||
val email: String = "",
|
val email: String = "",
|
||||||
val password: String = "",
|
val password: String = "",
|
||||||
val repeatPassword: String = ""
|
val repeatPassword: String = ""
|
||||||
|
|
|
@ -7,26 +7,37 @@ import be.ugent.sel.studeez.common.ext.passwordMatches
|
||||||
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
|
import be.ugent.sel.studeez.common.snackbar.SnackbarManager
|
||||||
import be.ugent.sel.studeez.domain.AccountDAO
|
import be.ugent.sel.studeez.domain.AccountDAO
|
||||||
import be.ugent.sel.studeez.domain.LogService
|
import be.ugent.sel.studeez.domain.LogService
|
||||||
|
import be.ugent.sel.studeez.domain.UserDAO
|
||||||
|
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN
|
||||||
import be.ugent.sel.studeez.navigation.StudeezDestinations.LOGIN_SCREEN
|
import be.ugent.sel.studeez.navigation.StudeezDestinations.LOGIN_SCREEN
|
||||||
import be.ugent.sel.studeez.navigation.StudeezDestinations.SIGN_UP_SCREEN
|
import be.ugent.sel.studeez.navigation.StudeezDestinations.SIGN_UP_SCREEN
|
||||||
import be.ugent.sel.studeez.screens.StudeezViewModel
|
import be.ugent.sel.studeez.screens.StudeezViewModel
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.FlowCollector
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.take
|
||||||
import be.ugent.sel.studeez.R.string as AppText
|
import be.ugent.sel.studeez.R.string as AppText
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class SignUpViewModel @Inject constructor(
|
class SignUpViewModel @Inject constructor(
|
||||||
private val accountService: AccountDAO,
|
private val accountDAO: AccountDAO,
|
||||||
|
private val userDAO: UserDAO,
|
||||||
logService: LogService
|
logService: LogService
|
||||||
) : StudeezViewModel(logService) {
|
) : StudeezViewModel(logService) {
|
||||||
var uiState = mutableStateOf(SignUpUiState())
|
var uiState = mutableStateOf(SignUpUiState())
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
private val username
|
||||||
|
get() = uiState.value.username
|
||||||
private val email
|
private val email
|
||||||
get() = uiState.value.email
|
get() = uiState.value.email
|
||||||
private val password
|
private val password
|
||||||
get() = uiState.value.password
|
get() = uiState.value.password
|
||||||
|
|
||||||
|
fun onUsernameChange(newValue: String) {
|
||||||
|
uiState.value = uiState.value.copy(username = newValue)
|
||||||
|
}
|
||||||
fun onEmailChange(newValue: String) {
|
fun onEmailChange(newValue: String) {
|
||||||
uiState.value = uiState.value.copy(email = newValue)
|
uiState.value = uiState.value.copy(email = newValue)
|
||||||
}
|
}
|
||||||
|
@ -56,8 +67,10 @@ class SignUpViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
launchCatching {
|
launchCatching {
|
||||||
accountService.signUpWithEmailAndPassword(email, password)
|
accountDAO.signUpWithEmailAndPassword(email, password)
|
||||||
openAndPopUp(LOGIN_SCREEN, SIGN_UP_SCREEN)
|
accountDAO.signInWithEmailAndPassword(email, password)
|
||||||
|
userDAO.save(username)
|
||||||
|
openAndPopUp(HOME_SCREEN, SIGN_UP_SCREEN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<resources>
|
<resources>
|
||||||
<!-- Common -->
|
<!-- Common -->
|
||||||
<string name="app_name">Studeez</string>
|
<string name="app_name">Studeez</string>
|
||||||
|
<string name="username">Username</string>
|
||||||
<string name="email">Email</string>
|
<string name="email">Email</string>
|
||||||
<string name="password">Password</string>
|
<string name="password">Password</string>
|
||||||
<string name="repeat_password">Repeat password</string>
|
<string name="repeat_password">Repeat password</string>
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
<string name="password_match_error">Passwords do not match.</string>
|
<string name="password_match_error">Passwords do not match.</string>
|
||||||
<string name="already_user">Already have an account? Log in.</string>
|
<string name="already_user">Already have an account? Log in.</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- LoginScreen -->
|
<!-- LoginScreen -->
|
||||||
<string name="not_already_user">Don\'t have an account yet? Sign up.</string>
|
<string name="not_already_user">Don\'t have an account yet? Sign up.</string>
|
||||||
<string name="sign_in">Sign in</string>
|
<string name="sign_in">Sign in</string>
|
||||||
|
|
Reference in a new issue