Started contacts list

This commit is contained in:
Sylvain Berfini 2023-07-31 13:50:43 +02:00
parent 2aeaf330a8
commit f7f5a3cf50
15 changed files with 733 additions and 11 deletions

2
.idea/gradle.xml generated
View file

@ -7,7 +7,7 @@
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="Embedded JDK" />
<option name="gradleJvm" value="jbr-17" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />

3
.idea/misc.xml generated
View file

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

View file

@ -0,0 +1,62 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.ui.contacts
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.fragment.app.Fragment
import androidx.navigation.navGraphViewModels
import org.linphone.R
import org.linphone.databinding.ContactsFragmentBinding
import org.linphone.ui.contacts.viewmodel.ContactsListViewModel
class ContactsFragment : Fragment() {
private lateinit var binding: ContactsFragmentBinding
private val listViewModel: ContactsListViewModel by navGraphViewModels(
R.id.contactsFragment
)
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
// Holds fragment in place while new fragment slides over it
return AnimationUtils.loadAnimation(activity, R.anim.hold)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = ContactsFragmentBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.lifecycleOwner = viewLifecycleOwner
binding.viewModel = listViewModel
// postponeEnterTransition()
}
}

View file

@ -0,0 +1,45 @@
/*
* 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
class ContactsListViewModel : ViewModel() {
val searchBarVisible = MutableLiveData<Boolean>()
val searchFilter = MutableLiveData<String>()
init {
searchBarVisible.value = false
}
fun openSearchBar() {
searchBarVisible.value = true
}
fun closeSearchBar() {
searchBarVisible.value = false
}
fun clearFilter() {
searchFilter.value = ""
}
}

View 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_1"
android:pathData="M 6.54 5 C 6.6 5.89 6.75 6.76 6.99 7.59 L 5.79 8.79 C 5.38 7.59 5.12 6.32 5.03 5 L 6.54 5 Z M 16.4 17.02 C 17.25 17.26 18.12 17.41 19 17.47 L 19 18.96 C 17.68 18.87 16.41 18.61 15.2 18.21 L 16.4 17.02 Z M 7.5 3 L 4 3 C 3.45 3 3 3.45 3 4 C 3 13.39 10.61 21 20 21 C 20.55 21 21 20.55 21 20 L 21 16.51 C 21 15.96 20.55 15.51 20 15.51 C 18.76 15.51 17.55 15.31 16.43 14.94 C 16.33 14.9 16.22 14.89 16.12 14.89 C 15.86 14.89 15.61 14.99 15.41 15.18 L 13.21 17.38 C 10.38 15.93 8.06 13.62 6.62 10.79 L 8.82 8.59 C 9.1 8.31 9.18 7.92 9.07 7.57 C 8.7 6.45 8.5 5.25 8.5 4 C 8.5 3.45 8.05 3 7.5 3 Z"
android:fillColor="#4e6074"
android:strokeWidth="1"/>
</vector>

View 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 19 6.41 L 17.59 5 L 12 10.59 L 6.41 5 L 5 6.41 L 10.59 12 L 5 17.59 L 6.41 19 L 12 13.41 L 17.59 19 L 19 17.59 L 13.41 12 L 19 6.41 Z"
android:fillColor="#ffffff"
android:strokeWidth="1"/>
</vector>

View 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 14 2 L 6 2 C 4.9 2 4 2.9 4 4 L 4 20 C 4 21.1 4.9 22 6 22 L 18 22 C 19.1 22 20 21.1 20 20 L 20 8 L 14 2 Z M 12 10 C 13.1 10 14 10.9 14 12 C 14 13.1 13.1 14 12 14 C 10.9 14 10 13.1 10 12 C 10 10.9 10.9 10 12 10 Z M 16 18 L 8 18 L 8 17.43 C 8 16.62 8.48 15.9 9.22 15.58 C 10.07 15.21 11.01 15 12 15 C 12.99 15 13.93 15.21 14.78 15.58 C 15.52 15.9 16 16.62 16 17.43 L 16 18 Z"
android:fillColor="#fe5e00"
android:strokeWidth="1"/>
</vector>

View 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 4 4 L 20 4 L 20 16 L 5.17 16 L 4 17.17 L 4 4 Z M 4 2 C 2.9 2 2.01 2.9 2.01 4 L 2 22 L 6 18 L 20 18 C 21.1 18 22 17.1 22 16 L 22 4 C 22 2.9 21.1 2 20 2 L 4 2 Z M 6 12 L 14 12 L 14 14 L 6 14 L 6 12 Z M 6 9 L 18 9 L 18 11 L 6 11 L 6 9 Z M 6 6 L 18 6 L 18 8 L 6 8 L 6 6 Z"
android:fillColor="#4e6074"
android:strokeWidth="1"/>
</vector>

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,13 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="24dp"
android:height="12dp"
android:viewportWidth="24"
android:viewportHeight="12">
<path
android:name="path"
android:pathData="M 4 7 C 5.1 7 6 6.1 6 5 C 6 3.9 5.1 3 4 3 C 2.9 3 2 3.9 2 5 C 2 6.1 2.9 7 4 7 Z M 5.13 8.1 C 4.76 8.04 4.39 8 4 8 C 3.01 8 2.07 8.21 1.22 8.58 C 0.48 8.9 0 9.62 0 10.43 L 0 12 L 4.5 12 L 4.5 10.39 C 4.5 9.56 4.73 8.78 5.13 8.1 Z M 20 7 C 21.1 7 22 6.1 22 5 C 22 3.9 21.1 3 20 3 C 18.9 3 18 3.9 18 5 C 18 6.1 18.9 7 20 7 Z M 24 10.43 C 24 9.62 23.52 8.9 22.78 8.58 C 21.93 8.21 20.99 8 20 8 C 19.61 8 19.24 8.04 18.87 8.1 C 19.27 8.78 19.5 9.56 19.5 10.39 L 19.5 12 L 24 12 L 24 10.43 Z M 16.24 7.65 C 15.07 7.13 13.63 6.75 12 6.75 C 10.37 6.75 8.93 7.14 7.76 7.65 C 6.68 8.13 6 9.21 6 10.39 L 6 12 L 18 12 L 18 10.39 C 18 9.21 17.32 8.13 16.24 7.65 Z M 8.07 10 C 8.16 9.77 8.2 9.61 8.98 9.31 C 9.95 8.93 10.97 8.75 12 8.75 C 13.03 8.75 14.05 8.93 15.02 9.31 C 15.79 9.61 15.83 9.77 15.93 10 L 8.07 10 Z M 12 2 C 12.55 2 13 2.45 13 3 C 13 3.55 12.55 4 12 4 C 11.45 4 11 3.55 11 3 C 11 2.45 11.45 2 12 2 Z M 12 0 C 10.34 0 9 1.34 9 3 C 9 4.66 10.34 6 12 6 C 13.66 6 15 4.66 15 3 C 15 1.34 13.66 0 12 0 Z"
android:fillColor="#4e6074"
android:strokeWidth="1"/>
</vector>

View file

@ -1,14 +1,13 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:name="vector"
android:width="14dp"
android:height="13dp"
android:viewportWidth="14"
android:viewportHeight="13">
android:width="24dp"
android:height="25dp"
android:viewportWidth="24"
android:viewportHeight="25">
<path
android:name="path"
android:pathData="M 12.858 12.358 C 12.949 12.267 13 12.143 13 12.014 C 13 11.885 12.949 11.761 12.858 11.67 L 9.353 8.167 C 10.035 7.33 10.407 6.282 10.405 5.203 C 10.404 3.956 9.908 2.761 9.026 1.879 C 8.145 0.997 6.949 0.501 5.703 0.5 C 4.456 0.501 3.261 0.997 2.379 1.879 C 1.497 2.761 1.001 3.956 1 5.203 C 1.001 6.449 1.497 7.645 2.379 8.526 C 3.261 9.408 4.456 9.904 5.703 9.905 C 6.782 9.907 7.83 9.535 8.667 8.853 L 12.171 12.358 C 12.262 12.449 12.385 12.5 12.514 12.5 C 12.578 12.5 12.641 12.488 12.7 12.463 C 12.759 12.439 12.813 12.403 12.858 12.358 Z M 9.433 5.203 C 9.432 6.191 9.038 7.139 8.339 7.839 C 7.64 8.538 6.692 8.931 5.703 8.932 C 4.714 8.931 3.766 8.538 3.067 7.839 C 2.368 7.14 1.974 6.192 1.973 5.203 C 1.974 4.214 2.368 3.266 3.067 2.567 C 3.766 1.868 4.714 1.474 5.703 1.473 C 6.691 1.474 7.64 1.867 8.339 2.567 C 9.038 3.266 9.432 4.214 9.433 5.203 Z"
android:fillColor="#676767"
android:strokeColor="#676767"
android:strokeWidth="0.5"/>
android:pathData="M 15.5 14.5 L 14.71 14.5 L 14.43 14.23 C 15.41 13.09 16 11.61 16 10 C 16 6.41 13.09 3.5 9.5 3.5 C 5.91 3.5 3 6.41 3 10 C 3 13.59 5.91 16.5 9.5 16.5 C 11.11 16.5 12.59 15.91 13.73 14.93 L 14 15.21 L 14 16 L 19 20.99 L 20.49 19.5 L 15.5 14.5 Z M 9.5 14.5 C 7.01 14.5 5 12.49 5 10 C 5 7.51 7.01 5.5 9.5 5.5 C 11.99 5.5 14 7.51 14 10 C 14 12.49 11.99 14.5 9.5 14.5 Z"
android:fillColor="#ffffff"
android:strokeWidth="1"/>
</vector>

View file

@ -0,0 +1,85 @@
<?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" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/contacts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:drawableTop="@drawable/contacts"
android:drawablePadding="10dp"
android:drawableTint="@color/primary_color"
android:text="Contacts"
android:textSize="11sp"
android:textColor="@color/gray_9"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/calls"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/calls"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:drawableTop="@drawable/calls"
android:drawablePadding="10dp"
android:text="Calls"
android:textSize="11sp"
android:textColor="@color/gray_9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/conversations"
app:layout_constraintStart_toEndOf="@id/contacts"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/conversations"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:drawableTop="@drawable/conversations"
android:drawablePadding="10dp"
android:text="Conversations"
android:textSize="11sp"
android:textColor="@color/gray_9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/meetings"
app:layout_constraintStart_toEndOf="@id/calls"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/meetings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="18dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:drawableTop="@drawable/meetings"
android:drawablePadding="10dp"
android:text="Meetings"
android:textSize="11sp"
android:textColor="@color/gray_9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/conversations"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -0,0 +1,186 @@
<?xml version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<import type="android.view.View" />
<variable
name="onNewContactClicked"
type="View.OnClickListener" />
<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="avatar, title, search_toggle"
android:visibility="@{viewModel.searchBarVisible ? View.INVISIBLE : View.VISIBLE}" />
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="cancel_search, search, clear_field"
android:visibility="@{viewModel.searchBarVisible ? View.VISIBLE : View.INVISIBLE, default=gone}" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/background_barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="title, search"
app:barrierDirection="bottom" />
<ImageView
android:id="@+id/avatar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:src="@drawable/contact_avatar"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/title" />
<TextView
android:id="@+id/title"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:gravity="center_vertical"
android:text="Contacts"
android:textColor="#FFFFFF"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/search_toggle"
app:layout_constraintStart_toEndOf="@id/avatar"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/search_toggle"
android:onClick="@{() -> viewModel.openSearchBar()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dp"
android:layout_marginEnd="9dp"
android:src="@drawable/search"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/title"
app:tint="@color/white" />
<ImageView
android:id="@+id/cancel_search"
android:onClick="@{() -> viewModel.closeSearchBar()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_marginStart="5dp"
android:src="@drawable/back"
app:layout_constraintBottom_toBottomOf="@id/search"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/search"
app:tint="@color/white" />
<EditText
android:id="@+id/search"
android:layout_width="0dp"
android:layout_height="35dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="10dp"
android:hint="Search contact"
android:focusedByDefault="true"
android:text="@={viewModel.searchFilter}"
android:gravity="center_vertical"
android:textStyle="bold"
android:textSize="16sp"
android:textCursorDrawable="@null"
android:textColor="@color/gray_6"
android:textColorHint="@color/gray_6"
android:background="@android:color/transparent"
android:visibility="@{viewModel.searchBarVisible ? View.VISIBLE : View.GONE, default=visible}"
app:layout_constraintEnd_toStartOf="@id/clear_field"
app:layout_constraintStart_toEndOf="@id/cancel_search"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/clear_field"
android:onClick="@{() -> viewModel.clearFilter()}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6dp"
android:layout_marginEnd="9dp"
android:src="@drawable/close"
app:layout_constraintBottom_toBottomOf="@id/search"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/search"
app:tint="@color/white" />
<ImageView
android:id="@+id/background"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="20dp"
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/background_barrier" />
<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_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" />
<include
android:id="@+id/bottom_nav_bar"
layout="@layout/bottom_nav_bar"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="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_toTopOf="@id/bottom_nav_bar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View file

@ -3,7 +3,7 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_nav_graph"
app:startDestination="@id/conversationsFragment">
app:startDestination="@id/contactsFragment">
<fragment
android:id="@+id/conversationsFragment"
@ -47,5 +47,10 @@
android:name="remoteSipUri"
app:argType="string" />
</fragment>
<fragment
android:id="@+id/contactsFragment"
android:name="org.linphone.ui.contacts.ContactsFragment"
android:label="ContactsFragment"
tools:layout="@layout/contacts_fragment" />
</navigation>

View file

@ -17,5 +17,7 @@
<color name="gray_5">#4E4E4E</color>
<color name="gray_6">#EDEDED</color>
<color name="gray_7">#F9F9F9</color>
<color name="gray_8">#364860</color>
<color name="gray_9">#4E6074</color>
<color name="separator">#E5E5EA</color>
</resources>