mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-04-24 13:08:33 +00:00
Reworked presence badge
This commit is contained in:
parent
5e1c681a8d
commit
e5bbe3a553
22 changed files with 220 additions and 51 deletions
|
|
@ -21,6 +21,8 @@ use_cpim=1
|
||||||
zrtp_key_agreements_suites=MS_ZRTP_KEY_AGREEMENT_K255_KYB512
|
zrtp_key_agreements_suites=MS_ZRTP_KEY_AGREEMENT_K255_KYB512
|
||||||
chat_messages_aggregation_delay=1000
|
chat_messages_aggregation_delay=1000
|
||||||
chat_messages_aggregation=1
|
chat_messages_aggregation=1
|
||||||
|
update_presence_model_timestamp_before_publish_expires_refresh=1
|
||||||
|
rls_uri=sips:rls@sip.linphone.org
|
||||||
|
|
||||||
[sound]
|
[sound]
|
||||||
#remove this property for any application that is not Linphone public version itself
|
#remove this property for any application that is not Linphone public version itself
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,45 @@ package org.linphone.contacts
|
||||||
|
|
||||||
import androidx.loader.app.LoaderManager
|
import androidx.loader.app.LoaderManager
|
||||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||||
|
import org.linphone.core.Core
|
||||||
|
import org.linphone.core.CoreListenerStub
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
|
import org.linphone.core.FriendList
|
||||||
|
import org.linphone.core.FriendListListenerStub
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.MainActivity
|
import org.linphone.ui.main.MainActivity
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
class ContactsManager {
|
class ContactsManager {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "[Contacts Manager]"
|
||||||
|
}
|
||||||
val localFriends = arrayListOf<Friend>()
|
val localFriends = arrayListOf<Friend>()
|
||||||
|
|
||||||
private val listeners = arrayListOf<ContactsListener>()
|
private val listeners = arrayListOf<ContactsListener>()
|
||||||
|
|
||||||
|
private val friendListListener: FriendListListenerStub = object : FriendListListenerStub() {
|
||||||
|
override fun onPresenceReceived(list: FriendList, friends: Array<Friend>) {
|
||||||
|
// Core thread
|
||||||
|
Log.i("$TAG Presence received")
|
||||||
|
for (listener in listeners) {
|
||||||
|
listener.onContactsLoaded()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val coreListener: CoreListenerStub = object : CoreListenerStub() {
|
||||||
|
override fun onFriendListCreated(core: Core, friendList: FriendList) {
|
||||||
|
// Core thread
|
||||||
|
friendList.addListener(friendListListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onFriendListRemoved(core: Core, friendList: FriendList) {
|
||||||
|
// Core thread
|
||||||
|
friendList.removeListener(friendListListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun loadContacts(activity: MainActivity) {
|
fun loadContacts(activity: MainActivity) {
|
||||||
// UI thread
|
// UI thread
|
||||||
val manager = LoaderManager.getInstance(activity)
|
val manager = LoaderManager.getInstance(activity)
|
||||||
|
|
@ -73,7 +102,7 @@ class ContactsManager {
|
||||||
|
|
||||||
fun updateLocalContacts() {
|
fun updateLocalContacts() {
|
||||||
// Core thread
|
// Core thread
|
||||||
Log.i("[Contacts Manager] Updating local contact(s)")
|
Log.i("$TAG Updating local contact(s)")
|
||||||
localFriends.clear()
|
localFriends.clear()
|
||||||
|
|
||||||
for (account in coreContext.core.accountList) {
|
for (account in coreContext.core.accountList) {
|
||||||
|
|
@ -84,7 +113,7 @@ class ContactsManager {
|
||||||
friend.address = address
|
friend.address = address
|
||||||
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Contacts Manager] Local contact created for account [${address.asString()}] and picture [${friend.photo}]"
|
"$TAG Local contact created for account [${address.asString()}] and picture [${friend.photo}]"
|
||||||
)
|
)
|
||||||
localFriends.add(friend)
|
localFriends.add(friend)
|
||||||
}
|
}
|
||||||
|
|
@ -92,11 +121,22 @@ class ContactsManager {
|
||||||
|
|
||||||
fun onCoreStarted() {
|
fun onCoreStarted() {
|
||||||
// Core thread
|
// Core thread
|
||||||
|
val core = coreContext.core
|
||||||
|
core.addListener(coreListener)
|
||||||
|
for (list in core.friendsLists) {
|
||||||
|
list.addListener(friendListListener)
|
||||||
|
}
|
||||||
|
|
||||||
updateLocalContacts()
|
updateLocalContacts()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCoreStopped() {
|
fun onCoreStopped() {
|
||||||
// Core thread
|
// Core thread
|
||||||
|
val core = coreContext.core
|
||||||
|
core.removeListener(coreListener)
|
||||||
|
for (list in core.friendsLists) {
|
||||||
|
list.removeListener(friendListListener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,12 @@ import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||||
import org.linphone.contacts.ContactsManager
|
import org.linphone.contacts.ContactsManager
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.voip.VoipActivity
|
import org.linphone.ui.voip.VoipActivity
|
||||||
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
||||||
lateinit var core: Core
|
lateinit var core: Core
|
||||||
|
|
||||||
lateinit var emojiCompat: EmojiCompat
|
val emojiCompat: EmojiCompat
|
||||||
|
|
||||||
val contactsManager = ContactsManager()
|
val contactsManager = ContactsManager()
|
||||||
|
|
||||||
|
|
@ -96,6 +97,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
||||||
)
|
)
|
||||||
|
|
||||||
computeUserAgent()
|
computeUserAgent()
|
||||||
|
|
||||||
core.start()
|
core.start()
|
||||||
|
|
||||||
contactsManager.onCoreStarted()
|
contactsManager.onCoreStarted()
|
||||||
|
|
@ -213,9 +215,8 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun computeUserAgent() {
|
private fun computeUserAgent() {
|
||||||
// TODO FIXME
|
val deviceName = LinphoneUtils.getDeviceName(context)
|
||||||
val deviceName: String = "Linphone6"
|
val appName = context.getString(org.linphone.R.string.app_name)
|
||||||
val appName: String = "Linphone Android"
|
|
||||||
val androidVersion = BuildConfig.VERSION_NAME
|
val androidVersion = BuildConfig.VERSION_NAME
|
||||||
val userAgent = "$appName/$androidVersion ($deviceName) LinphoneSDK"
|
val userAgent = "$appName/$androidVersion ($deviceName) LinphoneSDK"
|
||||||
val sdkVersion = context.getString(org.linphone.core.R.string.linphone_sdk_version)
|
val sdkVersion = context.getString(org.linphone.core.R.string.linphone_sdk_version)
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,7 @@ private class ContactDiffCallback : DiffUtil.ItemCallback<ContactAvatarModel>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areContentsTheSame(oldItem: ContactAvatarModel, newItem: ContactAvatarModel): Boolean {
|
override fun areContentsTheSame(oldItem: ContactAvatarModel, newItem: ContactAvatarModel): Boolean {
|
||||||
return oldItem.showFirstLetter.value == newItem.showFirstLetter.value
|
return oldItem.showFirstLetter.value == newItem.showFirstLetter.value &&
|
||||||
|
oldItem.presenceStatus.value == newItem.presenceStatus.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,14 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import org.linphone.core.ConsolidatedPresence
|
import org.linphone.core.ConsolidatedPresence
|
||||||
import org.linphone.core.Friend
|
import org.linphone.core.Friend
|
||||||
import org.linphone.core.FriendListenerStub
|
import org.linphone.core.FriendListenerStub
|
||||||
|
import org.linphone.core.tools.Log
|
||||||
import org.linphone.utils.LinphoneUtils
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
class ContactAvatarModel(val friend: Friend) {
|
class ContactAvatarModel(val friend: Friend) {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "[Contact Avatar Model]"
|
||||||
|
}
|
||||||
|
|
||||||
val id = friend.refKey
|
val id = friend.refKey
|
||||||
|
|
||||||
val avatar = MutableLiveData<Uri>()
|
val avatar = MutableLiveData<Uri>()
|
||||||
|
|
@ -47,19 +52,21 @@ class ContactAvatarModel(val friend: Friend) {
|
||||||
|
|
||||||
private val friendListener = object : FriendListenerStub() {
|
private val friendListener = object : FriendListenerStub() {
|
||||||
override fun onPresenceReceived(fr: Friend) {
|
override fun onPresenceReceived(fr: Friend) {
|
||||||
|
Log.d(
|
||||||
|
"$TAG Presence received for friend [${fr.name}]: [${friend.consolidatedPresence}]"
|
||||||
|
)
|
||||||
presenceStatus.postValue(fr.consolidatedPresence)
|
presenceStatus.postValue(fr.consolidatedPresence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Core thread
|
// Core thread
|
||||||
name.postValue(friend.name)
|
|
||||||
presenceStatus.postValue(friend.consolidatedPresence)
|
|
||||||
avatar.postValue(getAvatarUri())
|
|
||||||
|
|
||||||
friend.addListener(friendListener)
|
friend.addListener(friendListener)
|
||||||
|
|
||||||
presenceStatus.postValue(ConsolidatedPresence.Offline)
|
name.postValue(friend.name)
|
||||||
|
presenceStatus.postValue(friend.consolidatedPresence)
|
||||||
|
Log.d("$TAG Friend [${friend.name}] presence status is [${friend.consolidatedPresence}]")
|
||||||
|
avatar.postValue(getAvatarUri())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun destroy() {
|
fun destroy() {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,10 @@ import org.linphone.core.tools.Log
|
||||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||||
|
|
||||||
class ContactsListViewModel : ViewModel() {
|
class ContactsListViewModel : ViewModel() {
|
||||||
|
companion object {
|
||||||
|
const val TAG = "[Contacts List ViewModel]"
|
||||||
|
}
|
||||||
|
|
||||||
val contactsList = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
val contactsList = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
||||||
|
|
||||||
val favourites = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
val favourites = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
||||||
|
|
@ -48,7 +52,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
private val magicSearchListener = object : MagicSearchListenerStub() {
|
private val magicSearchListener = object : MagicSearchListenerStub() {
|
||||||
override fun onSearchResultsReceived(magicSearch: MagicSearch) {
|
override fun onSearchResultsReceived(magicSearch: MagicSearch) {
|
||||||
// Core thread
|
// Core thread
|
||||||
Log.i("[Contacts] Magic search contacts available")
|
Log.i("$TAG Magic search contacts available")
|
||||||
processMagicSearchResults(magicSearch.lastSearch)
|
processMagicSearchResults(magicSearch.lastSearch)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +60,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
private val contactsListener = object : ContactsListener {
|
private val contactsListener = object : ContactsListener {
|
||||||
override fun onContactsLoaded() {
|
override fun onContactsLoaded() {
|
||||||
// Core thread
|
// Core thread
|
||||||
|
Log.i("$TAG Contacts have been (re)loaded, updating list")
|
||||||
applyFilter(
|
applyFilter(
|
||||||
currentFilter,
|
currentFilter,
|
||||||
"",
|
"",
|
||||||
|
|
@ -92,7 +97,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
|
|
||||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||||
// Core thread
|
// Core thread
|
||||||
Log.i("[Contacts List] Processing ${results.size} results")
|
Log.i("$TAG Processing ${results.size} results")
|
||||||
contactsList.value.orEmpty().forEach(ContactAvatarModel::destroy)
|
contactsList.value.orEmpty().forEach(ContactAvatarModel::destroy)
|
||||||
|
|
||||||
val list = arrayListOf<ContactAvatarModel>()
|
val list = arrayListOf<ContactAvatarModel>()
|
||||||
|
|
@ -107,7 +112,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
currentLetter = friend.name?.get(0).toString()
|
currentLetter = friend.name?.get(0).toString()
|
||||||
ContactAvatarModel(friend)
|
ContactAvatarModel(friend)
|
||||||
} else {
|
} else {
|
||||||
Log.w("[Contacts] SearchResult [$result] has no Friend!")
|
Log.w("$TAG SearchResult [$result] has no Friend!")
|
||||||
val fakeFriend =
|
val fakeFriend =
|
||||||
createFriendFromSearchResult(result)
|
createFriendFromSearchResult(result)
|
||||||
currentLetter = fakeFriend.name?.get(0).toString()
|
currentLetter = fakeFriend.name?.get(0).toString()
|
||||||
|
|
@ -129,7 +134,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
favourites.postValue(favouritesList)
|
favourites.postValue(favouritesList)
|
||||||
contactsList.postValue(list)
|
contactsList.postValue(list)
|
||||||
|
|
||||||
Log.i("[Contacts] Processed ${results.size} results")
|
Log.i("$TAG Processed ${results.size} results")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyFilter(filter: String) {
|
fun applyFilter(filter: String) {
|
||||||
|
|
@ -163,7 +168,7 @@ class ContactsListViewModel : ViewModel() {
|
||||||
previousFilter = filter
|
previousFilter = filter
|
||||||
|
|
||||||
Log.i(
|
Log.i(
|
||||||
"[Contacts] Asking Magic search for contacts matching filter [$filter], domain [$domain] and in sources [$sources]"
|
"$TAG Asking Magic search for contacts matching filter [$filter], domain [$domain] and in sources [$sources]"
|
||||||
)
|
)
|
||||||
magicSearch.getContactsListAsync(
|
magicSearch.getContactsListAsync(
|
||||||
filter,
|
filter,
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@ class AccountModel(private val account: Account) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun openMenu() {
|
||||||
|
// UI thread
|
||||||
|
}
|
||||||
|
|
||||||
fun refreshRegister() {
|
fun refreshRegister() {
|
||||||
// UI thread
|
// UI thread
|
||||||
coreContext.postOnCoreThread { core ->
|
coreContext.postOnCoreThread { core ->
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ fun AppCompatTextView.setDrawableTint(color: Int) {
|
||||||
|
|
||||||
@BindingAdapter("coilContact")
|
@BindingAdapter("coilContact")
|
||||||
fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
||||||
// UI thread !
|
// UI thread
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
imageView.load(R.drawable.contact_avatar)
|
imageView.load(R.drawable.contact_avatar)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -142,18 +142,24 @@ fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@BindingAdapter("presenceIcon")
|
||||||
|
fun ImageView.setPresenceIcon(presence: ConsolidatedPresence?) {
|
||||||
|
// UI thread
|
||||||
|
val icon = when (presence) {
|
||||||
|
ConsolidatedPresence.Online -> R.drawable.led_online
|
||||||
|
ConsolidatedPresence.DoNotDisturb -> R.drawable.led_do_not_disturb
|
||||||
|
ConsolidatedPresence.Busy -> R.drawable.led_away
|
||||||
|
else -> R.drawable.led_not_registered
|
||||||
|
}
|
||||||
|
setImageResource(icon)
|
||||||
|
}
|
||||||
|
|
||||||
@BindingAdapter("contactAvatar")
|
@BindingAdapter("contactAvatar")
|
||||||
fun AvatarView.loadContactPicture(contact: ContactAvatarModel?) {
|
fun AvatarView.loadContactPicture(contact: ContactAvatarModel?) {
|
||||||
// UI thread !
|
// UI thread
|
||||||
if (contact == null) {
|
if (contact == null) {
|
||||||
loadImage(R.drawable.contact_avatar)
|
loadImage(R.drawable.contact_avatar)
|
||||||
} else {
|
} else {
|
||||||
indicatorColor = when (contact.presenceStatus.value) {
|
|
||||||
ConsolidatedPresence.Online -> R.color.green_online
|
|
||||||
else -> R.color.blue_outgoing_message
|
|
||||||
}
|
|
||||||
indicatorEnabled = contact.presenceStatus.value != ConsolidatedPresence.Offline
|
|
||||||
|
|
||||||
val uri = contact.avatar.value
|
val uri = contact.avatar.value
|
||||||
loadImage(
|
loadImage(
|
||||||
data = uri,
|
data = uri,
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@
|
||||||
*/
|
*/
|
||||||
package org.linphone.utils
|
package org.linphone.utils
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.Build
|
||||||
|
import android.provider.Settings
|
||||||
import androidx.annotation.IntegerRes
|
import androidx.annotation.IntegerRes
|
||||||
import androidx.emoji2.text.EmojiCompat
|
import androidx.emoji2.text.EmojiCompat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
@ -137,5 +141,26 @@ class LinphoneUtils {
|
||||||
fun getChatRoomId(chatRoom: ChatRoom): String {
|
fun getChatRoomId(chatRoom: ChatRoom): String {
|
||||||
return getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)
|
return getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getDeviceName(context: Context): String {
|
||||||
|
var name = Settings.Global.getString(
|
||||||
|
context.contentResolver,
|
||||||
|
Settings.Global.DEVICE_NAME
|
||||||
|
)
|
||||||
|
if (name == null) {
|
||||||
|
val adapter = BluetoothAdapter.getDefaultAdapter()
|
||||||
|
name = adapter?.name
|
||||||
|
}
|
||||||
|
if (name == null) {
|
||||||
|
name = Settings.Secure.getString(
|
||||||
|
context.contentResolver,
|
||||||
|
"bluetooth_name"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (name == null) {
|
||||||
|
name = Build.MANUFACTURER + " " + Build.MODEL
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
app/src/main/res/drawable/led_away.xml
Normal file
5
app/src/main/res/drawable/led_away.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||||
|
<solid android:color="@color/orange_away"/>
|
||||||
|
<size android:width="15dp" android:height="15dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/led_background.xml
Normal file
5
app/src/main/res/drawable/led_background.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||||
|
<solid android:color="@color/white"/>
|
||||||
|
<size android:width="20dp" android:height="20dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/led_do_not_disturb.xml
Normal file
5
app/src/main/res/drawable/led_do_not_disturb.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||||
|
<solid android:color="@color/red_danger"/>
|
||||||
|
<size android:width="15dp" android:height="15dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/led_not_registered.xml
Normal file
5
app/src/main/res/drawable/led_not_registered.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||||
|
<solid android:color="@color/gray_offline"/>
|
||||||
|
<size android:width="15dp" android:height="15dp"/>
|
||||||
|
</shape>
|
||||||
5
app/src/main/res/drawable/led_online.xml
Normal file
5
app/src/main/res/drawable/led_online.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||||
|
<solid android:color="@color/green_online"/>
|
||||||
|
<size android:width="15dp" android:height="15dp"/>
|
||||||
|
</shape>
|
||||||
|
|
@ -101,13 +101,16 @@
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
|
android:onClick="@{() -> model.openMenu()}"
|
||||||
android:id="@+id/menu"
|
android:id="@+id/menu"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="24dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="24dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:src="@drawable/dot_menu"
|
android:src="@drawable/dot_menu"
|
||||||
android:paddingTop="4dp"
|
android:paddingTop="4dp"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingEnd="10dp"
|
||||||
app:tint="@color/gray_1"
|
app:tint="@color/gray_1"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/name"
|
app:layout_constraintTop_toTopOf="@id/name"
|
||||||
|
|
|
||||||
|
|
@ -71,11 +71,6 @@
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
contactAvatar="@{viewModel.callLogModel.avatarModel}"
|
contactAvatar="@{viewModel.callLogModel.avatarModel}"
|
||||||
app:avatarViewBorderWidth="0dp"
|
app:avatarViewBorderWidth="0dp"
|
||||||
app:avatarViewIndicatorBorderColor="@color/white"
|
|
||||||
app:avatarViewIndicatorBorderSizeCriteria="8"
|
|
||||||
app:avatarViewIndicatorEnabled="true"
|
|
||||||
app:avatarViewIndicatorPosition="bottomRight"
|
|
||||||
app:avatarViewIndicatorSizeCriteria="7"
|
|
||||||
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
||||||
app:avatarViewInitialsTextColor="@color/gray_9"
|
app:avatarViewInitialsTextColor="@color/gray_9"
|
||||||
app:avatarViewInitialsTextSize="21sp"
|
app:avatarViewInitialsTextSize="21sp"
|
||||||
|
|
@ -86,6 +81,18 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/presence_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_big_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_big_size"
|
||||||
|
android:layout_marginEnd="@dimen/avatar_presence_badge_big_end_margin"
|
||||||
|
android:background="@drawable/led_background"
|
||||||
|
android:padding="@dimen/avatar_presence_badge_big_padding"
|
||||||
|
app:presenceIcon="@{viewModel.callLogModel.avatarModel.presenceStatus}"
|
||||||
|
android:visibility="@{viewModel.callLogModel.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
@ -118,7 +125,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{viewModel.callLogModel.avatarModel.presenceStatus == ConsolidatedPresence.Online ? `En ligne` : `Absent`, default=`En ligne`}"
|
android:text="@{viewModel.callLogModel.avatarModel.presenceStatus == ConsolidatedPresence.Online ? `En ligne` : `Absent`, default=`En ligne`}"
|
||||||
android:textColor="@{viewModel.callLogModel.avatarModel.presenceStatus == ConsolidatedPresence.Online ? @color/green_online : @color/green_online, default=@color/green_online}"
|
android:textColor="@{viewModel.callLogModel.avatarModel.presenceStatus == ConsolidatedPresence.Online ? @color/green_online : @color/orange_away, default=@color/green_online}"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="android.graphics.Typeface" />
|
<import type="android.graphics.Typeface" />
|
||||||
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.calls.model.CallLogModel" />
|
type="org.linphone.ui.main.calls.model.CallLogModel" />
|
||||||
|
|
@ -48,6 +49,18 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/presence_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_marginEnd="@dimen/avatar_presence_badge_end_margin"
|
||||||
|
android:background="@drawable/led_background"
|
||||||
|
android:padding="@dimen/avatar_presence_badge_padding"
|
||||||
|
app:presenceIcon="@{model.avatarModel.presenceStatus}"
|
||||||
|
android:visibility="@{model.avatarModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
||||||
|
|
@ -37,16 +38,22 @@
|
||||||
app:avatarViewInitialsTextSize="16sp"
|
app:avatarViewInitialsTextSize="16sp"
|
||||||
app:avatarViewInitialsTextStyle="bold"
|
app:avatarViewInitialsTextStyle="bold"
|
||||||
app:avatarViewShape="circle"
|
app:avatarViewShape="circle"
|
||||||
app:avatarViewBorderWidth="0dp"
|
|
||||||
app:avatarViewIndicatorEnabled="true"
|
|
||||||
app:avatarViewIndicatorBorderColor="@color/white"
|
|
||||||
app:avatarViewIndicatorSizeCriteria="7"
|
|
||||||
app:avatarViewIndicatorBorderSizeCriteria="8"
|
|
||||||
app:avatarViewIndicatorPosition="bottomRight"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/presence_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_marginEnd="@dimen/avatar_presence_badge_end_margin"
|
||||||
|
android:background="@drawable/led_background"
|
||||||
|
android:padding="@dimen/avatar_presence_badge_padding"
|
||||||
|
app:presenceIcon="@{model.presenceStatus}"
|
||||||
|
android:visibility="@{model.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -89,11 +89,6 @@
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
contactAvatar="@{viewModel.contact}"
|
contactAvatar="@{viewModel.contact}"
|
||||||
app:avatarViewBorderWidth="0dp"
|
app:avatarViewBorderWidth="0dp"
|
||||||
app:avatarViewIndicatorBorderColor="@color/white"
|
|
||||||
app:avatarViewIndicatorBorderSizeCriteria="8"
|
|
||||||
app:avatarViewIndicatorEnabled="true"
|
|
||||||
app:avatarViewIndicatorPosition="bottomRight"
|
|
||||||
app:avatarViewIndicatorSizeCriteria="7"
|
|
||||||
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
||||||
app:avatarViewInitialsTextColor="@color/gray_9"
|
app:avatarViewInitialsTextColor="@color/gray_9"
|
||||||
app:avatarViewInitialsTextSize="21sp"
|
app:avatarViewInitialsTextSize="21sp"
|
||||||
|
|
@ -104,6 +99,18 @@
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/presence_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_big_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_big_size"
|
||||||
|
android:layout_marginEnd="@dimen/avatar_presence_badge_big_end_margin"
|
||||||
|
android:background="@drawable/led_background"
|
||||||
|
android:padding="@dimen/avatar_presence_badge_big_padding"
|
||||||
|
app:presenceIcon="@{viewModel.contact.presenceStatus}"
|
||||||
|
android:visibility="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
@ -124,7 +131,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? `En ligne` : `Absent`, default=`En ligne`}"
|
android:text="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? `En ligne` : `Absent`, default=`En ligne`}"
|
||||||
android:textColor="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? @color/green_online : @color/green_online, default=@color/green_online}"
|
android:textColor="@{viewModel.contact.presenceStatus == ConsolidatedPresence.Online ? @color/green_online : @color/orange_away, default=@color/green_online}"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
<data>
|
<data>
|
||||||
<import type="android.view.View" />
|
<import type="android.view.View" />
|
||||||
<import type="android.graphics.Typeface" />
|
<import type="android.graphics.Typeface" />
|
||||||
|
<import type="org.linphone.core.ConsolidatedPresence" />
|
||||||
<variable
|
<variable
|
||||||
name="model"
|
name="model"
|
||||||
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
type="org.linphone.ui.main.contacts.model.ContactAvatarModel" />
|
||||||
|
|
@ -47,22 +48,29 @@
|
||||||
android:layout_marginBottom="5dp"
|
android:layout_marginBottom="5dp"
|
||||||
android:adjustViewBounds="true"
|
android:adjustViewBounds="true"
|
||||||
contactAvatar="@{model}"
|
contactAvatar="@{model}"
|
||||||
|
app:avatarViewInitials="SB"
|
||||||
app:avatarViewPlaceholder="@drawable/contact_avatar"
|
app:avatarViewPlaceholder="@drawable/contact_avatar"
|
||||||
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
app:avatarViewInitialsBackgroundColor="@color/blue_outgoing_message"
|
||||||
app:avatarViewInitialsTextColor="@color/gray_9"
|
app:avatarViewInitialsTextColor="@color/gray_9"
|
||||||
app:avatarViewInitialsTextSize="16sp"
|
app:avatarViewInitialsTextSize="16sp"
|
||||||
app:avatarViewInitialsTextStyle="bold"
|
app:avatarViewInitialsTextStyle="bold"
|
||||||
app:avatarViewShape="circle"
|
app:avatarViewShape="circle"
|
||||||
app:avatarViewBorderWidth="0dp"
|
|
||||||
app:avatarViewIndicatorEnabled="true"
|
|
||||||
app:avatarViewIndicatorBorderColor="@color/white"
|
|
||||||
app:avatarViewIndicatorSizeCriteria="7"
|
|
||||||
app:avatarViewIndicatorBorderSizeCriteria="8"
|
|
||||||
app:avatarViewIndicatorPosition="bottomRight"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/header"
|
app:layout_constraintStart_toEndOf="@id/header"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/presence_badge"
|
||||||
|
android:layout_width="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_height="@dimen/avatar_presence_badge_size"
|
||||||
|
android:layout_marginEnd="@dimen/avatar_presence_badge_end_margin"
|
||||||
|
android:background="@drawable/led_background"
|
||||||
|
android:padding="@dimen/avatar_presence_badge_padding"
|
||||||
|
app:presenceIcon="@{model.presenceStatus}"
|
||||||
|
android:visibility="@{model.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE}"
|
||||||
|
app:layout_constraintEnd_toEndOf="@id/avatar"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatTextView
|
<androidx.appcompat.widget.AppCompatTextView
|
||||||
style="@style/default_text_style"
|
style="@style/default_text_style"
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@
|
||||||
<color name="blue_outgoing_message">#DFECF2</color>
|
<color name="blue_outgoing_message">#DFECF2</color>
|
||||||
<color name="gray_incoming_message">#F4F4F7</color>
|
<color name="gray_incoming_message">#F4F4F7</color>
|
||||||
<color name="trusted_blue">#4AA8FF</color>
|
<color name="trusted_blue">#4AA8FF</color>
|
||||||
|
<color name="orange_away">#FFA645</color>
|
||||||
|
<color name="gray_offline">#E1E1E1</color>
|
||||||
<color name="warning_orange_background">#FFEACB</color>
|
<color name="warning_orange_background">#FFEACB</color>
|
||||||
<color name="warning_orange_pressed_background">#FFB266</color>
|
<color name="warning_orange_pressed_background">#FFB266</color>
|
||||||
<color name="dialog_background">#22334D</color>
|
<color name="dialog_background">#22334D</color>
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,12 @@
|
||||||
<dimen name="avatar_favorite_list_cell_size">50dp</dimen>
|
<dimen name="avatar_favorite_list_cell_size">50dp</dimen>
|
||||||
<dimen name="avatar_big_size">100dp</dimen>
|
<dimen name="avatar_big_size">100dp</dimen>
|
||||||
<dimen name="avatar_in_call_size">120dp</dimen>
|
<dimen name="avatar_in_call_size">120dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_size">12dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_padding">2dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_end_margin">3dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_big_size">22dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_big_padding">3dp</dimen>
|
||||||
|
<dimen name="avatar_presence_badge_big_end_margin">5dp</dimen>
|
||||||
|
|
||||||
<dimen name="top_search_bar_height">55dp</dimen>
|
<dimen name="top_search_bar_height">55dp</dimen>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue