More UI work on conference related screens

This commit is contained in:
Sylvain Berfini 2023-10-27 15:14:05 +02:00
parent aa52f3d2b5
commit 48baed897c
6 changed files with 123 additions and 39 deletions

View file

@ -19,6 +19,9 @@
*/
package org.linphone.ui.call.fragment
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.os.Bundle
import android.os.SystemClock
import android.view.LayoutInflater
@ -27,9 +30,11 @@ import android.view.ViewGroup
import androidx.lifecycle.ViewModelProvider
import com.google.android.material.bottomsheet.BottomSheetBehavior
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.core.tools.Log
import org.linphone.databinding.CallActiveConferenceFragmentBinding
import org.linphone.ui.call.viewmodel.CallsViewModel
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
import org.linphone.utils.Event
class ActiveConferenceCallFragment : GenericCallFragment() {
companion object {
@ -87,6 +92,11 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
}
}
callViewModel.fullScreenMode.observe(viewLifecycleOwner) { hide ->
Log.i("$TAG Switching full screen mode to ${if (hide) "ON" else "OFF"}")
sharedViewModel.toggleFullScreenEvent.value = Event(hide)
}
actionsBottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
when (newState) {
@ -102,6 +112,17 @@ class ActiveConferenceCallFragment : GenericCallFragment() {
override fun onSlide(bottomSheet: View, slideOffset: Float) {}
})
binding.setShareConferenceClickListener {
val sipUri = callViewModel.conferenceModel.sipUri.value.orEmpty()
if (sipUri.isNotEmpty()) {
Log.i("$TAG Sharing conference SIP URI [$sipUri]")
val clipboard = requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val label = "Conference SIP address"
clipboard.setPrimaryClip(ClipData.newPlainText(label, sipUri))
}
}
}
override fun onResume() {

View file

@ -35,10 +35,14 @@ class ConferenceModel {
val subject = MutableLiveData<String>()
val sipUri = MutableLiveData<String>()
val participantDevices = MutableLiveData<ArrayList<ConferenceParticipantDeviceModel>>()
private lateinit var conference: Conference
val isCurrentCallInConference = MutableLiveData<Boolean>()
private val conferenceListener = object : ConferenceListenerStub() {
@WorkerThread
override fun onParticipantDeviceAdded(
@ -103,6 +107,7 @@ class ConferenceModel {
@WorkerThread
fun destroy() {
isCurrentCallInConference.postValue(false)
if (::conference.isInitialized) {
conference.removeListener(conferenceListener)
participantDevices.value.orEmpty().forEach(ConferenceParticipantDeviceModel::destroy)
@ -116,12 +121,14 @@ class ConferenceModel {
conference.removeListener(conferenceListener)
}
isCurrentCallInConference.postValue(true)
conference = conf
conference.addListener(conferenceListener)
Log.i(
"$TAG Configuring conference with subject [${conference.subject}] from call [${call.callLog.callId}]"
)
sipUri.postValue(conference.conferenceAddress.asStringUriOnly())
subject.postValue(conference.subject)
if (conference.state == Conference.State.Created) {

View file

@ -236,10 +236,14 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
fullScreenMode.postValue(false)
}
if (call.state == Call.State.Connected && call.conference != null) {
Log.i("$TAG Call is in Connected state and conference isn't null")
conferenceModel.configureFromCall(call)
goToConferenceEvent.postValue(Event(true))
if (call.state == Call.State.Connected) {
if (call.conference != null) {
Log.i("$TAG Call is in Connected state and conference isn't null")
conferenceModel.configureFromCall(call)
goToConferenceEvent.postValue(Event(true))
} else {
conferenceModel.destroy()
}
}
}
@ -740,6 +744,8 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
if (call.conference != null) {
conferenceModel.configureFromCall(call)
goToConferenceEvent.postValue(Event(true))
} else {
conferenceModel.destroy()
}
if (call.dir == Call.Dir.Incoming) {

View file

@ -43,10 +43,10 @@
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginTop="10dp"
android:layout_marginTop="@dimen/call_top_bar_info_height"
android:layout_marginBottom="@dimen/call_main_actions_menu_height"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.GONE : View.VISIBLE, default=gone}"
app:layout_constraintTop_toBottomOf="@id/call_direction_label"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 || viewModel.pipMode ? View.GONE : View.VISIBLE}"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
@ -54,13 +54,16 @@
<androidx.appcompat.widget.AppCompatTextView
style="@style/default_text_style_300"
android:id="@+id/waiting_for_others"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:layout_marginStart="5dp"
android:layout_marginEnd="5dp"
android:text="@string/conference_call_empty"
android:textColor="@color/white"
android:textSize="22sp"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.GONE : View.VISIBLE, default=gone}"
android:gravity="center"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.GONE : View.VISIBLE}"
app:layout_constraintTop_toTopOf="@id/background"
app:layout_constraintBottom_toBottomOf="@id/background"
app:layout_constraintStart_toStartOf="parent"
@ -81,7 +84,7 @@
android:text="@string/conference_share_link_title"
android:textSize="18sp"
android:textColor="@color/gray_main2_400"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.GONE : View.VISIBLE, default=gone}"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 || viewModel.pipMode ? View.GONE : View.VISIBLE}"
android:drawableStart="@drawable/share_network"
android:drawablePadding="8dp"
app:drawableTint="@color/gray_main2_400"
@ -93,15 +96,13 @@
android:id="@+id/grid_box_layout"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="4dp"
android:layout_marginEnd="4dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="@dimen/call_main_actions_menu_height"
android:layout_marginBottom="@{viewModel.fullScreenMode || viewModel.pipMode ? @dimen/zero : @dimen/call_main_actions_menu_height, default=@dimen/call_main_actions_menu_height}"
android:layout_marginTop="@{viewModel.fullScreenMode || viewModel.pipMode ? @dimen/zero : @dimen/call_top_bar_info_height, default=@dimen/call_top_bar_info_height}"
android:onClick="@{() -> viewModel.toggleFullScreen()}"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.VISIBLE : View.GONE}"
android:visibility="@{conferenceViewModel.participantDevices.size() > 1 ? View.VISIBLE : View.GONE, default=gone}"
entries="@{conferenceViewModel.participantDevices}"
layout="@{@layout/call_conference_grid_cell}"
app:layout_constraintTop_toBottomOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
@ -111,29 +112,31 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="@{viewModel.fullScreenMode || viewModel.pipMode ? View.INVISIBLE : View.VISIBLE}"
app:constraint_referenced_ids="call_direction_icon, call_direction_label, separator, chronometer" />
app:constraint_referenced_ids="conference_icon, conference_subject, separator, chronometer" />
<ImageView
android:id="@+id/call_direction_icon"
android:id="@+id/conference_icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginStart="10dp"
android:adjustViewBounds="true"
android:src="@drawable/users_three"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/call_direction_label"
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="@id/conference_subject"
app:layout_constraintBottom_toBottomOf="@id/conference_subject"
app:tint="@color/orange_main_500" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/call_header_style"
android:id="@+id/call_direction_label"
android:id="@+id/conference_subject"
android:layout_width="wrap_content"
android:layout_height="@dimen/call_top_bar_text_height"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:text="@{conferenceViewModel.subject, default=`Meeting with John Doe`}"
app:layout_constraintStart_toEndOf="@id/call_direction_icon"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/conference_icon"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
@ -143,8 +146,8 @@
android:layout_height="@dimen/call_top_bar_text_height"
android:layout_marginStart="5dp"
android:text="@string/vertical_separator"
app:layout_constraintStart_toEndOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="@id/call_direction_label"/>
app:layout_constraintStart_toEndOf="@id/conference_subject"
app:layout_constraintTop_toTopOf="@id/conference_subject"/>
<Chronometer
style="@style/call_header_style"
@ -156,7 +159,7 @@
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/separator"
app:layout_constraintEnd_toStartOf="@id/switch_camera"
app:layout_constraintTop_toTopOf="@id/call_direction_label"/>
app:layout_constraintTop_toTopOf="@id/conference_subject"/>
<androidx.appcompat.widget.AppCompatTextView
style="@style/call_header_style"
@ -169,7 +172,7 @@
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toEndOf="@id/separator"
app:layout_constraintEnd_toStartOf="@id/switch_camera"
app:layout_constraintTop_toTopOf="@id/call_direction_label"/>
app:layout_constraintTop_toTopOf="@id/conference_subject"/>
<ImageView
android:onClick="@{() -> viewModel.switchCamera()}"
@ -181,8 +184,8 @@
android:src="@drawable/camera_rotate"
android:visibility="@{!viewModel.fullScreenMode &amp;&amp; !viewModel.pipMode &amp;&amp; viewModel.isVideoEnabled &amp;&amp; viewModel.showSwitchCamera ? View.VISIBLE : View.GONE}"
app:tint="@color/white"
app:layout_constraintTop_toTopOf="@id/call_direction_label"
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="@id/conference_subject"
app:layout_constraintBottom_toBottomOf="@id/conference_subject"
app:layout_constraintEnd_toEndOf="parent" />
<ImageView

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
@ -16,6 +15,20 @@
android:layout_height="match_parent"
android:background="@color/gray_900">
<androidx.constraintlayout.widget.Group
android:id="@+id/single_call_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="call_direction_label, call_direction_icon"
android:visibility="@{viewModel.conferenceModel.isCurrentCallInConference ? View.GONE : View.VISIBLE}" />
<androidx.constraintlayout.widget.Group
android:id="@+id/conference_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="conference_icon, conference_subject"
android:visibility="@{viewModel.conferenceModel.isCurrentCallInConference ? View.VISIBLE : View.GONE, default=gone}" />
<ImageView
android:id="@+id/call_direction_icon"
android:layout_width="12dp"
@ -33,12 +46,42 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/call_top_bar_text_height"
android:layout_marginStart="10dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="@string/call_ended"
app:layout_constraintStart_toEndOf="@id/call_direction_icon"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/background"/>
app:layout_constraintTop_toTopOf="@id/separator"
app:layout_constraintBottom_toBottomOf="@id/separator"/>
<ImageView
android:id="@+id/conference_icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginStart="10dp"
android:adjustViewBounds="true"
android:src="@drawable/users_three"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/conference_subject"
app:layout_constraintBottom_toBottomOf="@id/conference_subject"
app:tint="@color/orange_main_500" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/call_header_style"
android:id="@+id/conference_subject"
android:layout_width="wrap_content"
android:layout_height="@dimen/call_top_bar_text_height"
android:layout_marginStart="10dp"
android:text="@{viewModel.conferenceModel.subject, default=`Meeting with John Doe`}"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/conference_icon"
app:layout_constraintTop_toTopOf="@id/separator"
app:layout_constraintBottom_toBottomOf="@id/separator"/>
<androidx.constraintlayout.widget.Barrier
android:id="@+id/header_end_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="call_direction_label, conference_subject" />
<androidx.appcompat.widget.AppCompatTextView
style="@style/call_header_style"
@ -46,9 +89,10 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/call_top_bar_text_height"
android:layout_marginStart="5dp"
android:layout_marginTop="10dp"
android:text="@string/vertical_separator"
app:layout_constraintStart_toEndOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="@id/call_direction_label"/>
app:layout_constraintStart_toEndOf="@id/header_end_barrier"
app:layout_constraintTop_toTopOf="parent"/>
<Chronometer
style="@style/call_header_style"
@ -58,7 +102,7 @@
android:layout_marginStart="5dp"
android:visibility="@{viewModel.isPaused || viewModel.isPausedByRemote ? View.GONE : View.VISIBLE}"
app:layout_constraintStart_toEndOf="@id/separator"
app:layout_constraintTop_toTopOf="@id/call_direction_label"/>
app:layout_constraintTop_toTopOf="@id/separator"/>
<ImageView
android:id="@+id/media_encryption"
@ -67,8 +111,8 @@
android:padding="10dp"
android:src="@{viewModel.isZrtpPq ? @drawable/media_encryption_zrtp_pq : @drawable/media_encryption_srtp, default=@drawable/media_encryption_zrtp_pq}"
android:visibility="@{viewModel.isMediaEncrypted ? View.VISIBLE : View.GONE}"
app:layout_constraintTop_toTopOf="@id/call_direction_label"
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"
app:layout_constraintTop_toTopOf="@id/separator"
app:layout_constraintBottom_toBottomOf="@id/separator"
app:layout_constraintEnd_toEndOf="parent" />
<ImageView
@ -78,7 +122,8 @@
android:layout_height="0dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintTop_toBottomOf="@id/call_direction_label"
android:layout_marginTop="10dp"
app:layout_constraintTop_toBottomOf="@id/separator"
app:layout_constraintBottom_toTopOf="@id/bottom_bar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
@ -124,6 +169,7 @@
android:text="@{viewModel.displayedAddress, default=`sip:johndoe@sip.linphone.org`}"
android:textColor="@color/white"
android:textSize="14sp"
android:visibility="@{viewModel.conferenceModel.isCurrentCallInConference ? View.GONE : View.VISIBLE}"
app:layout_constraintTop_toBottomOf="@id/name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />

View file

@ -126,6 +126,7 @@
android:text="@{viewModel.displayedAddress, default=`sip:johndoe@sip.linphone.org`}"
android:textColor="@color/white"
android:textSize="14sp"
android:visibility="@{viewModel.conferenceModel.isCurrentCallInConference ? View.GONE : View.VISIBLE}"
app:layout_constraintTop_toBottomOf="@id/name"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />