More work on contact details

This commit is contained in:
Sylvain Berfini 2023-08-08 13:08:06 +02:00
parent 11f4ff4594
commit 8bb88f397e
13 changed files with 715 additions and 153 deletions

View file

@ -54,13 +54,14 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
override fun onCreateLoader(id: Int, args: Bundle?): Loader<Cursor> {
val mimeType = ContactsContract.Data.MIMETYPE
val mimeSelection = "$mimeType = ? OR $mimeType = ? OR $mimeType = ?"
val mimeSelection = "$mimeType = ? OR $mimeType = ? OR $mimeType = ? OR $mimeType = ?"
val selection = ContactsContract.Data.IN_DEFAULT_DIRECTORY + " == 1 AND ($mimeSelection)"
val selectionArgs = arrayOf(
linphoneMime,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE,
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE
)
return CursorLoader(
@ -135,6 +136,7 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
cursor.getColumnIndexOrThrow(ContactsContract.Contacts.STARRED)
) == 1
friend.starred = starred
val lookupKey =
cursor.getString(
cursor.getColumnIndexOrThrow(
@ -227,6 +229,24 @@ class ContactLoader : LoaderManager.LoaderCallbacks<Cursor> {
}
}
}
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE -> {
val organization: String? =
cursor.getString(
cursor.getColumnIndexOrThrow(
ContactsContract.CommonDataKinds.Organization.COMPANY
)
)
if (organization != null) {
friend.organization = organization
}
/*val job: String? =
cursor.getString(
cursor.getColumnIndexOrThrow(
ContactsContract.CommonDataKinds.Organization.TITLE
)
)*/
}
}
friends[id] = friend

View file

@ -0,0 +1,53 @@
/*
* Copyright (c) 2010-2020 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.contacts
import org.linphone.core.Address
class ContactNumberOrAddressData(
val address: Address?,
val displayedValue: String,
private val listener: ContactNumberOrAddressClickListener,
val isSip: Boolean = true,
val label: String = ""
) {
fun startCall() {
address ?: return
listener.onCall(address)
}
fun startVideoCall() {
address ?: return
listener.onVideoCall(address)
}
fun startChat(secured: Boolean) {
address ?: return
listener.onChat(address)
}
}
interface ContactNumberOrAddressClickListener {
fun onCall(address: Address)
fun onVideoCall(address: Address)
fun onChat(address: Address)
}

View file

@ -24,10 +24,9 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.doOnPreDraw
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import androidx.navigation.navGraphViewModels
import androidx.transition.ChangeBounds
import org.linphone.R
import org.linphone.databinding.ContactFragmentBinding
import org.linphone.ui.contacts.viewmodel.ContactViewModel
import org.linphone.ui.fragment.GenericFragment
@ -36,9 +35,7 @@ import org.linphone.utils.Event
class ContactFragment : GenericFragment() {
private lateinit var binding: ContactFragmentBinding
private val viewModel: ContactViewModel by navGraphViewModels(
R.id.contactFragment
)
private lateinit var viewModel: ContactViewModel
private val args: ContactFragmentArgs by navArgs()
@ -62,6 +59,8 @@ class ContactFragment : GenericFragment() {
postponeEnterTransition()
binding.lifecycleOwner = viewLifecycleOwner
viewModel = ViewModelProvider(this)[ContactViewModel::class.java]
binding.viewModel = viewModel
val refKey = args.contactRefKey
@ -78,6 +77,7 @@ class ContactFragment : GenericFragment() {
viewModel.contact.observe(viewLifecycleOwner) {
(view.parent as? ViewGroup)?.doOnPreDraw {
startPostponedEnterTransition()
sharedViewModel.openSlidingPaneEvent.value = Event(true)
}
}
}

View file

@ -64,10 +64,16 @@ class ContactsFragment : GenericFragment() {
sharedViewModel.closeSlidingPaneEvent.observe(
viewLifecycleOwner
) {
it.consume { close ->
if (close) {
binding.slidingPaneLayout.closePane()
}
it.consume {
binding.slidingPaneLayout.closePane()
}
}
sharedViewModel.openSlidingPaneEvent.observe(
viewLifecycleOwner
) {
it.consume {
binding.slidingPaneLayout.openPane()
}
}
@ -80,10 +86,6 @@ class ContactsFragment : GenericFragment() {
refKey
)
navController.navigate(action)
if (!binding.slidingPaneLayout.isOpen) {
binding.slidingPaneLayout.openPane()
}
}
}

View file

@ -22,23 +22,91 @@ package org.linphone.ui.contacts.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.core.Address
import org.linphone.ui.contacts.ContactNumberOrAddressClickListener
import org.linphone.ui.contacts.ContactNumberOrAddressData
import org.linphone.ui.contacts.model.ContactModel
import org.linphone.utils.Event
class ContactViewModel : ViewModel() {
val contact = MutableLiveData<ContactModel>()
val sipAddressesAndPhoneNumbers = MutableLiveData<ArrayList<ContactNumberOrAddressData>>()
val company = MutableLiveData<String>()
val showBackButton = MutableLiveData<Boolean>()
val showNumbersAndAddresses = MutableLiveData<Boolean>()
val showCompany = MutableLiveData<Boolean>()
val showDevicesTrust = MutableLiveData<Boolean>()
val friendFoundEvent = MutableLiveData<Event<Boolean>>()
val listener = object : ContactNumberOrAddressClickListener {
override fun onCall(address: Address) {
// UI thread
}
override fun onVideoCall(address: Address) {
// UI thread
}
override fun onChat(address: Address) {
// UI thread
}
}
init {
showNumbersAndAddresses.value = true
showCompany.value = false
}
fun findContactByRefKey(refKey: String) {
// UI thread
coreContext.postOnCoreThread {
coreContext.postOnCoreThread { core ->
val friend = coreContext.contactsManager.findContactById(refKey)
if (friend != null) {
val organization = friend.organization
if (!organization.isNullOrEmpty()) {
company.postValue(organization)
showCompany.postValue(true)
}
val addressesAndNumbers = arrayListOf<ContactNumberOrAddressData>()
for (address in friend.addresses) {
val data = ContactNumberOrAddressData(
address,
address.asStringUriOnly(),
listener,
true
)
addressesAndNumbers.add(data)
}
for (number in friend.phoneNumbersWithLabel) {
val address = core.interpretUrl(number.phoneNumber, true)
val data = ContactNumberOrAddressData(
address,
number.phoneNumber,
listener,
false,
label = number.label.orEmpty()
)
addressesAndNumbers.add(data)
}
sipAddressesAndPhoneNumbers.postValue(addressesAndNumbers)
contact.postValue(ContactModel(friend))
}
}
}
fun toggleNumbersAndAddressesVisibility() {
showNumbersAndAddresses.value = showNumbersAndAddresses.value == false
}
fun toggleDevicesTrustVisibility() {
showDevicesTrust.value = showDevicesTrust.value == false
}
}

View file

@ -30,6 +30,8 @@ class SharedMainViewModel : ViewModel() {
val closeSlidingPaneEvent = MutableLiveData<Event<Boolean>>()
val openSlidingPaneEvent = MutableLiveData<Event<Boolean>>()
val navigateToConversationsEvent = MutableLiveData<Event<Boolean>>()
val navigateToCallsEvent = MutableLiveData<Event<Boolean>>()

View file

@ -20,7 +20,9 @@
package org.linphone.utils
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.inputmethod.InputMethodManager
import android.widget.ImageView
@ -30,19 +32,51 @@ import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.doOnLayout
import androidx.databinding.BindingAdapter
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import coil.load
import coil.transform.CircleCropTransformation
import io.getstream.avatarview.AvatarView
import io.getstream.avatarview.coil.loadImage
import org.linphone.BR
import org.linphone.R
import org.linphone.contacts.ContactData
import org.linphone.core.ConsolidatedPresence
import org.linphone.ui.MainActivity
import org.linphone.ui.contacts.model.ContactModel
/**
* This file contains all the data binding necessary for the app
*/
@BindingAdapter("entries", "layout")
fun <T> setEntries(
viewGroup: ViewGroup,
entries: List<T>?,
layoutId: Int
) {
viewGroup.removeAllViews()
if (entries != null) {
val inflater = viewGroup.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
for (entry in entries) {
val binding = DataBindingUtil.inflate<ViewDataBinding>(
inflater,
layoutId,
viewGroup,
false
)
binding.setVariable(BR.model, entry)
// This is a bit hacky...
binding.lifecycleOwner = viewGroup.context as MainActivity
viewGroup.addView(binding.root)
}
}
}
fun View.showKeyboard(window: Window) {
this.requestFocus()
/*val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

View file

@ -0,0 +1,21 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<group android:name="group">
<path
android:name="path"
android:pathData="M 4.876 4.876 C 5.029 4.723 5.238 4.636 5.455 4.636 L 12.818 4.636 C 13.035 4.636 13.243 4.723 13.397 4.876 C 13.55 5.029 13.636 5.238 13.636 5.455 L 13.636 6.273 C 13.636 6.725 14.003 7.091 14.454 7.091 C 14.906 7.091 15.273 6.725 15.273 6.273 L 15.273 5.455 C 15.273 4.804 15.014 4.179 14.554 3.719 C 14.094 3.259 13.469 3 12.818 3 L 5.455 3 C 4.804 3 4.179 3.259 3.719 3.719 C 3.259 4.179 3 4.804 3 5.455 L 3 12.818 C 3 13.469 3.259 14.094 3.719 14.554 C 4.179 15.014 4.804 15.273 5.455 15.273 L 6.273 15.273 C 6.725 15.273 7.091 14.906 7.091 14.454 C 7.091 14.003 6.725 13.636 6.273 13.636 L 5.455 13.636 C 5.238 13.636 5.029 13.55 4.876 13.397 C 4.723 13.243 4.636 13.035 4.636 12.818 L 4.636 5.455 C 4.636 5.238 4.723 5.029 4.876 4.876 Z"
android:fillColor="#000"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 11.182 8.727 C 9.826 8.727 8.727 9.826 8.727 11.182 L 8.727 18.546 C 8.727 19.901 9.826 21 11.182 21 L 18.546 21 C 19.901 21 21 19.901 21 18.546 L 21 11.182 C 21 9.826 19.901 8.727 18.546 8.727 L 11.182 8.727 Z M 10.364 11.182 C 10.364 10.73 10.73 10.364 11.182 10.364 L 18.546 10.364 C 18.997 10.364 19.364 10.73 19.364 11.182 L 19.364 18.546 C 19.364 18.997 18.997 19.364 18.546 19.364 L 11.182 19.364 C 10.73 19.364 10.364 18.997 10.364 18.546 L 10.364 11.182 Z"
android:fillColor="#000"
android:strokeWidth="1"
android:fillType="evenOdd"/>
</group>
</vector>

View file

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="15dp" />
<solid android:color="@color/white"/>
</shape>

View file

@ -4,6 +4,7 @@
<data>
<import type="android.view.View" />
<import type="org.linphone.core.ConsolidatedPresence" />
<variable
name="backClickListener"
type="View.OnClickListener" />
@ -15,7 +16,17 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
android:background="@drawable/shape_gray_background">
<ImageView
android:id="@+id/top_bar_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:src="@color/white"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/scrollView" />
<ImageView
android:id="@+id/back"
@ -41,134 +52,399 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/background"
<ScrollView
android:id="@+id/scrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="17dp"
android:src="@drawable/shape_gray_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="22dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit" />
<io.getstream.avatarview.AvatarView
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginTop="38dp"
android:adjustViewBounds="true"
contactAvatar="@{viewModel.contact}"
app:avatarViewBorderWidth="0dp"
app:avatarViewIndicatorBorderColor="@color/white"
app:avatarViewIndicatorBorderSizeCriteria="8"
app:avatarViewIndicatorEnabled="true"
app:avatarViewIndicatorPosition="bottomRight"
app:avatarViewIndicatorSizeCriteria="7"
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
app:avatarViewInitialsTextColor="@color/gray_9"
app:avatarViewInitialsTextSize="21sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewPlaceholder="@drawable/contact_avatar"
app:avatarViewShape="circle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/background" />
app:layout_constraintTop_toBottomOf="@id/edit"
app:layout_constraintBottom_toBottomOf="parent">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{viewModel.contact.name, default=`John Doe`}"
android:textColor="@color/gray_8"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/avatar" />
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/status"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="En ligne"
android:textColor="@color/green_online"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/name" />
<androidx.constraintlayout.widget.Group
android:id="@+id/info_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="info_background, company_label, company"
android:visibility="@{viewModel.showCompany ? View.VISIBLE : View.GONE}" />
<ImageView
android:id="@+id/call"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/calls"
app:tint="@color/gray_1"
app:layout_constraintEnd_toStartOf="@id/chat"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status" />
<ImageView
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Call"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/call"
app:layout_constraintStart_toStartOf="@id/call"
app:layout_constraintEnd_toEndOf="@id/call"/>
<io.getstream.avatarview.AvatarView
android:id="@+id/avatar"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginTop="38dp"
android:adjustViewBounds="true"
contactAvatar="@{viewModel.contact}"
app:avatarViewBorderWidth="0dp"
app:avatarViewIndicatorBorderColor="@color/white"
app:avatarViewIndicatorBorderSizeCriteria="8"
app:avatarViewIndicatorEnabled="true"
app:avatarViewIndicatorPosition="bottomRight"
app:avatarViewIndicatorSizeCriteria="7"
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
app:avatarViewInitialsTextColor="@color/gray_9"
app:avatarViewInitialsTextSize="21sp"
app:avatarViewInitialsTextStyle="bold"
app:avatarViewPlaceholder="@drawable/contact_avatar"
app:avatarViewShape="circle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/background" />
<ImageView
android:id="@+id/chat"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/chat"
app:tint="@color/gray_1"
app:layout_constraintEnd_toStartOf="@id/video_call"
app:layout_constraintStart_toEndOf="@id/call"
app:layout_constraintTop_toBottomOf="@id/status" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{viewModel.contact.name, default=`John Doe`}"
android:textColor="@color/gray_8"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/avatar" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Message"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/chat"
app:layout_constraintStart_toStartOf="@id/chat"
app:layout_constraintEnd_toEndOf="@id/chat"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/status"
android:visibility="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? `En ligne` : `Absent`, default=`En ligne`}"
android:textColor="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? @color/green_online : @color/green_online, default=@color/green_online}"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/name" />
<ImageView
android:id="@+id/video_call"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/video_call"
app:tint="@color/gray_1"
app:layout_constraintStart_toEndOf="@id/chat"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/status" />
<ImageView
android:id="@+id/call"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/calls"
app:tint="@color/gray_1"
app:layout_constraintEnd_toStartOf="@id/chat"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/status" />
<androidx.appcompat.widget.AppCompatTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Video Call"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/video_call"
app:layout_constraintStart_toStartOf="@id/video_call"
app:layout_constraintEnd_toEndOf="@id/video_call"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/call_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Call"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/call"
app:layout_constraintStart_toStartOf="@id/call"
app:layout_constraintEnd_toEndOf="@id/call"/>
<ImageView
android:id="@+id/chat"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/chat"
app:tint="@color/gray_1"
app:layout_constraintEnd_toStartOf="@id/video_call"
app:layout_constraintStart_toEndOf="@id/call"
app:layout_constraintTop_toBottomOf="@id/status" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/chat_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Message"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/chat"
app:layout_constraintStart_toStartOf="@id/chat"
app:layout_constraintEnd_toEndOf="@id/chat"/>
<ImageView
android:id="@+id/video_call"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginTop="39dp"
android:background="@drawable/shape_button_round"
android:padding="16dp"
android:src="@drawable/video_call"
app:tint="@color/gray_1"
app:layout_constraintStart_toEndOf="@id/chat"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/status" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/video_call_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="Video Call"
android:textColor="@color/gray_9"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/video_call"
app:layout_constraintStart_toStartOf="@id/video_call"
app:layout_constraintEnd_toEndOf="@id/video_call"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.toggleNumbersAndAddressesVisibility()}"
android:id="@+id/numbers_and_addresses_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:layout_marginTop="45dp"
android:text="Numbers &amp; addresses"
android:drawableEnd="@{viewModel.showNumbersAndAddresses ? @drawable/collapse : @drawable/expand, default=@drawable/collapse}"
android:drawableTint="@color/gray_9"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/gray_9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/call_label"/>
<LinearLayout
android:id="@+id/numbers_and_addresses"
android:visibility="@{viewModel.showNumbersAndAddresses ? View.VISIBLE : View.GONE}"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginTop="9dp"
android:padding="10dp"
android:background="@drawable/shape_round_white_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/numbers_and_addresses_label"
app:entries="@{viewModel.sipAddressesAndPhoneNumbers}"
app:layout="@{@layout/contact_number_address_list_cell}" />
<ImageView
android:id="@+id/info_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="32dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:src="@drawable/shape_round_white_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/numbers_and_addresses"
app:layout_constraintBottom_toBottomOf="@id/company_label"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/company_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="Company : "
android:textColor="@color/gray_9"
android:textStyle="bold"
android:textSize="14sp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toStartOf="@id/info_background"
app:layout_constraintTop_toTopOf="@id/info_background"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/company"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="16dp"
android:paddingBottom="16dp"
android:text="@{viewModel.company, default=`Belledonne Comm`}"
android:textColor="@color/gray_9"
android:textSize="14sp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/company_label"
app:layout_constraintTop_toTopOf="@id/info_background"/>
<androidx.appcompat.widget.AppCompatTextView
android:onClick="@{() -> viewModel.toggleDevicesTrustVisibility()}"
android:id="@+id/trust_label"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:layout_marginTop="32dp"
android:text="Trust"
android:drawableEnd="@{viewModel.showDevicesTrust ? @drawable/collapse : @drawable/expand, default=@drawable/collapse}"
android:drawableTint="@color/gray_9"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/gray_9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/info_background"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/actions"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="5dp"
android:layout_marginStart="26dp"
android:layout_marginEnd="26dp"
android:layout_marginTop="32dp"
android:text="Other actions"
android:textSize="16sp"
android:textStyle="bold"
android:textColor="@color/gray_9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/trust_label"/>
<ImageView
android:id="@+id/actions_background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="9dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:src="@drawable/shape_round_white_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/actions"
app:layout_constraintBottom_toBottomOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/action_edit"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:gravity="left"
android:text="Edit"
style="@style/context_menu_action_label"
android:drawableLeft="@drawable/edit"
app:layout_constraintTop_toTopOf="@id/actions_background"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:background="@color/blue_outgoing_message"
app:layout_constraintStart_toStartOf="@id/action_edit"
app:layout_constraintEnd_toEndOf="@id/action_edit"
app:layout_constraintTop_toBottomOf="@+id/action_edit"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/action_favorite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:gravity="left"
android:text="Add to favourites"
style="@style/context_menu_action_label"
android:drawableLeft="@drawable/favorite"
app:layout_constraintTop_toBottomOf="@id/action_edit"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:background="@color/blue_outgoing_message"
app:layout_constraintStart_toStartOf="@id/action_favorite"
app:layout_constraintEnd_toEndOf="@id/action_favorite"
app:layout_constraintTop_toBottomOf="@+id/action_favorite"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/action_share"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:gravity="left"
android:text="Share"
style="@style/context_menu_action_label"
android:drawableLeft="@drawable/share"
app:layout_constraintTop_toBottomOf="@id/action_favorite"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:background="@color/blue_outgoing_message"
app:layout_constraintStart_toStartOf="@id/action_share"
app:layout_constraintEnd_toEndOf="@id/action_share"
app:layout_constraintTop_toBottomOf="@+id/action_share"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/action_invite"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:gravity="left"
android:text="Invite"
style="@style/context_menu_action_label"
android:drawableLeft="@drawable/invite"
app:layout_constraintTop_toBottomOf="@id/action_share"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:background="@color/blue_outgoing_message"
app:layout_constraintStart_toStartOf="@id/action_invite"
app:layout_constraintEnd_toEndOf="@id/action_invite"
app:layout_constraintTop_toBottomOf="@+id/action_invite"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/action_delete"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="17dp"
android:layout_marginEnd="17dp"
android:gravity="left"
android:text="Delete"
style="@style/context_menu_danger_action_label"
android:drawableLeft="@drawable/delete"
app:layout_constraintTop_toBottomOf="@id/action_invite"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,82 @@
<?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" />
<import type="android.graphics.Typeface" />
<variable
name="model"
type="org.linphone.ui.contacts.ContactNumberOrAddressData" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/cell_background">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/calls"
app:tint="@color/gray_9"
android:layout_marginStart="10dp"
app:layout_constraintTop_toTopOf="@id/header"
app:layout_constraintBottom_toBottomOf="@id/number_or_address"
app:layout_constraintStart_toStartOf="parent" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginStart="10dp"
android:text="@{model.sip ? `SIP address` : `Phone (` + model.label + `)`, default=`Phone (Home)`}"
android:textColor="@color/gray_9"
android:textStyle="bold"
android:textSize="14sp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toTopOf="parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/number_or_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@{model.displayedValue, default=`sip:johndoe@sip.linphone.org`}"
android:textColor="@color/gray_9"
android:textSize="14sp"
android:maxLines="1"
android:ellipsize="end"
app:layout_constraintStart_toEndOf="@id/icon"
app:layout_constraintTop_toBottomOf="@id/header"/>
<ImageView
android:id="@+id/copy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/copy"
app:tint="@color/gray_9"
android:layout_marginEnd="10dp"
app:layout_constraintTop_toTopOf="@id/header"
app:layout_constraintBottom_toBottomOf="@id/number_or_address"
app:layout_constraintEnd_toEndOf="parent" />
<View
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="10dp"
android:background="@color/blue_outgoing_message"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/number_or_address"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -29,14 +29,10 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Mettre en favoris"
android:padding="20dp"
android:textSize="17sp"
android:textColor="@color/gray_1"
android:gravity="center"
style="@style/context_menu_action_label"
android:background="@color/gray_2"
android:layout_marginBottom="1dp"
android:drawableLeft="@drawable/favorite"
android:drawablePadding="8dp"
app:layout_constraintBottom_toTopOf="@id/share"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
@ -47,14 +43,10 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Partager"
android:padding="20dp"
android:textSize="17sp"
android:textColor="@color/gray_1"
android:gravity="center"
style="@style/context_menu_action_label"
android:background="@color/gray_2"
android:layout_marginBottom="1dp"
android:drawableLeft="@drawable/share"
android:drawablePadding="8dp"
app:layout_constraintBottom_toTopOf="@id/invite"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
@ -65,14 +57,10 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Inviter"
android:padding="20dp"
android:textSize="17sp"
android:textColor="@color/gray_1"
android:gravity="center"
style="@style/context_menu_action_label"
android:background="@color/gray_2"
android:layout_marginBottom="1dp"
android:drawableLeft="@drawable/invite"
android:drawablePadding="8dp"
app:layout_constraintBottom_toTopOf="@id/delete"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
@ -83,14 +71,10 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Supprimer"
android:padding="20dp"
android:textSize="17sp"
android:textColor="@color/red_danger"
android:gravity="center"
style="@style/context_menu_danger_action_label"
android:background="@color/gray_2"
android:layout_marginBottom="1dp"
android:drawableLeft="@drawable/delete"
android:drawablePadding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>

View file

@ -1,4 +1,19 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<style name="context_menu_action_label">
<item name="android:textSize">17sp</item>
<item name="android:textColor">@color/gray_1</item>
<item name="android:gravity">center</item>
<item name="android:padding">20dp</item>
<item name="android:drawableTint">@color/gray_9</item>
<item name="android:drawablePadding">8dp</item>
</style>
<style name="context_menu_danger_action_label">
<item name="android:textSize">17sp</item>
<item name="android:textColor">@color/red_danger</item>
<item name="android:gravity">center</item>
<item name="android:padding">20dp</item>
<item name="android:drawableTint">@color/red_danger</item>
<item name="android:drawablePadding">8dp</item>
</style>
</resources>