From 4cf81fb07477d66c38c64f70e6d86074c3c21f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=88=E1=85=A1=E1=86=BC=E1=84=8C?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 26 Feb 2024 02:06:42 +0900 Subject: [PATCH 1/5] =?UTF-8?q?#299=20[chore]=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=EC=95=84=EC=9D=B4=EC=BD=98=EB=AA=85=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 --- .../main/res/drawable/{ic_detail_delete.xml => ic_delete.xml} | 0 app/src/main/res/layout/activity_detail.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename app/src/main/res/drawable/{ic_detail_delete.xml => ic_delete.xml} (100%) diff --git a/app/src/main/res/drawable/ic_detail_delete.xml b/app/src/main/res/drawable/ic_delete.xml similarity index 100% rename from app/src/main/res/drawable/ic_detail_delete.xml rename to app/src/main/res/drawable/ic_delete.xml diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 68c0105c..6f56f01d 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -46,7 +46,7 @@ android:layout_height="wrap_content" android:layout_marginEnd="6dp" android:background="@null" - android:src="@drawable/ic_detail_delete" + android:src="@drawable/ic_delete" android:visibility="@{vm.isMyDetailView == true ? View.VISIBLE : View.INVISIBLE}" app:layout_constraintBottom_toBottomOf="@id/btn_detail_edit" app:layout_constraintEnd_toEndOf="parent" From 19b010ccc03a65a1ead6fc709a3bec72709bd044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=88=E1=85=A1=E1=86=BC=E1=84=8C?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 26 Feb 2024 02:43:27 +0900 Subject: [PATCH 2/5] =?UTF-8?q?#299=20[chore]=20=EC=BB=AC=EB=9F=AC?= =?UTF-8?q?=EA=B0=92=20=EB=B0=8F=20shape=20=EB=B3=80=EC=88=98=EB=AA=85=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 --- ...{shape_red_line_0_rect.xml => shape_red_line_rect.xml} | 0 ...nes_0_rect.xml => shape_white30fill_redlines_rect.xml} | 0 ...line_0_rect.xml => shape_white40fill_redline_rect.xml} | 2 +- ...line_0_rect.xml => shape_white60fill_redline_rect.xml} | 0 ...line_0_rect.xml => shape_white80fill_redline_rect.xml} | 2 +- ..._0_rect_1.xml => shape_white80fill_redline_rect_1.xml} | 2 +- ..._0_rect_2.xml => shape_white80fill_redline_rect_2.xml} | 2 +- ...e_fill_20_rect.xml => shape_white_fill_top20_rect.xml} | 0 ...edline_0_rect.xml => shape_whitefill_redline_rect.xml} | 0 app/src/main/res/layout/activity_detail.xml | 4 ++-- app/src/main/res/layout/activity_edit_book.xml | 4 ++-- app/src/main/res/layout/activity_profile_modify.xml | 4 ++-- app/src/main/res/layout/activity_report.xml | 2 +- app/src/main/res/layout/dialog_bookshelf_bottom_sheet.xml | 2 +- app/src/main/res/layout/dialog_profile_bottom_sheet.xml | 2 +- app/src/main/res/layout/fragment_bookshelf.xml | 6 +++--- app/src/main/res/layout/fragment_create_book.xml | 4 ++-- app/src/main/res/layout/fragment_my_page.xml | 2 +- app/src/main/res/layout/fragment_recommendation.xml | 2 +- app/src/main/res/layout/fragment_user_input.xml | 4 ++-- app/src/main/res/layout/item_bookshelf_pick.xml | 6 +++--- app/src/main/res/layout/item_recommend.xml | 2 +- app/src/main/res/layout/item_search_book.xml | 2 +- app/src/main/res/values/colors.xml | 8 ++++---- 24 files changed, 31 insertions(+), 31 deletions(-) rename app/src/main/res/drawable/{shape_red_line_0_rect.xml => shape_red_line_rect.xml} (100%) rename app/src/main/res/drawable/{shape_white30fill_redlines_0_rect.xml => shape_white30fill_redlines_rect.xml} (100%) rename app/src/main/res/drawable/{shape_white66fill_redline_0_rect.xml => shape_white40fill_redline_rect.xml} (81%) rename app/src/main/res/drawable/{shape_white60fill_redline_0_rect.xml => shape_white60fill_redline_rect.xml} (100%) rename app/src/main/res/drawable/{shape_white88fill_redline_0_rect.xml => shape_white80fill_redline_rect.xml} (87%) rename app/src/main/res/drawable/{shape_white88fill_redline_0_rect_1.xml => shape_white80fill_redline_rect_1.xml} (87%) rename app/src/main/res/drawable/{shape_white88fill_redline_0_rect_2.xml => shape_white80fill_redline_rect_2.xml} (87%) rename app/src/main/res/drawable/{shape_white_fill_20_rect.xml => shape_white_fill_top20_rect.xml} (100%) rename app/src/main/res/drawable/{shape_whitefill_redline_0_rect.xml => shape_whitefill_redline_rect.xml} (100%) diff --git a/app/src/main/res/drawable/shape_red_line_0_rect.xml b/app/src/main/res/drawable/shape_red_line_rect.xml similarity index 100% rename from app/src/main/res/drawable/shape_red_line_0_rect.xml rename to app/src/main/res/drawable/shape_red_line_rect.xml diff --git a/app/src/main/res/drawable/shape_white30fill_redlines_0_rect.xml b/app/src/main/res/drawable/shape_white30fill_redlines_rect.xml similarity index 100% rename from app/src/main/res/drawable/shape_white30fill_redlines_0_rect.xml rename to app/src/main/res/drawable/shape_white30fill_redlines_rect.xml diff --git a/app/src/main/res/drawable/shape_white66fill_redline_0_rect.xml b/app/src/main/res/drawable/shape_white40fill_redline_rect.xml similarity index 81% rename from app/src/main/res/drawable/shape_white66fill_redline_0_rect.xml rename to app/src/main/res/drawable/shape_white40fill_redline_rect.xml index 89cf7197..3708ef91 100644 --- a/app/src/main/res/drawable/shape_white66fill_redline_0_rect.xml +++ b/app/src/main/res/drawable/shape_white40fill_redline_rect.xml @@ -2,7 +2,7 @@ - + diff --git a/app/src/main/res/drawable/shape_white60fill_redline_0_rect.xml b/app/src/main/res/drawable/shape_white60fill_redline_rect.xml similarity index 100% rename from app/src/main/res/drawable/shape_white60fill_redline_0_rect.xml rename to app/src/main/res/drawable/shape_white60fill_redline_rect.xml diff --git a/app/src/main/res/drawable/shape_white88fill_redline_0_rect.xml b/app/src/main/res/drawable/shape_white80fill_redline_rect.xml similarity index 87% rename from app/src/main/res/drawable/shape_white88fill_redline_0_rect.xml rename to app/src/main/res/drawable/shape_white80fill_redline_rect.xml index ab2a2412..59cac8ca 100644 --- a/app/src/main/res/drawable/shape_white88fill_redline_0_rect.xml +++ b/app/src/main/res/drawable/shape_white80fill_redline_rect.xml @@ -9,7 +9,7 @@ - + diff --git a/app/src/main/res/drawable/shape_white88fill_redline_0_rect_1.xml b/app/src/main/res/drawable/shape_white80fill_redline_rect_1.xml similarity index 87% rename from app/src/main/res/drawable/shape_white88fill_redline_0_rect_1.xml rename to app/src/main/res/drawable/shape_white80fill_redline_rect_1.xml index d77a7f2f..1b781784 100644 --- a/app/src/main/res/drawable/shape_white88fill_redline_0_rect_1.xml +++ b/app/src/main/res/drawable/shape_white80fill_redline_rect_1.xml @@ -9,7 +9,7 @@ - + diff --git a/app/src/main/res/drawable/shape_white88fill_redline_0_rect_2.xml b/app/src/main/res/drawable/shape_white80fill_redline_rect_2.xml similarity index 87% rename from app/src/main/res/drawable/shape_white88fill_redline_0_rect_2.xml rename to app/src/main/res/drawable/shape_white80fill_redline_rect_2.xml index 4554b1d5..9bc649b5 100644 --- a/app/src/main/res/drawable/shape_white88fill_redline_0_rect_2.xml +++ b/app/src/main/res/drawable/shape_white80fill_redline_rect_2.xml @@ -9,7 +9,7 @@ - + diff --git a/app/src/main/res/drawable/shape_white_fill_20_rect.xml b/app/src/main/res/drawable/shape_white_fill_top20_rect.xml similarity index 100% rename from app/src/main/res/drawable/shape_white_fill_20_rect.xml rename to app/src/main/res/drawable/shape_white_fill_top20_rect.xml diff --git a/app/src/main/res/drawable/shape_whitefill_redline_0_rect.xml b/app/src/main/res/drawable/shape_whitefill_redline_rect.xml similarity index 100% rename from app/src/main/res/drawable/shape_whitefill_redline_0_rect.xml rename to app/src/main/res/drawable/shape_whitefill_redline_rect.xml diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 6f56f01d..f9bd7960 100644 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -129,7 +129,7 @@ style="@style/H2Md" android:layout_width="0dp" android:layout_height="0dp" - android:background="@drawable/shape_red_line_0_rect" + android:background="@drawable/shape_red_line_rect" android:gravity="top" android:paddingHorizontal="14dp" android:paddingVertical="12dp" @@ -161,7 +161,7 @@ style="@style/H2Md" android:layout_width="0dp" android:layout_height="0dp" - android:background="@drawable/shape_red_line_0_rect" + android:background="@drawable/shape_red_line_rect" android:maxLength="50" android:paddingHorizontal="14dp" android:paddingVertical="12dp" diff --git a/app/src/main/res/layout/activity_edit_book.xml b/app/src/main/res/layout/activity_edit_book.xml index 21370bf0..56bb69a4 100644 --- a/app/src/main/res/layout/activity_edit_book.xml +++ b/app/src/main/res/layout/activity_edit_book.xml @@ -128,7 +128,7 @@ style="@style/H2Md" android:layout_width="0dp" android:layout_height="0dp" - android:background="@drawable/shape_whitefill_redline_0_rect" + android:background="@drawable/shape_whitefill_redline_rect" android:gravity="top" android:hint="@string/book_comment_hint" android:importantForAutofill="no" @@ -178,7 +178,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginBottom="20dp" - android:background="@drawable/shape_whitefill_redline_0_rect" + android:background="@drawable/shape_whitefill_redline_rect" android:gravity="top" android:hint="@string/book_memo_hint" android:importantForAutofill="no" diff --git a/app/src/main/res/layout/activity_profile_modify.xml b/app/src/main/res/layout/activity_profile_modify.xml index 36947f6d..2695a4fc 100644 --- a/app/src/main/res/layout/activity_profile_modify.xml +++ b/app/src/main/res/layout/activity_profile_modify.xml @@ -85,7 +85,7 @@ style="@style/H2Md" android:layout_width="0dp" android:layout_height="0dp" - android:background="@drawable/shape_white60fill_redline_0_rect" + android:background="@drawable/shape_white60fill_redline_rect" android:gravity="top" android:hint="@string/profile_modify_nickname_hint" android:importantForAutofill="no" @@ -164,7 +164,7 @@ style="@style/H2Md" android:layout_width="0dp" android:layout_height="0dp" - android:background="@drawable/shape_white60fill_redline_0_rect" + android:background="@drawable/shape_white60fill_redline_rect" android:gravity="top" android:hint="@string/profile_modify_intoduce_hint" android:importantForAutofill="no" diff --git a/app/src/main/res/layout/activity_report.xml b/app/src/main/res/layout/activity_report.xml index 7f3c2c18..48f37d7b 100644 --- a/app/src/main/res/layout/activity_report.xml +++ b/app/src/main/res/layout/activity_report.xml @@ -186,7 +186,7 @@ android:layout_marginHorizontal="21dp" android:layout_marginTop="21dp" android:layout_marginBottom="42dp" - android:background="@drawable/shape_white88fill_redline_0_rect" + android:background="@drawable/shape_white80fill_redline_rect" android:gravity="start" android:hint="@string/report_detail_reason" android:maxLength="200" diff --git a/app/src/main/res/layout/dialog_bookshelf_bottom_sheet.xml b/app/src/main/res/layout/dialog_bookshelf_bottom_sheet.xml index e55b0191..7bcf4e28 100644 --- a/app/src/main/res/layout/dialog_bookshelf_bottom_sheet.xml +++ b/app/src/main/res/layout/dialog_bookshelf_bottom_sheet.xml @@ -3,7 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:background="@drawable/shape_white_fill_20_rect" + android:background="@drawable/shape_white_fill_top20_rect" app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"> diff --git a/app/src/main/res/layout/fragment_recommendation.xml b/app/src/main/res/layout/fragment_recommendation.xml index 02a3bce6..dcebd2d4 100644 --- a/app/src/main/res/layout/fragment_recommendation.xml +++ b/app/src/main/res/layout/fragment_recommendation.xml @@ -165,7 +165,7 @@ android:layout_height="0dp" android:layout_marginHorizontal="20dp" android:layout_marginBottom="20dp" - android:background="@drawable/shape_whitefill_redline_0_rect" + android:background="@drawable/shape_whitefill_redline_rect" android:gravity="top" android:hint="@string/recommendation_hint" android:importantForAutofill="no" diff --git a/app/src/main/res/layout/fragment_user_input.xml b/app/src/main/res/layout/fragment_user_input.xml index de190845..6670f723 100644 --- a/app/src/main/res/layout/fragment_user_input.xml +++ b/app/src/main/res/layout/fragment_user_input.xml @@ -90,7 +90,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginHorizontal="20dp" - android:background="@drawable/shape_white60fill_redline_0_rect" + android:background="@drawable/shape_white60fill_redline_rect" android:gravity="top" android:hint="@string/user_input_nickname_hint" android:importantForAutofill="no" @@ -171,7 +171,7 @@ android:layout_width="0dp" android:layout_height="0dp" android:layout_marginHorizontal="20dp" - android:background="@drawable/shape_white60fill_redline_0_rect" + android:background="@drawable/shape_white60fill_redline_rect" android:gravity="top" android:hint="@string/user_input_introduce_hint" android:importantForAutofill="no" diff --git a/app/src/main/res/layout/item_bookshelf_pick.xml b/app/src/main/res/layout/item_bookshelf_pick.xml index b6b2ed2f..2c5a41d8 100644 --- a/app/src/main/res/layout/item_bookshelf_pick.xml +++ b/app/src/main/res/layout/item_bookshelf_pick.xml @@ -16,13 +16,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="20dp" - android:background="@drawable/shape_white88fill_redline_0_rect_1"> + android:background="@drawable/shape_white80fill_redline_rect_1"> diff --git a/app/src/main/res/layout/item_search_book.xml b/app/src/main/res/layout/item_search_book.xml index f3ad4b38..dedec4a6 100644 --- a/app/src/main/res/layout/item_search_book.xml +++ b/app/src/main/res/layout/item_search_book.xml @@ -17,7 +17,7 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="20dp" android:layout_marginTop="12dp" - android:background="@drawable/shape_whitefill_redline_0_rect"> + android:background="@drawable/shape_whitefill_redline_rect"> #998e8e8e #8e8e8e #99902b21 + #CCffffff #99ffffff - #66ffffff + #66FFFFFF + #4DFFFFFF #ffffff #fefdfa - #4DFFFFFF - #66FFFFFF - #FC000000 + #99000000 #4e2a00 #fee400 #6A6964 From 5e988f4afa5649157bd940bec5f30260f37c1e06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=88=E1=85=A1=E1=86=BC=E1=84=8C?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 26 Feb 2024 07:18:03 +0900 Subject: [PATCH 3/5] =?UTF-8?q?#299=20[ui]=20=EC=B6=94=EC=B2=9C=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../peekabookaos/domain/entity/Recommend.kt | 3 +- .../recommend/BookRecommendAdapter.kt | 16 +++- .../recommend/RecommendDeleteDialog.kt | 82 +++++++++++++++++++ .../recommend/RecommendDeleteDialogContent.kt | 21 +++++ .../recommend/RecommendFragment.kt | 1 + .../presentation/recommend/RecommendType.kt | 5 ++ .../recommend/RecommendViewModel.kt | 25 ++++++ .../recommend/RecommendedFragment.kt | 13 ++- .../recommend/RecommendingFragment.kt | 14 +++- .../res/layout/dialog_recommend_delete.xml | 81 ++++++++++++++++++ .../main/res/layout/fragment_recommend.xml | 24 ++++++ app/src/main/res/layout/item_recommend.xml | 31 ++++++- app/src/main/res/values/colors.xml | 1 + app/src/main/res/values/strings.xml | 6 ++ 14 files changed, 314 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt create mode 100644 app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialogContent.kt create mode 100644 app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendType.kt create mode 100644 app/src/main/res/layout/dialog_recommend_delete.xml diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/Recommend.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/Recommend.kt index 3527f589..b5b068cb 100644 --- a/app/src/main/java/com/sopt/peekabookaos/domain/entity/Recommend.kt +++ b/app/src/main/java/com/sopt/peekabookaos/domain/entity/Recommend.kt @@ -10,5 +10,6 @@ data class Recommend( val bookId: Int = -1, val bookTitle: String = "", val author: String = "", - val bookImage: String = "" + val bookImage: String = "", + val isEditMode: Boolean = false ) diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/BookRecommendAdapter.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/BookRecommendAdapter.kt index eb2d511f..2a52d669 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/BookRecommendAdapter.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/BookRecommendAdapter.kt @@ -8,8 +8,9 @@ import com.sopt.peekabookaos.databinding.ItemRecommendBinding import com.sopt.peekabookaos.domain.entity.Recommend import com.sopt.peekabookaos.util.ItemDiffCallback -class BookRecommendAdapter : - ListAdapter(recommendationDiffUtil) { +class BookRecommendAdapter( + private val onClickDelete: (Int) -> Unit +) : ListAdapter(recommendationDiffUtil) { override fun onCreateViewHolder( parent: ViewGroup, @@ -22,7 +23,8 @@ class BookRecommendAdapter : false ) return BookRecommendationViewHolder( - itemRecommendRecommendedBinding + itemRecommendRecommendedBinding, + onClickDelete ) } @@ -30,10 +32,16 @@ class BookRecommendAdapter : holder.onBind(getItem(position)) } - class BookRecommendationViewHolder(private val binding: ItemRecommendBinding) : + class BookRecommendationViewHolder( + private val binding: ItemRecommendBinding, + private val onClickDelete: (Int) -> Unit + ) : RecyclerView.ViewHolder(binding.root) { fun onBind(data: Recommend) { binding.data = data + binding.ivItemRecommendDelete.setOnClickListener { + onClickDelete(data.recommendId) + } } } diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt new file mode 100644 index 00000000..84254c30 --- /dev/null +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt @@ -0,0 +1,82 @@ +package com.sopt.peekabookaos.presentation.recommend + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.view.WindowManager +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels +import com.sopt.peekabookaos.R +import com.sopt.peekabookaos.databinding.DialogRecommendDeleteBinding +import com.sopt.peekabookaos.util.extensions.getSerializableCompat +import timber.log.Timber + +class RecommendDeleteDialog : DialogFragment() { + private var _binding: DialogRecommendDeleteBinding? = null + private val binding get() = _binding ?: error(getString(R.string.binding_error)) + + private val recommendViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = DialogRecommendDeleteBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + isCancelable = true + initLayout() + initWarningDialogContent() + initConfirmBtnClickListener() + initCancelBtnClickListener() + } + + private fun initLayout() { + val ratio = 0.89 + val layoutParams = requireNotNull(dialog).window!!.attributes + layoutParams.width = (resources.displayMetrics.widthPixels * ratio).toInt() + layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT + requireNotNull(dialog).window!!.attributes = layoutParams + } + + private fun initWarningDialogContent() { + val recommendType = arguments?.getSerializableCompat(RECOMMEND_TYPE) as? RecommendType + ?: Timber.e(getString(R.string.null_point_exception_warning_dialog_argument)) + with(binding) { + type = when (recommendType as RecommendType) { + RecommendType.RECOMMENDED -> + RecommendDeleteDialogContent().getRecommended(requireContext()) + + RecommendType.RECOMMENDING -> + RecommendDeleteDialogContent().getRecommending(requireContext()) + } + } + } + + private fun initConfirmBtnClickListener() { + binding.btnRecommendDeleteDialogConfirm.setOnClickListener { + recommendViewModel.deleteRecommend() + } + } + + private fun initCancelBtnClickListener() { + binding.btnRecommendDeleteDialogCancel.setOnClickListener { + dismiss() + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + companion object { + const val DIALOG_TYPE = "recommendDeleteDialog" + const val RECOMMEND_TYPE = "recommendType" + } +} diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialogContent.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialogContent.kt new file mode 100644 index 00000000..2712b4a4 --- /dev/null +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialogContent.kt @@ -0,0 +1,21 @@ +package com.sopt.peekabookaos.presentation.recommend + +import android.content.Context +import com.sopt.peekabookaos.R + +data class RecommendDeleteDialogContent( + val title: String = "", + val content: String = "" +) { + fun getRecommended(context: Context): RecommendDeleteDialogContent = + RecommendDeleteDialogContent( + title = context.getString(R.string.recommend_recommended_delete_dialog_title), + content = context.getString(R.string.recommend_recommended_delete_dialog_content) + ) + + fun getRecommending(context: Context): RecommendDeleteDialogContent = + RecommendDeleteDialogContent( + title = context.getString(R.string.recommend_recommending_delete_dialog_title), + content = context.getString(R.string.recommend_recommending_delete_dialog_content) + ) +} diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendFragment.kt index 5488332c..5878be8d 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendFragment.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendFragment.kt @@ -22,6 +22,7 @@ class RecommendFragment : BindingFragment(R.layout.fra override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + binding.viewModel = recommendViewModel initAdapter() initTabLayout() } diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendType.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendType.kt new file mode 100644 index 00000000..b857ad2d --- /dev/null +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendType.kt @@ -0,0 +1,5 @@ +package com.sopt.peekabookaos.presentation.recommend + +enum class RecommendType { + RECOMMENDED, RECOMMENDING +} diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt index 50c21082..d9832f56 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt @@ -21,6 +21,31 @@ class RecommendViewModel @Inject constructor( private val _recommendingBook = MutableLiveData>() val recommendingBook: LiveData> = _recommendingBook + private val _isEditMode = MutableLiveData(false) + val isEditMode: LiveData = _isEditMode + + private val _recommendId = MutableLiveData(-1) + val recommendId: LiveData = _recommendId + + fun toggleEditMode() { + _isEditMode.value = _isEditMode.value?.not() + val updatedRecommendedBooks = + _recommendedBook.value?.map { it.copy(isEditMode = _isEditMode.value!!) } + _recommendedBook.value = updatedRecommendedBooks!! + + val updatedRecommendingBooks = + _recommendingBook.value?.map { it.copy(isEditMode = _isEditMode.value!!) } + _recommendingBook.value = updatedRecommendingBooks!! + } + + fun deleteRecommend() { + + } + + fun setRecommendId(recommendId: Int) { + _recommendId.value = recommendId + } + fun getRecommend() { viewModelScope.launch { getRecommendUseCase() diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendedFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendedFragment.kt index 1e404430..20fd3722 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendedFragment.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendedFragment.kt @@ -7,6 +7,7 @@ import androidx.fragment.app.activityViewModels import com.sopt.peekabookaos.R import com.sopt.peekabookaos.databinding.ItemRecommendViewBinding import com.sopt.peekabookaos.util.binding.BindingFragment +import com.sopt.peekabookaos.util.extensions.withArgs import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -24,7 +25,17 @@ class RecommendedFragment : } private fun initAdapter() { - binding.rvRecommend.adapter = BookRecommendAdapter() + binding.rvRecommend.adapter = BookRecommendAdapter(::onClickDelete) + } + + private fun onClickDelete(recommendId: Int) { + recommendViewModel.setRecommendId(recommendId) + RecommendDeleteDialog().withArgs { + putSerializable( + RecommendDeleteDialog.RECOMMEND_TYPE, + RecommendType.RECOMMENDED + ) + }.show(childFragmentManager, RecommendDeleteDialog.DIALOG_TYPE) } private fun initObserver() { diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendingFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendingFragment.kt index ae707734..71eec64e 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendingFragment.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendingFragment.kt @@ -6,7 +6,9 @@ import androidx.core.view.isVisible import androidx.fragment.app.activityViewModels import com.sopt.peekabookaos.R import com.sopt.peekabookaos.databinding.ItemRecommendViewBinding +import com.sopt.peekabookaos.presentation.recommend.RecommendDeleteDialog.Companion.DIALOG_TYPE import com.sopt.peekabookaos.util.binding.BindingFragment +import com.sopt.peekabookaos.util.extensions.withArgs import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -24,7 +26,17 @@ class RecommendingFragment : } private fun initAdapter() { - binding.rvRecommend.adapter = BookRecommendAdapter() + binding.rvRecommend.adapter = BookRecommendAdapter(::onClickDelete) + } + + private fun onClickDelete(recommendId: Int) { + recommendViewModel.setRecommendId(recommendId) + RecommendDeleteDialog().withArgs { + putSerializable( + RecommendDeleteDialog.RECOMMEND_TYPE, + RecommendType.RECOMMENDING + ) + }.show(childFragmentManager, DIALOG_TYPE) } private fun initObserver() { diff --git a/app/src/main/res/layout/dialog_recommend_delete.xml b/app/src/main/res/layout/dialog_recommend_delete.xml new file mode 100644 index 00000000..483265e5 --- /dev/null +++ b/app/src/main/res/layout/dialog_recommend_delete.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_recommend.xml b/app/src/main/res/layout/fragment_recommend.xml index cfc74f4d..84a67665 100644 --- a/app/src/main/res/layout/fragment_recommend.xml +++ b/app/src/main/res/layout/fragment_recommend.xml @@ -5,6 +5,11 @@ + + + + + + + @@ -94,8 +96,7 @@ app:layout_constraintDimensionRatio="1:1.6" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - tools:layout_width="92dp" - tools:src="@color/black" /> + tools:layout_width="92dp" /> + + + + + + #998e8e8e #8e8e8e #99902b21 + #E6ffffff #CCffffff #99ffffff #66FFFFFF diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 593f12b5..17a1115f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -68,9 +68,15 @@ 추천받은 책 추천한 책 + 수정하기 + 완료 %s님의 책장 보러가기 → 아직 친구가 추천해준 책이 없네요.\n친구와 함께 읽을 책을 공유해보세요. 친구에게 추천해준 책이 없네요.\n친구와 함께 읽을 책을 공유해보세요. + 추천받은 책을 삭제하시겠어요? + 추천한 책을 삭제하시겠어요? + 나에게 추천해준 사용자의 추천 내역에서도 사라지며,\n삭제 후에는 되돌릴 수 없어요. + 추천받은 사용자의 추천 내역에서도 사라지며,\n삭제 후에는 되돌릴 수 없어요. 북과픽 From 4ed10a4af0c7c39f9ed75f2efe1db97575874328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=88=E1=85=A1=E1=86=BC=E1=84=8C?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 26 Feb 2024 07:45:13 +0900 Subject: [PATCH 4/5] =?UTF-8?q?#299=20[feat]=20=EC=B1=85=EC=82=AD=EC=A0=9C?= =?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 --- .../repository/RecommendRepositoryImpl.kt | 5 +++++ .../data/service/RecommendService.kt | 7 +++++++ .../data/source/remote/RecommendDataSource.kt | 4 ++++ .../domain/repository/RecommendRepository.kt | 2 ++ .../domain/usecase/DeleteRecommendUseCase.kt | 10 +++++++++ .../recommend/RecommendDeleteDialog.kt | 20 ++++++++++++++++++ .../recommend/RecommendViewModel.kt | 21 +++++++++++++++++-- 7 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/sopt/peekabookaos/domain/usecase/DeleteRecommendUseCase.kt diff --git a/app/src/main/java/com/sopt/peekabookaos/data/repository/RecommendRepositoryImpl.kt b/app/src/main/java/com/sopt/peekabookaos/data/repository/RecommendRepositoryImpl.kt index a1ec7aa1..a95f03aa 100644 --- a/app/src/main/java/com/sopt/peekabookaos/data/repository/RecommendRepositoryImpl.kt +++ b/app/src/main/java/com/sopt/peekabookaos/data/repository/RecommendRepositoryImpl.kt @@ -31,4 +31,9 @@ class RecommendRepositoryImpl @Inject constructor( friendId ) }.map { response -> response.success } + + override suspend fun deleteRecommend(recommendId: Int): Result = + kotlin.runCatching { + recommendDataSource.deleteRecommend(recommendId) + } } diff --git a/app/src/main/java/com/sopt/peekabookaos/data/service/RecommendService.kt b/app/src/main/java/com/sopt/peekabookaos/data/service/RecommendService.kt index 70ad7b93..9509182d 100644 --- a/app/src/main/java/com/sopt/peekabookaos/data/service/RecommendService.kt +++ b/app/src/main/java/com/sopt/peekabookaos/data/service/RecommendService.kt @@ -1,10 +1,12 @@ package com.sopt.peekabookaos.data.service import com.sopt.peekabookaos.data.entity.BaseResponse +import com.sopt.peekabookaos.data.entity.NoResponse import com.sopt.peekabookaos.data.entity.request.RecommendationRequest import com.sopt.peekabookaos.data.entity.response.RecommendResponse import com.sopt.peekabookaos.data.entity.response.RecommendationResponse import retrofit2.http.Body +import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.POST import retrofit2.http.Path @@ -18,4 +20,9 @@ interface RecommendService { @Body body: RecommendationRequest, @Path("friendId") friendId: Int ): BaseResponse + + @DELETE("recommend/{recommendId}") + suspend fun deleteRecommend( + @Path("recommendId") recommendId: Int + ): BaseResponse } diff --git a/app/src/main/java/com/sopt/peekabookaos/data/source/remote/RecommendDataSource.kt b/app/src/main/java/com/sopt/peekabookaos/data/source/remote/RecommendDataSource.kt index a3733f97..f8154625 100644 --- a/app/src/main/java/com/sopt/peekabookaos/data/source/remote/RecommendDataSource.kt +++ b/app/src/main/java/com/sopt/peekabookaos/data/source/remote/RecommendDataSource.kt @@ -1,6 +1,7 @@ package com.sopt.peekabookaos.data.source.remote import com.sopt.peekabookaos.data.entity.BaseResponse +import com.sopt.peekabookaos.data.entity.NoResponse import com.sopt.peekabookaos.data.entity.request.RecommendationRequest import com.sopt.peekabookaos.data.entity.response.RecommendResponse import com.sopt.peekabookaos.data.entity.response.RecommendationResponse @@ -31,4 +32,7 @@ data class RecommendDataSource @Inject constructor( ), friendId ) + + suspend fun deleteRecommend(recommendId: Int): BaseResponse = + recommendService.deleteRecommend(recommendId) } diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/repository/RecommendRepository.kt b/app/src/main/java/com/sopt/peekabookaos/domain/repository/RecommendRepository.kt index 0fad05f4..647991c4 100644 --- a/app/src/main/java/com/sopt/peekabookaos/domain/repository/RecommendRepository.kt +++ b/app/src/main/java/com/sopt/peekabookaos/domain/repository/RecommendRepository.kt @@ -13,4 +13,6 @@ interface RecommendRepository { publisher: String, friendId: Int ): Result + + suspend fun deleteRecommend(recommendId: Int): Result } diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/DeleteRecommendUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/DeleteRecommendUseCase.kt new file mode 100644 index 00000000..cac8597c --- /dev/null +++ b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/DeleteRecommendUseCase.kt @@ -0,0 +1,10 @@ +package com.sopt.peekabookaos.domain.usecase + +import com.sopt.peekabookaos.domain.repository.RecommendRepository +import javax.inject.Inject + +class DeleteRecommendUseCase @Inject constructor( + private val recommendRepository: RecommendRepository +) { + suspend operator fun invoke(recommendId: Int) = recommendRepository.deleteRecommend(recommendId) +} diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt index 84254c30..221df551 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt @@ -5,11 +5,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.WindowManager +import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.sopt.peekabookaos.R import com.sopt.peekabookaos.databinding.DialogRecommendDeleteBinding +import com.sopt.peekabookaos.util.UiEvent import com.sopt.peekabookaos.util.extensions.getSerializableCompat +import com.sopt.peekabookaos.util.extensions.repeatOnStarted import timber.log.Timber class RecommendDeleteDialog : DialogFragment() { @@ -34,6 +37,23 @@ class RecommendDeleteDialog : DialogFragment() { initWarningDialogContent() initConfirmBtnClickListener() initCancelBtnClickListener() + collectUiEvent() + } + + private fun collectUiEvent() { + repeatOnStarted { + recommendViewModel.uiEvent.collect { uiEvent -> + when (uiEvent) { + UiEvent.IDLE -> {} + UiEvent.SUCCESS -> { + dismiss() + } + UiEvent.ERROR -> { + dismiss() + } + } + } + } } private fun initLayout() { diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt index d9832f56..6e46770a 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt @@ -5,16 +5,24 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sopt.peekabookaos.domain.entity.Recommend +import com.sopt.peekabookaos.domain.usecase.DeleteRecommendUseCase import com.sopt.peekabookaos.domain.usecase.GetRecommendUseCase +import com.sopt.peekabookaos.util.UiEvent import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch import timber.log.Timber import javax.inject.Inject @HiltViewModel class RecommendViewModel @Inject constructor( - private val getRecommendUseCase: GetRecommendUseCase + private val getRecommendUseCase: GetRecommendUseCase, + private val deleteRecommendUseCase: DeleteRecommendUseCase ) : ViewModel() { + private val _uiEvent = MutableSharedFlow() + val uiEvent = _uiEvent.asSharedFlow() + private val _recommendedBook = MutableLiveData>() val recommendedBook: LiveData> = _recommendedBook @@ -39,7 +47,16 @@ class RecommendViewModel @Inject constructor( } fun deleteRecommend() { - + viewModelScope.launch { + _uiEvent.emit(UiEvent.IDLE) + deleteRecommendUseCase(requireNotNull(_recommendId.value)) + .onSuccess { + _uiEvent.emit(UiEvent.SUCCESS) + }.onFailure { throwable -> + _uiEvent.emit(UiEvent.ERROR) + Timber.e("$throwable") + } + } } fun setRecommendId(recommendId: Int) { From a541b72f448a8d1735dea7a20e998f5643384512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8B=E1=85=B5=E1=84=88=E1=85=A1=E1=86=BC=E1=84=8C?= =?UTF-8?q?=E1=85=AE?= Date: Mon, 26 Feb 2024 08:22:11 +0900 Subject: [PATCH 5/5] =?UTF-8?q?#299=20[feat]=20=EC=B6=94=EC=B2=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=98=EA=B8=B0=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../recommend/RecommendDeleteDialog.kt | 3 +- .../recommend/RecommendViewModel.kt | 31 ++++++++++++++++--- 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt index 221df551..c205e7e0 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendDeleteDialog.kt @@ -5,7 +5,6 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.WindowManager -import androidx.core.view.isVisible import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import com.sopt.peekabookaos.R @@ -46,8 +45,10 @@ class RecommendDeleteDialog : DialogFragment() { when (uiEvent) { UiEvent.IDLE -> {} UiEvent.SUCCESS -> { + recommendViewModel.getRecommend() dismiss() } + UiEvent.ERROR -> { dismiss() } diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt index 6e46770a..6c3bb8df 100644 --- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt +++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommend/RecommendViewModel.kt @@ -1,6 +1,7 @@ package com.sopt.peekabookaos.presentation.recommend import androidx.lifecycle.LiveData +import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -29,12 +30,31 @@ class RecommendViewModel @Inject constructor( private val _recommendingBook = MutableLiveData>() val recommendingBook: LiveData> = _recommendingBook - private val _isEditMode = MutableLiveData(false) - val isEditMode: LiveData = _isEditMode +// private val _isEditMode = MutableLiveData(false) +// val isEditMode: LiveData = _isEditMode private val _recommendId = MutableLiveData(-1) val recommendId: LiveData = _recommendId + private val _isEditMode = MediatorLiveData().apply { + value = false + + addSource(_recommendedBook) { value = checkEditMode(it, _recommendingBook.value) } + addSource(_recommendingBook) { value = checkEditMode(_recommendedBook.value, it) } + } + val isEditMode: LiveData = _isEditMode + + private fun checkEditMode( + recommendedBooks: List?, + recommendingBooks: List? + ): Boolean { + val recommendedBooksEmpty = recommendedBooks.isNullOrEmpty() + val recommendingBooksEmpty = recommendingBooks.isNullOrEmpty() + + return if (recommendedBooksEmpty && recommendingBooksEmpty) false else _isEditMode.value + ?: false + } + fun toggleEditMode() { _isEditMode.value = _isEditMode.value?.not() val updatedRecommendedBooks = @@ -67,8 +87,11 @@ class RecommendViewModel @Inject constructor( viewModelScope.launch { getRecommendUseCase() .onSuccess { response -> - _recommendingBook.value = response.recommendingBook - _recommendedBook.value = response.recommendedBook + _recommendingBook.value = + response.recommendingBook.map { it.copy(isEditMode = _isEditMode.value!!) } + _recommendedBook.value = + response.recommendedBook.map { it.copy(isEditMode = _isEditMode.value!!) } + checkEditMode(_recommendingBook.value, _recommendedBook.value) }.onFailure { throwable -> Timber.e("$throwable") }