Changes to use shared main view model for sliding pane state

This commit is contained in:
Sylvain Berfini 2023-08-04 13:54:20 +02:00
parent f3233528d6
commit bb22845b54
22 changed files with 330 additions and 225 deletions

View file

@ -7,11 +7,11 @@
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="1A051FDEE005XG" />
<value value="R5CNA03EXMM" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2023-08-04T10:20:13.247754228Z" />
<timeTargetWasSelectedWithDropDown value="2023-08-04T11:43:29.149882171Z" />
</component>
</project>

View file

@ -21,6 +21,7 @@ package org.linphone.contacts
import androidx.loader.app.LoaderManager
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.core.Friend
import org.linphone.ui.MainActivity
class ContactsManager {
@ -55,6 +56,10 @@ class ContactsManager {
}
}
fun findContactById(id: String): Friend? {
return coreContext.core.defaultFriendList?.findFriendByRefKey(id)
}
fun onCoreStarted() {
}

View file

@ -25,13 +25,24 @@ import android.view.View
import android.view.ViewGroup
import androidx.core.view.doOnPreDraw
import androidx.fragment.app.Fragment
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.viewmodel.SharedMainViewModel
class ContactFragment : Fragment() {
private lateinit var binding: ContactFragmentBinding
private lateinit var sharedViewModel: SharedMainViewModel
private val viewModel: ContactViewModel by navGraphViewModels(
R.id.contactFragment
)
private val args: ContactFragmentArgs by navArgs()
override fun onCreate(savedInstanceState: Bundle?) {
@ -45,6 +56,11 @@ class ContactFragment : Fragment() {
savedInstanceState: Bundle?
): View {
binding = ContactFragmentBinding.inflate(layoutInflater)
sharedViewModel = requireActivity().run {
ViewModelProvider(this)[SharedMainViewModel::class.java]
}
return binding.root
}
@ -54,16 +70,23 @@ class ContactFragment : Fragment() {
postponeEnterTransition()
binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = viewModel
val model = args.contact
binding.model = model
val refKey = args.contactRefKey
viewModel.findContactByRefKey(refKey)
binding.setBackClickListener {
requireActivity().onBackPressedDispatcher.onBackPressed()
}
(view.parent as? ViewGroup)?.doOnPreDraw {
startPostponedEnterTransition()
sharedViewModel.isSlidingPaneSlideable.observe(viewLifecycleOwner) { slideable ->
viewModel.showBackButton.value = slideable
}
viewModel.contact.observe(viewLifecycleOwner) {
(view.parent as? ViewGroup)?.doOnPreDraw {
startPostponedEnterTransition()
}
}
}
}

View file

@ -28,6 +28,7 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.core.view.doOnPreDraw
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.fragment.findNavController
@ -40,6 +41,7 @@ import org.linphone.databinding.ContactsFragmentBinding
import org.linphone.ui.MainActivity
import org.linphone.ui.contacts.adapter.ContactsListAdapter
import org.linphone.ui.contacts.viewmodel.ContactsListViewModel
import org.linphone.ui.viewmodel.SharedMainViewModel
import org.linphone.utils.SlidingPaneBackPressedCallback
import org.linphone.utils.hideKeyboard
import org.linphone.utils.setKeyboardInsetListener
@ -47,9 +49,13 @@ import org.linphone.utils.showKeyboard
class ContactsFragment : Fragment() {
private lateinit var binding: ContactsFragmentBinding
private lateinit var sharedViewModel: SharedMainViewModel
private val listViewModel: ContactsListViewModel by navGraphViewModels(
R.id.contactsFragment
)
private lateinit var adapter: ContactsListAdapter
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
@ -67,6 +73,11 @@ class ContactsFragment : Fragment() {
): View {
binding = ContactsFragmentBinding.inflate(layoutInflater)
sharedElementEnterTransition = AutoTransition()
sharedViewModel = requireActivity().run {
ViewModelProvider(this)[SharedMainViewModel::class.java]
}
return binding.root
}
@ -85,16 +96,20 @@ class ContactsFragment : Fragment() {
binding.root.doOnPreDraw {
val slidingPane = binding.slidingPaneLayout
sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable
requireActivity().onBackPressedDispatcher.addCallback(
viewLifecycleOwner,
SlidingPaneBackPressedCallback(slidingPane)
)
slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED
}
adapter = ContactsListAdapter(viewLifecycleOwner)
binding.contactsList.setHasFixedSize(true)
binding.contactsList.adapter = adapter
binding.contactsView.contactsList.setHasFixedSize(true)
binding.contactsView.contactsList.adapter = adapter
adapter.contactLongClickedEvent.observe(viewLifecycleOwner) {
it.consume { model ->
@ -106,15 +121,14 @@ class ContactsFragment : Fragment() {
}
adapter.contactClickedEvent.observe(viewLifecycleOwner) {
it.consume { pair ->
val b = pair.first
val model = pair.second
it.consume { model ->
if (findNavController().currentDestination?.id == R.id.contactsFragment) {
val navHostFragment = childFragmentManager.findFragmentById(
R.id.contacts_nav_container
) as NavHostFragment
val action = ContactFragmentDirections.actionGlobalContactFragment(model)
val action = ContactFragmentDirections.actionGlobalContactFragment(
model.id ?: ""
)
navHostFragment.navController.navigate(action)
if (!binding.slidingPaneLayout.isOpen) {
@ -125,7 +139,7 @@ class ContactsFragment : Fragment() {
}
val layoutManager = LinearLayoutManager(requireContext())
binding.contactsList.layoutManager = layoutManager
binding.contactsView.contactsList.layoutManager = layoutManager
listViewModel.contactsList.observe(
viewLifecycleOwner
@ -156,13 +170,7 @@ class ContactsFragment : Fragment() {
binding.setOnNewContactClicked {
if (findNavController().currentDestination?.id == R.id.contactsFragment) {
val navHostFragment =
childFragmentManager.findFragmentById(R.id.contacts_nav_container) as NavHostFragment?
if (navHostFragment != null) {
navHostFragment.navController.navigate(R.id.action_global_newContactFragment)
} else {
findNavController().navigate(R.id.action_contactsFragment_to_newContactFragment)
}
findNavController().navigate(R.id.action_contactsFragment_to_newContactFragment)
}
}

View file

@ -18,8 +18,8 @@ class ContactsListAdapter(
) : ListAdapter<ContactModel, RecyclerView.ViewHolder>(ContactDiffCallback()) {
var selectedAdapterPosition = -1
val contactClickedEvent: MutableLiveData<Event<Pair<ContactListCellBinding, ContactModel>>> by lazy {
MutableLiveData<Event<Pair<ContactListCellBinding, ContactModel>>>()
val contactClickedEvent: MutableLiveData<Event<ContactModel>> by lazy {
MutableLiveData<Event<ContactModel>>()
}
val contactLongClickedEvent: MutableLiveData<Event<ContactModel>> by lazy {
@ -74,7 +74,7 @@ class ContactsListAdapter(
binding.root.isSelected = bindingAdapterPosition == selectedAdapterPosition
binding.setOnClickListener {
contactClickedEvent.value = Event(Pair(binding, contactModel))
contactClickedEvent.value = Event(contactModel)
}
binding.setOnLongClickListener {

View file

@ -23,13 +23,12 @@ import android.content.ContentUris
import android.net.Uri
import android.provider.ContactsContract
import androidx.lifecycle.MutableLiveData
import java.io.Serializable
import org.linphone.core.ConsolidatedPresence
import org.linphone.core.Friend
import org.linphone.core.FriendListenerStub
import org.linphone.utils.LinphoneUtils
class ContactModel(val friend: Friend) : Serializable {
class ContactModel(val friend: Friend) {
val id = friend.refKey
val initials = LinphoneUtils.getInitials(friend.name.orEmpty())

View file

@ -0,0 +1,44 @@
/*
* 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.contacts.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.ui.contacts.model.ContactModel
class ContactViewModel : ViewModel() {
val contact = MutableLiveData<ContactModel>()
val showBackButton = MutableLiveData<Boolean>()
init {
}
fun findContactByRefKey(refKey: String) {
// UI thread
coreContext.postOnCoreThread {
val friend = coreContext.contactsManager.findContactById(refKey)
if (friend != null) {
contact.postValue(ContactModel(friend))
}
}
}
}

View file

@ -27,8 +27,8 @@ import org.linphone.core.Friend
import org.linphone.core.MagicSearch
import org.linphone.core.SearchResult
import org.linphone.core.tools.Log
import org.linphone.ui.TopBarViewModel
import org.linphone.ui.contacts.model.ContactModel
import org.linphone.ui.viewmodel.TopBarViewModel
class ContactsListViewModel : TopBarViewModel() {
val bottomNavBarVisible = MutableLiveData<Boolean>()

View file

@ -29,8 +29,8 @@ import org.linphone.core.Core
import org.linphone.core.CoreListenerStub
import org.linphone.core.SearchResult
import org.linphone.core.tools.Log
import org.linphone.ui.TopBarViewModel
import org.linphone.ui.conversations.data.ChatRoomData
import org.linphone.ui.viewmodel.TopBarViewModel
import org.linphone.utils.Event
import org.linphone.utils.LinphoneUtils

View file

@ -0,0 +1,27 @@
/*
* 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.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
class SharedMainViewModel : ViewModel() {
val isSlidingPaneSlideable = MutableLiveData<Boolean>()
}

View file

@ -17,7 +17,7 @@
* 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
package org.linphone.ui.viewmodel
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

View file

@ -22,7 +22,6 @@ package org.linphone.utils
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.slidingpanelayout.widget.SlidingPaneLayout
import org.linphone.core.tools.Log
class SlidingPaneBackPressedCallback(private val slidingPaneLayout: SlidingPaneLayout) :
OnBackPressedCallback(
@ -31,25 +30,19 @@ class SlidingPaneBackPressedCallback(private val slidingPaneLayout: SlidingPaneL
SlidingPaneLayout.PanelSlideListener {
init {
Log.d(
"[Master Fragment] SlidingPane isSlideable = ${slidingPaneLayout.isSlideable}, isOpen = ${slidingPaneLayout.isOpen}"
)
slidingPaneLayout.addPanelSlideListener(this)
}
override fun handleOnBackPressed() {
Log.d("[Master Fragment] handleOnBackPressed, closing sliding pane")
slidingPaneLayout.hideKeyboard()
slidingPaneLayout.closePane()
}
override fun onPanelOpened(panel: View) {
Log.d("[Master Fragment] onPanelOpened")
isEnabled = true
}
override fun onPanelClosed(panel: View) {
Log.d("[Master Fragment] onPanelClosed")
isEnabled = false
}

View file

@ -43,6 +43,8 @@
android:gravity="center"
android:onClick="@{onContactsClicked}"
android:text="Contacts"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/gray_9"
android:textSize="11sp"
android:textStyle="@{contactsSelected ? Typeface.BOLD : Typeface.NORMAL}"
@ -60,6 +62,8 @@
android:drawableTint="@{callsSelected ? @color/primary_color : @color/gray_9, default=@color/gray_9}"
android:gravity="center"
android:text="Calls"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/gray_9"
android:textSize="11sp"
android:textStyle="@{callsSelected ? Typeface.BOLD : Typeface.NORMAL}"
@ -78,6 +82,8 @@
android:gravity="center"
android:onClick="@{onConversationsClicked}"
android:text="Conversations"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/gray_9"
android:textSize="11sp"
android:textStyle="@{conversationsSelected ? Typeface.BOLD : Typeface.NORMAL}"
@ -95,6 +101,8 @@
android:drawableTint="@{meetingsSelected ? @color/primary_color : @color/gray_9, default=@color/gray_9}"
android:gravity="center"
android:text="Meetings"
android:maxLines="1"
android:ellipsize="end"
android:textColor="@color/gray_9"
android:textSize="11sp"
android:textStyle="@{meetingsSelected ? Typeface.BOLD : Typeface.NORMAL}"

View file

@ -19,122 +19,88 @@
type="org.linphone.ui.contacts.viewmodel.ContactsListViewModel" />
</data>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
android:id="@+id/sliding_pane_layout"
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="355dp"
android:layout_height="match_parent"
android:background="@color/primary_color">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="no_contacts_image, no_contacts_label"
android:visibility="@{viewModel.contactsList.empty ? View.VISIBLE : View.GONE}" />
<include
android:id="@+id/top_bar"
bind:viewModel="@{viewModel}"
bind:onAvatarClickListener="@{onAvatarClickListener}"
layout="@layout/top_search_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="7dp"
android:src="@drawable/shape_white_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintTop_toBottomOf="@id/top_bar" />
<ImageView
android:id="@+id/no_contacts_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@drawable/illu"
android:layout_margin="10dp"
app:layout_constraintHeight_max="200dp"
app:layout_constraintBottom_toTopOf="@id/no_contacts_label"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintTop_toBottomOf="@id/background" />
<TextView
android:id="@+id/no_contacts_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No contacts for the moment..."
android:textColor="@color/gray_9"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintTop_toBottomOf="@id/no_contacts_image" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
android:layout_marginStart="10dp"
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_constraintBottom_toBottomOf="parent" />
<include
bind:onConversationsClicked="@{onConversationsClicked}"
bind:contactsSelected="@{true}"
android:visibility="@{viewModel.bottomNavBarVisible ? View.VISIBLE : View.GONE}"
android:id="@+id/bottom_nav_bar"
layout="@layout/bottom_nav_bar"
android:layout_width="75dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/new_contact"
android:onClick="@{onNewContactClicked}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="@drawable/add"
app:tint="@color/gray_8"
app:backgroundTint="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/contacts_nav_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="false"
app:navGraph="@navigation/chat_nav_graph"
<include
bind:onConversationsClicked="@{onConversationsClicked}"
bind:contactsSelected="@{true}"
android:visibility="@{viewModel.bottomNavBarVisible ? View.VISIBLE : View.GONE}"
android:id="@+id/bottom_nav_bar"
layout="@layout/bottom_nav_bar"
android:layout_width="75dp"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/contactsList"
app:layout_constraintBottom_toBottomOf="parent"/>
<include
android:id="@+id/top_bar"
bind:viewModel="@{viewModel}"
bind:onAvatarClickListener="@{onAvatarClickListener}"
layout="@layout/top_search_bar"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
android:id="@+id/sliding_pane_layout"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="280dp"
android:layout_height="match_parent"
android:background="@color/primary_color">
<include
android:id="@+id/contacts_view"
layout="@layout/contacts_list_fragment"
bind:viewModel="@{viewModel}"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/new_contact"
android:onClick="@{onNewContactClicked}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="@drawable/add"
app:tint="@color/gray_8"
app:backgroundTint="@color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/contacts_nav_container"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="false"
app:navGraph="@navigation/contact_nav_graph"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/contactsList"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -43,6 +43,8 @@
android:drawableTop="@drawable/contacts"
android:drawablePadding="10dp"
android:text="Contacts"
android:maxLines="1"
android:ellipsize="end"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/gray_9"
@ -63,6 +65,8 @@
android:drawableTop="@drawable/calls"
android:drawablePadding="10dp"
android:text="Calls"
android:maxLines="1"
android:ellipsize="end"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/gray_9"
@ -84,6 +88,8 @@
android:drawableTop="@drawable/conversations"
android:drawablePadding="10dp"
android:text="Conversations"
android:maxLines="1"
android:ellipsize="end"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/gray_9"
@ -104,6 +110,8 @@
android:drawableTop="@drawable/meetings"
android:drawablePadding="10dp"
android:text="Meetings"
android:maxLines="1"
android:ellipsize="end"
android:textSize="11sp"
android:gravity="center"
android:textColor="@color/gray_9"

View file

@ -8,8 +8,8 @@
name="backClickListener"
type="View.OnClickListener" />
<variable
name="model"
type="org.linphone.ui.contacts.model.ContactModel" />
name="viewModel"
type="org.linphone.ui.contacts.viewmodel.ContactViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
@ -24,6 +24,7 @@
android:layout_marginStart="10dp"
android:layout_marginTop="17dp"
android:onClick="@{backClickListener}"
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.GONE}"
android:padding="1dp"
android:src="@drawable/back"
app:layout_constraintStart_toStartOf="parent"
@ -57,7 +58,7 @@
android:layout_height="72dp"
android:layout_marginTop="38dp"
android:adjustViewBounds="true"
contactAvatar="@{model}"
contactAvatar="@{viewModel.contact}"
app:avatarViewBorderWidth="0dp"
app:avatarViewIndicatorBorderColor="@color/white"
app:avatarViewIndicatorBorderSizeCriteria="8"
@ -79,7 +80,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@{model.name, default=`John Doe`}"
android:text="@{viewModel.contact.name, default=`John Doe`}"
android:textColor="@color/gray_8"
android:textSize="14sp"
app:layout_constraintEnd_toEndOf="parent"

View file

@ -29,66 +29,22 @@
android:layout_height="match_parent"
android:background="@color/primary_color">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="no_contacts_image, no_contacts_label"
android:visibility="@{viewModel.contactsList.empty ? View.VISIBLE : View.GONE}" />
<include
android:id="@+id/top_bar"
bind:viewModel="@{viewModel}"
bind:onAvatarClickListener="@{onAvatarClickListener}"
layout="@layout/top_search_bar" />
<ImageView
android:id="@+id/background"
<include
android:id="@+id/contacts_view"
layout="@layout/contacts_list_fragment"
bind:viewModel="@{viewModel}"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="7dp"
android:src="@drawable/shape_white_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/top_bar" />
<ImageView
android:id="@+id/no_contacts_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@drawable/illu"
android:layout_margin="10dp"
app:layout_constraintHeight_max="200dp"
app:layout_constraintBottom_toTopOf="@id/no_contacts_label"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/background" />
<TextView
android:id="@+id/no_contacts_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No contacts for the moment..."
android:textColor="@color/gray_9"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/no_contacts_image" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/background"
app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar" />
app:layout_constraintTop_toBottomOf="@id/top_bar"
app:layout_constraintBottom_toTopOf="@id/bottom_nav_bar"
app:layout_constraintEnd_toEndOf="parent"/>
<include
bind:onConversationsClicked="@{onConversationsClicked}"
@ -124,7 +80,7 @@
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="false"
app:navGraph="@navigation/chat_nav_graph"/>
app:navGraph="@navigation/contact_nav_graph"/>
</androidx.slidingpanelayout.widget.SlidingPaneLayout>

View file

@ -0,0 +1,75 @@
<?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="viewModel"
type="org.linphone.ui.contacts.viewmodel.ContactsListViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/primary_color">
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="no_contacts_image, no_contacts_label"
android:visibility="@{viewModel.contactsList.empty ? View.VISIBLE : View.GONE}" />
<ImageView
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="7dp"
android:src="@drawable/shape_white_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/no_contacts_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:src="@drawable/illu"
android:layout_margin="10dp"
app:layout_constraintHeight_max="200dp"
app:layout_constraintBottom_toTopOf="@id/no_contacts_label"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/background" />
<TextView
android:id="@+id/no_contacts_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="No contacts for the moment..."
android:textColor="@color/gray_9"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@id/background"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/no_contacts_image" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contactsList"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
android:layout_marginStart="10dp"
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" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -11,7 +11,7 @@
type="View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.ui.TopBarViewModel" />
type="org.linphone.ui.viewmodel.TopBarViewModel" />
</data>
<!-- Background color here is mandatory for transparency effect on child views -->

View file

@ -10,7 +10,7 @@
type="View.OnClickListener" />
<variable
name="viewModel"
type="org.linphone.ui.TopBarViewModel" />
type="org.linphone.ui.viewmodel.TopBarViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
@ -53,7 +53,7 @@
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginTop="10dp"
android:layout_marginEnd="10dp"
android:gravity="center_vertical"
android:text="@{viewModel.title, default=`Title`}"
@ -95,7 +95,7 @@
android:id="@+id/search"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginTop="20dp"
android:layout_marginTop="10dp"
android:gravity="center_vertical"
android:textColorHint="@color/gray_6"
app:hintEnabled="false"

View file

@ -2,7 +2,7 @@
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/chat_nav_graph"
android:id="@+id/contact_nav_graph"
app:startDestination="@id/emptyFragment">
<fragment
@ -17,22 +17,11 @@
android:label="ContactFragment"
tools:layout="@layout/contact_fragment" >
<argument
android:name="contact"
app:argType="org.linphone.ui.contacts.model.ContactModel" />
android:name="contactRefKey"
app:argType="string" />
</fragment>
<action android:id="@+id/action_global_contactFragment"
app:destination="@id/contactFragment"/>
<fragment
android:id="@+id/newContactFragment"
android:name="org.linphone.ui.contacts.NewContactFragment"
android:label="NewContactFragment"
tools:layout="@layout/new_contact_fragment" />
<action android:id="@+id/action_global_newContactFragment"
app:destination="@id/newContactFragment"
app:enterAnim="@anim/slide_in"
app:popExitAnim="@anim/slide_out"/>
</navigation>

View file

@ -79,11 +79,14 @@
android:label="ContactFragment"
tools:layout="@layout/contact_fragment" >
<argument
android:name="contact"
app:argType="org.linphone.ui.contacts.model.ContactModel" />
android:name="contactRefKey"
app:argType="string" />
</fragment>
<action android:id="@+id/action_global_contactFragment"
app:destination="@id/contactFragment"/>
<fragment
android:id="@+id/newContactFragment"
android:name="org.linphone.ui.contacts.NewContactFragment"
android:label="NewContactFragment"
tools:layout="@layout/new_contact_fragment" />
</navigation>