mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added remote contact directory lookup if friend isn't found locally
This commit is contained in:
parent
8d78f2b698
commit
213e62d125
13 changed files with 308 additions and 51 deletions
|
|
@ -52,6 +52,8 @@ import org.linphone.core.Factory
|
|||
import org.linphone.core.Friend
|
||||
import org.linphone.core.FriendList
|
||||
import org.linphone.core.FriendListListenerStub
|
||||
import org.linphone.core.MagicSearch
|
||||
import org.linphone.core.MagicSearchListenerStub
|
||||
import org.linphone.core.SecurityLevel
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.MainActivity
|
||||
|
|
@ -70,7 +72,8 @@ class ContactsManager @UiThread constructor() {
|
|||
private const val TAG = "[Contacts Manager]"
|
||||
|
||||
private const val DELAY_BEFORE_RELOADING_CONTACTS_AFTER_PRESENCE_RECEIVED = 1000L // 1 second
|
||||
private const val FRIEND_LIST_TEMPORARY_STORED = "TempNativeContacts"
|
||||
private const val FRIEND_LIST_TEMPORARY_STORED_NATIVE = "TempNativeContacts"
|
||||
private const val FRIEND_LIST_TEMPORARY_STORED_REMOTE_DIRECTORY = "TempRemoteDirectoryContacts"
|
||||
}
|
||||
|
||||
private var nativeContactsLoaded = false
|
||||
|
|
@ -88,6 +91,36 @@ class ContactsManager @UiThread constructor() {
|
|||
|
||||
private var loadContactsOnlyFromDefaultDirectory = true
|
||||
|
||||
private lateinit var magicSearch: MagicSearch
|
||||
|
||||
private val magicSearchListener = object : MagicSearchListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onSearchResultsReceived(magicSearch: MagicSearch) {
|
||||
val results = magicSearch.lastSearch
|
||||
Log.i("$TAG [${results.size}] magic search results available")
|
||||
|
||||
if (results.isNotEmpty()) {
|
||||
val result = results.first() {
|
||||
it.friend != null
|
||||
}
|
||||
if (result != null) {
|
||||
val friend = result.friend!!
|
||||
Log.i("$TAG Found matching friend in source [${result.sourceFlags}]")
|
||||
|
||||
// Store friend in app's cache to be re-used in call history, conversations, etc...
|
||||
val temporaryFriendList = getTemporaryFriendList(native = false)
|
||||
temporaryFriendList.addFriend(friend)
|
||||
newContactAdded(friend)
|
||||
Log.i("$TAG Stored discovered friend in temporary friend list, for later use")
|
||||
|
||||
for (listener in listeners) {
|
||||
listener.onContactFoundInRemoteDirectory(friend)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val friendListListener: FriendListListenerStub = object : FriendListListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onNewSipAddressDiscovered(
|
||||
|
|
@ -106,7 +139,7 @@ class ContactsManager @UiThread constructor() {
|
|||
friend.addAddress(address)
|
||||
friend.done()
|
||||
|
||||
newContactAddedWithSipUri(sipUri)
|
||||
newContactAddedWithSipUri(friend, sipUri)
|
||||
} else {
|
||||
Log.e("$TAG Failed to parse SIP URI [$sipUri] as Address!")
|
||||
}
|
||||
|
|
@ -182,7 +215,7 @@ class ContactsManager @UiThread constructor() {
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun newContactAddedWithSipUri(sipUri: String) {
|
||||
private fun newContactAddedWithSipUri(friend: Friend, sipUri: String) {
|
||||
if (unknownContactsAvatarsMap.keys.contains(sipUri)) {
|
||||
Log.d("$TAG Found SIP URI [$sipUri] in unknownContactsAvatarsMap, removing it")
|
||||
val oldModel = unknownContactsAvatarsMap[sipUri]
|
||||
|
|
@ -195,13 +228,19 @@ class ContactsManager @UiThread constructor() {
|
|||
val oldModel = knownContactsAvatarsMap[sipUri]
|
||||
val address = Factory.instance().createAddress(sipUri)
|
||||
oldModel?.update(address)
|
||||
} else {
|
||||
Log.i(
|
||||
"$TAG New contact added with SIP URI [$sipUri] but no avatar yet, let's create it"
|
||||
)
|
||||
val model = ContactAvatarModel(friend)
|
||||
knownContactsAvatarsMap[sipUri] = model
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun newContactAdded(friend: Friend) {
|
||||
for (sipAddress in friend.addresses) {
|
||||
newContactAddedWithSipUri(sipAddress.asStringUriOnly())
|
||||
newContactAddedWithSipUri(friend, sipAddress.asStringUriOnly())
|
||||
}
|
||||
|
||||
conferenceAvatarMap.values.forEach(ContactAvatarModel::destroy)
|
||||
|
|
@ -240,14 +279,12 @@ class ContactsManager @UiThread constructor() {
|
|||
Log.i("$TAG Native contacts have been loaded, cleaning avatars maps")
|
||||
|
||||
val core = coreContext.core
|
||||
val found = core.getFriendListByName(FRIEND_LIST_TEMPORARY_STORED)
|
||||
if (found != null) {
|
||||
val count = found.friends.size
|
||||
Log.i(
|
||||
"$TAG Found temporary friend list with [$count] friends, removing it as no longer necessary"
|
||||
)
|
||||
core.removeFriendList(found)
|
||||
}
|
||||
val found = getTemporaryFriendList(native = true)
|
||||
val count = found.friends.size
|
||||
Log.i(
|
||||
"$TAG Found temporary friend list with [$count] friends, removing it as no longer necessary"
|
||||
)
|
||||
core.removeFriendList(found)
|
||||
|
||||
knownContactsAvatarsMap.values.forEach(ContactAvatarModel::destroy)
|
||||
knownContactsAvatarsMap.clear()
|
||||
|
|
@ -296,6 +333,21 @@ class ContactsManager @UiThread constructor() {
|
|||
return found
|
||||
}
|
||||
|
||||
// Start an async query in Magic Search in case LDAP or remote CardDAV is configured
|
||||
val remoteContactDirectories = coreContext.core.remoteContactDirectories
|
||||
if (remoteContactDirectories.isNotEmpty()) {
|
||||
Log.i(
|
||||
"$TAG SIP URI [$sipUri] not found in locally stored Friends, trying LDAP/CardDAV remote directory"
|
||||
)
|
||||
magicSearch.resetSearchCache()
|
||||
magicSearch.getContactsListAsync(
|
||||
username,
|
||||
address.domain,
|
||||
MagicSearch.Source.LdapServers.toInt() or MagicSearch.Source.RemoteCardDAV.toInt(),
|
||||
MagicSearch.Aggregation.Friend
|
||||
)
|
||||
}
|
||||
|
||||
val sipAddress = if (sipUri.startsWith("sip:")) {
|
||||
sipUri.substring("sip:".length)
|
||||
} else if (sipUri.startsWith("sips:")) {
|
||||
|
|
@ -435,6 +487,17 @@ class ContactsManager @UiThread constructor() {
|
|||
return avatar
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun isContactAvailable(friend: Friend): Boolean {
|
||||
return !friend.refKey.isNullOrEmpty() && !isContactTemporary(friend)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun isContactTemporary(friend: Friend): Boolean {
|
||||
val friendList = friend.friendList
|
||||
return friendList == null || friendList.displayName == FRIEND_LIST_TEMPORARY_STORED_NATIVE || friendList.displayName == FRIEND_LIST_TEMPORARY_STORED_REMOTE_DIRECTORY
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun onCoreStarted(core: Core) {
|
||||
loadContactsOnlyFromDefaultDirectory = corePreferences.fetchContactsFromDefaultDirectory
|
||||
|
|
@ -444,6 +507,10 @@ class ContactsManager @UiThread constructor() {
|
|||
list.addListener(friendListListener)
|
||||
}
|
||||
|
||||
magicSearch = core.createMagicSearch()
|
||||
magicSearch.limitedSearch = false
|
||||
magicSearch.addListener(magicSearchListener)
|
||||
|
||||
val context = coreContext.context
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
context,
|
||||
|
|
@ -467,12 +534,31 @@ class ContactsManager @UiThread constructor() {
|
|||
@WorkerThread
|
||||
fun onCoreStopped(core: Core) {
|
||||
coroutineScope.cancel()
|
||||
|
||||
magicSearch.removeListener(magicSearchListener)
|
||||
core.removeListener(coreListener)
|
||||
|
||||
for (list in core.friendsLists) {
|
||||
list.removeListener(friendListListener)
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getTemporaryFriendList(native: Boolean): FriendList {
|
||||
val core = coreContext.core
|
||||
val name = if (native) FRIEND_LIST_TEMPORARY_STORED_NATIVE else FRIEND_LIST_TEMPORARY_STORED_REMOTE_DIRECTORY
|
||||
val temporaryFriendList = core.getFriendListByName(name) ?: core.createFriendList()
|
||||
if (temporaryFriendList.displayName.isNullOrEmpty()) {
|
||||
temporaryFriendList.isDatabaseStorageEnabled = false
|
||||
temporaryFriendList.displayName = name
|
||||
core.addFriendList(temporaryFriendList)
|
||||
Log.i(
|
||||
"$TAG Created temporary friend list with name [$name]"
|
||||
)
|
||||
}
|
||||
return temporaryFriendList
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun findNativeContact(address: String, username: String, searchAsPhoneNumber: Boolean): Friend? {
|
||||
if (nativeContactsLoaded) {
|
||||
|
|
@ -499,16 +585,7 @@ class ContactsManager @UiThread constructor() {
|
|||
"$TAG Looking for native contact with address [$address] ${if (searchAsPhoneNumber) "or phone number [$username]" else ""}"
|
||||
)
|
||||
|
||||
val temporaryFriendList = core.getFriendListByName(FRIEND_LIST_TEMPORARY_STORED) ?: core.createFriendList()
|
||||
if (temporaryFriendList.displayName.isNullOrEmpty()) {
|
||||
temporaryFriendList.isDatabaseStorageEnabled = false
|
||||
temporaryFriendList.displayName = FRIEND_LIST_TEMPORARY_STORED
|
||||
core.addFriendList(temporaryFriendList)
|
||||
Log.i(
|
||||
"$TAG Created temporary friend list with name [$FRIEND_LIST_TEMPORARY_STORED]"
|
||||
)
|
||||
}
|
||||
|
||||
val temporaryFriendList = getTemporaryFriendList(native = true)
|
||||
try {
|
||||
val selection = if (searchAsPhoneNumber) {
|
||||
"${ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ? OR ${ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS} LIKE ?"
|
||||
|
|
@ -649,6 +726,8 @@ class ContactsManager @UiThread constructor() {
|
|||
|
||||
interface ContactsListener {
|
||||
fun onContactsLoaded()
|
||||
|
||||
fun onContactFoundInRemoteDirectory(friend: Friend)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ import org.linphone.LinphoneApplication.Companion.corePreferences
|
|||
import org.linphone.R
|
||||
import org.linphone.compatibility.Compatibility
|
||||
import org.linphone.contacts.AvatarGenerator
|
||||
import org.linphone.contacts.ContactsManager.ContactsListener
|
||||
import org.linphone.contacts.getAvatarBitmap
|
||||
import org.linphone.contacts.getPerson
|
||||
import org.linphone.core.Address
|
||||
|
|
@ -59,10 +60,12 @@ import org.linphone.core.ChatMessageListener
|
|||
import org.linphone.core.ChatMessageListenerStub
|
||||
import org.linphone.core.ChatMessageReaction
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.ConferenceParams
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreInCallService
|
||||
import org.linphone.core.CoreKeepAliveThirdPartyAccountsService
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.Factory
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.MediaDirection
|
||||
import org.linphone.core.tools.Log
|
||||
|
|
@ -116,6 +119,57 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
|
||||
private var currentlyDisplayedChatRoomId: String = ""
|
||||
|
||||
private val contactsListener = object : ContactsListener {
|
||||
@WorkerThread
|
||||
override fun onContactsLoaded() { }
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) {
|
||||
val addresses = friend.addresses
|
||||
Log.i(
|
||||
"$TAG Found contact [${friend.name}] in remote directory with [${addresses.size}] addresses"
|
||||
)
|
||||
|
||||
for ((remoteAddress, notifiable) in callNotificationsMap.entries) {
|
||||
val parsedAddress = Factory.instance().createAddress(remoteAddress)
|
||||
parsedAddress ?: continue
|
||||
val addressMatch = addresses.find {
|
||||
it.weakEqual(parsedAddress)
|
||||
}
|
||||
if (addressMatch != null) {
|
||||
Log.i(
|
||||
"$TAG Found call [${addressMatch.asStringUriOnly()}] with contact in notifications, updating it"
|
||||
)
|
||||
updateCallNotification(notifiable, addressMatch, friend)
|
||||
}
|
||||
}
|
||||
|
||||
for ((remoteAddress, notifiable) in chatNotificationsMap.entries) {
|
||||
var updated = false
|
||||
var peerAddress: Address? = null
|
||||
for (message in notifiable.messages) {
|
||||
val parsedAddress = Factory.instance().createAddress(message.senderAddress)
|
||||
parsedAddress ?: continue
|
||||
val addressMatch = addresses.find {
|
||||
it.weakEqual(parsedAddress)
|
||||
}
|
||||
if (addressMatch != null) {
|
||||
peerAddress = addressMatch
|
||||
updated = true
|
||||
message.sender = friend.name ?: LinphoneUtils.getDisplayName(addressMatch)
|
||||
message.friend = friend
|
||||
}
|
||||
}
|
||||
if (updated && peerAddress != null) {
|
||||
Log.i(
|
||||
"$TAG Found conversation [${peerAddress.asStringUriOnly()}] with contact in notifications, updating it"
|
||||
)
|
||||
updateConversationNotification(notifiable, peerAddress)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onCallStateChanged(
|
||||
|
|
@ -468,12 +522,15 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
}
|
||||
|
||||
core.addListener(coreListener)
|
||||
|
||||
coreContext.contactsManager.addListener(contactsListener)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun onCoreStopped(core: Core) {
|
||||
Log.i("$TAG Getting destroyed, clearing foreground Service & call notifications")
|
||||
core.removeListener(coreListener)
|
||||
coreContext.contactsManager.removeListener(contactsListener)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
|
|
@ -499,7 +556,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun showCallNotification(call: Call, isIncoming: Boolean) {
|
||||
private fun showCallNotification(call: Call, isIncoming: Boolean, friend: Friend? = null) {
|
||||
val notifiable = getNotifiableForCall(call)
|
||||
|
||||
val callNotificationIntent = Intent(context, CallActivity::class.java)
|
||||
|
|
@ -518,11 +575,11 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
)
|
||||
|
||||
val notification = createCallNotification(
|
||||
context,
|
||||
call,
|
||||
notifiable,
|
||||
pendingIntent,
|
||||
isIncoming
|
||||
isIncoming,
|
||||
friend
|
||||
)
|
||||
if (isIncoming) {
|
||||
currentlyRingingCallRemoteAddress = call.remoteAddress
|
||||
|
|
@ -801,6 +858,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
text,
|
||||
contact,
|
||||
displayName,
|
||||
address.asStringUriOnly(),
|
||||
message.time * 1000, /* Linphone timestamps are in seconds */
|
||||
isOutgoing = false,
|
||||
isReaction = true,
|
||||
|
|
@ -826,6 +884,33 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateConversationNotification(notifiable: Notifiable, remoteAddress: Address) {
|
||||
val localAddress = Factory.instance().createAddress(notifiable.localIdentity.orEmpty())
|
||||
localAddress ?: return
|
||||
val params: ConferenceParams? = null
|
||||
val chatRoom: ChatRoom? = coreContext.core.searchChatRoom(
|
||||
params,
|
||||
localAddress,
|
||||
remoteAddress,
|
||||
arrayOfNulls<Address>(0)
|
||||
)
|
||||
chatRoom ?: return
|
||||
|
||||
val me = coreContext.contactsManager.getMePerson(chatRoom.localAddress)
|
||||
val pendingIntent = getChatRoomPendingIntent(chatRoom, notifiable.notificationId)
|
||||
val notification = createMessageNotification(
|
||||
notifiable,
|
||||
pendingIntent,
|
||||
LinphoneUtils.getChatRoomId(chatRoom),
|
||||
me
|
||||
)
|
||||
Log.i(
|
||||
"$TAG Updating chat notification with ID [${notifiable.notificationId}]"
|
||||
)
|
||||
notify(notifiable.notificationId, notification, CHAT_TAG)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun notify(id: Int, notification: Notification, tag: String? = null) {
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
|
|
@ -876,7 +961,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
var notifiable: Notifiable? = callNotificationsMap[address]
|
||||
if (notifiable == null) {
|
||||
notifiable = Notifiable(getNotificationIdForCall(call))
|
||||
notifiable.remoteAddress = call.remoteAddress.asStringUriOnly()
|
||||
notifiable.remoteAddress = address
|
||||
|
||||
callNotificationsMap[address] = notifiable
|
||||
}
|
||||
|
|
@ -890,10 +975,12 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
val displayName = contact?.name ?: LinphoneUtils.getDisplayName(message.fromAddress)
|
||||
|
||||
val text = LinphoneUtils.getPlainTextDescribingMessage(message)
|
||||
val address = message.fromAddress
|
||||
val notifiableMessage = NotifiableMessage(
|
||||
text,
|
||||
contact,
|
||||
displayName,
|
||||
address.asStringUriOnly(),
|
||||
message.time * 1000, /* Linphone timestamps are in seconds */
|
||||
isOutgoing = message.isOutgoing
|
||||
)
|
||||
|
|
@ -922,11 +1009,11 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
|
||||
@WorkerThread
|
||||
private fun createCallNotification(
|
||||
context: Context,
|
||||
call: Call,
|
||||
notifiable: Notifiable,
|
||||
pendingIntent: PendingIntent?,
|
||||
isIncoming: Boolean
|
||||
isIncoming: Boolean,
|
||||
friend: Friend? = null
|
||||
): Notification {
|
||||
val declineIntent = getCallDeclinePendingIntent(notifiable)
|
||||
val answerIntent = getCallAnswerPendingIntent(notifiable)
|
||||
|
|
@ -953,8 +1040,8 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
.setImportant(false)
|
||||
.build()
|
||||
} else {
|
||||
val contact =
|
||||
coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
val contact = friend
|
||||
?: coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
val displayName = contact?.name ?: LinphoneUtils.getDisplayName(remoteAddress)
|
||||
|
||||
getPerson(contact, displayName)
|
||||
|
|
@ -1036,6 +1123,47 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
return builder.build()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateCallNotification(
|
||||
notifiable: Notifiable,
|
||||
remoteAddress: Address,
|
||||
friend: Friend
|
||||
) {
|
||||
val call = coreContext.core.getCallByRemoteAddress2(remoteAddress)
|
||||
if (call == null) {
|
||||
Log.w(
|
||||
"$TAG Failed to find call with remote SIP URI [${remoteAddress.asStringUriOnly()}]"
|
||||
)
|
||||
return
|
||||
}
|
||||
val isIncoming = LinphoneUtils.isCallIncoming(call.state)
|
||||
|
||||
val notification = notificationsMap[notifiable.notificationId]
|
||||
if (notification == null) {
|
||||
Log.w(
|
||||
"$TAG Failed to find notification with ID [${notifiable.notificationId}], creating a new one"
|
||||
)
|
||||
showCallNotification(call, isIncoming, friend)
|
||||
return
|
||||
}
|
||||
|
||||
val pendingIntent = notification.fullScreenIntent
|
||||
val newNotification = createCallNotification(
|
||||
call,
|
||||
notifiable,
|
||||
pendingIntent,
|
||||
isIncoming,
|
||||
friend
|
||||
)
|
||||
if (isIncoming) {
|
||||
Log.i("$TAG Updating incoming call notification with ID [$INCOMING_CALL_ID]")
|
||||
notify(INCOMING_CALL_ID, newNotification)
|
||||
} else {
|
||||
Log.i("$TAG Updating call notification with ID [${notifiable.notificationId}]")
|
||||
notify(notifiable.notificationId, newNotification)
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createMessageNotification(
|
||||
notifiable: Notifiable,
|
||||
|
|
@ -1078,6 +1206,9 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
|
||||
style.conversationTitle = if (notifiable.isGroup) notifiable.groupTitle else lastPerson?.name
|
||||
style.isGroupConversation = notifiable.isGroup
|
||||
Log.i(
|
||||
"$TAG Conversation is ${if (style.isGroupConversation) "group" else "1-1"} with title [${style.conversationTitle}]"
|
||||
)
|
||||
|
||||
val largeIcon = lastPersonAvatar
|
||||
val notificationBuilder = NotificationCompat.Builder(
|
||||
|
|
@ -1131,7 +1262,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
val notifiable: Notifiable? = chatNotificationsMap[address]
|
||||
if (notifiable != null) {
|
||||
Log.i(
|
||||
"$TAG Dismissing notification for conversation $chatRoom with id ${notifiable.notificationId}"
|
||||
"$TAG Dismissing notification for conversation [${chatRoom.peerAddress.asStringUriOnly()}] with id ${notifiable.notificationId}"
|
||||
)
|
||||
notifiable.messages.clear()
|
||||
cancelNotification(notifiable.notificationId, CHAT_TAG)
|
||||
|
|
@ -1193,6 +1324,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
text,
|
||||
null,
|
||||
notifiable.myself ?: LinphoneUtils.getDisplayName(senderAddress),
|
||||
senderAddress.asStringUriOnly(),
|
||||
System.currentTimeMillis(),
|
||||
isOutgoing = true
|
||||
)
|
||||
|
|
@ -1459,9 +1591,10 @@ class NotificationsManager @MainThread constructor(private val context: Context)
|
|||
}
|
||||
|
||||
class NotifiableMessage(
|
||||
var message: String,
|
||||
val friend: Friend?,
|
||||
val sender: String,
|
||||
val message: String,
|
||||
var friend: Friend?,
|
||||
var sender: String,
|
||||
val senderAddress: String,
|
||||
val time: Long,
|
||||
var filePath: Uri? = null,
|
||||
var fileMime: String? = null,
|
||||
|
|
|
|||
|
|
@ -349,8 +349,8 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
val isAdmin = participantModel.isParticipantAdmin
|
||||
popupView.isParticipantAdmin = isAdmin
|
||||
popupView.isMeAdmin = participantModel.isMyselfAdmin
|
||||
val friendRefKey = participantModel.avatarModel.friend.refKey
|
||||
popupView.isParticipantContact = !friendRefKey.isNullOrEmpty()
|
||||
val friendRefKey = participantModel.refKey
|
||||
popupView.isParticipantContact = participantModel.friendAvailable
|
||||
|
||||
popupView.setRemoveParticipantClickListener {
|
||||
Log.i("$TAG Trying to remove participant [$address]")
|
||||
|
|
@ -372,7 +372,7 @@ class ConversationInfoFragment : SlidingPaneChildFragment() {
|
|||
|
||||
popupView.setSeeContactProfileClickListener {
|
||||
Log.i("$TAG Trying to display participant [$address] contact page")
|
||||
if (!friendRefKey.isNullOrEmpty()) {
|
||||
if (friendRefKey.isNotEmpty()) {
|
||||
sharedViewModel.navigateToContactsEvent.value = Event(true)
|
||||
sharedViewModel.showContactEvent.value = Event(friendRefKey)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import androidx.annotation.UiThread
|
|||
import androidx.annotation.WorkerThread
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Address
|
||||
import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
||||
|
||||
class ParticipantModel @WorkerThread constructor(
|
||||
val address: Address,
|
||||
|
|
@ -36,7 +37,15 @@ class ParticipantModel @WorkerThread constructor(
|
|||
) {
|
||||
val sipUri = address.asStringUriOnly()
|
||||
|
||||
val avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val avatarModel: ContactAvatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(
|
||||
address
|
||||
)
|
||||
|
||||
val refKey: String = avatarModel.friend.refKey.orEmpty()
|
||||
|
||||
val friendAvailable: Boolean = coreContext.contactsManager.isContactAvailable(
|
||||
avatarModel.friend
|
||||
)
|
||||
|
||||
@UiThread
|
||||
fun onClicked() {
|
||||
|
|
|
|||
|
|
@ -76,6 +76,8 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
|
||||
val oneToOneParticipantRefKey = MutableLiveData<String>()
|
||||
|
||||
val friendAvailable = MutableLiveData<Boolean>()
|
||||
|
||||
val groupLeftEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
|
@ -201,6 +203,9 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
Log.i("$TAG Contacts have been (re)loaded, updating list")
|
||||
computeParticipantsList()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
@ -497,7 +502,13 @@ class ConversationInfoViewModel @UiThread constructor() : AbstractConversationVi
|
|||
sipUri.postValue(uri)
|
||||
|
||||
val friend = coreContext.contactsManager.findContactByAddress(address)
|
||||
oneToOneParticipantRefKey.postValue(friend?.refKey ?: "")
|
||||
if (friend == null) {
|
||||
oneToOneParticipantRefKey.postValue("")
|
||||
friendAvailable.postValue(false)
|
||||
} else {
|
||||
oneToOneParticipantRefKey.postValue(friend.refKey)
|
||||
friendAvailable.postValue(coreContext.contactsManager.isContactAvailable(friend))
|
||||
}
|
||||
}
|
||||
|
||||
ephemeralLifetime.postValue(
|
||||
|
|
|
|||
|
|
@ -301,6 +301,9 @@ class ConversationViewModel @UiThread constructor() : AbstractConversationViewMo
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import org.linphone.core.ChatMessage
|
|||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.chat.model.ConversationModel
|
||||
import org.linphone.ui.main.viewmodel.AbstractMainViewModel
|
||||
|
|
@ -86,6 +87,9 @@ class ConversationsListViewModel @UiThread constructor() : AbstractMainViewModel
|
|||
model.updateLastMessage()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
|||
|
|
@ -186,6 +186,9 @@ class ContactViewModel @UiThread constructor() : GenericViewModel() {
|
|||
refreshContactInfo()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
private val chatRoomListener = object : ChatRoomListenerStub() {
|
||||
|
|
|
|||
|
|
@ -90,6 +90,9 @@ class ContactsListViewModel @UiThread constructor() : AbstractMainViewModel() {
|
|||
domainFilter
|
||||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
@ -281,15 +284,19 @@ class ContactsListViewModel @UiThread constructor() : AbstractMainViewModel() {
|
|||
|
||||
for (result in results) {
|
||||
val friend = result.friend
|
||||
if (friend != null && friend.refKey.orEmpty().isEmpty()) {
|
||||
if (friend.vcard != null) {
|
||||
friend.vcard?.generateUniqueId()
|
||||
friend.refKey = friend.vcard?.uid
|
||||
} else {
|
||||
Log.w(
|
||||
"$TAG Friend [${friend.name}] found in SearchResults doesn't have a refKey, using name instead"
|
||||
)
|
||||
friend.refKey = friend.name
|
||||
if (friend != null) {
|
||||
if (coreContext.contactsManager.isContactTemporary(friend)) continue
|
||||
|
||||
if (friend.refKey.orEmpty().isEmpty()) {
|
||||
if (friend.vcard != null) {
|
||||
friend.vcard?.generateUniqueId()
|
||||
friend.refKey = friend.vcard?.uid
|
||||
} else {
|
||||
Log.w(
|
||||
"$TAG Friend [${friend.name}] found in SearchResults doesn't have a refKey, using name instead"
|
||||
)
|
||||
friend.refKey = friend.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ class CallLogModel @WorkerThread constructor(private val callLog: CallLog) {
|
|||
avatarModel = coreContext.contactsManager.getContactAvatarModelForAddress(address)
|
||||
val friend = avatarModel.friend
|
||||
friendRefKey = friend.refKey
|
||||
friendExists = !friendRefKey.isNullOrEmpty()
|
||||
friendExists = coreContext.contactsManager.isContactAvailable(friend)
|
||||
}
|
||||
displayedAddress = if (corePreferences.onlyDisplaySipUriUsername) {
|
||||
avatarModel.friend.address?.username ?: address.username ?: ""
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import org.linphone.contacts.ContactsManager
|
|||
import org.linphone.core.CallLog
|
||||
import org.linphone.core.Core
|
||||
import org.linphone.core.CoreListenerStub
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.GlobalState
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.history.model.CallLogModel
|
||||
|
|
@ -72,6 +73,9 @@ class HistoryListViewModel @UiThread constructor() : AbstractMainViewModel() {
|
|||
Log.i("$TAG Contacts have been (re)loaded, updating list")
|
||||
computeCallLogsList(currentFilter)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import org.linphone.R
|
|||
import org.linphone.contacts.ContactsManager
|
||||
import org.linphone.core.Address
|
||||
import org.linphone.core.ChatRoom
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.MagicSearch
|
||||
import org.linphone.core.MagicSearchListenerStub
|
||||
import org.linphone.core.SearchResult
|
||||
|
|
@ -87,6 +88,9 @@ abstract class AddressSelectionViewModel @UiThread constructor() : DefaultAccoun
|
|||
magicSearchSourceFlags
|
||||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onContactFoundInRemoteDirectory(friend: Friend) { }
|
||||
}
|
||||
|
||||
init {
|
||||
|
|
|
|||
|
|
@ -400,7 +400,7 @@
|
|||
android:drawableStart="@drawable/address_book"
|
||||
android:onClick="@{goToContactClickListener}"
|
||||
android:text="@string/conversation_info_menu_go_to_contact"
|
||||
android:visibility="@{!viewModel.isGroup && viewModel.oneToOneParticipantRefKey.length() != 0 ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{!viewModel.isGroup && viewModel.friendAvailable ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/actions_background"
|
||||
app:layout_constraintStart_toStartOf="@id/actions_background"
|
||||
app:layout_constraintTop_toTopOf="@id/actions_background" />
|
||||
|
|
@ -424,7 +424,7 @@
|
|||
android:drawableStart="@drawable/user_plus"
|
||||
android:onClick="@{addToContactsClickListener}"
|
||||
android:text="@string/conversation_info_menu_add_to_contacts"
|
||||
android:visibility="@{!viewModel.isGroup && viewModel.oneToOneParticipantRefKey.length() == 0 ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:visibility="@{!viewModel.isGroup && !viewModel.friendAvailable ? View.VISIBLE : View.GONE, default=gone}"
|
||||
app:layout_constraintEnd_toEndOf="@id/actions_background"
|
||||
app:layout_constraintStart_toStartOf="@id/actions_background"
|
||||
app:layout_constraintTop_toBottomOf="@id/action_see_contact" />
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue