diff --git a/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/AuthService.kt b/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/AuthService.kt index 2de427ba2..0247f7b40 100644 --- a/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/AuthService.kt +++ b/android/app/src/main/java/com/now/naaga/data/remote/retrofit/service/AuthService.kt @@ -4,6 +4,7 @@ import com.now.naaga.data.remote.dto.NaagaAuthDto import com.now.naaga.data.remote.dto.PlatformAuthDto import retrofit2.Response import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.POST interface AuthService { @@ -11,4 +12,7 @@ interface AuthService { suspend fun requestAuth( @Body platformAuthDto: PlatformAuthDto, ): Response + + @DELETE("/auth/unlink") + suspend fun withdrawalMember(): Response } diff --git a/android/app/src/main/java/com/now/naaga/data/repository/DefaultAuthRepository.kt b/android/app/src/main/java/com/now/naaga/data/repository/DefaultAuthRepository.kt index da7e225e9..3479e45e0 100644 --- a/android/app/src/main/java/com/now/naaga/data/repository/DefaultAuthRepository.kt +++ b/android/app/src/main/java/com/now/naaga/data/repository/DefaultAuthRepository.kt @@ -6,13 +6,14 @@ import com.now.naaga.data.local.AuthDataSource import com.now.naaga.data.mapper.toDto import com.now.naaga.data.remote.retrofit.ServicePool.authService import com.now.naaga.util.getValueOrThrow +import com.now.naaga.util.unlinkWithKakao import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext class DefaultAuthRepository( private val authDataSource: AuthDataSource, - private val dispatcher: CoroutineDispatcher = Dispatchers.IO + private val dispatcher: CoroutineDispatcher = Dispatchers.IO, ) : AuthRepository { override suspend fun getToken(platformAuth: PlatformAuth): Boolean { @@ -27,4 +28,9 @@ class DefaultAuthRepository( return@withContext false } } + + override suspend fun withdrawalMember() { + authService.withdrawalMember() + unlinkWithKakao() + } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/login/LoginActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/login/LoginActivity.kt index e81fd810d..0616df5e7 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/login/LoginActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/login/LoginActivity.kt @@ -2,6 +2,8 @@ package com.now.naaga.presentation.login import android.content.Context import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.os.Bundle import android.widget.Toast import androidx.appcompat.app.AppCompatActivity @@ -75,5 +77,12 @@ class LoginActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytics fun getIntent(context: Context): Intent { return Intent(context, LoginActivity::class.java) } + + fun getIntentWithTop(context: Context): Intent { + return Intent(context, LoginActivity::class.java).apply { + addFlags(FLAG_ACTIVITY_NEW_TASK) + addFlags(FLAG_ACTIVITY_CLEAR_TASK) + } + } } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/setting/SettingActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/setting/SettingActivity.kt index ed6a8d99d..d955e54f6 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/setting/SettingActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/setting/SettingActivity.kt @@ -3,9 +3,14 @@ package com.now.naaga.presentation.setting import android.content.Context import android.content.Intent import android.os.Bundle +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.ViewModelProvider +import com.now.naaga.R +import com.now.naaga.data.throwable.DataThrowable import com.now.naaga.databinding.ActivitySettingBinding +import com.now.naaga.presentation.login.LoginActivity +import com.now.naaga.presentation.onadventure.NaagaAlertDialog class SettingActivity : AppCompatActivity() { private lateinit var binding: ActivitySettingBinding @@ -17,6 +22,7 @@ class SettingActivity : AppCompatActivity() { setContentView(binding.root) initViewModel() setClickListeners() + subscribe() } private fun initViewModel() { @@ -28,9 +34,54 @@ class SettingActivity : AppCompatActivity() { binding.ivSettingBack.setOnClickListener { finish() } + + binding.tvSettingUnlink.setOnClickListener { + showWithdrawalDialog() + } + } + + private fun subscribe() { + viewModel.withdrawalStatus.observe(this) { status -> + if (status == true) { + shortToast(getString(R.string.setting_withdrawal_success_message)) + navigateLogin() + } + } + + viewModel.errorMessage.observe(this) { error: DataThrowable -> + when (error.code) { + WRONG_AUTH_ERROR_CODE -> shortToast(getString(R.string.setting_wrong_error_message)) + EXPIRATION_AUTH_ERROR_CODE -> shortToast(getString(R.string.setting_expiration_error_message)) + } + } + } + + private fun navigateLogin() { + startActivity(LoginActivity.getIntentWithTop(this)) + finish() + } + + private fun shortToast(message: String) { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show() + } + + private fun showWithdrawalDialog() { + NaagaAlertDialog.Builder().build( + title = getString(R.string.withdrawal_dialog_title), + description = getString(R.string.withdrawal_dialog_description), + positiveText = getString(R.string.withdrawal_dialog_negative), + negativeText = getString(R.string.withdrawal_dialog_positive), + positiveAction = { }, + negativeAction = { viewModel.withdrawalMember() }, + ).show(supportFragmentManager, WITHDRAWAL) } companion object { + private const val WITHDRAWAL = "WITHDRAWAL" + + private const val WRONG_AUTH_ERROR_CODE = 101 + private const val EXPIRATION_AUTH_ERROR_CODE = 102 + fun getIntent(context: Context): Intent { return Intent(context, SettingActivity::class.java) } diff --git a/android/app/src/main/java/com/now/naaga/presentation/setting/SettingViewModel.kt b/android/app/src/main/java/com/now/naaga/presentation/setting/SettingViewModel.kt index 985c3caa2..24712229e 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/setting/SettingViewModel.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/setting/SettingViewModel.kt @@ -1,13 +1,32 @@ package com.now.naaga.presentation.setting +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import androidx.lifecycle.viewModelScope import com.now.domain.repository.AuthRepository import com.now.naaga.NaagaApplication.DependencyContainer.authDataSource import com.now.naaga.data.repository.DefaultAuthRepository +import com.now.naaga.data.throwable.DataThrowable +import kotlinx.coroutines.launch class SettingViewModel(private val authRepository: AuthRepository) : ViewModel() { + private val _withdrawalStatus = MutableLiveData() + val withdrawalStatus: LiveData = _withdrawalStatus + + private val _errorMessage = MutableLiveData() + val errorMessage: LiveData = _errorMessage + + fun withdrawalMember() { + viewModelScope.launch { + runCatching { authRepository.withdrawalMember() } + .onSuccess { _withdrawalStatus.value = true } + .onFailure { _errorMessage.value = it as DataThrowable } + } + } + companion object { val Factory = SettingFactory(DefaultAuthRepository(authDataSource)) diff --git a/android/app/src/main/java/com/now/naaga/util/KakaoLoginUtil.kt b/android/app/src/main/java/com/now/naaga/util/KakaoLoginUtil.kt index 20e78b956..e98de10fe 100644 --- a/android/app/src/main/java/com/now/naaga/util/KakaoLoginUtil.kt +++ b/android/app/src/main/java/com/now/naaga/util/KakaoLoginUtil.kt @@ -7,9 +7,11 @@ import com.kakao.sdk.common.model.ClientError import com.kakao.sdk.common.model.ClientErrorCause import com.kakao.sdk.user.UserApiClient -private const val KAKAO_LOGIN_LOG_TAG = "kakao login" +const val KAKAO_LOGIN_LOG_TAG = "kakao login" private const val KAKAO_LOGIN_FAIL_MESSAGE = "카카오계정으로 로그인 실패" private const val KAKAO_LOGIN_SUCCESS_MESSAGE = "카카오계정으로 로그인 성공" +private const val KAKAO_UNLINK_FAIL_MESSAGE = "연결 끊기 실패" +private const val KAKAO_UNLINK_SUCCESS_MESSAGE = "연결 끊기 성공. SDK에서 토큰 삭제 됨" private fun getLoginCallback(doNextAction: (token: String) -> Unit): (OAuthToken?, Throwable?) -> Unit { val callback: (OAuthToken?, Throwable?) -> Unit = { token, error -> @@ -50,3 +52,13 @@ fun loginWithKakao(context: Context, doNextAction: (token: String) -> Unit) { UserApiClient.instance.loginWithKakaoAccount(context, callback = callback) } } + +fun unlinkWithKakao() { + UserApiClient.instance.unlink { error -> + if (error != null) { + Log.e(KAKAO_LOGIN_LOG_TAG, KAKAO_UNLINK_FAIL_MESSAGE, error) + } else { + Log.i(KAKAO_LOGIN_LOG_TAG, KAKAO_UNLINK_SUCCESS_MESSAGE) + } + } +} diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 87d221dde..8f0f452f6 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -105,4 +105,15 @@ 근방에 다른 미션장소가 존재해서 추가할 수 없어요! 전송에 실패했어요! 다시 시도해주세요! 모든 정보를 입력해주세요. + + + "성공적으로 회원 탈퇴 되었습니다." + "인증 정보가 잘 못 되었어요!" + "인증 정보가 만료 되었어요!" + + + 정말 회원 탈퇴를 하시겠습니까? + 나아가와 함께 즐거운 모험을 계속해보세요! + + 아니요 diff --git a/android/domain/src/main/java/com/now/domain/repository/AuthRepository.kt b/android/domain/src/main/java/com/now/domain/repository/AuthRepository.kt index 045223603..286986b0f 100644 --- a/android/domain/src/main/java/com/now/domain/repository/AuthRepository.kt +++ b/android/domain/src/main/java/com/now/domain/repository/AuthRepository.kt @@ -6,4 +6,6 @@ interface AuthRepository { suspend fun getToken( platformAuth: PlatformAuth, ): Boolean + + suspend fun withdrawalMember() }