mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 03:18:06 +00:00
Added favourites contacts list
This commit is contained in:
parent
f104d5c891
commit
437fa5c128
14 changed files with 275 additions and 65 deletions
|
|
@ -30,6 +30,8 @@ import coil.decode.VideoFrameDecoder
|
|||
import coil.disk.DiskCache
|
||||
import coil.memory.MemoryCache
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import io.getstream.avatarview.coil.AvatarCoil
|
||||
import io.getstream.avatarview.coil.AvatarImageLoaderFactory
|
||||
import org.linphone.core.CoreContext
|
||||
import org.linphone.core.CorePreferences
|
||||
import org.linphone.core.Factory
|
||||
|
|
@ -72,10 +74,17 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
|
|||
coreContext.start()
|
||||
|
||||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
AvatarCoil.setImageLoader(
|
||||
AvatarImageLoaderFactory(context) {
|
||||
newImageLoader()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun newImageLoader(): ImageLoader {
|
||||
return ImageLoader.Builder(this)
|
||||
.crossfade(true)
|
||||
.crossfade(400)
|
||||
.components {
|
||||
add(VideoFrameDecoder.Factory())
|
||||
add(SvgDecoder.Factory())
|
||||
|
|
|
|||
|
|
@ -9,12 +9,14 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.ContactFavouriteListCellBinding
|
||||
import org.linphone.databinding.ContactListCellBinding
|
||||
import org.linphone.ui.contacts.model.ContactModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class ContactsListAdapter(
|
||||
private val viewLifecycleOwner: LifecycleOwner
|
||||
private val viewLifecycleOwner: LifecycleOwner,
|
||||
private val favourites: Boolean
|
||||
) : ListAdapter<ContactModel, RecyclerView.ViewHolder>(ContactDiffCallback()) {
|
||||
var selectedAdapterPosition = -1
|
||||
|
||||
|
|
@ -27,17 +29,31 @@ class ContactsListAdapter(
|
|||
}
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||
val binding: ContactListCellBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
R.layout.contact_list_cell,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return ViewHolder(binding)
|
||||
if (favourites) {
|
||||
val binding: ContactFavouriteListCellBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
R.layout.contact_favourite_list_cell,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return FavouriteViewHolder(binding)
|
||||
} else {
|
||||
val binding: ContactListCellBinding = DataBindingUtil.inflate(
|
||||
LayoutInflater.from(parent.context),
|
||||
R.layout.contact_list_cell,
|
||||
parent,
|
||||
false
|
||||
)
|
||||
return ViewHolder(binding)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
||||
(holder as ViewHolder).bind(getItem(position))
|
||||
if (favourites) {
|
||||
(holder as FavouriteViewHolder).bind(getItem(position))
|
||||
} else {
|
||||
(holder as ViewHolder).bind(getItem(position))
|
||||
}
|
||||
}
|
||||
|
||||
fun resetSelection() {
|
||||
|
|
@ -45,29 +61,39 @@ class ContactsListAdapter(
|
|||
selectedAdapterPosition = -1
|
||||
}
|
||||
|
||||
fun showHeaderForPosition(position: Int): Boolean {
|
||||
if (position >= itemCount) return false
|
||||
|
||||
val contact = getItem(position)
|
||||
val firstLetter = contact.name.value?.get(0).toString()
|
||||
val previousPosition = position - 1
|
||||
|
||||
return if (previousPosition >= 0) {
|
||||
val previousItemFirstLetter = getItem(previousPosition).name.value?.get(0).toString()
|
||||
!firstLetter.equals(previousItemFirstLetter, ignoreCase = true)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
inner class ViewHolder(
|
||||
val binding: ContactListCellBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(contactModel: ContactModel) {
|
||||
with(binding) {
|
||||
model = contactModel
|
||||
firstLetter = contactModel.name.value?.get(0).toString()
|
||||
showFirstLetter = showHeaderForPosition(bindingAdapterPosition)
|
||||
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
binding.root.isSelected = bindingAdapterPosition == selectedAdapterPosition
|
||||
|
||||
binding.setOnClickListener {
|
||||
contactClickedEvent.value = Event(contactModel)
|
||||
}
|
||||
|
||||
binding.setOnLongClickListener {
|
||||
selectedAdapterPosition = bindingAdapterPosition
|
||||
binding.root.isSelected = true
|
||||
contactLongClickedEvent.value = Event(contactModel)
|
||||
true
|
||||
}
|
||||
|
||||
executePendingBindings()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class FavouriteViewHolder(
|
||||
val binding: ContactFavouriteListCellBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
fun bind(contactModel: ContactModel) {
|
||||
with(binding) {
|
||||
model = contactModel
|
||||
|
||||
lifecycleOwner = viewLifecycleOwner
|
||||
|
||||
|
|
@ -96,6 +122,6 @@ private class ContactDiffCallback : DiffUtil.ItemCallback<ContactModel>() {
|
|||
}
|
||||
|
||||
override fun areContentsTheSame(oldItem: ContactModel, newItem: ContactModel): Boolean {
|
||||
return true
|
||||
return oldItem.showFirstLetter.value == newItem.showFirstLetter.value
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ class ContactsListFragment : Fragment() {
|
|||
)
|
||||
|
||||
private lateinit var adapter: ContactsListAdapter
|
||||
private lateinit var favouritesAdapter: ContactsListAdapter
|
||||
|
||||
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
|
||||
if (findNavController().currentDestination?.id == R.id.newContactFragment) {
|
||||
|
|
@ -89,28 +90,23 @@ class ContactsListFragment : Fragment() {
|
|||
listViewModel.bottomNavBarVisible.value = !portraitOrientation || !keyboardVisible
|
||||
}
|
||||
|
||||
adapter = ContactsListAdapter(viewLifecycleOwner)
|
||||
adapter = ContactsListAdapter(viewLifecycleOwner, false)
|
||||
binding.contactsList.setHasFixedSize(true)
|
||||
binding.contactsList.adapter = adapter
|
||||
|
||||
adapter.contactLongClickedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { model ->
|
||||
val modalBottomSheet = ContactsListMenuDialogFragment(model.friend) {
|
||||
adapter.resetSelection()
|
||||
}
|
||||
modalBottomSheet.show(parentFragmentManager, ContactsListMenuDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
adapter.contactClickedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { model ->
|
||||
sharedViewModel.showContactEvent.value = Event(model.id ?: "")
|
||||
}
|
||||
}
|
||||
configureAdapter(adapter)
|
||||
|
||||
val layoutManager = LinearLayoutManager(requireContext())
|
||||
binding.contactsList.layoutManager = layoutManager
|
||||
|
||||
favouritesAdapter = ContactsListAdapter(viewLifecycleOwner, true)
|
||||
binding.favouritesContactsList.setHasFixedSize(true)
|
||||
binding.favouritesContactsList.adapter = favouritesAdapter
|
||||
configureAdapter(favouritesAdapter)
|
||||
|
||||
val favouritesLayoutManager = LinearLayoutManager(requireContext())
|
||||
favouritesLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
|
||||
binding.favouritesContactsList.layoutManager = favouritesLayoutManager
|
||||
|
||||
listViewModel.contactsList.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
|
|
@ -121,6 +117,12 @@ class ContactsListFragment : Fragment() {
|
|||
}
|
||||
}
|
||||
|
||||
listViewModel.favourites.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
favouritesAdapter.submitList(it)
|
||||
}
|
||||
|
||||
listViewModel.focusSearchBarEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { show ->
|
||||
if (show) {
|
||||
|
|
@ -154,4 +156,21 @@ class ContactsListFragment : Fragment() {
|
|||
(requireActivity() as MainActivity).toggleDrawerMenu()
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureAdapter(adapter: ContactsListAdapter) {
|
||||
adapter.contactLongClickedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { model ->
|
||||
val modalBottomSheet = ContactsListMenuDialogFragment(model.friend) {
|
||||
adapter.resetSelection()
|
||||
}
|
||||
modalBottomSheet.show(parentFragmentManager, ContactsListMenuDialogFragment.TAG)
|
||||
}
|
||||
}
|
||||
|
||||
adapter.contactClickedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { model ->
|
||||
sharedViewModel.showContactEvent.value = Event(model.id ?: "")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ class ContactModel(val friend: Friend) {
|
|||
|
||||
val name = MutableLiveData<String>()
|
||||
|
||||
val firstLetter: String by lazy {
|
||||
LinphoneUtils.getFirstLetter(friend.name.orEmpty())
|
||||
}
|
||||
|
||||
val showFirstLetter = MutableLiveData<Boolean>()
|
||||
|
||||
private val friendListener = object : FriendListenerStub() {
|
||||
override fun onPresenceReceived(fr: Friend) {
|
||||
presenceStatus.postValue(fr.consolidatedPresence)
|
||||
|
|
|
|||
|
|
@ -34,6 +34,10 @@ import org.linphone.ui.viewmodel.TopBarViewModel
|
|||
class ContactsListViewModel : TopBarViewModel() {
|
||||
val contactsList = MutableLiveData<ArrayList<ContactModel>>()
|
||||
|
||||
val favourites = MutableLiveData<ArrayList<ContactModel>>()
|
||||
|
||||
val showFavourites = MutableLiveData<Boolean>()
|
||||
|
||||
private var currentFilter = ""
|
||||
private var previousFilter = "NotSet"
|
||||
|
||||
|
|
@ -57,6 +61,7 @@ class ContactsListViewModel : TopBarViewModel() {
|
|||
init {
|
||||
title.value = "Contacts"
|
||||
bottomNavBarVisible.value = true
|
||||
showFavourites.value = true
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
coreContext.contactsManager.addListener(contactsListener)
|
||||
|
|
@ -75,28 +80,48 @@ class ContactsListViewModel : TopBarViewModel() {
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
fun toggleFavouritesVisibility() {
|
||||
// UI thread
|
||||
showFavourites.value = showFavourites.value == false
|
||||
}
|
||||
|
||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
// Core thread
|
||||
Log.i("[Contacts List] Processing ${results.size} results")
|
||||
contactsList.value.orEmpty().forEach(ContactModel::destroy)
|
||||
|
||||
val list = arrayListOf<ContactModel>()
|
||||
val favouritesList = arrayListOf<ContactModel>()
|
||||
var previousLetter = ""
|
||||
|
||||
for (result in results) {
|
||||
val friend = result.friend
|
||||
|
||||
val viewModel = if (friend != null) {
|
||||
var currentLetter = ""
|
||||
val model = if (friend != null) {
|
||||
currentLetter = friend.name?.get(0).toString()
|
||||
ContactModel(friend)
|
||||
} else {
|
||||
Log.w("[Contacts] SearchResult [$result] has no Friend!")
|
||||
val fakeFriend =
|
||||
createFriendFromSearchResult(result)
|
||||
currentLetter = fakeFriend.name?.get(0).toString()
|
||||
ContactModel(fakeFriend)
|
||||
}
|
||||
|
||||
list.add(viewModel)
|
||||
val displayLetter = previousLetter.isEmpty() || currentLetter != previousLetter
|
||||
if (currentLetter != previousLetter) {
|
||||
previousLetter = currentLetter
|
||||
}
|
||||
model.showFirstLetter.postValue(displayLetter)
|
||||
|
||||
list.add(model)
|
||||
if (friend?.starred == true) {
|
||||
favouritesList.add(model)
|
||||
}
|
||||
}
|
||||
|
||||
favourites.postValue(favouritesList)
|
||||
contactsList.postValue(list)
|
||||
|
||||
Log.i("[Contacts] Processed ${results.size} results")
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ abstract class TopBarViewModel : ViewModel() {
|
|||
|
||||
fun closeSearchBar() {
|
||||
// UI thread
|
||||
clearFilter()
|
||||
searchBarVisible.value = false
|
||||
focusSearchBarEvent.value = Event(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ fun AvatarView.loadContactPicture(contact: ContactModel?) {
|
|||
ConsolidatedPresence.Online -> R.color.green_online
|
||||
else -> R.color.blue_outgoing_message
|
||||
}
|
||||
indicatorEnabled = true
|
||||
indicatorEnabled = contact.presenceStatus.value != ConsolidatedPresence.Offline
|
||||
|
||||
val uri = contact.getAvatarUri()
|
||||
loadImage(
|
||||
|
|
|
|||
|
|
@ -47,6 +47,10 @@ class LinphoneUtils {
|
|||
}
|
||||
}
|
||||
|
||||
fun getFirstLetter(displayName: String): String {
|
||||
return getInitials(displayName, 1)
|
||||
}
|
||||
|
||||
fun getInitials(displayName: String, limit: Int = 2): String {
|
||||
if (displayName.isEmpty()) return ""
|
||||
|
||||
|
|
|
|||
13
app/src/main/res/drawable/collapse.xml
Normal file
13
app/src/main/res/drawable/collapse.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<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">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 7.41 16.41 L 12 11.83 L 16.59 16.41 L 18 15 L 12 9 L 6 15 L 7.41 16.41 Z"
|
||||
android:fillColor="#4e6074"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/expand.xml
Normal file
17
app/src/main/res/drawable/expand.xml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<rotate
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fromDegrees="180"
|
||||
android:toDegrees="180">
|
||||
<vector
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 7.41 16.41 L 12 11.83 L 16.59 16.41 L 18 15 L 12 9 L 6 15 L 7.41 16.41 Z"
|
||||
android:fillColor="#4e6074"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
</rotate>
|
||||
|
|
@ -94,6 +94,53 @@
|
|||
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_contacts_image" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/favourites_label"
|
||||
android:visibility="@{viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
onClickListener="@{() -> viewModel.toggleFavouritesVisibility()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="Favourites"
|
||||
android:drawableEnd="@drawable/collapse"
|
||||
android:drawableTint="@color/gray_9"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/gray_9"
|
||||
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/background"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/favourites_contacts_list"
|
||||
android:visibility="@{viewModel.showFavourites && viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintTop_toBottomOf="@id/favourites_label" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/all_contacts_label"
|
||||
android:visibility="@{viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="All contacts"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/gray_9"
|
||||
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/favourites_contacts_list"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/contactsList"
|
||||
android:layout_width="0dp"
|
||||
|
|
@ -103,7 +150,7 @@
|
|||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/background"
|
||||
app:layout_constraintTop_toBottomOf="@id/all_contacts_label"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
|
|
|
|||
|
|
@ -21,16 +21,13 @@
|
|||
android:onLongClick="@{onLongClickListener}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/cell_background">
|
||||
|
||||
<io.getstream.avatarview.AvatarView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="72dp"
|
||||
android:layout_height="72dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:adjustViewBounds="true"
|
||||
contactAvatar="@{model}"
|
||||
app:avatarViewPlaceholder="@drawable/contact_avatar"
|
||||
|
|
@ -53,12 +50,15 @@
|
|||
android:id="@+id/name"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="@{model.name, default=`John Doe`}"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_9"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/avatar"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
|
|||
|
|
@ -9,12 +9,6 @@
|
|||
<variable
|
||||
name="model"
|
||||
type="org.linphone.ui.contacts.model.ContactModel" />
|
||||
<variable
|
||||
name="first_letter"
|
||||
type="String" />
|
||||
<variable
|
||||
name="show_first_letter"
|
||||
type="Boolean" />
|
||||
<variable
|
||||
name="onClickListener"
|
||||
type="View.OnClickListener" />
|
||||
|
|
@ -36,8 +30,8 @@
|
|||
android:id="@+id/header"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@{first_letter, default=`A`}"
|
||||
android:visibility="@{show_first_letter ? View.VISIBLE : View.INVISIBLE, default=invisible}"
|
||||
android:text="@{model.firstLetter, default=`A`}"
|
||||
android:visibility="@{model.showFirstLetter ? View.VISIBLE : View.INVISIBLE, default=invisible}"
|
||||
android:textColor="@color/gray_10"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@
|
|||
android:layout_height="0dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:src="@drawable/shape_white_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/top_bar" />
|
||||
|
|
@ -76,6 +76,55 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/no_contacts_image" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/favourites_label"
|
||||
android:visibility="@{viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
onClickListener="@{() -> viewModel.toggleFavouritesVisibility()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:text="Favourites"
|
||||
android:drawableEnd="@{viewModel.showFavourites ? @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_toTopOf="@id/background"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/favourites_contacts_list"
|
||||
android:visibility="@{viewModel.showFavourites && viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginTop="5dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/favourites_label" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatTextView
|
||||
android:id="@+id/all_contacts_label"
|
||||
android:visibility="@{viewModel.searchFilter.length() == 0 ? View.VISIBLE : View.GONE}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="5dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:text="All contacts"
|
||||
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/favourites_contacts_list"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/contactsList"
|
||||
android:layout_width="0dp"
|
||||
|
|
@ -85,8 +134,8 @@
|
|||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/background"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:layout_constraintTop_toBottomOf="@id/all_contacts_label"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar" />
|
||||
|
||||
<include
|
||||
bind:onConversationsClicked="@{onConversationsClicked}"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue