diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/EventStoryRepository.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/EventStoryRepository.kt index 7fafa77..e503398 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/EventStoryRepository.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/EventStoryRepository.kt @@ -196,7 +196,7 @@ class EventStoryRepository @Inject constructor( fun getFollowingWithEventState(eventId: Int): Flow> { return flowOf(true) .map { - eventStoryApi.getFollowingWithEventStatus(eventId).users + eventStoryApi.getFollowingWithEventStatus(eventId).users.sortedBy { it.nickname } }.catch { throw it.toException() } @@ -205,7 +205,7 @@ class EventStoryRepository @Inject constructor( fun getFollowerWithEventState(eventId: Int): Flow> { return flowOf(true) .map { - eventStoryApi.getFollowerWithEventStatus(eventId).users + eventStoryApi.getFollowerWithEventStatus(eventId).users.sortedBy { it.nickname } }.catch { throw it.toException() } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/FollowRepository.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/FollowRepository.kt index d6e80d4..0520a49 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/FollowRepository.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/data/repository/FollowRepository.kt @@ -35,7 +35,7 @@ class FollowRepository @Inject constructor( fun getFollowingWithFollowState(): Flow> { return flowOf(true) .map { - followApi.getFollowingWithFollowStatus().users + followApi.getFollowingWithFollowStatus().users.sortedBy { it.nickname } }.catch { throw it.toException() } @@ -44,7 +44,7 @@ class FollowRepository @Inject constructor( fun getFollowerWithFollowState(): Flow> { return flowOf(true) .map { - followApi.getFollowerWithFollowStatus().users + followApi.getFollowerWithFollowStatus().users.sortedBy { it.nickname } }.catch { throw it.toException() } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/addevent/AddEventActivity.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/addevent/AddEventActivity.kt index 3193795..869cef2 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/addevent/AddEventActivity.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/addevent/AddEventActivity.kt @@ -17,6 +17,8 @@ import com.teameetmeet.meetmeet.databinding.ActivityAddEventBinding import com.teameetmeet.meetmeet.presentation.base.BaseActivity import com.teameetmeet.meetmeet.presentation.model.EventNotification import com.teameetmeet.meetmeet.presentation.model.EventRepeatTerm +import com.teameetmeet.meetmeet.presentation.util.setClickEvent +import com.teameetmeet.meetmeet.presentation.util.setMenuClickEvent import com.teameetmeet.meetmeet.util.date.toLocalDateTime import com.teameetmeet.meetmeet.util.date.toLong import dagger.hilt.android.AndroidEntryPoint @@ -51,14 +53,11 @@ class AddEventActivity : BaseActivity(R.layout.activity private fun setTopAppBar() { with(binding.topAppBar) { - setOnMenuItemClickListener { menuItem -> - when (menuItem.itemId) { + setMenuClickEvent(lifecycleScope) { menuItemId -> + when (menuItemId) { R.id.menu_save -> { viewModel.eventSave() - true } - - else -> false } } setNavigationOnClickListener { @@ -138,13 +137,13 @@ class AddEventActivity : BaseActivity(R.layout.activity ) } - binding.addEventTvValueStartDate.setOnClickListener { + binding.addEventTvValueStartDate.setClickEvent(lifecycleScope) { dateRangePicker.show(supportFragmentManager, "DateRangePicker") } - binding.addEventTvValueEndDate.setOnClickListener { + binding.addEventTvValueEndDate.setClickEvent(lifecycleScope) { dateRangePicker.show(supportFragmentManager, "DateRangePicker") } - binding.eventStoryTvValueEventRepeatEndDate.setOnClickListener { + binding.eventStoryTvValueEventRepeatEndDate.setClickEvent(lifecycleScope) { val datePicker = MaterialDatePicker.Builder.datePicker() .setTitleText(getString(R.string.story_detail_description_event_repeat_end_date)) .build() @@ -173,10 +172,10 @@ class AddEventActivity : BaseActivity(R.layout.activity viewModel.setEventEndTime(endTimePicker.hour, endTimePicker.minute) } - binding.addEventTvValueStartTime.setOnClickListener { + binding.addEventTvValueStartTime.setClickEvent(lifecycleScope) { startTimePicker.show(supportFragmentManager, "StartTimePicker") } - binding.addEventTvValueEndTime.setOnClickListener { + binding.addEventTvValueEndTime.setClickEvent(lifecycleScope) { endTimePicker.show(supportFragmentManager, "EndTimePicker") } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowAdapter.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowAdapter.kt index dc57359..14658a7 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowAdapter.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowAdapter.kt @@ -9,30 +9,29 @@ import com.teameetmeet.meetmeet.data.model.UserStatus class FollowAdapter( private val actionType: FollowActionType, private val userClickListener: OnUserClickListener, - private val id: Int? -) : - ListAdapter(ItemDiffCallback) { + private val eventId: Int? +) : ListAdapter(diffCallback) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FollowViewHolder { - return FollowViewHolder.from(parent) + return FollowViewHolder.from(parent, actionType, userClickListener, eventId) } override fun onBindViewHolder(holder: FollowViewHolder, position: Int) { - holder.bind(getItem(position), actionType, userClickListener, id) + holder.bind(getItem(position)) } - object ItemDiffCallback : DiffUtil.ItemCallback() { - override fun areItemsTheSame( - oldItem: UserStatus, - newItem: UserStatus - ): Boolean { - return oldItem.id == newItem.id - } + companion object { + private val diffCallback = object : DiffUtil.ItemCallback() { + override fun areItemsTheSame( + oldItem: UserStatus, newItem: UserStatus + ): Boolean { + return oldItem.id == newItem.id + } - override fun areContentsTheSame( - oldItem: UserStatus, - newItem: UserStatus - ): Boolean { - return oldItem == newItem + override fun areContentsTheSame( + oldItem: UserStatus, newItem: UserStatus + ): Boolean { + return oldItem == newItem + } } } } \ No newline at end of file diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowFragment.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowFragment.kt index 4e1490f..cfe2a25 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowFragment.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowFragment.kt @@ -87,7 +87,7 @@ class FollowFragment : BaseFragment(R.layout.fragment_fol followAdapter = FollowAdapter( actionType = args.actionType, userClickListener = viewModel, - id = args.id + eventId = args.id ) binding.followSearchResultRv.adapter = followAdapter } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowSearchFragment.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowSearchFragment.kt index cf467ad..991d017 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowSearchFragment.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowSearchFragment.kt @@ -42,7 +42,7 @@ class FollowSearchFragment : binding.state = followState followAdapter = FollowAdapter( - actionType = actionType, userClickListener = followViewModel, id = id + actionType = actionType, userClickListener = followViewModel, eventId = id ) binding.followListRv.adapter = followAdapter } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowViewHolder.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowViewHolder.kt index d869c01..7ad3139 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowViewHolder.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/follow/FollowViewHolder.kt @@ -2,88 +2,111 @@ package com.teameetmeet.meetmeet.presentation.follow import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.doOnAttach +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.data.model.UserStatus import com.teameetmeet.meetmeet.databinding.ItemFollowBinding +import com.teameetmeet.meetmeet.presentation.util.setClickEvent -class FollowViewHolder private constructor(private val binding: ItemFollowBinding) : - RecyclerView.ViewHolder(binding.root) { +class FollowViewHolder private constructor( + private val binding: ItemFollowBinding, + private val actionType: FollowActionType, + private val userClickListener: OnUserClickListener, + private val eventId: Int? +) : RecyclerView.ViewHolder(binding.root) { - fun bind( - user: UserStatus, - actionType: FollowActionType, - userClickListener: OnUserClickListener, - id: Int? - ) { - binding.user = user - itemView.setOnClickListener { - userClickListener.onProfileClick(user) - } - when (actionType) { - FollowActionType.FOLLOW -> { - with(binding.followBtnAction) { - user.isFollowed?.let { followStatus -> - if (followStatus) { - text = context.getString(R.string.follow_title_unfollow) - setOnClickListener { - userClickListener.onUnfollowClick(user) - } - } else { - text = context.getString(R.string.follow_title_follow) - setOnClickListener { - userClickListener.onFollowClick(user) - } - } + init { + itemView.doOnAttach { + itemView.findViewTreeLifecycleOwner()?.let { lifecycleOwner -> + binding.user?.let { user -> + itemView.setClickEvent(lifecycleOwner.lifecycleScope) { + userClickListener.onProfileClick(user) } - } - } - - FollowActionType.EVENT -> { - with(binding.followBtnAction) { - when (user.isJoined) { - UserStatus.JOIN_STATUS_JOINABLE -> { - text = context.getString(R.string.event_story_invite) - setOnClickListener { - id?.let { - userClickListener.onInviteEventClick(user, id) + when (actionType) { + FollowActionType.FOLLOW -> { + with(binding.followBtnAction) { + user.isFollowed?.let { followStatus -> + if (followStatus) { + text = context.getString(R.string.follow_title_unfollow) + setClickEvent(lifecycleOwner.lifecycleScope) { + userClickListener.onUnfollowClick(user) + } + } else { + text = context.getString(R.string.follow_title_follow) + setClickEvent(lifecycleOwner.lifecycleScope) { + userClickListener.onFollowClick(user) + } + } } } - isEnabled = true } - UserStatus.JOIN_STATUS_PENDING -> { - text = context.getString(R.string.event_story_pending) - isEnabled = false - } + FollowActionType.EVENT -> { + with(binding.followBtnAction) { + when (user.isJoined) { + UserStatus.JOIN_STATUS_JOINABLE -> { + text = context.getString(R.string.event_story_invite) + setClickEvent(lifecycleOwner.lifecycleScope) { + eventId?.let { + userClickListener.onInviteEventClick(user, eventId) + } + } + isEnabled = true + } - UserStatus.JOIN_STATUS_ACCEPTED -> { - text = context.getString(R.string.event_story_participating) - isEnabled = false - } + UserStatus.JOIN_STATUS_PENDING -> { + text = context.getString(R.string.event_story_pending) + isEnabled = false + } + + UserStatus.JOIN_STATUS_ACCEPTED -> { + text = context.getString(R.string.event_story_participating) + isEnabled = false + } - else -> { - isEnabled = false + else -> { + isEnabled = false + } + } + } } - } - } - } - FollowActionType.GROUP -> { - binding.followBtnAction.setOnClickListener { - id?.let { - userClickListener.onInviteGroupClick(user, id) + FollowActionType.GROUP -> { + binding.followBtnAction.setClickEvent(lifecycleOwner.lifecycleScope) { + eventId?.let { + userClickListener.onInviteGroupClick(user, eventId) + } + } + } } } } } + } + fun bind( + user: UserStatus + ) { + binding.user = user } companion object { - fun from(parent: ViewGroup): FollowViewHolder { + fun from( + parent: ViewGroup, + actionType: FollowActionType, + userClickListener: OnUserClickListener, + eventId: Int? + ): FollowViewHolder { val inflater = LayoutInflater.from(parent.context) - return FollowViewHolder(ItemFollowBinding.inflate(inflater, parent, false)) + return FollowViewHolder( + ItemFollowBinding.inflate(inflater, parent, false), + actionType, + userClickListener, + eventId + ) } } } \ No newline at end of file diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/EventNotificationViewModel.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/EventNotificationViewModel.kt index 2451172..4acebad 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/EventNotificationViewModel.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/EventNotificationViewModel.kt @@ -82,12 +82,14 @@ class EventNotificationViewModel @Inject constructor( fun onDeleteAll() { viewModelScope.launch { - userRepository.deleteUserNotification( - _eventNotificationList.value.map { it.inviteId }.joinToString(",") - ).catch { - emitExceptionEvent(it, R.string.notification_delete_fail) - }.collectLatest { - fetchEventNotificationList() + if (_eventNotificationList.value.isNotEmpty()) { + userRepository.deleteUserNotification( + _eventNotificationList.value.map { it.inviteId }.joinToString(",") + ).catch { + emitExceptionEvent(it, R.string.notification_delete_fail) + }.collectLatest { + fetchEventNotificationList() + } } } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/FollowNotificationViewModel.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/FollowNotificationViewModel.kt index b540a4d..5c71dc5 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/FollowNotificationViewModel.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/FollowNotificationViewModel.kt @@ -44,12 +44,14 @@ class FollowNotificationViewModel @Inject constructor( fun onDeleteAll() { viewModelScope.launch { - userRepository.deleteUserNotification( - _followNotificationList.value.map { it.inviteId }.joinToString(",") - ).catch { - emitExceptionEvent(it, R.string.notification_delete_fail) - }.collectLatest { - fetchFollowNotificationList() + if (_followNotificationList.value.isNotEmpty()) { + userRepository.deleteUserNotification( + _followNotificationList.value.map { it.inviteId }.joinToString(",") + ).catch { + emitExceptionEvent(it, R.string.notification_delete_fail) + }.collectLatest { + fetchFollowNotificationList() + } } } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/NotificationActivity.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/NotificationActivity.kt index d5eebe9..3f7fa82 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/NotificationActivity.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/NotificationActivity.kt @@ -4,11 +4,13 @@ import android.content.Intent import android.os.Bundle import androidx.activity.OnBackPressedCallback import androidx.activity.viewModels +import androidx.lifecycle.lifecycleScope import com.google.android.material.tabs.TabLayoutMediator import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.databinding.ActivityNotificationBinding import com.teameetmeet.meetmeet.presentation.base.BaseActivity import com.teameetmeet.meetmeet.presentation.home.HomeActivity +import com.teameetmeet.meetmeet.presentation.util.setMenuClickEvent import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -42,8 +44,8 @@ class NotificationActivity : binding.notificationMtb.setNavigationOnClickListener { navigateToPrev() } - binding.notificationMtb.setOnMenuItemClickListener { - when (it.itemId) { + binding.notificationMtb.setMenuClickEvent(lifecycleScope) { menuItemId -> + when (menuItemId) { R.id.menu_delete_notification_all -> { when (binding.notificationVp.currentItem) { TAB_INDEX_FOLLOW -> { @@ -59,7 +61,6 @@ class NotificationActivity : } } } - true } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationAdapter.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationAdapter.kt index 0002716..d10c667 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationAdapter.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationAdapter.kt @@ -1,25 +1,20 @@ package com.teameetmeet.meetmeet.presentation.notification.event -import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter import com.teameetmeet.meetmeet.data.network.entity.EventInvitationNotification -import com.teameetmeet.meetmeet.databinding.ItemEventNotificationBinding class EventNotificationAdapter(private val eventNotificationItemClickListener: EventNotificationItemClickListener) : ListAdapter(diffCallback) { override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): EventNotificationViewHolder { - val binding = ItemEventNotificationBinding.inflate( - LayoutInflater.from(parent.context), parent, false - ) - return EventNotificationViewHolder(binding) + return EventNotificationViewHolder.from(parent, eventNotificationItemClickListener) } override fun onBindViewHolder(holder: EventNotificationViewHolder, position: Int) { - holder.bind(getItem(position), eventNotificationItemClickListener) + holder.bind(getItem(position)) } override fun onViewRecycled(holder: EventNotificationViewHolder) { diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationViewHolder.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationViewHolder.kt index 54d9f63..8e62339 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationViewHolder.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/event/EventNotificationViewHolder.kt @@ -1,48 +1,78 @@ package com.teameetmeet.meetmeet.presentation.notification.event +import android.view.LayoutInflater +import android.view.ViewGroup import androidx.core.content.ContextCompat +import androidx.core.view.doOnAttach +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.data.model.UserStatus import com.teameetmeet.meetmeet.data.network.entity.EventInvitationNotification import com.teameetmeet.meetmeet.databinding.ItemEventNotificationBinding +import com.teameetmeet.meetmeet.presentation.util.setClickEvent -class EventNotificationViewHolder(private val binding: ItemEventNotificationBinding) : - RecyclerView.ViewHolder(binding.root) { +class EventNotificationViewHolder private constructor( + private val binding: ItemEventNotificationBinding, + private val eventNotificationItemClickListener: EventNotificationItemClickListener +) : RecyclerView.ViewHolder(binding.root) { - fun bind( - item: EventInvitationNotification, - eventNotificationItemClickListener: EventNotificationItemClickListener - ) { - binding.item = item - when (item.status) { - UserStatus.JOIN_STATUS_PENDING -> { - binding.swipeView.setBackgroundColor( - ContextCompat.getColor( - itemView.context, R.color.notification_highlight - ) - ) - } + init { + itemView.doOnAttach { + itemView.findViewTreeLifecycleOwner()?.let { lifecycleOwner -> + binding.item?.let { item -> + when (item.status) { + UserStatus.JOIN_STATUS_PENDING -> { + binding.swipeView.setBackgroundColor( + ContextCompat.getColor( + itemView.context, R.color.notification_highlight + ) + ) + } + + else -> { + binding.swipeView.setBackgroundColor( + ContextCompat.getColor( + itemView.context, R.color.grey3 + ) + ) + } + } - else -> { - binding.swipeView.setBackgroundColor( - ContextCompat.getColor( - itemView.context, R.color.grey3 - ) - ) + binding.swipeView.setClickEvent(lifecycleOwner.lifecycleScope) { + eventNotificationItemClickListener.onClick(item) + } + binding.tvRemove.setClickEvent(lifecycleOwner.lifecycleScope) { + eventNotificationItemClickListener.onDelete(item) + } + } } } + } - binding.swipeView.setOnClickListener { - eventNotificationItemClickListener.onClick(item) - } - binding.tvRemove.setOnClickListener { - eventNotificationItemClickListener.onDelete(item) - } + fun bind( + item: EventInvitationNotification, + ) { + binding.item = item } fun resetSwipeState() { itemView.animate().cancel() binding.swipeView.translationX = 0f } + + companion object { + fun from( + parent: ViewGroup, + eventNotificationItemClickListener: EventNotificationItemClickListener + ): EventNotificationViewHolder { + val inflater = LayoutInflater.from(parent.context) + return EventNotificationViewHolder( + ItemEventNotificationBinding.inflate( + inflater, parent, false + ), eventNotificationItemClickListener + ) + } + } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationAdapter.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationAdapter.kt index 9ebef0d..32e183b 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationAdapter.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationAdapter.kt @@ -11,11 +11,11 @@ class FollowNotificationAdapter(private val followNotificationItemClickListener: parent: ViewGroup, viewType: Int ): FollowNotificationViewHolder { - return FollowNotificationViewHolder.from(parent) + return FollowNotificationViewHolder.from(parent, followNotificationItemClickListener) } override fun onBindViewHolder(holder: FollowNotificationViewHolder, position: Int) { - holder.bind(getItem(position), followNotificationItemClickListener) + holder.bind(getItem(position)) } override fun onViewRecycled(holder: FollowNotificationViewHolder) { diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationViewHolder.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationViewHolder.kt index 5e09790..11f41f8 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationViewHolder.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/notification/follow/FollowNotificationViewHolder.kt @@ -2,21 +2,36 @@ package com.teameetmeet.meetmeet.presentation.notification.follow import android.view.LayoutInflater import android.view.ViewGroup +import androidx.core.view.doOnAttach +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.lifecycle.lifecycleScope import androidx.recyclerview.widget.RecyclerView import com.teameetmeet.meetmeet.data.network.entity.FollowNotification import com.teameetmeet.meetmeet.databinding.ItemFollowNotificationBinding +import com.teameetmeet.meetmeet.presentation.util.setClickEvent -class FollowNotificationViewHolder(private val binding: ItemFollowNotificationBinding) : +class FollowNotificationViewHolder private constructor( + private val binding: ItemFollowNotificationBinding, + private val followNotificationItemClickListener: FollowNotificationItemClickListener +) : RecyclerView.ViewHolder(binding.root) { + init { + itemView.doOnAttach { + itemView.findViewTreeLifecycleOwner()?.let { lifecycleOwner -> + binding.item?.let { item -> + binding.tvRemove.setClickEvent(lifecycleOwner.lifecycleScope) { + followNotificationItemClickListener.onDelete(item) + } + } + } + } + } + fun bind( item: FollowNotification, - followNotificationItemClickListener: FollowNotificationItemClickListener ) { binding.item = item - binding.tvRemove.setOnClickListener { - followNotificationItemClickListener.onDelete(item) - } } fun resetSwipeState() { @@ -25,14 +40,18 @@ class FollowNotificationViewHolder(private val binding: ItemFollowNotificationBi } companion object { - fun from(parent: ViewGroup): FollowNotificationViewHolder { + fun from( + parent: ViewGroup, + followNotificationItemClickListener: FollowNotificationItemClickListener + ): FollowNotificationViewHolder { val inflater = LayoutInflater.from(parent.context) return FollowNotificationViewHolder( ItemFollowNotificationBinding.inflate( inflater, parent, false - ) + ), + followNotificationItemClickListener ) } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/account/SettingAccountFragment.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/account/SettingAccountFragment.kt index b163db5..b332c5a 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/account/SettingAccountFragment.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/account/SettingAccountFragment.kt @@ -11,6 +11,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.databinding.FragmentSettingAccountBinding import com.teameetmeet.meetmeet.presentation.base.BaseFragment +import com.teameetmeet.meetmeet.presentation.util.setClickEvent import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -52,7 +53,7 @@ class SettingAccountFragment : } private fun setDialog() { - binding.settingAccountBtnAccountDelete.setOnClickListener { + binding.settingAccountBtnAccountDelete.setClickEvent(viewLifecycleOwner.lifecycleScope) { MaterialAlertDialogBuilder(requireActivity()) .setTitle(resources.getString(R.string.setting_account_delete_title)) .setIcon(R.drawable.ic_warning) @@ -74,7 +75,7 @@ class SettingAccountFragment : } private fun setNavigation() { - binding.settingAccountBtnPasswordChange.setOnClickListener { + binding.settingAccountBtnPasswordChange.setClickEvent(viewLifecycleOwner.lifecycleScope) { findNavController().navigate( SettingAccountFragmentDirections.actionSettingAccountFragmentToSettingPasswordChangeFragment() ) diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/home/SettingHomeFragment.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/home/SettingHomeFragment.kt index 3274291..0f1d7c3 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/home/SettingHomeFragment.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/setting/home/SettingHomeFragment.kt @@ -12,6 +12,7 @@ import androidx.navigation.fragment.findNavController import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.databinding.FragmentSettingHomeBinding import com.teameetmeet.meetmeet.presentation.base.BaseFragment +import com.teameetmeet.meetmeet.presentation.util.setClickEvent import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.launch @@ -39,17 +40,19 @@ class SettingHomeFragment : } private fun setNavigation() { - binding.settingHomeBtnAccountSetting.setOnClickListener { + binding.settingHomeBtnAccountSetting.setClickEvent(viewLifecycleOwner.lifecycleScope) { findNavController().navigate( SettingHomeFragmentDirections.actionSettingHomeFragmentToSettingAccountFragment() ) } - binding.settingHomeBtnProfileSetting.setOnClickListener { + + binding.settingHomeBtnProfileSetting.setClickEvent(viewLifecycleOwner.lifecycleScope) { findNavController().navigate( SettingHomeFragmentDirections.actionSettingHomeFragmentToSettingProfileFragment() ) } - binding.settingHomeBtnAlarmSetting.setOnClickListener { + + binding.settingHomeBtnAlarmSetting.setClickEvent(viewLifecycleOwner.lifecycleScope) { navigateToNotificationSetting() } } @@ -72,7 +75,10 @@ class SettingHomeFragment : viewModel.event.collect { event -> when (event) { is SettingHomeUiEvent.NavigateToLoginActivity -> navigateToLoginActivity() - is SettingHomeUiEvent.ShowMessage -> showMessage(event.messageId, event.extraMessage) + is SettingHomeUiEvent.ShowMessage -> showMessage( + event.messageId, + event.extraMessage + ) } } } diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/util/ClickEventUtil.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/util/ClickEventUtil.kt index 26e9e29..4a66540 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/util/ClickEventUtil.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/presentation/util/ClickEventUtil.kt @@ -1,6 +1,7 @@ package com.teameetmeet.meetmeet.presentation.util import android.view.View +import com.google.android.material.appbar.MaterialToolbar import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow @@ -18,6 +19,14 @@ fun View.clicks(): Flow = callbackFlow { awaitClose { setOnClickListener(null) } } +fun MaterialToolbar.menuClicks(): Flow = callbackFlow { + setOnMenuItemClickListener { menuItem -> + this.trySend(menuItem.itemId) + true + } + awaitClose { setOnMenuItemClickListener(null) } +} + fun Flow.throttleFirst(windowDuration: Long): Flow = flow { var lastEmissionTime = 0L collect { upstream -> @@ -38,4 +47,15 @@ fun View.setClickEvent( .throttleFirst(windowDuration) .onEach { onClick.invoke() } .launchIn(uiScope) +} + +fun MaterialToolbar.setMenuClickEvent( + uiScope: CoroutineScope, + windowDuration: Long = THROTTLE_DURATION, + onMenuClick: (menuId: Int) -> Unit, +) { + menuClicks() + .throttleFirst(windowDuration) + .onEach { onMenuClick.invoke(it) } + .launchIn(uiScope) } \ No newline at end of file diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmHelper.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmHelper.kt index 8bb948b..03a8d50 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmHelper.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmHelper.kt @@ -8,8 +8,6 @@ import android.os.SystemClock import com.teameetmeet.meetmeet.R import com.teameetmeet.meetmeet.data.datasource.LocalCalendarDataSource import com.teameetmeet.meetmeet.service.INTENT_REQUEST_ID_ALARM_UPDATE -import com.teameetmeet.meetmeet.service.INTENT_REQUEST_ID_EVENT_INVITATION_ACCEPT_ACTION -import com.teameetmeet.meetmeet.service.INTENT_REQUEST_ID_EVENT_INVITATION_REJECT_ACTION import com.teameetmeet.meetmeet.service.alarm.model.EventAlarm import com.teameetmeet.meetmeet.service.messaging.model.EventInvitationMessage import com.teameetmeet.meetmeet.util.date.DateTimeFormat @@ -160,21 +158,18 @@ class AlarmHelper @Inject constructor( accept: Boolean ): PendingIntent { val actionIntent = Intent(context, AlarmReceiver::class.java).apply { - action = INTENT_ACTION_ACCEPT_INVITE_EVENT + action = if (accept) { + INTENT_ACTION_ACCEPT_INVITE_EVENT + } else { + INTENT_ACTION_REJECT_INVITE_EVENT + } putExtra(INTENT_EXTRA_INVITE_ID, eventInviteMessage.inviteId) putExtra(INTENT_EXTRA_EVENT_ID, eventInviteMessage.eventId) - putExtra(INTENT_EXTRA_ACCEPT, accept) - } - - val requestId = if (accept) { - INTENT_REQUEST_ID_EVENT_INVITATION_ACCEPT_ACTION - } else { - INTENT_REQUEST_ID_EVENT_INVITATION_REJECT_ACTION } return PendingIntent.getBroadcast( context, - requestId, + eventInviteMessage.eventId, actionIntent, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) @@ -186,12 +181,12 @@ class AlarmHelper @Inject constructor( const val INTENT_ACTION_ALARM_UPDATE = "intentActionAlarmUpdate" const val INTENT_ACTION_ACCEPT_INVITE_EVENT = "intentActionAcceptInviteEvent" + const val INTENT_ACTION_REJECT_INVITE_EVENT = "intentActionRejectInviteEvent" const val INTENT_EXTRA_TITLE = "intentExtraTitle" const val INTENT_EXTRA_INVITE_ID = "intentExtraInviteId" const val INTENT_EXTRA_EVENT_ID = "intentExtraEventId" const val INTENT_EXTRA_CONTENT = "intentExtraContent" - const val INTENT_EXTRA_ACCEPT = "intentExtraAccept" const val UPDATE_DAY_UNIT = 8L const val LAST_DATE = "2040-01-01" diff --git a/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmReceiver.kt b/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmReceiver.kt index fd8d120..95188e2 100644 --- a/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmReceiver.kt +++ b/android/app/src/main/java/com/teameetmeet/meetmeet/service/alarm/AlarmReceiver.kt @@ -48,12 +48,23 @@ class AlarmReceiver : BroadcastReceiver() { } AlarmHelper.INTENT_ACTION_ACCEPT_INVITE_EVENT -> { - val accept = intent.getBooleanExtra(AlarmHelper.INTENT_EXTRA_ACCEPT, false) val inviteId = intent.getIntExtra(AlarmHelper.INTENT_EXTRA_INVITE_ID, 0) val eventId = intent.getIntExtra(AlarmHelper.INTENT_EXTRA_EVENT_ID, 0) CoroutineScope(Dispatchers.IO).launch { - eventStoryRepository.acceptEventInvite(accept, inviteId, eventId).first() + eventStoryRepository.acceptEventInvite(true, inviteId, eventId).first() + } + + NotificationManagerCompat.from(context).cancel(eventId) + notificationHelper.emitActiveNotificationCount() + } + + AlarmHelper.INTENT_ACTION_REJECT_INVITE_EVENT -> { + val inviteId = intent.getIntExtra(AlarmHelper.INTENT_EXTRA_INVITE_ID, 0) + val eventId = intent.getIntExtra(AlarmHelper.INTENT_EXTRA_EVENT_ID, 0) + + CoroutineScope(Dispatchers.IO).launch { + eventStoryRepository.acceptEventInvite(false, inviteId, eventId).first() } NotificationManagerCompat.from(context).cancel(eventId)