mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Started conference call UI
This commit is contained in:
parent
4368e1a5f7
commit
e8ca20a7e2
11 changed files with 410 additions and 6 deletions
|
|
@ -119,7 +119,20 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
) {
|
||||
Log.i("$TAG Call [${call.remoteAddress.asStringUriOnly()}] state changed [$state]")
|
||||
when (state) {
|
||||
Call.State.OutgoingProgress, Call.State.Connected -> {
|
||||
Call.State.OutgoingProgress -> {
|
||||
val conferenceInfo = core.findConferenceInformationFromUri(call.remoteAddress)
|
||||
// Do not show outgoing call view for conference calls, wait for connected state
|
||||
if (conferenceInfo == null) {
|
||||
postOnMainThread {
|
||||
showCallActivity()
|
||||
}
|
||||
} else {
|
||||
Log.i(
|
||||
"$TAG Call peer address matches known conference, delaying in-call UI until Connected state"
|
||||
)
|
||||
}
|
||||
}
|
||||
Call.State.Connected -> {
|
||||
postOnMainThread {
|
||||
showCallActivity()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@ import androidx.databinding.DataBindingUtil
|
|||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.window.layout.FoldingFeature
|
||||
import androidx.window.layout.WindowInfoTracker
|
||||
import androidx.window.layout.WindowLayoutInfo
|
||||
|
|
@ -166,7 +165,7 @@ class CallActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
callViewModel.goTEndedCallEvent.observe(this) {
|
||||
callViewModel.goToEndedCallEvent.observe(this) {
|
||||
it.consume {
|
||||
val action = ActiveCallFragmentDirections.actionGlobalEndedCallFragment()
|
||||
findNavController(R.id.call_nav_container).navigate(action)
|
||||
|
|
|
|||
|
|
@ -251,6 +251,14 @@ class ActiveCallFragment : GenericCallFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
callViewModel.goToConferenceEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
Log.i("$TAG Going to conference fragment")
|
||||
val action = ActiveCallFragmentDirections.actionActiveCallFragmentToActiveConferenceCallFragment()
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
}
|
||||
|
||||
actionsBottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() {
|
||||
override fun onStateChanged(bottomSheet: View, newState: Int) {
|
||||
when (newState) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.call.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.databinding.CallActiveConferenceFragmentBinding
|
||||
import org.linphone.ui.call.viewmodel.CallsViewModel
|
||||
import org.linphone.ui.call.viewmodel.CurrentCallViewModel
|
||||
|
||||
class ActiveConferenceCallFragment : GenericCallFragment() {
|
||||
companion object {
|
||||
private const val TAG = "[Active Conference Call Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: CallActiveConferenceFragmentBinding
|
||||
|
||||
private lateinit var callViewModel: CurrentCallViewModel
|
||||
|
||||
private lateinit var callsViewModel: CallsViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = CallActiveConferenceFragmentBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
callViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[CurrentCallViewModel::class.java]
|
||||
}
|
||||
|
||||
callsViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[CallsViewModel::class.java]
|
||||
}
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = callViewModel
|
||||
binding.conferenceViewModel = callViewModel.conferenceModel
|
||||
binding.callsViewModel = callsViewModel
|
||||
binding.numpadModel = callViewModel.numpadModel
|
||||
|
||||
callViewModel.callDuration.observe(viewLifecycleOwner) { duration ->
|
||||
binding.chronometer.base = SystemClock.elapsedRealtime() - (1000 * duration)
|
||||
binding.chronometer.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.call.model
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.Conference
|
||||
import org.linphone.core.tools.Log
|
||||
|
||||
class ConferenceModel {
|
||||
companion object {
|
||||
private const val TAG = "[Conference ViewModel]"
|
||||
}
|
||||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
||||
private lateinit var conference: Conference
|
||||
|
||||
@WorkerThread
|
||||
fun configureFromCall(call: Call) {
|
||||
val conf = call.conference ?: return
|
||||
conference = conf
|
||||
|
||||
Log.i(
|
||||
"$TAG Configuring conference with subject [${conference.subject}] from call [${call.callLog.callId}]"
|
||||
)
|
||||
subject.postValue(conference.subject)
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ import org.linphone.core.MediaDirection
|
|||
import org.linphone.core.MediaEncryption
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.call.model.AudioDeviceModel
|
||||
import org.linphone.ui.call.model.ConferenceModel
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
import org.linphone.ui.main.history.model.NumpadModel
|
||||
import org.linphone.utils.AppUtils
|
||||
|
|
@ -110,7 +111,7 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val goTEndedCallEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
val goToEndedCallEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
|
|
@ -129,6 +130,14 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
MutableLiveData<Event<Pair<String, String>>>()
|
||||
}
|
||||
|
||||
// Conference
|
||||
|
||||
val conferenceModel = ConferenceModel()
|
||||
|
||||
val goToConferenceEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
// Extras actions
|
||||
|
||||
val isActionsMenuExpanded = MutableLiveData<Boolean>()
|
||||
|
|
@ -201,13 +210,13 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
Log.e(
|
||||
"$TAG Failed to get a valid call to display, go to ended call fragment"
|
||||
)
|
||||
goTEndedCallEvent.postValue(Event(true))
|
||||
goToEndedCallEvent.postValue(Event(true))
|
||||
}
|
||||
} else {
|
||||
Log.i("$TAG Call is ending, go to ended call fragment")
|
||||
// Show that call was ended for a few seconds, then leave
|
||||
// TODO FIXME: do not show it when call is being ended due to user terminating the call
|
||||
goTEndedCallEvent.postValue(Event(true))
|
||||
goToEndedCallEvent.postValue(Event(true))
|
||||
}
|
||||
} else {
|
||||
val videoEnabled = call.currentParams.isVideoEnabled
|
||||
|
|
@ -224,6 +233,12 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
Log.w("$TAG Video is not longer enabled, leaving full screen mode")
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
isPaused.postValue(isCallPaused())
|
||||
|
|
@ -719,6 +734,11 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
currentCall = call
|
||||
call.addListener(callListener)
|
||||
|
||||
if (call.conference != null) {
|
||||
conferenceModel.configureFromCall(call)
|
||||
goToConferenceEvent.postValue(Event(true))
|
||||
}
|
||||
|
||||
if (call.dir == Call.Dir.Incoming) {
|
||||
if (call.core.accountList.size > 1) {
|
||||
val displayName = LinphoneUtils.getDisplayName(call.toAddress)
|
||||
|
|
|
|||
|
|
@ -109,6 +109,13 @@ class MeetingWaitingRoomFragment : GenericFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.conferenceCreatedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
Log.i("$TAG Conference was joined, leaving waiting room")
|
||||
goBack()
|
||||
}
|
||||
}
|
||||
|
||||
if (!isCameraPermissionGranted()) {
|
||||
viewModel.isVideoAvailable.value = false
|
||||
Log.w("$TAG Camera permission wasn't granted yet, asking for it now")
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ import androidx.annotation.WorkerThread
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Conference
|
||||
import org.linphone.core.ConferenceInfo
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
|
|
@ -53,11 +56,38 @@ class MeetingWaitingRoomViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val conferenceInfoFoundEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
val conferenceCreatedEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
private lateinit var conferenceInfo: ConferenceInfo
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.addListener(coreListener)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.removeListener(coreListener)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
|
|
|
|||
192
app/src/main/res/layout/call_active_conference_fragment.xml
Normal file
192
app/src/main/res/layout/call_active_conference_fragment.xml
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
<?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>
|
||||
<import type="android.view.View" />
|
||||
<import type="org.linphone.core.ChatRoom.SecurityLevel" />
|
||||
<variable
|
||||
name="newCallClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="callsListClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.call.viewmodel.CurrentCallViewModel" />
|
||||
<variable
|
||||
name="conferenceViewModel"
|
||||
type="org.linphone.ui.call.model.ConferenceModel" />
|
||||
<variable
|
||||
name="callsViewModel"
|
||||
type="org.linphone.ui.call.viewmodel.CallsViewModel" />
|
||||
<variable
|
||||
name="numpadModel"
|
||||
type="org.linphone.ui.main.history.model.NumpadModel" />
|
||||
</data>
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/constraint_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/gray_900">
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/hinge_top"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="0" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/hinge_bottom"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintGuide_percent="1" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/background"
|
||||
android:src="@drawable/shape_round_in_call_gray_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="@dimen/call_main_actions_menu_height"
|
||||
app:layout_constraintTop_toBottomOf="@id/call_direction_label"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/waiting_for_others"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="@string/conference_call_empty"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="22sp"
|
||||
app:layout_constraintTop_toTopOf="@id/background"
|
||||
app:layout_constraintBottom_toBottomOf="@id/background"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/header_info_visibility"
|
||||
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" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/call_direction_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:tint="@color/orange_main_500" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/call_header_style"
|
||||
android:id="@+id/call_direction_label"
|
||||
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="@{conferenceViewModel.subject, default=`Meeting with John Doe`}"
|
||||
app:layout_constraintStart_toEndOf="@id/call_direction_icon"
|
||||
app:layout_constraintTop_toTopOf="@id/hinge_top"
|
||||
app:layout_constraintBottom_toTopOf="@id/background"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/call_header_style"
|
||||
android:id="@+id/separator"
|
||||
android:layout_width="wrap_content"
|
||||
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"/>
|
||||
|
||||
<Chronometer
|
||||
style="@style/call_header_style"
|
||||
android:id="@+id/chronometer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/call_top_bar_text_height"
|
||||
android:layout_marginStart="5dp"
|
||||
android:visibility="@{viewModel.isPaused || viewModel.isPausedByRemote ? View.GONE : View.VISIBLE}"
|
||||
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"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/call_header_style"
|
||||
android:id="@+id/paused_call_header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/call_top_bar_text_height"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@{viewModel.isPaused ? @string/call_state_paused : @string/call_state_paused_by_remote, default=@string/call_state_paused}"
|
||||
android:visibility="@{viewModel.isPaused || viewModel.isPausedByRemote ? View.VISIBLE : View.GONE, default=gone}"
|
||||
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"/>
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.switchCamera()}"
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="@dimen/call_top_bar_info_height"
|
||||
android:layout_height="@dimen/call_top_bar_info_height"
|
||||
android:padding="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/camera_rotate"
|
||||
android:visibility="@{!viewModel.fullScreenMode && !viewModel.pipMode && viewModel.isVideoEnabled && 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_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/recording"
|
||||
android:layout_width="@dimen/icon_size"
|
||||
android:layout_height="@dimen/icon_size"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:src="@drawable/record_fill"
|
||||
android:visibility="@{viewModel.isRecording ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintTop_toTopOf="@id/background"
|
||||
app:layout_constraintStart_toStartOf="@id/background"
|
||||
app:tint="@color/red_danger_500" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/bottom_bar"
|
||||
android:visibility="@{viewModel.fullScreenMode || viewModel.pipMode ? View.INVISIBLE : View.VISIBLE}"
|
||||
layout="@layout/call_extra_actions"
|
||||
bind:viewModel="@{viewModel}"
|
||||
bind:callsViewModel="@{callsViewModel}"
|
||||
bind:newCallClickListener="@{newCallClickListener}"
|
||||
bind:callsListClickListener="@{callsListClickListener}"/>
|
||||
|
||||
<include
|
||||
android:id="@+id/call_numpad"
|
||||
android:visibility="@{viewModel.fullScreenMode || viewModel.pipMode ? View.INVISIBLE : View.VISIBLE}"
|
||||
layout="@layout/call_numpad"
|
||||
bind:model="@{numpadModel}"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -66,6 +66,12 @@
|
|||
app:enterAnim="@anim/slide_in"
|
||||
app:popExitAnim="@anim/slide_out"
|
||||
app:launchSingleTop="true" />
|
||||
<action
|
||||
android:id="@+id/action_activeCallFragment_to_activeConferenceCallFragment"
|
||||
app:destination="@id/activeConferenceCallFragment"
|
||||
app:popUpTo="@id/activeCallFragment"
|
||||
app:popUpToInclusive="true"
|
||||
app:launchSingleTop="true" />
|
||||
</fragment>
|
||||
|
||||
<action android:id="@+id/action_global_activeCallFragment"
|
||||
|
|
@ -104,4 +110,10 @@
|
|||
app:destination="@id/endedCallFragment"
|
||||
app:launchSingleTop="true"/>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/activeConferenceCallFragment"
|
||||
android:name="org.linphone.ui.call.fragment.ActiveConferenceCallFragment"
|
||||
android:label="ActiveConferenceCallFragment"
|
||||
tools:layout="@layout/call_active_conference_fragment"/>
|
||||
|
||||
</navigation>
|
||||
|
|
@ -427,6 +427,8 @@
|
|||
<string name="calls_count_label">%s calls</string>
|
||||
<string name="calls_paused_count_label">%s paused calls</string>
|
||||
|
||||
<string name="conference_call_empty">Waiting for other participants…</string>
|
||||
|
||||
<string name="connection_error_for_non_default_account">Account connection error</string>
|
||||
|
||||
<!-- Keep <u></u> in following strings translations! -->
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue