From bfc435c350cbaa73892caa622bfe6cff7029da47 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 4 Feb 2025 11:23:28 +0100 Subject: [PATCH] Ask user confirmation for cancelling meeting if it us the organizer, to delete it if it's only a participant --- .../fragment/ConversationsListFragment.kt | 2 + .../main/meetings/fragment/MeetingFragment.kt | 41 ++++++- .../meetings/fragment/MeetingsListFragment.kt | 53 +++++++-- .../fragment/MeetingsMenuDialogFragment.kt | 2 + .../viewmodel/MeetingWaitingRoomViewModel.kt | 8 ++ .../java/org/linphone/utils/DialogUtils.kt | 17 +++ .../main/res/layout/dialog_cancel_meeting.xml | 2 +- .../main/res/layout/dialog_delete_meeting.xml | 103 ++++++++++++++++++ .../main/res/layout/meeting_popup_menu.xml | 5 +- .../layout/meetings_list_long_press_menu.xml | 5 +- app/src/main/res/values-fr/strings.xml | 6 +- app/src/main/res/values/strings.xml | 6 +- 12 files changed, 228 insertions(+), 22 deletions(-) create mode 100644 app/src/main/res/layout/dialog_delete_meeting.xml diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt index 8fa661c00..ce968857d 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt @@ -214,6 +214,8 @@ class ConversationsListFragment : AbstractMainFragment() { uri ) findNavController().navigate(action) + } else { + Log.e("$TAG Failed to navigate to meeting waiting room, wrong current destination (expected conversationsListFragment but was something else)") } } } diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt index e254da21f..12a7bc163 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt @@ -198,7 +198,7 @@ class MeetingFragment : SlidingPaneChildFragment() { viewModel.conferenceCancelledEvent.observe(viewLifecycleOwner) { it.consume { - Log.i("$TAG Meeting has been cancelled successfully, deleting it") + Log.i("$TAG Meeting has been cancelled successfully") (requireActivity() as GenericActivity).showGreenToast( getString(R.string.meeting_info_cancelled_toast), R.drawable.trash_simple @@ -222,11 +222,15 @@ class MeetingFragment : SlidingPaneChildFragment() { true ) + val isUserOrganizer = viewModel.isEditable.value == true && viewModel.isCancelled.value == false + popupView.cancelInsteadOfDelete = isUserOrganizer popupView.setDeleteClickListener { - if (viewModel.isEditable.value == true) { + if (isUserOrganizer) { + // In case we are organizer of the meeting, ask user confirmation before cancelling it showCancelMeetingDialog() } else { - viewModel.delete() + // If we're not organizer, ask user confirmation of removing itself from participants & deleting it locally + showDeleteMeetingDialog() } popupWindow.dismiss() } @@ -283,8 +287,7 @@ class MeetingFragment : SlidingPaneChildFragment() { } private fun showCancelMeetingDialog() { - Log.i("$TAG Meeting is editable, asking whether to cancel it or not before deleting it") - + Log.i("$TAG Meeting is editable, asking whether to cancel it or not") val model = ConfirmationDialogModel() val dialog = DialogUtils.getCancelMeetingDialog(requireContext(), model) @@ -296,7 +299,6 @@ class MeetingFragment : SlidingPaneChildFragment() { model.cancelEvent.observe(viewLifecycleOwner) { it.consume { - viewModel.delete() dialog.dismiss() } } @@ -310,4 +312,31 @@ class MeetingFragment : SlidingPaneChildFragment() { dialog.show() } + + private fun showDeleteMeetingDialog() { + Log.i("$TAG Meeting is not editable or already cancelled, asking whether to delete it or not") + val model = ConfirmationDialogModel() + val dialog = DialogUtils.getDeleteMeetingDialog(requireContext(), model) + + model.dismissEvent.observe(viewLifecycleOwner) { + it.consume { + dialog.dismiss() + } + } + + model.cancelEvent.observe(viewLifecycleOwner) { + it.consume { + dialog.dismiss() + } + } + + model.confirmEvent.observe(viewLifecycleOwner) { + it.consume { + viewModel.delete() + dialog.dismiss() + } + } + + dialog.show() + } } diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt index f93c2a4f2..615df6227 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt @@ -177,6 +177,7 @@ class MeetingsListFragment : AbstractMainFragment() { meetingViewModelBeingCancelled?.delete() meetingViewModelBeingCancelled = null listViewModel.applyFilter() + (requireActivity() as GenericActivity).showGreenToast( getString(R.string.meeting_info_deleted_toast), R.drawable.trash_simple @@ -186,22 +187,25 @@ class MeetingsListFragment : AbstractMainFragment() { adapter.meetingLongClickedEvent.observe(viewLifecycleOwner) { it.consume { model -> + val isUserOrganizer = model.isOrganizer() && !model.isCancelled val modalBottomSheet = MeetingsMenuDialogFragment( + isUserOrganizer, { // onDismiss adapter.resetSelection() }, { // onDelete - if (model.isOrganizer() && !model.isCancelled) { + if (isUserOrganizer) { showCancelMeetingDialog(model) } else { - Log.i("$TAG Deleting meeting [${model.id}]") + showDeleteMeetingDialog(model) + /*Log.i("$TAG Deleting meeting [${model.id}]") model.delete() listViewModel.applyFilter() (requireActivity() as GenericActivity).showGreenToast( getString(R.string.meeting_info_deleted_toast), R.drawable.trash_simple - ) + )*/ } } ) @@ -326,15 +330,7 @@ class MeetingsListFragment : AbstractMainFragment() { model.cancelEvent.observe(viewLifecycleOwner) { it.consume { - Log.i("$TAG Deleting meeting [${meetingModel.id}]") - meetingModel.delete() - listViewModel.applyFilter() - dialog.dismiss() - (requireActivity() as GenericActivity).showGreenToast( - getString(R.string.meeting_info_deleted_toast), - R.drawable.trash_simple - ) } } @@ -349,4 +345,39 @@ class MeetingsListFragment : AbstractMainFragment() { dialog.show() } + + private fun showDeleteMeetingDialog(meetingModel: MeetingModel) { + Log.i("$TAG Meeting is not editable or already cancelled, asking whether to deleting it or not") + + val model = ConfirmationDialogModel() + val dialog = DialogUtils.getDeleteMeetingDialog(requireContext(), model) + + model.dismissEvent.observe(viewLifecycleOwner) { + it.consume { + dialog.dismiss() + } + } + + model.cancelEvent.observe(viewLifecycleOwner) { + it.consume { + dialog.dismiss() + } + } + + model.confirmEvent.observe(viewLifecycleOwner) { + it.consume { + Log.i("$TAG Deleting meeting [${meetingModel.id}]") + meetingModel.delete() + listViewModel.applyFilter() + + dialog.dismiss() + (requireActivity() as GenericActivity).showGreenToast( + getString(R.string.meeting_info_deleted_toast), + R.drawable.trash_simple + ) + } + } + + dialog.show() + } } diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsMenuDialogFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsMenuDialogFragment.kt index 7bd7b72fc..e5529097b 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsMenuDialogFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsMenuDialogFragment.kt @@ -33,6 +33,7 @@ import org.linphone.databinding.MeetingsListLongPressMenuBinding @UiThread class MeetingsMenuDialogFragment( + private val isUserOrganizer: Boolean, private val onDismiss: (() -> Unit)? = null, private val onDeleteMeeting: (() -> Unit)? = null ) : BottomSheetDialogFragment() { @@ -64,6 +65,7 @@ class MeetingsMenuDialogFragment( savedInstanceState: Bundle? ): View { val view = MeetingsListLongPressMenuBinding.inflate(layoutInflater) + view.cancelInsteadOfDelete = isUserOrganizer view.setDeleteClickListener { onDeleteMeeting?.invoke() diff --git a/app/src/main/java/org/linphone/ui/main/meetings/viewmodel/MeetingWaitingRoomViewModel.kt b/app/src/main/java/org/linphone/ui/main/meetings/viewmodel/MeetingWaitingRoomViewModel.kt index 92d612156..155cbaa04 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/viewmodel/MeetingWaitingRoomViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/viewmodel/MeetingWaitingRoomViewModel.kt @@ -190,6 +190,14 @@ class MeetingWaitingRoomViewModel conferenceInfoFoundEvent.postValue(Event(true)) } else { Log.e("$TAG Conference info with SIP URI [$uri] couldn't be found!") + showRedToastEvent.postValue( + Event( + Pair( + R.string.meeting_info_not_found_toast, + R.drawable.warning_circle + ) + ) + ) conferenceInfoFoundEvent.postValue(Event(false)) } } else { diff --git a/app/src/main/java/org/linphone/utils/DialogUtils.kt b/app/src/main/java/org/linphone/utils/DialogUtils.kt index 4dc0843cb..e41ae3264 100644 --- a/app/src/main/java/org/linphone/utils/DialogUtils.kt +++ b/app/src/main/java/org/linphone/utils/DialogUtils.kt @@ -43,6 +43,7 @@ import org.linphone.databinding.DialogConfirmTurningOnVfsBinding import org.linphone.databinding.DialogContactConfirmTrustCallBinding import org.linphone.databinding.DialogContactTrustProcessBinding import org.linphone.databinding.DialogDeleteContactBinding +import org.linphone.databinding.DialogDeleteMeetingBinding import org.linphone.databinding.DialogKickFromConferenceBinding import org.linphone.databinding.DialogManageAccountInternationalPrefixHelpBinding import org.linphone.databinding.DialogMergeCallsIntoConferenceBinding @@ -513,6 +514,22 @@ class DialogUtils { return getDialog(context, binding) } + @UiThread + fun getDeleteMeetingDialog( + context: Context, + viewModel: ConfirmationDialogModel + ): Dialog { + val binding: DialogDeleteMeetingBinding = DataBindingUtil.inflate( + LayoutInflater.from(context), + R.layout.dialog_delete_meeting, + null, + false + ) + binding.viewModel = viewModel + + return getDialog(context, binding) + } + @UiThread private fun getDialog(context: Context, binding: ViewDataBinding): Dialog { val dialog = Dialog(context, R.style.Theme_LinphoneDialog) diff --git a/app/src/main/res/layout/dialog_cancel_meeting.xml b/app/src/main/res/layout/dialog_cancel_meeting.xml index 326e2cfe6..289c90956 100644 --- a/app/src/main/res/layout/dialog_cancel_meeting.xml +++ b/app/src/main/res/layout/dialog_cancel_meeting.xml @@ -68,7 +68,7 @@ android:layout_marginTop="32dp" android:layout_marginStart="15dp" android:layout_marginEnd="15dp" - android:text="@string/dialog_no" + android:text= "@string/dialog_no" app:layout_constraintStart_toStartOf="@id/dialog_background" app:layout_constraintEnd_toEndOf="@id/dialog_background" app:layout_constraintTop_toBottomOf="@id/message" diff --git a/app/src/main/res/layout/dialog_delete_meeting.xml b/app/src/main/res/layout/dialog_delete_meeting.xml new file mode 100644 index 000000000..3ea8a9076 --- /dev/null +++ b/app/src/main/res/layout/dialog_delete_meeting.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/meeting_popup_menu.xml b/app/src/main/res/layout/meeting_popup_menu.xml index 82454e676..d94aaa109 100644 --- a/app/src/main/res/layout/meeting_popup_menu.xml +++ b/app/src/main/res/layout/meeting_popup_menu.xml @@ -11,6 +11,9 @@ + + Envoyer l\'invitation par message aux participants Rejoindre la réunion Organisateur - Supprimer la réunion Ajouter dans le calendrier Réunion supprimée + Réunion introuvable ! Description Modifier la réunion Annuler la réunion? Voulez-vous annuler la réunion et envoyer une notification aux participants ? + Annuler la réunion + Supprimer la réunion ? + Voulez-vous supprimer la réunion ? + Supprimer la réunion Réunion créée Réunion mise à jour Réunion annulée diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7d3cad640..d7ea62242 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -613,13 +613,17 @@ Send invitation to participants Join the meeting now Organizer - Delete meeting Create calendar event Meeting has been deleted + Meeting cannot be found! Description Edit meeting Cancel the meeting? Do you want to cancel the meeting and send a notification to all participants? + Cancel meeting + Delete the meeting? + Do you want to delete the meeting? + Delete meeting Meeting has been created Meeting has been updated Meeting has been cancelled