From 06a178c2b1bf1363fe21160c8d8e47346b176490 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Mon, 17 Jul 2023 00:45:56 +0900 Subject: [PATCH 01/20] #61 [add] edit text and button ui --- .../changepassword/ChangePasswordActivity.kt | 88 ++++++++++++++++++- .../viewmodel/ChangePasswordViewModel.kt | 39 +++++++- app/src/main/res/values/strings.xml | 1 + 3 files changed, 124 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt index 180755f1..b7e50c55 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt @@ -1,6 +1,8 @@ package com.jjbaksa.jjbaksa.ui.changepassword +import android.graphics.drawable.Drawable import androidx.activity.viewModels +import androidx.core.content.ContextCompat import com.jjbaksa.jjbaksa.R import com.jjbaksa.jjbaksa.base.BaseActivity import com.jjbaksa.jjbaksa.databinding.ActivityChangePasswordBinding @@ -14,8 +16,37 @@ class ChangePasswordActivity : BaseActivity() { get() = R.layout.activity_change_password private val viewModel: ChangePasswordViewModel by viewModels() + var currentPasswordText = "" + var newPasswordText = "" + var checkPasswordText = "" + var isFailedCurrentPassword = false + var isFailedNewPassword = false + override fun initView() { binding.jjAppBarContainer.setOnClickListener { finish() } + observeData() + } + + private fun observeData() { + viewModel.currentPasswordState.observe(this) { + isFailedCurrentPassword = !it + if (!it) { + binding.currentPasswordEditText.editTextBackground = failButtonBackground() + } else { + if (newPasswordText != checkPasswordText) { + showSnackBar( + getString(R.string.not_match_new_password), + getString(R.string.cancel) + ) + binding.newPasswordEditText.editTextBackground = failButtonBackground() + binding.checkNewPasswordEditText.editTextBackground = failButtonBackground() + isFailedNewPassword = true + } + } + viewModel.isEnableButton.observe(this) { + binding.changePasswordButton.isEnabled = it + binding.changePasswordButton.isSelected = it + } } override fun subscribe() { @@ -25,29 +56,80 @@ class ChangePasswordActivity : BaseActivity() { setCurrentPassword() setNewPassword() setCheckNewPassword() + setConfirmButton() } private fun setCurrentPassword() { binding.currentPasswordEditText.also { it.setOnFocusChangeListener { _, _ -> } - it.addTextChangedListener { currentPassword -> } + it.addTextChangedListener { currentPassword -> + if (isFailedCurrentPassword) { + it.editTextBackground = comeBackButtonBackground() + isFailedCurrentPassword = false + } + currentPasswordText = currentPassword.toString() + setEditTextState() + } } } private fun setNewPassword() { binding.newPasswordEditText.also { it.setOnFocusChangeListener { _, _ -> } - it.addTextChangedListener { newPassword -> } + it.addTextChangedListener { newPassword -> + if (isFailedNewPassword) { + it.editTextBackground = comeBackButtonBackground() + binding.checkNewPasswordEditText.editTextBackground = comeBackButtonBackground() + isFailedNewPassword = false + } + newPasswordText = newPassword.toString() + setEditTextState() + } } } private fun setCheckNewPassword() { binding.checkNewPasswordEditText.also { it.setOnFocusChangeListener { _, _ -> } - it.addTextChangedListener { checkNewPassword -> } + it.addTextChangedListener { checkNewPassword -> + if (isFailedNewPassword) { + it.editTextBackground = comeBackButtonBackground() + binding.newPasswordEditText.editTextBackground = comeBackButtonBackground() + isFailedNewPassword = false + } + checkPasswordText = checkNewPassword.toString() + setEditTextState() + } + } + } + + private fun isNotEmptyEditText(): Boolean = + currentPasswordText.isNotEmpty() && newPasswordText.isNotEmpty() && checkPasswordText.isNotEmpty() + + private fun setEditTextState() { + if (isNotEmptyEditText()) { + viewModel.setEnabledButton(true) + } else { + viewModel.setEnabledButton(false) } } + private fun setConfirmButton() { + binding.changePasswordButton.setOnClickListener { + viewModel.checkPassword(binding.currentPasswordEditText.editTextText) + } + } + + private fun failButtonBackground(): Drawable? = ContextCompat.getDrawable( + this, + R.drawable.shape_rect_eeeeee_solid_radius_100_stroke_ff7f23 + ) + + private fun comeBackButtonBackground(): Drawable? = ContextCompat.getDrawable( + this, + R.drawable.shape_rect_eeeeee_solid_radius_100_padding_7_11_11_8 + ) + private fun setConfirmDialog() { ConfirmDialog( getString(R.string.success_change_password), diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt index f290b421..2e1607fd 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt @@ -1,8 +1,13 @@ package com.jjbaksa.jjbaksa.ui.changepassword.viewmodel +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.jjbaksa.domain.base.RespResult import com.jjbaksa.domain.repository.UserRepository +import com.jjbaksa.jjbaksa.util.SingleLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -11,9 +16,41 @@ import javax.inject.Inject class ChangePasswordViewModel @Inject constructor( val repository: UserRepository ) : ViewModel() { + var isEnableButton = MutableLiveData(false) + + private val _currentPasswordState = SingleLiveEvent() + val currentPasswordState: SingleLiveEvent get() = _currentPasswordState + fun checkPassword(password: String) { viewModelScope.launch { - repository.checkPassword(password) + runCatching { + repository.checkPassword(password) + }.onSuccess { + when (it) { + is RespResult.Success -> { + _currentPasswordState.value = true + Log.d("로그", "checkPassword Success : ${it.data}") + } + + is RespResult.Error -> { + _currentPasswordState.value = false + Log.d("로그", "checkPassword Error message : ${it.errorType.errorMessage}") + Log.d("로그", "checkPassword Error code : ${it.errorType.code}") + } + } + }.onFailure { + + } + } + } + + fun setNewPassword(password: String) { + viewModelScope.launch { + repository.setNewPassword(password) } } + + fun setEnabledButton(enable: Boolean) { + isEnableButton.value = enable + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b1a66ec6..66929d82 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,6 +46,7 @@ 새 비밀번호 확인 새 비밀번호를 입력하세요. 새 비밀번호를 설정해 주세요. + 새 비밀번호가 일치하지 않습니다. 인증번호 보내기 인증 완료 이메일로 발송된\n인증번호를 입력해 주세요. From 1bc9aea29197472a4e621feb78eba54635323ac0 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Mon, 17 Jul 2023 00:46:10 +0900 Subject: [PATCH 02/20] #61 [add] set new password api --- .../jjbaksa/ui/changepassword/ChangePasswordActivity.kt | 3 +++ .../java/com/jjbaksa/data/repository/UserRepositoryImpl.kt | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt index b7e50c55..d611f9cf 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt @@ -41,6 +41,9 @@ class ChangePasswordActivity : BaseActivity() { binding.newPasswordEditText.editTextBackground = failButtonBackground() binding.checkNewPasswordEditText.editTextBackground = failButtonBackground() isFailedNewPassword = true + } else { + viewModel.setNewPassword(binding.newPasswordEditText.editTextText) + } } } viewModel.isEnableButton.observe(this) { diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index 5524bd79..24f3ee69 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -84,7 +84,6 @@ class UserRepositoryImpl @Inject constructor( "Bearer " + userLocalDataSource.getAccessToken(), password ) - Log.d("로그", "response : $response") return if (response.isSuccessful && response.code() == 200) { RespResult.Success(response.isSuccessful) } else { @@ -133,8 +132,9 @@ class UserRepositoryImpl @Inject constructor( override suspend fun setNewPassword(password: String): FormatResp { val item = PasswordAndNicknameReq(password, null) + val token = userLocalDataSource.getAuthPasswordToken().ifEmpty { userLocalDataSource.getAccessToken() } val response = userRemoteDataSource.setNewPassword( - "Bearer " + userLocalDataSource.getAuthPasswordToken(), + "Bearer $token", item ) return if (response.isSuccessful && response.code() == 200) { From 29677dc0a7e6bfe5880131ca80f121cb3ca544b6 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Mon, 17 Jul 2023 16:49:55 +0900 Subject: [PATCH 03/20] #61 [add] DTO user profile image --- .../changepassword/viewmodel/ChangePasswordViewModel.kt | 5 +---- .../java/com/jjbaksa/data/model/user/UserProfileResp.kt | 8 ++++++++ .../src/main/java/com/jjbaksa/data/model/user/UserResp.kt | 1 + .../com/jjbaksa/data/repository/UserRepositoryImpl.kt | 1 - .../java/com/jjbaksa/domain/repository/UserRepository.kt | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 data/src/main/java/com/jjbaksa/data/model/user/UserProfileResp.kt diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt index 2e1607fd..89a39c3d 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt @@ -1,7 +1,6 @@ package com.jjbaksa.jjbaksa.ui.changepassword.viewmodel import android.util.Log -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -38,9 +37,7 @@ class ChangePasswordViewModel @Inject constructor( Log.d("로그", "checkPassword Error code : ${it.errorType.code}") } } - }.onFailure { - - } + }.onFailure { } } } diff --git a/data/src/main/java/com/jjbaksa/data/model/user/UserProfileResp.kt b/data/src/main/java/com/jjbaksa/data/model/user/UserProfileResp.kt new file mode 100644 index 00000000..826c23a9 --- /dev/null +++ b/data/src/main/java/com/jjbaksa/data/model/user/UserProfileResp.kt @@ -0,0 +1,8 @@ +package com.jjbaksa.data.model.user + +data class UserProfileResp( + var id: Int, + var originalName: String, + var path: String, + var url: String +) diff --git a/data/src/main/java/com/jjbaksa/data/model/user/UserResp.kt b/data/src/main/java/com/jjbaksa/data/model/user/UserResp.kt index 28ef221e..10b87416 100644 --- a/data/src/main/java/com/jjbaksa/data/model/user/UserResp.kt +++ b/data/src/main/java/com/jjbaksa/data/model/user/UserResp.kt @@ -6,6 +6,7 @@ data class UserResp( var id: Long, var nickname: String, var oauthType: String, + var profileImage: UserProfileResp, var userCountResp: UserCountResp, var userType: String ) diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index 24f3ee69..939d1baf 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -1,6 +1,5 @@ package com.jjbaksa.data.repository -import android.util.Log import com.jjbaksa.data.SUCCESS import com.jjbaksa.data.datasource.local.UserLocalDataSource import com.jjbaksa.data.datasource.remote.UserRemoteDataSource diff --git a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt index f6354eab..ab3afde5 100644 --- a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt @@ -17,7 +17,7 @@ interface UserRepository { onResult: (LoginResult) -> Unit ) suspend fun checkAuthEmail(email: String): FormatResp - suspend fun checkPassword(password:String): RespResult + suspend fun checkPassword(password: String): RespResult suspend fun getPasswordVerificationCode(id: String, email: String): FormatResp suspend fun findAccount(email: String, code: String): FormatResp suspend fun findPassword(user: FindPasswordReq): FormatResp From 17c4a3556aff3a634277fde99f9e712ad4de1492 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Mon, 17 Jul 2023 17:10:58 +0900 Subject: [PATCH 04/20] #61 [add] current&new password api with token MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 비밀번호 확인&새 비밀번호 설정 api 추가 및 토큰 사용, 새 비밀번호 설정 성공 시 dialog 표시 --- .../changepassword/ChangePasswordActivity.kt | 15 ++++++++-- .../viewmodel/ChangePasswordViewModel.kt | 29 +++++-------------- .../data/repository/UserRepositoryImpl.kt | 6 ++-- .../domain/repository/UserRepository.kt | 2 +- 4 files changed, 25 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt index d611f9cf..e510adae 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt @@ -29,9 +29,10 @@ class ChangePasswordActivity : BaseActivity() { private fun observeData() { viewModel.currentPasswordState.observe(this) { - isFailedCurrentPassword = !it - if (!it) { + isFailedCurrentPassword = !it.isSuccess + if (isFailedCurrentPassword) { binding.currentPasswordEditText.editTextBackground = failButtonBackground() + showSnackBar(it.msg.toString(), getString(R.string.cancel)) } else { if (newPasswordText != checkPasswordText) { showSnackBar( @@ -46,6 +47,16 @@ class ChangePasswordActivity : BaseActivity() { } } } + viewModel.newPasswordState.observe(this) { + if (it.isSuccess) { + setConfirmDialog() + } else { + showSnackBar(it.msg.toString(), getString(R.string.cancel)) + binding.newPasswordEditText.editTextBackground = failButtonBackground() + binding.checkNewPasswordEditText.editTextBackground = failButtonBackground() + isFailedNewPassword = true + } + } viewModel.isEnableButton.observe(this) { binding.changePasswordButton.isEnabled = it binding.changePasswordButton.isSelected = it diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt index 89a39c3d..db157d71 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt @@ -1,11 +1,10 @@ package com.jjbaksa.jjbaksa.ui.changepassword.viewmodel -import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.jjbaksa.domain.base.RespResult import com.jjbaksa.domain.repository.UserRepository +import com.jjbaksa.domain.resp.user.FormatResp import com.jjbaksa.jjbaksa.util.SingleLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch @@ -17,33 +16,21 @@ class ChangePasswordViewModel @Inject constructor( ) : ViewModel() { var isEnableButton = MutableLiveData(false) - private val _currentPasswordState = SingleLiveEvent() - val currentPasswordState: SingleLiveEvent get() = _currentPasswordState + private val _currentPasswordState = SingleLiveEvent() + val currentPasswordState: SingleLiveEvent get() = _currentPasswordState + + private val _newPasswordState = SingleLiveEvent() + val newPasswordState: SingleLiveEvent get() = _newPasswordState fun checkPassword(password: String) { viewModelScope.launch { - runCatching { - repository.checkPassword(password) - }.onSuccess { - when (it) { - is RespResult.Success -> { - _currentPasswordState.value = true - Log.d("로그", "checkPassword Success : ${it.data}") - } - - is RespResult.Error -> { - _currentPasswordState.value = false - Log.d("로그", "checkPassword Error message : ${it.errorType.errorMessage}") - Log.d("로그", "checkPassword Error code : ${it.errorType.code}") - } - } - }.onFailure { } + _currentPasswordState.value = repository.checkPassword(password) } } fun setNewPassword(password: String) { viewModelScope.launch { - repository.setNewPassword(password) + _newPasswordState.value = repository.setNewPassword(password) } } diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index deb47e15..b808116b 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -78,17 +78,17 @@ class UserRepositoryImpl @Inject constructor( } } - override suspend fun checkPassword(password: String): RespResult { + override suspend fun checkPassword(password: String): FormatResp { val response = userRemoteDataSource.checkPassword( "Bearer " + userLocalDataSource.getAccessToken(), password ) return if (response.isSuccessful && response.code() == 200) { - RespResult.Success(response.isSuccessful) + FormatResp(response.isSuccessful, null, response.code()) } else { val errorBodyJson = response.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) - RespResult.Error(ErrorType(errorBody.errorMessage, errorBody.code)) + FormatResp(response.isSuccessful, errorBody.errorMessage, errorBody.code) } } diff --git a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt index 580cc607..d2a660b4 100644 --- a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt @@ -18,7 +18,7 @@ interface UserRepository { ) suspend fun checkAuthEmail(email: String): FormatResp - suspend fun checkPassword(password: String): RespResult + suspend fun checkPassword(password: String): FormatResp suspend fun getPasswordVerificationCode(id: String, email: String): FormatResp suspend fun findAccount(email: String, code: String): FormatResp suspend fun findPassword(user: FindPasswordReq): FormatResp From e6026f7d38dede95ac8e26252e0e71821995565b Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Wed, 19 Jul 2023 01:19:59 +0900 Subject: [PATCH 05/20] #61 [add] mypage profile ui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 마이페이지 프로필 UI 업데이트 --- .../jjbaksa/jjbaksa/ui/login/LoginActivity.kt | 2 +- .../jjbaksa/ui/login/LoginViewModel.kt | 19 +++------- .../ui/mainpage/mypage/NaviMyPageFragment.kt | 15 ++++++-- .../mypage/viewmodel/MyPageViewModel.kt | 19 ++++++++-- .../databinding/ImageDataBindingAdapter.kt | 22 +++++++++++ .../baseline_supervised_user_circle_24.xml | 5 +++ .../main/res/layout/fragment_navi_my_page.xml | 13 +++++-- app/src/main/res/values/strings.xml | 3 ++ .../jjbaksa/data/database/UserPreferences.kt | 4 ++ .../jjbaksa/data/datasource/UserDataSource.kt | 8 +++- .../datasource/local/UserLocalDataSource.kt | 38 ++++++++++++++++++- .../datasource/remote/UserRemoteDataSource.kt | 23 ++++++++++- .../data/repository/UserRepositoryImpl.kt | 21 ++++++++-- .../domain/repository/UserRepository.kt | 5 ++- 14 files changed, 165 insertions(+), 32 deletions(-) create mode 100644 app/src/main/java/com/jjbaksa/jjbaksa/util/databinding/ImageDataBindingAdapter.kt create mode 100644 app/src/main/res/drawable/baseline_supervised_user_circle_24.xml diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginActivity.kt index bc8f8cb9..9923ea2a 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginActivity.kt @@ -28,11 +28,11 @@ class LoginActivity : BaseActivity() { override fun subscribe() { with(viewModel) { - loginState.observe(this@LoginActivity) { if (it != null) { if (it.isSuccess) { goToMainActivity() + viewModel.loadUserMe() } else { if (it.erroMessage.isNotEmpty()) { showSnackBar(it.erroMessage, getString(R.string.cancel)) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginViewModel.kt index 71c92ffd..62ed1a66 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/login/LoginViewModel.kt @@ -22,9 +22,6 @@ class LoginViewModel @Inject constructor( private val _loginState = SingleLiveEvent() val loginState: SingleLiveEvent get() = _loginState - private val _autoLoginState = SingleLiveEvent() - val autoLoginState: SingleLiveEvent get() = _autoLoginState - fun login(isCheckedSwitch: Boolean) { if (!TextUtils.isEmpty(account.value) && !TextUtils.isEmpty(password.value)) { viewModelScope.launch(ceh) { @@ -35,15 +32,9 @@ class LoginViewModel @Inject constructor( } } -// fun getAutoLoginFlag() { -// viewModelScope.launch(ceh) { -// -// if (repository.getAutoLoginFlag()) { -// isAutoLogin.value = true -// account.value = repository.getAccount() -// password.value = repository.getPasswrod() -// login() -// } -// } -// } + fun loadUserMe() { + viewModelScope.launch { + repository.me() + } + } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt index 0729d09e..dc44c349 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt @@ -3,11 +3,13 @@ package com.jjbaksa.jjbaksa.ui.mainpage.mypage import android.content.Intent import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.jjbaksa.jjbaksa.R import com.jjbaksa.jjbaksa.base.BaseFragment import com.jjbaksa.jjbaksa.databinding.FragmentNaviMyPageBinding +import com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel.MyPageViewModel import com.jjbaksa.jjbaksa.ui.setting.SettingActivity import com.jjbaksa.jjbaksa.util.setExtendView import dagger.hilt.android.AndroidEntryPoint @@ -16,18 +18,24 @@ import dagger.hilt.android.AndroidEntryPoint class NaviMyPageFragment : BaseFragment() { override val layoutId: Int get() = R.layout.fragment_navi_my_page + private val viewModel: MyPageViewModel by activityViewModels() + private val reviewFragment by lazy { ReviewFragment() } private val bookmarkFragment by lazy { BookmarkFragment() } - private val settingResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { - // Handle SettingActivity result - } + private val settingResult = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + // Handle SettingActivity result + } override fun initView() { requireActivity().setExtendView(binding.myPageConstraintLayout) initFragment(reviewFragment) setTabLayout() + binding.vm = viewModel + viewModel.getUserProfile() } + private fun initFragment(fragment: Fragment) { parentFragmentManager.beginTransaction() .replace(R.id.fragment_container, fragment) @@ -42,6 +50,7 @@ class NaviMyPageFragment : BaseFragment() { 1 -> initFragment(bookmarkFragment) } } + override fun onTabUnselected(tab: TabLayout.Tab?) {} override fun onTabReselected(tab: TabLayout.Tab?) {} }) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt index 357e90e2..61696159 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt @@ -1,11 +1,24 @@ package com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.jjbaksa.domain.repository.HomeRepository +import com.jjbaksa.domain.repository.UserRepository import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject @HiltViewModel class MyPageViewModel @Inject constructor( - val repository: HomeRepository -) : ViewModel() + val repository: UserRepository +) : ViewModel() { + val account = MutableLiveData("") + val nickname = MutableLiveData("") + val profileFollowers = MutableLiveData(0) + val profileImage = MutableLiveData("") + + fun getUserProfile() { + account.value = repository.getAccount() + nickname.value = repository.getNickname() + profileFollowers.value = repository.getFollowers() + profileImage.value = repository.getProfileImage() + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/util/databinding/ImageDataBindingAdapter.kt b/app/src/main/java/com/jjbaksa/jjbaksa/util/databinding/ImageDataBindingAdapter.kt new file mode 100644 index 00000000..5222eaca --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/util/databinding/ImageDataBindingAdapter.kt @@ -0,0 +1,22 @@ +package com.jjbaksa.jjbaksa.util.databinding + +import android.widget.ImageView +import androidx.databinding.BindingAdapter +import coil.load +import coil.transform.CircleCropTransformation +import com.jjbaksa.jjbaksa.R + +@BindingAdapter("img") +fun ImageView.setImage(image: String?) { + if (image == null) { + return + } + + if (image.isEmpty()) { + load(R.drawable.baseline_supervised_user_circle_24) + } else { + load(image) { + transformations(CircleCropTransformation()) + } + } +} diff --git a/app/src/main/res/drawable/baseline_supervised_user_circle_24.xml b/app/src/main/res/drawable/baseline_supervised_user_circle_24.xml new file mode 100644 index 00000000..3ea888a6 --- /dev/null +++ b/app/src/main/res/drawable/baseline_supervised_user_circle_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/fragment_navi_my_page.xml b/app/src/main/res/layout/fragment_navi_my_page.xml index aa8bbed6..de71fecb 100644 --- a/app/src/main/res/layout/fragment_navi_my_page.xml +++ b/app/src/main/res/layout/fragment_navi_my_page.xml @@ -8,6 +8,9 @@ + @@ -34,6 +38,7 @@ android:textColor="@color/color_000000" android:textSize="16dp" android:textStyle="bold" + android:text="@{vm.nickname}" app:layout_constraintStart_toEndOf="@id/profile_image_view" app:layout_constraintTop_toTopOf="@id/profile_image_view" tools:text="이병건이올씨다" /> @@ -42,9 +47,10 @@ android:id="@+id/follower_text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginStart="13dp" android:textColor="@color/color_000000" + android:layout_marginStart="2dp" android:textSize="14dp" + android:text="@{@string/my_page_followers(vm.profileFollowers)}" app:layout_constraintBottom_toBottomOf="@id/profile_name_text_view" app:layout_constraintStart_toEndOf="@id/profile_name_text_view" app:layout_constraintTop_toTopOf="@id/profile_name_text_view" @@ -56,10 +62,11 @@ android:layout_height="wrap_content" android:layout_marginTop="2dp" android:textColor="@color/color_000000" + android:text="@{@string/my_page_account(vm.account)}" android:textSize="14dp" app:layout_constraintStart_toStartOf="@id/profile_name_text_view" app:layout_constraintTop_toBottomOf="@id/profile_name_text_view" - tools:text="\@dangerousman" /> + tools:text="\@dangerousman"/> 다녀온 음식점의 리뷰를 작성해 보세요! 등록된 북마크가 없어요. 새로운 음식점을 저장해 보세요! + + • 팔로우 %1$d + \@%s \ No newline at end of file diff --git a/data/src/main/java/com/jjbaksa/data/database/UserPreferences.kt b/data/src/main/java/com/jjbaksa/data/database/UserPreferences.kt index b6e7bde9..f044cba0 100644 --- a/data/src/main/java/com/jjbaksa/data/database/UserPreferences.kt +++ b/data/src/main/java/com/jjbaksa/data/database/UserPreferences.kt @@ -2,6 +2,7 @@ package com.jjbaksa.data.database import android.content.Context import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.intPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore @@ -12,6 +13,9 @@ object PreferenceKeys { val ACCESS_TOKEN = stringPreferencesKey("ACEESS_TOKEN") val REFRESH_TOKEN = stringPreferencesKey("REFRESH_TOKEN") val ACCOUNT = stringPreferencesKey("ACCOUNT") + val NICKNAME = stringPreferencesKey("NICKNAME") + val FOLLOWERS = intPreferencesKey("FOLLOWERS") + val IMAGE = stringPreferencesKey("IMAGE") val PASSWORD = stringPreferencesKey("PASSWORD") var AUTO_LOGIN = booleanPreferencesKey("AUTO_LOGIN") val AUTH_PASSWORD_TOKEN = stringPreferencesKey("AUTH_PASSWORD_TOKEN") diff --git a/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt index 8ffe1e9a..7ac70c19 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt @@ -22,12 +22,18 @@ interface UserDataSource { suspend fun setNewPassword(token: String, item: PasswordAndNicknameReq): Response suspend fun saveAccessToken(accessToken: String) suspend fun saveAccount(account: String) + suspend fun saveNickname(nickname: String) + suspend fun saveFollowers(followers: Int) + suspend fun saveProfileImage(image: String) suspend fun savePassword(password: String) suspend fun saveRefreshToken(refreshToken: String) suspend fun saveAutoLogin(isAutoLogin: Boolean) suspend fun saveAuthPasswordToken(passwordToken: String) fun getAutoLoginFlag(): Boolean - fun getAcount(): String + fun getAccount(): String + fun getNickname(): String + fun getFollowers(): Int + fun getProfileImage(): String fun getPassword(): String fun getAccessToken(): String fun getAuthPasswordToken(): String diff --git a/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt index 1442737c..ecb4f2f7 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt @@ -73,6 +73,24 @@ class UserLocalDataSource @Inject constructor( } } + override suspend fun saveNickname(nickname: String) { + dataStore.edit { + it[PreferenceKeys.NICKNAME] = nickname + } + } + + override suspend fun saveFollowers(followers: Int) { + dataStore.edit { + it[PreferenceKeys.FOLLOWERS] = followers + } + } + + override suspend fun saveProfileImage(image: String) { + dataStore.edit { + it[PreferenceKeys.IMAGE] = image + } + } + override suspend fun savePassword(password: String) { dataStore.edit { it[PreferenceKeys.PASSWORD] = password @@ -103,12 +121,30 @@ class UserLocalDataSource @Inject constructor( } } - override fun getAcount(): String { + override fun getAccount(): String { return runBlocking { dataStore.data.first()[PreferenceKeys.ACCOUNT] ?: "" } } + override fun getNickname(): String { + return runBlocking { + dataStore.data.first()[PreferenceKeys.NICKNAME] ?: "" + } + } + + override fun getFollowers(): Int { + return runBlocking { + dataStore.data.first()[PreferenceKeys.FOLLOWERS] ?: 0 + } + } + + override fun getProfileImage(): String { + return runBlocking { + dataStore.data.first()[PreferenceKeys.IMAGE] ?: "" + } + } + override fun getPassword(): String { return runBlocking { dataStore.data.first()[PreferenceKeys.PASSWORD] ?: "" diff --git a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt index 89eaa5a3..64a7ddc9 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt @@ -63,6 +63,15 @@ class UserRemoteDataSource @Inject constructor( override suspend fun saveAccount(account: String) { } + override suspend fun saveNickname(nickname: String) { + } + + override suspend fun saveFollowers(followers: Int) { + } + + override suspend fun saveProfileImage(image: String) { + } + override suspend fun savePassword(password: String) { } @@ -83,7 +92,19 @@ class UserRemoteDataSource @Inject constructor( return false } - override fun getAcount(): String { + override fun getAccount(): String { + return "" + } + + override fun getNickname(): String { + return "" + } + + override fun getFollowers(): Int { + return 0 + } + + override fun getProfileImage(): String { return "" } diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index b808116b..dbfa2bdb 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -42,7 +42,6 @@ class UserRepositoryImpl @Inject constructor( isAutoLogin: Boolean, onResult: (LoginResult) -> Unit ) { - val response = userRemoteDataSource.postLogin(LoginReq(account, password)) if (response != null) { @@ -147,8 +146,10 @@ class UserRepositoryImpl @Inject constructor( override suspend fun me(): RespResult { val response = userRemoteDataSource.me() - return if (response.isSuccessful) { + userLocalDataSource.saveNickname(response.body()?.nickname ?: "") + userLocalDataSource.saveFollowers(response.body()?.userCountResp?.friendCount ?: 0) + userLocalDataSource.saveProfileImage(response.body()?.profileImage?.path ?: "") RespResult.Success(response.isSuccessful) } else { val errorBodyJson = response.errorBody()!!.string() @@ -162,10 +163,22 @@ class UserRepositoryImpl @Inject constructor( } override fun getAccount(): String { - return userLocalDataSource.getAcount() + return userLocalDataSource.getAccount() + } + + override fun getNickname(): String { + return userLocalDataSource.getNickname() + } + + override fun getFollowers(): Int { + return userLocalDataSource.getFollowers() + } + + override fun getProfileImage(): String { + return userLocalDataSource.getProfileImage() } - override fun getPasswrod(): String { + override fun getPassword(): String { return userLocalDataSource.getPassword() } diff --git a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt index d2a660b4..636cbae9 100644 --- a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt @@ -26,6 +26,9 @@ interface UserRepository { suspend fun me(): RespResult fun getAutoLoginFlag(): Boolean fun getAccount(): String - fun getPasswrod(): String + fun getNickname(): String + fun getFollowers(): Int + fun getProfileImage(): String + fun getPassword(): String fun getAccessToken(): String } From 71116b919e48f2cda00bf98f89087b5599831f74 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Wed, 19 Jul 2023 02:57:40 +0900 Subject: [PATCH 06/20] #61 [add] profile bottomsheetdialog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 프로필 이미지 클릭 시 bottomSheetDialog 띄우기 --- .../jjbaksa/jjbaksa/dialog/MyPageDialog.kt | 50 +++++++ .../ui/mainpage/mypage/NaviMyPageFragment.kt | 16 ++- .../mypage/viewmodel/MyPageViewModel.kt | 6 + .../res/drawable/bg_bottom_sheet_dialog.xml | 8 ++ .../shape_circ_d9d9d9_stroke_ffffff.xml | 11 ++ app/src/main/res/layout/dialog_mypage.xml | 135 ++++++++++++++++++ app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 2 + app/src/main/res/values/themes.xml | 8 ++ .../data/repository/UserRepositoryImpl.kt | 2 +- 10 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt create mode 100644 app/src/main/res/drawable/bg_bottom_sheet_dialog.xml create mode 100644 app/src/main/res/drawable/shape_circ_d9d9d9_stroke_ffffff.xml create mode 100644 app/src/main/res/layout/dialog_mypage.xml diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt new file mode 100644 index 00000000..7dce82f1 --- /dev/null +++ b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt @@ -0,0 +1,50 @@ +package com.jjbaksa.jjbaksa.dialog + +import android.view.View +import androidx.core.widget.addTextChangedListener +import androidx.fragment.app.activityViewModels +import com.jjbaksa.jjbaksa.R +import com.jjbaksa.jjbaksa.base.BaseBottomSheetDialogFragment +import com.jjbaksa.jjbaksa.databinding.DialogMypageBinding +import com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel.MyPageViewModel +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class MyPageDialog : BaseBottomSheetDialogFragment() { + override val layoutResId: Int + get() = R.layout.dialog_mypage + private val viewModel: MyPageViewModel by activityViewModels() + + override fun initView(view: View) { + binding.vm = viewModel + viewModel.getUserProfile() + } + + override fun initEvent() { + loadProfileImage() + setTextLength() + observeData() + } + + private fun loadProfileImage() { + binding.addProfileImage.setOnClickListener { } + } + + private fun setTextLength() { + binding.profileNicknameEditText.addTextChangedListener { + viewModel.setTextLength(it?.length.toString()) + } + } + + private fun observeData() { + viewModel.textLength.observe(viewLifecycleOwner) { + binding.textLengthCountTextView.text = getString(R.string.text_length, it) + } + } + + override fun subscribe() { + } + + override fun initData() { + } +} diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt index dc44c349..6420900e 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/NaviMyPageFragment.kt @@ -9,6 +9,7 @@ import com.google.android.material.tabs.TabLayout.OnTabSelectedListener import com.jjbaksa.jjbaksa.R import com.jjbaksa.jjbaksa.base.BaseFragment import com.jjbaksa.jjbaksa.databinding.FragmentNaviMyPageBinding +import com.jjbaksa.jjbaksa.dialog.MyPageDialog import com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel.MyPageViewModel import com.jjbaksa.jjbaksa.ui.setting.SettingActivity import com.jjbaksa.jjbaksa.util.setExtendView @@ -57,10 +58,17 @@ class NaviMyPageFragment : BaseFragment() { } override fun initEvent() { - setSettingActivity() + onClickSettingImage() + onClickProfileImage() } - private fun setSettingActivity() { + private fun onClickProfileImage() { + binding.profileImageView.setOnClickListener { + MyPageDialog().show(parentFragmentManager, MY_PAGE_DIALOG_TAG) + } + } + + private fun onClickSettingImage() { binding.settingImageButton.setOnClickListener { settingResult.launch(Intent(requireContext(), SettingActivity::class.java)) } @@ -68,4 +76,8 @@ class NaviMyPageFragment : BaseFragment() { override fun subscribe() { } + + companion object { + const val MY_PAGE_DIALOG_TAG = "MY_PAGE_DIALOG_TAG" + } } diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt index 61696159..904ce08a 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt @@ -14,11 +14,17 @@ class MyPageViewModel @Inject constructor( val nickname = MutableLiveData("") val profileFollowers = MutableLiveData(0) val profileImage = MutableLiveData("") + val textLength = MutableLiveData("") fun getUserProfile() { account.value = repository.getAccount() nickname.value = repository.getNickname() profileFollowers.value = repository.getFollowers() profileImage.value = repository.getProfileImage() + textLength.value = repository.getNickname().length.toString() + } + + fun setTextLength(length: String) { + textLength.value = length } } diff --git a/app/src/main/res/drawable/bg_bottom_sheet_dialog.xml b/app/src/main/res/drawable/bg_bottom_sheet_dialog.xml new file mode 100644 index 00000000..010d9525 --- /dev/null +++ b/app/src/main/res/drawable/bg_bottom_sheet_dialog.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/shape_circ_d9d9d9_stroke_ffffff.xml b/app/src/main/res/drawable/shape_circ_d9d9d9_stroke_ffffff.xml new file mode 100644 index 00000000..70851a1c --- /dev/null +++ b/app/src/main/res/drawable/shape_circ_d9d9d9_stroke_ffffff.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_mypage.xml b/app/src/main/res/layout/dialog_mypage.xml new file mode 100644 index 00000000..c810718a --- /dev/null +++ b/app/src/main/res/layout/dialog_mypage.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 6eeaaedb..9793b11f 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -14,6 +14,7 @@ #CCFFFFFF #E6FFFFFF #fbfbfa + #d9d9d9 #595959 #666666 #989898 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2025d968..3abbfa0f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -116,4 +116,6 @@ • 팔로우 %1$d \@%s + %s/10 + %s님,\n프로필을 변경하시겠어요? \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 5efad671..ec9f1cca 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -14,6 +14,10 @@ true + + \ No newline at end of file diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index dbfa2bdb..1f780f72 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -83,7 +83,7 @@ class UserRepositoryImpl @Inject constructor( password ) return if (response.isSuccessful && response.code() == 200) { - FormatResp(response.isSuccessful, null, response.code()) + FormatResp(response.isSuccessful, "", response.code()) } else { val errorBodyJson = response.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) From b7205f29b8c438a1aeeac3a61572b3ac00862316 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Wed, 19 Jul 2023 22:08:27 +0900 Subject: [PATCH 07/20] #61 build check --- .../ui/changepassword/ChangePasswordActivity.kt | 6 +++--- .../viewmodel/ChangePasswordViewModel.kt | 16 ++++++++-------- .../data/repository/UserRepositoryImpl.kt | 8 ++++---- .../com/jjbaksa/domain/resp/user/FormatResp.kt | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt index e510adae..3515c0f9 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/ChangePasswordActivity.kt @@ -29,10 +29,10 @@ class ChangePasswordActivity : BaseActivity() { private fun observeData() { viewModel.currentPasswordState.observe(this) { - isFailedCurrentPassword = !it.isSuccess + isFailedCurrentPassword = !it?.isSuccess!! if (isFailedCurrentPassword) { binding.currentPasswordEditText.editTextBackground = failButtonBackground() - showSnackBar(it.msg.toString(), getString(R.string.cancel)) + showSnackBar(it?.msg.toString(), getString(R.string.cancel)) } else { if (newPasswordText != checkPasswordText) { showSnackBar( @@ -48,7 +48,7 @@ class ChangePasswordActivity : BaseActivity() { } } viewModel.newPasswordState.observe(this) { - if (it.isSuccess) { + if (it?.isSuccess!!) { setConfirmDialog() } else { showSnackBar(it.msg.toString(), getString(R.string.cancel)) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt index db157d71..a926b755 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/changepassword/viewmodel/ChangePasswordViewModel.kt @@ -1,10 +1,10 @@ package com.jjbaksa.jjbaksa.ui.changepassword.viewmodel import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.jjbaksa.domain.repository.UserRepository import com.jjbaksa.domain.resp.user.FormatResp +import com.jjbaksa.jjbaksa.base.BaseViewModel import com.jjbaksa.jjbaksa.util.SingleLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch @@ -13,23 +13,23 @@ import javax.inject.Inject @HiltViewModel class ChangePasswordViewModel @Inject constructor( val repository: UserRepository -) : ViewModel() { +) : BaseViewModel() { var isEnableButton = MutableLiveData(false) - private val _currentPasswordState = SingleLiveEvent() - val currentPasswordState: SingleLiveEvent get() = _currentPasswordState + private val _currentPasswordState = SingleLiveEvent() + val currentPasswordState: SingleLiveEvent get() = _currentPasswordState - private val _newPasswordState = SingleLiveEvent() - val newPasswordState: SingleLiveEvent get() = _newPasswordState + private val _newPasswordState = SingleLiveEvent() + val newPasswordState: SingleLiveEvent get() = _newPasswordState fun checkPassword(password: String) { - viewModelScope.launch { + viewModelScope.launch(ceh) { _currentPasswordState.value = repository.checkPassword(password) } } fun setNewPassword(password: String) { - viewModelScope.launch { + viewModelScope.launch(ceh) { _newPasswordState.value = repository.setNewPassword(password) } } diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index 1f780f72..29579b1f 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -69,7 +69,7 @@ class UserRepositoryImpl @Inject constructor( override suspend fun checkAuthEmail(email: String): FormatResp { val result = userRemoteDataSource.checkAuthEmail(email) return if (result.isSuccessful) { - FormatResp(result.isSuccessful, null, result.code()) + FormatResp(result.isSuccessful, "", result.code()) } else { val errorBodyJson = result.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) @@ -97,7 +97,7 @@ class UserRepositoryImpl @Inject constructor( ): FormatResp { val response = userRemoteDataSource.getPasswordVerificationCode(id, email) return if (response.isSuccessful && response.code() == 200) { - FormatResp(response.isSuccessful, null, response.code()) + FormatResp(response.isSuccessful, "", response.code()) } else { val errorBodyJson = response.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) @@ -120,7 +120,7 @@ class UserRepositoryImpl @Inject constructor( val response = userRemoteDataSource.findPassword(user) return if (response.isSuccessful && response.code() == 200) { userLocalDataSource.saveAuthPasswordToken(response.body().toString()) - FormatResp(response.isSuccessful, null, response.code()) + FormatResp(response.isSuccessful, "", response.code()) } else { val errorBodyJson = response.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) @@ -136,7 +136,7 @@ class UserRepositoryImpl @Inject constructor( item ) return if (response.isSuccessful && response.code() == 200) { - FormatResp(response.isSuccessful, null, response.code()) + FormatResp(response.isSuccessful, "", response.code()) } else { val errorBodyJson = response.errorBody()!!.string() val errorBody = RespMapper.errorMapper(errorBodyJson) diff --git a/domain/src/main/java/com/jjbaksa/domain/resp/user/FormatResp.kt b/domain/src/main/java/com/jjbaksa/domain/resp/user/FormatResp.kt index c1c11a39..d2a5dedd 100644 --- a/domain/src/main/java/com/jjbaksa/domain/resp/user/FormatResp.kt +++ b/domain/src/main/java/com/jjbaksa/domain/resp/user/FormatResp.kt @@ -2,6 +2,6 @@ package com.jjbaksa.domain.resp.user data class FormatResp( val isSuccess: Boolean, - val msg: String?, + val msg: String, val code: Int ) From 5847decc0a98f310f1cf235fe79eac77d527365e Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Thu, 20 Jul 2023 14:00:19 +0900 Subject: [PATCH 08/20] #61 [add] use saf to load profile image --- .../jjbaksa/jjbaksa/dialog/MyPageDialog.kt | 33 ++++++++++++++++++- .../mypage/viewmodel/MyPageViewModel.kt | 4 +++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt index 7dce82f1..4c45a028 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt @@ -1,6 +1,7 @@ package com.jjbaksa.jjbaksa.dialog import android.view.View +import androidx.activity.result.contract.ActivityResultContracts import androidx.core.widget.addTextChangedListener import androidx.fragment.app.activityViewModels import com.jjbaksa.jjbaksa.R @@ -8,12 +9,22 @@ import com.jjbaksa.jjbaksa.base.BaseBottomSheetDialogFragment import com.jjbaksa.jjbaksa.databinding.DialogMypageBinding import com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel.MyPageViewModel import dagger.hilt.android.AndroidEntryPoint +import coil.load +import coil.transform.CircleCropTransformation @AndroidEntryPoint class MyPageDialog : BaseBottomSheetDialogFragment() { override val layoutResId: Int get() = R.layout.dialog_mypage private val viewModel: MyPageViewModel by activityViewModels() + private val loadImageUri = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> + if (uri == null) { + return@registerForActivityResult + } else { + viewModel.setProfileImage(uri.toString()) + } + } + override fun initView(view: View) { binding.vm = viewModel @@ -21,13 +32,28 @@ class MyPageDialog : BaseBottomSheetDialogFragment() { } override fun initEvent() { + confirmProfile() + cancelProfile() loadProfileImage() setTextLength() observeData() } + private fun confirmProfile() { + binding.confirmButton.setOnClickListener { + } + } + + private fun cancelProfile() { + binding.cancelButton.setOnClickListener { + dismiss() + } + } + private fun loadProfileImage() { - binding.addProfileImage.setOnClickListener { } + binding.addProfileImage.setOnClickListener { + loadImageUri.launch("image/*") + } } private fun setTextLength() { @@ -40,6 +66,11 @@ class MyPageDialog : BaseBottomSheetDialogFragment() { viewModel.textLength.observe(viewLifecycleOwner) { binding.textLengthCountTextView.text = getString(R.string.text_length, it) } + viewModel.profileImage.observe(viewLifecycleOwner) { + binding.profileImageView.load(it) { + transformations(CircleCropTransformation()) + } + } } override fun subscribe() { diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt index 904ce08a..f9da7536 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt @@ -27,4 +27,8 @@ class MyPageViewModel @Inject constructor( fun setTextLength(length: String) { textLength.value = length } + + fun setProfileImage(image: String) { + profileImage.value = image + } } From eda724fe28a497505839cc1c6a4dd7269f587ed8 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Thu, 20 Jul 2023 14:40:21 +0900 Subject: [PATCH 09/20] #61 [add] bottomsheetdialog resize --- .../{MyPageDialog.kt => MyPageBottomSheetDialog.kt} | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) rename app/src/main/java/com/jjbaksa/jjbaksa/dialog/{MyPageDialog.kt => MyPageBottomSheetDialog.kt} (80%) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt similarity index 80% rename from app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt rename to app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt index 4c45a028..000ee810 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageDialog.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt @@ -13,7 +13,7 @@ import coil.load import coil.transform.CircleCropTransformation @AndroidEntryPoint -class MyPageDialog : BaseBottomSheetDialogFragment() { +class MyPageBottomSheetDialog : BaseBottomSheetDialogFragment() { override val layoutResId: Int get() = R.layout.dialog_mypage private val viewModel: MyPageViewModel by activityViewModels() @@ -25,10 +25,11 @@ class MyPageDialog : BaseBottomSheetDialogFragment() { } } - override fun initView(view: View) { binding.vm = viewModel viewModel.getUserProfile() + this.heightPercent = 0.55f + this.setLayoutMaxHeight(view) } override fun initEvent() { @@ -41,6 +42,14 @@ class MyPageDialog : BaseBottomSheetDialogFragment() { private fun confirmProfile() { binding.confirmButton.setOnClickListener { + if (viewModel.profileImage.value.isNullOrEmpty() || viewModel.textLength.value == "0") { + // todo:: empty profile image or nickname + } else { + viewModel.setProfileImageAndNickname( + viewModel.profileImage.value.toString(), + binding.profileNicknameEditText.text.toString() + ) + } } } From 15ef0bd78d89b1c1515c4c67891e70bf2634955c Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Thu, 20 Jul 2023 14:44:32 +0900 Subject: [PATCH 10/20] #61 [add] use multi part --- data/src/main/java/com/jjbaksa/data/api/AuthApi.kt | 5 +++++ .../jjbaksa/data/datasource/remote/UserRemoteDataSource.kt | 3 +++ .../java/com/jjbaksa/data/repository/UserRepositoryImpl.kt | 7 +++++++ .../java/com/jjbaksa/domain/repository/UserRepository.kt | 1 + 4 files changed, 16 insertions(+) diff --git a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt index cd9d5eb9..109dec17 100644 --- a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt +++ b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt @@ -7,4 +7,9 @@ import retrofit2.Response interface AuthApi { @GET("user/me") suspend fun userMe(): Response + @Multipart + @PATCH("user/profile") + suspend fun editUserProfileImage( + @Part profile: MultipartBody.Part + ): Response } diff --git a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt index 64a7ddc9..90caedef 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt @@ -87,6 +87,9 @@ class UserRemoteDataSource @Inject constructor( suspend fun me(): Response { return authApi.userMe() } + suspend fun editUserProfileImage(profile: MultipartBody.Part): Response { + return authApi.editUserProfileImage(profile) + } override fun getAutoLoginFlag(): Boolean { return false diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index 29579b1f..c3a5c02f 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -158,6 +158,13 @@ class UserRepositoryImpl @Inject constructor( } } + override suspend fun editUserProfileImage(profile: String): RespResult { + val fileBody = profile.toRequestBody("image/*".toMediaTypeOrNull()) + val profilePart = MultipartBody.Part.createFormData("profile", profile, fileBody) + val response = userRemoteDataSource.editUserProfileImage(profilePart) + return RespResult.Success(true) + } + override fun getAutoLoginFlag(): Boolean { return userLocalDataSource.getAutoLoginFlag() } diff --git a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt index 636cbae9..1ae0801f 100644 --- a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt @@ -24,6 +24,7 @@ interface UserRepository { suspend fun findPassword(user: FindPasswordReq): FormatResp suspend fun setNewPassword(password: String): FormatResp suspend fun me(): RespResult + suspend fun editUserProfileImage(photo: String): RespResult fun getAutoLoginFlag(): Boolean fun getAccount(): String fun getNickname(): String From 5aa99c41e9dd5e5fdd6c67d8e9be27e00f14c457 Mon Sep 17 00:00:00 2001 From: wnehdals Date: Thu, 20 Jul 2023 16:30:01 +0900 Subject: [PATCH 11/20] #61 [mod] modify file upload --- .idea/compiler.xml | 8 +- .idea/misc.xml | 3 +- app/build.gradle.kts | 6 +- app/src/main/AndroidManifest.xml | 3 +- .../jjbaksa/dialog/MyPageBottomSheetDialog.kt | 55 ++++++++- .../ui/mainpage/mypage/NaviMyPageFragment.kt | 10 +- .../mypage/viewmodel/MyPageViewModel.kt | 14 ++- data/build.gradle.kts | 6 +- .../main/java/com/jjbaksa/data/api/AuthApi.kt | 6 +- .../datasource/remote/UserRemoteDataSource.kt | 1 + .../com/jjbaksa/data/mapper/FormDataUtil.kt | 106 ++++++++++++++++++ .../data/repository/UserRepositoryImpl.kt | 17 ++- domain/build.gradle.kts | 4 +- 13 files changed, 202 insertions(+), 37 deletions(-) create mode 100644 data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 3bcb6b3b..c107dbd7 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,7 @@ - + @@ -9,12 +9,6 @@ - - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 17e911dc..618ec4cf 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,3 +1,4 @@ + - + diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5f4bd501..4dc87e17 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -10,8 +10,8 @@ plugins { } android { - compileSdk = Constants.compileSdk + compileSdk = 32 defaultConfig { applicationId = Constants.packageName minSdk = Constants.minSdk @@ -40,8 +40,8 @@ android { } compileOptions { - sourceCompatibility = Versions.javaVersion - targetCompatibility = Versions.javaVersion + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0394a578..acdd4cfb 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -6,8 +6,7 @@ + android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt index 000ee810..e831d425 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt @@ -1,5 +1,9 @@ package com.jjbaksa.jjbaksa.dialog +import android.Manifest +import android.app.Activity +import android.content.Intent +import android.util.Log import android.view.View import androidx.activity.result.contract.ActivityResultContracts import androidx.core.widget.addTextChangedListener @@ -11,17 +15,43 @@ import com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel.MyPageViewModel import dagger.hilt.android.AndroidEntryPoint import coil.load import coil.transform.CircleCropTransformation +import com.example.imageselector.gallery.GalleryActivity +import com.jjbaksa.jjbaksa.util.checkPermissionsAndRequest +import com.jjbaksa.jjbaksa.util.hasPermission @AndroidEntryPoint class MyPageBottomSheetDialog : BaseBottomSheetDialogFragment() { override val layoutResId: Int get() = R.layout.dialog_mypage private val viewModel: MyPageViewModel by activityViewModels() - private val loadImageUri = registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> - if (uri == null) { - return@registerForActivityResult + private val loadImageUri = + registerForActivityResult(ActivityResultContracts.GetContent()) { uri -> + if (uri == null) { + return@registerForActivityResult + } else { + viewModel.setProfileImage(uri.toString()) + } + } + val permissions = arrayOf( + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + private val galleryActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { + if (it.resultCode == Activity.RESULT_OK) { + val images = it.data!!.getStringArrayListExtra("images")!! + viewModel.setProfileImage(images[0]) + } + } + private val requestPermissions = registerForActivityResult( + ActivityResultContracts.RequestPermission() + ) { + Log.e("jdm_tag", it.toString()) + if (it) { + val intent = Intent(requireContext(), GalleryActivity::class.java) + intent.putExtra("limit", 1) + galleryActivityLauncher.launch(intent) + //loadImageUri.launch("image/*") } else { - viewModel.setProfileImage(uri.toString()) + Log.e("jdm_tag", "else") } } @@ -43,12 +73,19 @@ class MyPageBottomSheetDialog : BaseBottomSheetDialogFragment() { override fun initEvent() { onClickSettingImage() - onClickProfileImage() - } - - private fun onClickProfileImage() { binding.profileImageView.setOnClickListener { - MyPageDialog().show(parentFragmentManager, MY_PAGE_DIALOG_TAG) + MyPageBottomSheetDialog().show(parentFragmentManager, MY_PAGE_DIALOG_TAG) } } + + private fun onClickSettingImage() { binding.settingImageButton.setOnClickListener { settingResult.launch(Intent(requireContext(), SettingActivity::class.java)) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt index f9da7536..9885b09e 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt @@ -1,21 +1,25 @@ package com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel +import android.net.Uri +import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.jjbaksa.domain.repository.UserRepository +import com.jjbaksa.jjbaksa.base.BaseViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class MyPageViewModel @Inject constructor( val repository: UserRepository -) : ViewModel() { +) : BaseViewModel() { val account = MutableLiveData("") val nickname = MutableLiveData("") val profileFollowers = MutableLiveData(0) val profileImage = MutableLiveData("") val textLength = MutableLiveData("") - fun getUserProfile() { account.value = repository.getAccount() nickname.value = repository.getNickname() @@ -31,4 +35,10 @@ class MyPageViewModel @Inject constructor( fun setProfileImage(image: String) { profileImage.value = image } + fun uploadProfileImg() { + viewModelScope.launch(ceh) { + var result = repository.editUserProfileImage(profileImage.value!!) + Log.e("tag", result.toString()) + } + } } diff --git a/data/build.gradle.kts b/data/build.gradle.kts index 14d0b4d4..d50e954d 100644 --- a/data/build.gradle.kts +++ b/data/build.gradle.kts @@ -7,8 +7,8 @@ plugins { } android { - compileSdk = Constants.compileSdk + compileSdk = 32 defaultConfig { minSdk = Constants.minSdk targetSdk = Constants.targetSdk @@ -18,8 +18,8 @@ android { } compileOptions { - sourceCompatibility = Versions.javaVersion - targetCompatibility = Versions.javaVersion + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } kotlinOptions { jvmTarget = Versions.jvmVersion diff --git a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt index 109dec17..a80d7394 100644 --- a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt +++ b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt @@ -2,7 +2,11 @@ package com.jjbaksa.data.api import retrofit2.http.GET import com.jjbaksa.data.model.user.UserResp +import okhttp3.MultipartBody import retrofit2.Response +import retrofit2.http.Multipart +import retrofit2.http.PATCH +import retrofit2.http.Part interface AuthApi { @GET("user/me") @@ -10,6 +14,6 @@ interface AuthApi { @Multipart @PATCH("user/profile") suspend fun editUserProfileImage( - @Part profile: MultipartBody.Part + @Part profile: MultipartBody.Part ): Response } diff --git a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt index 90caedef..823c3923 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt @@ -11,6 +11,7 @@ import com.jjbaksa.domain.resp.user.LoginReq import com.jjbaksa.domain.resp.user.PasswordAndNicknameReq import com.jjbaksa.domain.resp.user.SignUpReq import com.jjbaksa.domain.resp.user.SignUpResp +import okhttp3.MultipartBody import retrofit2.Response import javax.inject.Inject diff --git a/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt b/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt new file mode 100644 index 00000000..d4530c9e --- /dev/null +++ b/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt @@ -0,0 +1,106 @@ +package com.jjbaksa.data.mapper + +import android.annotation.SuppressLint +import android.content.ContentResolver +import android.content.Context +import android.database.Cursor +import android.net.Uri +import android.provider.MediaStore +import android.provider.OpenableColumns +import android.util.Log +import androidx.core.net.toFile +import okhttp3.MediaType +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.MultipartBody +import okhttp3.RequestBody +import okhttp3.RequestBody.Companion.asRequestBody +import okio.BufferedSink +import okio.source +import java.io.File +import java.net.URLConnection +import kotlin.math.abs + + +object FormDataUtil { + val secUnit = 60L + val milliSec = 1000L + + fun getBody(key: String, value: Any): MultipartBody.Part { + return MultipartBody.Part.createFormData(key, value.toString()) + } + + fun getImageBody(key:String, uri: Uri): MultipartBody.Part{ + try{ + return getImageBody(key,File(uri.path)) + }catch (e: Exception){ + Log.e("jdm_Tag", e.message.toString()) + throw e + } + } + + + fun getImageBody(key: String, file: File): MultipartBody.Part { + return MultipartBody.Part.createFormData( + name = key, + filename = file.name, + body = file.asRequestBody(URLConnection.guessContentTypeFromName(file.name).toMediaType()) + ) + } + + fun getVideoBody(key: String, file: File): MultipartBody.Part { + return MultipartBody.Part.createFormData( + name = key, + filename = file.name, + body = file.asRequestBody("video/*".toMediaType()) + ) + } + + @SuppressLint("Range") + fun Uri.asMultipart(key: String = "multipartFile", contentResolver: ContentResolver): MultipartBody.Part? { + return contentResolver.query(this, null, null, null, null)?.let { + it.use { cursor -> + if(cursor.moveToNext()){ + val displayName = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + val requestBody = object : RequestBody() { + override fun contentType(): MediaType? { + return contentResolver.getType(this@asMultipart)?.toMediaType() + } + + override fun writeTo(sink: BufferedSink) { + sink.writeAll(contentResolver.openInputStream(this@asMultipart)?.source()!!) + } + } + MultipartBody.Part.createFormData(key, displayName, requestBody) + }else { + null + } + } + } + } + fun secondToStringHHMMWithUnit(timeS: Long, hourText:String, minuteText:String): String{ + val timeArr = stringArrForTimeHHMMSS(timeS,false) + val bNegative = timeS < 0 + val sb = StringBuilder() + if(bNegative){ + sb.append("-") + } + + if(timeArr[0] > 0){ + sb.append(String.format("%d$hourText ",timeArr[0])) + } + sb.append(String.format("%d$minuteText", timeArr[1])) + return sb.toString() + } + fun stringArrForTimeHHMMSS(time: Long, isMillis : Boolean): List{ + val absTimeMs = abs(time) + val totalSeconds = if (isMillis) { + absTimeMs / milliSec + } else { + absTimeMs + } + val seconds = totalSeconds % secUnit + val minutes = totalSeconds / secUnit % secUnit + val hours = totalSeconds / (secUnit * secUnit) + return listOf(hours,minutes,seconds) + } +} \ No newline at end of file diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index c3a5c02f..bfdfc823 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -1,8 +1,10 @@ package com.jjbaksa.data.repository +import android.net.Uri import com.jjbaksa.data.SUCCESS import com.jjbaksa.data.datasource.local.UserLocalDataSource import com.jjbaksa.data.datasource.remote.UserRemoteDataSource +import com.jjbaksa.data.mapper.FormDataUtil import com.jjbaksa.data.mapper.RespMapper import com.jjbaksa.domain.base.ErrorType import com.jjbaksa.domain.base.RespResult @@ -14,6 +16,9 @@ import com.jjbaksa.domain.resp.user.SignUpReq import com.jjbaksa.domain.resp.user.SignUpResp import com.jjbaksa.domain.resp.user.FindPasswordReq import com.jjbaksa.domain.resp.user.PasswordAndNicknameReq +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.toRequestBody import javax.inject.Inject class UserRepositoryImpl @Inject constructor( @@ -159,10 +164,14 @@ class UserRepositoryImpl @Inject constructor( } override suspend fun editUserProfileImage(profile: String): RespResult { - val fileBody = profile.toRequestBody("image/*".toMediaTypeOrNull()) - val profilePart = MultipartBody.Part.createFormData("profile", profile, fileBody) - val response = userRemoteDataSource.editUserProfileImage(profilePart) - return RespResult.Success(true) + val fileBody = FormDataUtil.getImageBody("multipartFile", Uri.parse(profile)) + val response = userRemoteDataSource.editUserProfileImage(fileBody) + if (response.isSuccessful) { + return RespResult.Success(true) + } else { + return RespResult.Success(false) + } + } override fun getAutoLoginFlag(): Boolean { diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index f06e158b..8e3ea767 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -5,8 +5,8 @@ plugins { } java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } dependencies { From 2620a87fbc3f2e851fbd7b25e283972f65c40ee0 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Thu, 20 Jul 2023 23:44:28 +0900 Subject: [PATCH 12/20] #61 [mod] upload profile image --- .idea/compiler.xml | 8 ++- .idea/misc.xml | 3 +- .../jjbaksa/dialog/MyPageBottomSheetDialog.kt | 41 ++++----------- .../ui/mainpage/mypage/NaviMyPageFragment.kt | 23 ++++++++- .../mypage/viewmodel/MyPageViewModel.kt | 31 ++++++++--- .../main/java/com/jjbaksa/data/api/AuthApi.kt | 2 + .../com/jjbaksa/data/mapper/FormDataUtil.kt | 51 ++++++++++--------- .../data/repository/UserRepositoryImpl.kt | 17 +++++-- 8 files changed, 104 insertions(+), 72 deletions(-) diff --git a/.idea/compiler.xml b/.idea/compiler.xml index c107dbd7..fc8e4964 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,7 +1,7 @@ - + @@ -9,6 +9,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 618ec4cf..1d2c5ec2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,3 @@ - - + diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt index e831d425..de89b7f8 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/dialog/MyPageBottomSheetDialog.kt @@ -3,7 +3,6 @@ package com.jjbaksa.jjbaksa.dialog import android.Manifest import android.app.Activity import android.content.Intent -import android.util.Log import android.view.View import androidx.activity.result.contract.ActivityResultContracts import androidx.core.widget.addTextChangedListener @@ -16,7 +15,6 @@ import dagger.hilt.android.AndroidEntryPoint import coil.load import coil.transform.CircleCropTransformation import com.example.imageselector.gallery.GalleryActivity -import com.jjbaksa.jjbaksa.util.checkPermissionsAndRequest import com.jjbaksa.jjbaksa.util.hasPermission @AndroidEntryPoint @@ -24,34 +22,24 @@ class MyPageBottomSheetDialog : BaseBottomSheetDialogFragment - if (uri == null) { - return@registerForActivityResult - } else { - viewModel.setProfileImage(uri.toString()) - } - } - val permissions = arrayOf( - Manifest.permission.WRITE_EXTERNAL_STORAGE - ) + private val galleryActivityLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { if (it.resultCode == Activity.RESULT_OK) { val images = it.data!!.getStringArrayListExtra("images")!! - viewModel.setProfileImage(images[0]) + viewModel.setLoadImage(images[0]) + binding.profileImageView.load(images[0]) { + transformations(CircleCropTransformation()) + } } } private val requestPermissions = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { - Log.e("jdm_tag", it.toString()) if (it) { val intent = Intent(requireContext(), GalleryActivity::class.java) intent.putExtra("limit", 1) galleryActivityLauncher.launch(intent) - //loadImageUri.launch("image/*") } else { - Log.e("jdm_tag", "else") } } @@ -72,20 +60,13 @@ class MyPageBottomSheetDialog : BaseBottomSheetDialogFragment() { initFragment(reviewFragment) setTabLayout() binding.vm = viewModel + binding.lifecycleOwner = this viewModel.getUserProfile() + observeData() + } + + private fun observeData() { + viewModel.nickname.observe(viewLifecycleOwner) { + binding.profileNameTextView.text = it + } + viewModel.profileImage.observe(viewLifecycleOwner) { + if (it.isEmpty()) { + binding.profileImageView.load(R.drawable.baseline_supervised_user_circle_24) { + transformations(CircleCropTransformation()) + } + } else { + binding.profileImageView.load(it) { + transformations(CircleCropTransformation()) + } + } + } } private fun initFragment(fragment: Fragment) { @@ -64,8 +85,6 @@ class NaviMyPageFragment : BaseFragment() { } } - - private fun onClickSettingImage() { binding.settingImageButton.setOnClickListener { settingResult.launch(Intent(requireContext(), SettingActivity::class.java)) diff --git a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt index 9885b09e..dbade065 100644 --- a/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt +++ b/app/src/main/java/com/jjbaksa/jjbaksa/ui/mainpage/mypage/viewmodel/MyPageViewModel.kt @@ -1,12 +1,12 @@ package com.jjbaksa.jjbaksa.ui.mainpage.mypage.viewmodel -import android.net.Uri -import android.util.Log +import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.jjbaksa.domain.base.RespResult import com.jjbaksa.domain.repository.UserRepository import com.jjbaksa.jjbaksa.base.BaseViewModel +import com.jjbaksa.jjbaksa.util.SingleLiveEvent import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import javax.inject.Inject @@ -20,6 +20,13 @@ class MyPageViewModel @Inject constructor( val profileFollowers = MutableLiveData(0) val profileImage = MutableLiveData("") val textLength = MutableLiveData("") + + private val _loadImage = SingleLiveEvent() + val loadImage: LiveData get() = _loadImage + + private val _isResult = SingleLiveEvent() + val isResult: LiveData get() = _isResult + fun getUserProfile() { account.value = repository.getAccount() nickname.value = repository.getNickname() @@ -32,13 +39,21 @@ class MyPageViewModel @Inject constructor( textLength.value = length } - fun setProfileImage(image: String) { - profileImage.value = image + fun setLoadImage(image: String) { + _loadImage.value = image } - fun uploadProfileImg() { + + fun uploadProfileImgAndNickname(image: String, newNickname: String) { viewModelScope.launch(ceh) { - var result = repository.editUserProfileImage(profileImage.value!!) - Log.e("tag", result.toString()) + val response = repository.editUserProfileImage(image) + if (response == RespResult.Success(true)) { + profileImage.value = repository.getProfileImage() + val nicknameResponse = repository.setNewNickname(newNickname) + if (nicknameResponse.isSuccess) { + nickname.value = repository.getNickname() + _isResult.value = true + } + } } } } diff --git a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt index a80d7394..d1277126 100644 --- a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt +++ b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt @@ -4,6 +4,8 @@ import retrofit2.http.GET import com.jjbaksa.data.model.user.UserResp import okhttp3.MultipartBody import retrofit2.Response +import com.jjbaksa.domain.resp.user.PasswordAndNicknameReq +import retrofit2.http.Body import retrofit2.http.Multipart import retrofit2.http.PATCH import retrofit2.http.Part diff --git a/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt b/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt index d4530c9e..51e32438 100644 --- a/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt +++ b/data/src/main/java/com/jjbaksa/data/mapper/FormDataUtil.kt @@ -2,13 +2,9 @@ package com.jjbaksa.data.mapper import android.annotation.SuppressLint import android.content.ContentResolver -import android.content.Context -import android.database.Cursor import android.net.Uri -import android.provider.MediaStore import android.provider.OpenableColumns import android.util.Log -import androidx.core.net.toFile import okhttp3.MediaType import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody @@ -20,7 +16,6 @@ import java.io.File import java.net.URLConnection import kotlin.math.abs - object FormDataUtil { val secUnit = 60L val milliSec = 1000L @@ -29,21 +24,22 @@ object FormDataUtil { return MultipartBody.Part.createFormData(key, value.toString()) } - fun getImageBody(key:String, uri: Uri): MultipartBody.Part{ - try{ - return getImageBody(key,File(uri.path)) - }catch (e: Exception){ + fun getImageBody(key: String, uri: Uri): MultipartBody.Part { + try { + return getImageBody(key, File(uri.path)) + } catch (e: Exception) { Log.e("jdm_Tag", e.message.toString()) throw e } } - fun getImageBody(key: String, file: File): MultipartBody.Part { return MultipartBody.Part.createFormData( name = key, filename = file.name, - body = file.asRequestBody(URLConnection.guessContentTypeFromName(file.name).toMediaType()) + body = file.asRequestBody( + URLConnection.guessContentTypeFromName(file.name).toMediaType() + ) ) } @@ -56,42 +52,49 @@ object FormDataUtil { } @SuppressLint("Range") - fun Uri.asMultipart(key: String = "multipartFile", contentResolver: ContentResolver): MultipartBody.Part? { + fun Uri.asMultipart( + key: String = "multipartFile", + contentResolver: ContentResolver + ): MultipartBody.Part? { return contentResolver.query(this, null, null, null, null)?.let { it.use { cursor -> - if(cursor.moveToNext()){ - val displayName = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)); + if (cursor.moveToNext()) { + val displayName = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)) val requestBody = object : RequestBody() { override fun contentType(): MediaType? { return contentResolver.getType(this@asMultipart)?.toMediaType() } override fun writeTo(sink: BufferedSink) { - sink.writeAll(contentResolver.openInputStream(this@asMultipart)?.source()!!) + sink.writeAll( + contentResolver.openInputStream(this@asMultipart)?.source()!! + ) } } MultipartBody.Part.createFormData(key, displayName, requestBody) - }else { + } else { null } } } } - fun secondToStringHHMMWithUnit(timeS: Long, hourText:String, minuteText:String): String{ - val timeArr = stringArrForTimeHHMMSS(timeS,false) + + fun secondToStringHHMMWithUnit(timeS: Long, hourText: String, minuteText: String): String { + val timeArr = stringArrForTimeHHMMSS(timeS, false) val bNegative = timeS < 0 val sb = StringBuilder() - if(bNegative){ + if (bNegative) { sb.append("-") } - if(timeArr[0] > 0){ - sb.append(String.format("%d$hourText ",timeArr[0])) + if (timeArr[0] > 0) { + sb.append(String.format("%d$hourText ", timeArr[0])) } sb.append(String.format("%d$minuteText", timeArr[1])) return sb.toString() } - fun stringArrForTimeHHMMSS(time: Long, isMillis : Boolean): List{ + + fun stringArrForTimeHHMMSS(time: Long, isMillis: Boolean): List { val absTimeMs = abs(time) val totalSeconds = if (isMillis) { absTimeMs / milliSec @@ -101,6 +104,6 @@ object FormDataUtil { val seconds = totalSeconds % secUnit val minutes = totalSeconds / secUnit % secUnit val hours = totalSeconds / (secUnit * secUnit) - return listOf(hours,minutes,seconds) + return listOf(hours, minutes, seconds) } -} \ No newline at end of file +} diff --git a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt index bfdfc823..467875f5 100644 --- a/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt +++ b/data/src/main/java/com/jjbaksa/data/repository/UserRepositoryImpl.kt @@ -16,9 +16,6 @@ import com.jjbaksa.domain.resp.user.SignUpReq import com.jjbaksa.domain.resp.user.SignUpResp import com.jjbaksa.domain.resp.user.FindPasswordReq import com.jjbaksa.domain.resp.user.PasswordAndNicknameReq -import okhttp3.MediaType.Companion.toMediaTypeOrNull -import okhttp3.MultipartBody -import okhttp3.RequestBody.Companion.toRequestBody import javax.inject.Inject class UserRepositoryImpl @Inject constructor( @@ -149,6 +146,19 @@ class UserRepositoryImpl @Inject constructor( } } + override suspend fun setNewNickname(nickname: String): FormatResp { + val item = PasswordAndNicknameReq(null, nickname) + val response = userRemoteDataSource.setNewNickname(item) + return if (response.isSuccessful && response.code() == 200) { + userLocalDataSource.saveNickname(nickname) + FormatResp(response.isSuccessful, "", response.code()) + } else { + val errorBodyJson = response.errorBody()!!.string() + val errorBody = RespMapper.errorMapper(errorBodyJson) + FormatResp(response.isSuccessful, errorBody.errorMessage, response.code()) + } + } + override suspend fun me(): RespResult { val response = userRemoteDataSource.me() return if (response.isSuccessful) { @@ -171,7 +181,6 @@ class UserRepositoryImpl @Inject constructor( } else { return RespResult.Success(false) } - } override fun getAutoLoginFlag(): Boolean { From 33c520628c259f1739447282c455feab38a48fec Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Thu, 20 Jul 2023 23:45:01 +0900 Subject: [PATCH 13/20] #61 [add] set new nickname MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 새로운 닉네임 변경 로직 --- data/src/main/java/com/jjbaksa/data/api/AuthApi.kt | 4 ++++ .../main/java/com/jjbaksa/data/datasource/UserDataSource.kt | 1 + .../com/jjbaksa/data/datasource/local/UserLocalDataSource.kt | 4 ++++ .../jjbaksa/data/datasource/remote/UserRemoteDataSource.kt | 4 ++++ .../main/java/com/jjbaksa/domain/repository/UserRepository.kt | 1 + 5 files changed, 14 insertions(+) diff --git a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt index d1277126..f9494216 100644 --- a/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt +++ b/data/src/main/java/com/jjbaksa/data/api/AuthApi.kt @@ -13,6 +13,10 @@ import retrofit2.http.Part interface AuthApi { @GET("user/me") suspend fun userMe(): Response + @PATCH("user/me") + suspend fun setUserNickname( + @Body item: PasswordAndNicknameReq + ): Response @Multipart @PATCH("user/profile") suspend fun editUserProfileImage( diff --git a/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt index 7ac70c19..30f3bc72 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/UserDataSource.kt @@ -20,6 +20,7 @@ interface UserDataSource { suspend fun findAccount(email: String, code: String): Response suspend fun findPassword(findPasswordReq: FindPasswordReq): Response suspend fun setNewPassword(token: String, item: PasswordAndNicknameReq): Response + suspend fun setNewNickname(item: PasswordAndNicknameReq): Response suspend fun saveAccessToken(accessToken: String) suspend fun saveAccount(account: String) suspend fun saveNickname(nickname: String) diff --git a/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt index ecb4f2f7..69e0d743 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/local/UserLocalDataSource.kt @@ -61,6 +61,10 @@ class UserLocalDataSource @Inject constructor( TODO("Not yet implemented") } + override suspend fun setNewNickname(item: PasswordAndNicknameReq): Response { + TODO("Not yet implemented") + } + override suspend fun saveAccessToken(accessToken: String) { dataStore.edit { it[PreferenceKeys.ACCESS_TOKEN] = accessToken diff --git a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt index 823c3923..fd0e0b9c 100644 --- a/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt +++ b/data/src/main/java/com/jjbaksa/data/datasource/remote/UserRemoteDataSource.kt @@ -58,6 +58,10 @@ class UserRemoteDataSource @Inject constructor( return noAuthApi.setNewPassword(token, item) } + override suspend fun setNewNickname(item: PasswordAndNicknameReq): Response { + return authApi.setUserNickname(item) + } + override suspend fun saveAccessToken(accessToken: String) { } diff --git a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt index 1ae0801f..a32f7959 100644 --- a/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt +++ b/domain/src/main/java/com/jjbaksa/domain/repository/UserRepository.kt @@ -23,6 +23,7 @@ interface UserRepository { suspend fun findAccount(email: String, code: String): FormatResp suspend fun findPassword(user: FindPasswordReq): FormatResp suspend fun setNewPassword(password: String): FormatResp + suspend fun setNewNickname(nickname: String): FormatResp suspend fun me(): RespResult suspend fun editUserProfileImage(photo: String): RespResult fun getAutoLoginFlag(): Boolean From 250878a07d9a5f22747c0ba60fd89d29213b6ad0 Mon Sep 17 00:00:00 2001 From: JoKwanhee Date: Fri, 21 Jul 2023 02:41:45 +0900 Subject: [PATCH 14/20] #61 [mod] gallery image selector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit null 에러 및 DiffUtil 사용, 코드 리팩토링 --- .idea/gradle.xml | 2 +- .../imageselector/gallery/GalleryActivity.kt | 96 +++++++++++++------ .../imageselector/gallery/GalleryAdapter.kt | 78 +++++++-------- .../imageselector/gallery/GalleryViewModel.kt | 21 ++-- .../repository/ImageRepository.kt | 2 +- .../repository/ImageRepositoryImpl.kt | 15 ++- .../imageselector/utils/DataBindingAdapter.kt | 12 +++ .../src/main/res/layout/item_layout.xml | 1 + 8 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 image_selector/src/main/java/com/example/imageselector/utils/DataBindingAdapter.kt diff --git a/.idea/gradle.xml b/.idea/gradle.xml index e8bdd8c9..f3adca57 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,7 +7,7 @@ \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index f3adca57..e8bdd8c9 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,7 +7,7 @@