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

feat: 활동 관련 뷰 더보기 팝업메뉴 구현 #412

Open
wants to merge 15 commits into
base: develop
Choose a base branch
from
Open
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 @@ -3,16 +3,29 @@ package com.teamwss.websoso.ui.activityDetail
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.WindowManager
import android.widget.PopupWindow
import android.widget.TextView
import androidx.activity.viewModels
import androidx.databinding.ViewDataBinding
import com.teamwss.websoso.R
import com.teamwss.websoso.R.string.my_activity_detail_title
import com.teamwss.websoso.R.string.other_user_page_activity
import com.teamwss.websoso.common.ui.base.BaseActivity
import com.teamwss.websoso.databinding.ActivityActivityDetailBinding
import com.teamwss.websoso.databinding.MenuMyActivityPopupBinding
import com.teamwss.websoso.databinding.MenuOtherUserActivityPopupBinding
import com.teamwss.websoso.ui.activityDetail.adapter.ActivityDetailAdapter
import com.teamwss.websoso.ui.createFeed.CreateFeedActivity
import com.teamwss.websoso.ui.feedDetail.FeedDetailActivity
import com.teamwss.websoso.ui.feedDetail.model.EditFeedModel
import com.teamwss.websoso.ui.main.feed.dialog.FeedRemoveDialogFragment
import com.teamwss.websoso.ui.main.feed.dialog.FeedReportDialogFragment
import com.teamwss.websoso.ui.main.feed.dialog.FeedReportDoneDialogFragment
import com.teamwss.websoso.ui.main.feed.dialog.RemoveMenuType
import com.teamwss.websoso.ui.main.feed.dialog.ReportMenuType
import com.teamwss.websoso.ui.main.myPage.MyPageViewModel
import com.teamwss.websoso.ui.main.myPage.myActivity.ActivityItemClickListener
import com.teamwss.websoso.ui.main.myPage.myActivity.MyActivityFragment
Expand All @@ -38,6 +51,7 @@ class ActivityDetailActivity :
intent.getStringExtra(MyActivityFragment.EXTRA_SOURCE) ?: ""
}
private val userId: Long by lazy { intent.getLongExtra(USER_ID_KEY, DEFAULT_USER_ID) }
private var _popupWindow: PopupWindow? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand Down Expand Up @@ -74,9 +88,9 @@ class ActivityDetailActivity :
}

private fun setupObserver() {
activityDetailViewModel.userActivity.observe(this) { activities ->
activityDetailViewModel.activityDetailUiState.observe(this) { uiState ->
val userProfile = getUserProfile()
updateAdapterWithActivitiesAndProfile(activities, userProfile)
updateAdapterWithActivitiesAndProfile(uiState.activities, userProfile)
}

when (activityDetailViewModel.source) {
Expand All @@ -85,7 +99,7 @@ class ActivityDetailActivity :
uiState.myProfile?.let { myProfile ->
val userProfile = myProfile.toUserProfileModel()
updateAdapterWithActivitiesAndProfile(
activityDetailViewModel.userActivity.value,
activityDetailViewModel.activityDetailUiState.value?.activities,
userProfile
)
}
Expand All @@ -97,8 +111,8 @@ class ActivityDetailActivity :
otherUserProfile?.let {
val userProfile = otherUserProfile.toUserProfileModel()
updateAdapterWithActivitiesAndProfile(
activityDetailViewModel.userActivity.value,
userProfile
activityDetailViewModel.activityDetailUiState.value?.activities,
userProfile,
)
}
}
Expand Down Expand Up @@ -162,18 +176,113 @@ class ActivityDetailActivity :
likeCountTextView.text = updatedLikeCount.toString()
view.isSelected = !view.isSelected

activityDetailViewModel.updateActivityLike(
view.isSelected,
feedId,
updatedLikeCount,
)
activityDetailViewModel.updateActivityLike(view.isSelected, feedId, updatedLikeCount)
}

override fun onMoreButtonClick(view: View, feedId: Long) {
// TODO 팝업메뉴 수정 및 차단
showPopupMenu(view, feedId)
}
}

private fun showPopupMenu(view: View, feedId: Long) {
val inflater = LayoutInflater.from(this)
val binding = when (source) {
SOURCE_MY_ACTIVITY -> MenuMyActivityPopupBinding.inflate(inflater)
SOURCE_OTHER_USER_ACTIVITY -> MenuOtherUserActivityPopupBinding.inflate(inflater)
else -> return
}

_popupWindow?.dismiss()
_popupWindow = PopupWindow(
binding.root,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
true
).apply {
elevation = 2f
showAsDropDown(view)
}
setupPopupMenuClickListeners(binding, feedId)
}

private fun setupPopupMenuClickListeners(binding: ViewDataBinding, feedId: Long) {
when (binding) {
is MenuMyActivityPopupBinding -> {
binding.tvMyActivityModification.setOnClickListener {
navigateToFeedEdit(feedId)
_popupWindow?.dismiss()
}
binding.tvMyActivityPopupDeletion.setOnClickListener {
showRemoveDialog(feedId)
_popupWindow?.dismiss()
}
}

is MenuOtherUserActivityPopupBinding -> {
binding.tvOtherUserActivityReportSpoiler.setOnClickListener {
showReportDialog(feedId, ReportMenuType.SPOILER_FEED.name)
_popupWindow?.dismiss()
}
binding.tvOtherUserActivityReportExpression.setOnClickListener {
showReportDialog(feedId, ReportMenuType.IMPERTINENCE_FEED.name)
_popupWindow?.dismiss()
}
}
}
}

private fun navigateToFeedEdit(feedId: Long) {
val activityModel =
activityDetailViewModel.activityDetailUiState.value?.activities?.find { it.feedId == feedId }
activityModel?.let { feed ->
val editFeedModel = EditFeedModel(
feedId = feed.feedId,
novelId = feed.novelId ?: 0L,
novelTitle = feed.title ?: "",
feedContent = feed.feedContent,
feedCategory = feed.relevantCategories?.split(", ") ?: emptyList()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: 트콤

)
startActivity(CreateFeedActivity.getIntent(this, editFeedModel))
} ?: throw IllegalArgumentException("Feed not found")
}

private fun showRemoveDialog(feedId: Long) {
val dialogFragment = FeedRemoveDialogFragment.newInstance(
menuType = RemoveMenuType.REMOVE_FEED.name,
event = {
activityDetailViewModel.updateRemovedFeed(feedId)
}
)
dialogFragment.show(supportFragmentManager, FeedRemoveDialogFragment.TAG)
}

private fun showReportDialog(feedId: Long, menuType: String) {
val dialogFragment = FeedReportDialogFragment.newInstance(
menuType = menuType,
event = {
when (menuType) {
ReportMenuType.SPOILER_FEED.name -> activityDetailViewModel.updateReportedSpoilerFeed(
feedId
)

ReportMenuType.IMPERTINENCE_FEED.name -> activityDetailViewModel.updateReportedImpertinenceFeed(
feedId
)
}
showReportDoneDialog(menuType)
}
)
dialogFragment.show(supportFragmentManager, FeedReportDialogFragment.TAG)
}

private fun showReportDoneDialog(menuType: String) {
val doneDialogFragment = FeedReportDoneDialogFragment.newInstance(
menuType = menuType,
event = {}
)
doneDialogFragment.show(supportFragmentManager, FeedReportDoneDialogFragment.TAG)
}
Comment on lines +278 to +284
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c: 신고는 지금 기능구현이 안되어 있는걸까요?


companion object {
const val USER_ID_KEY = "userId"
const val DEFAULT_USER_ID = -1L
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.lifecycle.viewModelScope
import com.teamwss.websoso.data.repository.FeedRepository
import com.teamwss.websoso.data.repository.UserRepository
import com.teamwss.websoso.ui.activityDetail.ActivityDetailActivity.Companion.SOURCE_MY_ACTIVITY
import com.teamwss.websoso.ui.main.myPage.myActivity.model.ActivitiesModel.ActivityModel
import com.teamwss.websoso.ui.activityDetail.model.ActivityDetailUiState
import com.teamwss.websoso.ui.main.myPage.myActivity.model.ActivityLikeState
import com.teamwss.websoso.ui.mapper.toUi
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -22,15 +22,12 @@ class ActivityDetailViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
) : ViewModel() {

private val _userActivity = MutableLiveData<List<ActivityModel>>()
val userActivity: LiveData<List<ActivityModel>> get() = _userActivity
private val _activityDetailUiState = MutableLiveData<ActivityDetailUiState>()
val activityDetailUiState: LiveData<ActivityDetailUiState> get() = _activityDetailUiState

private val _likeState = MutableLiveData<ActivityLikeState>()
val likeState: LiveData<ActivityLikeState> get() = _likeState

private val _lastFeedId: MutableLiveData<Long> = MutableLiveData(0L)
val lastFeedId: LiveData<Long> get() = _lastFeedId

private val size: Int = ACTIVITY_LOAD_SIZE

var source: String?
Expand All @@ -45,6 +42,10 @@ class ActivityDetailViewModel @Inject constructor(
savedStateHandle["userId"] = value
}

init {
_activityDetailUiState.value = ActivityDetailUiState()
}

fun updateUserActivities(userId: Long) {
this.userId = userId
if (source == SOURCE_MY_ACTIVITY) {
Expand All @@ -55,32 +56,50 @@ class ActivityDetailViewModel @Inject constructor(
}

private fun updateMyActivities() {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(isLoading = true)
viewModelScope.launch {
runCatching {
userRepository.fetchMyActivities(
lastFeedId.value ?: 0L,
_activityDetailUiState.value?.lastFeedId ?: 0L,
size,
)
}.onSuccess { response ->
_userActivity.value = response.feeds.map { it.toUi() }

_lastFeedId.value = response.feeds.lastOrNull()?.feedId?.toLong() ?: 0L
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
activities = response.feeds.map { it.toUi() },
lastFeedId = response.feeds.lastOrNull()?.feedId?.toLong() ?: 0L,
error = false,
)
}.onFailure { exception ->
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
error = true,
)
}
}
}

private fun updateOtherUserActivities(userId: Long) {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(isLoading = true)
viewModelScope.launch {
runCatching {
userRepository.fetchUserFeeds(
userId = userId,
lastFeedId = lastFeedId.value ?: 0L,
lastFeedId = _activityDetailUiState.value?.lastFeedId ?: 0L,
size = size,
)
}.onSuccess { response ->
_userActivity.value = response.feeds.map { it.toUi() }
_lastFeedId.value = response.feeds.lastOrNull()?.feedId?.toLong() ?: 0L
}.onFailure {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
activities = response.feeds.map { it.toUi() },
lastFeedId = response.feeds.lastOrNull()?.feedId?.toLong() ?: 0L,
error = false,
)
}.onFailure { exception ->
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
error = true,
)
}
}
}
Expand All @@ -96,22 +115,80 @@ class ActivityDetailViewModel @Inject constructor(
}.onSuccess {
val newLikeCount = if (isLiked) currentLikeCount - 1 else currentLikeCount + 1
_likeState.value = ActivityLikeState(feedId, !isLiked, newLikeCount)

saveActivityLikeState(feedId, !isLiked, newLikeCount)
updateLikeStateInUi(feedId, !isLiked, newLikeCount)
}.onFailure {

}
}
}

private fun saveActivityLikeState(feedId: Long, isLiked: Boolean, likeCount: Int) {
_userActivity.value = _userActivity.value?.map { activity ->
if (activity.feedId == feedId) {
activity.copy(
isLiked = isLiked,
likeCount = likeCount,
private fun updateLikeStateInUi(feedId: Long, isLiked: Boolean, likeCount: Int) {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
activities = _activityDetailUiState.value?.activities?.map { activity ->
if (activity.feedId == feedId) {
activity.copy(
isLiked = isLiked,
likeCount = likeCount,
)
} else {
activity
}
} ?: emptyList()
)
}

fun updateRemovedFeed(feedId: Long) {
viewModelScope.launch {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(isLoading = true)
runCatching {
feedRepository.saveRemovedFeed(feedId)
}.onSuccess {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
activities = _activityDetailUiState.value?.activities?.filter { it.feedId != feedId }
?: emptyList(),
)
}.onFailure {
_activityDetailUiState.value = _activityDetailUiState.value?.copy(
isLoading = false,
error = true,
)
} else {
activity
}
}
}

fun updateReportedSpoilerFeed(feedId: Long) {
activityDetailUiState.value?.let { feedUiState ->
viewModelScope.launch {
_activityDetailUiState.value = feedUiState.copy(isLoading = true)
runCatching {
feedRepository.saveSpoilerFeed(feedId)
}.onSuccess {
_activityDetailUiState.value = feedUiState.copy(isLoading = false)
}.onFailure {
_activityDetailUiState.value = feedUiState.copy(
isLoading = false,
error = true,
)
}
}
}
}

fun updateReportedImpertinenceFeed(feedId: Long) {
activityDetailUiState.value?.let { feedUiState ->
viewModelScope.launch {
_activityDetailUiState.value = feedUiState.copy(isLoading = true)
runCatching {
feedRepository.saveImpertinenceFeed(feedId)
}.onSuccess {
_activityDetailUiState.value = feedUiState.copy(isLoading = false)
}.onFailure {
_activityDetailUiState.value = feedUiState.copy(
isLoading = false,
error = true,
)
}
}
}
}
Expand All @@ -120,4 +197,4 @@ class ActivityDetailViewModel @Inject constructor(
const val ACTIVITY_LOAD_SIZE = 10
const val DEFAULT_USER_ID = -1L
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.teamwss.websoso.ui.activityDetail.model

import com.teamwss.websoso.ui.main.myPage.myActivity.model.ActivitiesModel

data class ActivityDetailUiState(
val isLoading: Boolean = false,
val activities: List<ActivitiesModel.ActivityModel> = emptyList(),
val lastFeedId: Long = 0L,
val error: Boolean = false,
)
Loading