Skip to content

Commit

Permalink
[feature/fix-dependencies] 뷰모델/도메인단 코드 리팩토링 (#394)
Browse files Browse the repository at this point in the history
* remove services in authrepository

* remove datastore dependency in authrepository

* firebase token 가져오는 로직 suspend 하게 변경

* mypage viewmodel에서 repository만 참조하게 변경
  • Loading branch information
l2hyunwoo authored Oct 13, 2023
1 parent bbf2454 commit 7ad8d46
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,51 +1,47 @@
package org.sopt.official.data.repository

import org.sopt.official.common.di.Auth
import org.sopt.official.data.model.request.LogOutRequest
import org.sopt.official.data.model.request.RefreshRequest
import org.sopt.official.data.model.response.LogOutResponse
import org.sopt.official.data.persistence.SoptDataStore
import org.sopt.official.data.service.AuthService
import org.sopt.official.data.source.api.auth.LocalAuthDataSource
import org.sopt.official.data.source.api.auth.RemoteAuthDataSource
import org.sopt.official.domain.entity.auth.Token
import org.sopt.official.domain.entity.auth.UserStatus
import org.sopt.official.domain.repository.AuthRepository
import javax.inject.Inject

class AuthRepositoryImpl @Inject constructor(
@Auth private val service: AuthService,
@Auth(false) private val noneAuthService: AuthService,
private val dataStore: SoptDataStore
private val remoteAuthDataSource: RemoteAuthDataSource,
private val localAuthDataSource: LocalAuthDataSource,
) : AuthRepository {
override suspend fun refresh(token: String) = runCatching {
noneAuthService.refresh(RefreshRequest(token)).toEntity()
remoteAuthDataSource.refresh(RefreshRequest(token)).toEntity()
}

override fun save(token: Token) {
dataStore.apply {
accessToken = token.accessToken
refreshToken = token.refreshToken
playgroundToken = token.playgroundToken
}
localAuthDataSource.save(token)
}

override fun save(status: UserStatus) {
dataStore.apply {
userStatus = status.value
}
localAuthDataSource.save(status)
}

override suspend fun withdraw() = runCatching {
service.withdraw()
remoteAuthDataSource.withdraw()
}

override suspend fun logout(
pushToken: String
): Result<LogOutResponse> = runCatching {
service.logOut(
remoteAuthDataSource.logout(
LogOutRequest(
platform = "Android",
pushToken = pushToken
)
)
}

override suspend fun clearLocalData() {
localAuthDataSource.clear()
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.official.data.source.api.auth

import org.sopt.official.domain.entity.auth.Token
import org.sopt.official.domain.entity.auth.UserStatus

interface LocalAuthDataSource {
fun save(token: Token)
fun save(status: UserStatus)
fun clear()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.sopt.official.data.source.api.auth

import org.sopt.official.data.model.request.LogOutRequest
import org.sopt.official.data.model.request.RefreshRequest
import org.sopt.official.data.model.response.AuthResponse
import org.sopt.official.data.model.response.LogOutResponse

interface RemoteAuthDataSource {
suspend fun refresh(token: RefreshRequest): AuthResponse
suspend fun withdraw()
suspend fun logout(request: LogOutRequest): LogOutResponse
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.sopt.official.data.source.impl

import org.sopt.official.data.persistence.SoptDataStore
import org.sopt.official.data.source.api.auth.LocalAuthDataSource
import org.sopt.official.domain.entity.auth.Token
import org.sopt.official.domain.entity.auth.UserStatus
import javax.inject.Inject

class DefaultLocalAuthDataSource @Inject constructor(
private val dataStore: SoptDataStore
) : LocalAuthDataSource {
override fun save(token: Token) {
dataStore.apply {
accessToken = token.accessToken
refreshToken = token.refreshToken
playgroundToken = token.playgroundToken
}
}

override fun save(status: UserStatus) {
dataStore.apply {
userStatus = status.value
}
}

override fun clear() {
dataStore.clear()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package org.sopt.official.data.source.impl

import org.sopt.official.common.di.Auth
import org.sopt.official.data.model.request.LogOutRequest
import org.sopt.official.data.model.request.RefreshRequest
import org.sopt.official.data.model.response.AuthResponse
import org.sopt.official.data.model.response.LogOutResponse
import org.sopt.official.data.service.AuthService
import org.sopt.official.data.source.api.auth.RemoteAuthDataSource
import javax.inject.Inject

class DefaultRemoteAuthDataSource @Inject constructor(
@Auth private val service: AuthService,
@Auth(false) private val noneAuthService: AuthService,
) : RemoteAuthDataSource {
override suspend fun refresh(token: RefreshRequest): AuthResponse {
return noneAuthService.refresh(token)
}

override suspend fun withdraw() {
service.withdraw()
}

override suspend fun logout(request: LogOutRequest): LogOutResponse {
return service.logOut(request)
}
}
31 changes: 24 additions & 7 deletions app/src/main/java/org/sopt/official/di/AuthModule.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sopt.official.di

import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
Expand All @@ -10,6 +11,10 @@ import org.sopt.official.common.di.Auth
import org.sopt.official.data.interceptor.AuthInterceptor
import org.sopt.official.data.repository.AuthRepositoryImpl
import org.sopt.official.data.service.AuthService
import org.sopt.official.data.source.api.auth.LocalAuthDataSource
import org.sopt.official.data.source.api.auth.RemoteAuthDataSource
import org.sopt.official.data.source.impl.DefaultLocalAuthDataSource
import org.sopt.official.data.source.impl.DefaultRemoteAuthDataSource
import org.sopt.official.domain.repository.AuthRepository
import retrofit2.Retrofit
import javax.inject.Singleton
Expand All @@ -27,12 +32,24 @@ object AuthModule {
@Auth(false)
fun provideNoneAuthService(@AppRetrofit(false) retrofit: Retrofit): AuthService = retrofit.create(AuthService::class.java)

@Provides
@Singleton
fun provideAuthRepository(repository: AuthRepositoryImpl): AuthRepository = repository
@Module
@InstallIn(SingletonComponent::class)
interface Binder {
@Binds
@Singleton
fun bindAuthRepository(repository: AuthRepositoryImpl): AuthRepository

@Provides
@Singleton
@Auth
fun provideAuthInterceptor(interceptor: AuthInterceptor): Interceptor = interceptor
@Binds
@Singleton
@Auth
fun bindAuthInterceptor(interceptor: AuthInterceptor): Interceptor

@Binds
@Singleton
fun bindRemoteAuthDataSource(dataSource: DefaultRemoteAuthDataSource): RemoteAuthDataSource

@Binds
@Singleton
fun bindLocalAuthDataSource(dataSource: DefaultLocalAuthDataSource): LocalAuthDataSource
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ interface AuthRepository {
fun save(status: UserStatus)
suspend fun withdraw(): Result<Unit>
suspend fun logout(pushToken: String): Result<LogOutResponse>
suspend fun clearLocalData()
}
22 changes: 11 additions & 11 deletions app/src/main/java/org/sopt/official/feature/home/HomeViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.tasks.await
import kotlinx.datetime.Instant
import org.sopt.official.R
import org.sopt.official.domain.entity.UserActiveState
Expand All @@ -39,7 +39,7 @@ import javax.inject.Inject

@HiltViewModel
class HomeViewModel @Inject constructor(
private val mainViewRepository: HomeRepository,
private val homeRepository: HomeRepository,
private val registerPushTokenUseCase: RegisterPushTokenUseCase,
) : ViewModel() {

Expand Down Expand Up @@ -149,7 +149,7 @@ class HomeViewModel @Inject constructor(
fun initHomeUi(userStatus: UserStatus) {
viewModelScope.launch {
if (userStatus != UserStatus.UNAUTHENTICATED) {
mainViewRepository.getMainView()
homeRepository.getMainView()
.onSuccess {
homeUiState.value = it
}
Expand All @@ -175,7 +175,7 @@ class HomeViewModel @Inject constructor(
fun initMainDescription(userStatus: UserStatus) {
viewModelScope.launch {
if (userStatus != UserStatus.UNAUTHENTICATED) {
mainViewRepository.getMainDescription()
homeRepository.getMainDescription()
.onSuccess {
_description.value = it
}
Expand All @@ -185,13 +185,13 @@ class HomeViewModel @Inject constructor(

fun registerPushToken(userStatus: UserStatus) {
if (userStatus == UserStatus.UNAUTHENTICATED) return
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isComplete) {
viewModelScope.launch {
registerPushTokenUseCase.invoke(task.result)
.onFailure { Timber.e(it) }
}
}
viewModelScope.launch {
runCatching {
FirebaseMessaging.getInstance().token.await()
}.onSuccess {
registerPushTokenUseCase(it)
.onFailure(Timber::e)
}.onFailure(Timber::e)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import io.reactivex.rxjava3.processors.BehaviorProcessor
import io.reactivex.rxjava3.subjects.PublishSubject
import kotlinx.coroutines.launch
import org.sopt.official.data.persistence.SoptDataStore
import kotlinx.coroutines.tasks.await
import org.sopt.official.domain.repository.AuthRepository
import org.sopt.official.feature.mypage.model.MyPageUiState
import org.sopt.official.stamp.domain.repository.StampRepository
Expand All @@ -16,7 +16,6 @@ import javax.inject.Inject

@HiltViewModel
class MyPageViewModel @Inject constructor(
private val dataStore: SoptDataStore,
private val authRepository: AuthRepository,
private val stampRepository: StampRepository,
) : ViewModel() {
Expand All @@ -26,25 +25,23 @@ class MyPageViewModel @Inject constructor(

fun logOut() {
viewModelScope.launch {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task ->
if (task.isComplete) {
viewModelScope.launch {
authRepository.logout(task.result)
.onSuccess {
dataStore.clear()
restartSignal.onNext(true)
}
.onFailure { Timber.e(it) }
}
}
runCatching {
FirebaseMessaging.getInstance().token.await()
}.onSuccess {
authRepository.logout(it)
.onSuccess {
authRepository.clearLocalData()
restartSignal.onNext(true)
}.onFailure { error -> Timber.e(error) }
}.onFailure {
Timber.e(it)
}
}
}

fun resetSoptamp() {
viewModelScope.launch {
stampRepository.deleteAllStamps()
.onSuccess {}
.onFailure { Timber.e(it) }
}
}
Expand Down

0 comments on commit 7ad8d46

Please sign in to comment.