-
Notifications
You must be signed in to change notification settings - Fork 0
6주차 필수,심화 #20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
The head ref may contain hidden characters: "6\uC8FC\uCC28-\uD544\uC218,\uC2EC\uD654"
6주차 필수,심화 #20
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,42 +2,76 @@ package org.sopt.dosopttemplate.presentation.auth | |
|
|
||
| import android.content.Intent | ||
| import android.os.Bundle | ||
| import android.view.View.INVISIBLE | ||
| import android.view.View.VISIBLE | ||
| import androidx.activity.viewModels | ||
| import androidx.core.content.ContextCompat | ||
| import dagger.hilt.android.AndroidEntryPoint | ||
| import org.sopt.dosopttemplate.R | ||
| import org.sopt.dosopttemplate.data.datasource.local.DoSoptStorage | ||
| import org.sopt.dosopttemplate.databinding.ActivitySignupBinding | ||
| import org.sopt.dosopttemplate.util.UiState | ||
| import org.sopt.dosopttemplate.util.binding.BindingActivity | ||
| import org.sopt.dosopttemplate.util.extension.setOnSingleClickListener | ||
| import org.sopt.dosopttemplate.util.extension.setVisible | ||
| import org.sopt.dosopttemplate.util.extension.showSnackbar | ||
| import java.util.regex.Pattern | ||
|
|
||
| @AndroidEntryPoint | ||
| class SignUpActivity : BindingActivity<ActivitySignupBinding>(R.layout.activity_signup) { | ||
|
|
||
| private val signUpViewModel: SignUpViewModel by viewModels() | ||
| private lateinit var id: String | ||
| private lateinit var pw: String | ||
| private lateinit var name: String | ||
| private lateinit var mbti: String | ||
|
|
||
| override fun onCreate(savedInstanceState: Bundle?) { | ||
| super.onCreate(savedInstanceState) | ||
| setContentView(binding.root) | ||
| binding.signupViewModel = signUpViewModel | ||
|
|
||
| clickSignUpEnd() | ||
| observeId() | ||
| observePw() | ||
| observeSignUpButton() | ||
| } | ||
|
|
||
| private fun observeSignUpButton() { | ||
| signUpViewModel.isEnabledLoginButton.observe(this) { | ||
| binding.btnSignupEnd.isEnabled = it | ||
| } | ||
| } | ||
|
|
||
| private fun observePw() { | ||
| signUpViewModel.pw.observe(this) { | ||
| if (signUpViewModel.isValidatePassWord(it)) { | ||
| binding.tvSignupPasswordErrorMessage.setVisible(INVISIBLE) | ||
| binding.etSignupPw.backgroundTintList = | ||
| ContextCompat.getColorStateList(this, R.color.Gray_500) | ||
| } else { | ||
| binding.tvSignupPasswordErrorMessage.setVisible(VISIBLE) | ||
| binding.etSignupPw.backgroundTintList = | ||
| ContextCompat.getColorStateList(this, R.color.Pink_500) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun observeId() { | ||
| signUpViewModel.id.observe(this) { | ||
| if (signUpViewModel.isValidateId(it)) { | ||
| binding.tvSignupIdErrorMessage.setVisible(INVISIBLE) | ||
| binding.etSignupId.backgroundTintList = | ||
| ContextCompat.getColorStateList(this, R.color.Gray_500) | ||
| } else { | ||
| binding.tvSignupIdErrorMessage.setVisible(VISIBLE) | ||
| binding.etSignupId.backgroundTintList = | ||
| ContextCompat.getColorStateList(this, R.color.Pink_500) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun clickSignUpEnd() { | ||
| binding.btnSignupEnd.setOnSingleClickListener { | ||
| getSignUpInfo() | ||
| if (isValidateForm()) { | ||
| signUpViewModel.signUp(id, pw, name) | ||
| observeSignUp() | ||
| } else { | ||
| showSnackbar(binding.root, getString(R.string.signup_error_message)) | ||
| } | ||
| signUpViewModel.signUp() | ||
| observeSignUp() | ||
|
||
| } | ||
| } | ||
|
|
||
|
|
@@ -62,40 +96,9 @@ class SignUpActivity : BindingActivity<ActivitySignupBinding>(R.layout.activity_ | |
|
|
||
| private fun getSignUpInfo() { | ||
| with(binding) { | ||
| id = etSignupId.text.toString() | ||
| pw = etSignupPw.text.toString() | ||
| name = etSignupName.text.toString() | ||
| mbti = etSignupMbti.text.toString() | ||
| } | ||
| } | ||
|
|
||
| private fun isValidateForm(): Boolean { | ||
|
|
||
| return isValidateId(id) && isValidatePassWord(pw) && isValidateNickName(name) && | ||
| isValidateMbti(mbti) | ||
| } | ||
|
|
||
| private fun isValidateId(id: String): Boolean { | ||
| return id.isNotBlank() && ID_REGEX.matcher(id).matches() | ||
| } | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 왕 근데 새삼,, 삭제된 함수들도 진짜 간결하구 야무지네요.... 삭제됐지만 배워야겠는데여 |
||
| private fun isValidatePassWord(pw: String): Boolean { | ||
| return pw.isNotBlank() && PW_REGEX.matcher(pw).matches() | ||
| } | ||
|
|
||
| private fun isValidateNickName(name: String): Boolean { | ||
| return name.isNotBlank() | ||
| } | ||
|
|
||
| private fun isValidateMbti(mbti: String): Boolean { | ||
| return mbti.isNotBlank() | ||
| } | ||
|
|
||
| companion object { | ||
| private const val ID_PATTERN = "(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]{6,10}" | ||
| private const val PW_PATTERN = | ||
| "(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#%^&*()])[a-zA-Z0-9!@#%^&*()]{8,12}" | ||
| val ID_REGEX: Pattern = Pattern.compile(ID_PATTERN) | ||
| val PW_REGEX: Pattern = Pattern.compile(PW_PATTERN) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,17 @@ | ||
| package org.sopt.dosopttemplate.presentation.auth | ||
|
|
||
| import androidx.lifecycle.LiveData | ||
| import androidx.lifecycle.MediatorLiveData | ||
| import androidx.lifecycle.MutableLiveData | ||
| import androidx.lifecycle.ViewModel | ||
| import androidx.lifecycle.map | ||
| import androidx.lifecycle.viewModelScope | ||
| import dagger.hilt.android.lifecycle.HiltViewModel | ||
| import kotlinx.coroutines.launch | ||
| import org.sopt.dosopttemplate.data.repository.auth.AuthRepository | ||
| import org.sopt.dosopttemplate.util.UiState | ||
| import org.sopt.dosopttemplate.util.extension.addSourceList | ||
| import java.util.regex.Pattern | ||
| import javax.inject.Inject | ||
|
|
||
| @HiltViewModel | ||
|
|
@@ -18,17 +22,57 @@ class SignUpViewModel @Inject constructor( | |
| private val _signUpResult = MutableLiveData<UiState<Boolean>>() | ||
| val signUpResult: LiveData<UiState<Boolean>> = _signUpResult | ||
|
|
||
| fun signUp(username: String, password: String, nickname: String) { | ||
| val id = MutableLiveData("") | ||
| val pw = MutableLiveData("") | ||
| val nickname = MutableLiveData("") | ||
| val mbti = MutableLiveData("") | ||
|
|
||
| val isEnabledLoginButton = MediatorLiveData<Boolean>().apply { | ||
| addSourceList(id, pw, nickname, mbti) { isValidSignUpInfo() } | ||
| } | ||
|
Comment on lines
+30
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 확장함수 진짜 짱이네염 배워갑니둥,,,
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 편안해지죠 |
||
|
|
||
| val nicknameLength = nickname.map { | ||
| it.length | ||
| } | ||
|
|
||
| fun signUp() { | ||
| viewModelScope.launch { | ||
| authRepository.postSignUpInfo( | ||
| username = username, | ||
| password = password, | ||
| nickname = nickname | ||
| username = id.value.toString(), | ||
| password = pw.value.toString(), | ||
| nickname = nickname.value.toString() | ||
| ).onSuccess { _signUpResult.value = UiState.Success(true) } | ||
|
|
||
| .onFailure { throwable -> | ||
| _signUpResult.value = throwable.message?.let { UiState.Failure(it) } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private fun isValidSignUpInfo() = isValidateId(id.value) && isValidatePassWord(pw.value) | ||
| && isValidateNickName() && isValidateMbti() | ||
|
|
||
| fun isValidateId(id: String?): Boolean { | ||
| return id.isNullOrEmpty() || ID_REGEX.matcher(id).matches() | ||
| } | ||
|
|
||
| fun isValidatePassWord(pw: String?): Boolean { | ||
| return pw.isNullOrEmpty() || PW_REGEX.matcher(pw).matches() | ||
| } | ||
|
|
||
| private fun isValidateNickName(): Boolean { | ||
| return nickname.value?.isNotBlank() ?: false | ||
| } | ||
|
|
||
| private fun isValidateMbti(): Boolean { | ||
| return mbti.value?.isNotBlank() ?: false | ||
| } | ||
|
|
||
| companion object { | ||
| private const val ID_PATTERN = "(?=.*[a-zA-Z])(?=.*[0-9])[a-zA-Z0-9]{6,10}" | ||
| private const val PW_PATTERN = | ||
| "(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[!@#%^&*()])[a-zA-Z0-9!@#%^&*()]{6,12}" | ||
| val ID_REGEX: Pattern = Pattern.compile(ID_PATTERN) | ||
| val PW_REGEX: Pattern = Pattern.compile(PW_PATTERN) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,18 @@ | ||
| package org.sopt.dosopttemplate.util.binding | ||
|
|
||
| import android.view.View | ||
| import android.widget.TextView | ||
| import androidx.databinding.BindingAdapter | ||
|
|
||
| object BindingAdapter { | ||
| @JvmStatic | ||
| @BindingAdapter("setSignupZeroErrorTextVisible") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요런식으루 작성하는 건 먼가요?! Adapter를 Binding하는데 이런식으로 쓰는 건가요?? 아님 어댑터 안의 어떤 요소를 바인딩하는 것인지.. 아니면 어댑터에 끼워줄 애를 이렇게 넣는 것인지.. |
||
| fun setSignupZeroErrorTextVisible(view: TextView, length: Int) { | ||
| if (length == 0) { | ||
| view.visibility = View.VISIBLE | ||
| } else { | ||
| view.visibility = View.INVISIBLE | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 파일은 어떤 역할을 하는건가요?? 이해가 어렵...
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MediatorLiveData에 대한 확장함수 입니다! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package org.sopt.dosopttemplate.util.extension | ||
|
|
||
| import androidx.lifecycle.MediatorLiveData | ||
| import androidx.lifecycle.MutableLiveData | ||
|
|
||
| fun <T> MediatorLiveData<T>.addSourceList( | ||
| vararg liveDataArgument: MutableLiveData<*>, | ||
| onChanged: () -> T | ||
| ) { | ||
| liveDataArgument.forEach { | ||
| this.addSource(it) { value = onChanged() } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
observe가 상태변화가 있을 만한 곳에 넣는 거 맞나요? 어떤 기준으로 observe를 쓰는지 궁금합니당
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
상태변화가 있을 만한 곳이라기 보다는 상태변화 감지가 필요한 곳이 맞는것 같습니다!
이 경우에는 pw가 비밀번호 입력에 대한 LiveData이므로 상태가 변화할 때 마다 감지되어서
비밀번호 입력 조건에 부합한지 확인 후에 오류메세지의 visible처리를 해야되므로 필요하죠!
여기도 함수 분리가 필요해 보이긴 하는데 귀찮음 이슈로 패스....