From 4bd46092191ae86f053c91727f063fab17708522 Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 01:31:46 +0900 Subject: [PATCH 01/16] =?UTF-8?q?feat=20:=20=ED=99=88=20=ED=99=94=EB=A9=B4?= =?UTF-8?q?=20=EB=94=A5=EB=A7=81=ED=81=AC=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nexters/boolti/presentation/screen/home/HomeScreen.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 87eb1034..f12843bc 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -86,6 +86,12 @@ fun HomeScreen( ) { composable( route = Destination.Show.route, + deepLinks = listOf( + navDeepLink { + uriPattern = "https://app.boolti.in/home/shows" + action = Intent.ACTION_VIEW + } + ) ) { ShowScreen( modifier = modifier.padding(innerPadding), From ea5a2e8c771211df31725f46b78212aeb6bd2c0c Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 01:45:17 +0900 Subject: [PATCH 02/16] =?UTF-8?q?feat=20:=20=EB=B0=9B=EC=9D=80=20=EC=84=A0?= =?UTF-8?q?=EB=AC=BC=20=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=80=EC=9E=A5=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20api?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boolti/data/repository/GiftRepositoryImpl.kt | 12 ++++++++++++ .../boolti/domain/repository/GiftRepository.kt | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt b/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt index 4faa3ca5..795a3489 100644 --- a/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt +++ b/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt @@ -15,6 +15,8 @@ import javax.inject.Inject internal class GiftRepositoryImpl @Inject constructor( private val dataSource: GiftDataSource ) : GiftRepository { + var pendingGiftUuid: String? = null + override fun receiveGift(giftUuid: String): Flow = flow { emit(dataSource.receiveGift(GiftReceiveRequest(giftUuid))) } @@ -30,4 +32,14 @@ internal class GiftRepositoryImpl @Inject constructor( override fun getGiftImages(): Flow> = flow { emit(dataSource.getGiftImages().toDomains()) } + + override fun saveGift(giftUuid: String) { + pendingGiftUuid = giftUuid + } + + override fun popPendingGift(): String? { + val giftUuid = pendingGiftUuid + pendingGiftUuid = null + return giftUuid + } } \ No newline at end of file diff --git a/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt b/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt index e860bcfd..f7775f99 100644 --- a/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt +++ b/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt @@ -14,4 +14,8 @@ interface GiftRepository { fun getGift(giftUuid: String): Flow fun getGiftImages(): Flow> + + fun saveGift(giftUuid: String) + + fun popPendingGift(): String? } \ No newline at end of file From 28293ccbd5d4fda2a52c908382a841546403009d Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 02:11:57 +0900 Subject: [PATCH 03/16] =?UTF-8?q?fix=20:=20=EC=9D=BC=EA=B4=80=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=EB=A5=BC=20=EC=9C=84=ED=95=B4=20=EA=B8=B0=EC=A1=B4=20=EC=9D=B4?= =?UTF-8?q?=EB=B2=A4=ED=8A=B8=20=ED=95=B8=EB=93=A4=EB=A7=81=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/screen/home/HomeEvent.kt | 7 ++++ .../presentation/screen/home/HomeScreen.kt | 21 +++++++++-- .../screen/{ => home}/HomeViewModel.kt | 36 ++++++++++++++----- 3 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt rename presentation/src/main/java/com/nexters/boolti/presentation/screen/{ => home}/HomeViewModel.kt (55%) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt new file mode 100644 index 00000000..aacc2f9a --- /dev/null +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt @@ -0,0 +1,7 @@ +package com.nexters.boolti.presentation.screen.home + +sealed interface HomeEvent { + data class DeepLinkEvent( + val deepLink: String, + ) : HomeEvent +} \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index f12843bc..04434c14 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -20,6 +20,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -32,7 +33,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navDeepLink import com.nexters.boolti.presentation.R -import com.nexters.boolti.presentation.screen.HomeViewModel +import com.nexters.boolti.presentation.extension.requireActivity import com.nexters.boolti.presentation.screen.my.MyScreen import com.nexters.boolti.presentation.screen.show.ShowScreen import com.nexters.boolti.presentation.screen.ticket.TicketLoginScreen @@ -58,10 +59,24 @@ fun HomeScreen( val currentDestination = navBackStackEntry?.destination?.route ?: Destination.Show.route val loggedIn by viewModel.loggedIn.collectAsStateWithLifecycle() + val context = LocalContext.current LaunchedEffect(Unit) { - viewModel.event.collect { deepLink -> - navController.navigate(Uri.parse(deepLink)) + viewModel.events.collect { event -> + when (event) { + is HomeEvent.DeepLinkEvent -> navController.navigate(Uri.parse(event.deepLink)) + } + } + } + + LaunchedEffect(Unit) { + val intent = context.requireActivity().intent + intent.action?.let { deepLink -> + val regex = "^https://app.boolti.in/gift/(\\w)+$".toRegex() + if (regex.matches(deepLink)) { + val giftUuid = deepLink.split("/").last() + viewModel.receiveGift(giftUuid) + } } } diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt similarity index 55% rename from presentation/src/main/java/com/nexters/boolti/presentation/screen/HomeViewModel.kt rename to presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index 18db2497..c3cd78f7 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -1,14 +1,19 @@ -package com.nexters.boolti.presentation.screen +package com.nexters.boolti.presentation.screen.home import androidx.lifecycle.viewModelScope import com.nexters.boolti.domain.repository.AuthRepository +import com.nexters.boolti.domain.repository.GiftRepository import com.nexters.boolti.presentation.base.BaseViewModel +import com.nexters.boolti.presentation.screen.DeepLinkEvent import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch @@ -18,7 +23,8 @@ import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor( private val authRepository: AuthRepository, - deepLinkEvent: DeepLinkEvent, + private val giftRepository: GiftRepository, + private val deepLinkEvent: DeepLinkEvent, ) : BaseViewModel() { val loggedIn = authRepository.loggedIn.stateIn( viewModelScope, @@ -26,16 +32,13 @@ class HomeViewModel @Inject constructor( null, ) - val event: SharedFlow = - deepLinkEvent.events.filter { it.startsWith("https://app.boolti.in/home") } - .shareIn( - scope = viewModelScope, - started = SharingStarted.Lazily, - ) + private val _events = MutableSharedFlow() + val events: SharedFlow = _events.asSharedFlow() init { initUserInfo() sendFcmToken() + collectDeepLinkEvent() } private fun initUserInfo() { @@ -50,4 +53,21 @@ class HomeViewModel @Inject constructor( } } } + + private fun collectDeepLinkEvent() { + deepLinkEvent.events + .filter { it.startsWith("https://app.boolti.in/home") } + .onEach { sendEvent(HomeEvent.DeepLinkEvent(it)) } + .launchIn(viewModelScope) + } + + fun receiveGift(giftUuid: String) { + // TODO: 선물 받는 로직 + } + + private fun sendEvent(event: HomeEvent) { + viewModelScope.launch { + _events.emit(event) + } + } } From 4793617e556826c65948fcd944a8b9fe26c7635c Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 02:45:48 +0900 Subject: [PATCH 04/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=93=B1?= =?UTF-8?q?=EB=A1=9D]=20=EB=B9=84=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=9D=B8=20?= =?UTF-8?q?=EA=B2=BD=EC=9A=B0=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=9A=94?= =?UTF-8?q?=EC=B2=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/screen/home/HomeDialog.kt | 5 ++++ .../presentation/screen/home/HomeEvent.kt | 2 ++ .../presentation/screen/home/HomeScreen.kt | 27 +++++++++++++++++-- .../presentation/screen/home/HomeViewModel.kt | 11 ++++++-- presentation/src/main/res/values/strings.xml | 2 ++ 5 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt new file mode 100644 index 00000000..2afa471a --- /dev/null +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt @@ -0,0 +1,5 @@ +package com.nexters.boolti.presentation.screen.home + +enum class HomeDialog { + NEED_LOGIN_FOR_GIFT +} \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt index aacc2f9a..bac1778d 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt @@ -4,4 +4,6 @@ sealed interface HomeEvent { data class DeepLinkEvent( val deepLink: String, ) : HomeEvent + + data object RequireLoginForGift : HomeEvent } \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 04434c14..73e205b6 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -19,6 +19,9 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -33,6 +36,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navDeepLink import com.nexters.boolti.presentation.R +import com.nexters.boolti.presentation.component.BTDialog import com.nexters.boolti.presentation.extension.requireActivity import com.nexters.boolti.presentation.screen.my.MyScreen import com.nexters.boolti.presentation.screen.show.ShowScreen @@ -61,18 +65,24 @@ fun HomeScreen( val loggedIn by viewModel.loggedIn.collectAsStateWithLifecycle() val context = LocalContext.current + var dialog: HomeDialog? by rememberSaveable { mutableStateOf(null) } + LaunchedEffect(Unit) { viewModel.events.collect { event -> when (event) { is HomeEvent.DeepLinkEvent -> navController.navigate(Uri.parse(event.deepLink)) + HomeEvent.RequireLoginForGift -> { + dialog = HomeDialog.NEED_LOGIN_FOR_GIFT + } } } } LaunchedEffect(Unit) { val intent = context.requireActivity().intent - intent.action?.let { deepLink -> - val regex = "^https://app.boolti.in/gift/(\\w)+$".toRegex() + intent.action?.let { _ -> + val deepLink = intent.data.toString() + val regex = "^https://app.boolti.in/gift/([\\w-])+$".toRegex() if (regex.matches(deepLink)) { val giftUuid = deepLink.split("/").last() viewModel.receiveGift(giftUuid) @@ -151,6 +161,19 @@ fun HomeScreen( } } } + + if (dialog != null) { + val dialogText = stringResource(id = R.string.gift_need_login) + val action = requireLogin + + BTDialog( + onDismiss = { dialog = null }, + onClickPositiveButton = action, + positiveButtonLabel = stringResource(id = R.string.gift_login), + ) { + Text(text = dialogText) + } + } } @Stable diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index c3cd78f7..a4a1fdc4 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.plus @@ -62,7 +61,15 @@ class HomeViewModel @Inject constructor( } fun receiveGift(giftUuid: String) { - // TODO: 선물 받는 로직 + when (loggedIn.value) { + true -> TODO("선물 받는 로직") + false -> { + giftRepository.saveGift(giftUuid) + sendEvent(HomeEvent.RequireLoginForGift) + } + + null -> TODO() + } } private fun sendEvent(event: HomeEvent) { diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 36d9d5e2..9a5a44d2 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -187,6 +187,8 @@ 마이 > 결제 내역 > 결제 내역 상세에서 선물을 취소할 수 있습니다. 받는 분이 선물 거절 시 결제가 자동 취소됩니다. + 로그인하기 + 로그인 후 선물 등록이 가능합니다.\n로그인해 주세요. 전화 문의하기 From de2ba653480278289faca2f7a1d091b53f726904 Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 03:11:48 +0900 Subject: [PATCH 05/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=93=B1?= =?UTF-8?q?=EB=A1=9D]=20=EC=84=A0=EB=AC=BC=20=EB=B0=9B=EB=8A=94=20?= =?UTF-8?q?=EC=BC=80=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20=ED=8B=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boolti/presentation/component/BTDialog.kt | 39 ++++++++++++++++--- .../presentation/screen/home/GiftStatus.kt | 8 ++++ .../presentation/screen/home/HomeDialog.kt | 5 --- .../presentation/screen/home/HomeEvent.kt | 4 +- .../presentation/screen/home/HomeScreen.kt | 34 +++++++++++++--- .../presentation/screen/home/HomeViewModel.kt | 7 +++- presentation/src/main/res/values/strings.xml | 6 +++ 7 files changed, 84 insertions(+), 19 deletions(-) create mode 100644 presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftStatus.kt delete mode 100644 presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt index 000ab51c..552d92d8 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height @@ -35,6 +36,9 @@ fun BTDialog( enableDismiss: Boolean = true, showCloseButton: Boolean = true, onDismiss: () -> Unit = {}, + hasNegativeButton: Boolean = false, + negativeButtonLabel: String = stringResource(R.string.cancel), + onClickNegativeButton: () -> Unit = {}, positiveButtonLabel: String = stringResource(R.string.btn_ok), positiveButtonEnabled: Boolean = true, horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, @@ -79,12 +83,21 @@ fun BTDialog( } content() Spacer(modifier = Modifier.size(28.dp)) - MainButton( - modifier = Modifier.fillMaxWidth(), - label = positiveButtonLabel, - enabled = positiveButtonEnabled, - onClick = onClickPositiveButton, - ) + Row { + if (hasNegativeButton) { + MainButton( + modifier = Modifier.weight(1f), + label = negativeButtonLabel, + onClick = onClickNegativeButton, + ) + } + MainButton( + modifier = Modifier.weight(1f), + label = positiveButtonLabel, + enabled = positiveButtonEnabled, + onClick = onClickPositiveButton, + ) + } } } } @@ -101,3 +114,17 @@ fun BTDialogPreview() { } } } + +@Preview +@Composable +fun BTDialogHavingNegativeButtonPreview() { + BooltiTheme { + Surface { + BTDialog( + hasNegativeButton = true + ) { + Text(text = "관리자 코드로 입장 확인") + } + } + } +} diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftStatus.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftStatus.kt new file mode 100644 index 00000000..608b5828 --- /dev/null +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftStatus.kt @@ -0,0 +1,8 @@ +package com.nexters.boolti.presentation.screen.home + +enum class GiftStatus { + NEED_LOGIN, + FAILED, + SELF, + CAN_REGISTER, +} \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt deleted file mode 100644 index 2afa471a..00000000 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeDialog.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.nexters.boolti.presentation.screen.home - -enum class HomeDialog { - NEED_LOGIN_FOR_GIFT -} \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt index bac1778d..3c7edc00 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeEvent.kt @@ -5,5 +5,7 @@ sealed interface HomeEvent { val deepLink: String, ) : HomeEvent - data object RequireLoginForGift : HomeEvent + data class ShowMessage( + val status: GiftStatus + ) : HomeEvent } \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 73e205b6..974de96d 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -65,14 +65,14 @@ fun HomeScreen( val loggedIn by viewModel.loggedIn.collectAsStateWithLifecycle() val context = LocalContext.current - var dialog: HomeDialog? by rememberSaveable { mutableStateOf(null) } + var dialog: GiftStatus? by rememberSaveable { mutableStateOf(null) } LaunchedEffect(Unit) { viewModel.events.collect { event -> when (event) { is HomeEvent.DeepLinkEvent -> navController.navigate(Uri.parse(event.deepLink)) - HomeEvent.RequireLoginForGift -> { - dialog = HomeDialog.NEED_LOGIN_FOR_GIFT + is HomeEvent.ShowMessage -> { + dialog = event.status } } } @@ -163,13 +163,37 @@ fun HomeScreen( } if (dialog != null) { - val dialogText = stringResource(id = R.string.gift_need_login) - val action = requireLogin + val textRes = when (dialog!!) { + GiftStatus.SELF -> R.string.gift_need_login + GiftStatus.NEED_LOGIN -> R.string.gift_register + GiftStatus.CAN_REGISTER -> R.string.gift_self_dialog + GiftStatus.FAILED -> R.string.gift_registration_failed + } + val dialogText = stringResource(id = textRes) + + val action: () -> Unit = when (dialog!!) { + GiftStatus.SELF -> { + {} + } + + GiftStatus.NEED_LOGIN -> requireLogin + GiftStatus.CAN_REGISTER -> { + {} + } + + GiftStatus.FAILED -> { + { dialog = null } + } + } + + val hasNegativeButton = dialog in listOf(GiftStatus.SELF, GiftStatus.CAN_REGISTER) BTDialog( onDismiss = { dialog = null }, onClickPositiveButton = action, positiveButtonLabel = stringResource(id = R.string.gift_login), + hasNegativeButton = hasNegativeButton, + onClickNegativeButton = { dialog = GiftStatus.FAILED } ) { Text(text = dialogText) } diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index a4a1fdc4..610c917f 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -62,10 +62,13 @@ class HomeViewModel @Inject constructor( fun receiveGift(giftUuid: String) { when (loggedIn.value) { - true -> TODO("선물 받는 로직") + true -> { + sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) + } + false -> { giftRepository.saveGift(giftUuid) - sendEvent(HomeEvent.RequireLoginForGift) + sendEvent(HomeEvent.ShowMessage(GiftStatus.NEED_LOGIN)) } null -> TODO() diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 9a5a44d2..f92a9a9c 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -189,6 +189,12 @@ 로그인하기 로그인 후 선물 등록이 가능합니다.\n로그인해 주세요. + 등록하기 + 선물을 등록하면\n선물 취소 및 환불이 불가합니다.\n등록하시겠습니까? + 본인이 결제한 선물입니다.\n선물을 등록하면 다른 분께 보낼 수 없습니다. 등록하시겠습니까? + 선물 등록에 실패했어요 + 선물 등록 중 오류가 발생했습니다.\n웹 링크에서 선물 상태를 확인 후 다시 시도해 주세요 + 취소하기 전화 문의하기 From 464ef9d8efab4787546a5ce68d7e9f813dacc877 Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 03:52:15 +0900 Subject: [PATCH 06/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=93=B1?= =?UTF-8?q?=EB=A1=9D]=20=EC=84=A0=EB=AC=BC=20=EB=93=B1=EB=A1=9D=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/request/GiftReceiveRequest.kt | 3 ++ .../data/repository/GiftRepositoryImpl.kt | 12 ------ .../domain/repository/GiftRepository.kt | 4 -- .../boolti/presentation/component/BTDialog.kt | 11 +++++- .../presentation/screen/home/HomeScreen.kt | 39 ++++++++++++++----- .../presentation/screen/home/HomeViewModel.kt | 23 +++++++++-- 6 files changed, 63 insertions(+), 29 deletions(-) diff --git a/data/src/main/java/com/nexters/boolti/data/network/request/GiftReceiveRequest.kt b/data/src/main/java/com/nexters/boolti/data/network/request/GiftReceiveRequest.kt index 1f766d0a..34d01fe9 100644 --- a/data/src/main/java/com/nexters/boolti/data/network/request/GiftReceiveRequest.kt +++ b/data/src/main/java/com/nexters/boolti/data/network/request/GiftReceiveRequest.kt @@ -1,5 +1,8 @@ package com.nexters.boolti.data.network.request +import kotlinx.serialization.Serializable + +@Serializable data class GiftReceiveRequest( val giftUuid: String, ) \ No newline at end of file diff --git a/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt b/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt index 795a3489..4faa3ca5 100644 --- a/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt +++ b/data/src/main/java/com/nexters/boolti/data/repository/GiftRepositoryImpl.kt @@ -15,8 +15,6 @@ import javax.inject.Inject internal class GiftRepositoryImpl @Inject constructor( private val dataSource: GiftDataSource ) : GiftRepository { - var pendingGiftUuid: String? = null - override fun receiveGift(giftUuid: String): Flow = flow { emit(dataSource.receiveGift(GiftReceiveRequest(giftUuid))) } @@ -32,14 +30,4 @@ internal class GiftRepositoryImpl @Inject constructor( override fun getGiftImages(): Flow> = flow { emit(dataSource.getGiftImages().toDomains()) } - - override fun saveGift(giftUuid: String) { - pendingGiftUuid = giftUuid - } - - override fun popPendingGift(): String? { - val giftUuid = pendingGiftUuid - pendingGiftUuid = null - return giftUuid - } } \ No newline at end of file diff --git a/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt b/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt index f7775f99..e860bcfd 100644 --- a/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt +++ b/domain/src/main/java/com/nexters/boolti/domain/repository/GiftRepository.kt @@ -14,8 +14,4 @@ interface GiftRepository { fun getGift(giftUuid: String): Flow fun getGiftImages(): Flow> - - fun saveGift(giftUuid: String) - - fun popPendingGift(): String? } \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt index 552d92d8..a0d34885 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt @@ -1,6 +1,7 @@ package com.nexters.boolti.presentation.component import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope @@ -28,7 +29,9 @@ import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import com.nexters.boolti.presentation.R import com.nexters.boolti.presentation.theme.BooltiTheme +import com.nexters.boolti.presentation.theme.Grey05 import com.nexters.boolti.presentation.theme.Grey50 +import com.nexters.boolti.presentation.theme.Grey80 @Composable fun BTDialog( @@ -83,12 +86,18 @@ fun BTDialog( } content() Spacer(modifier = Modifier.size(28.dp)) - Row { + Row( + horizontalArrangement = Arrangement.spacedBy(9.dp) + ) { if (hasNegativeButton) { MainButton( modifier = Modifier.weight(1f), label = negativeButtonLabel, onClick = onClickNegativeButton, + colors = MainButtonDefaults.buttonColors( + containerColor = Grey80, + contentColor = Grey05, + ) ) } MainButton( diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 974de96d..786cac7f 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -43,6 +44,7 @@ import com.nexters.boolti.presentation.screen.show.ShowScreen import com.nexters.boolti.presentation.screen.ticket.TicketLoginScreen import com.nexters.boolti.presentation.screen.ticket.TicketScreen import com.nexters.boolti.presentation.theme.Grey10 +import com.nexters.boolti.presentation.theme.Grey15 import com.nexters.boolti.presentation.theme.Grey50 import com.nexters.boolti.presentation.theme.Grey85 @@ -85,7 +87,7 @@ fun HomeScreen( val regex = "^https://app.boolti.in/gift/([\\w-])+$".toRegex() if (regex.matches(deepLink)) { val giftUuid = deepLink.split("/").last() - viewModel.receiveGift(giftUuid) + viewModel.processGift(giftUuid) } } } @@ -163,22 +165,35 @@ fun HomeScreen( } if (dialog != null) { + // TODO: 중복코드 제거 + + val buttonTextRes = when (dialog!!) { + GiftStatus.SELF, GiftStatus.CAN_REGISTER -> R.string.gift_register + GiftStatus.NEED_LOGIN -> R.string.gift_login + GiftStatus.FAILED -> R.string.description_close_button + } + val textRes = when (dialog!!) { - GiftStatus.SELF -> R.string.gift_need_login - GiftStatus.NEED_LOGIN -> R.string.gift_register - GiftStatus.CAN_REGISTER -> R.string.gift_self_dialog + GiftStatus.SELF -> R.string.gift_self_dialog + GiftStatus.NEED_LOGIN -> R.string.gift_need_login + GiftStatus.CAN_REGISTER -> R.string.gift_register_dialog GiftStatus.FAILED -> R.string.gift_registration_failed } - val dialogText = stringResource(id = textRes) val action: () -> Unit = when (dialog!!) { GiftStatus.SELF -> { - {} + { + viewModel.receiveGift() + dialog = null + } } GiftStatus.NEED_LOGIN -> requireLogin GiftStatus.CAN_REGISTER -> { - {} + { + viewModel.receiveGift() + dialog = null + } } GiftStatus.FAILED -> { @@ -191,11 +206,17 @@ fun HomeScreen( BTDialog( onDismiss = { dialog = null }, onClickPositiveButton = action, - positiveButtonLabel = stringResource(id = R.string.gift_login), + positiveButtonLabel = stringResource(id = buttonTextRes), hasNegativeButton = hasNegativeButton, onClickNegativeButton = { dialog = GiftStatus.FAILED } ) { - Text(text = dialogText) + Text( + text = stringResource(id = textRes), + style = MaterialTheme.typography.titleLarge.copy( + color = Grey15, + textAlign = TextAlign.Center + ), + ) } } } diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index 610c917f..b2ea3ecf 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -34,6 +34,8 @@ class HomeViewModel @Inject constructor( private val _events = MutableSharedFlow() val events: SharedFlow = _events.asSharedFlow() + var pendingGiftUuid: String? = null + init { initUserInfo() sendFcmToken() @@ -60,18 +62,20 @@ class HomeViewModel @Inject constructor( .launchIn(viewModelScope) } - fun receiveGift(giftUuid: String) { + fun processGift(giftUuid: String) { + // TODO: 자기 자신의 선물을 받는 케이스 처리 + pendingGiftUuid = giftUuid + when (loggedIn.value) { true -> { sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) } false -> { - giftRepository.saveGift(giftUuid) sendEvent(HomeEvent.ShowMessage(GiftStatus.NEED_LOGIN)) } - null -> TODO() + null -> TODO("null인 케이스 처리") } } @@ -80,4 +84,17 @@ class HomeViewModel @Inject constructor( _events.emit(event) } } + + fun receiveGift() { + val giftUuid = pendingGiftUuid ?: return + pendingGiftUuid = null + + giftRepository.receiveGift(giftUuid) + .onEach { isSuccessful -> + if (!isSuccessful) { + sendEvent(HomeEvent.ShowMessage(GiftStatus.FAILED)) + } + } + .launchIn(viewModelScope + recordExceptionHandler) + } } From 021984653c4e6b738a61fec76953b72407a04cbd Mon Sep 17 00:00:00 2001 From: algosketch Date: Thu, 25 Jul 2024 04:02:48 +0900 Subject: [PATCH 07/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=93=B1?= =?UTF-8?q?=EB=A1=9D]=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EC=A7=81=ED=9B=84?= =?UTF-8?q?=20=EC=84=A0=EB=AC=BC=20=EC=A0=95=EB=B3=B4=EA=B0=80=20=EC=9E=88?= =?UTF-8?q?=EB=8B=A4=EB=A9=B4=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nexters/boolti/presentation/screen/home/HomeScreen.kt | 4 ++++ .../boolti/presentation/screen/home/HomeViewModel.kt | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 786cac7f..85135bd5 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -92,6 +92,10 @@ fun HomeScreen( } } + LaunchedEffect(loggedIn) { + if (loggedIn == true) viewModel.processGift() + } + Scaffold( bottomBar = { HomeNavigationBar( diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index b2ea3ecf..d8b5fe82 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -62,6 +62,13 @@ class HomeViewModel @Inject constructor( .launchIn(viewModelScope) } + fun processGift() { + // TODO: 자기 자신의 선물을 받는 케이스 처리 + if (pendingGiftUuid != null) { + sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) + } + } + fun processGift(giftUuid: String) { // TODO: 자기 자신의 선물을 받는 케이스 처리 pendingGiftUuid = giftUuid From a57975784a7a1c266d4fbb97c82b3e478b015819 Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 01:12:00 +0900 Subject: [PATCH 08/16] =?UTF-8?q?refactor=20:=20[=EC=84=A0=EB=AC=BC?= =?UTF-8?q?=EB=B0=9B=EA=B8=B0]=20=EB=8B=A4=EC=9D=B4=EC=96=BC=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/screen/home/GiftDialog.kt | 69 +++++++++++++++++++ .../presentation/screen/home/HomeScreen.kt | 58 ++-------------- 2 files changed, 75 insertions(+), 52 deletions(-) create mode 100644 presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt new file mode 100644 index 00000000..a5f9b5a7 --- /dev/null +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt @@ -0,0 +1,69 @@ +package com.nexters.boolti.presentation.screen.home + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import com.nexters.boolti.presentation.R +import com.nexters.boolti.presentation.component.BTDialog +import com.nexters.boolti.presentation.theme.Grey15 + +@Composable +fun GiftDialog( + status: GiftStatus, + onDismiss: () -> Unit, + receiveGift: () -> Unit, + requireLogin: () -> Unit, + onFailed: () -> Unit, +) { + val buttonTextRes = when (status) { + GiftStatus.SELF, GiftStatus.CAN_REGISTER -> R.string.gift_register + GiftStatus.NEED_LOGIN -> R.string.gift_login + GiftStatus.FAILED -> R.string.description_close_button + } + + val textRes = when (status) { + GiftStatus.SELF -> R.string.gift_self_dialog + GiftStatus.NEED_LOGIN -> R.string.gift_need_login + GiftStatus.CAN_REGISTER -> R.string.gift_register_dialog + GiftStatus.FAILED -> R.string.gift_registration_failed + } + + val action: () -> Unit = when (status) { + GiftStatus.SELF -> { + { + receiveGift() + onDismiss() + } + } + + GiftStatus.NEED_LOGIN -> requireLogin + GiftStatus.CAN_REGISTER -> { + { + receiveGift() + onDismiss() + } + } + + GiftStatus.FAILED -> onDismiss + } + + val hasNegativeButton = status in listOf(GiftStatus.SELF, GiftStatus.CAN_REGISTER) + + BTDialog( + onDismiss = onDismiss, + onClickPositiveButton = action, + positiveButtonLabel = stringResource(id = buttonTextRes), + hasNegativeButton = hasNegativeButton, + onClickNegativeButton = onFailed + ) { + Text( + text = stringResource(id = textRes), + style = MaterialTheme.typography.titleLarge.copy( + color = Grey15, + textAlign = TextAlign.Center + ), + ) + } +} \ No newline at end of file diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index 85135bd5..de1c37de 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -169,59 +169,13 @@ fun HomeScreen( } if (dialog != null) { - // TODO: 중복코드 제거 - - val buttonTextRes = when (dialog!!) { - GiftStatus.SELF, GiftStatus.CAN_REGISTER -> R.string.gift_register - GiftStatus.NEED_LOGIN -> R.string.gift_login - GiftStatus.FAILED -> R.string.description_close_button - } - - val textRes = when (dialog!!) { - GiftStatus.SELF -> R.string.gift_self_dialog - GiftStatus.NEED_LOGIN -> R.string.gift_need_login - GiftStatus.CAN_REGISTER -> R.string.gift_register_dialog - GiftStatus.FAILED -> R.string.gift_registration_failed - } - - val action: () -> Unit = when (dialog!!) { - GiftStatus.SELF -> { - { - viewModel.receiveGift() - dialog = null - } - } - - GiftStatus.NEED_LOGIN -> requireLogin - GiftStatus.CAN_REGISTER -> { - { - viewModel.receiveGift() - dialog = null - } - } - - GiftStatus.FAILED -> { - { dialog = null } - } - } - - val hasNegativeButton = dialog in listOf(GiftStatus.SELF, GiftStatus.CAN_REGISTER) - - BTDialog( + GiftDialog( + status = dialog!!, onDismiss = { dialog = null }, - onClickPositiveButton = action, - positiveButtonLabel = stringResource(id = buttonTextRes), - hasNegativeButton = hasNegativeButton, - onClickNegativeButton = { dialog = GiftStatus.FAILED } - ) { - Text( - text = stringResource(id = textRes), - style = MaterialTheme.typography.titleLarge.copy( - color = Grey15, - textAlign = TextAlign.Center - ), - ) - } + receiveGift = viewModel::receiveGift, + requireLogin = requireLogin, + onFailed = { dialog = GiftStatus.FAILED } + ) } } From 529b9c1cb018222e810e0cb85ce4d564a271ec6f Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 01:28:12 +0900 Subject: [PATCH 09/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=B0=9B?= =?UTF-8?q?=EA=B8=B0]=20=EC=9E=90=EA=B8=B0=20=EC=9E=90=EC=8B=A0=EC=9D=98?= =?UTF-8?q?=20=EC=84=A0=EB=AC=BC=20=EC=8B=9D=EB=B3=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/network/response/GiftResponse.kt | 2 ++ .../com/nexters/boolti/domain/model/Gift.kt | 1 + .../presentation/screen/home/HomeViewModel.kt | 30 ++++++++++++------- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt b/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt index d331171f..7ee9e1ec 100644 --- a/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt +++ b/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt @@ -7,6 +7,7 @@ import kotlinx.serialization.Serializable @Serializable data class GiftResponse( val id: String, + val userId: String, val giftUuid: String, val orderId: String, val reservationId: String, @@ -23,6 +24,7 @@ data class GiftResponse( fun toDomain(): Gift { return Gift( id = id, + userId = userId, uuid = giftUuid, orderId = orderId, reservationId = reservationId, diff --git a/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt b/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt index f0cbdaab..fb49858e 100644 --- a/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt +++ b/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt @@ -4,6 +4,7 @@ import java.time.LocalDate data class Gift( val id: String, + val userId: String, val uuid: String, val orderId: String, val reservationId: String, diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index d8b5fe82..a6b9f51b 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -12,6 +12,7 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn @@ -63,26 +64,35 @@ class HomeViewModel @Inject constructor( } fun processGift() { - // TODO: 자기 자신의 선물을 받는 케이스 처리 if (pendingGiftUuid != null) { - sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) + processGiftWhenLoggedIn(pendingGiftUuid!!) } } fun processGift(giftUuid: String) { - // TODO: 자기 자신의 선물을 받는 케이스 처리 pendingGiftUuid = giftUuid when (loggedIn.value) { - true -> { - sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) - } + true -> processGiftWhenLoggedIn(giftUuid) + false -> sendEvent(HomeEvent.ShowMessage(GiftStatus.NEED_LOGIN)) + null -> Unit + } + } - false -> { - sendEvent(HomeEvent.ShowMessage(GiftStatus.NEED_LOGIN)) - } + private fun processGiftWhenLoggedIn(giftUuid: String) { + viewModelScope.launch(recordExceptionHandler) { + val senderId = giftRepository + .getGift(giftUuid) + .first() + .userId + + val myUserId = authRepository.cachedUser.first()?.id ?: return@launch - null -> TODO("null인 케이스 처리") + if (senderId == myUserId) { + sendEvent(HomeEvent.ShowMessage(GiftStatus.SELF)) + } else { + sendEvent(HomeEvent.ShowMessage(GiftStatus.CAN_REGISTER)) + } } } From 4ab3081201354810f51ff434f69c1d80ef9728ce Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 01:41:23 +0900 Subject: [PATCH 10/16] =?UTF-8?q?feat=20:=20[=EC=84=A0=EB=AC=BC=EB=B0=9B?= =?UTF-8?q?=EA=B8=B0]=20=EC=82=AC=EC=9A=A9=EC=84=B1=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/screen/home/HomeScreen.kt | 18 ++++++++++++------ .../presentation/screen/home/HomeViewModel.kt | 6 +++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index de1c37de..afd67ed9 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -26,7 +26,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -37,14 +36,12 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import androidx.navigation.navDeepLink import com.nexters.boolti.presentation.R -import com.nexters.boolti.presentation.component.BTDialog import com.nexters.boolti.presentation.extension.requireActivity import com.nexters.boolti.presentation.screen.my.MyScreen import com.nexters.boolti.presentation.screen.show.ShowScreen import com.nexters.boolti.presentation.screen.ticket.TicketLoginScreen import com.nexters.boolti.presentation.screen.ticket.TicketScreen import com.nexters.boolti.presentation.theme.Grey10 -import com.nexters.boolti.presentation.theme.Grey15 import com.nexters.boolti.presentation.theme.Grey50 import com.nexters.boolti.presentation.theme.Grey85 @@ -171,10 +168,19 @@ fun HomeScreen( if (dialog != null) { GiftDialog( status = dialog!!, - onDismiss = { dialog = null }, + onDismiss = { + dialog = null + viewModel.cancelGift() + }, receiveGift = viewModel::receiveGift, - requireLogin = requireLogin, - onFailed = { dialog = GiftStatus.FAILED } + requireLogin = { + dialog = null + requireLogin() + }, + onFailed = { + dialog = GiftStatus.FAILED + viewModel.cancelGift() + } ) } } diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index a6b9f51b..710cd0cc 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -35,7 +35,7 @@ class HomeViewModel @Inject constructor( private val _events = MutableSharedFlow() val events: SharedFlow = _events.asSharedFlow() - var pendingGiftUuid: String? = null + private var pendingGiftUuid: String? = null init { initUserInfo() @@ -114,4 +114,8 @@ class HomeViewModel @Inject constructor( } .launchIn(viewModelScope + recordExceptionHandler) } + + fun cancelGift() { + pendingGiftUuid = null + } } From 5ab52bf81296e3c86b309e21724fcf209e161e33 Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 02:09:50 +0900 Subject: [PATCH 11/16] =?UTF-8?q?fix=20:=20=EC=9C=A0=EC=A0=80=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=A5=BC=20=EB=AA=BB=20=EA=B0=80=EC=A0=B8=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nexters/boolti/data/repository/AuthRepositoryImpl.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/src/main/java/com/nexters/boolti/data/repository/AuthRepositoryImpl.kt b/data/src/main/java/com/nexters/boolti/data/repository/AuthRepositoryImpl.kt index 08dd4869..530767db 100644 --- a/data/src/main/java/com/nexters/boolti/data/repository/AuthRepositoryImpl.kt +++ b/data/src/main/java/com/nexters/boolti/data/repository/AuthRepositoryImpl.kt @@ -13,6 +13,7 @@ import com.nexters.boolti.domain.request.LoginRequest import com.nexters.boolti.domain.request.SignUpRequest import com.nexters.boolti.domain.request.SignoutRequest import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map import javax.inject.Inject @@ -34,6 +35,7 @@ internal class AuthRepositoryImpl @Inject constructor( return authDataSource.login(request).onSuccess { response -> tokenDataSource.saveTokens(response.accessToken ?: "", response.refreshToken ?: "") deviceTokenDataSource.sendFcmToken() + getUserAndCache().first() }.mapCatching(LoginResponse::toDomain) } From c5b4c74318c2a58eb16534496cc8f971513a02ac Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 02:19:50 +0900 Subject: [PATCH 12/16] =?UTF-8?q?fix=20:=20=EC=84=A0=EB=AC=BC=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EA=B0=80=20=EC=95=88=20=EC=82=AC=EB=9D=BC=EC=A7=80?= =?UTF-8?q?=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nexters/boolti/presentation/screen/home/HomeScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt index afd67ed9..3ebf4f22 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeScreen.kt @@ -81,6 +81,7 @@ fun HomeScreen( val intent = context.requireActivity().intent intent.action?.let { _ -> val deepLink = intent.data.toString() + intent.data = null val regex = "^https://app.boolti.in/gift/([\\w-])+$".toRegex() if (regex.matches(deepLink)) { val giftUuid = deepLink.split("/").last() From 0edd38c349df5bfdaa864cb031dd63a561fd1e4f Mon Sep 17 00:00:00 2001 From: algosketch Date: Fri, 26 Jul 2024 02:24:50 +0900 Subject: [PATCH 13/16] =?UTF-8?q?feat=20:=20=EC=84=A0=EB=AC=BC=20=EB=93=B1?= =?UTF-8?q?=EB=A1=9D=20=EC=8B=A4=ED=8C=A8=EC=8B=9C=20=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EC=96=BC=EB=A1=9C=EA=B7=B8=20=EC=84=A4=EB=AA=85=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../boolti/presentation/screen/home/GiftDialog.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt index a5f9b5a7..8e712c82 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt @@ -1,13 +1,17 @@ package com.nexters.boolti.presentation.screen.home +import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import com.nexters.boolti.presentation.R import com.nexters.boolti.presentation.component.BTDialog import com.nexters.boolti.presentation.theme.Grey15 +import com.nexters.boolti.presentation.theme.Grey50 @Composable fun GiftDialog( @@ -65,5 +69,15 @@ fun GiftDialog( textAlign = TextAlign.Center ), ) + if (status == GiftStatus.FAILED) { + Text( + modifier = Modifier.padding(top = 4.dp), + text = stringResource(id = R.string.gift_registration_failed_dialog), + style = MaterialTheme.typography.bodySmall.copy( + color = Grey50, + textAlign = TextAlign.Center + ), + ) + } } } \ No newline at end of file From a77a9aa70d7f5ab5a0fd10277be656fbbb4c6919 Mon Sep 17 00:00:00 2001 From: HamBP Date: Sun, 28 Jul 2024 18:59:49 +0900 Subject: [PATCH 14/16] =?UTF-8?q?refactor=20:=20giftResponse=EC=9D=98=20us?= =?UTF-8?q?erId=20=EA=B5=AC=EB=B6=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nexters/boolti/data/network/response/GiftResponse.kt | 5 +++-- domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt | 2 +- .../nexters/boolti/presentation/screen/home/HomeViewModel.kt | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt b/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt index 061f8de2..6389fe11 100644 --- a/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt +++ b/data/src/main/java/com/nexters/boolti/data/network/response/GiftResponse.kt @@ -2,12 +2,13 @@ package com.nexters.boolti.data.network.response import com.nexters.boolti.data.util.toLocalDate import com.nexters.boolti.domain.model.Gift +import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class GiftResponse( val id: String, - val userId: String, + @SerialName("userId") val senderUserId: String, val giftUuid: String, val orderId: String?, val reservationId: String, @@ -24,7 +25,7 @@ data class GiftResponse( fun toDomain(): Gift { return Gift( id = id, - userId = userId, + senderUserId = senderUserId, uuid = giftUuid, orderId = orderId, reservationId = reservationId, diff --git a/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt b/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt index 989a7f41..c5733e8a 100644 --- a/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt +++ b/domain/src/main/java/com/nexters/boolti/domain/model/Gift.kt @@ -4,7 +4,7 @@ import java.time.LocalDate data class Gift( val id: String, - val userId: String, + val senderUserId: String, val uuid: String, val orderId: String?, val reservationId: String, diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt index 710cd0cc..8c475b55 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/HomeViewModel.kt @@ -84,7 +84,7 @@ class HomeViewModel @Inject constructor( val senderId = giftRepository .getGift(giftUuid) .first() - .userId + .senderUserId val myUserId = authRepository.cachedUser.first()?.id ?: return@launch From a9cbfbaecfef0f1ce23bb51d80ff2e34c00af4b0 Mon Sep 17 00:00:00 2001 From: HamBP Date: Sun, 28 Jul 2024 19:10:37 +0900 Subject: [PATCH 15/16] =?UTF-8?q?refactor=20:=20GiftDialog=EC=9D=98=20hasN?= =?UTF-8?q?egativeButton=20=ED=8C=8C=EB=9D=BC=EB=AF=B8=ED=84=B0=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/nexters/boolti/presentation/component/BTDialog.kt | 7 +++---- .../nexters/boolti/presentation/screen/home/GiftDialog.kt | 3 +-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt index a0d34885..cb348eac 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt @@ -39,9 +39,8 @@ fun BTDialog( enableDismiss: Boolean = true, showCloseButton: Boolean = true, onDismiss: () -> Unit = {}, - hasNegativeButton: Boolean = false, negativeButtonLabel: String = stringResource(R.string.cancel), - onClickNegativeButton: () -> Unit = {}, + onClickNegativeButton: (() -> Unit)? = null, positiveButtonLabel: String = stringResource(R.string.btn_ok), positiveButtonEnabled: Boolean = true, horizontalAlignment: Alignment.Horizontal = Alignment.CenterHorizontally, @@ -89,7 +88,7 @@ fun BTDialog( Row( horizontalArrangement = Arrangement.spacedBy(9.dp) ) { - if (hasNegativeButton) { + if (onClickNegativeButton != null) { MainButton( modifier = Modifier.weight(1f), label = negativeButtonLabel, @@ -130,7 +129,7 @@ fun BTDialogHavingNegativeButtonPreview() { BooltiTheme { Surface { BTDialog( - hasNegativeButton = true + onClickNegativeButton = {} ) { Text(text = "관리자 코드로 입장 확인") } diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt index 8e712c82..1e7fb311 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/screen/home/GiftDialog.kt @@ -59,8 +59,7 @@ fun GiftDialog( onDismiss = onDismiss, onClickPositiveButton = action, positiveButtonLabel = stringResource(id = buttonTextRes), - hasNegativeButton = hasNegativeButton, - onClickNegativeButton = onFailed + onClickNegativeButton = if(hasNegativeButton) onFailed else null ) { Text( text = stringResource(id = textRes), From a01afd1a8059c49c1118cc3d5a7db27ee5ab802d Mon Sep 17 00:00:00 2001 From: HamBP Date: Sun, 28 Jul 2024 19:11:35 +0900 Subject: [PATCH 16/16] =?UTF-8?q?fix=20:=20=EB=94=94=EC=9E=90=EC=9D=B4?= =?UTF-8?q?=EB=84=88=20=EB=AA=B0=EB=9E=98=209dp=20->=208dp=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/nexters/boolti/presentation/component/BTDialog.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt index cb348eac..94a08efe 100644 --- a/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt +++ b/presentation/src/main/java/com/nexters/boolti/presentation/component/BTDialog.kt @@ -86,7 +86,7 @@ fun BTDialog( content() Spacer(modifier = Modifier.size(28.dp)) Row( - horizontalArrangement = Arrangement.spacedBy(9.dp) + horizontalArrangement = Arrangement.spacedBy(8.dp) ) { if (onClickNegativeButton != null) { MainButton(