mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Started calls list
This commit is contained in:
parent
f345db49cd
commit
8011bd997c
22 changed files with 403 additions and 44 deletions
|
|
@ -208,6 +208,14 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
return
|
||||
}
|
||||
|
||||
val currentCall = core.currentCall
|
||||
if (currentCall != null) {
|
||||
Log.w(
|
||||
"$TAG Found current call [${currentCall.remoteAddress.asStringUriOnly()}], pausing it first"
|
||||
)
|
||||
currentCall.pause()
|
||||
}
|
||||
|
||||
val params = callParams ?: core.createCallParams(null)
|
||||
if (params == null) {
|
||||
val call = core.inviteAddress(address)
|
||||
|
|
|
|||
|
|
@ -24,13 +24,11 @@ import androidx.annotation.WorkerThread
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.model.AccountModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
|
|
@ -169,7 +167,7 @@ open class AbstractTopBarViewModel @UiThread constructor() : ViewModel() {
|
|||
callDisplayName.postValue(
|
||||
contact?.name ?: LinphoneUtils.getDisplayName(currentCall.remoteAddress)
|
||||
)
|
||||
callStatus.postValue(callStateToString(currentCall.state))
|
||||
callStatus.postValue(LinphoneUtils.callStateToString(currentCall.state))
|
||||
} else {
|
||||
val firstCall = core.calls.firstOrNull()
|
||||
if (firstCall != null) {
|
||||
|
|
@ -179,38 +177,10 @@ open class AbstractTopBarViewModel @UiThread constructor() : ViewModel() {
|
|||
callDisplayName.postValue(
|
||||
contact?.name ?: LinphoneUtils.getDisplayName(firstCall.remoteAddress)
|
||||
)
|
||||
callStatus.postValue(callStateToString(firstCall.state))
|
||||
callStatus.postValue(LinphoneUtils.callStateToString(firstCall.state))
|
||||
}
|
||||
}
|
||||
Log.i("$TAG At least a call, asking fragment to change status bar color")
|
||||
changeSystemTopBarColorToInCallEvent.postValue(Event(true))
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun callStateToString(state: Call.State): String {
|
||||
return when (state) {
|
||||
Call.State.IncomingEarlyMedia, Call.State.IncomingReceived -> {
|
||||
AppUtils.getString(R.string.voip_call_state_incoming_received)
|
||||
}
|
||||
Call.State.OutgoingInit, Call.State.OutgoingProgress -> {
|
||||
AppUtils.getString(R.string.voip_call_state_outgoing_progress)
|
||||
}
|
||||
Call.State.OutgoingRinging, Call.State.OutgoingEarlyMedia -> {
|
||||
AppUtils.getString(R.string.voip_call_state_outgoing_ringing)
|
||||
}
|
||||
Call.State.Connected, Call.State.StreamsRunning, Call.State.Updating, Call.State.UpdatedByRemote -> {
|
||||
AppUtils.getString(R.string.voip_call_state_connected)
|
||||
}
|
||||
Call.State.Pausing, Call.State.Paused, Call.State.PausedByRemote -> {
|
||||
AppUtils.getString(R.string.voip_call_state_paused)
|
||||
}
|
||||
Call.State.End, Call.State.Released, Call.State.Error -> {
|
||||
AppUtils.getString(R.string.voip_call_state_ended)
|
||||
}
|
||||
else -> {
|
||||
// TODO: handle other states
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,11 @@ class ActiveCallFragment : GenericCallFragment() {
|
|||
findNavController().navigate(action)
|
||||
}
|
||||
|
||||
binding.setCallsListClickListener {
|
||||
val action = ActiveCallFragmentDirections.actionActiveCallFragmentToCallsListFragment()
|
||||
findNavController().navigate(action)
|
||||
}
|
||||
|
||||
sharedViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[SharedCallViewModel::class.java]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.voip.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.VoipCallsListFragmentBinding
|
||||
import org.linphone.ui.voip.viewmodel.CallsViewModel
|
||||
|
||||
class CallsListFragment : GenericCallFragment() {
|
||||
companion object {
|
||||
private const val TAG = "[Calls List Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: VoipCallsListFragmentBinding
|
||||
|
||||
private val viewModel: CallsViewModel by navGraphViewModels(
|
||||
R.id.voip_nav_graph
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = VoipCallsListFragmentBinding.inflate(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = viewModel
|
||||
|
||||
binding.setBackClickListener {
|
||||
findNavController().popBackStack()
|
||||
}
|
||||
}
|
||||
}
|
||||
64
app/src/main/java/org/linphone/ui/voip/model/CallModel.kt
Normal file
64
app/src/main/java/org/linphone/ui/voip/model/CallModel.kt
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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.voip.model
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Call
|
||||
import org.linphone.core.CallListenerStub
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
class CallModel @WorkerThread constructor(val call: Call) {
|
||||
val displayName = MutableLiveData<String>()
|
||||
|
||||
val state = MutableLiveData<String>()
|
||||
|
||||
val isPaused = MutableLiveData<Boolean>()
|
||||
|
||||
val friend = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
|
||||
|
||||
val contact = MutableLiveData<ContactAvatarModel>()
|
||||
|
||||
private val callListener = object : CallListenerStub() {
|
||||
override fun onStateChanged(call: Call, state: Call.State, message: String) {
|
||||
this@CallModel.state.postValue(LinphoneUtils.callStateToString(state))
|
||||
isPaused.postValue(LinphoneUtils.isCallPaused(state))
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
call.addListener(callListener)
|
||||
|
||||
displayName.postValue(friend?.name ?: LinphoneUtils.getDisplayName(call.remoteAddress))
|
||||
if (friend != null) {
|
||||
contact.postValue(ContactAvatarModel(friend))
|
||||
}
|
||||
|
||||
state.postValue(LinphoneUtils.callStateToString(call.state))
|
||||
isPaused.postValue(LinphoneUtils.isCallPaused(call.state))
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun destroy() {
|
||||
call.removeListener(callListener)
|
||||
}
|
||||
}
|
||||
|
|
@ -30,6 +30,7 @@ import org.linphone.core.Call
|
|||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.voip.model.CallModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class CallsViewModel @UiThread constructor() : ViewModel() {
|
||||
|
|
@ -41,6 +42,8 @@ class CallsViewModel @UiThread constructor() : ViewModel() {
|
|||
private const val ALERT_NETWORK_TYPE_CELLULAR = "mobile"
|
||||
}
|
||||
|
||||
val calls = MutableLiveData<ArrayList<CallModel>>()
|
||||
|
||||
val goToActiveCallEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
val showIncomingCallEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
|
@ -94,6 +97,34 @@ class CallsViewModel @UiThread constructor() : ViewModel() {
|
|||
state: Call.State,
|
||||
message: String
|
||||
) {
|
||||
// Update calls list if needed
|
||||
val found = calls.value.orEmpty().find {
|
||||
it.call == call
|
||||
}
|
||||
if (found == null) {
|
||||
if (state != Call.State.End && state != Call.State.Released && state != Call.State.Error) {
|
||||
Log.i(
|
||||
"$TAG Found a call [${call.remoteAddress.asStringUriOnly()}] not yet in calls list, let's add it"
|
||||
)
|
||||
val list = arrayListOf<CallModel>()
|
||||
list.addAll(calls.value.orEmpty())
|
||||
val model = CallModel(call)
|
||||
list.add(model)
|
||||
calls.postValue(list)
|
||||
}
|
||||
} else {
|
||||
if (state == Call.State.End || state == Call.State.Released || state == Call.State.Error) {
|
||||
Log.i(
|
||||
"$TAG Call [${call.remoteAddress.asStringUriOnly()}] shouldn't be in calls list anymore, let's remove it"
|
||||
)
|
||||
val list = arrayListOf<CallModel>()
|
||||
list.addAll(calls.value.orEmpty())
|
||||
list.remove(found)
|
||||
calls.postValue(list)
|
||||
found.destroy()
|
||||
}
|
||||
}
|
||||
|
||||
if (call == core.currentCall || core.currentCall == null) {
|
||||
Log.i(
|
||||
"$TAG Current call [${call.remoteAddress.asStringUriOnly()}] state changed [$state]"
|
||||
|
|
@ -139,6 +170,13 @@ class CallsViewModel @UiThread constructor() : ViewModel() {
|
|||
core.addListener(coreListener)
|
||||
|
||||
if (core.callsNb > 0) {
|
||||
val list = arrayListOf<CallModel>()
|
||||
for (call in core.calls) {
|
||||
val model = CallModel(call)
|
||||
list.add(model)
|
||||
}
|
||||
calls.postValue(list)
|
||||
|
||||
val currentCall = core.currentCall ?: core.calls.first()
|
||||
|
||||
when (currentCall.state) {
|
||||
|
|
@ -165,6 +203,7 @@ class CallsViewModel @UiThread constructor() : ViewModel() {
|
|||
super.onCleared()
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
calls.value.orEmpty().forEach(CallModel::destroy)
|
||||
core.removeListener(coreListener)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -118,6 +118,14 @@ class LinphoneUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun isCallPaused(callState: Call.State): Boolean {
|
||||
return when (callState) {
|
||||
Call.State.Pausing, Call.State.Paused, Call.State.PausedByRemote, Call.State.Resuming -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
@IntegerRes
|
||||
fun getIconResId(callStatus: Status, callDir: Dir): Int {
|
||||
|
|
@ -189,5 +197,33 @@ class LinphoneUtils {
|
|||
remoteSipUri.clean()
|
||||
return "${localSipUri.asStringUriOnly()}~${remoteSipUri.asStringUriOnly()}"
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun callStateToString(state: Call.State): String {
|
||||
return when (state) {
|
||||
Call.State.IncomingEarlyMedia, Call.State.IncomingReceived -> {
|
||||
AppUtils.getString(R.string.voip_call_state_incoming_received)
|
||||
}
|
||||
Call.State.OutgoingInit, Call.State.OutgoingProgress -> {
|
||||
AppUtils.getString(R.string.voip_call_state_outgoing_progress)
|
||||
}
|
||||
Call.State.OutgoingRinging, Call.State.OutgoingEarlyMedia -> {
|
||||
AppUtils.getString(R.string.voip_call_state_outgoing_ringing)
|
||||
}
|
||||
Call.State.Connected, Call.State.StreamsRunning, Call.State.Updating, Call.State.UpdatedByRemote -> {
|
||||
AppUtils.getString(R.string.voip_call_state_connected)
|
||||
}
|
||||
Call.State.Pausing, Call.State.Paused, Call.State.PausedByRemote -> {
|
||||
AppUtils.getString(R.string.voip_call_state_paused)
|
||||
}
|
||||
Call.State.End, Call.State.Released, Call.State.Error -> {
|
||||
AppUtils.getString(R.string.voip_call_state_ended)
|
||||
}
|
||||
else -> {
|
||||
// TODO: handle other states
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<size android:width="55dp" android:height="55dp" />
|
||||
<solid android:color="@color/gray_400"/>
|
||||
<solid android:color="@color/gray_main2_400"/>
|
||||
</shape>
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/avatar_big_size"
|
||||
android:layout_height="@dimen/avatar_big_size"
|
||||
android:layout_marginTop="21dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/shape_circle_light_blue_background"
|
||||
accountAvatar="@{viewModel.accountModel}"
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
android:onClick="@{backClickListener}"
|
||||
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.GONE}"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title"/>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
android:onClick="@{backClickListener}"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
android:onClick="@{backClickListener}"
|
||||
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.GONE}"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/invisible_title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/invisible_title"/>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
android:adjustViewBounds="true"
|
||||
android:padding="15dp"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title" />
|
||||
|
|
|
|||
100
app/src/main/res/layout/voip_call_list_cell.xml
Normal file
100
app/src/main/res/layout/voip_call_list_cell.xml
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="model"
|
||||
type="org.linphone.ui.voip.model.CallModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="5dp"
|
||||
android:src="@drawable/primary_cell_background"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<io.getstream.avatarview.AvatarView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/avatar_list_cell_size"
|
||||
android:layout_height="@dimen/avatar_list_cell_size"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/shape_circle_light_blue_background"
|
||||
contactAvatar="@{model.contact}"
|
||||
app:avatarViewPlaceholder="@drawable/user_circle"
|
||||
app:avatarViewInitialsBackgroundColor="@color/gray_main2_200"
|
||||
app:avatarViewInitialsTextColor="@color/gray_main2_600"
|
||||
app:avatarViewInitialsTextSize="16sp"
|
||||
app:avatarViewInitialsTextStyle="bold"
|
||||
app:avatarViewShape="circle"
|
||||
app:avatarViewBorderWidth="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style"
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{model.displayName, default=`John Doe`}"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/call_state_icon"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:src="@{model.isPaused ? @drawable/pause_call : @drawable/phone, default=@drawable/pause_call}"
|
||||
app:tint="@color/gray_main2_500"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/default_text_style_300"
|
||||
android:id="@+id/call_state"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@{model.state, default=`Paused`}"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
app:layout_constraintStart_toEndOf="@id/name"
|
||||
app:layout_constraintEnd_toStartOf="@id/call_state_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
<View
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="@color/gray_main2_200"
|
||||
app:layout_constraintStart_toStartOf="@id/name"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
||||
61
app/src/main/res/layout/voip_calls_list_fragment.xml
Normal file
61
app/src/main/res/layout/voip_calls_list_fragment.xml
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:bind="http://schemas.android.com/tools">
|
||||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<variable
|
||||
name="backClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.voip.viewmodel.CallsViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@color/white">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:padding="15dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:onClick="@{backClickListener}"
|
||||
android:src="@drawable/caret_left"
|
||||
app:tint="@color/orange_main_500"
|
||||
app:layout_constraintBottom_toBottomOf="@id/title"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title"/>
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
style="@style/main_page_title_style"
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/top_bar_height"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:text="@string/voip_calls_list_title"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/back"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/calls_list"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
entries="@{viewModel.calls}"
|
||||
layout="@{@layout/voip_call_list_cell}"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -54,6 +54,12 @@
|
|||
app:enterAnim="@anim/slide_in"
|
||||
app:popExitAnim="@anim/slide_out"
|
||||
app:launchSingleTop="true" />
|
||||
<action
|
||||
android:id="@+id/action_activeCallFragment_to_callsListFragment"
|
||||
app:destination="@id/callsListFragment"
|
||||
app:enterAnim="@anim/slide_in"
|
||||
app:popExitAnim="@anim/slide_out"
|
||||
app:launchSingleTop="true" />
|
||||
</fragment>
|
||||
|
||||
<action android:id="@+id/action_global_activeCallFragment"
|
||||
|
|
@ -68,4 +74,10 @@
|
|||
android:label="NewCallFragment"
|
||||
tools:layout="@layout/call_start_fragment" />
|
||||
|
||||
<fragment
|
||||
android:id="@+id/callsListFragment"
|
||||
android:name="org.linphone.ui.voip.fragment.CallsListFragment"
|
||||
android:label="CallsListFragment"
|
||||
tools:layout="@layout/voip_calls_list_fragment" />
|
||||
|
||||
</navigation>
|
||||
|
|
@ -290,6 +290,8 @@
|
|||
<string name="voip_call_state_paused">Paused</string>
|
||||
<string name="voip_call_state_ended">Ended</string>
|
||||
|
||||
<string name="voip_calls_list_title">Calls list</string>
|
||||
|
||||
<!-- Keep <u></u> in following strings translations! -->
|
||||
<string name="welcome_carousel_skip"><u>Skip</u></string>
|
||||
<string name="assistant_forgotten_password"><u>Forgotten password?</u></string>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue