From 4c26d698a687914ad21f5851de1a29c17a4fe5eb Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 01:44:00 +0900 Subject: [PATCH 01/13] =?UTF-8?q?[Feat]=20=EC=9D=B8=ED=84=B0=EB=84=B7=20?= =?UTF-8?q?=EA=B6=8C=ED=95=9C=20=EC=B6=94=EA=B0=80,=20gradle=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95,=20DTO=20+=20ApiService=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=ED=88=B4=20=EA=B5=AC=EC=B6=95=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 21 ++++++++++++++-- app/src/main/AndroidManifest.xml | 1 + .../com/sopt/now/data/{ => model}/ItemData.kt | 2 +- .../sopt/now/data/model/RequestSignUpDto.kt | 16 ++++++++++++ .../sopt/now/data/model/ResponseSignUpDto.kt | 12 +++++++++ .../com/sopt/now/data/module/ApiFactory.kt | 25 +++++++++++++++++++ .../com/sopt/now/data/network/AuthService.kt | 14 +++++++++++ .../com/sopt/now/ui/adapter/ItemAdapter.kt | 2 +- .../java/com/sopt/now/ui/home/HomFragment.kt | 2 +- .../now/ui/home/viewModel/HomeViewModel.kt | 2 +- build.gradle | 1 + 11 files changed, 92 insertions(+), 6 deletions(-) rename app/src/main/java/com/sopt/now/data/{ => model}/ItemData.kt (92%) create mode 100644 app/src/main/java/com/sopt/now/data/model/RequestSignUpDto.kt create mode 100644 app/src/main/java/com/sopt/now/data/model/ResponseSignUpDto.kt create mode 100644 app/src/main/java/com/sopt/now/data/module/ApiFactory.kt create mode 100644 app/src/main/java/com/sopt/now/data/network/AuthService.kt diff --git a/app/build.gradle b/app/build.gradle index 3a2689d..8d4a567 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,6 +3,9 @@ plugins { id 'org.jetbrains.kotlin.android' } +Properties properties = new Properties() +properties.load(project.rootProject.file('local.properties').newDataInputStream()) + android { namespace 'com.sopt.now' compileSdk 34 @@ -15,6 +18,7 @@ android { versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + buildConfigField "String", "AUTH_BASE_URL", properties["base.url"] } buildTypes { @@ -32,12 +36,13 @@ android { } buildFeatures { viewBinding true + buildConfig true } } dependencies { - implementation 'androidx.core:core-ktx:1.12.0' + implementation 'androidx.core:core-ktx:1.13.0' implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' @@ -45,8 +50,20 @@ dependencies { androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + // Lifecycle Viewmodel implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0' + // Fragment && Activity implementation 'androidx.fragment:fragment-ktx:1.6.2' - implementation 'androidx.activity:activity-ktx:1.8.2' + implementation 'androidx.activity:activity-ktx:1.9.0' + + // Retrofit + implementation 'com.squareup.retrofit2:retrofit:2.9.0' + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1' + implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0' + + // OKHttp + implementation platform('com.squareup.okhttp3:okhttp-bom:4.10.0') + implementation 'com.squareup.okhttp3:okhttp' + implementation 'com.squareup.okhttp3:logging-interceptor' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ec5264f..620246a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,7 @@ + create(): T = retrofit.create(T::class.java) +} + +object ServicePool { + val authService = ApiFactory.create() +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/network/AuthService.kt b/app/src/main/java/com/sopt/now/data/network/AuthService.kt new file mode 100644 index 0000000..d5b42b0 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/network/AuthService.kt @@ -0,0 +1,14 @@ +package com.sopt.now.data.network + +import com.sopt.now.data.model.RequestSignUpDto +import com.sopt.now.data.model.ResponseSignUpDto +import retrofit2.Call +import retrofit2.http.Body +import retrofit2.http.POST + +interface AuthService { + @POST("member/join") + fun signUp( + @Body request: RequestSignUpDto, + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt b/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt index b1dc9a6..3ed2e7a 100644 --- a/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt +++ b/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt @@ -5,7 +5,7 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder -import com.sopt.now.data.ItemData +import com.sopt.now.data.model.ItemData import com.sopt.now.databinding.ItemFriendBinding import com.sopt.now.databinding.ItemMyProfileBinding diff --git a/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt b/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt index 9318151..a91d428 100644 --- a/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt @@ -6,7 +6,7 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import com.sopt.now.data.ItemData +import com.sopt.now.data.model.ItemData import com.sopt.now.databinding.FragmentHomeBinding import com.sopt.now.ui.adapter.ItemAdapter import com.sopt.now.ui.home.viewModel.HomeViewModel diff --git a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt index f390781..67d4b9a 100644 --- a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt @@ -2,7 +2,7 @@ package com.sopt.now.ui.home.viewModel import androidx.lifecycle.ViewModel import com.sopt.now.R -import com.sopt.now.data.ItemData +import com.sopt.now.data.model.ItemData class HomeViewModel : ViewModel() { val friendList = mutableListOf( diff --git a/build.gradle b/build.gradle index be6601c..4c76592 100644 --- a/build.gradle +++ b/build.gradle @@ -3,4 +3,5 @@ plugins { id 'com.android.application' version '8.3.1' apply false id 'com.android.library' version '8.3.1' apply false id 'org.jetbrains.kotlin.android' version '1.9.0' apply false + id("org.jetbrains.kotlin.plugin.serialization") version "1.9.20" apply false } \ No newline at end of file From b4c8ba44bec0cc4adf42d33dc7e549eb65e17a01 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 02:50:40 +0900 Subject: [PATCH 02/13] =?UTF-8?q?[Feat]=20ViewModel=20StateFlow=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 1 + .../com/sopt/now/data/model/SignUpState.kt | 6 ++ .../com/sopt/now/ui/myPage/MyPageFragment.kt | 2 +- .../com/sopt/now/ui/signUp/SignUpActivity.kt | 58 ++++++++++++++----- .../ui/signUp/viewModel/SignUpViewModel.kt | 56 ++++++++++++++++++ app/src/main/res/layout/activity_main.xml | 4 +- app/src/main/res/layout/activity_sign_up.xml | 8 +-- app/src/main/res/layout/fragment_my_page.xml | 4 +- app/src/main/res/values/strings.xml | 4 +- 9 files changed, 117 insertions(+), 26 deletions(-) create mode 100644 app/src/main/java/com/sopt/now/data/model/SignUpState.kt create mode 100644 app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index 8d4a567..d6582b9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'org.jetbrains.kotlin.plugin.serialization' } Properties properties = new Properties() diff --git a/app/src/main/java/com/sopt/now/data/model/SignUpState.kt b/app/src/main/java/com/sopt/now/data/model/SignUpState.kt new file mode 100644 index 0000000..c7c43d4 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/SignUpState.kt @@ -0,0 +1,6 @@ +package com.sopt.now.data.model + +data class SignUpState( + val isSuccess: Boolean, + val message: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt index 80de876..3ab6814 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt @@ -41,7 +41,7 @@ class MyPageFragment( tvMyId.text = id tvMyPw.text = pw tvMyNickname.text = nickname - tvMyMbti.text = mbti + tvMyPhoneNumber.text = mbti } } diff --git a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt index 1d780bf..d6eb0f1 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt @@ -4,26 +4,27 @@ import android.os.Bundle import android.view.MotionEvent import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.sopt.now.data.model.RequestSignUpDto import com.sopt.now.databinding.ActivitySignUpBinding +import com.sopt.now.ui.signUp.viewModel.SignUpViewModel +import kotlinx.coroutines.launch class SignUpActivity : AppCompatActivity() { - companion object { - const val MIN_LENGTH_LOGIN = 6 - const val MAX_LENGTH_LOGIN = 10 - const val MIN_LENGTH_PASSWORD = 8 - const val MAX_LENGTH_PASSWORD = 12 - const val MBTI_LENGTH = 4 - } - private lateinit var binding: ActivitySignUpBinding + private val binding by lazy { ActivitySignUpBinding.inflate(layoutInflater) } + private val viewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding = ActivitySignUpBinding.inflate(layoutInflater) setContentView(binding.root) setSignUpButton() + setCollect() } override fun dispatchTouchEvent(ev: MotionEvent): Boolean { @@ -38,14 +39,33 @@ class SignUpActivity : AppCompatActivity() { private fun setSignUpButton() { binding.btnSignUp.setOnClickListener { - if (isInputValid()) { - handleValidInput() - } else { - showToastMessage("회원 정보를 모두 입력해주세요.") + viewModel.signUp(getSignUpRequestDto()) + } + } + + private fun setCollect() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.signUpState.collect { uiState -> + showToastMessage(uiState.message) + } } } } + private fun getSignUpRequestDto(): RequestSignUpDto { + val id = binding.edtSignUpId.text.toString() + val password = binding.edtSignUpPw.text.toString() + val nickname = binding.edtSignUpNickname.text.toString() + val phoneNumber = binding.edtSignUpPhoneNumber.text.toString() + return RequestSignUpDto( + authenticationId = id, + password = password, + nickname = nickname, + phone = phoneNumber + ) + } + private fun isInputValid(): Boolean { return isIdValid() && isPwValid() && isNicknameValid() && isMbtiValid() } @@ -66,7 +86,7 @@ class SignUpActivity : AppCompatActivity() { } private fun isMbtiValid(): Boolean { - val mbtiText = binding.edtSignUpMbti.text.toString() + val mbtiText = binding.edtSignUpPhoneNumber.text.toString() return mbtiText.isNotBlank() && mbtiText.length == MBTI_LENGTH } @@ -77,7 +97,7 @@ class SignUpActivity : AppCompatActivity() { putExtra("id", binding.edtSignUpId.text.toString()) putExtra("pw", binding.edtSignUpPw.text.toString()) putExtra("nickname", binding.edtSignUpNickname.text.toString()) - putExtra("mbti", binding.edtSignUpMbti.text.toString()) + putExtra("mbti", binding.edtSignUpPhoneNumber.text.toString()) } setResult(RESULT_OK, intent) @@ -87,4 +107,12 @@ class SignUpActivity : AppCompatActivity() { private fun showToastMessage(text: String) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() } + + companion object { + const val MIN_LENGTH_LOGIN = 6 + const val MAX_LENGTH_LOGIN = 10 + const val MIN_LENGTH_PASSWORD = 8 + const val MAX_LENGTH_PASSWORD = 12 + const val MBTI_LENGTH = 4 + } } diff --git a/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt new file mode 100644 index 0000000..de287e2 --- /dev/null +++ b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt @@ -0,0 +1,56 @@ +package com.sopt.now.ui.signUp.viewModel + +import android.util.Log +import androidx.lifecycle.ViewModel +import com.sopt.now.data.model.RequestSignUpDto +import com.sopt.now.data.model.ResponseSignUpDto +import com.sopt.now.data.model.SignUpState +import com.sopt.now.data.module.ServicePool +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class SignUpViewModel : ViewModel() { + private val authService by lazy { ServicePool.authService } + + private val _signUpState = MutableStateFlow(SignUpState(isSuccess = false, message = "")) + val signUpState = _signUpState.asStateFlow() + + fun signUp(request: RequestSignUpDto) { + authService.signUp(request).enqueue( + object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + if (response.isSuccessful) { + val data: ResponseSignUpDto? = response.body() + val userId = response.headers()["location"] + _signUpState.update { + SignUpState( + isSuccess = true, + message = "가입된 유저 아이디는 $userId" + ) + } + Log.d("SignUp", "data : $data, userId: $userId") + } else { + val error = response.message() + _signUpState.update { + SignUpState( + isSuccess = false, + message = "로그인 실패 : $error" + ) + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + _signUpState.update { SignUpState(isSuccess = false, message = "서버 에러") } + } + }, + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 9eadf13..e3d3436 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -64,14 +64,14 @@ android:text="@string/pw_label" /> + android:text="@string/phone_number_label" /> diff --git a/app/src/main/res/layout/activity_sign_up.xml b/app/src/main/res/layout/activity_sign_up.xml index 3eeb1db..30c06d5 100644 --- a/app/src/main/res/layout/activity_sign_up.xml +++ b/app/src/main/res/layout/activity_sign_up.xml @@ -108,17 +108,17 @@ android:textSize="14sp" /> diff --git a/app/src/main/res/layout/fragment_my_page.xml b/app/src/main/res/layout/fragment_my_page.xml index 151463d..d03c592 100644 --- a/app/src/main/res/layout/fragment_my_page.xml +++ b/app/src/main/res/layout/fragment_my_page.xml @@ -64,14 +64,14 @@ android:text="@string/pw_label" /> + android:text="@string/phone_number_label" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 978087c..adf55e4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,8 +14,8 @@ SIGN UP 닉네임 닉네임을 입력해주세요 - MBTI - MBTI를 입력해주세요 + 전화번호 + 전화번호를 입력해주세요 From 2ac386e84e950cacc64ac016e728cec473acda00 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 03:19:06 +0900 Subject: [PATCH 03/13] =?UTF-8?q?[Feat]=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20API=20200=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=84=B1?= =?UTF-8?q?=EA=B3=B5=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 1 + app/src/main/java/com/sopt/now/data/module/ApiFactory.kt | 5 ----- app/src/main/java/com/sopt/now/data/module/ServicePool.kt | 7 +++++++ 3 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/com/sopt/now/data/module/ServicePool.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 620246a..c279201 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,6 +5,7 @@ create(): T = retrofit.create(T::class.java) -} - -object ServicePool { - val authService = ApiFactory.create() } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/module/ServicePool.kt b/app/src/main/java/com/sopt/now/data/module/ServicePool.kt new file mode 100644 index 0000000..8fa9b95 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/module/ServicePool.kt @@ -0,0 +1,7 @@ +package com.sopt.now.data.module + +import com.sopt.now.data.network.AuthService + +object ServicePool { + val authService = ApiFactory.create() +} \ No newline at end of file From ec9703b83ee2e02d86927777130aa23c91d4e0f3 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 04:00:20 +0900 Subject: [PATCH 04/13] =?UTF-8?q?[Feat]=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EC=A1=B0=EA=B1=B4=20=EB=A7=8C=EC=A1=B1=EC=8B=9C=20?= =?UTF-8?q?API=20=EC=9A=94=EC=B2=AD=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/sopt/now/ui/login/LoginActivity.kt | 15 +------- .../com/sopt/now/ui/signUp/SignUpActivity.kt | 38 +++++++++---------- .../ui/signUp/viewModel/SignUpViewModel.kt | 2 +- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt b/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt index 15624df..bde39f2 100644 --- a/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt @@ -1,13 +1,10 @@ package com.sopt.now.ui.login -import android.app.Activity import android.content.Intent import android.os.Bundle import android.view.MotionEvent import android.view.inputmethod.InputMethodManager import android.widget.Toast -import androidx.activity.result.ActivityResult -import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.appcompat.app.AppCompatActivity import com.sopt.now.databinding.ActivityLoginBinding import com.sopt.now.ui.main.MainActivity @@ -35,16 +32,6 @@ class LoginActivity : AppCompatActivity() { return super.dispatchTouchEvent(ev) } - private val startForResult = - registerForActivityResult(StartActivityForResult()) { result: ActivityResult -> - if (result.resultCode == Activity.RESULT_OK) { - savedId = result.data?.getStringExtra("id") ?: "" - savedPw = result.data?.getStringExtra("pw") ?: "" - savedNickname = result.data?.getStringExtra("nickname") ?: "" - savedMbti = result.data?.getStringExtra("mbti") ?: "" - } - } - private fun setLoginButtonClickListeners() { binding.btnLogin.setOnClickListener { val id = binding.edtLoginId.text.toString() @@ -74,7 +61,7 @@ class LoginActivity : AppCompatActivity() { private fun moveToSignUp() { val intent = Intent(this, SignUpActivity::class.java) - startForResult.launch(intent) + startActivity(intent) } private fun moveToMain() { diff --git a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt index d6eb0f1..d86a6a1 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt @@ -39,15 +39,23 @@ class SignUpActivity : AppCompatActivity() { private fun setSignUpButton() { binding.btnSignUp.setOnClickListener { - viewModel.signUp(getSignUpRequestDto()) + when { + isInputValid() -> viewModel.signUp(getSignUpRequestDto()) + else -> showToastMessage("모든 정보를 입력해주세요.") + } } } private fun setCollect() { lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { - viewModel.signUpState.collect { uiState -> - showToastMessage(uiState.message) + viewModel.signUpState.collect { signUpState -> + if (signUpState.message.isNotBlank()) { + showToastMessage(signUpState.message) + if (signUpState.isSuccess) { + handleValidInput() + } + } } } } @@ -67,7 +75,7 @@ class SignUpActivity : AppCompatActivity() { } private fun isInputValid(): Boolean { - return isIdValid() && isPwValid() && isNicknameValid() && isMbtiValid() + return isIdValid() && isPwValid() && isNicknameValid() && isPhoneNumberValid() } private fun isIdValid(): Boolean { @@ -77,7 +85,10 @@ class SignUpActivity : AppCompatActivity() { private fun isPwValid(): Boolean { val pwText = binding.edtSignUpPw.text.toString() - return pwText.isNotBlank() && pwText.length in MIN_LENGTH_PASSWORD..MAX_LENGTH_PASSWORD + return pwText.isNotBlank() && pwText.length >= MIN_LENGTH_PASSWORD + && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z[0-9]\$@!%*#?&.]{8,20}\$").matches( + pwText + ) } private fun isNicknameValid(): Boolean { @@ -85,22 +96,13 @@ class SignUpActivity : AppCompatActivity() { return nicknameText.isNotBlank() && !nicknameText.contains(" ") } - private fun isMbtiValid(): Boolean { - val mbtiText = binding.edtSignUpPhoneNumber.text.toString() - return mbtiText.isNotBlank() && mbtiText.length == MBTI_LENGTH + private fun isPhoneNumberValid(): Boolean { + val phoneNumberText = binding.edtSignUpPhoneNumber.text.toString() + return phoneNumberText.isNotBlank() && Regex("^010-\\d{4}-\\d{4}\$").matches(phoneNumberText) } private fun handleValidInput() { showToastMessage("회원가입이 완료되었습니다.") - - intent.apply { - putExtra("id", binding.edtSignUpId.text.toString()) - putExtra("pw", binding.edtSignUpPw.text.toString()) - putExtra("nickname", binding.edtSignUpNickname.text.toString()) - putExtra("mbti", binding.edtSignUpPhoneNumber.text.toString()) - } - - setResult(RESULT_OK, intent) finish() } @@ -112,7 +114,5 @@ class SignUpActivity : AppCompatActivity() { const val MIN_LENGTH_LOGIN = 6 const val MAX_LENGTH_LOGIN = 10 const val MIN_LENGTH_PASSWORD = 8 - const val MAX_LENGTH_PASSWORD = 12 - const val MBTI_LENGTH = 4 } } diff --git a/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt index de287e2..1821324 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt @@ -37,7 +37,7 @@ class SignUpViewModel : ViewModel() { } Log.d("SignUp", "data : $data, userId: $userId") } else { - val error = response.message() + val error = response.code() _signUpState.update { SignUpState( isSuccess = false, From 9bd843e9eaff34a376a8bade3a1330465b4544ef Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 04:22:43 +0900 Subject: [PATCH 05/13] =?UTF-8?q?[Feat]=20=EC=84=9C=EB=B2=84=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EC=9D=B8=20API=20=EA=B5=AC=ED=98=84=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 2 +- .../sopt/now/data/model/RequestSignInDto.kt | 12 ++++ .../sopt/now/data/model/ResponseSignInDto.kt | 12 ++++ .../com/sopt/now/data/model/SignInState.kt | 6 ++ .../com/sopt/now/data/network/AuthService.kt | 7 ++ .../SignInActivity.kt} | 69 +++++++++++-------- .../ui/signIn/viewModel/SignInViewModel.kt | 58 ++++++++++++++++ .../com/sopt/now/ui/signUp/SignUpActivity.kt | 2 +- .../ui/signUp/viewModel/SignUpViewModel.kt | 5 +- app/src/main/res/layout/activity_login.xml | 12 ++-- 10 files changed, 143 insertions(+), 42 deletions(-) create mode 100644 app/src/main/java/com/sopt/now/data/model/RequestSignInDto.kt create mode 100644 app/src/main/java/com/sopt/now/data/model/ResponseSignInDto.kt create mode 100644 app/src/main/java/com/sopt/now/data/model/SignInState.kt rename app/src/main/java/com/sopt/now/ui/{login/LoginActivity.kt => signIn/SignInActivity.kt} (52%) create mode 100644 app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c279201..832197d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -15,7 +15,7 @@ android:theme="@style/Theme.NOWSOPTAndroid" tools:targetApi="31"> diff --git a/app/src/main/java/com/sopt/now/data/model/RequestSignInDto.kt b/app/src/main/java/com/sopt/now/data/model/RequestSignInDto.kt new file mode 100644 index 0000000..c6ba27e --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/RequestSignInDto.kt @@ -0,0 +1,12 @@ +package com.sopt.now.data.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class RequestSignInDto( + @SerialName("authenticationId") + val authenticationId: String, + @SerialName("password") + val password: String, +) diff --git a/app/src/main/java/com/sopt/now/data/model/ResponseSignInDto.kt b/app/src/main/java/com/sopt/now/data/model/ResponseSignInDto.kt new file mode 100644 index 0000000..e1ef401 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/ResponseSignInDto.kt @@ -0,0 +1,12 @@ +package com.sopt.now.data.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseSignInDto( + @SerialName("code") + val code: Int, + @SerialName("message") + val message: String, +) diff --git a/app/src/main/java/com/sopt/now/data/model/SignInState.kt b/app/src/main/java/com/sopt/now/data/model/SignInState.kt new file mode 100644 index 0000000..8756c3b --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/SignInState.kt @@ -0,0 +1,6 @@ +package com.sopt.now.data.model + +data class SignInState( + val isSuccess: Boolean, + val message: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/network/AuthService.kt b/app/src/main/java/com/sopt/now/data/network/AuthService.kt index d5b42b0..94ff2f6 100644 --- a/app/src/main/java/com/sopt/now/data/network/AuthService.kt +++ b/app/src/main/java/com/sopt/now/data/network/AuthService.kt @@ -1,6 +1,8 @@ package com.sopt.now.data.network +import com.sopt.now.data.model.RequestSignInDto import com.sopt.now.data.model.RequestSignUpDto +import com.sopt.now.data.model.ResponseSignInDto import com.sopt.now.data.model.ResponseSignUpDto import retrofit2.Call import retrofit2.http.Body @@ -11,4 +13,9 @@ interface AuthService { fun signUp( @Body request: RequestSignUpDto, ): Call + + @POST("member/login") + fun singIn( + @Body request: RequestSignInDto, + ): Call } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt b/app/src/main/java/com/sopt/now/ui/signIn/SignInActivity.kt similarity index 52% rename from app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt rename to app/src/main/java/com/sopt/now/ui/signIn/SignInActivity.kt index bde39f2..7658515 100644 --- a/app/src/main/java/com/sopt/now/ui/login/LoginActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signIn/SignInActivity.kt @@ -1,28 +1,31 @@ -package com.sopt.now.ui.login +package com.sopt.now.ui.signIn import android.content.Intent import android.os.Bundle import android.view.MotionEvent import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.sopt.now.data.model.RequestSignInDto import com.sopt.now.databinding.ActivityLoginBinding import com.sopt.now.ui.main.MainActivity +import com.sopt.now.ui.signIn.viewModel.SignInViewModel import com.sopt.now.ui.signUp.SignUpActivity +import kotlinx.coroutines.launch -class LoginActivity : AppCompatActivity() { - private lateinit var binding: ActivityLoginBinding - private var isCheckLogin: Boolean = false - private var savedId: String = "" - private var savedPw: String = "" - private var savedNickname: String = "" - private var savedMbti: String = "" +class SignInActivity : AppCompatActivity() { + private val binding by lazy { ActivityLoginBinding.inflate(layoutInflater) } + private val viewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - binding = ActivityLoginBinding.inflate(layoutInflater) setContentView(binding.root) + setCollect() setLoginButtonClickListeners() setSignUpButtonClickListeners() } @@ -32,17 +35,34 @@ class LoginActivity : AppCompatActivity() { return super.dispatchTouchEvent(ev) } + private fun setCollect() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.signInState.collect { signInState -> + if (signInState.message.isNotBlank()) { + showToastMessage(signInState.message) + if (signInState.isSuccess) { + moveToMain() + } + } + } + } + } + } + + private fun getSignInRequestDto(): RequestSignInDto { + val id = binding.edtSignInId.text.toString() + val pw = binding.edtSignInPw.text.toString() + + return RequestSignInDto( + authenticationId = id, + password = pw, + ) + } + private fun setLoginButtonClickListeners() { binding.btnLogin.setOnClickListener { - val id = binding.edtLoginId.text.toString() - val pw = binding.edtLoginPw.text.toString() - isCheckLogin = checkLogin(id, pw, savedId, savedPw) - if (isCheckLogin) { - showToastMessage("로그인 성공!") - moveToMain() - } else { - showToastMessage("로그인에 실패하였습니다.") - } + viewModel.signIn(getSignInRequestDto()) } } @@ -65,15 +85,8 @@ class LoginActivity : AppCompatActivity() { } private fun moveToMain() { - val intent = Intent(this, MainActivity::class.java).apply { - putExtra("id", savedId) - putExtra("pw", savedPw) - putExtra("nickname", savedNickname) - putExtra("mbti", savedMbti) - } + val intent = Intent(this, MainActivity::class.java) startActivity(intent) - setResult(RESULT_OK, intent) - finish() } private fun showToastMessage(text: String = "") { @@ -83,8 +96,4 @@ class LoginActivity : AppCompatActivity() { Toast.LENGTH_SHORT ).show() } - - private fun checkLogin(id: String, pw: String, savedId: String, savedPw: String): Boolean { - return id.isNotEmpty() && pw.isNotEmpty() && id == savedId && pw == savedPw - } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt b/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt new file mode 100644 index 0000000..53ed2f0 --- /dev/null +++ b/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt @@ -0,0 +1,58 @@ +package com.sopt.now.ui.signIn.viewModel + +import android.util.Log +import androidx.lifecycle.ViewModel +import com.sopt.now.data.model.RequestSignInDto +import com.sopt.now.data.model.ResponseSignInDto +import com.sopt.now.data.model.SignInState +import com.sopt.now.data.module.ServicePool +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +class SignInViewModel : ViewModel() { + private val authService by lazy { ServicePool.authService } + + private val _signInState = MutableStateFlow(SignInState(isSuccess = false, message = "")) + val signInState = _signInState.asStateFlow() + + fun signIn(request: RequestSignInDto) { + authService.singIn(request).enqueue( + object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + if (response.isSuccessful) { + val data = response.body() + val userId = response.headers()["location"] + _signInState.update { + SignInState( + isSuccess = true, + message = "유저 아이디는 $userId" + ) + } + Log.d("SignIn", "$data") + } else { + val data = response.body() + val error = response.code() + _signInState.update { + SignInState( + isSuccess = false, + message = "로그인 실패 : $error" + ) + } + Log.d("SignIn", "${data?.message}") + } + } + + override fun onFailure(call: Call, t: Throwable) { + _signInState.update { SignInState(isSuccess = false, message = "서버 에러") } + } + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt index d86a6a1..0a42cdc 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt @@ -86,7 +86,7 @@ class SignUpActivity : AppCompatActivity() { private fun isPwValid(): Boolean { val pwText = binding.edtSignUpPw.text.toString() return pwText.isNotBlank() && pwText.length >= MIN_LENGTH_PASSWORD - && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z[0-9]\$@!%*#?&.]{8,20}\$").matches( + && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z\\[0-9]\\\$@!%*#?&.]{8,20}\$").matches( pwText ) } diff --git a/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt index 1821324..e80cb59 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/viewModel/SignUpViewModel.kt @@ -1,6 +1,5 @@ package com.sopt.now.ui.signUp.viewModel -import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.data.model.RequestSignUpDto import com.sopt.now.data.model.ResponseSignUpDto @@ -27,7 +26,6 @@ class SignUpViewModel : ViewModel() { response: Response, ) { if (response.isSuccessful) { - val data: ResponseSignUpDto? = response.body() val userId = response.headers()["location"] _signUpState.update { SignUpState( @@ -35,13 +33,12 @@ class SignUpViewModel : ViewModel() { message = "가입된 유저 아이디는 $userId" ) } - Log.d("SignUp", "data : $data, userId: $userId") } else { val error = response.code() _signUpState.update { SignUpState( isSuccess = false, - message = "로그인 실패 : $error" + message = "회원가입 실패 : $error" ) } } diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml index 0ce195b..ffa6096 100644 --- a/app/src/main/res/layout/activity_login.xml +++ b/app/src/main/res/layout/activity_login.xml @@ -5,7 +5,7 @@ android:id="@+id/main" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".ui.login.LoginActivity"> + tools:context=".ui.signIn.SignInActivity"> From 8e90152c6f028bc03b4817e1ee4773c84fa54744 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 12:53:06 +0900 Subject: [PATCH 06/13] =?UTF-8?q?[Feat]=20followerList=20=EB=B6=88?= =?UTF-8?q?=EB=9F=AC=EC=98=A4=EA=B8=B0=20=EA=B5=AC=ED=98=84=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 5 + app/src/main/AndroidManifest.xml | 9 +- .../java/com/sopt/now/data/model/ItemData.kt | 2 +- .../sopt/now/data/model/ResponseInfoDto.kt | 14 +++ .../sopt/now/data/model/ResponseUserDto.kt | 29 +++++ .../com/sopt/now/data/module/ApiFactory.kt | 20 +++- .../com/sopt/now/data/module/ServicePool.kt | 7 -- .../com/sopt/now/data/network/AuthService.kt | 7 +- .../sopt/now/data/network/FollowerService.kt | 13 ++ .../com/sopt/now/ui/adapter/ItemAdapter.kt | 8 +- .../home/{HomFragment.kt => HomeFragment.kt} | 29 +++-- .../now/ui/home/viewModel/HomeViewModel.kt | 113 ++++++++---------- .../java/com/sopt/now/ui/main/MainActivity.kt | 8 +- .../com/sopt/now/ui/myPage/MyPageFragment.kt | 12 +- .../ui/myPage/viewModel/MyPageViewModel.kt | 12 ++ .../ui/signIn/viewModel/SignInViewModel.kt | 8 +- app/src/main/res/layout/fragment_my_page.xml | 10 -- 17 files changed, 194 insertions(+), 112 deletions(-) create mode 100644 app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt create mode 100644 app/src/main/java/com/sopt/now/data/model/ResponseUserDto.kt delete mode 100644 app/src/main/java/com/sopt/now/data/module/ServicePool.kt create mode 100644 app/src/main/java/com/sopt/now/data/network/FollowerService.kt rename app/src/main/java/com/sopt/now/ui/home/{HomFragment.kt => HomeFragment.kt} (63%) create mode 100644 app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt diff --git a/app/build.gradle b/app/build.gradle index d6582b9..62cb488 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -20,6 +20,7 @@ android { testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" buildConfigField "String", "AUTH_BASE_URL", properties["base.url"] + buildConfigField "String", "FOLLOWER_URL", properties["follower.url"] } buildTypes { @@ -67,4 +68,8 @@ dependencies { implementation platform('com.squareup.okhttp3:okhttp-bom:4.10.0') implementation 'com.squareup.okhttp3:okhttp' implementation 'com.squareup.okhttp3:logging-interceptor' + + // Glide + implementation 'com.github.bumptech.glide:glide:4.13.0' + annotationProcessor 'com.github.bumptech.glide:compiler:4.13.0' } \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 832197d..39e86b6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,15 +16,18 @@ tools:targetApi="31"> + + + - + diff --git a/app/src/main/java/com/sopt/now/data/model/ItemData.kt b/app/src/main/java/com/sopt/now/data/model/ItemData.kt index 1722cf0..5eadebf 100644 --- a/app/src/main/java/com/sopt/now/data/model/ItemData.kt +++ b/app/src/main/java/com/sopt/now/data/model/ItemData.kt @@ -12,7 +12,7 @@ sealed class ItemData { data class Friend( - @DrawableRes val profileImage: Int?, + val profileImage: String?, val name: String, val description: String?, ) : ItemData() diff --git a/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt b/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt new file mode 100644 index 0000000..a7d2416 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt @@ -0,0 +1,14 @@ +package com.sopt.now.data.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class ResponseInfoDto( + @SerialName("authenticationId") + val authenticationId: String, + @SerialName("nickname") + val nickname: String, + @SerialName("phone") + val phone: String, +) \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/model/ResponseUserDto.kt b/app/src/main/java/com/sopt/now/data/model/ResponseUserDto.kt new file mode 100644 index 0000000..aca3029 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/model/ResponseUserDto.kt @@ -0,0 +1,29 @@ +package com.sopt.now.data.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class UserDataResponse( + val page: Int, + @SerialName("per_page") val perPage: Int, + val total: Int, + @SerialName("total_pages") val totalPages: Int, + val data: List, + val support: Support, +) + +@Serializable +data class UserData( + val id: Int, + val email: String, + @SerialName("first_name") val firstName: String, + @SerialName("last_name") val lastName: String, + val avatar: String, +) + +@Serializable +data class Support( + val url: String, + val text: String, +) diff --git a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt index 844809d..3e765d9 100644 --- a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt +++ b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt @@ -2,19 +2,35 @@ package com.sopt.now.data.module import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.sopt.now.BuildConfig +import com.sopt.now.data.network.AuthService +import com.sopt.now.data.network.FollowerService import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType import retrofit2.Retrofit object ApiFactory { private const val BASE_URL: String = BuildConfig.AUTH_BASE_URL + private const val FOLLOWER_URL: String = BuildConfig.FOLLOWER_URL - val retrofit: Retrofit by lazy { + val baseRetrofit: Retrofit by lazy { Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) .build() } - inline fun create(): T = retrofit.create(T::class.java) + val followerRetrofit: Retrofit by lazy { + Retrofit.Builder() + .baseUrl(FOLLOWER_URL) + .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) + .build() + } + + inline fun createBase(): T = baseRetrofit.create(T::class.java) + inline fun createFollower(): T = followerRetrofit.create(T::class.java) +} + +object ServicePool { + val authService = ApiFactory.createBase() + val followerService = ApiFactory.createFollower() } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/module/ServicePool.kt b/app/src/main/java/com/sopt/now/data/module/ServicePool.kt deleted file mode 100644 index 8fa9b95..0000000 --- a/app/src/main/java/com/sopt/now/data/module/ServicePool.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.sopt.now.data.module - -import com.sopt.now.data.network.AuthService - -object ServicePool { - val authService = ApiFactory.create() -} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/network/AuthService.kt b/app/src/main/java/com/sopt/now/data/network/AuthService.kt index 94ff2f6..77127b9 100644 --- a/app/src/main/java/com/sopt/now/data/network/AuthService.kt +++ b/app/src/main/java/com/sopt/now/data/network/AuthService.kt @@ -2,10 +2,12 @@ package com.sopt.now.data.network import com.sopt.now.data.model.RequestSignInDto import com.sopt.now.data.model.RequestSignUpDto +import com.sopt.now.data.model.ResponseInfoDto import com.sopt.now.data.model.ResponseSignInDto import com.sopt.now.data.model.ResponseSignUpDto import retrofit2.Call import retrofit2.http.Body +import retrofit2.http.GET import retrofit2.http.POST interface AuthService { @@ -15,7 +17,10 @@ interface AuthService { ): Call @POST("member/login") - fun singIn( + fun signIn( @Body request: RequestSignInDto, ): Call + + @GET("member/info") + fun memberInfo(): Call } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/network/FollowerService.kt b/app/src/main/java/com/sopt/now/data/network/FollowerService.kt new file mode 100644 index 0000000..33100bb --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/network/FollowerService.kt @@ -0,0 +1,13 @@ +package com.sopt.now.data.network + +import com.sopt.now.data.model.UserDataResponse +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Query + +interface FollowerService { + @GET("/api/users") + fun getUserList( + @Query("page") page: Int, + ): Call +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt b/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt index 3ed2e7a..3886cda 100644 --- a/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt +++ b/app/src/main/java/com/sopt/now/ui/adapter/ItemAdapter.kt @@ -5,6 +5,7 @@ import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView.ViewHolder +import com.bumptech.glide.Glide import com.sopt.now.data.model.ItemData import com.sopt.now.databinding.ItemFriendBinding import com.sopt.now.databinding.ItemMyProfileBinding @@ -47,9 +48,12 @@ class ItemAdapter(private val items: MutableList) : RecyclerView.Adapt } is ItemData.Friend -> { - (holder as FriendViewHolder).profileImage.setImageResource(item.profileImage!!) - holder.name.text = item.name + (holder as FriendViewHolder).name.text = item.name holder.description.text = item.description + Glide.with(holder.profileImage.context) + .load(item.profileImage) + .into(holder.profileImage) + holder.itemView.setOnClickListener { itemClick?.onItemClick(it, position) } diff --git a/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt b/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt similarity index 63% rename from app/src/main/java/com/sopt/now/ui/home/HomFragment.kt rename to app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt index a91d428..5914b41 100644 --- a/app/src/main/java/com/sopt/now/ui/home/HomFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt @@ -6,10 +6,14 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels -import com.sopt.now.data.model.ItemData +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import androidx.recyclerview.widget.LinearLayoutManager import com.sopt.now.databinding.FragmentHomeBinding import com.sopt.now.ui.adapter.ItemAdapter import com.sopt.now.ui.home.viewModel.HomeViewModel +import kotlinx.coroutines.launch class HomeFragment : Fragment() { private var _binding: FragmentHomeBinding? = null @@ -31,10 +35,9 @@ class HomeFragment : Fragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val items = viewModel.friendList - val friendAdapter = ItemAdapter(items) - binding.rvFriends.adapter = friendAdapter - setFriendList(items) + + setCollect() + setAdapter() } override fun onDestroy() { @@ -42,8 +45,20 @@ class HomeFragment : Fragment() { super.onDestroy() } - private fun setFriendList(friendList: List) { - friendList.toList() + private fun setCollect() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.followerState.collect { + setAdapter() + } + } + } } + private fun setAdapter() { + val friendAdapter = ItemAdapter(viewModel.friendList) + + binding.rvFriends.layoutManager = LinearLayoutManager(requireContext()) + binding.rvFriends.adapter = friendAdapter + } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt index 67d4b9a..b98cff4 100644 --- a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt @@ -1,76 +1,67 @@ package com.sopt.now.ui.home.viewModel +import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.R import com.sopt.now.data.model.ItemData +import com.sopt.now.data.model.UserData +import com.sopt.now.data.model.UserDataResponse +import com.sopt.now.data.module.ServicePool +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class HomeViewModel : ViewModel() { - val friendList = mutableListOf( + private val followerService by lazy { ServicePool.followerService } + private val _followerState = MutableStateFlow>(emptyList()) + val followerState = _followerState.asStateFlow() + + val friendList = mutableListOf( ItemData.MyProfile( profileImage = R.drawable.img_arin, name = "김아린", description = "업보 청산 중..", ), - ItemData.Friend( - profileImage = R.drawable.img_profile0, - name = "이의경", - description = "김아린 과제 벼락치기 하지 마라", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile1, - name = "최준서", - description = "오운완 ㅋㅋ", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile2, - name = "이연진", - description = "아리니 넘 기엽당..", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile3, - name = "손민재", - description = "점심 뭐 먹지?", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile4, - name = "홍해인", - description = "난 눈물의 여왕이야", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile5, - name = "백현우", - description = "눈물의여왕시작하지말걸공부가안된다", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile6, - name = "이서경", - description = "저는 환연 과몰입러예요", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile7, - name = "이주원", - description = "너가 자기야 미안해 했잖아?", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile8, - name = "김광태", - description = "내일 뭐 해?", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile9, - name = "정현규", - description = "내봬누", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile10, - name = "성해은", - description = "벌써 스물 아홉이야", - ), - ItemData.Friend( - profileImage = R.drawable.img_profile11, - name = "정규민", - description = "오마카세 사줄게", - ), ) + + init { + fetchFollowerList() + } + + private fun fetchFollowerList() { + followerService.getUserList(page = 2).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + if (response.isSuccessful) { + val data = response.body()?.data + if (data != null) { + _followerState.value = data + mapFollowersToFriendList(data) + Log.d("FOLLOWER", "$data") + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("HomeError", "${t.message}") + } + }) + } + + fun mapFollowersToFriendList(followers: List) { + for (follower in followers) { + friendList.add( + ItemData.Friend( + profileImage = follower.avatar, + name = "${follower.firstName} ${follower.lastName}", + description = follower.email + ) + ) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt b/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt index 2156d96..79412a8 100644 --- a/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt @@ -14,7 +14,7 @@ class MainActivity : AppCompatActivity() { private lateinit var id: String private lateinit var pw: String private lateinit var nickname: String - private lateinit var mbti: String + private lateinit var phoneNumber: String override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -36,7 +36,7 @@ class MainActivity : AppCompatActivity() { id = getStringExtra(ID).toString() pw = getStringExtra(PW).toString() nickname = getStringExtra(NICKNAME).toString() - mbti = getStringExtra(MBTI).toString() + phoneNumber = getStringExtra(PHONE_NUMBER).toString() } } @@ -67,7 +67,7 @@ class MainActivity : AppCompatActivity() { R.id.menu_my_page -> { replaceFragment( MyPageFragment( - id, pw, nickname, mbti + id, nickname, phoneNumber ) ) true @@ -88,6 +88,6 @@ class MainActivity : AppCompatActivity() { const val ID = "id" const val PW = "pw" const val NICKNAME = "nickname" - const val MBTI = "mbti" + const val PHONE_NUMBER = "phoneNumber" } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt index 3ab6814..1ff9a5c 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt @@ -9,9 +9,8 @@ import com.sopt.now.databinding.FragmentMyPageBinding class MyPageFragment( private val id: String, - private val pw: String, private val nickname: String, - private val mbti: String, + private val phoneNumber: String, ) : Fragment() { private var _binding: FragmentMyPageBinding? = null private val binding @@ -19,7 +18,6 @@ class MyPageFragment( "바인딩 객체 미생성" } - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -32,16 +30,14 @@ class MyPageFragment( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setMainProfile(id, pw, nickname, mbti) - + setMainProfile(id, nickname, phoneNumber) } - private fun setMainProfile(id: String, pw: String, nickname: String, mbti: String) { + private fun setMainProfile(id: String, nickname: String, phoneNumber: String) { with(binding) { tvMyId.text = id - tvMyPw.text = pw tvMyNickname.text = nickname - tvMyPhoneNumber.text = mbti + tvMyPhoneNumber.text = phoneNumber } } diff --git a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt new file mode 100644 index 0000000..76ed1ee --- /dev/null +++ b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt @@ -0,0 +1,12 @@ +package com.sopt.now.ui.myPage.viewModel + +import androidx.lifecycle.ViewModel +import com.sopt.now.data.model.ResponseInfoDto +import com.sopt.now.data.module.ServicePool +import kotlinx.coroutines.flow.MutableStateFlow + +class MyPageViewModel : ViewModel() { + private val authService by lazy { ServicePool.authService } + + private val _infoState = MutableStateFlow(ResponseInfoDto) +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt b/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt index 53ed2f0..7536515 100644 --- a/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/signIn/viewModel/SignInViewModel.kt @@ -1,6 +1,5 @@ package com.sopt.now.ui.signIn.viewModel -import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.data.model.RequestSignInDto import com.sopt.now.data.model.ResponseSignInDto @@ -20,24 +19,22 @@ class SignInViewModel : ViewModel() { val signInState = _signInState.asStateFlow() fun signIn(request: RequestSignInDto) { - authService.singIn(request).enqueue( + authService.signIn(request).enqueue( object : Callback { override fun onResponse( call: Call, response: Response, ) { if (response.isSuccessful) { - val data = response.body() val userId = response.headers()["location"] + _signInState.update { SignInState( isSuccess = true, message = "유저 아이디는 $userId" ) } - Log.d("SignIn", "$data") } else { - val data = response.body() val error = response.code() _signInState.update { SignInState( @@ -45,7 +42,6 @@ class SignInViewModel : ViewModel() { message = "로그인 실패 : $error" ) } - Log.d("SignIn", "${data?.message}") } } diff --git a/app/src/main/res/layout/fragment_my_page.xml b/app/src/main/res/layout/fragment_my_page.xml index d03c592..e8d8b95 100644 --- a/app/src/main/res/layout/fragment_my_page.xml +++ b/app/src/main/res/layout/fragment_my_page.xml @@ -53,16 +53,6 @@ android:layout_marginBottom="16dp" android:text="@string/id_label" /> - - Date: Fri, 3 May 2024 13:45:22 +0900 Subject: [PATCH 07/13] =?UTF-8?q?[Feat]=20myInfo=20Get=20API=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 11 ++--- .../sopt/now/data/model/ResponseInfoDto.kt | 10 ++++ .../com/sopt/now/data/module/ApiFactory.kt | 5 ++ .../sopt/now/data/module/AuthInterceptor.kt | 14 ++++++ .../com/sopt/now/data/network/AuthService.kt | 3 +- .../java/com/sopt/now/ui/home/HomeFragment.kt | 1 - .../now/ui/home/viewModel/HomeViewModel.kt | 2 +- .../java/com/sopt/now/ui/main/MainActivity.kt | 4 +- .../com/sopt/now/ui/myPage/MyPageFragment.kt | 38 +++++++++------ .../ui/myPage/viewModel/MyPageViewModel.kt | 46 ++++++++++++++++++- app/src/main/res/layout/fragment_my_page.xml | 6 +-- 11 files changed, 109 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 39e86b6..507b979 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -5,7 +5,6 @@ - - - - + diff --git a/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt b/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt index a7d2416..a712ac8 100644 --- a/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt +++ b/app/src/main/java/com/sopt/now/data/model/ResponseInfoDto.kt @@ -5,6 +5,16 @@ import kotlinx.serialization.Serializable @Serializable data class ResponseInfoDto( + @SerialName("code") + val code: Int, + @SerialName("message") + val message: String, + @SerialName("data") + val data: UserInfo, +) + +@Serializable +data class UserInfo( @SerialName("authenticationId") val authenticationId: String, @SerialName("nickname") diff --git a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt index 3e765d9..17016aa 100644 --- a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt +++ b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt @@ -6,15 +6,20 @@ import com.sopt.now.data.network.AuthService import com.sopt.now.data.network.FollowerService import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient import retrofit2.Retrofit object ApiFactory { private const val BASE_URL: String = BuildConfig.AUTH_BASE_URL private const val FOLLOWER_URL: String = BuildConfig.FOLLOWER_URL + private val interceptorClient = OkHttpClient().newBuilder() + .addInterceptor(AuthInterceptor("100")).build() + val baseRetrofit: Retrofit by lazy { Retrofit.Builder() .baseUrl(BASE_URL) + .client(interceptorClient) .addConverterFactory(Json.asConverterFactory("application/json".toMediaType())) .build() } diff --git a/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt new file mode 100644 index 0000000..db7de88 --- /dev/null +++ b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt @@ -0,0 +1,14 @@ +package com.sopt.now.data.module + +import okhttp3.Interceptor +import okhttp3.Response + +class AuthInterceptor(private val memberId: String) : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val originalRequest = chain.request() + val newRequest = originalRequest.newBuilder() + .addHeader("memberId", memberId) + .build() + return chain.proceed(newRequest) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/data/network/AuthService.kt b/app/src/main/java/com/sopt/now/data/network/AuthService.kt index 77127b9..6d2995e 100644 --- a/app/src/main/java/com/sopt/now/data/network/AuthService.kt +++ b/app/src/main/java/com/sopt/now/data/network/AuthService.kt @@ -22,5 +22,6 @@ interface AuthService { ): Call @GET("member/info") - fun memberInfo(): Call + fun memberInfo( + ): Call } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt b/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt index 5914b41..bcdaa64 100644 --- a/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/home/HomeFragment.kt @@ -37,7 +37,6 @@ class HomeFragment : Fragment() { super.onViewCreated(view, savedInstanceState) setCollect() - setAdapter() } override fun onDestroy() { diff --git a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt index b98cff4..2a9a139 100644 --- a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt @@ -32,7 +32,7 @@ class HomeViewModel : ViewModel() { } private fun fetchFollowerList() { - followerService.getUserList(page = 2).enqueue(object : Callback { + followerService.getUserList(page = 0).enqueue(object : Callback { override fun onResponse( call: Call, response: Response, diff --git a/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt b/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt index 79412a8..56805e7 100644 --- a/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/main/MainActivity.kt @@ -66,9 +66,7 @@ class MainActivity : AppCompatActivity() { R.id.menu_my_page -> { replaceFragment( - MyPageFragment( - id, nickname, phoneNumber - ) + MyPageFragment() ) true } diff --git a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt index 1ff9a5c..4f16028 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/MyPageFragment.kt @@ -5,19 +5,23 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import com.sopt.now.databinding.FragmentMyPageBinding +import com.sopt.now.ui.myPage.viewModel.MyPageViewModel +import kotlinx.coroutines.launch -class MyPageFragment( - private val id: String, - private val nickname: String, - private val phoneNumber: String, -) : Fragment() { +class MyPageFragment : Fragment() { private var _binding: FragmentMyPageBinding? = null private val binding get() = requireNotNull(_binding) { "바인딩 객체 미생성" } + private val viewModel by viewModels() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -30,19 +34,25 @@ class MyPageFragment( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - setMainProfile(id, nickname, phoneNumber) - } - - private fun setMainProfile(id: String, nickname: String, phoneNumber: String) { - with(binding) { - tvMyId.text = id - tvMyNickname.text = nickname - tvMyPhoneNumber.text = phoneNumber - } + setCollect() } override fun onDestroy() { super.onDestroy() _binding = null } + + private fun setCollect() { + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.infoState.collect { info -> + with(binding) { + tvMyId.text = info.data.authenticationId + tvMyNickname.text = info.data.nickname + tvMyPhoneNumber.text = info.data.phone + } + } + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt index 76ed1ee..e70e70d 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt @@ -1,12 +1,56 @@ package com.sopt.now.ui.myPage.viewModel +import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.data.model.ResponseInfoDto +import com.sopt.now.data.model.UserInfo import com.sopt.now.data.module.ServicePool import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class MyPageViewModel : ViewModel() { private val authService by lazy { ServicePool.authService } - private val _infoState = MutableStateFlow(ResponseInfoDto) + private val _infoState = + MutableStateFlow( + ResponseInfoDto( + code = 0, + message = "", + data = UserInfo(authenticationId = "", nickname = "", phone = "") + ) + ) + val infoState = _infoState.asStateFlow() + + init { + fetchInfo() + } + + private fun fetchInfo() { + authService.memberInfo().enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response, + ) { + if (response.isSuccessful) { + val data = response.body() + if (data != null) { + _infoState.update { + data + } + Log.d("MyPage", "$data") + } else { + Log.d("MyPage", "$data") + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + Log.e("MyPageError", "${t.message}") + } + }) + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_my_page.xml b/app/src/main/res/layout/fragment_my_page.xml index e8d8b95..5de1d86 100644 --- a/app/src/main/res/layout/fragment_my_page.xml +++ b/app/src/main/res/layout/fragment_my_page.xml @@ -16,14 +16,14 @@ From 11e74758eb3b827b7a981c9c8592e876a89727f9 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 14:51:23 +0900 Subject: [PATCH 08/13] =?UTF-8?q?[Feat]=20myInfo=20Get=20API=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sopt/now/data/module/ApiFactory.kt | 2 +- .../main/java/com/sopt/now/data/module/AuthInterceptor.kt | 7 +++++-- .../com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt | 3 --- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt index 17016aa..b293622 100644 --- a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt +++ b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt @@ -14,7 +14,7 @@ object ApiFactory { private const val FOLLOWER_URL: String = BuildConfig.FOLLOWER_URL private val interceptorClient = OkHttpClient().newBuilder() - .addInterceptor(AuthInterceptor("100")).build() + .addInterceptor(AuthInterceptor()).build() val baseRetrofit: Retrofit by lazy { Retrofit.Builder() diff --git a/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt index db7de88..da36554 100644 --- a/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt +++ b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt @@ -3,12 +3,15 @@ package com.sopt.now.data.module import okhttp3.Interceptor import okhttp3.Response -class AuthInterceptor(private val memberId: String) : Interceptor { +class AuthInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { val originalRequest = chain.request() + val newRequest = originalRequest.newBuilder() - .addHeader("memberId", memberId) + .addHeader("memberId", "403") .build() + return chain.proceed(newRequest) } } \ No newline at end of file diff --git a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt index e70e70d..f8ced4e 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt @@ -41,9 +41,6 @@ class MyPageViewModel : ViewModel() { _infoState.update { data } - Log.d("MyPage", "$data") - } else { - Log.d("MyPage", "$data") } } } From d5b2ee89f4de5a8a406aa7782e662a24d5120e9e Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 3 May 2024 14:56:42 +0900 Subject: [PATCH 09/13] =?UTF-8?q?[Feat]=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20(#9)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt | 2 +- app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt index da36554..ac96a76 100644 --- a/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt +++ b/app/src/main/java/com/sopt/now/data/module/AuthInterceptor.kt @@ -9,7 +9,7 @@ class AuthInterceptor : Interceptor { val originalRequest = chain.request() val newRequest = originalRequest.newBuilder() - .addHeader("memberId", "403") + .addHeader("memberId", "495") .build() return chain.proceed(newRequest) diff --git a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt index 0a42cdc..d86a6a1 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt @@ -86,7 +86,7 @@ class SignUpActivity : AppCompatActivity() { private fun isPwValid(): Boolean { val pwText = binding.edtSignUpPw.text.toString() return pwText.isNotBlank() && pwText.length >= MIN_LENGTH_PASSWORD - && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z\\[0-9]\\\$@!%*#?&.]{8,20}\$").matches( + && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z[0-9]\$@!%*#?&.]{8,20}\$").matches( pwText ) } From 680a8b101420d31a83f456791702b9e8d8f6dc16 Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 23 May 2024 22:11:19 +0900 Subject: [PATCH 10/13] =?UTF-8?q?[Feat]=20map=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sopt/now/ui/home/viewModel/HomeViewModel.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt index 2a9a139..7d6c591 100644 --- a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt @@ -54,14 +54,12 @@ class HomeViewModel : ViewModel() { } fun mapFollowersToFriendList(followers: List) { - for (follower in followers) { - friendList.add( - ItemData.Friend( - profileImage = follower.avatar, - name = "${follower.firstName} ${follower.lastName}", - description = follower.email - ) + friendList.addAll(followers.map { follower -> + ItemData.Friend( + profileImage = follower.avatar, + name = "${follower.firstName} ${follower.lastName}", + description = follower.email ) - } + }) } } \ No newline at end of file From 1cbb5e0bf0130d602005a9e3e8cd435ccf5b367d Mon Sep 17 00:00:00 2001 From: arinming Date: Thu, 23 May 2024 22:21:26 +0900 Subject: [PATCH 11/13] =?UTF-8?q?[Refactor]=20string=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=20=EC=B6=94=EA=B0=80,=20toast=20message=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=88=98=EC=A0=95=20(#10)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sopt/now/ui/signUp/SignUpActivity.kt | 13 +++++-------- app/src/main/res/values/strings.xml | 3 +++ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt index d86a6a1..1cdbbd4 100644 --- a/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt +++ b/app/src/main/java/com/sopt/now/ui/signUp/SignUpActivity.kt @@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle +import com.sopt.now.R import com.sopt.now.data.model.RequestSignUpDto import com.sopt.now.databinding.ActivitySignUpBinding import com.sopt.now.ui.signUp.viewModel.SignUpViewModel @@ -41,7 +42,7 @@ class SignUpActivity : AppCompatActivity() { binding.btnSignUp.setOnClickListener { when { isInputValid() -> viewModel.signUp(getSignUpRequestDto()) - else -> showToastMessage("모든 정보를 입력해주세요.") + else -> showToastMessage(R.string.toast_sign_up_fail) } } } @@ -51,7 +52,6 @@ class SignUpActivity : AppCompatActivity() { repeatOnLifecycle(Lifecycle.State.STARTED) { viewModel.signUpState.collect { signUpState -> if (signUpState.message.isNotBlank()) { - showToastMessage(signUpState.message) if (signUpState.isSuccess) { handleValidInput() } @@ -86,9 +86,6 @@ class SignUpActivity : AppCompatActivity() { private fun isPwValid(): Boolean { val pwText = binding.edtSignUpPw.text.toString() return pwText.isNotBlank() && pwText.length >= MIN_LENGTH_PASSWORD - && Regex("^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[\$@!%*#?&.])[A-Za-z[0-9]\$@!%*#?&.]{8,20}\$").matches( - pwText - ) } private fun isNicknameValid(): Boolean { @@ -98,15 +95,15 @@ class SignUpActivity : AppCompatActivity() { private fun isPhoneNumberValid(): Boolean { val phoneNumberText = binding.edtSignUpPhoneNumber.text.toString() - return phoneNumberText.isNotBlank() && Regex("^010-\\d{4}-\\d{4}\$").matches(phoneNumberText) + return phoneNumberText.isNotBlank() } private fun handleValidInput() { - showToastMessage("회원가입이 완료되었습니다.") + showToastMessage(R.string.toast_sign_up_success) finish() } - private fun showToastMessage(text: String) { + private fun showToastMessage(text: Int) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show() } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index adf55e4..e270d75 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,4 +26,7 @@ 이름 소개 + + 모든 정보를 입력해주세요. + 회원가입이 완료되었습니다. \ No newline at end of file From 0dac1b4c4a5c7fcfcc955cc48bc0a2c31d1972c4 Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 24 May 2024 17:11:33 +0900 Subject: [PATCH 12/13] =?UTF-8?q?[Refactor]=20Log=20=EC=82=AD=EC=A0=9C=20(?= =?UTF-8?q?#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sopt/now/data/module/ApiFactory.kt | 2 +- .../main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt | 3 --- .../java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt | 2 -- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt index b293622..41a0abf 100644 --- a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt +++ b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt @@ -1,7 +1,7 @@ package com.sopt.now.data.module import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory -import com.sopt.now.BuildConfig +import com.sopt.now.compose.BuildConfig import com.sopt.now.data.network.AuthService import com.sopt.now.data.network.FollowerService import kotlinx.serialization.json.Json diff --git a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt index 7d6c591..0c37aa6 100644 --- a/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/home/viewModel/HomeViewModel.kt @@ -1,6 +1,5 @@ package com.sopt.now.ui.home.viewModel -import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.R import com.sopt.now.data.model.ItemData @@ -42,13 +41,11 @@ class HomeViewModel : ViewModel() { if (data != null) { _followerState.value = data mapFollowersToFriendList(data) - Log.d("FOLLOWER", "$data") } } } override fun onFailure(call: Call, t: Throwable) { - Log.e("HomeError", "${t.message}") } }) } diff --git a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt index f8ced4e..9b55f15 100644 --- a/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt +++ b/app/src/main/java/com/sopt/now/ui/myPage/viewModel/MyPageViewModel.kt @@ -1,6 +1,5 @@ package com.sopt.now.ui.myPage.viewModel -import android.util.Log import androidx.lifecycle.ViewModel import com.sopt.now.data.model.ResponseInfoDto import com.sopt.now.data.model.UserInfo @@ -46,7 +45,6 @@ class MyPageViewModel : ViewModel() { } override fun onFailure(call: Call, t: Throwable) { - Log.e("MyPageError", "${t.message}") } }) } From 272f70790cfb90c35cd7f79bb1b7625cd30defcf Mon Sep 17 00:00:00 2001 From: arinming Date: Fri, 24 May 2024 17:17:34 +0900 Subject: [PATCH 13/13] =?UTF-8?q?[Feat]=20createBaseRetrofit=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#14)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/sopt/now/data/module/ApiFactory.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt index 41a0abf..9c7ae56 100644 --- a/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt +++ b/app/src/main/java/com/sopt/now/data/module/ApiFactory.kt @@ -8,6 +8,7 @@ import kotlinx.serialization.json.Json import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient import retrofit2.Retrofit +import retrofit2.create object ApiFactory { private const val BASE_URL: String = BuildConfig.AUTH_BASE_URL @@ -31,11 +32,11 @@ object ApiFactory { .build() } - inline fun createBase(): T = baseRetrofit.create(T::class.java) - inline fun createFollower(): T = followerRetrofit.create(T::class.java) + inline fun createBaseRetrofit(): T = baseRetrofit.create() + inline fun createFollowerRetrofit(): T = followerRetrofit.create() } object ServicePool { - val authService = ApiFactory.createBase() - val followerService = ApiFactory.createFollower() + val authService = ApiFactory.createBaseRetrofit() + val followerService = ApiFactory.createFollowerRetrofit() } \ No newline at end of file