mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Started chat room layout
This commit is contained in:
parent
7b71f32d18
commit
33a33867b5
22 changed files with 527 additions and 23 deletions
|
|
@ -22,6 +22,7 @@ package org.linphone.ui
|
|||
import android.Manifest
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
|
|
@ -105,4 +106,12 @@ class MainActivity : AppCompatActivity() {
|
|||
private fun getNavBar(): NavigationBarView? {
|
||||
return binding.mainNavView ?: binding.mainNavRail
|
||||
}
|
||||
|
||||
fun hideNavBar() {
|
||||
getNavBar()?.visibility = View.GONE
|
||||
}
|
||||
|
||||
fun showNavBar() {
|
||||
getNavBar()?.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ import org.linphone.utils.TimestampUtils
|
|||
|
||||
class ChatRoomData(val chatRoom: ChatRoom) {
|
||||
val id = LinphoneUtils.getChatRoomId(chatRoom)
|
||||
val localSipUri = chatRoom.localAddress.asString()
|
||||
val remoteSipUri = chatRoom.peerAddress.asString()
|
||||
|
||||
val contactName = MutableLiveData<String>()
|
||||
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.ConversationFragmentBinding
|
||||
|
||||
class ConversationFragment : Fragment() {
|
||||
private lateinit var binding: ConversationFragmentBinding
|
||||
private val viewModel: ConversationViewModel by navGraphViewModels(
|
||||
R.id.conversationFragment
|
||||
)
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
|
|
@ -42,5 +47,23 @@ class ConversationFragment : Fragment() {
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = viewModel
|
||||
|
||||
val localSipUri = arguments?.getString("localSipUri")
|
||||
?: savedInstanceState?.getString("localSipUri")
|
||||
val remoteSipUri = arguments?.getString("remoteSipUri")
|
||||
?: savedInstanceState?.getString("remoteSipUri")
|
||||
if (localSipUri != null && remoteSipUri != null) {
|
||||
viewModel.loadChatRoom(localSipUri, remoteSipUri)
|
||||
} else {
|
||||
// Chat room not found, going back
|
||||
|
||||
// TODO FIXME : show error
|
||||
}
|
||||
arguments?.clear()
|
||||
|
||||
binding.setBackClickListener {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ class ConversationMenuDialogFragment(
|
|||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
// TODO FIXME: use a viewmodel and use core thread
|
||||
val view = ChatRoomMenuBinding.inflate(layoutInflater)
|
||||
|
||||
val id = LinphoneUtils.getChatRoomId(chatRoom)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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.conversations
|
||||
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.contacts.ContactData
|
||||
import org.linphone.contacts.ContactsListener
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
class ConversationViewModel : ViewModel() {
|
||||
private lateinit var chatRoom: ChatRoom
|
||||
|
||||
val contactName = MutableLiveData<String>()
|
||||
|
||||
val contactData = MutableLiveData<ContactData>()
|
||||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
||||
val isOneToOne = MutableLiveData<Boolean>()
|
||||
|
||||
private val contactsListener = object : ContactsListener {
|
||||
override fun onContactsLoaded() {
|
||||
contactLookup()
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
coreContext.contactsManager.addListener(contactsListener)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
coreContext.contactsManager.removeListener(contactsListener)
|
||||
}
|
||||
|
||||
fun loadChatRoom(localSipUri: String, remoteSipUri: String) {
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val localAddress = Factory.instance().createAddress(localSipUri)
|
||||
val remoteSipAddress = Factory.instance().createAddress(remoteSipUri)
|
||||
|
||||
val found = core.searchChatRoom(
|
||||
null,
|
||||
localAddress,
|
||||
remoteSipAddress,
|
||||
arrayOfNulls(
|
||||
0
|
||||
)
|
||||
)
|
||||
if (found != null) {
|
||||
chatRoom = found
|
||||
|
||||
isOneToOne.postValue(chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt()))
|
||||
subject.postValue(chatRoom.subject)
|
||||
contactLookup()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun contactLookup() {
|
||||
if (chatRoom.hasCapability(ChatRoom.Capabilities.Basic.toInt())) {
|
||||
val remoteAddress = chatRoom.peerAddress
|
||||
val friend = chatRoom.core.findFriend(remoteAddress)
|
||||
if (friend != null) {
|
||||
contactData.postValue(ContactData(friend))
|
||||
}
|
||||
contactName.postValue(friend?.name ?: LinphoneUtils.getDisplayName(remoteAddress))
|
||||
} else {
|
||||
if (chatRoom.hasCapability(ChatRoom.Capabilities.OneToOne.toInt())) {
|
||||
val first = chatRoom.participants.firstOrNull()
|
||||
if (first != null) {
|
||||
val remoteAddress = first.address
|
||||
val friend = chatRoom.core.findFriend(remoteAddress)
|
||||
if (friend != null) {
|
||||
contactData.postValue(ContactData(friend))
|
||||
}
|
||||
contactName.postValue(
|
||||
friend?.name ?: LinphoneUtils.getDisplayName(remoteAddress)
|
||||
)
|
||||
} else {
|
||||
Log.e("[Conversation View Model] No participant in the chat room!")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
|
@ -33,6 +34,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
|
|||
import androidx.recyclerview.widget.RecyclerView
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.ConversationsFragmentBinding
|
||||
import org.linphone.ui.MainActivity
|
||||
|
||||
class ConversationsFragment : Fragment() {
|
||||
private lateinit var binding: ConversationsFragmentBinding
|
||||
|
|
@ -58,6 +60,7 @@ class ConversationsFragment : Fragment() {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
@ -91,9 +94,17 @@ class ConversationsFragment : Fragment() {
|
|||
|
||||
adapter.chatRoomClickedEvent.observe(viewLifecycleOwner) {
|
||||
it.consume { data ->
|
||||
findNavController().navigate(
|
||||
R.id.action_conversationsFragment_to_conversationFragment
|
||||
)
|
||||
val bundle = bundleOf()
|
||||
bundle.putString("localSipUri", data.localSipUri)
|
||||
bundle.putString("remoteSipUri", data.remoteSipUri)
|
||||
|
||||
if (findNavController().currentDestination?.id == R.id.conversationsFragment) {
|
||||
(requireActivity() as MainActivity).hideNavBar()
|
||||
findNavController().navigate(
|
||||
R.id.action_conversationsFragment_to_conversationFragment,
|
||||
bundle
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,12 +137,20 @@ class ConversationsFragment : Fragment() {
|
|||
}
|
||||
|
||||
binding.setOnNewConversationClicked {
|
||||
findNavController().navigate(
|
||||
R.id.action_conversationsFragment_to_newConversationFragment
|
||||
)
|
||||
if (findNavController().currentDestination?.id == R.id.conversationsFragment) {
|
||||
(requireActivity() as MainActivity).hideNavBar()
|
||||
findNavController().navigate(
|
||||
R.id.action_conversationsFragment_to_newConversationFragment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
(requireActivity() as MainActivity).showNavBar()
|
||||
}
|
||||
|
||||
private fun scrollToTop() {
|
||||
binding.conversationsList.scrollToPosition(0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,11 @@ 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.core.view.doOnPreDraw
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -39,6 +42,14 @@ class NewConversationFragment : Fragment() {
|
|||
R.id.conversationsFragment
|
||||
)
|
||||
|
||||
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
|
||||
if (findNavController().currentDestination?.id == R.id.conversationFragment) {
|
||||
// Holds fragment in place while created conversation fragment slides over it
|
||||
return AnimationUtils.loadAnimation(activity, R.anim.hold)
|
||||
}
|
||||
return super.onCreateAnimation(transit, enter, nextAnim)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
|
|
@ -85,5 +96,15 @@ class NewConversationFragment : Fragment() {
|
|||
binding.setCancelClickListener {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
}
|
||||
|
||||
viewModel.goToChatRoom.observe(viewLifecycleOwner) {
|
||||
it.consume {
|
||||
if (findNavController().currentDestination?.id == R.id.newConversationFragment) {
|
||||
findNavController().navigate(
|
||||
R.id.action_newConversationFragment_to_conversationFragment
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,17 @@ import org.linphone.core.MagicSearch
|
|||
import org.linphone.core.MagicSearchListenerStub
|
||||
import org.linphone.core.SearchResult
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class NewConversationViewModel : ViewModel() {
|
||||
val contactsList = MutableLiveData<ArrayList<ContactData>>()
|
||||
|
||||
val groupEnabled = MutableLiveData<Boolean>()
|
||||
|
||||
val goToChatRoom: MutableLiveData<Event<Pair<String, String>>> by lazy {
|
||||
MutableLiveData<Event<Pair<String, String>>>()
|
||||
}
|
||||
|
||||
val filter = MutableLiveData<String>()
|
||||
private var previousFilter = "NotSet"
|
||||
|
||||
|
|
@ -56,16 +63,16 @@ class NewConversationViewModel : ViewModel() {
|
|||
init {
|
||||
coreContext.postOnCoreThread {
|
||||
magicSearch.addListener(magicSearchListener)
|
||||
coreContext.contactsManager.addListener(contactsListener)
|
||||
applyFilter("")
|
||||
}
|
||||
coreContext.contactsManager.addListener(contactsListener)
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
coreContext.postOnCoreThread {
|
||||
coreContext.contactsManager.removeListener(contactsListener)
|
||||
magicSearch.removeListener(magicSearchListener)
|
||||
}
|
||||
coreContext.contactsManager.removeListener(contactsListener)
|
||||
super.onCleared()
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +95,14 @@ class NewConversationViewModel : ViewModel() {
|
|||
)
|
||||
}
|
||||
|
||||
fun createGroup() {
|
||||
goToChatRoom.value = Event(Pair("", ""))
|
||||
}
|
||||
|
||||
fun enableGroupSelection() {
|
||||
groupEnabled.value = true
|
||||
}
|
||||
|
||||
private fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("[New Conversation ViewModel] [${results.size}] matching results")
|
||||
contactsList.value.orEmpty().forEach(ContactData::onDestroy)
|
||||
|
|
|
|||
26
app/src/main/res/drawable/add_file.xml
Normal file
26
app/src/main/res/drawable/add_file.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<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 12 8.327 L 12 15.654 M 15.667 11.991 L 8.333 11.991"
|
||||
android:fillColor="#6c7a87"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#6c7a87"
|
||||
android:strokeWidth="1"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:pathData="M 16.686 2 L 7.314 2 C 4.048 2 2 4.312 2 7.585 L 2 16.415 C 2 19.688 4.038 22 7.314 22 L 16.686 22 C 19.962 22 22 19.688 22 16.415 L 22 7.585 C 22 4.312 19.962 2 16.686 2 Z"
|
||||
android:fillColor="#6c7a87"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#6c7a87"
|
||||
android:strokeWidth="1"
|
||||
android:fillType="evenOdd"/>
|
||||
</group>
|
||||
</vector>
|
||||
15
app/src/main/res/drawable/back.xml
Normal file
15
app/src/main/res/drawable/back.xml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="21dp"
|
||||
android:height="20dp"
|
||||
android:viewportWidth="21"
|
||||
android:viewportHeight="20">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 13.912 15.833 L 8.079 10 L 13.912 4.167"
|
||||
android:strokeColor="#fe5e00"
|
||||
android:strokeWidth="1.5"
|
||||
android:strokeLineCap="round"
|
||||
android:strokeLineJoin="round"/>
|
||||
</vector>
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
android:viewportHeight="12">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 5.801 6.88 L 6.507 7.586 L 10.74 3.353 L 11.447 4.06 L 6.507 9 L 3.325 5.818 L 4.032 5.111 L 5.095 6.173 L 5.801 6.879 L 5.801 6.88 Z M 5.802 5.466 L 8.278 2.989 L 8.983 3.694 L 6.507 6.171 L 5.802 5.466 Z M 4.388 8.293 L 3.682 9 L 0.5 5.818 L 1.207 5.111 L 1.913 5.817 L 1.913 5.818 L 4.388 8.293 Z"
|
||||
android:fillColor="#6c7a87"
|
||||
android:pathData="M 5 7.586 L 9.596 2.99 L 10.303 3.696 L 5 9 L 1.818 5.818 L 2.525 5.111 L 5 7.586 Z"
|
||||
android:fillColor="#fe5e00"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
|
|
|
|||
13
app/src/main/res/drawable/info.xml
Normal file
13
app/src/main/res/drawable/info.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="19dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="18">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 9.549 18 C 4.578 18 0.549 13.971 0.549 9 C 0.549 4.029 4.578 0 9.549 0 C 14.52 0 18.549 4.029 18.549 9 C 18.549 13.971 14.52 18 9.549 18 Z M 9.549 16.2 C 11.459 16.2 13.29 15.441 14.64 14.091 C 15.991 12.741 16.749 10.91 16.749 9 C 16.749 7.09 15.991 5.259 14.64 3.909 C 13.29 2.559 11.459 1.8 9.549 1.8 C 7.64 1.8 5.808 2.559 4.458 3.909 C 3.108 5.259 2.349 7.09 2.349 9 C 2.349 10.91 3.108 12.741 4.458 14.091 C 5.808 15.441 7.64 16.2 9.549 16.2 Z M 8.649 4.5 L 10.449 4.5 L 10.449 6.3 L 8.649 6.3 L 8.649 4.5 Z M 8.649 8.1 L 10.449 8.1 L 10.449 13.5 L 8.649 13.5 L 8.649 8.1 Z"
|
||||
android:fillColor="#6c7a87"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
20
app/src/main/res/drawable/phone_call.xml
Normal file
20
app/src/main/res/drawable/phone_call.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="19dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="18">
|
||||
<group android:name="wrapper">
|
||||
<clip-path
|
||||
android:name="clip0_96_25861"
|
||||
android:pathData="M 0.549 0 L 18.549 0 L 18.549 18 L 0.549 18 Z"/>
|
||||
<group android:name="group">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 5.454 3.75 C 5.499 4.418 5.612 5.07 5.792 5.692 L 4.892 6.593 C 4.584 5.692 4.389 4.74 4.322 3.75 L 5.454 3.75 Z M 12.849 12.765 C 13.487 12.945 14.139 13.057 14.799 13.102 L 14.799 14.22 C 13.809 14.152 12.857 13.957 11.949 13.658 L 12.849 12.765 Z M 6.174 2.25 L 3.549 2.25 C 3.137 2.25 2.799 2.587 2.799 3 C 2.799 10.043 8.507 15.75 15.549 15.75 C 15.962 15.75 16.299 15.412 16.299 15 L 16.299 12.383 C 16.299 11.97 15.962 11.633 15.549 11.633 C 14.619 11.633 13.712 11.482 12.872 11.205 C 12.797 11.175 12.714 11.168 12.639 11.168 C 12.444 11.168 12.257 11.242 12.107 11.385 L 10.457 13.035 C 8.334 11.947 6.594 10.215 5.514 8.092 L 7.164 6.442 C 7.374 6.232 7.434 5.94 7.352 5.678 C 7.074 4.838 6.924 3.938 6.924 3 C 6.924 2.587 6.587 2.25 6.174 2.25 Z"
|
||||
android:fillColor="#fe5e00"
|
||||
android:strokeWidth="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||
<corners android:radius="24dp" />
|
||||
<solid android:color="@color/white"/>
|
||||
<size android:height="48dp" android:width="234dp" />
|
||||
</shape>
|
||||
13
app/src/main/res/drawable/video_call.xml
Normal file
13
app/src/main/res/drawable/video_call.xml
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="19dp"
|
||||
android:height="14dp"
|
||||
android:viewportWidth="19"
|
||||
android:viewportHeight="14">
|
||||
<path
|
||||
android:name="path"
|
||||
android:pathData="M 3.089 13.23 C 2.416 13.23 1.77 12.962 1.294 12.487 C 0.818 12.011 0.55 11.366 0.55 10.693 L 0.55 3.308 C 0.55 2.635 0.818 1.99 1.294 1.514 C 1.77 1.038 2.415 0.77 3.089 0.77 L 11.396 0.77 C 12.052 0.77 12.682 1.025 13.155 1.479 C 13.627 1.934 13.906 2.554 13.933 3.209 L 16.333 2.248 C 16.73 2.09 17.175 2.095 17.569 2.264 C 17.963 2.433 18.273 2.751 18.433 3.148 C 18.509 3.339 18.549 3.543 18.549 3.748 L 18.549 10.248 C 18.549 10.513 18.484 10.773 18.36 11.006 C 18.237 11.239 18.058 11.439 17.839 11.587 C 17.62 11.735 17.368 11.827 17.106 11.855 C 16.843 11.883 16.578 11.847 16.333 11.748 L 13.933 10.789 C 13.906 11.444 13.627 12.064 13.155 12.519 C 12.682 12.973 12.052 13.228 11.396 13.229 L 3.089 13.23 Z M 1.934 3.308 L 1.934 10.693 C 1.934 10.999 2.056 11.292 2.272 11.508 C 2.489 11.725 2.782 11.846 3.089 11.847 L 11.396 11.847 C 11.701 11.846 11.995 11.725 12.211 11.508 C 12.428 11.292 12.549 10.998 12.55 10.693 L 12.55 3.308 C 12.549 3.002 12.428 2.709 12.211 2.492 C 11.995 2.276 11.702 2.154 11.396 2.154 L 3.089 2.154 C 2.782 2.154 2.489 2.276 2.272 2.492 C 2.056 2.709 1.934 3.002 1.934 3.308 Z M 16.85 10.47 C 16.884 10.483 16.922 10.488 16.96 10.484 C 16.997 10.48 17.033 10.467 17.064 10.446 C 17.095 10.425 17.121 10.396 17.138 10.363 C 17.156 10.33 17.165 10.293 17.166 10.255 L 17.166 3.756 C 17.165 3.718 17.156 3.681 17.138 3.648 C 17.121 3.614 17.095 3.586 17.064 3.565 C 17.033 3.544 16.997 3.531 16.96 3.527 C 16.922 3.523 16.884 3.528 16.85 3.542 L 13.935 4.699 L 13.935 9.3 L 16.85 10.47 Z"
|
||||
android:fillColor="#fe5e00"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
||||
31
app/src/main/res/drawable/voice_message.xml
Normal file
31
app/src/main/res/drawable/voice_message.xml
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<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_1">
|
||||
<path
|
||||
android:name="path_2"
|
||||
android:pathData="M 12 22 L 12 18.839"
|
||||
android:fillColor="#000"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#6c7a87"
|
||||
android:strokeWidth="1"/>
|
||||
<path
|
||||
android:name="path_3"
|
||||
android:pathData="M 12 14.848 C 9.757 14.848 7.938 13.022 7.938 10.768 L 7.938 6.081 C 7.938 3.827 9.757 2 12 2 C 14.244 2 16.062 3.827 16.062 6.081 L 16.062 10.768 C 16.062 13.022 14.244 14.848 12 14.848 Z"
|
||||
android:fillColor="#000"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#6c7a87"
|
||||
android:strokeWidth="1"/>
|
||||
<path
|
||||
android:name="path_4"
|
||||
android:pathData="M 20 10.801 C 20 15.239 16.419 18.838 11.999 18.838 C 7.581 18.838 4 15.239 4 10.801"
|
||||
android:fillColor="#000"
|
||||
android:fillAlpha="0"
|
||||
android:strokeColor="#6c7a87"
|
||||
android:strokeWidth="1"/>
|
||||
</group>
|
||||
</vector>
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@{data.isComposing ? `... est en train d'écrire` : data.lastMessage, default=`Lorem Ipsum`}"
|
||||
android:textColor="@{data.unreadChatCount > 0 ? @color/black : @color/gray_4, default=@color/gray_4}"
|
||||
android:textColor="@{data.isComposing ? @color/primary_color : data.unreadChatCount > 0 ? @color/black : @color/gray_4, default=@color/gray_4}"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="@{data.unreadChatCount > 0 ? Typeface.BOLD : Typeface.NORMAL, default=normal}"
|
||||
android:maxLines="1"
|
||||
|
|
|
|||
|
|
@ -8,23 +8,176 @@
|
|||
<variable
|
||||
name="backClickListener"
|
||||
type="View.OnClickListener" />
|
||||
<variable
|
||||
name="viewModel"
|
||||
type="org.linphone.ui.conversations.ConversationViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/transparent">
|
||||
android:background="@color/white">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/back"
|
||||
android:onClick="@{backClickListener}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/back"
|
||||
android:padding="20dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="36dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@{viewModel.isOneToOne ? @drawable/contact_avatar : @drawable/group_avatar, default=@drawable/contact_avatar}"
|
||||
coilContact="@{viewModel.contactData}"
|
||||
app:layout_constraintStart_toEndOf="@id/back"
|
||||
app:layout_constraintTop_toTopOf="@id/back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@{viewModel.isOneToOne ? viewModel.contactName : viewModel.subject, default=`John Doe`}"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="14sp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintEnd_toStartOf="@id/phone_call"
|
||||
app:layout_constraintTop_toTopOf="@id/avatar" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/presence"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="Online"
|
||||
android:textColor="@color/green_online"
|
||||
android:textSize="14sp"
|
||||
android:textStyle=""
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintStart_toEndOf="@id/avatar"
|
||||
app:layout_constraintEnd_toStartOf="@id/phone_call"
|
||||
app:layout_constraintTop_toBottomOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:src="@drawable/shape_white_background"
|
||||
android:src="@drawable/info"
|
||||
android:padding="10dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
app:layout_constraintTop_toTopOf="@id/back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/video_call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:src="@drawable/video_call"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintTop_toTopOf="@id/back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintEnd_toStartOf="@id/info" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/phone_call"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:src="@drawable/phone_call"
|
||||
android:padding="10dp"
|
||||
app:layout_constraintTop_toTopOf="@id/back"
|
||||
app:layout_constraintBottom_toBottomOf="@id/back"
|
||||
app:layout_constraintEnd_toStartOf="@id/video_call" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composing_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="... est en train d’écrire..."
|
||||
android:textSize="12sp"
|
||||
android:textColor="#73000000"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginBottom="15dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/bottom_background" />
|
||||
|
||||
<View
|
||||
android:id="@+id/bottom_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="@color/gray_7"
|
||||
android:layout_marginTop="-15dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/message"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/emoji_picker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:text="🙂"
|
||||
android:textSize="18sp"
|
||||
android:padding="5dp"
|
||||
android:gravity="center"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/message"
|
||||
app:layout_constraintBottom_toBottomOf="@id/message" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/attach_file"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:src="@drawable/add_file"
|
||||
android:padding="5dp"
|
||||
android:layout_marginStart="10dp"
|
||||
app:layout_constraintStart_toEndOf="@id/emoji_picker"
|
||||
app:layout_constraintTop_toTopOf="@id/message"
|
||||
app:layout_constraintBottom_toBottomOf="@id/message" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/message"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Dites quelque chose..."
|
||||
android:layout_marginBottom="15dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingBottom="5dp"
|
||||
android:maxLines="5"
|
||||
android:textSize="14sp"
|
||||
android:background="@drawable/shape_edittext_white_background"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/attach_file"
|
||||
app:layout_constraintEnd_toStartOf="@id/voice_message"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/voice_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="0dp"
|
||||
android:src="@drawable/voice_message"
|
||||
android:padding="5dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/message"
|
||||
app:layout_constraintBottom_toBottomOf="@id/message" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</layout>
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
android:layout_marginTop="10dp"
|
||||
android:text="Récents"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/gray_1"
|
||||
android:textColor="@color/blue_filter"
|
||||
android:drawablePadding="5dp"
|
||||
app:layout_constraintStart_toEndOf="@id/sort_by_label"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_bar"
|
||||
|
|
|
|||
|
|
@ -42,6 +42,21 @@
|
|||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/subtitle"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/create_group"
|
||||
android:onClick="@{() -> viewModel.createGroup()}"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Créer"
|
||||
android:textSize="15sp"
|
||||
android:padding="10dp"
|
||||
android:textColor="@color/primary_color"
|
||||
android:layout_marginEnd="15dp"
|
||||
android:visibility="@{viewModel.groupEnabled ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/title"
|
||||
app:layout_constraintBottom_toBottomOf="@id/subtitle"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
@ -86,6 +101,7 @@
|
|||
app:layout_constraintTop_toBottomOf="@id/subtitle" />
|
||||
|
||||
<ImageView
|
||||
android:onClick="@{() -> viewModel.enableGroupSelection()}"
|
||||
android:id="@+id/new_group_avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -94,21 +110,23 @@
|
|||
android:background="@drawable/shape_orange_round"
|
||||
android:layout_marginTop="30dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:visibility="@{viewModel.filter.length() > 0 ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.filter.length() > 0 || viewModel.groupEnabled ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_bar"
|
||||
app:layout_constraintStart_toStartOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:onClick="@{() -> viewModel.enableGroupSelection()}"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Créer un nouveau groupe"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="25dp"
|
||||
android:padding="5dp"
|
||||
android:layout_marginStart="7dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:drawableEnd="@drawable/next"
|
||||
android:drawablePadding="5dp"
|
||||
android:visibility="@{viewModel.filter.length() > 0 ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.filter.length() > 0 || viewModel.groupEnabled ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintStart_toEndOf="@id/new_group_avatar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/new_group_avatar"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
android:id="@+id/action_conversationsFragment_to_newConversationFragment"
|
||||
app:destination="@id/newConversationFragment"
|
||||
app:enterAnim="@anim/slide_in"
|
||||
app:popExitAnim="@anim/slide_out" />
|
||||
app:popExitAnim="@anim/slide_out"/>
|
||||
<action
|
||||
android:id="@+id/action_conversationsFragment_to_conversationFragment"
|
||||
app:destination="@id/conversationFragment"
|
||||
|
|
@ -29,13 +29,23 @@
|
|||
tools:layout="@layout/new_conversation_fragment" >
|
||||
<action
|
||||
android:id="@+id/action_newConversationFragment_to_conversationFragment"
|
||||
app:destination="@id/conversationFragment" />
|
||||
app:destination="@id/conversationFragment"
|
||||
app:enterAnim="@anim/slide_in_right"
|
||||
app:popExitAnim="@anim/slide_out_right"
|
||||
app:popUpTo="@id/conversationsFragment" />
|
||||
</fragment>
|
||||
|
||||
<fragment
|
||||
android:id="@+id/conversationFragment"
|
||||
android:name="org.linphone.ui.conversations.ConversationFragment"
|
||||
android:label="ConversationFragment"
|
||||
tools:layout="@layout/conversation_fragment" />
|
||||
tools:layout="@layout/conversation_fragment" >
|
||||
<argument
|
||||
android:name="localSipUri"
|
||||
app:argType="string" />
|
||||
<argument
|
||||
android:name="remoteSipUri"
|
||||
app:argType="string" />
|
||||
</fragment>
|
||||
|
||||
</navigation>
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
<color name="black">#000000</color>
|
||||
<color name="white">#FFFFFF</color>
|
||||
<color name="red_danger">#DD5F5F</color>
|
||||
<color name="green_online">#4FAE80</color>
|
||||
<color name="blue_filter">#09C5F4</color>
|
||||
|
||||
<color name="gray_1">#6C7A87</color>
|
||||
<color name="gray_2">#F9F9F9</color>
|
||||
|
|
@ -12,5 +14,6 @@
|
|||
<color name="gray_4">#949494</color>
|
||||
<color name="gray_5">#4E4E4E</color>
|
||||
<color name="gray_6">#EDEDED</color>
|
||||
<color name="gray_7">#F9F9F9</color>
|
||||
<color name="separator">#E5E5EA</color>
|
||||
</resources>
|
||||
Loading…
Add table
Reference in a new issue