Skip to content

Commit

Permalink
Merge pull request #278 from Nexters/fix/277
Browse files Browse the repository at this point in the history
Fix/277 유저 정보 관련 안정화 작업
  • Loading branch information
HamBP authored Aug 3, 2024
2 parents f90cb61 + 3b1a75b commit 1f435e4
Show file tree
Hide file tree
Showing 17 changed files with 38 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import javax.inject.Inject
internal class UserDataSource @Inject constructor(
private val userService: UserService,
) {
suspend fun getUser(): UserResponse = userService.getUser()
suspend fun getUser(): UserResponse? {
val response = userService.getUser()
return if (response.isSuccessful) response.body() else null
}

suspend fun signout(request: SignoutRequest) = userService.signout(request)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ package com.nexters.boolti.data.network.api

import com.nexters.boolti.data.network.response.UserResponse
import com.nexters.boolti.domain.request.SignoutRequest
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.HTTP

internal interface UserService {
@GET("/app/api/v1/user")
suspend fun getUser(): UserResponse
suspend fun getUser(): Response<UserResponse>

@HTTP(method = "DELETE", path = "/app/api/v1/user", hasBody = true)
suspend fun signout(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,13 @@ internal class AuthRepositoryImpl @Inject constructor(
authDataSource.localLogout()
}

override fun getUserAndCache(): Flow<User> = flow {
override fun getUserAndCache(): Flow<User?> = flow {
val response = userDateSource.getUser()
authDataSource.updateUser(response)
emit(response.toDomain())
response?.let {
authDataSource.updateUser(it)
}

emit(response?.toDomain())
}

override suspend fun sendFcmToken(): Result<Unit> = deviceTokenDataSource.sendFcmToken()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ interface AuthRepository {
suspend fun logout(): Result<Unit>
suspend fun signUp(signUpRequest: SignUpRequest): Result<Unit>
suspend fun signout(request: SignoutRequest): Result<Unit>
fun getUserAndCache(): Flow<User>
fun getUserAndCache(): Flow<User?>
suspend fun sendFcmToken(): Result<Unit>

val loggedIn: Flow<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ import javax.inject.Inject
class GetUserUsecase @Inject constructor(
private val authRepository: AuthRepository,
) {
operator fun invoke(): User = runBlocking { authRepository.getUserAndCache().first() }
operator fun invoke(): User? = runBlocking { authRepository.getUserAndCache().first() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class GiftViewModel @Inject constructor(
private val giftRepository: GiftRepository,
private val getRefundPolicyUseCase: GetRefundPolicyUsecase,
) : BaseViewModel() {
private val userId = getUserUseCase().id
private val userId = checkNotNull(getUserUseCase()?.id) {
"[GiftViewModel] 사용자 정보가 없습니다."
}
val showId: String = requireNotNull(savedStateHandle["showId"])
val salesTicketTypeId: String = requireNotNull(savedStateHandle["salesTicketId"])
private val ticketCount: Int = savedStateHandle["ticketCount"] ?: 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ fun HomeScreen(
ShowScreen(
modifier = modifier.padding(innerPadding),
onClickShowItem = onClickShowItem,
navigateToReservations = navigateToReservations,
navigateToBusiness = navigateToBusiness,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ class HomeViewModel @Inject constructor(
private var pendingGiftUuid: String? = null

init {
initUserInfo()
fetchUserInfo()
sendFcmToken()
collectDeepLinkEvent()
}

private fun initUserInfo() {
private fun fetchUserInfo() {
authRepository.getUserAndCache()
.launchIn(viewModelScope + recordExceptionHandler)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ sealed interface LoginEvent {
data object RequireSignUp : LoginEvent
data object SignOutCancelled : LoginEvent
data object Invalid : LoginEvent
data object SignupFailed : LoginEvent
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.nexters.boolti.presentation.component.BTDialog
import com.nexters.boolti.presentation.component.BtCloseableAppBar
import com.nexters.boolti.presentation.component.KakaoLoginButton
import com.nexters.boolti.presentation.component.MainButton
import com.nexters.boolti.presentation.screen.LocalSnackbarController
import com.nexters.boolti.presentation.theme.Grey30
import com.nexters.boolti.presentation.theme.marginHorizontal

Expand All @@ -49,18 +50,22 @@ fun LoginScreen(
modifier: Modifier = Modifier,
viewModel: LoginViewModel = hiltViewModel(),
) {
val context = LocalContext.current
val snackbarController = LocalSnackbarController.current

val sheetState = rememberModalBottomSheetState()
var showSignOutCancelledDialog by remember { mutableStateOf(false) }
var isSheetOpen by rememberSaveable { mutableStateOf(false) }
val loginFailedMessage = stringResource(id = R.string.login_failed)
val signupFailedMessage = stringResource(id = R.string.signup_failed)

LaunchedEffect(Unit) {
viewModel.event.collect {
when (it) {
LoginEvent.Success -> onBackPressed()
LoginEvent.RequireSignUp -> isSheetOpen = true
LoginEvent.SignOutCancelled -> showSignOutCancelledDialog = true
LoginEvent.Invalid -> Toast.makeText(context, "로그인 실패", Toast.LENGTH_SHORT).show()
LoginEvent.Invalid -> snackbarController.showMessage(loginFailedMessage)
LoginEvent.SignupFailed -> snackbarController.showMessage(signupFailedMessage)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.nexters.boolti.presentation.screen.login

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.firebase.crashlytics.FirebaseCrashlytics
import com.nexters.boolti.domain.repository.AuthRepository
import com.nexters.boolti.domain.request.LoginRequest
import com.nexters.boolti.domain.request.OauthType
Expand Down Expand Up @@ -39,7 +40,7 @@ class LoginViewModel @Inject constructor(
else -> event(LoginEvent.Success)
}
}.onFailure {
Timber.d("login failed: $it")
FirebaseCrashlytics.getInstance().setCustomKey("LOGIN", "FAILED")
event(LoginEvent.Invalid)
}
}
Expand Down Expand Up @@ -78,7 +79,8 @@ class LoginViewModel @Inject constructor(
).onSuccess {
event(LoginEvent.Success)
}.onFailure {
// TODO 예외 처리
FirebaseCrashlytics.getInstance().setCustomKey("SIGNUP", "FAILED")
event(LoginEvent.SignupFailed)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ class MyViewModel @Inject constructor(
null,
)

fun logout() {
viewModelScope.launch {
authRepository.logout()
}
}

fun fetchMyInfo() {
authRepository.getUserAndCache()
.launchIn(viewModelScope + recordExceptionHandler)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ import com.nexters.boolti.presentation.theme.point4

@Composable
fun ShowScreen(
navigateToReservations: () -> Unit,
navigateToBusiness: () -> Unit,
onClickShowItem: (showId: String) -> Unit,
modifier: Modifier = Modifier,
Expand All @@ -78,7 +77,7 @@ fun ShowScreen(
val uiState by viewModel.uiState.collectAsStateWithLifecycle()

val lazyGridState = rememberLazyGridState()
val appbarHeight = if (uiState.hasPendingTicket) 196.dp + 52.dp else 196.dp
val appbarHeight = 196.dp
val searchBarHeight = 80.dp
val changeableAppBarHeightPx = (appbarHeight - searchBarHeight).toPx()
var appbarOffsetHeightPx by rememberSaveable { mutableFloatStateOf(0f) }
Expand All @@ -102,7 +101,6 @@ fun ShowScreen(
}

LaunchedEffect(Unit) {
viewModel.fetchReservationInfo()
viewModel.events.collect { event ->
when (event) {
ShowEvent.Search -> appbarOffsetHeightPx = 0f
Expand Down Expand Up @@ -152,8 +150,6 @@ fun ShowScreen(
y = appbarOffsetHeightPx.coerceAtLeast(-changeableAppBarHeightPx).toInt(),
)
},
navigateToReservations = navigateToReservations,
hasPendingTicket = uiState.hasPendingTicket,
nickname = nickname.ifBlank { stringResource(id = R.string.nickname_default) },
text = uiState.keyword,
onKeywordChanged = viewModel::updateKeyword,
Expand All @@ -166,8 +162,6 @@ fun ShowScreen(
@Composable
fun ShowAppBar(
text: String,
hasPendingTicket: Boolean,
navigateToReservations: () -> Unit,
nickname: String,
onKeywordChanged: (keyword: String) -> Unit,
search: () -> Unit,
Expand All @@ -180,10 +174,6 @@ fun ShowAppBar(
.padding(horizontal = marginHorizontal)
) {
Spacer(modifier = Modifier.height(20.dp))
if (hasPendingTicket) Banner(
modifier = Modifier.fillMaxWidth(),
navigateToReservations = navigateToReservations,
)
Spacer(modifier = Modifier.height(20.dp))
Text(
modifier = Modifier
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ import com.nexters.boolti.domain.model.Show
data class ShowUiState(
val keyword: String = "",
val shows: List<Show> = emptyList(),
val hasPendingTicket: Boolean = false,
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import javax.inject.Inject
@HiltViewModel
class ShowViewModel @Inject constructor(
private val showRepository: ShowRepository,
private val reservationRepository: ReservationRepository,
authRepository: AuthRepository,
) : BaseViewModel() {
val user: StateFlow<User?> = authRepository.cachedUser.stateIn(
Expand Down Expand Up @@ -67,17 +66,4 @@ class ShowViewModel @Inject constructor(
fun updateKeyword(newKeyword: String) {
_uiState.update { it.copy(keyword = newKeyword) }
}

fun fetchReservationInfo() {
reservationRepository.getReservations()
.map { reservations ->
reservations.firstOrNull { it.reservationState == ReservationState.DEPOSITING } != null
}
.onEach { hasPendingTicket ->
_uiState.update {
it.copy(hasPendingTicket = hasPendingTicket)
}
}
.launchIn(viewModelScope + recordExceptionHandler)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ class TicketingViewModel @Inject constructor(
val showId: String = requireNotNull(savedStateHandle["showId"])
val salesTicketTypeId: String = requireNotNull(savedStateHandle["salesTicketId"])
private val ticketCount: Int = savedStateHandle["ticketCount"] ?: 1
private val userId = getUserUsecase().id
private val userId = checkNotNull(getUserUsecase()?.id) {
"[TicketingViewModel] 사용자 정보가 없습니다."
}

private val _uiState = MutableStateFlow(TicketingState())
val uiState = _uiState.asStateFlow()
Expand Down
2 changes: 2 additions & 0 deletions presentation/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
<string name="nickname_default">불티 유저</string>
<string name="signout_cancelled_message">30일 내에 로그인하여\n계정 삭제가 취소되었어요.\n불티를 다시 찾아주셔서 감사해요!</string>
<string name="user_code">식별 코드</string>
<string name="login_failed">로그인 실패</string>
<string name="signup_failed">회원가입 실패</string>

<!-- 탈퇴 -->
<string name="signout">계정 삭제</string>
Expand Down

0 comments on commit 1f435e4

Please sign in to comment.