Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix] 위니피드, 마이피드 / 일부 아이템만 갱신하도록 변경 #172

Merged
merged 2 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,19 @@ import com.android.go.sopt.winey.util.view.ItemDiffCallback
import com.android.go.sopt.winey.util.view.setOnSingleClickListener

class WineyFeedAdapter(
private val onlikeButtonClicked: (WineyFeed: WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed: WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed: WineyFeed) -> Unit
private val onlikeButtonClicked: (WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed) -> Unit
) : PagingDataAdapter<WineyFeed, WineyFeedAdapter.WineyFeedViewHolder>(diffUtil) {

class WineyFeedViewHolder(
private val binding: ItemWineyfeedPostBinding,
private val onlikeButtonClicked: (WineyFeed: WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed: WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed: WineyFeed) -> Unit
inner class WineyFeedViewHolder(
private val binding: ItemWineyfeedPostBinding
) : RecyclerView.ViewHolder(binding.root) {

fun onBind(data: WineyFeed?) {
binding.apply {
this.data = data
if (data == null) {
return
}
if (data == null) return

ivWineyfeedLike.setOnSingleClickListener {
onlikeButtonClicked(data)
}
Expand All @@ -50,7 +45,7 @@ class WineyFeedAdapter(
): WineyFeedViewHolder {
val binding =
ItemWineyfeedPostBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return WineyFeedViewHolder(binding, onlikeButtonClicked, onPopupMenuClicked, toFeedDetail)
return WineyFeedViewHolder(binding)
}

override fun onBindViewHolder(holder: WineyFeedViewHolder, position: Int) {
Expand All @@ -69,6 +64,14 @@ class WineyFeedAdapter(
return null
}

fun deleteItem(feedId: Int): MutableList<WineyFeed> {
val currentList = snapshot().items
val newList = currentList.toMutableList()
val feed = currentList.find { it.feedId == feedId }
newList.remove(feed)
return newList
}

companion object {
private val diffUtil = ItemDiffCallback<WineyFeed>(
onItemsTheSame = { old, new -> old.feedId == new.feedId },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.paging.LoadState
import androidx.paging.PagingData
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.SimpleItemAnimator
import com.android.go.sopt.winey.R
Expand Down Expand Up @@ -82,9 +83,11 @@ class WineyFeedFragment :
initAdapter()
setSwipeRefreshListener()
initFabClickListener()
initNotificationButtonClickListener()

initGetFeedStateObserver()
initPostLikeStateObserver()
initNotificationButtonClickListener()
initDeleteFeedStateObserver()
removeRecyclerviewItemChangeAnimation()
}

Expand Down Expand Up @@ -167,17 +170,26 @@ class WineyFeedFragment :
showAsDropDown(anchorView, -POPUP_MENU_OFFSET, -POPUP_MENU_OFFSET, Gravity.END)
}

private fun showFeedDeleteDialog(wineyFeed: WineyFeed) {
private fun showFeedDeleteDialog(feed: WineyFeed) {
val dialog = WineyDialogFragment(
stringOf(R.string.feed_delete_dialog_title),
stringOf(R.string.feed_delete_dialog_subtitle),
stringOf(R.string.comment_delete_dialog_negative_button),
stringOf(R.string.comment_delete_dialog_positive_button),
handleNegativeButton = {},
handlePositiveButton = { viewModel.deleteFeed(wineyFeed.feedId) }
handlePositiveButton = {
viewModel.deleteFeed(feed.feedId)
deletePagingDataItem(feed.feedId)
}
)
dialog.show(parentFragmentManager, TAG_FEED_DELETE_DIALOG)
initDeleteFeedStateObserver()
}

private fun deletePagingDataItem(feedId: Int) {
viewLifeCycleScope.launch {
val newList = wineyFeedAdapter.deleteItem(feedId)
wineyFeedAdapter.submitData(PagingData.from(newList))
}
}

private fun showFeedReportDialog() {
Expand All @@ -201,24 +213,24 @@ class WineyFeedFragment :
private fun isMyFeed(currentUserId: Int?, writerId: Int) = currentUserId == writerId

private fun initDeleteFeedStateObserver() {
viewModel.deleteWineyFeedState.flowWithLifecycle(viewLifeCycle).onEach { state ->
when (state) {
is UiState.Success -> {
refreshWineyFeed()
wineySnackbar(
binding.root,
true,
stringOf(R.string.snackbar_feed_delete_success)
)
}
viewModel.deleteWineyFeedState.flowWithLifecycle(viewLifeCycle)
.onEach { state ->
when (state) {
is UiState.Success -> {
wineySnackbar(
binding.root,
true,
stringOf(R.string.snackbar_feed_delete_success)
)
}

is UiState.Failure -> {
snackBar(binding.root) { state.msg }
}
is UiState.Failure -> {
snackBar(binding.root) { state.msg }
}

else -> Timber.tag("failure").e(MSG_WINEYFEED_ERROR)
}
}.launchIn(viewLifeCycleScope)
else -> Timber.tag("failure").e(MSG_WINEYFEED_ERROR)
}
}.launchIn(viewLifeCycleScope)
}

private fun initGetFeedStateObserver() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ class WineyFeedViewModel @Inject constructor(
private val feedRepository: FeedRepository
) : ViewModel() {
private val _getWineyFeedListState =
MutableStateFlow<UiState<PagingData<WineyFeed>>>(UiState.Loading)
MutableStateFlow<UiState<PagingData<WineyFeed>>>(UiState.Empty)
val getWineyFeedListState: StateFlow<UiState<PagingData<WineyFeed>>> =
_getWineyFeedListState.asStateFlow()

private val _postWineyFeedLikeState = MutableStateFlow<UiState<Like>>(UiState.Empty)
val postWineyFeedLikeState: StateFlow<UiState<Like>> = _postWineyFeedLikeState.asStateFlow()

val _deleteWineyFeedState = MutableStateFlow<UiState<Unit>>(UiState.Loading)
val _deleteWineyFeedState = MutableStateFlow<UiState<Unit>>(UiState.Empty)
val deleteWineyFeedState: StateFlow<UiState<Unit>> = _deleteWineyFeedState.asStateFlow()

init {
Expand All @@ -45,6 +45,8 @@ class WineyFeedViewModel @Inject constructor(

fun deleteFeed(feedId: Int) {
viewModelScope.launch {
_deleteWineyFeedState.emit(UiState.Loading)

feedRepository.deleteFeed(feedId)
.onSuccess { response ->
_deleteWineyFeedState.emit(UiState.Success(response))
Expand All @@ -56,6 +58,7 @@ class WineyFeedViewModel @Inject constructor(
private fun postLike(feedId: Int, requestPostLikeDto: RequestPostLikeDto) {
viewModelScope.launch {
_postWineyFeedLikeState.emit(UiState.Loading)

feedRepository.postFeedLike(feedId, requestPostLikeDto)
.onSuccess { response ->
_postWineyFeedLikeState.emit(UiState.Success(response))
Expand All @@ -67,6 +70,7 @@ class WineyFeedViewModel @Inject constructor(
fun getWineyFeed() {
viewModelScope.launch {
_getWineyFeedListState.emit(UiState.Loading)

feedRepository.getWineyFeedList().cachedIn(viewModelScope)
.collectLatest { response ->
_getWineyFeedListState.emit(UiState.Success(response))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package com.android.go.sopt.winey.presentation.main.mypage.myfeed
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.paging.ItemSnapshotList
import androidx.paging.PagingDataAdapter
import androidx.recyclerview.widget.RecyclerView
import com.android.go.sopt.winey.databinding.ItemMyfeedPostBinding
Expand All @@ -12,18 +11,13 @@ import com.android.go.sopt.winey.util.view.ItemDiffCallback
import com.android.go.sopt.winey.util.view.setOnSingleClickListener

class MyFeedAdapter(
private val onlikeButtonClicked: (WineyFeed: WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed: WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed: WineyFeed) -> Unit
private val onlikeButtonClicked: (WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed) -> Unit
) : PagingDataAdapter<WineyFeed, MyFeedAdapter.MyFeedViewHolder>(diffUtil) {
private val currentData: ItemSnapshotList<WineyFeed>
get() = snapshot()

class MyFeedViewHolder(
private val binding: ItemMyfeedPostBinding,
private val onlikeButtonClicked: (WineyFeed: WineyFeed) -> Unit,
private val onPopupMenuClicked: (View, WineyFeed: WineyFeed) -> Unit,
private val toFeedDetail: (WineyFeed: WineyFeed) -> Unit
inner class MyFeedViewHolder(
private val binding: ItemMyfeedPostBinding
) : RecyclerView.ViewHolder(binding.root) {
fun onBind(data: WineyFeed?) {
binding.apply {
Expand All @@ -50,7 +44,7 @@ class MyFeedAdapter(
): MyFeedViewHolder {
val binding =
ItemMyfeedPostBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return MyFeedViewHolder(binding, onlikeButtonClicked, onPopupMenuClicked, toFeedDetail)
return MyFeedViewHolder(binding)
}

override fun onBindViewHolder(holder: MyFeedViewHolder, position: Int) {
Expand All @@ -67,6 +61,14 @@ class MyFeedAdapter(
}
}

fun deleteItem(feedId: Int): MutableList<WineyFeed> {
val currentList = snapshot().items
val newList = currentList.toMutableList()
val feed = currentList.find { it.feedId == feedId }
newList.remove(feed)
return newList
}

companion object {
private val diffUtil = ItemDiffCallback<WineyFeed>(
onItemsTheSame = { old, new -> old.feedId == new.feedId },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.paging.LoadState
import androidx.paging.PagingData
import androidx.recyclerview.widget.SimpleItemAnimator
import com.android.go.sopt.winey.R
import com.android.go.sopt.winey.databinding.FragmentMyfeedBinding
Expand All @@ -23,8 +24,6 @@ import com.android.go.sopt.winey.presentation.main.feed.WineyFeedLoadAdapter
import com.android.go.sopt.winey.presentation.main.feed.detail.DetailActivity
import com.android.go.sopt.winey.presentation.main.mypage.MyPageFragment
import com.android.go.sopt.winey.util.binding.BindingFragment
import com.android.go.sopt.winey.util.context.stringOf
import com.android.go.sopt.winey.util.context.wineySnackbar
import com.android.go.sopt.winey.util.fragment.WineyDialogFragment
import com.android.go.sopt.winey.util.fragment.snackBar
import com.android.go.sopt.winey.util.fragment.stringOf
Expand Down Expand Up @@ -52,11 +51,14 @@ class MyFeedFragment : BindingFragment<FragmentMyfeedBinding>(R.layout.fragment_

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

removeRecyclerviewItemChangeAnimation()
initAdapter()
initBackButtonClickListener()

initGetFeedStateObserver()
initPostLikeStateObserver()
initButtonClickListener()
initDeleteFeedStateObserver()
}

override fun onStart() {
Expand Down Expand Up @@ -112,20 +114,37 @@ class MyFeedFragment : BindingFragment<FragmentMyfeedBinding>(R.layout.fragment_
showAsDropDown(anchorView, -POPUP_MENU_OFFSET, -POPUP_MENU_OFFSET, Gravity.END)
}

private fun showFeedDeleteDialog(wineyFeed: WineyFeed) {
private fun showFeedDeleteDialog(feed: WineyFeed) {
val dialog = WineyDialogFragment(
stringOf(R.string.feed_delete_dialog_title),
stringOf(R.string.feed_delete_dialog_subtitle),
stringOf(R.string.comment_delete_dialog_negative_button),
stringOf(R.string.comment_delete_dialog_positive_button),
handleNegativeButton = {},
handlePositiveButton = { viewModel.deleteFeed(wineyFeed.feedId) }
handlePositiveButton = {
viewModel.deleteFeed(feed.feedId)
deletePagingDataItem(feed.feedId)
}
)
dialog.show(parentFragmentManager, TAG_FEED_DELETE_DIALOG)
initDeleteFeedStateObserver()
}

private fun initButtonClickListener() {
private fun deletePagingDataItem(feedId: Int) {
viewLifeCycleScope.launch {
val newList = myFeedAdapter.deleteItem(feedId)
checkEmptyList(newList)
myFeedAdapter.submitData(PagingData.from(newList))
}
}

private fun checkEmptyList(newList: MutableList<WineyFeed>) {
if (newList.isEmpty()) {
binding.rvMyfeedPost.isVisible = false
binding.clMyfeedEmpty.isVisible = true
}
}

private fun initBackButtonClickListener() {
binding.imgMyfeedBack.setOnSingleClickListener {
navigateTo<MyPageFragment>()
parentFragmentManager.popBackStack()
Expand All @@ -136,7 +155,6 @@ class MyFeedFragment : BindingFragment<FragmentMyfeedBinding>(R.layout.fragment_
viewModel.deleteMyFeedState.flowWithLifecycle(viewLifeCycle).onEach { state ->
when (state) {
is UiState.Success -> {
refreshMyFeed()
wineySnackbar(requireView(), true, stringOf(R.string.snackbar_feed_delete_success))
}

Expand All @@ -150,22 +168,21 @@ class MyFeedFragment : BindingFragment<FragmentMyfeedBinding>(R.layout.fragment_
}

private fun initGetFeedStateObserver() {
viewLifecycleOwner.lifecycleScope.launch {
viewLifeCycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.getMyFeedListState.collectLatest { state ->
when (state) {
is UiState.Success -> {
myFeedAdapter.addLoadStateListener { loadState ->
when (loadState.refresh) {
is LoadState.Loading -> {
binding.lMyfeedEmpty.isVisible = false
binding.clMyfeedEmpty.isVisible = false
binding.rvMyfeedPost.isVisible = false
}

is LoadState.NotLoading -> {
binding.rvMyfeedPost.isVisible = myFeedAdapter.itemCount > 0
binding.lMyfeedEmpty.isVisible =
myFeedAdapter.itemCount == 0
binding.clMyfeedEmpty.isVisible = myFeedAdapter.itemCount == 0
restoreScrollPosition()
}

Expand Down Expand Up @@ -208,14 +225,6 @@ class MyFeedFragment : BindingFragment<FragmentMyfeedBinding>(R.layout.fragment_
}.launchIn(viewLifeCycleScope)
}

private fun refreshMyFeed() {
val fragmentManager = requireActivity().supportFragmentManager
fragmentManager.beginTransaction().apply {
replace(R.id.fcv_main, MyFeedFragment())
commit()
}
}

private fun navigateToDetail(wineyFeed: WineyFeed) {
selectedItemIndex = myFeedAdapter.snapshot().indexOf(wineyFeed)
selectedScrollPosition = binding.rvMyfeedPost.layoutManager?.onSaveInstanceState()
Expand Down
Loading