diff --git a/app/src/main/java/org/linphone/contacts/ContactLoader.kt b/app/src/main/java/org/linphone/contacts/ContactLoader.kt index 4db74b3dd..aa1459224 100644 --- a/app/src/main/java/org/linphone/contacts/ContactLoader.kt +++ b/app/src/main/java/org/linphone/contacts/ContactLoader.kt @@ -54,13 +54,14 @@ class ContactLoader : LoaderManager.LoaderCallbacks { override fun onCreateLoader(id: Int, args: Bundle?): Loader { 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.getColumnIndexOrThrow(ContactsContract.Contacts.STARRED) ) == 1 friend.starred = starred + val lookupKey = cursor.getString( cursor.getColumnIndexOrThrow( @@ -227,6 +229,24 @@ class ContactLoader : LoaderManager.LoaderCallbacks { } } } + 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 diff --git a/app/src/main/java/org/linphone/ui/contacts/ContactNumberOrAddressData.kt b/app/src/main/java/org/linphone/ui/contacts/ContactNumberOrAddressData.kt new file mode 100644 index 000000000..0c35ae701 --- /dev/null +++ b/app/src/main/java/org/linphone/ui/contacts/ContactNumberOrAddressData.kt @@ -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 . + */ +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) +} diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt index 2ad646194..f64f883c9 100644 --- a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt +++ b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt @@ -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) } } } diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt index cab1df8e6..f1c48883d 100644 --- a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt +++ b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt @@ -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() - } } } diff --git a/app/src/main/java/org/linphone/ui/contacts/viewmodel/ContactViewModel.kt b/app/src/main/java/org/linphone/ui/contacts/viewmodel/ContactViewModel.kt index 977e83ca4..6cf40f4b0 100644 --- a/app/src/main/java/org/linphone/ui/contacts/viewmodel/ContactViewModel.kt +++ b/app/src/main/java/org/linphone/ui/contacts/viewmodel/ContactViewModel.kt @@ -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() + val sipAddressesAndPhoneNumbers = MutableLiveData>() + + val company = MutableLiveData() + val showBackButton = MutableLiveData() + val showNumbersAndAddresses = MutableLiveData() + + val showCompany = MutableLiveData() + + val showDevicesTrust = MutableLiveData() + + val friendFoundEvent = MutableLiveData>() + + 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() + 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 + } } diff --git a/app/src/main/java/org/linphone/ui/viewmodel/SharedMainViewModel.kt b/app/src/main/java/org/linphone/ui/viewmodel/SharedMainViewModel.kt index 1843a6c85..3e88bf773 100644 --- a/app/src/main/java/org/linphone/ui/viewmodel/SharedMainViewModel.kt +++ b/app/src/main/java/org/linphone/ui/viewmodel/SharedMainViewModel.kt @@ -30,6 +30,8 @@ class SharedMainViewModel : ViewModel() { val closeSlidingPaneEvent = MutableLiveData>() + val openSlidingPaneEvent = MutableLiveData>() + val navigateToConversationsEvent = MutableLiveData>() val navigateToCallsEvent = MutableLiveData>() diff --git a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt index 98cbc6b6d..badf43472 100644 --- a/app/src/main/java/org/linphone/utils/DataBindingUtils.kt +++ b/app/src/main/java/org/linphone/utils/DataBindingUtils.kt @@ -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 setEntries( + viewGroup: ViewGroup, + entries: List?, + 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( + 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 diff --git a/app/src/main/res/drawable/copy.xml b/app/src/main/res/drawable/copy.xml new file mode 100644 index 000000000..4ca7f95fa --- /dev/null +++ b/app/src/main/res/drawable/copy.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/app/src/main/res/drawable/shape_round_white_background.xml b/app/src/main/res/drawable/shape_round_white_background.xml new file mode 100644 index 000000000..706ef93e2 --- /dev/null +++ b/app/src/main/res/drawable/shape_round_white_background.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/contact_fragment.xml b/app/src/main/res/layout/contact_fragment.xml index e183e6517..74a99c4cf 100644 --- a/app/src/main/res/layout/contact_fragment.xml +++ b/app/src/main/res/layout/contact_fragment.xml @@ -4,6 +4,7 @@ + @@ -15,7 +16,17 @@ + android:background="@drawable/shape_gray_background"> + + - - - + app:layout_constraintTop_toBottomOf="@id/edit" + app:layout_constraintBottom_toBottomOf="parent"> - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/contact_number_address_list_cell.xml b/app/src/main/res/layout/contact_number_address_list_cell.xml new file mode 100644 index 000000000..c28efe7f0 --- /dev/null +++ b/app/src/main/res/layout/contact_number_address_list_cell.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/contacts_list_long_press_menu.xml b/app/src/main/res/layout/contacts_list_long_press_menu.xml index ff868a8f5..b3a57fc73 100644 --- a/app/src/main/res/layout/contacts_list_long_press_menu.xml +++ b/app/src/main/res/layout/contacts_list_long_press_menu.xml @@ -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"/> diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 30f2574f5..b931bf6c5 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,4 +1,19 @@ - + +