diff --git a/app/src/main/java/com/terning/point/di/DataSourceModule.kt b/app/src/main/java/com/terning/point/di/DataSourceModule.kt index d5ad31320..ff0aff976 100644 --- a/app/src/main/java/com/terning/point/di/DataSourceModule.kt +++ b/app/src/main/java/com/terning/point/di/DataSourceModule.kt @@ -3,15 +3,17 @@ package com.terning.point.di import com.terning.data.datasource.AuthDataSource import com.terning.data.datasource.CalendarDataSource import com.terning.data.datasource.FilteringDataSource -import com.terning.data.datasource.InternDataSource import com.terning.data.datasource.HomeDataSource +import com.terning.data.datasource.InternDataSource +import com.terning.data.datasource.MyPageDataSource import com.terning.data.datasource.SearchDataSource import com.terning.data.datasource.TokenReissueDataSource import com.terning.data.datasourceimpl.AuthDataSourceImpl import com.terning.data.datasourceimpl.CalendarDataSourceImpl import com.terning.data.datasourceimpl.FilteringDataSourceImpl -import com.terning.data.datasourceimpl.InternDataSourceImpl import com.terning.data.datasourceimpl.HomeDataSourceImpl +import com.terning.data.datasourceimpl.InternDataSourceImpl +import com.terning.data.datasourceimpl.MyPageDataSourceImpl import com.terning.data.datasourceimpl.SearchDataSourceImpl import com.terning.data.datasourceimpl.TokenReissueDataSourceImpl import dagger.Binds @@ -53,4 +55,8 @@ abstract class DataSourceModule { @Binds @Singleton abstract fun bindHomeDataSource(homeDataSourceImpl: HomeDataSourceImpl): HomeDataSource + + @Binds + @Singleton + abstract fun bindMyPageDataSource(myPageDataSourceImpl: MyPageDataSourceImpl): MyPageDataSource } \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/RepositoryModule.kt b/app/src/main/java/com/terning/point/di/RepositoryModule.kt index 619294824..8dee61198 100644 --- a/app/src/main/java/com/terning/point/di/RepositoryModule.kt +++ b/app/src/main/java/com/terning/point/di/RepositoryModule.kt @@ -3,16 +3,18 @@ package com.terning.point.di import com.terning.data.repositoryimpl.AuthRepositoryImpl import com.terning.data.repositoryimpl.CalendarRepositoryImpl import com.terning.data.repositoryimpl.FilteringRepositoryImpl -import com.terning.data.repositoryimpl.InternRepositoryImpl import com.terning.data.repositoryimpl.HomeRepositoryImpl +import com.terning.data.repositoryimpl.InternRepositoryImpl +import com.terning.data.repositoryimpl.MyPageRepositoryImpl import com.terning.data.repositoryimpl.SearchRepositoryImpl import com.terning.data.repositoryimpl.TokenReissueRepositoryImpl import com.terning.data.repositoryimpl.TokenRepositoryImpl import com.terning.domain.repository.AuthRepository import com.terning.domain.repository.CalendarRepository import com.terning.domain.repository.FilteringRepository -import com.terning.domain.repository.InternRepository import com.terning.domain.repository.HomeRepository +import com.terning.domain.repository.InternRepository +import com.terning.domain.repository.MyPageRepository import com.terning.domain.repository.SearchRepository import com.terning.domain.repository.TokenReissueRepository import com.terning.domain.repository.TokenRepository @@ -57,4 +59,8 @@ abstract class RepositoryModule { @Binds @Singleton abstract fun bindHomeRepository(homeRepositoryImpl: HomeRepositoryImpl): HomeRepository + + @Binds + @Singleton + abstract fun bindMyPageRepository(myPageRepositoryImpl: MyPageRepositoryImpl): MyPageRepository } \ No newline at end of file diff --git a/app/src/main/java/com/terning/point/di/ServiceModule.kt b/app/src/main/java/com/terning/point/di/ServiceModule.kt index 96c52a2eb..fd6b252b2 100644 --- a/app/src/main/java/com/terning/point/di/ServiceModule.kt +++ b/app/src/main/java/com/terning/point/di/ServiceModule.kt @@ -2,9 +2,10 @@ package com.terning.point.di import com.terning.data.service.AuthService import com.terning.data.service.CalendarService -import com.terning.data.service.InternService import com.terning.data.service.FilteringService import com.terning.data.service.HomeService +import com.terning.data.service.InternService +import com.terning.data.service.MyPageService import com.terning.data.service.SearchService import com.terning.data.service.TokenReissueService import com.terning.point.di.qualifier.JWT @@ -55,4 +56,9 @@ object ServiceModule { @Singleton fun provideHomeService(@JWT retrofit: Retrofit): HomeService = retrofit.create(HomeService::class.java) + + @Provides + @Singleton + fun provideMyPageService(@JWT retrofit: Retrofit): MyPageService = + retrofit.create(MyPageService::class.java) } \ No newline at end of file diff --git a/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageLogoutBottomSheet.kt b/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageLogoutBottomSheet.kt index dbe1469a9..0cccd2206 100644 --- a/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageLogoutBottomSheet.kt +++ b/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageLogoutBottomSheet.kt @@ -48,12 +48,7 @@ fun MyPageLogoutBottomSheet( cornerRadius = 10.dp, text = R.string.my_page_logout_button, onButtonClick = { - scope.launch { sheetState.hide() } - .invokeOnCompletion { - if (!sheetState.isVisible) { - onLogoutClick() - } - } + onLogoutClick() }, modifier = modifier.padding( start = 24.dp, diff --git a/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageQuitBottomSheet.kt b/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageQuitBottomSheet.kt index c77bc397d..fe722d1aa 100644 --- a/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageQuitBottomSheet.kt +++ b/core/src/main/java/com/terning/core/designsystem/component/bottomsheet/MyPageQuitBottomSheet.kt @@ -69,12 +69,7 @@ fun MyPageQuitBottomSheet( cornerRadius = 10.dp, text = R.string.my_page_back_button, onButtonClick = { - scope.launch { sheetState.hide() } - .invokeOnCompletion { - if (!sheetState.isVisible) { - onDismiss() - } - } + onDismiss() }, modifier = modifier.padding( start = 24.dp, diff --git a/data/src/main/java/com/terning/data/datasource/MyPageDataSource.kt b/data/src/main/java/com/terning/data/datasource/MyPageDataSource.kt new file mode 100644 index 000000000..aec35848d --- /dev/null +++ b/data/src/main/java/com/terning/data/datasource/MyPageDataSource.kt @@ -0,0 +1,7 @@ +package com.terning.data.datasource + +import com.terning.data.dto.NonDataBaseResponse + +interface MyPageDataSource { + suspend fun postLogout(): NonDataBaseResponse +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/datasourceimpl/MyPageDataSourceImpl.kt b/data/src/main/java/com/terning/data/datasourceimpl/MyPageDataSourceImpl.kt new file mode 100644 index 000000000..d884be7fc --- /dev/null +++ b/data/src/main/java/com/terning/data/datasourceimpl/MyPageDataSourceImpl.kt @@ -0,0 +1,12 @@ +package com.terning.data.datasourceimpl + +import com.terning.data.datasource.MyPageDataSource +import com.terning.data.dto.NonDataBaseResponse +import com.terning.data.service.MyPageService +import javax.inject.Inject + +class MyPageDataSourceImpl @Inject constructor( + private val myPageService: MyPageService +) : MyPageDataSource { + override suspend fun postLogout(): NonDataBaseResponse = myPageService.postLogout() +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/repositoryimpl/MyPageRepositoryImpl.kt b/data/src/main/java/com/terning/data/repositoryimpl/MyPageRepositoryImpl.kt new file mode 100644 index 000000000..580294a1d --- /dev/null +++ b/data/src/main/java/com/terning/data/repositoryimpl/MyPageRepositoryImpl.kt @@ -0,0 +1,14 @@ +package com.terning.data.repositoryimpl + +import com.terning.data.datasource.MyPageDataSource +import com.terning.domain.repository.MyPageRepository +import javax.inject.Inject + +class MyPageRepositoryImpl @Inject constructor( + private val myPageDataSource: MyPageDataSource +) : MyPageRepository { + override suspend fun postLogout(): Result = + runCatching { + myPageDataSource.postLogout() + } +} \ No newline at end of file diff --git a/data/src/main/java/com/terning/data/service/MyPageService.kt b/data/src/main/java/com/terning/data/service/MyPageService.kt new file mode 100644 index 000000000..9c73cd98c --- /dev/null +++ b/data/src/main/java/com/terning/data/service/MyPageService.kt @@ -0,0 +1,9 @@ +package com.terning.data.service + +import com.terning.data.dto.NonDataBaseResponse +import retrofit2.http.POST + +interface MyPageService { + @POST("api/v1/auth/logout") + suspend fun postLogout(): NonDataBaseResponse +} \ No newline at end of file diff --git a/domain/src/main/java/com/terning/domain/repository/MyPageRepository.kt b/domain/src/main/java/com/terning/domain/repository/MyPageRepository.kt new file mode 100644 index 000000000..3e2ac65c7 --- /dev/null +++ b/domain/src/main/java/com/terning/domain/repository/MyPageRepository.kt @@ -0,0 +1,5 @@ +package com.terning.domain.repository + +interface MyPageRepository { + suspend fun postLogout() : Result +} \ No newline at end of file diff --git a/feature/build.gradle.kts b/feature/build.gradle.kts index 372c480bb..ecb21af29 100644 --- a/feature/build.gradle.kts +++ b/feature/build.gradle.kts @@ -90,6 +90,7 @@ dependencies { implementation(libs.timber) implementation(libs.ossLicense) implementation(libs.lottie) + implementation(libs.process.phoenix) // Compose Preview debugImplementation(libs.compose.ui.tooling) diff --git a/feature/src/main/java/com/terning/feature/mypage/MyPageRoute.kt b/feature/src/main/java/com/terning/feature/mypage/MyPageRoute.kt index d65f3debb..41173af9a 100644 --- a/feature/src/main/java/com/terning/feature/mypage/MyPageRoute.kt +++ b/feature/src/main/java/com/terning/feature/mypage/MyPageRoute.kt @@ -16,9 +16,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.terning.core.designsystem.component.bottomsheet.MyPageLogoutBottomSheet import com.terning.core.designsystem.component.bottomsheet.MyPageQuitBottomSheet import com.terning.core.designsystem.component.image.TerningImage @@ -30,6 +32,7 @@ import com.terning.core.designsystem.theme.TerningTheme import com.terning.core.designsystem.theme.White import com.terning.core.extension.customShadow import com.terning.core.extension.noRippleClickable +import com.terning.core.state.UiState import com.terning.feature.R import com.terning.feature.mypage.component.MyPageItem @@ -37,6 +40,8 @@ import com.terning.feature.mypage.component.MyPageItem fun MyPageRoute( viewModel: MyPageViewModel = hiltViewModel(), ) { + val state by viewModel.state.collectAsStateWithLifecycle() + val context = LocalContext.current var showLogoutBottomSheet by remember { mutableStateOf(false) } var showQuitBottomSheet by remember { mutableStateOf(false) } @@ -45,8 +50,7 @@ fun MyPageRoute( MyPageLogoutBottomSheet( onDismiss = { showLogoutBottomSheet = false }, onLogoutClick = { - showLogoutBottomSheet = false - viewModel.patchLogout() + viewModel.logoutKakao() }, ) } @@ -55,12 +59,21 @@ fun MyPageRoute( MyPageQuitBottomSheet( onDismiss = { showQuitBottomSheet = false }, onQuitClick = { - showQuitBottomSheet = false viewModel.patchQuit() } ) } + when (state.isSuccess) { + is UiState.Success -> { + viewModel.restartApp(context) + } + + is UiState.Loading -> {} + is UiState.Empty -> {} + is UiState.Failure -> {} + } + MyPageScreen( onLogoutClick = { showLogoutBottomSheet = true }, onQuitClick = { showQuitBottomSheet = true } diff --git a/feature/src/main/java/com/terning/feature/mypage/MyPageState.kt b/feature/src/main/java/com/terning/feature/mypage/MyPageState.kt new file mode 100644 index 000000000..58e86acae --- /dev/null +++ b/feature/src/main/java/com/terning/feature/mypage/MyPageState.kt @@ -0,0 +1,7 @@ +package com.terning.feature.mypage + +import com.terning.core.state.UiState + +data class MyPageState( + val isSuccess: UiState = UiState.Loading +) \ No newline at end of file diff --git a/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt b/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt index 9d440c0aa..fdcbf8c50 100644 --- a/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt +++ b/feature/src/main/java/com/terning/feature/mypage/MyPageViewModel.kt @@ -1,14 +1,63 @@ package com.terning.feature.mypage +import android.content.Context +import android.content.Intent +import android.os.Handler +import android.os.Looper import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.jakewharton.processphoenix.ProcessPhoenix +import com.kakao.sdk.user.UserApiClient +import com.terning.core.state.UiState +import com.terning.domain.repository.MyPageRepository +import com.terning.domain.repository.TokenRepository +import com.terning.feature.main.MainActivity import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class MyPageViewModel @Inject constructor() : ViewModel() { +class MyPageViewModel @Inject constructor( + private val myPageRepository: MyPageRepository, + private val tokenRepository: TokenRepository +) : ViewModel() { - fun patchLogout() { + private val _state: MutableStateFlow = MutableStateFlow(MyPageState()) + val state: StateFlow get() = _state.asStateFlow() + fun logoutKakao() { + UserApiClient.instance.logout { error -> + if (error == null) { + postLogout() + } else { + _state.value = _state.value.copy(isSuccess = UiState.Failure(error.toString())) + } + } + } + + private fun postLogout() { + viewModelScope.launch { + myPageRepository.postLogout().onSuccess { + tokenRepository.clearInfo() + _state.value = _state.value.copy(isSuccess = UiState.Success(true)) + }.onFailure { + _state.value = _state.value.copy(isSuccess = UiState.Failure(it.toString())) + } + } + } + + fun restartApp(context: Context) { + Handler(Looper.getMainLooper()).post { + Handler(Looper.getMainLooper()).post { + ProcessPhoenix.triggerRebirth( + context, + Intent(context, MainActivity::class.java) + ) + } + } } fun patchQuit() {