From 0fe808eb38074193a4a25c6683a7c8fce3eea3d5 Mon Sep 17 00:00:00 2001 From: Jokwanhee Date: Mon, 26 Aug 2024 01:40:56 +0900 Subject: [PATCH] =?UTF-8?q?[feat/#123]=20=EC=8B=9C=EC=95=BC=EC=B0=BE?= =?UTF-8?q?=EA=B8=B0=202=EC=B0=A8=20MVP=204=EB=B2=88=EC=A7=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84...?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../viewfinder/ResponseBlockReviewDto.kt | 12 ++++--- .../com/dpm/presentation/home/HomeActivity.kt | 24 ++++++++++++- .../presentation/seatreview/ReviewActivity.kt | 28 ++++++++++++--- .../seatreview/SelectViewImageActivity.kt | 35 +++++++++++++++---- .../dialog/view/ViewUploadDialog.kt | 13 +++++-- .../seatreview/sample/ReviewData.kt | 7 ++++ .../viewfinder/compose/StadiumDetailScreen.kt | 27 ++++++++++++-- 7 files changed, 124 insertions(+), 22 deletions(-) diff --git a/data/src/main/java/com/dpm/data/model/response/viewfinder/ResponseBlockReviewDto.kt b/data/src/main/java/com/dpm/data/model/response/viewfinder/ResponseBlockReviewDto.kt index 42993643..c9f8695d 100644 --- a/data/src/main/java/com/dpm/data/model/response/viewfinder/ResponseBlockReviewDto.kt +++ b/data/src/main/java/com/dpm/data/model/response/viewfinder/ResponseBlockReviewDto.kt @@ -73,7 +73,11 @@ data class ResponseBlockReviewDto( val scrapsCount: Long, @SerialName("reviewType") val reviewType: String?, - ) { + @SerialName("isLiked") + val isLiked: Boolean, + @SerialName("isScrapped") + val isScrapped: Boolean, + ) { @Serializable data class ResponseReviewImageDto( @SerialName("id") @@ -198,11 +202,11 @@ fun ResponseBlockReviewDto.ResponseReviewDto.toReviewResponse() = content = content ?: "", images = images.map { it.toReviewImageResponse() }, keywords = keywords.map { it.toReviewKeywordResponse() }, - isLike = false, - isScrap = false, + isLike = isLiked, + isScrap = isScrapped, likesCount = likesCount, scrapsCount = scrapsCount, - reviewType = reviewType ?: "" + reviewType = reviewType ?: "", ) fun ResponseBlockReviewDto.ResponseLocationDto.toLocationResponse() = diff --git a/presentation/src/main/java/com/dpm/presentation/home/HomeActivity.kt b/presentation/src/main/java/com/dpm/presentation/home/HomeActivity.kt index f61c1850..c745f293 100644 --- a/presentation/src/main/java/com/dpm/presentation/home/HomeActivity.kt +++ b/presentation/src/main/java/com/dpm/presentation/home/HomeActivity.kt @@ -102,7 +102,15 @@ class HomeActivity : BaseActivity( endMessage = "확인하러 가기", marginBottom = 93, ) { - // TODO : onclick -> 방금 작성한 시야 후기 상세페이지 게시물 화면으로 이동 + val reviewData = intent.getCompatibleParcelableExtra(REVIEW_DATA) + if (reviewData != null) { + Intent(this@HomeActivity, StadiumDetailActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + putExtra(SchemeKey.STADIUM_ID, reviewData.stadiumId) + putExtra(SchemeKey.BLOCK_CODE, reviewData.blockCode) + putExtra(SchemeKey.REVIEW_ID, reviewData.reviewId) + }.let { startActivity(it) } + } }.show() } } @@ -298,9 +306,23 @@ class HomeActivity : BaseActivity( val navReview = intent.getCompatibleParcelableExtra(SchemeKey.NAV_REVIEW) if (navReview != null) { Intent(this, StadiumDetailActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) putExtra(SchemeKey.STADIUM_ID, navReview.stadiumId) putExtra(SchemeKey.BLOCK_CODE, navReview.blockCode) }.let { startActivity(it) } } + navigateToReviewDetail() + } + + private fun navigateToReviewDetail() { + val navReviewDetail = intent.getCompatibleParcelableExtra(SchemeKey.NAV_REVIEW_DETAIL) + if (navReviewDetail != null) { + Intent(this, StadiumDetailActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + putExtra(SchemeKey.STADIUM_ID, navReviewDetail.stadiumId) + putExtra(SchemeKey.BLOCK_CODE, navReviewDetail.blockCode) + putExtra(SchemeKey.REVIEW_ID, navReviewDetail.reviewId) + }.let { startActivity(it) } + } } } \ No newline at end of file diff --git a/presentation/src/main/java/com/dpm/presentation/seatreview/ReviewActivity.kt b/presentation/src/main/java/com/dpm/presentation/seatreview/ReviewActivity.kt index 7c46c1a2..bd7a60e0 100644 --- a/presentation/src/main/java/com/dpm/presentation/seatreview/ReviewActivity.kt +++ b/presentation/src/main/java/com/dpm/presentation/seatreview/ReviewActivity.kt @@ -57,7 +57,9 @@ class ReviewActivity : BaseActivity({ } private val viewModel by viewModels() - private val method by lazy { intent.getStringExtra(METHOD_KEY)?.let { ReviewMethod.valueOf(it) } } + private val method by lazy { + intent.getStringExtra(METHOD_KEY)?.let { ReviewMethod.valueOf(it) } + } private val selectedImage: List by lazy { listOf( binding.ivFirstImage, @@ -125,11 +127,13 @@ class ReviewActivity : BaseActivity({ binding.tvAddImage.text = "야구장 시야 사진을\n올려주세요" binding.tvReviewMySeat.text = "내 시야 후기" } + ReviewMethod.FEED -> { binding.tvTitle.text = "경기의 순간을 간직해보세요" binding.tvAddImage.text = "직관후기 사진을\n올려주세요" binding.tvReviewMySeat.text = "내 직관 후기" } + null -> {} } } @@ -276,7 +280,11 @@ class ReviewActivity : BaseActivity({ } observeReviewViewModel() } - is UiState.Failure -> { toast("오류가 발생했습니다") } + + is UiState.Failure -> { + toast("오류가 발생했습니다") + } + is UiState.Loading -> {} is UiState.Empty -> {} else -> {} @@ -328,6 +336,7 @@ class ReviewActivity : BaseActivity({ viewModel.setSelectedImages(selectedImageUris) } } + private fun updateSelectedImages() { with(binding) { layoutAddDefaultImage.isVisible = selectedImageUris.isEmpty() @@ -355,6 +364,7 @@ class ReviewActivity : BaseActivity({ tvImageCount.text = selectedImageUris.size.toString() } } + private fun updateNextButtonState() { val isSelectedDateFilled = viewModel.selectedDate.value.isNotEmpty() val isSelectedImageFilled = viewModel.selectedImages.value.isNotEmpty() @@ -366,9 +376,9 @@ class ReviewActivity : BaseActivity({ with(binding.tvUploadBtn) { val isReadyToUpload = isSelectedDateFilled && isSelectedImageFilled && - (isSelectedGoodBtnFilled || isSelectedBadBtnFilled) && - isSelectedBlockFilled && - (isSelectedColumnFilled || isSelectedNumberFilled) + (isSelectedGoodBtnFilled || isSelectedBadBtnFilled) && + isSelectedBlockFilled && + (isSelectedColumnFilled || isSelectedNumberFilled) if (isReadyToUpload) { setBackgroundResource(R.drawable.rect_action_enabled_fill_8) @@ -409,13 +419,16 @@ class ReviewActivity : BaseActivity({ binding.tvUploadBtn.setBackgroundResource(R.drawable.rect_action_disabled_fill_8) makeSpotImageAppbar("내 시야 후기를 등록해주세요") } + !(isSelectedBlockFilled && (isSelectedColumnFilled || isSelectedNumberFilled)) && (isSelectedGoodBtnFilled || isSelectedBadBtnFilled) -> { binding.tvUploadBtn.setBackgroundResource(R.drawable.rect_action_disabled_fill_8) makeSpotImageAppbar("좌석을 선택해주세요") } + ((!isSelectedGoodBtnFilled && !isSelectedBadBtnFilled) || !(isSelectedBlockFilled && (isSelectedColumnFilled || isSelectedNumberFilled))) -> { binding.tvUploadBtn.setBackgroundResource(R.drawable.rect_action_disabled_fill_8) } + else -> { val uniqueImageUris = selectedImageUris.distinct() uniqueImageUris.forEach { imageUriString -> @@ -465,9 +478,11 @@ class ReviewActivity : BaseActivity({ ReviewMethod.VIEW -> { viewModel.postSeatReview(ReviewMethod.VIEW) } + ReviewMethod.FEED -> { viewModel.postSeatReview(ReviewMethod.FEED) } + null -> {} } } @@ -498,12 +513,15 @@ class ReviewActivity : BaseActivity({ ) dialogType?.let { Intent(this, HomeActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) putExtra(DIALOG_TYPE, dialogType) putExtra(REVIEW_DATA, reviewData) + finish() startActivity(this) } } } + is UiState.Failure -> { toast("리뷰 등록 실패: $state") } diff --git a/presentation/src/main/java/com/dpm/presentation/seatreview/SelectViewImageActivity.kt b/presentation/src/main/java/com/dpm/presentation/seatreview/SelectViewImageActivity.kt index 57739af7..f20a8f41 100644 --- a/presentation/src/main/java/com/dpm/presentation/seatreview/SelectViewImageActivity.kt +++ b/presentation/src/main/java/com/dpm/presentation/seatreview/SelectViewImageActivity.kt @@ -13,11 +13,11 @@ import coil.transform.RoundedCornersTransformation import com.depromeet.presentation.R import com.depromeet.presentation.databinding.ActivitySelectViewImageBinding import com.dpm.core.base.BaseActivity +import com.dpm.core.state.UiState import com.dpm.domain.model.seatreview.ReviewMethod import com.dpm.presentation.extension.setOnSingleClickListener import com.dpm.presentation.home.HomeActivity import com.dpm.presentation.seatreview.adapter.SelectKeywordAdapter -import com.dpm.presentation.seatreview.dialog.feed.FeedUploadDialog import com.dpm.presentation.seatreview.viewmodel.ReviewViewModel import dagger.hilt.android.AndroidEntryPoint @@ -40,7 +40,7 @@ class SelectViewImageActivity : BaseActivity({ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) initView() - observeSelectedImageUris() + initObserve() } private fun initView() { @@ -56,6 +56,32 @@ class SelectViewImageActivity : BaseActivity({ initEvent() } + private fun initObserve() { + observeSelectedImageUris() + viewModel.postReviewState.asLiveData().observe(this) { uiState -> + when (uiState) { + is UiState.Success -> { + var reviewData = intent.getParcelableExtra(REVIEW_DATA) + reviewData = reviewData?.copy( + reviewId = uiState.data.id + ) + + Intent(this, HomeActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + putExtra(UPLOAD_SNACKBAR, true) + putExtra(REVIEW_DATA,reviewData) + }.let { + finish() + startActivity(it) + } + } + is UiState.Empty -> Unit + is UiState.Failure -> Unit + is UiState.Loading -> Unit + } + } + } + private fun updateImageViews(urls: List) { val selectImages = listOf( binding.clFirstImage to binding.ivFirstImage, @@ -158,11 +184,6 @@ class SelectViewImageActivity : BaseActivity({ } viewModel.postSeatReview(ReviewMethod.VIEW) - startActivity( - Intent(this, HomeActivity::class.java) - .putExtra(UPLOAD_SNACKBAR, true) - .putExtra(REVIEW_DATA,reviewData) - ); finish() } binding.ivExit.setOnSingleClickListener { startActivity(Intent(this, HomeActivity::class.java)) diff --git a/presentation/src/main/java/com/dpm/presentation/seatreview/dialog/view/ViewUploadDialog.kt b/presentation/src/main/java/com/dpm/presentation/seatreview/dialog/view/ViewUploadDialog.kt index 2c6703a6..d17ac4f1 100644 --- a/presentation/src/main/java/com/dpm/presentation/seatreview/dialog/view/ViewUploadDialog.kt +++ b/presentation/src/main/java/com/dpm/presentation/seatreview/dialog/view/ViewUploadDialog.kt @@ -8,7 +8,11 @@ import com.depromeet.presentation.R import com.depromeet.presentation.databinding.FragmentViewUploadDialogBinding import com.dpm.core.base.BindingDialogFragment import com.dpm.presentation.extension.setOnSingleClickListener +import com.dpm.presentation.home.HomeActivity +import com.dpm.presentation.scheme.SchemeKey +import com.dpm.presentation.scheme.viewmodel.SchemeState import com.dpm.presentation.viewfinder.StadiumDetailActivity +import toNavReviewDetail class ViewUploadDialog : BindingDialogFragment( R.layout.fragment_view_upload_dialog, @@ -35,8 +39,13 @@ class ViewUploadDialog : BindingDialogFragment( dismiss() } binding.btnConfirmReview.setOnSingleClickListener { - // TODO : 방금 작성한 시야 후기 상세 페이지 게시물 화면으로 이동 - startActivity(Intent(requireContext(), StadiumDetailActivity::class.java)) + if (reviewData != null) { + val navReviewDetail = reviewData.toNavReviewDetail() + Intent(requireContext(), HomeActivity::class.java).apply { + addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) + putExtra(SchemeKey.NAV_REVIEW_DETAIL, navReviewDetail) + }.let { startActivity(it) } + } } } } diff --git a/presentation/src/main/java/com/dpm/presentation/seatreview/sample/ReviewData.kt b/presentation/src/main/java/com/dpm/presentation/seatreview/sample/ReviewData.kt index b16fc3b0..061853e5 100644 --- a/presentation/src/main/java/com/dpm/presentation/seatreview/sample/ReviewData.kt +++ b/presentation/src/main/java/com/dpm/presentation/seatreview/sample/ReviewData.kt @@ -1,4 +1,5 @@ import android.os.Parcelable +import com.dpm.presentation.scheme.viewmodel.SchemeState import kotlinx.parcelize.Parcelize @Parcelize @@ -15,3 +16,9 @@ data class ReviewData( val detailReviewText: String, val selectedDate: String, ) : Parcelable + +fun ReviewData.toNavReviewDetail() = SchemeState.NavReviewDetail( + stadiumId = stadiumId, + blockCode = blockCode, + reviewId = reviewId +) diff --git a/presentation/src/main/java/com/dpm/presentation/viewfinder/compose/StadiumDetailScreen.kt b/presentation/src/main/java/com/dpm/presentation/viewfinder/compose/StadiumDetailScreen.kt index 51178be4..ac167a28 100644 --- a/presentation/src/main/java/com/dpm/presentation/viewfinder/compose/StadiumDetailScreen.kt +++ b/presentation/src/main/java/com/dpm/presentation/viewfinder/compose/StadiumDetailScreen.kt @@ -14,7 +14,9 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue +import androidx.compose.runtime.withFrameNanos import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext @@ -36,6 +38,8 @@ import com.dpm.presentation.util.toTitle import com.dpm.presentation.viewfinder.StadiumDetailActivity import com.dpm.presentation.viewfinder.uistate.StadiumDetailUiState import com.dpm.presentation.viewfinder.viewmodel.StadiumDetailViewModel +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import timber.log.Timber @OptIn(ExperimentalFoundationApi::class) @@ -63,10 +67,27 @@ fun StadiumDetailScreen( val detailUiState by viewModel.detailUiState.collectAsStateWithLifecycle() val currentIndex by viewModel.currentIndex.collectAsStateWithLifecycle() - LaunchedEffect(key1 = scrollState) { - verticalScrollState.scrollToItem(0) - viewModel.updateScrollState(false) + if (viewModel.reviewId == 0){ + verticalScrollState.scrollToItem(0) + viewModel.updateScrollState(false) + } + } + + LaunchedEffect(key1 = detailUiState) { + if (viewModel.reviewId != 0) { + when (val data = detailUiState) { + is StadiumDetailUiState.ReviewsData -> { + val index = data.reviews.indexOfFirst { it.id.toInt() == viewModel.reviewId } + if (index != -1){ + verticalScrollState.scrollToItem(index + 1) + viewModel.reviewId = 0 + } + } + + else -> Unit + } + } } LaunchedEffect(key1 = verticalScrollState.firstVisibleItemScrollOffset) {