From 555fee1e58c975739aed6a9e858df762f38a0a96 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sun, 28 Jan 2024 22:50:48 +0900 Subject: [PATCH 01/16] =?UTF-8?q?[FIX]=20#314=20=EC=BD=94=EC=8A=A4=20?= =?UTF-8?q?=EB=B0=9C=EA=B2=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=EC=97=90=20=EC=84=B1=EA=B3=B5=ED=96=88?= =?UTF-8?q?=EC=9D=84=20=EB=95=8C=EB=A7=8C=20=EB=B7=B0=EB=A5=BC=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0=EC=8B=9C=ED=82=A4=EB=8F=84=EB=A1=9D=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/discover/DiscoverFragment.kt | 24 ++++++++++++---- .../adapter/DiscoverMarathonAdapter.kt | 8 ++++++ .../adapter/DiscoverRecommendAdapter.kt | 11 ++++++-- .../multiview/DiscoverMultiViewAdapter.kt | 28 +++++++++++++++++++ 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt index bf3af0050..a657e4aa2 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/DiscoverFragment.kt @@ -429,12 +429,24 @@ class DiscoverFragment : BindingFragment(R.layout.fragm private fun setupCourseScrapStateObserver() { viewModel.courseScrapState.observe(viewLifecycleOwner) { state -> - if (state is UiStateV2.Failure) { - context?.showSnackbar( - anchorView = binding.root, - message = state.msg, - gravity = Gravity.TOP - ) + when (state) { + is UiStateV2.Success -> { + val response = state.data ?: return@observe + multiViewAdapter.updateCourseScrap( + publicCourseId = response.publicCourseId.toInt(), + scrap = response.scrapTF + ) + } + + is UiStateV2.Failure -> { + context?.showSnackbar( + anchorView = binding.root, + message = state.msg, + gravity = Gravity.TOP + ) + } + + else -> {} } } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverMarathonAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverMarathonAdapter.kt index 1e3f57f7e..d295a3fca 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverMarathonAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverMarathonAdapter.kt @@ -88,6 +88,14 @@ class DiscoverMarathonAdapter( notifyItemChanged(targetIndex) } + fun updateMarathonCourseScrap( + targetIndex: Int, + scrap: Boolean + ) { + currentList[targetIndex].scrap = scrap + notifyItemChanged(targetIndex) + } + companion object { private val diffUtil = ItemDiffCallback( onItemsTheSame = { old, new -> old.id == new.id }, diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverRecommendAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverRecommendAdapter.kt index 89996c7ba..6b23957c3 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverRecommendAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/DiscoverRecommendAdapter.kt @@ -63,8 +63,7 @@ class DiscoverRecommendAdapter( return@setOnClickListener } - view.isSelected = !view.isSelected - onHeartButtonClick.invoke(course.id, view.isSelected) + onHeartButtonClick.invoke(course.id, !view.isSelected) } } @@ -89,6 +88,14 @@ class DiscoverRecommendAdapter( notifyItemChanged(targetIndex) } + fun updateRecommendCourseScrap( + targetIndex: Int, + scrap: Boolean + ) { + currentList[targetIndex].scrap = scrap + notifyItemChanged(targetIndex) + } + fun addRecommendCourseNextPage(items: List) { val newList = currentList + items submitList(newList) diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/multiview/DiscoverMultiViewAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/multiview/DiscoverMultiViewAdapter.kt index 3604d78cb..fa32d53a0 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/multiview/DiscoverMultiViewAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/adapter/multiview/DiscoverMultiViewAdapter.kt @@ -130,4 +130,32 @@ class DiscoverMultiViewAdapter( } } } + + fun updateCourseScrap( + publicCourseId: Int, + scrap: Boolean + ) { + val multiViewItems = marathonCourses + recommendCourses + val targetItem = multiViewItems.find { item -> + item.id == publicCourseId + } ?: return + + when (targetItem) { + is MarathonCourse -> { + val targetIndex = marathonCourses.indexOf(targetItem) + multiViewHolderFactory.marathonCourseAdapter.updateMarathonCourseScrap( + targetIndex = targetIndex, + scrap = scrap + ) + } + + is RecommendCourse -> { + val targetIndex = recommendCourses.indexOf(targetItem) + multiViewHolderFactory.recommendCourseAdapter.updateRecommendCourseScrap( + targetIndex = targetIndex, + scrap = scrap + ) + } + } + } } \ No newline at end of file From 65413b01516cde3c99b38b6f1dabb8506dc44dc7 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sun, 28 Jan 2024 22:56:25 +0900 Subject: [PATCH 02/16] =?UTF-8?q?[UI]=20#314=20=EC=83=81=EC=84=B8=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=20=ED=85=8D=EC=8A=A4=ED=8A=B8=20=ED=81=AC=EA=B8=B0=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/activity_course_detail.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_course_detail.xml b/app/src/main/res/layout/activity_course_detail.xml index 32b5f29bb..5372cf3cc 100644 --- a/app/src/main/res/layout/activity_course_detail.xml +++ b/app/src/main/res/layout/activity_course_detail.xml @@ -323,7 +323,7 @@ android:fontFamily="@font/pretendard_semibold" android:text="@{courseDetail.scrapCount}" android:textColor="@color/G2" - android:textSize="10sp" + android:textSize="11sp" app:layout_constraintEnd_toEndOf="@id/iv_course_detail_scrap" app:layout_constraintStart_toStartOf="@id/iv_course_detail_scrap" app:layout_constraintTop_toBottomOf="@id/iv_course_detail_scrap" @@ -333,8 +333,8 @@ android:id="@+id/btn_course_detail_start_run" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginTop="8dp" android:layout_marginStart="17dp" + android:layout_marginTop="8dp" android:layout_marginEnd="12dp" android:background="@drawable/course_detail_finish_btn" android:fontFamily="@font/pretendard_semibold" From 5344fa1920ee4092b6baca567f70ddf57afa3de0 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sun, 28 Jan 2024 22:57:33 +0900 Subject: [PATCH 03/16] =?UTF-8?q?[FIX]=20#314=20=EC=83=81=EC=84=B8?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=81=AC=EB=9E=A9=20=EC=84=9C=EB=B2=84=20=ED=86=B5=EC=8B=A0?= =?UTF-8?q?=EC=97=90=20=EC=84=B1=EA=B3=B5=ED=95=9C=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=EC=97=90=EB=A7=8C=20=EB=B7=B0=20=EA=B0=B1=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/detail/CourseDetailActivity.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt index 59c90fde6..eb7a7cf07 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailActivity.kt @@ -359,8 +359,7 @@ class CourseDetailActivity : return@setOnClickListener } - it.isSelected = !it.isSelected - viewModel.postCourseScrap(publicCourseId, it.isSelected) + viewModel.postCourseScrap(publicCourseId, !it.isSelected) } } @@ -581,8 +580,18 @@ class CourseDetailActivity : private fun setupCourseScrapStateObserver() { viewModel.courseScrapState.observe(this) { state -> - if (state is UiStateV2.Failure) { - showSnackbar(binding.root, state.msg) + when (state) { + is UiStateV2.Success -> { + val response = state.data ?: return@observe + binding.tvCourseDetailScrapCount.text = response.scrapCount.toString() + binding.ivCourseDetailScrap.isSelected = response.scrapTF + } + + is UiStateV2.Failure -> { + showSnackbar(binding.root, state.msg) + } + + else -> {} } } } From 781d10f57176c0645cdb6f350382d1c414137097 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sun, 28 Jan 2024 23:02:05 +0900 Subject: [PATCH 04/16] =?UTF-8?q?[CHORE]=20#314=20=EB=9D=BC=EC=9D=B4?= =?UTF-8?q?=EB=B8=8C=EB=8D=B0=EC=9D=B4=ED=84=B0=20var=20->=20val=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/presentation/detail/CourseDetailViewModel.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailViewModel.kt index 895cd711b..62d0be2e2 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/detail/CourseDetailViewModel.kt @@ -26,19 +26,19 @@ class CourseDetailViewModel @Inject constructor( private val courseRepository: CourseRepository, private val userRepository: UserRepository ) : ViewModel() { // 서버통신 코드 - private var _courseGetState = MutableLiveData>() + private val _courseGetState = MutableLiveData>() val courseGetState: LiveData> get() = _courseGetState - private var _coursePatchState = MutableLiveData>() + private val _coursePatchState = MutableLiveData>() val coursePatchState: LiveData> get() = _coursePatchState - private var _courseDeleteState = MutableLiveData>() + private val _courseDeleteState = MutableLiveData>() val courseDeleteState: LiveData> get() = _courseDeleteState - private var _courseScrapState = MutableLiveData>() + private val _courseScrapState = MutableLiveData>() val courseScrapState: LiveData> get() = _courseScrapState From ffda301ab06dcbefc1e9b3e0ecad0635e8b29971 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sun, 28 Jan 2024 23:10:55 +0900 Subject: [PATCH 05/16] =?UTF-8?q?[FIX]=20#314=20=EC=BD=94=EC=8A=A4=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EC=8B=9C=20=EB=82=98=EC=98=A4=EB=8A=94=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=EC=97=90=EB=8F=84=20=EB=8F=99?= =?UTF-8?q?=EC=9D=BC=ED=95=9C=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../discover/search/DiscoverSearchActivity.kt | 22 +++++++++++++++++++ .../search/DiscoverSearchViewModel.kt | 14 +++++++++++- .../search/adapter/DiscoverSearchAdapter.kt | 18 ++++++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt index d93179ddc..3b1c64862 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchActivity.kt @@ -29,6 +29,7 @@ import com.runnect.runnect.util.extension.getCompatibleParcelableExtra import com.runnect.runnect.util.extension.hideKeyboard import com.runnect.runnect.util.extension.navigateToPreviousScreenWithAnimation import com.runnect.runnect.util.extension.showKeyboard +import com.runnect.runnect.util.extension.showSnackbar import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -141,6 +142,7 @@ class DiscoverSearchActivity : private fun addObserver() { setupCourseSearchStateObserver() + setupCourseScrapStateObserver() } private fun setupCourseSearchStateObserver() { @@ -182,6 +184,26 @@ class DiscoverSearchActivity : binding.pbDiscoverSearch.isVisible = false } + private fun setupCourseScrapStateObserver() { + viewModel.courseScrapState.observe(this) { state -> + when (state) { + is UiStateV2.Success -> { + val response = state.data ?: return@observe + searchAdapter.updateCourseScrap( + publicCourseId = response.publicCourseId.toInt(), + scrap = response.scrapTF + ) + } + + is UiStateV2.Failure -> { + showSnackbar(binding.root, state.msg) + } + + else -> {} + } + } + } + override fun dispatchTouchEvent(event: MotionEvent): Boolean { if (event.action == MotionEvent.ACTION_DOWN) { currentFocus?.let { view -> diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchViewModel.kt index e1905d39a..434cd670a 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/search/DiscoverSearchViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.runnect.runnect.data.dto.request.RequestPostCourseScrap +import com.runnect.runnect.data.dto.response.ResponsePostScrap import com.runnect.runnect.domain.entity.DiscoverSearchCourse import com.runnect.runnect.domain.repository.CourseRepository import com.runnect.runnect.presentation.state.UiStateV2 @@ -20,6 +21,10 @@ class DiscoverSearchViewModel @Inject constructor( val courseSearchState: LiveData?>> get() = _courseSearchState + private val _courseScrapState = MutableLiveData>() + val courseScrapState: LiveData> + get() = _courseScrapState + private var _clickedCourseId = -1 val clickedCourseId get() = _clickedCourseId @@ -50,11 +55,18 @@ class DiscoverSearchViewModel @Inject constructor( fun postCourseScrap(id: Int, scrapTF: Boolean) { viewModelScope.launch { + _courseScrapState.value = UiStateV2.Loading + courseRepository.postCourseScrap( RequestPostCourseScrap( publicCourseId = id, scrapTF = scrapTF.toString() ) - ) + ).onSuccess { response -> + _courseScrapState.value = UiStateV2.Success(response) + } + .onFailure { exception -> + _courseScrapState.value = UiStateV2.Failure(exception.message.toString()) + } } } } \ No newline at end of file diff --git a/app/src/main/java/com/runnect/runnect/presentation/discover/search/adapter/DiscoverSearchAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/discover/search/adapter/DiscoverSearchAdapter.kt index d946032c1..3ec9d7f61 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/discover/search/adapter/DiscoverSearchAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/discover/search/adapter/DiscoverSearchAdapter.kt @@ -28,7 +28,7 @@ class DiscoverSearchAdapter( } inner class DiscoverSearchViewHolder( - private val binding: com.runnect.runnect.databinding.ItemDiscoverSearchBinding + private val binding: ItemDiscoverSearchBinding ) : RecyclerView.ViewHolder(binding.root) { fun bind(course: DiscoverSearchCourse) { with(binding) { @@ -45,8 +45,7 @@ class DiscoverSearchAdapter( course: DiscoverSearchCourse ) { imageView.setOnClickListener { view -> - view.isSelected = !view.isSelected - onHeartButtonClick(course.id, view.isSelected) + onHeartButtonClick(course.id, !view.isSelected) } } @@ -71,6 +70,19 @@ class DiscoverSearchAdapter( } } + fun updateCourseScrap( + publicCourseId: Int, + scrap: Boolean + ) { + currentList.forEachIndexed { index, course -> + if (course.id == publicCourseId) { + course.scrap = scrap + notifyItemChanged(index) + return@forEachIndexed + } + } + } + companion object { private val diffUtil = ItemDiffCallback( onItemsTheSame = { old, new -> old.id == new.id }, From ebb56b8f2ad12a2d94ad325dddd64232d9eb903f Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 18:27:31 +0900 Subject: [PATCH 06/16] =?UTF-8?q?[FIX]=20#314=20=ED=94=84=EB=9E=98?= =?UTF-8?q?=EA=B7=B8=EB=A8=BC=ED=8A=B8=20LifecycleOwner=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(=EC=95=A1=ED=8B=B0=EB=B9=84=ED=8B=B0=20=EB=A7=90?= =?UTF-8?q?=EA=B3=A0=20=ED=94=84=EB=9E=98=EA=B7=B8=EB=A8=BC=ED=8A=B8=20?= =?UTF-8?q?=EB=B7=B0=EB=A1=9C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/presentation/storage/StorageScrapFragment.kt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index ccf3b55ae..8d16d800d 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -31,14 +31,13 @@ class StorageScrapFragment : OnHeartButtonClick, OnScrapItemClick, ItemCount { - val viewModel: StorageViewModel by viewModels() - lateinit var storageScrapAdapter: StorageScrapAdapter + private lateinit var storageScrapAdapter: StorageScrapAdapter override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding.lifecycleOwner = viewLifecycleOwner - binding.lifecycleOwner = requireActivity() initLayout() initAdapter() getCourse() From 62e239cad4de2656759d8a4de3a3212ce31b68ed Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 19:25:59 +0900 Subject: [PATCH 07/16] =?UTF-8?q?[FIX]=20#314=20LayoutParams=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20=EC=BA=90=EC=8A=A4=ED=8C=85=20=EC=95=88=EB=90=98?= =?UTF-8?q?=EB=A9=B4=20null=20=EB=B0=98=ED=99=98=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/runnect/runnect/util/extension/ContextExt.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/util/extension/ContextExt.kt b/app/src/main/java/com/runnect/runnect/util/extension/ContextExt.kt index cafff350e..7caac816e 100644 --- a/app/src/main/java/com/runnect/runnect/util/extension/ContextExt.kt +++ b/app/src/main/java/com/runnect/runnect/util/extension/ContextExt.kt @@ -175,8 +175,8 @@ fun Context.showToast(message: String) { fun Context.showSnackbar(anchorView: View, message: String, @GravityFlag gravity: Int = Gravity.BOTTOM) { val snackbar = Snackbar.make(anchorView, message, Snackbar.LENGTH_SHORT) - val layoutParams = snackbar.view.layoutParams as CoordinatorLayout.LayoutParams - layoutParams.apply { + val layoutParams = snackbar.view.layoutParams as? CoordinatorLayout.LayoutParams + layoutParams?.apply { this.gravity = gravity snackbar.view.layoutParams = this } From 44552311e931d9de3310b84917ca9d266672f6c5 Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 19:47:44 +0900 Subject: [PATCH 08/16] =?UTF-8?q?[MOD]=20#314=20=EB=82=B4=EA=B0=80=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=9E=A9=ED=95=9C=20=EC=BD=94=EC=8A=A4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=ED=95=98=EB=8A=94=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=20=EC=BD=94=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/ResponseGetMyScrapCourse.kt | 80 +++++++++---------- .../data/repository/StorageRepositoryImpl.kt | 25 +----- .../runnect/data/service/CourseService.kt | 8 +- .../source/remote/RemoteStorageDataSource.kt | 7 +- .../domain/repository/StorageRepository.kt | 4 +- .../main/res/layout/item_storage_scrap.xml | 2 +- 6 files changed, 54 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/data/dto/response/ResponseGetMyScrapCourse.kt b/app/src/main/java/com/runnect/runnect/data/dto/response/ResponseGetMyScrapCourse.kt index cb8ddc59b..e9c11701e 100644 --- a/app/src/main/java/com/runnect/runnect/data/dto/response/ResponseGetMyScrapCourse.kt +++ b/app/src/main/java/com/runnect/runnect/data/dto/response/ResponseGetMyScrapCourse.kt @@ -1,55 +1,55 @@ package com.runnect.runnect.data.dto.response - +import com.runnect.runnect.domain.entity.MyScrapCourse import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable @Serializable data class ResponseGetMyScrapCourse( - @SerialName("data") - val data: Data, - @SerialName("message") - val message: String, - @SerialName("status") - val status: Int, - @SerialName("success") - val success: Boolean, + @SerialName("user") + val user: User, + @SerialName("scraps") + val scraps: List, ) { @Serializable - data class Data( - @SerialName("Scraps") - val scraps: List, - @SerialName("user") - val user: User, + data class User( + @SerialName("userId") + val id: Int, + ) + + @Serializable + data class Scrap( + @SerialName("courseId") + val courseId: Int, + @SerialName("departure") + val departure: Departure, + @SerialName("id") + val id: Int, + @SerialName("image") + val image: String, + @SerialName("publicCourseId") + val publicCourseId: Int, + @SerialName("title") + val title: String, ) { @Serializable - data class Scrap( - @SerialName("courseId") - val courseId: Int, - @SerialName("departure") - val departure: Departure, - @SerialName("id") - val id: Int, - @SerialName("image") - val image: String, - @SerialName("publicCourseId") - val publicCourseId: Int, - @SerialName("title") - val title: String, - ) { - @Serializable - data class Departure( - @SerialName("city") - val city: String, - @SerialName("region") - val region: String, - ) - } + data class Departure( + @SerialName("city") + val city: String, + @SerialName("region") + val region: String, + ) + } - @Serializable - data class User( - @SerialName("id") - val id: Int, + fun toMyScrapCourses(): List = scraps.map { course -> + MyScrapCourse( + courseId = course.courseId, + id = course.id, + publicCourseId = course.publicCourseId, + image = course.image, + city = course.departure.city, + region = course.departure.region, + title = course.title ) } } \ No newline at end of file diff --git a/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt b/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt index 2f0cf5201..cae7c591b 100644 --- a/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt +++ b/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt @@ -1,10 +1,9 @@ package com.runnect.runnect.data.repository import com.runnect.runnect.data.dto.MyDrawCourse -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse import com.runnect.runnect.data.dto.response.ResponseGetMyDrawCourse -import com.runnect.runnect.data.dto.response.ResponseGetMyScrapCourse import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse import com.runnect.runnect.data.source.remote.RemoteStorageDataSource import com.runnect.runnect.domain.repository.StorageRepository @@ -35,24 +34,8 @@ class StorageRepositoryImpl @Inject constructor(private val remoteStorageDataSou return remoteStorageDataSource.deleteMyDrawCourse(deleteCourseList = deleteCourseList) } - override suspend fun getMyScrapCourse(): MutableList { - return changeMyScrapData( - data = remoteStorageDataSource.getMyScrapCourse().body()!!.data.scraps - ).toMutableList() - } - - private fun changeMyScrapData(data: List): List { - val changedData = data.map { - MyScrapCourse( - courseId = it.courseId, - id = it.id, - publicCourseId = it.publicCourseId, - image = it.image, - city = it.departure.city, - region = it.departure.region, - title = it.title - ) + override suspend fun getMyScrapCourse(): Result?> = + runCatching { + remoteStorageDataSource.getMyScrapCourse().data?.toMyScrapCourses() } - return changedData - } } \ No newline at end of file diff --git a/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt b/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt index 96e0448f4..cc4ddc226 100644 --- a/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt +++ b/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt @@ -38,8 +38,7 @@ interface CourseService { ): BaseResponse @GET("/api/course/private/user") - suspend fun getMyCourseLoad( - ): ResponseGetDiscoverPick + suspend fun getMyCourseLoad(): ResponseGetDiscoverPick @POST("/api/public-course") suspend fun postUploadMyCourse( @@ -61,13 +60,12 @@ interface CourseService { //보관함 내가 그린 코스 가져오기 @GET("/api/course/user") - suspend fun getCourseList( + suspend fun getDrawCourseList( ): Response //보관함 스크랩 코스 가져오기 @GET("/api/scrap/user") - suspend fun getScrapList( - ): Response + suspend fun getScrapCourseList(): BaseResponse //내가 그린 코스 Detail 가져오기 @GET("/api/course/detail/{courseId}") diff --git a/app/src/main/java/com/runnect/runnect/data/source/remote/RemoteStorageDataSource.kt b/app/src/main/java/com/runnect/runnect/data/source/remote/RemoteStorageDataSource.kt index 1444323bb..c6c3558b3 100644 --- a/app/src/main/java/com/runnect/runnect/data/source/remote/RemoteStorageDataSource.kt +++ b/app/src/main/java/com/runnect/runnect/data/source/remote/RemoteStorageDataSource.kt @@ -5,16 +5,17 @@ import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse import com.runnect.runnect.data.dto.response.ResponseGetMyDrawCourse import com.runnect.runnect.data.dto.response.ResponseGetMyScrapCourse import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse +import com.runnect.runnect.data.dto.response.base.BaseResponse import retrofit2.Response import javax.inject.Inject class RemoteStorageDataSource @Inject constructor(private val courseService: CourseService) { suspend fun getMyDrawCourse(): Response = - courseService.getCourseList() + courseService.getDrawCourseList() suspend fun deleteMyDrawCourse(deleteCourseList: RequestPutMyDrawCourse): Response = courseService.deleteMyDrawCourse(deleteCourseList) - suspend fun getMyScrapCourse(): Response = - courseService.getScrapList() + suspend fun getMyScrapCourse(): BaseResponse = + courseService.getScrapCourseList() } \ No newline at end of file diff --git a/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt b/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt index 3ab37cd36..85150f2eb 100644 --- a/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt +++ b/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt @@ -1,7 +1,7 @@ package com.runnect.runnect.domain.repository import com.runnect.runnect.data.dto.MyDrawCourse -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse import retrofit2.Response @@ -9,5 +9,5 @@ import retrofit2.Response interface StorageRepository { suspend fun getMyDrawCourse(): MutableList? suspend fun deleteMyDrawCourse(deleteCourseList: RequestPutMyDrawCourse) : Response - suspend fun getMyScrapCourse(): MutableList? + suspend fun getMyScrapCourse(): Result?> } \ No newline at end of file diff --git a/app/src/main/res/layout/item_storage_scrap.xml b/app/src/main/res/layout/item_storage_scrap.xml index 82df4da5b..1da4408ef 100644 --- a/app/src/main/res/layout/item_storage_scrap.xml +++ b/app/src/main/res/layout/item_storage_scrap.xml @@ -7,7 +7,7 @@ + type="com.runnect.runnect.domain.entity.MyScrapCourse" /> Date: Mon, 29 Jan 2024 19:48:40 +0900 Subject: [PATCH 09/16] =?UTF-8?q?[MOD]=20#314=20=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=84=B0=20=ED=81=B4=EB=9E=98=EC=8A=A4=EC=9D=98=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?(data=20->=20domain)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/{data/dto => domain/entity}/MyScrapCourse.kt | 6 +++--- .../runnect/util/callback/listener/OnScrapItemClick.kt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename app/src/main/java/com/runnect/runnect/{data/dto => domain/entity}/MyScrapCourse.kt (74%) diff --git a/app/src/main/java/com/runnect/runnect/data/dto/MyScrapCourse.kt b/app/src/main/java/com/runnect/runnect/domain/entity/MyScrapCourse.kt similarity index 74% rename from app/src/main/java/com/runnect/runnect/data/dto/MyScrapCourse.kt rename to app/src/main/java/com/runnect/runnect/domain/entity/MyScrapCourse.kt index 1b2cbc13c..e33aac0b4 100644 --- a/app/src/main/java/com/runnect/runnect/data/dto/MyScrapCourse.kt +++ b/app/src/main/java/com/runnect/runnect/domain/entity/MyScrapCourse.kt @@ -1,4 +1,4 @@ -package com.runnect.runnect.data.dto +package com.runnect.runnect.domain.entity import android.os.Parcelable @@ -6,8 +6,8 @@ import kotlinx.android.parcel.Parcelize @Parcelize data class MyScrapCourse( - val courseId: Int?, - val id: Int?, + val courseId: Int, + val id: Int, val publicCourseId: Int, val image: String?, val city: String, diff --git a/app/src/main/java/com/runnect/runnect/util/callback/listener/OnScrapItemClick.kt b/app/src/main/java/com/runnect/runnect/util/callback/listener/OnScrapItemClick.kt index 935bff0c5..173a9b65b 100644 --- a/app/src/main/java/com/runnect/runnect/util/callback/listener/OnScrapItemClick.kt +++ b/app/src/main/java/com/runnect/runnect/util/callback/listener/OnScrapItemClick.kt @@ -1,6 +1,6 @@ package com.runnect.runnect.util.callback.listener -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse interface OnScrapItemClick { fun selectItem(item: MyScrapCourse) From 9a1fa3b3129979030de5f316ae747dd1e9d7e5b6 Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 19:49:37 +0900 Subject: [PATCH 10/16] =?UTF-8?q?[MOD]=20#314=20=EB=82=B4=EA=B0=80=20?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=9E=A9=ED=95=9C=20=EC=BD=94=EC=8A=A4=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=ED=9B=84=20=EB=B7=B0=EC=97=90=20=EB=B0=94?= =?UTF-8?q?=EC=9D=B8=EB=94=A9=20=ED=95=98=EB=8A=94=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/presentation/MainActivity.kt | 2 +- .../storage/StorageMyDrawFragment.kt | 2 +- .../storage/StorageScrapFragment.kt | 169 ++++++++++-------- .../presentation/storage/StorageViewModel.kt | 57 +++--- .../storage/adapter/StorageScrapAdapter.kt | 4 +- 5 files changed, 132 insertions(+), 102 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt b/app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt index 7bef940ae..af233bf8f 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/MainActivity.kt @@ -153,7 +153,7 @@ class MainActivity : BindingActivity(R.layout.activity_main } fun updateStorageScrapScreen() { - storageScrapFragment?.getCourse() + storageScrapFragment?.getMyScrapCourses() } } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt index 0c4d407d2..eda0d4ec2 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt @@ -258,7 +258,7 @@ class StorageMyDrawFragment : } private fun observeStorageState() { - viewModel.storageState.observe(viewLifecycleOwner) { + viewModel.myDrawCoursesGetState.observe(viewLifecycleOwner) { when (it) { UiState.Empty -> hideLoadingBar() UiState.Loading -> showLoadingBar() diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index 8d16d800d..ab3c256c6 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -11,23 +11,23 @@ import androidx.fragment.app.viewModels import androidx.recyclerview.widget.GridLayoutManager import com.runnect.runnect.R import com.runnect.runnect.binding.BindingFragment -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.databinding.FragmentStorageScrapBinding import com.runnect.runnect.presentation.MainActivity import com.runnect.runnect.presentation.detail.CourseDetailActivity import com.runnect.runnect.presentation.detail.CourseDetailRootScreen -import com.runnect.runnect.presentation.state.UiState +import com.runnect.runnect.presentation.state.UiStateV2 import com.runnect.runnect.presentation.storage.adapter.StorageScrapAdapter import com.runnect.runnect.util.custom.deco.GridSpacingItemDecoration import com.runnect.runnect.util.callback.ItemCount import com.runnect.runnect.util.callback.listener.OnHeartButtonClick import com.runnect.runnect.util.callback.listener.OnScrapItemClick +import com.runnect.runnect.util.extension.showSnackbar import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @AndroidEntryPoint -class StorageScrapFragment : - BindingFragment(R.layout.fragment_storage_scrap), +class StorageScrapFragment : BindingFragment(R.layout.fragment_storage_scrap), OnHeartButtonClick, OnScrapItemClick, ItemCount { @@ -38,60 +38,104 @@ class StorageScrapFragment : super.onViewCreated(view, savedInstanceState) binding.lifecycleOwner = viewLifecycleOwner + getMyScrapCourses() initLayout() initAdapter() - getCourse() - toScrapCourseBtn() + addListener() addObserver() - pullToRefresh() } - private fun pullToRefresh() { - binding.refreshLayout.setOnRefreshListener { - getCourse() - binding.refreshLayout.isRefreshing = false - } + fun getMyScrapCourses() { + viewModel.getMyScrapCoures() } - override fun onAttach(context: Context) { - super.onAttach(context) - if (context is MainActivity) { - MainActivity.storageScrapFragment = this + private fun initLayout() { + binding.recyclerViewStorageScrap.apply { + val context = context ?: return + layoutManager = GridLayoutManager(context, 2) + addItemDecoration( + GridSpacingItemDecoration( + context = context, + spanCount = 2, + horizontalSpaceSize = 6, + topSpaceSize = 20 + ) + ) } } - override fun onDestroy() { - super.onDestroy() - MainActivity.storageScrapFragment = null + private fun initAdapter() { + storageScrapAdapter = StorageScrapAdapter( + onScrapItemClick = this, + onHeartButtonClick = this, + itemCount = this + ).apply { + binding.recyclerViewStorageScrap.adapter = this + } } - override fun scrapCourse(id: Int, scrapTF: Boolean) { - viewModel.postCourseScrap(id, scrapTF) + private fun addListener() { + initGoToScrapButtonClickListener() + initRefreshLayoutListener() } - private fun initLayout() { - binding.recyclerViewStorageScrap - .layoutManager = GridLayoutManager(requireContext(), 2) - binding.recyclerViewStorageScrap.addItemDecoration( - GridSpacingItemDecoration( - context = requireContext(), - spanCount = 2, - horizontalSpaceSize = 6, - topSpaceSize = 20 + private fun initGoToScrapButtonClickListener() { + binding.btnStorageNoScrap.setOnClickListener { + isFromStorageScrap = true + + val intent = Intent(activity, MainActivity::class.java).apply { + putExtra(EXTRA_FRAGMENT_REPLACEMENT_DIRECTION, "fromMyScrap") + } + startActivity(intent) + requireActivity().overridePendingTransition( + R.anim.slide_in_right, + R.anim.slide_out_left ) - ) + } + } + + private fun initRefreshLayoutListener() { + binding.refreshLayout.setOnRefreshListener { + getMyScrapCourses() + binding.refreshLayout.isRefreshing = false + } } private fun addObserver() { observeItemSize() - observeStorageState() + setupMyScrapCourseGetStateObserver() } - private fun showLoadingBar() { + private fun setupMyScrapCourseGetStateObserver() { + viewModel.myScrapCoursesGetState.observe(viewLifecycleOwner) { state -> + when (state) { + is UiStateV2.Loading -> { + showLoadingProgressBar() + } + + is UiStateV2.Success -> { + dismissLoadingProgressBar() + storageScrapAdapter.submitList(state.data) + } + + is UiStateV2.Failure -> { + dismissLoadingProgressBar() + context?.showSnackbar( + anchorView = binding.root, + message = state.msg + ) + } + + else -> {} + } + } + } + + private fun showLoadingProgressBar() { binding.indeterminateBar.isVisible = true } - private fun hideLoadingBar() { + private fun dismissLoadingProgressBar() { binding.indeterminateBar.isVisible = false } @@ -121,53 +165,12 @@ class StorageScrapFragment : storageScrapAdapter.submitList(viewModel.getScrapListResult.value!!) } - private fun observeStorageState() { - viewModel.storageState.observe(viewLifecycleOwner) { - when (it) { - UiState.Empty -> hideLoadingBar() - UiState.Loading -> showLoadingBar() - UiState.Success -> { - hideLoadingBar() - showScrapResult() - updateAdapterData() - } - - UiState.Failure -> { - hideLoadingBar() - Timber.tag(ContentValues.TAG) - .d("Failure : ${viewModel.errorMessage}") - } - } - } - } - - private fun toScrapCourseBtn() { - binding.btnStorageNoScrap.setOnClickListener { - isFromStorageScrap = true - - val intent = Intent(activity, MainActivity::class.java).apply { - putExtra(EXTRA_FRAGMENT_REPLACEMENT_DIRECTION, "fromMyScrap") - } - startActivity(intent) - requireActivity().overridePendingTransition( - R.anim.slide_in_right, - R.anim.slide_out_left - ) - } - } - - - fun getCourse() { - viewModel.getScrapList() - } - override fun calcItemSize(itemCount: Int) { viewModel.itemSize.value = itemCount } - private fun initAdapter() { - storageScrapAdapter = StorageScrapAdapter(this, this, this) - binding.recyclerViewStorageScrap.adapter = storageScrapAdapter + override fun scrapCourse(id: Int, scrapTF: Boolean) { + viewModel.postCourseScrap(id, scrapTF) } override fun selectItem(item: MyScrapCourse) { @@ -183,6 +186,18 @@ class StorageScrapFragment : ) } + override fun onAttach(context: Context) { + super.onAttach(context) + if (context is MainActivity) { + MainActivity.storageScrapFragment = this + } + } + + override fun onDestroy() { + super.onDestroy() + MainActivity.storageScrapFragment = null + } + companion object { var isFromStorageScrap = false const val EXTRA_FRAGMENT_REPLACEMENT_DIRECTION = "fragmentReplacementDirection" diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt index a93d93224..48c1eccdb 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt @@ -6,12 +6,14 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.runnect.runnect.data.dto.MyDrawCourse -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.request.RequestPostCourseScrap import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse +import com.runnect.runnect.data.dto.response.ResponsePostScrap import com.runnect.runnect.domain.repository.CourseRepository import com.runnect.runnect.domain.repository.StorageRepository import com.runnect.runnect.presentation.state.UiState +import com.runnect.runnect.presentation.state.UiStateV2 import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import timber.log.Timber @@ -22,17 +24,25 @@ class StorageViewModel @Inject constructor( private val storageRepository: StorageRepository, private val courseRepository: CourseRepository ) : ViewModel() { - private var _myDrawCoursesDeleteState = MutableLiveData() + private val _myDrawCoursesDeleteState = MutableLiveData() val myDrawCourseDeleteState: LiveData get() = _myDrawCoursesDeleteState + private val _myDrawCoursesGetState = MutableLiveData(UiState.Empty) + val myDrawCoursesGetState: LiveData + get() = _myDrawCoursesGetState + private var _myDrawCourses = mutableListOf() val myDrawCourses: List get() = _myDrawCourses - private var _storageState = MutableLiveData(UiState.Empty) - val storageState: LiveData - get() = _storageState + private val _myScrapCoursesGetState = MutableLiveData>?>() + val myScrapCoursesGetState: LiveData>?> + get() = _myScrapCoursesGetState + + private val _courseScrapState = MutableLiveData>() + val courseScrapState: LiveData> + get() = _courseScrapState val getScrapListResult = MutableLiveData>() val errorMessage = MutableLiveData() @@ -46,16 +56,16 @@ class StorageViewModel @Inject constructor( fun getMyDrawList() { viewModelScope.launch { runCatching { - _storageState.value = UiState.Loading + _myDrawCoursesGetState.value = UiState.Loading storageRepository.getMyDrawCourse() }.onSuccess { _myDrawCourses = it!! Timber.tag(ContentValues.TAG).d("데이터 수신 완료") - _storageState.value = UiState.Success + _myDrawCoursesGetState.value = UiState.Success }.onFailure { Timber.tag(ContentValues.TAG).d("onFailure 메세지 : $it") errorMessage.value = it.message - _storageState.value = UiState.Failure + _myDrawCoursesGetState.value = UiState.Failure } } } @@ -82,19 +92,26 @@ class StorageViewModel @Inject constructor( } } - fun getScrapList() { + fun getMyScrapCoures() { viewModelScope.launch { - runCatching { - _storageState.value = UiState.Loading - storageRepository.getMyScrapCourse() - }.onSuccess { - getScrapListResult.value = it - Timber.tag(ContentValues.TAG).d("스크랩 리스트 사이즈 : ${it!!.size}") - _storageState.value = UiState.Success - }.onFailure { - errorMessage.value = it.message - _storageState.value = UiState.Failure - } + _myScrapCoursesGetState.value = UiStateV2.Loading + + storageRepository.getMyScrapCourse() + .onSuccess { response -> + if (response == null) { + _myScrapCoursesGetState.value = + UiStateV2.Failure("MY SCRAP COURSE DATA IS NULL") + return@launch + } + + Timber.d("MY SCRAP COURSE GET SUCCESS") + _myScrapCoursesGetState.value = UiStateV2.Success(response) + } + .onFailure { t -> + Timber.e("MY SCRAP COURSE GET FAIL") + Timber.e("${t.message}") + _myScrapCoursesGetState.value = UiStateV2.Failure(t.message.toString()) + } } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt index f343da17b..f8e9b12aa 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt @@ -2,11 +2,9 @@ package com.runnect.runnect.presentation.storage.adapter import android.view.LayoutInflater import android.view.ViewGroup -import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView -import com.runnect.runnect.data.dto.MyDrawCourse -import com.runnect.runnect.data.dto.MyScrapCourse +import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.databinding.ItemStorageScrapBinding import com.runnect.runnect.util.callback.ItemCount import com.runnect.runnect.util.callback.diff.ItemDiffCallback From 3a1bb9e02930d32db779afbc7d962e4a3fa86b8c Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 20:04:08 +0900 Subject: [PATCH 11/16] =?UTF-8?q?[MOD]=20#314=20=EB=A6=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=9D=98=20=EC=95=84=EC=9D=B4=ED=85=9C=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=EC=97=90=20=EB=94=B0=EB=9D=BC=20=EB=B7=B0=20=EA=B0=B1?= =?UTF-8?q?=EC=8B=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../storage/StorageScrapFragment.kt | 50 ++++++++----------- .../presentation/storage/StorageViewModel.kt | 6 +-- .../res/layout/fragment_storage_scrap.xml | 2 +- 3 files changed, 25 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index ab3c256c6..9208d3c75 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -1,6 +1,5 @@ package com.runnect.runnect.presentation.storage -import android.annotation.SuppressLint import android.content.ContentValues import android.content.Context import android.content.Intent @@ -102,10 +101,26 @@ class StorageScrapFragment : BindingFragment(R.layo } private fun addObserver() { - observeItemSize() + setupItemSizeObserver() setupMyScrapCourseGetStateObserver() } + private fun setupItemSizeObserver() { + viewModel.itemSize.observe(viewLifecycleOwner) { itemSize -> + val isEmpty = (itemSize == 0) + updateEmptyView(isEmpty, itemSize) + } + } + + private fun updateEmptyView(isEmpty: Boolean, itemSize: Int) { + binding.apply { + layoutMyDrawNoScrap.isVisible = isEmpty + recyclerViewStorageScrap.isVisible = !isEmpty + tvTotalScrapCount.isVisible = !isEmpty + tvTotalScrapCount.text = if (!isEmpty) "총 코스 ${itemSize}개" else "" + } + } + private fun setupMyScrapCourseGetStateObserver() { viewModel.myScrapCoursesGetState.observe(viewLifecycleOwner) { state -> when (state) { @@ -115,7 +130,10 @@ class StorageScrapFragment : BindingFragment(R.layo is UiStateV2.Success -> { dismissLoadingProgressBar() - storageScrapAdapter.submitList(state.data) + + val scrapCourses = state.data + updateEmptyView(scrapCourses.isEmpty(), scrapCourses.size) + storageScrapAdapter.submitList(scrapCourses) } is UiStateV2.Failure -> { @@ -139,32 +157,6 @@ class StorageScrapFragment : BindingFragment(R.layo binding.indeterminateBar.isVisible = false } - @SuppressLint("SetTextI18n") - private fun observeItemSize() { - viewModel.itemSize.observe(viewLifecycleOwner) { itemSize -> - val isEmpty = (itemSize == 0) - updateEmptyView(isEmpty, itemSize) - } - } - - private fun updateEmptyView(isEmpty: Boolean, itemSize: Int) { - binding.apply { - layoutMyDrawNoScrap.isVisible = isEmpty - recyclerViewStorageScrap.isVisible = !isEmpty - tvTotalScrapCount.isVisible = !isEmpty - tvTotalScrapCount.text = if (!isEmpty) "총 코스 ${itemSize}개" else "" - } - } - - private fun showScrapResult() { - val scrapListResult = viewModel.getScrapListResult.value ?: emptyList() - updateEmptyView(scrapListResult.isEmpty(), scrapListResult.size) - } - - private fun updateAdapterData() { - storageScrapAdapter.submitList(viewModel.getScrapListResult.value!!) - } - override fun calcItemSize(itemCount: Int) { viewModel.itemSize.value = itemCount } diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt index 48c1eccdb..b502954bb 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt @@ -106,6 +106,7 @@ class StorageViewModel @Inject constructor( Timber.d("MY SCRAP COURSE GET SUCCESS") _myScrapCoursesGetState.value = UiStateV2.Success(response) + itemSize.value = response.size } .onFailure { t -> Timber.e("MY SCRAP COURSE GET FAIL") @@ -115,12 +116,11 @@ class StorageViewModel @Inject constructor( } } - // todo: id를 non-null 타입으로 바꾸기 - fun postCourseScrap(id: Int?, scrapTF: Boolean) { + fun postCourseScrap(id: Int, scrapTF: Boolean) { viewModelScope.launch { courseRepository.postCourseScrap( RequestPostCourseScrap( - publicCourseId = id!!, scrapTF = scrapTF.toString() + publicCourseId = id, scrapTF = scrapTF.toString() ) ) } diff --git a/app/src/main/res/layout/fragment_storage_scrap.xml b/app/src/main/res/layout/fragment_storage_scrap.xml index 9a4559660..6a13c84cb 100644 --- a/app/src/main/res/layout/fragment_storage_scrap.xml +++ b/app/src/main/res/layout/fragment_storage_scrap.xml @@ -55,7 +55,7 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:text="총 기록 152개" /> + tools:text="총 코스 5개" /> From 254bf7814b7cfb588586ec937c83d311fc0d5841 Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 20:24:44 +0900 Subject: [PATCH 12/16] =?UTF-8?q?[REFACTOR]=20#314=20=EB=A6=AC=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=ED=81=B4=EB=9F=AC=EB=B7=B0=EB=A5=BC=20=EA=B0=90?= =?UTF-8?q?=EC=8B=B8=EA=B3=A0=20=EC=9E=88=EB=8A=94=20=EB=84=A4=EC=8A=A4?= =?UTF-8?q?=ED=8B=B0=EB=93=9C=20=EB=B7=B0=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../storage/StorageScrapFragment.kt | 16 ++--- .../res/layout/fragment_storage_scrap.xml | 67 +++++++------------ 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index 9208d3c75..0c578e04a 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -49,7 +49,7 @@ class StorageScrapFragment : BindingFragment(R.layo } private fun initLayout() { - binding.recyclerViewStorageScrap.apply { + binding.rvStorageScrap.apply { val context = context ?: return layoutManager = GridLayoutManager(context, 2) addItemDecoration( @@ -69,7 +69,7 @@ class StorageScrapFragment : BindingFragment(R.layo onHeartButtonClick = this, itemCount = this ).apply { - binding.recyclerViewStorageScrap.adapter = this + binding.rvStorageScrap.adapter = this } } @@ -114,10 +114,10 @@ class StorageScrapFragment : BindingFragment(R.layo private fun updateEmptyView(isEmpty: Boolean, itemSize: Int) { binding.apply { - layoutMyDrawNoScrap.isVisible = isEmpty - recyclerViewStorageScrap.isVisible = !isEmpty - tvTotalScrapCount.isVisible = !isEmpty - tvTotalScrapCount.text = if (!isEmpty) "총 코스 ${itemSize}개" else "" + clMyDrawNoScrap.isVisible = isEmpty + rvStorageScrap.isVisible = !isEmpty + tvStorageScrapCount.isVisible = !isEmpty + tvStorageScrapCount.text = if (!isEmpty) "총 코스 ${itemSize}개" else "" } } @@ -150,11 +150,11 @@ class StorageScrapFragment : BindingFragment(R.layo } private fun showLoadingProgressBar() { - binding.indeterminateBar.isVisible = true + binding.pbStorageScrapLoading.isVisible = true } private fun dismissLoadingProgressBar() { - binding.indeterminateBar.isVisible = false + binding.pbStorageScrapLoading.isVisible = false } override fun calcItemSize(itemCount: Int) { diff --git a/app/src/main/res/layout/fragment_storage_scrap.xml b/app/src/main/res/layout/fragment_storage_scrap.xml index 6a13c84cb..d6d0176ce 100644 --- a/app/src/main/res/layout/fragment_storage_scrap.xml +++ b/app/src/main/res/layout/fragment_storage_scrap.xml @@ -20,7 +20,7 @@ android:layout_height="match_parent"> - + + - - - - - - - - - + \ No newline at end of file From c0d415053f3f9602eb097a1193d24585a6215c15 Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 20:30:43 +0900 Subject: [PATCH 13/16] =?UTF-8?q?[CHORE]=20#314=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=EB=AA=85=EC=97=90=EC=84=9C=20=EC=98=A4=ED=83=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/presentation/storage/StorageScrapFragment.kt | 2 +- .../runnect/runnect/presentation/storage/StorageViewModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index 0c578e04a..879626b13 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -45,7 +45,7 @@ class StorageScrapFragment : BindingFragment(R.layo } fun getMyScrapCourses() { - viewModel.getMyScrapCoures() + viewModel.getMyScrapCourses() } private fun initLayout() { diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt index b502954bb..514f62ce9 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt @@ -92,7 +92,7 @@ class StorageViewModel @Inject constructor( } } - fun getMyScrapCoures() { + fun getMyScrapCourses() { viewModelScope.launch { _myScrapCoursesGetState.value = UiStateV2.Loading From 1545b38389703ba6ab05e18073349225ed0db190 Mon Sep 17 00:00:00 2001 From: leeeha Date: Mon, 29 Jan 2024 21:22:15 +0900 Subject: [PATCH 14/16] =?UTF-8?q?[MOD]=20#314=20=EC=84=9C=EB=B2=84=20?= =?UTF-8?q?=ED=86=B5=EC=8B=A0=EC=97=90=20=EC=84=B1=EA=B3=B5=ED=96=88?= =?UTF-8?q?=EC=9D=84=20=EB=95=8C=EB=A7=8C=20=EC=8A=A4=ED=81=AC=EB=9E=A9=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=EB=A1=9C=EB=B6=80=ED=84=B0=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=ED=85=9C=20=EC=82=AD=EC=A0=9C=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../storage/StorageScrapFragment.kt | 23 ++++++++- .../presentation/storage/StorageViewModel.kt | 16 ++++-- .../storage/adapter/StorageScrapAdapter.kt | 51 ++++++++++--------- 3 files changed, 61 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index 879626b13..ca6990e23 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -26,7 +26,8 @@ import dagger.hilt.android.AndroidEntryPoint import timber.log.Timber @AndroidEntryPoint -class StorageScrapFragment : BindingFragment(R.layout.fragment_storage_scrap), +class StorageScrapFragment : + BindingFragment(R.layout.fragment_storage_scrap), OnHeartButtonClick, OnScrapItemClick, ItemCount { @@ -103,6 +104,26 @@ class StorageScrapFragment : BindingFragment(R.layo private fun addObserver() { setupItemSizeObserver() setupMyScrapCourseGetStateObserver() + setupCourseScrapStateObserver() + } + + private fun setupCourseScrapStateObserver() { + viewModel.courseScrapState.observe(viewLifecycleOwner) { state -> + when (state) { + is UiStateV2.Success -> { + storageScrapAdapter.removeCourseItem() + } + + is UiStateV2.Failure -> { + context?.showSnackbar( + anchorView = binding.root, + message = state.msg + ) + } + + else -> {} + } + } } private fun setupItemSizeObserver() { diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt index 514f62ce9..061d6eae0 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt @@ -40,13 +40,11 @@ class StorageViewModel @Inject constructor( val myScrapCoursesGetState: LiveData>?> get() = _myScrapCoursesGetState - private val _courseScrapState = MutableLiveData>() - val courseScrapState: LiveData> + private val _courseScrapState = MutableLiveData>() + val courseScrapState: LiveData> get() = _courseScrapState - val getScrapListResult = MutableLiveData>() val errorMessage = MutableLiveData() - val itemSize = MutableLiveData() val myDrawSize = MutableLiveData() @@ -118,11 +116,19 @@ class StorageViewModel @Inject constructor( fun postCourseScrap(id: Int, scrapTF: Boolean) { viewModelScope.launch { + _courseScrapState.value = UiStateV2.Loading + courseRepository.postCourseScrap( RequestPostCourseScrap( publicCourseId = id, scrapTF = scrapTF.toString() ) - ) + ).onSuccess { response -> + _courseScrapState.value = UiStateV2.Success(response) + } + .onFailure { t -> + Timber.e("${t.message}") + _courseScrapState.value = UiStateV2.Failure(t.message.toString()) + } } } diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt index f8e9b12aa..14c31d292 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/adapter/StorageScrapAdapter.kt @@ -1,7 +1,9 @@ package com.runnect.runnect.presentation.storage.adapter import android.view.LayoutInflater +import android.view.View import android.view.ViewGroup +import android.widget.ImageView import androidx.recyclerview.widget.ListAdapter import androidx.recyclerview.widget.RecyclerView import com.runnect.runnect.domain.entity.MyScrapCourse @@ -16,47 +18,50 @@ class StorageScrapAdapter( private val onHeartButtonClick: OnHeartButtonClick, private val itemCount: ItemCount ) : ListAdapter(diffUtil) { + private var clickedItemPosition = -1 + inner class ItemViewHolder(val binding: ItemStorageScrapBinding) : RecyclerView.ViewHolder(binding.root) { - fun onBind(data: MyScrapCourse) { - with(binding) { - ivItemStorageScrapHeart.isSelected = true - ivItemStorageScrapHeart.setOnClickListener { - ivItemStorageScrapHeart.isSelected = false - deleteItem(absoluteAdapterPosition) - onHeartButtonClick.scrapCourse(data.publicCourseId, it.isSelected) - } + fun onBind(course: MyScrapCourse) { + binding.storageScrap = course + binding.ivItemStorageScrapHeart.isSelected = true - root.setOnClickListener { - onScrapItemClick.selectItem(data) - } - } + initCourseItemClickListener(binding.root, course) + initHeartButtonClickListener(binding.ivItemStorageScrapHeart, course) } - fun bind(scrapList: MyScrapCourse) { - binding.storageScrap = scrapList + + private fun initCourseItemClickListener(view: View, course: MyScrapCourse) { + view.setOnClickListener { + onScrapItemClick.selectItem(course) + } } - } - fun deleteItem(position: Int) { - val itemList = mutableListOf() - itemList.addAll(currentList) - itemList.removeAt(position) - submitList(itemList) - itemCount.calcItemSize(itemList.size) + private fun initHeartButtonClickListener(view: ImageView, course: MyScrapCourse) { + view.setOnClickListener { + clickedItemPosition = absoluteAdapterPosition + onHeartButtonClick.scrapCourse(course.publicCourseId, !it.isSelected) + } + } } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { val inflater = LayoutInflater.from(parent.context) val binding = ItemStorageScrapBinding.inflate(inflater) - return ItemViewHolder(binding) } override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { - holder.bind(currentList[position]) holder.onBind(currentList[position]) } + fun removeCourseItem() { + if (clickedItemPosition == -1) return + val newList = currentList.toMutableList() + newList.removeAt(clickedItemPosition) + submitList(newList) + itemCount.calcItemSize(newList.size) + } + companion object { private val diffUtil = ItemDiffCallback( onItemsTheSame = { old, new -> old.publicCourseId == new.publicCourseId }, From b8852f20906319a02272b62d8af09bde44830006 Mon Sep 17 00:00:00 2001 From: leeeha Date: Sat, 10 Feb 2024 17:15:46 +0900 Subject: [PATCH 15/16] =?UTF-8?q?[MERGE]=20#314=20=EB=94=94=EB=B2=A8?= =?UTF-8?q?=EB=A1=AD=20=EB=B8=8C=EB=9E=9C=EC=B9=98=EC=99=80=EC=9D=98=20?= =?UTF-8?q?=EB=A8=B8=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/repository/StorageRepositoryImpl.kt | 3 +- .../runnect/data/service/CourseService.kt | 18 +++++- .../domain/repository/StorageRepository.kt | 2 +- .../storage/StorageMyDrawFragment.kt | 2 +- .../storage/StorageScrapFragment.kt | 2 +- .../presentation/storage/StorageViewModel.kt | 59 ++++++++++--------- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt b/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt index b15b55684..a786e2e40 100644 --- a/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt +++ b/app/src/main/java/com/runnect/runnect/data/repository/StorageRepositoryImpl.kt @@ -1,10 +1,11 @@ package com.runnect.runnect.data.repository import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse -import com.runnect.runnect.data.dto.MyDrawCourse import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse +import com.runnect.runnect.data.dto.response.toMyDrawCourse import com.runnect.runnect.data.source.remote.RemoteStorageDataSource +import com.runnect.runnect.domain.entity.MyDrawCourse import com.runnect.runnect.domain.repository.StorageRepository import retrofit2.Response import javax.inject.Inject diff --git a/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt b/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt index 10c5238e6..0032bec02 100644 --- a/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt +++ b/app/src/main/java/com/runnect/runnect/data/service/CourseService.kt @@ -5,7 +5,20 @@ import com.runnect.runnect.data.dto.request.RequestPostCourseScrap import com.runnect.runnect.data.dto.request.RequestPostPublicCourse import com.runnect.runnect.data.dto.request.RequestPostRunningHistory import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse -import com.runnect.runnect.data.dto.response.* +import com.runnect.runnect.data.dto.response.ResponseGetCourseDetail +import com.runnect.runnect.data.dto.response.ResponseGetDiscoverMarathon +import com.runnect.runnect.data.dto.response.ResponseGetDiscoverPick +import com.runnect.runnect.data.dto.response.ResponseGetDiscoverRecommend +import com.runnect.runnect.data.dto.response.ResponseGetDiscoverSearch +import com.runnect.runnect.data.dto.response.ResponseGetMyDrawCourse +import com.runnect.runnect.data.dto.response.ResponseGetMyDrawDetail +import com.runnect.runnect.data.dto.response.ResponseGetMyScrapCourse +import com.runnect.runnect.data.dto.response.ResponsePatchPublicCourse +import com.runnect.runnect.data.dto.response.ResponsePostDiscoverUpload +import com.runnect.runnect.data.dto.response.ResponsePostMyDrawCourse +import com.runnect.runnect.data.dto.response.ResponsePostMyHistory +import com.runnect.runnect.data.dto.response.ResponsePostScrap +import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse import com.runnect.runnect.data.dto.response.base.BaseResponse import okhttp3.MultipartBody import okhttp3.RequestBody @@ -60,8 +73,7 @@ interface CourseService { //보관함 내가 그린 코스 가져오기 @GET("/api/course/user") - suspend fun getDrawCourseList( - ): Response + suspend fun getDrawCourseList(): BaseResponse //보관함 스크랩 코스 가져오기 @GET("/api/scrap/user") diff --git a/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt b/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt index 9d2d4f777..75e1fe0e2 100644 --- a/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt +++ b/app/src/main/java/com/runnect/runnect/domain/repository/StorageRepository.kt @@ -1,9 +1,9 @@ package com.runnect.runnect.domain.repository -import com.runnect.runnect.data.dto.MyDrawCourse import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse import com.runnect.runnect.data.dto.response.ResponsePutMyDrawCourse +import com.runnect.runnect.domain.entity.MyDrawCourse import retrofit2.Response interface StorageRepository { diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt index eda0d4ec2..791252e20 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageMyDrawFragment.kt @@ -258,7 +258,7 @@ class StorageMyDrawFragment : } private fun observeStorageState() { - viewModel.myDrawCoursesGetState.observe(viewLifecycleOwner) { + viewModel.myDrawCourseGetState.observe(viewLifecycleOwner) { when (it) { UiState.Empty -> hideLoadingBar() UiState.Loading -> showLoadingBar() diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index ca6990e23..596d5237c 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -143,7 +143,7 @@ class StorageScrapFragment : } private fun setupMyScrapCourseGetStateObserver() { - viewModel.myScrapCoursesGetState.observe(viewLifecycleOwner) { state -> + viewModel.myScrapCourseGetState.observe(viewLifecycleOwner) { state -> when (state) { is UiStateV2.Loading -> { showLoadingProgressBar() diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt index fc672eba4..b090f3185 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageViewModel.kt @@ -5,11 +5,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.runnect.runnect.data.dto.MyDrawCourse import com.runnect.runnect.domain.entity.MyScrapCourse import com.runnect.runnect.data.dto.request.RequestPostCourseScrap import com.runnect.runnect.data.dto.request.RequestPutMyDrawCourse import com.runnect.runnect.data.dto.response.ResponsePostScrap +import com.runnect.runnect.domain.entity.MyDrawCourse import com.runnect.runnect.domain.repository.CourseRepository import com.runnect.runnect.domain.repository.StorageRepository import com.runnect.runnect.presentation.state.UiState @@ -24,21 +24,21 @@ class StorageViewModel @Inject constructor( private val storageRepository: StorageRepository, private val courseRepository: CourseRepository ) : ViewModel() { - private val _myDrawCoursesDeleteState = MutableLiveData() - val myDrawCourseDeleteState: LiveData - get() = _myDrawCoursesDeleteState - - private val _myDrawCoursesGetState = MutableLiveData(UiState.Empty) - val myDrawCoursesGetState: LiveData - get() = _myDrawCoursesGetState + private val _myDrawCourseGetState = MutableLiveData(UiState.Empty) + val myDrawCourseGetState: LiveData + get() = _myDrawCourseGetState private var _myDrawCourses = mutableListOf() val myDrawCourses: List get() = _myDrawCourses - private val _myScrapCoursesGetState = MutableLiveData>?>() - val myScrapCoursesGetState: LiveData>?> - get() = _myScrapCoursesGetState + private val _myDrawCourseDeleteState = MutableLiveData() + val myDrawCourseDeleteState: LiveData + get() = _myDrawCourseDeleteState + + private val _myScrapCourseGetState = MutableLiveData>?>() + val myScrapCourseGetState: LiveData>?> + get() = _myScrapCourseGetState private val _courseScrapState = MutableLiveData>() val courseScrapState: LiveData> @@ -54,16 +54,16 @@ class StorageViewModel @Inject constructor( fun getMyDrawList() { viewModelScope.launch { runCatching { - _myDrawCoursesGetState.value = UiState.Loading + _myDrawCourseGetState.value = UiState.Loading storageRepository.getMyDrawCourse() }.onSuccess { _myDrawCourses = (it.getOrNull() ?: emptyList()).toMutableList() Timber.tag(ContentValues.TAG).d("데이터 수신 완료") - _myDrawCoursesGetState.value = UiState.Success + _myDrawCourseGetState.value = UiState.Success }.onFailure { Timber.tag(ContentValues.TAG).d("onFailure 메세지 : $it") errorMessage.value = it.message - _myDrawCoursesGetState.value = UiState.Failure + _myDrawCourseGetState.value = UiState.Failure } } } @@ -71,7 +71,7 @@ class StorageViewModel @Inject constructor( fun deleteMyDrawCourse() { viewModelScope.launch { runCatching { - _myDrawCoursesDeleteState.value = UiState.Loading + _myDrawCourseDeleteState.value = UiState.Loading storageRepository.deleteMyDrawCourse( RequestPutMyDrawCourse( courseIdList = itemsToDelete @@ -81,35 +81,35 @@ class StorageViewModel @Inject constructor( Timber.tag(ContentValues.TAG).d("삭제 성공입니다") _myDrawCourses = _myDrawCourses.filter { !itemsToDelete.contains(it.courseId) }.toMutableList() - _myDrawCoursesDeleteState.value = UiState.Success + _myDrawCourseDeleteState.value = UiState.Success }.onFailure { Timber.tag(ContentValues.TAG).d("실패했고 문제는 다음과 같습니다 $it") - _myDrawCoursesDeleteState.value = UiState.Failure + _myDrawCourseDeleteState.value = UiState.Failure } } } fun getMyScrapCourses() { viewModelScope.launch { - _myScrapCoursesGetState.value = UiStateV2.Loading + _myScrapCourseGetState.value = UiStateV2.Loading storageRepository.getMyScrapCourse() - .onSuccess { response -> + .onSuccess { response -> if (response == null) { - _myScrapCoursesGetState.value = + _myScrapCourseGetState.value = UiStateV2.Failure("MY SCRAP COURSE DATA IS NULL") return@launch } Timber.d("MY SCRAP COURSE GET SUCCESS") - _myScrapCoursesGetState.value = UiStateV2.Success(response) + _myScrapCourseGetState.value = UiStateV2.Success(response) itemSize.value = response.size } .onFailure { t -> Timber.e("MY SCRAP COURSE GET FAIL") Timber.e("${t.message}") - _myScrapCoursesGetState.value = UiStateV2.Failure(t.message.toString()) + _myScrapCourseGetState.value = UiStateV2.Failure(t.message.toString()) } } } @@ -122,13 +122,14 @@ class StorageViewModel @Inject constructor( RequestPostCourseScrap( publicCourseId = id, scrapTF = scrapTF.toString() ) - ).onSuccess { response -> - _courseScrapState.value = UiStateV2.Success(response) - } - .onFailure { t -> - Timber.e("${t.message}") - _courseScrapState.value = UiStateV2.Failure(t.message.toString()) - } + ) + .onSuccess { response -> + _courseScrapState.value = UiStateV2.Success(response) + } + .onFailure { t -> + Timber.e("${t.message}") + _courseScrapState.value = UiStateV2.Failure(t.message.toString()) + } } } From c7b1f906e4816dfc9b1b492b6da0225cde7af557 Mon Sep 17 00:00:00 2001 From: leeeha Date: Wed, 14 Feb 2024 22:46:28 +0900 Subject: [PATCH 16/16] =?UTF-8?q?[MOD]=20#314=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=9E=A9=20=EC=84=9C=EB=B2=84=ED=86=B5=EC=8B=A0=EC=9D=B4=20?= =?UTF-8?q?=EB=A1=9C=EB=94=A9=20=EC=83=81=ED=83=9C=EC=9D=BC=20=EB=95=8C?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EB=94=A9=20=ED=94=84=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EB=A0=88=EC=8A=A4=EB=B0=94=20=EB=9D=84=EC=9A=B0=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../runnect/presentation/storage/StorageScrapFragment.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt index 596d5237c..de7288cfb 100644 --- a/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt +++ b/app/src/main/java/com/runnect/runnect/presentation/storage/StorageScrapFragment.kt @@ -110,11 +110,17 @@ class StorageScrapFragment : private fun setupCourseScrapStateObserver() { viewModel.courseScrapState.observe(viewLifecycleOwner) { state -> when (state) { + is UiStateV2.Loading -> { + showLoadingProgressBar() + } + is UiStateV2.Success -> { + dismissLoadingProgressBar() storageScrapAdapter.removeCourseItem() } is UiStateV2.Failure -> { + dismissLoadingProgressBar() context?.showSnackbar( anchorView = binding.root, message = state.msg