#18 Edit and delete profile implemented
This commit is contained in:
		
							parent
							
								
									f263b34c12
								
							
						
					
					
						commit
						5e2c8de521
					
				
					 9 changed files with 32 additions and 25 deletions
				
			
		|  | @ -118,6 +118,6 @@ fun NavGraphBuilder.studeezGraph(appState: StudeezAppstate) { | ||||||
| 
 | 
 | ||||||
|     // Edit screens |     // Edit screens | ||||||
|     composable(StudeezDestinations.EDIT_PROFILE_SCREEN) { |     composable(StudeezDestinations.EDIT_PROFILE_SCREEN) { | ||||||
|         EditProfileScreen(goBack) |         EditProfileScreen(goBack, openAndPopUp) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -1,7 +1,6 @@ | ||||||
| package be.ugent.sel.studeez.common.composable | package be.ugent.sel.studeez.common.composable | ||||||
| 
 | 
 | ||||||
| import androidx.annotation.StringRes | import androidx.annotation.StringRes | ||||||
| import androidx.compose.foundation.text.KeyboardActions |  | ||||||
| import androidx.compose.foundation.text.KeyboardOptions | import androidx.compose.foundation.text.KeyboardOptions | ||||||
| import androidx.compose.material.Icon | import androidx.compose.material.Icon | ||||||
| import androidx.compose.material.IconButton | import androidx.compose.material.IconButton | ||||||
|  | @ -12,17 +11,15 @@ 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.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.drawable as AppIcon |  | ||||||
| import androidx.compose.ui.Modifier | import androidx.compose.ui.Modifier | ||||||
| import androidx.compose.ui.input.key.Key |  | ||||||
| import androidx.compose.ui.res.painterResource | import androidx.compose.ui.res.painterResource | ||||||
| import androidx.compose.ui.res.stringResource | import androidx.compose.ui.res.stringResource | ||||||
| import androidx.compose.ui.text.input.ImeAction |  | ||||||
| import androidx.compose.ui.text.input.KeyboardType | import androidx.compose.ui.text.input.KeyboardType | ||||||
| import androidx.compose.ui.text.input.PasswordVisualTransformation | import androidx.compose.ui.text.input.PasswordVisualTransformation | ||||||
| import androidx.compose.ui.text.input.VisualTransformation | import androidx.compose.ui.text.input.VisualTransformation | ||||||
| import be.ugent.sel.studeez.common.ext.fieldModifier | import be.ugent.sel.studeez.common.ext.fieldModifier | ||||||
|  | import be.ugent.sel.studeez.R.drawable as AppIcon | ||||||
|  | import be.ugent.sel.studeez.R.string as AppText | ||||||
| 
 | 
 | ||||||
| @Composable | @Composable | ||||||
| fun BasicField( | fun BasicField( | ||||||
|  |  | ||||||
|  | @ -29,5 +29,6 @@ interface AccountDAO { | ||||||
|     suspend fun sendRecoveryEmail(email: String) |     suspend fun sendRecoveryEmail(email: String) | ||||||
|     suspend fun signUpWithEmailAndPassword(email: String, password: String) |     suspend fun signUpWithEmailAndPassword(email: String, password: String) | ||||||
|     suspend fun deleteAccount() |     suspend fun deleteAccount() | ||||||
|  | 
 | ||||||
|     suspend fun signOut() |     suspend fun signOut() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -4,4 +4,10 @@ interface UserDAO { | ||||||
| 
 | 
 | ||||||
|     suspend fun getUsername(): String? |     suspend fun getUsername(): String? | ||||||
|     suspend fun save(newUsername: String) |     suspend fun save(newUsername: String) | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Delete all references to this user in the database. Similar to the deleteCascade in | ||||||
|  |      * relational databases. | ||||||
|  |      */ | ||||||
|  |     suspend fun deleteUserReferences() | ||||||
| } | } | ||||||
|  | @ -1,19 +1,13 @@ | ||||||
| package be.ugent.sel.studeez.domain.implementation | package be.ugent.sel.studeez.domain.implementation | ||||||
| 
 | 
 | ||||||
| import androidx.compose.runtime.rememberCoroutineScope | import be.ugent.sel.studeez.R | ||||||
|  | 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.UserDAO | import be.ugent.sel.studeez.domain.UserDAO | ||||||
| import com.google.firebase.firestore.DocumentReference | import com.google.firebase.firestore.DocumentReference | ||||||
| import com.google.firebase.firestore.FirebaseFirestore | import com.google.firebase.firestore.FirebaseFirestore | ||||||
| import kotlinx.coroutines.CoroutineScope |  | ||||||
| import kotlinx.coroutines.channels.awaitClose |  | ||||||
| import kotlinx.coroutines.coroutineScope |  | ||||||
| import kotlinx.coroutines.flow.Flow |  | ||||||
| import kotlinx.coroutines.flow.callbackFlow |  | ||||||
| import kotlinx.coroutines.flow.flow |  | ||||||
| import kotlinx.coroutines.tasks.await | import kotlinx.coroutines.tasks.await | ||||||
| import javax.inject.Inject | import javax.inject.Inject | ||||||
| import kotlin.coroutines.coroutineContext |  | ||||||
| 
 | 
 | ||||||
| class FirebaseUserDAO @Inject constructor( | class FirebaseUserDAO @Inject constructor( | ||||||
|     private val firestore: FirebaseFirestore, |     private val firestore: FirebaseFirestore, | ||||||
|  | @ -34,4 +28,10 @@ class FirebaseUserDAO @Inject constructor( | ||||||
|     companion object { |     companion object { | ||||||
|         private const val USER_COLLECTION = "users" |         private const val USER_COLLECTION = "users" | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     override suspend fun deleteUserReferences() { | ||||||
|  |         currentUserDocument().delete() | ||||||
|  |             .addOnSuccessListener { SnackbarManager.showMessage(R.string.success) } | ||||||
|  |             .addOnFailureListener { SnackbarManager.showMessage(R.string.generic_error) } | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | @ -17,6 +17,7 @@ import be.ugent.sel.studeez.ui.theme.StudeezTheme | ||||||
| @Composable | @Composable | ||||||
| fun EditProfileScreen( | fun EditProfileScreen( | ||||||
|     goBack: () -> Unit, |     goBack: () -> Unit, | ||||||
|  |     openAndPopUp: (String, String) -> Unit, | ||||||
|     viewModel: ProfileEditViewModel = hiltViewModel() |     viewModel: ProfileEditViewModel = hiltViewModel() | ||||||
| ) { | ) { | ||||||
|     val uiState by viewModel.uiState |     val uiState by viewModel.uiState | ||||||
|  | @ -36,7 +37,7 @@ fun EditProfileScreen( | ||||||
|                 viewModel.onSaveClick() |                 viewModel.onSaveClick() | ||||||
|             } |             } | ||||||
|             BasicTextButton(text = R.string.delete_profile, Modifier.textButton()) { |             BasicTextButton(text = R.string.delete_profile, Modifier.textButton()) { | ||||||
|                 viewModel.onDeleteClick() |                 viewModel.onDeleteClick(openAndPopUp) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | @ -47,7 +48,8 @@ fun EditProfileScreen( | ||||||
| fun EditProfileScreenComposable() { | fun EditProfileScreenComposable() { | ||||||
|     StudeezTheme { |     StudeezTheme { | ||||||
|         EditProfileScreen ( |         EditProfileScreen ( | ||||||
|             {} |             {}, | ||||||
|  |             {_, _ -> {}} | ||||||
|         ) |         ) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -6,6 +6,7 @@ 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.domain.UserDAO | ||||||
|  | import be.ugent.sel.studeez.navigation.StudeezDestinations | ||||||
| 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 javax.inject.Inject | import javax.inject.Inject | ||||||
|  | @ -33,13 +34,15 @@ class ProfileEditViewModel @Inject constructor( | ||||||
|     fun onSaveClick() { |     fun onSaveClick() { | ||||||
|         launchCatching { |         launchCatching { | ||||||
|             userDAO.save(uiState.value.username) |             userDAO.save(uiState.value.username) | ||||||
|             SnackbarManager.showMessage(R.string.save_success) |             SnackbarManager.showMessage(R.string.success) | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun onDeleteClick() { |     fun onDeleteClick(openAndPopUp: (String, String) -> Unit) { | ||||||
|         launchCatching { |         launchCatching { | ||||||
|             accountDAO.deleteAccount() |             userDAO.deleteUserReferences() // Delete references | ||||||
|  |             accountDAO.deleteAccount() // Delete authentication | ||||||
|         } |         } | ||||||
|  |         openAndPopUp(StudeezDestinations.SIGN_UP_SCREEN, StudeezDestinations.EDIT_PROFILE_SCREEN) | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -13,11 +13,8 @@ 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 javax.inject.Inject | import javax.inject.Inject | ||||||
|  | import be.ugent.sel.studeez.R.string as AppText | ||||||
| 
 | 
 | ||||||
| @HiltViewModel | @HiltViewModel | ||||||
| class SignUpViewModel @Inject constructor( | class SignUpViewModel @Inject constructor( | ||||||
|  |  | ||||||
|  | @ -5,16 +5,17 @@ | ||||||
|     <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> | ||||||
|     <string name="go_back">Go back</string> |  | ||||||
|     <string name="menu">Menu</string> |     <string name="menu">Menu</string> | ||||||
| 
 | 
 | ||||||
|         <!-- Actions --> |         <!-- Actions --> | ||||||
|         <string name="confirm">Confirm</string> |         <string name="confirm">Confirm</string> | ||||||
|         <string name="save">Save</string> |         <string name="save">Save</string> | ||||||
|         <string name="cancel">Cancel</string> |         <string name="cancel">Cancel</string> | ||||||
|  |         <string name="go_back">Go back</string> | ||||||
|  |         <string name="next">Next</string> | ||||||
| 
 | 
 | ||||||
|         <!-- Messages --> |         <!-- Messages --> | ||||||
|         <string name="save_success">Saved successfully!</string> |         <string name="success">Success!</string> | ||||||
|         <string name="try_again">Try again</string> |         <string name="try_again">Try again</string> | ||||||
|         <string name="generic_error">Something wrong happened. Please try again.</string> |         <string name="generic_error">Something wrong happened. Please try again.</string> | ||||||
|         <string name="email_error">Please insert a valid email.</string> |         <string name="email_error">Please insert a valid email.</string> | ||||||
|  |  | ||||||
		Reference in a new issue