Improved meeting room fragment, added cancel button

This commit is contained in:
Sylvain Berfini 2024-04-15 12:03:00 +02:00
parent b0a05b5905
commit 3e845b32b6
18 changed files with 143 additions and 30 deletions

View file

@ -88,7 +88,10 @@ class SingleSignOnFragment : Fragment() {
viewModel.onErrorEvent.observe(viewLifecycleOwner) {
it.consume { errorMessage ->
(requireActivity() as AssistantActivity).showRedToast(errorMessage, R.drawable.x)
(requireActivity() as AssistantActivity).showRedToast(
errorMessage,
R.drawable.warning_circle
)
findNavController().popBackStack()
}
}

View file

@ -355,7 +355,7 @@ class ActiveCallFragment : GenericCallFragment() {
it.consume { error ->
(requireActivity() as CallActivity).showRedToast(
error,
R.drawable.x
R.drawable.warning_circle
)
}
}

View file

@ -264,7 +264,10 @@ class ConversationFragment : GenericCallFragment() {
Log.e("$TAG Failed to find conversation, going back")
findNavController().popBackStack()
val message = getString(R.string.toast_cant_find_conversation_to_display)
(requireActivity() as CallActivity).showRedToast(message, R.drawable.x)
(requireActivity() as CallActivity).showRedToast(
message,
R.drawable.warning_circle
)
}
} else {
sendMessageViewModel.configureChatRoom(viewModel.chatRoom)

View file

@ -379,7 +379,10 @@ class ConversationFragment : SlidingPaneChildFragment() {
Log.e("$TAG Failed to find conversation, going back")
goBack()
val message = getString(R.string.toast_cant_find_conversation_to_display)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(
message,
R.drawable.warning_circle
)
}
} else {
sendMessageViewModel.configureChatRoom(viewModel.chatRoom)

View file

@ -116,7 +116,10 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
Log.e("$TAG Failed to find conversation, going back")
goBack()
val message = getString(R.string.toast_cant_find_conversation_to_display)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(
message,
R.drawable.warning_circle
)
}
}
}
@ -258,7 +261,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
} else {
Log.e("$TAG Can't go to contact page, friend ref key is null or empty!")
val message = getString(R.string.toast_cant_find_contact_to_display)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.warning_circle)
}
}
@ -272,7 +275,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
} else {
Log.e("$TAG Can't add empty/null SIP URI to contacts!")
val message = getString(R.string.toast_no_address_to_add_to_contact)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.warning_circle)
}
}
@ -337,7 +340,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
} else {
Log.e("$TAG Can't go to contact page, friend ref key is null or empty!")
val message = getString(R.string.toast_cant_find_contact_to_display)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.warning_circle)
}
popupWindow.dismiss()
}
@ -352,7 +355,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
} else {
Log.e("$TAG Can't add empty/null SIP URI to contacts!")
val message = getString(R.string.toast_no_address_to_add_to_contact)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.warning_circle)
}
popupWindow.dismiss()
}

View file

@ -95,7 +95,7 @@ class EventModel @WorkerThread constructor(private val eventLog: EventLog) {
R.drawable.clock_countdown
}
EventLog.Type.ConferenceTerminated -> {
R.drawable.x
R.drawable.warning_circle
}
EventLog.Type.ConferenceSubjectChanged -> {
R.drawable.pencil_simple

View file

@ -403,7 +403,7 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
val message = AppUtils.getString(
R.string.toast_failed_to_add_participant_to_group_conversation
)
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
showRedToastEvent.postValue(Event(Pair(message, R.drawable.warning_circle)))
}
}
}

View file

@ -520,7 +520,7 @@ class SendMessageInConversationViewModel @UiThread constructor() : ViewModel() {
val message = AppUtils.getString(
R.string.toast_voice_recording_max_duration_reached
)
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
showRedToastEvent.postValue(Event(Pair(message, R.drawable.warning_circle)))
}
}
}.launchIn(viewModelScope)

View file

@ -188,7 +188,10 @@ class MediaListViewerFragment : GenericFragment() {
val message = AppUtils.getString(
R.string.toast_export_file_to_media_store_error
)
(requireActivity() as MainActivity).showRedToast(message, R.drawable.x)
(requireActivity() as MainActivity).showRedToast(
message,
R.drawable.warning_circle
)
}
}
}

View file

@ -221,7 +221,7 @@ class FileViewModel @UiThread constructor() : ViewModel() {
val message = AppUtils.getString(
R.string.toast_export_file_to_documents_error
)
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
showRedToastEvent.postValue(Event(Pair(message, R.drawable.warning_circle)))
}
}
}
@ -246,7 +246,7 @@ class FileViewModel @UiThread constructor() : ViewModel() {
val message = AppUtils.getString(
R.string.toast_export_file_to_documents_error
)
showRedToastEvent.postValue(Event(Pair(message, R.drawable.x)))
showRedToastEvent.postValue(Event(Pair(message, R.drawable.warning_circle)))
}
}
}

View file

@ -126,9 +126,9 @@ class MeetingWaitingRoomFragment : GenericFragment() {
}
}
viewModel.conferenceCreatedEvent.observe(viewLifecycleOwner) {
viewModel.leaveWaitingRoomEvent.observe(viewLifecycleOwner) {
it.consume {
Log.i("$TAG Conference was joined, leaving waiting room")
Log.i("$TAG Leaving waiting room")
goBack()
}
}
@ -137,9 +137,9 @@ class MeetingWaitingRoomFragment : GenericFragment() {
it.consume {
Log.e("$TAG Error joining the conference!")
val message = getString(
R.string.toast_no_app_registered_to_handle_content_type_error
R.string.toast_failed_to_join_conference
)
val icon = R.drawable.x
val icon = R.drawable.warning_circle
(requireActivity() as MainActivity).showRedToast(message, icon)
}
}
@ -169,6 +169,7 @@ class MeetingWaitingRoomFragment : GenericFragment() {
override fun onPause() {
bottomSheetDialog?.dismiss()
bottomSheetDialog = null
viewModel.joining.value = false
coreContext.postOnCoreThread { core ->
core.nativePreviewWindowId = null

View file

@ -29,7 +29,9 @@ import androidx.lifecycle.ViewModel
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.core.Address
import org.linphone.core.AudioDevice
import org.linphone.core.Call
import org.linphone.core.Conference
import org.linphone.core.ConferenceInfo
import org.linphone.core.Core
@ -78,7 +80,7 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
MutableLiveData<Event<ArrayList<AudioDeviceModel>>>()
}
val conferenceCreatedEvent: MutableLiveData<Event<Boolean>> by lazy {
val leaveWaitingRoomEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
@ -86,6 +88,7 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
MutableLiveData<Event<Boolean>>()
}
private lateinit var conferenceAddress: Address
private lateinit var conferenceInfo: ConferenceInfo
private lateinit var selectedOutputAudioDevice: AudioDevice
@ -95,18 +98,48 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
private var bluetoothAudioDevice: AudioDevice? = null
private val coreListener = object : CoreListenerStub() {
@WorkerThread
override fun onCallStateChanged(
core: Core,
call: Call,
state: Call.State?,
message: String
) {
if (::conferenceAddress.isInitialized && conferenceAddress.weakEqual(call.remoteAddress)) {
when (state) {
Call.State.End -> {
Log.i("$TAG Call has ended, leaving waiting room fragment")
leaveWaitingRoomEvent.postValue(Event(true))
}
Call.State.Error -> {
Log.w("$TAG Call has failed, leaving waiting room fragment")
leaveWaitingRoomEvent.postValue(Event(true))
}
else -> {}
}
}
}
@WorkerThread
override fun onConferenceStateChanged(
core: Core,
conference: Conference,
state: Conference.State?
) {
Log.i("$TAG Conference state changed: [$state]")
if (conference.state == Conference.State.Created) {
conferenceCreatedEvent.postValue(Event(true))
joining.postValue(false)
} else if (conference.state == Conference.State.CreationFailed) {
conferenceCreationError.postValue(Event(true))
joining.postValue(false)
val remoteAddress = conference.conferenceAddress
if (::conferenceAddress.isInitialized && remoteAddress != null && conferenceAddress.weakEqual(
remoteAddress
)
) {
Log.i("$TAG Conference state changed: [$state]")
if (conference.state == Conference.State.Created) {
leaveWaitingRoomEvent.postValue(Event(true))
} else if (conference.state == Conference.State.CreationFailed) {
conferenceCreationError.postValue(Event(true))
joining.postValue(false)
}
}
}
}
@ -144,6 +177,7 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
coreContext.postOnCoreThread { core ->
val address = Factory.instance().createAddress(uri)
if (address != null) {
conferenceAddress = address
val found = core.findConferenceInformationFromUri(address)
if (found != null) {
Log.i("$TAG Conference info with SIP URI [$uri] was found")
@ -211,6 +245,27 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
}
}
@UiThread
fun cancel() {
coreContext.postOnCoreThread { core ->
if (::conferenceAddress.isInitialized) {
val found = core.calls.find {
it.remoteAddress.weakEqual(conferenceAddress)
}
if (found != null) {
coreContext.terminateCall(found)
} else {
Log.e(
"$TAG No call found matching conference address [${conferenceAddress.asStringUriOnly()}]"
)
}
} else {
Log.e("$TAG No conference address stored!")
}
}
}
@UiThread
fun switchCamera() {
coreContext.postOnCoreThread {

View file

@ -79,7 +79,7 @@ class CardDavViewModel : ViewModel() {
}
FriendList.SyncStatus.Failure -> {
syncInProgress.postValue(false)
val icon = R.drawable.x
val icon = R.drawable.warning_circle
showErrorToastEvent.postValue(Event(Pair(icon, message.orEmpty())))
if (isEdit.value == false) {
Log.e("$TAG Synchronization failed, removing Friend list from Core")
@ -148,7 +148,9 @@ class CardDavViewModel : ViewModel() {
val server = serverUrl.value.orEmpty().trim()
if (name.isEmpty() || server.isEmpty()) {
// TODO: improve toast
showErrorToastEvent.postValue(Event(Pair(R.drawable.x, "Name or Server is empty!")))
showErrorToastEvent.postValue(
Event(Pair(R.drawable.warning_circle, "Name or Server is empty!"))
)
return
}

View file

@ -173,7 +173,7 @@ class LdapViewModel : ViewModel() {
Log.e("$TAG Exception while creating LDAP: $e")
// TODO: improve toast
showErrorToastEvent.postValue(
Event(Pair(R.drawable.x, e.toString()))
Event(Pair(R.drawable.warning_circle, e.toString()))
)
}
}

View file

@ -244,6 +244,24 @@
app:layout_constraintTop_toBottomOf="@id/joining_subtitle"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/primary_button_label_style"
android:id="@+id/cancel"
android:onClick="@{() -> viewModel.cancel()}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@string/meeting_waiting_room_cancel"
app:layout_constraintWidth_max="@dimen/button_max_width"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -240,6 +240,24 @@
app:layout_constraintTop_toBottomOf="@id/joining_subtitle"
app:layout_constraintBottom_toBottomOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/primary_button_label_style"
android:id="@+id/cancel"
android:onClick="@{() -> viewModel.cancel()}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="@dimen/screen_bottom_margin"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text="@string/meeting_waiting_room_cancel"
app:layout_constraintWidth_max="@dimen/button_max_width"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -102,6 +102,7 @@
<string name="toast_call_transfer_in_progress">Appel en cours de transfert</string>
<string name="toast_call_transfer_successful">L\'appel a été transferré</string>
<string name="toast_call_transfer_failed">Le transfert a échoué !</string>
<string name="toast_failed_to_join_conference">Echec lors de la connexion à la conférence!</string>
<string name="toast_remote_provisioning_config_applied">Configuration appliquée avec succès</string>
<string name="toast_remote_provisioning_config_failed">Erreur durant la récupération ou l\'application de la configuration</string>
@ -499,6 +500,7 @@
<string name="meeting_info_cancelled_toast">La réunion a été annulée</string>
<string name="meeting_waiting_room_join">Rejoindre</string>
<string name="meeting_waiting_room_cancel">Annuler</string>
<string name="meeting_waiting_room_joining_title">Connexion à la réunion</string>
<string name="meeting_waiting_room_joining_subtitle">Vous allez rejoindre la réunion dans quelques instants…</string>

View file

@ -137,6 +137,7 @@
<string name="toast_call_transfer_in_progress">Call is being transferred</string>
<string name="toast_call_transfer_successful">Call has been successfully transferred</string>
<string name="toast_call_transfer_failed">Call transfer failed!</string>
<string name="toast_failed_to_join_conference">Failed to join conference!</string>
<string name="toast_remote_provisioning_config_applied">Configuration successfully applied</string>
<string name="toast_remote_provisioning_config_failed">Error while trying to download and apply remote configuration</string>
@ -535,6 +536,7 @@
<string name="meeting_info_cancelled_toast">Meeting has been cancelled</string>
<string name="meeting_waiting_room_join">Join</string>
<string name="meeting_waiting_room_cancel">Cancel</string>
<string name="meeting_waiting_room_joining_title">Connection in progress</string>
<string name="meeting_waiting_room_joining_subtitle">You\'ll be joining in a short moment</string>