-
Notifications
You must be signed in to change notification settings - Fork 3
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
[AN] 마이페이지 수정 및 보기 기능 개선 #602
Changes from 15 commits
c493caa
fa1efb2
264c137
5c8b837
dd7a23a
829d605
3c4dfb9
8110519
6c38e2b
7fd38b9
b181627
39db7ee
88fc692
1be2271
cc6016b
dba6c67
0ef0bef
71c2000
fca93bf
8d3920e
c582543
4803819
058d484
24ce134
e97f2b7
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 |
---|---|---|
@@ -1,32 +1,46 @@ | ||
package com.created.team201.presentation.myPage | ||
|
||
import android.content.res.ColorStateList | ||
import android.os.Bundle | ||
import android.util.TypedValue | ||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.EditText | ||
import android.widget.GridLayout | ||
import android.widget.ImageView | ||
import android.widget.Toast | ||
import androidx.core.content.ContextCompat | ||
import androidx.core.view.forEach | ||
import androidx.core.view.setMargins | ||
import androidx.core.widget.doOnTextChanged | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.commit | ||
import androidx.fragment.app.viewModels | ||
import com.bumptech.glide.Glide | ||
import com.created.team201.R | ||
import com.created.team201.databinding.FragmentMyPageBinding | ||
import com.created.team201.presentation.common.BindingFragment | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.FAIL | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.IDLE | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.SUCCESS | ||
import com.created.team201.presentation.myPage.MyPageViewModel.Event.EnableModify | ||
import com.created.team201.presentation.myPage.MyPageViewModel.Event.ModifyMyPage | ||
import com.created.team201.presentation.myPage.MyPageViewModel.Event.ShowDialog | ||
import com.created.team201.presentation.myPage.MyPageViewModel.Event.ShowToast | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.Fail | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.Loading | ||
import com.created.team201.presentation.myPage.MyPageViewModel.State.Success | ||
import com.created.team201.presentation.myPage.model.ProfileType | ||
import com.created.team201.presentation.myPage.model.TierProgress | ||
import com.created.team201.presentation.setting.SettingActivity | ||
import com.created.team201.presentation.studyDetail.model.Tier | ||
import com.created.team201.util.FirebaseLogUtil | ||
import com.created.team201.util.FirebaseLogUtil.SCREEN_MY_PAGE | ||
import com.created.team201.util.collectOnStarted | ||
import dagger.hilt.android.AndroidEntryPoint | ||
|
||
@AndroidEntryPoint | ||
class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_my_page) { | ||
class MyPageFragment : Fragment() { | ||
private val myPageViewModel: MyPageViewModel by viewModels() | ||
private var _binding: FragmentMyPageBinding? = null | ||
private val binding: FragmentMyPageBinding get() = _binding!! | ||
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. 오래동안 안써서 까먹을 법도 한데 세심하게 잘 처리해주셨네요! |
||
|
||
override fun onHiddenChanged(hidden: Boolean) { | ||
super.onHiddenChanged(hidden) | ||
|
@@ -43,21 +57,39 @@ class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_ | |
FirebaseLogUtil.logScreenEvent(SCREEN_MY_PAGE, [email protected]) | ||
} | ||
|
||
override fun onCreateView( | ||
inflater: LayoutInflater, | ||
container: ViewGroup?, | ||
savedInstanceState: Bundle? | ||
): View { | ||
_binding = FragmentMyPageBinding.inflate(layoutInflater) | ||
return binding.root | ||
} | ||
|
||
override fun onDestroyView() { | ||
super.onDestroyView() | ||
|
||
_binding = null | ||
} | ||
|
||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { | ||
super.onViewCreated(view, savedInstanceState) | ||
|
||
initBinding() | ||
setActionBar() | ||
initMyProfile() | ||
setNicknameValidate() | ||
setMyPageObserve() | ||
setActionBar() | ||
setOnProfileModifyClick() | ||
observeProfile() | ||
setEditTextChangeListener() | ||
collectMyProfileInformation() | ||
collectMyProfileType() | ||
collectModifyProfileState() | ||
collectNicknameState() | ||
collectMyProfile() | ||
collectMyPageEvent() | ||
} | ||
|
||
private fun initBinding() { | ||
binding.lifecycleOwner = viewLifecycleOwner | ||
binding.viewModel = myPageViewModel | ||
private fun initMyProfile() { | ||
myPageViewModel.loadProfile() | ||
myPageViewModel.setProfileType(ProfileType.VIEW) | ||
} | ||
|
||
private fun setActionBar() { | ||
|
@@ -77,58 +109,167 @@ class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_ | |
startActivity(SettingActivity.getIntent(requireContext())) | ||
} | ||
|
||
private fun initMyProfile() { | ||
myPageViewModel.loadProfile() | ||
myPageViewModel.setProfileType(ProfileType.VIEW) | ||
private fun setOnProfileModifyClick() { | ||
binding.tvMyPageBtnModifyProfile.setOnClickListener { | ||
when (myPageViewModel.profileType.value) { | ||
ProfileType.VIEW -> { | ||
myPageViewModel.switchProfileType() | ||
} | ||
|
||
ProfileType.MODIFY -> { | ||
myPageViewModel.changeMyPageEvent(ShowDialog) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun setProfileView(enabled: Boolean) { | ||
setNicknameReadWriteMode(enabled) | ||
setIntroductionReadWriteMode(enabled) | ||
binding.etMyPageProfileNickname.requestFocus(View.FOCUS_UP) | ||
binding.tvMyPageNicknameValidateIntroduction.visibility = | ||
if (enabled) View.VISIBLE else View.GONE | ||
binding.tbMyPage.menu.forEach { item -> | ||
item.isVisible = !enabled | ||
} | ||
binding.tvMyPageBtnModifyProfile.text = | ||
if (enabled) getString(R.string.myPage_button_save_profile) else getString(R.string.myPage_button_modify_profile) | ||
} | ||
|
||
private fun setNicknameValidate() { | ||
binding.etMyPageProfileNickname.setOnFocusChangeListener { _, focus -> | ||
if (focus) return@setOnFocusChangeListener | ||
myPageViewModel.checkAvailableNickname() | ||
private fun setNicknameReadWriteMode(enabled: Boolean) { | ||
with(binding.etMyPageProfileNickname) { | ||
isEnabled = enabled | ||
when (enabled) { | ||
true -> { | ||
backgroundTintList = | ||
ColorStateList.valueOf(requireContext().getColor(R.color.green02_E639D353)) | ||
setCompoundDrawablesWithIntrinsicBounds( | ||
null, | ||
null, | ||
ContextCompat.getDrawable(requireContext(), R.drawable.ic_edit_16), | ||
null, | ||
) | ||
} | ||
|
||
false -> { | ||
backgroundTintList = | ||
ColorStateList.valueOf(requireContext().getColor(R.color.transparent)) | ||
setCompoundDrawables(null, null, null, null) | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun setMyPageObserve() { | ||
myPageViewModel.profileType.observe(viewLifecycleOwner) { profileType -> | ||
private fun setIntroductionReadWriteMode(enabled: Boolean) { | ||
with(binding.etMyPageProfileIntroduction) { | ||
when (enabled) { | ||
true -> { | ||
background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_stroke_fill_color_5dp) | ||
linksClickable = enabled.not() | ||
isCursorVisible = enabled | ||
keyListener = EditText(requireContext()).keyListener | ||
} | ||
|
||
false -> { | ||
background = ContextCompat.getDrawable(requireContext(), R.drawable.bg_rectangle_radius_5dp) | ||
linksClickable = enabled.not() | ||
isCursorVisible = enabled | ||
keyListener = null | ||
} | ||
} | ||
} | ||
} | ||
|
||
private fun setEditTextChangeListener() { | ||
binding.etMyPageProfileNickname.filters = myPageViewModel.getInputFilter() | ||
binding.etMyPageProfileNickname.doOnTextChanged { text, start, before, count -> | ||
myPageViewModel.setNickname(text.toString()) | ||
} | ||
binding.etMyPageProfileIntroduction.doOnTextChanged { text, _, _, _ -> | ||
myPageViewModel.setIntroduction(text.toString()) | ||
} | ||
} | ||
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. 함수 파라미터가 없기 때문에 prefix를 set 대신 setup으로 변경하시는게 좋을 것 같네요 |
||
|
||
private fun collectMyProfileInformation() { | ||
myPageViewModel.nickname.collectOnStarted(viewLifecycleOwner) { nickname -> | ||
if (binding.etMyPageProfileNickname.text.toString() == nickname) return@collectOnStarted | ||
binding.etMyPageProfileNickname.setText(nickname) | ||
} | ||
|
||
myPageViewModel.introduction.collectOnStarted(viewLifecycleOwner) { introduction -> | ||
if (binding.etMyPageProfileIntroduction.text.toString() == introduction) return@collectOnStarted | ||
binding.etMyPageProfileIntroduction.setText(introduction) | ||
} | ||
} | ||
|
||
private fun collectMyProfileType() { | ||
myPageViewModel.profileType.collectOnStarted(viewLifecycleOwner) { profileType -> | ||
when (profileType) { | ||
ProfileType.VIEW -> setProfileView(false) | ||
ProfileType.MODIFY -> setProfileView(true) | ||
else -> Unit | ||
} | ||
} | ||
myPageViewModel.modifyProfileState.observe(viewLifecycleOwner) { modifyProfileState -> | ||
} | ||
|
||
private fun collectModifyProfileState() { | ||
|
||
myPageViewModel.modifyProfileState.collectOnStarted(viewLifecycleOwner) { modifyProfileState -> | ||
when (modifyProfileState) { | ||
SUCCESS -> { | ||
Toast.makeText( | ||
requireContext(), | ||
getString(R.string.myPage_toast_modify_profile_success), | ||
Toast.LENGTH_SHORT, | ||
).show() | ||
Loading -> Unit | ||
Success -> { | ||
myPageViewModel.changeMyPageEvent( | ||
ShowToast(getString(R.string.myPage_toast_modify_profile_success)) | ||
) | ||
} | ||
|
||
FAIL -> { | ||
Toast.makeText( | ||
requireContext(), | ||
getString(R.string.myPage_toast_modify_profile_failed), | ||
Toast.LENGTH_SHORT, | ||
).show() | ||
myPageViewModel.resetModifyProfile() | ||
Fail -> { | ||
myPageViewModel.changeMyPageEvent( | ||
ShowToast(getString(R.string.myPage_toast_modify_profile_failed)) | ||
) | ||
} | ||
} | ||
} | ||
} | ||
|
||
IDLE -> throw IllegalStateException() | ||
private fun collectNicknameState() { | ||
myPageViewModel.nicknameState.collectOnStarted(viewLifecycleOwner) { state -> | ||
with(binding.tvMyPageNicknameValidateIntroduction) { | ||
text = getString(state.introduction) | ||
setTextColor(requireContext().getColor(state.color)) | ||
} | ||
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. wow. |
||
} | ||
} | ||
|
||
private fun setOnProfileModifyClick() { | ||
binding.tvMyPageBtnModifyProfile.setOnClickListener { | ||
when (myPageViewModel.profileType.value) { | ||
ProfileType.VIEW -> { | ||
myPageViewModel.switchProfileType() | ||
} | ||
private fun collectMyProfile() { | ||
myPageViewModel.profile.collectOnStarted(viewLifecycleOwner) { profile -> | ||
binding.ivMyPageProfile.loadImageUrl(profile.profileImageUrl) | ||
binding.tvMyPageProfileId.text = profile.githubId | ||
binding.etMyPageProfileNickname.setText(profile.profileInformation.nickname.nickname) | ||
binding.etMyPageProfileIntroduction.setText(profile.profileInformation.introduction) | ||
binding.layoutMyPageStudySuccessRate.result = | ||
getString(R.string.profile_success_rate_format, profile.successRate) | ||
binding.layoutMyPageTodoSuccessRate.result = | ||
getString(R.string.profile_todo_success_rate_format, profile.successfulRoundCount) | ||
setupTierProgress( | ||
TierProgress.of( | ||
Tier.of(profile.tier), | ||
profile.tierProgress, | ||
).getTierProgressTable(), | ||
) | ||
} | ||
} | ||
|
||
ProfileType.MODIFY -> { | ||
private fun ImageView.loadImageUrl(imageUrl: String?) { | ||
Glide.with(requireContext()) | ||
.load(imageUrl) | ||
.into(this) | ||
} | ||
|
||
private fun collectMyPageEvent() { | ||
myPageViewModel.myPageEvent.collectOnStarted(viewLifecycleOwner) { event -> | ||
when (event) { | ||
is ShowToast -> showToast(event.message) | ||
ShowDialog -> { | ||
removeDialog() | ||
showDialog( | ||
getString(R.string.myPage_dialog_modify_profile_title), | ||
|
@@ -137,40 +278,18 @@ class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_ | |
) | ||
} | ||
|
||
else -> throw IllegalStateException() | ||
ModifyMyPage -> myPageViewModel.patchMyProfile() | ||
is EnableModify -> binding.tvMyPageBtnModifyProfile.isEnabled = event.isEnable | ||
} | ||
} | ||
} | ||
|
||
private fun onModifySaveClick(): MyPageDialogClickListener = | ||
object : MyPageDialogClickListener { | ||
override fun onCancelClick() { | ||
myPageViewModel.resetModifyProfile() | ||
Toast.makeText( | ||
requireContext(), | ||
getString(R.string.myPage_toast_modify_profile_cancel), | ||
Toast.LENGTH_SHORT, | ||
).show() | ||
myPageViewModel.switchProfileType() | ||
} | ||
|
||
override fun onOkClick() { | ||
myPageViewModel.patchMyProfile() | ||
myPageViewModel.switchProfileType() | ||
private fun removeDialog() { | ||
childFragmentManager.findFragmentByTag(TAG_DIALOG_MODIFY_PROFILE)?.let { | ||
childFragmentManager.commit { | ||
remove(it) | ||
} | ||
} | ||
|
||
private fun setProfileView(enabled: Boolean) { | ||
binding.etMyPageProfileNickname.isEnabled = enabled | ||
binding.etMyPageProfileIntroduction.isEnabled = enabled | ||
binding.etMyPageProfileNickname.requestFocus(View.FOCUS_UP) | ||
binding.tvMyPageNicknameValidateIntroduction.visibility = | ||
if (enabled) View.VISIBLE else View.GONE | ||
binding.tbMyPage.menu.forEach { item -> | ||
item.isVisible = !enabled | ||
} | ||
binding.tvMyPageBtnModifyProfile.text = | ||
if (enabled) getString(R.string.myPage_button_save_profile) else getString(R.string.myPage_button_modify_profile) | ||
} | ||
|
||
private fun showDialog( | ||
|
@@ -184,21 +303,21 @@ class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_ | |
) | ||
} | ||
|
||
private fun removeDialog() { | ||
childFragmentManager.findFragmentByTag(TAG_DIALOG_MODIFY_PROFILE)?.let { | ||
childFragmentManager.commit { | ||
remove(it) | ||
private fun onModifySaveClick(): MyPageDialogClickListener = | ||
object : MyPageDialogClickListener { | ||
override fun onCancelClick() { | ||
myPageViewModel.changeMyPageEvent( | ||
ShowToast(getString(R.string.myPage_toast_modify_profile_cancel)) | ||
) | ||
myPageViewModel.resetModifyProfile() | ||
myPageViewModel.switchProfileType() | ||
} | ||
} | ||
} | ||
|
||
private fun observeProfile() { | ||
myPageViewModel.profile.observe(viewLifecycleOwner) { profile -> | ||
val tierProgress = | ||
TierProgress.of(Tier.of(profile.tier), profile.tierProgress).getTierProgressTable() | ||
setupTierProgress(tierProgress) | ||
override fun onOkClick() { | ||
myPageViewModel.changeMyPageEvent(ModifyMyPage) | ||
myPageViewModel.switchProfileType() | ||
} | ||
} | ||
} | ||
|
||
private fun setupTierProgress(tierProgress: List<Int>) { | ||
binding.glMyPageTierProgress.removeAllViews() | ||
|
@@ -228,6 +347,9 @@ class MyPageFragment : BindingFragment<FragmentMyPageBinding>(R.layout.fragment_ | |
requireContext().resources.displayMetrics, | ||
).toInt() | ||
|
||
private fun showToast(message: String) = | ||
Toast.makeText(requireContext(), message, Toast.LENGTH_SHORT).show() | ||
|
||
companion object { | ||
private const val TAG_DIALOG_MODIFY_PROFILE = "TAG_DIALOG_MODIFY_PROFILE" | ||
private const val TOTAL_BLOCK_COUNT = 20 | ||
|
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.
새로운 ViewBinding BaseClass 만들어두었습니다! HomeFragement참고