Show contacts consolidated presence if not offline + updated EXPIRE for sip.linphone.org from 1 year to 1 month
This commit is contained in:
parent
536bfd0020
commit
dc65d27603
35 changed files with 537 additions and 55 deletions
|
@ -3,11 +3,11 @@
|
|||
<section name="proxy_default_values">
|
||||
<entry name="avpf" overwrite="true">1</entry>
|
||||
<entry name="dial_escape_plus" overwrite="true">0</entry>
|
||||
<entry name="publish" overwrite="true">0</entry>
|
||||
<entry name="publish" overwrite="true">1</entry>
|
||||
<entry name="quality_reporting_collector" overwrite="true">sip:voip-metrics@sip.linphone.org;transport=tls</entry>
|
||||
<entry name="quality_reporting_enabled" overwrite="true">1</entry>
|
||||
<entry name="quality_reporting_interval" overwrite="true">180</entry>
|
||||
<entry name="reg_expires" overwrite="true">31536000</entry>
|
||||
<entry name="reg_expires" overwrite="true">2629800</entry>
|
||||
<entry name="reg_identity" overwrite="true">sip:?@sip.linphone.org</entry>
|
||||
<entry name="reg_proxy" overwrite="true"><sip:sip.linphone.org;transport=tls></entry>
|
||||
<entry name="reg_route" overwrite="true"><sip:sip.linphone.org;transport=tls></entry>
|
||||
|
|
|
@ -43,6 +43,7 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface {
|
|||
override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
override val showGroupChatAvatar: Boolean
|
||||
get() = conferenceChatRoom && !oneToOneChatRoom
|
||||
override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
override val coroutineScope: CoroutineScope = coreContext.coroutineScope
|
||||
|
||||
val unreadMessagesCount = MutableLiveData<Int>()
|
||||
|
@ -79,6 +80,7 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface {
|
|||
|
||||
init {
|
||||
unreadMessagesCount.value = chatRoom.unreadMessagesCount
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
|
||||
subject.value = chatRoom.subject
|
||||
updateSecurityIcon()
|
||||
|
@ -135,7 +137,14 @@ class ChatRoomData(private val chatRoom: ChatRoom) : ContactDataInterface {
|
|||
}
|
||||
}
|
||||
if (remoteAddress != null) {
|
||||
contact.value = coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
val friend = coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -595,12 +595,6 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
}
|
||||
}
|
||||
|
||||
binding.setTitleClickListener {
|
||||
binding.sipUri.visibility = if (!viewModel.oneToOneChatRoom ||
|
||||
binding.sipUri.visibility == View.VISIBLE
|
||||
) View.GONE else View.VISIBLE
|
||||
}
|
||||
|
||||
binding.setMenuClickListener {
|
||||
showPopupMenu(chatRoom)
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.linphone.core.*
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
import org.linphone.utils.TimestampUtils
|
||||
|
||||
class ChatRoomViewModelFactory(private val chatRoom: ChatRoom) :
|
||||
ViewModelProvider.NewInstanceFactory() {
|
||||
|
@ -51,6 +52,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
override val showGroupChatAvatar: Boolean
|
||||
get() = conferenceChatRoom && !oneToOneChatRoom
|
||||
override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
override val coroutineScope: CoroutineScope = viewModelScope
|
||||
|
||||
val subject = MutableLiveData<String>()
|
||||
|
@ -67,7 +69,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
|
||||
val securityLevelContentDescription = MutableLiveData<Int>()
|
||||
|
||||
val peerSipUri = MutableLiveData<String>()
|
||||
val lastPresenceInfo = MutableLiveData<String>()
|
||||
|
||||
val ephemeralEnabled = MutableLiveData<Boolean>()
|
||||
|
||||
|
@ -230,6 +232,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
}
|
||||
|
||||
fun contactLookup() {
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
displayName.value = when {
|
||||
basicChatRoom -> LinphoneUtils.getDisplayName(
|
||||
chatRoom.peerAddress
|
||||
|
@ -304,7 +307,42 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
private fun searchMatchingContact() {
|
||||
val remoteAddress = getRemoteAddress()
|
||||
if (remoteAddress != null) {
|
||||
contact.value = coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
val friend = coreContext.contactsManager.findContactByAddress(remoteAddress)
|
||||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
computeLastSeenLabel(friend)
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
computeLastSeenLabel(friend)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun computeLastSeenLabel(friend: Friend) {
|
||||
if (friend.consolidatedPresence == ConsolidatedPresence.Online) {
|
||||
lastPresenceInfo.value = AppUtils.getString(R.string.chat_room_presence_online)
|
||||
return
|
||||
}
|
||||
|
||||
val timestamp = friend.presenceModel?.timestamp ?: -1
|
||||
lastPresenceInfo.value = when {
|
||||
TimestampUtils.isToday(timestamp) -> {
|
||||
val time = TimestampUtils.timeToString(timestamp, timestampInSecs = true)
|
||||
val text = AppUtils.getString(R.string.chat_room_presence_last_seen_online_today)
|
||||
"$text $time"
|
||||
}
|
||||
TimestampUtils.isYesterday(timestamp) -> {
|
||||
val time = TimestampUtils.timeToString(timestamp, timestampInSecs = true)
|
||||
val text = AppUtils.getString(R.string.chat_room_presence_last_seen_online_yesterday)
|
||||
"$text $time"
|
||||
}
|
||||
else -> {
|
||||
val date = TimestampUtils.toString(timestamp, onlyDate = true, shortDate = false, hideYear = true)
|
||||
val text = AppUtils.getString(R.string.chat_room_presence_last_seen_online)
|
||||
"$text $date"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -354,12 +392,6 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactDataInterf
|
|||
|
||||
private fun updateParticipants() {
|
||||
val participants = chatRoom.participants
|
||||
peerSipUri.value = if (oneToOneChatRoom && !basicChatRoom) {
|
||||
participants.firstOrNull()?.address?.asStringUriOnly()
|
||||
?: chatRoom.peerAddress.asStringUriOnly()
|
||||
} else {
|
||||
chatRoom.peerAddress.asStringUriOnly()
|
||||
}
|
||||
|
||||
oneParticipantOneDevice = oneToOneChatRoom &&
|
||||
chatRoom.me?.devices?.size == 1 &&
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.linphone.LinphoneApplication.Companion.corePreferences
|
|||
import org.linphone.R
|
||||
import org.linphone.contact.*
|
||||
import org.linphone.core.ChatRoomSecurityLevel
|
||||
import org.linphone.core.ConsolidatedPresence
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.utils.AppUtils
|
||||
|
@ -42,6 +43,7 @@ class ContactEditorData(val friend: Friend?) : ContactDataInterface {
|
|||
override val contact: MutableLiveData<Friend> = MutableLiveData<Friend>()
|
||||
override val displayName: MutableLiveData<String> = MutableLiveData<String>()
|
||||
override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
override val coroutineScope: CoroutineScope = coreContext.coroutineScope
|
||||
|
||||
val firstName = MutableLiveData<String>()
|
||||
|
@ -66,8 +68,13 @@ class ContactEditorData(val friend: Friend?) : ContactDataInterface {
|
|||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
displayName.value = friend.name ?: ""
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
} else {
|
||||
displayName.value = ""
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
}
|
||||
|
||||
organization.value = friend?.organization ?: ""
|
||||
|
|
|
@ -54,6 +54,7 @@ class ContactViewModel(friend: Friend, async: Boolean = false) : MessageNotifier
|
|||
override val contact: MutableLiveData<Friend> = MutableLiveData<Friend>()
|
||||
override val displayName: MutableLiveData<String> = MutableLiveData<String>()
|
||||
override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
override val coroutineScope: CoroutineScope = viewModelScope
|
||||
|
||||
var fullName = ""
|
||||
|
@ -142,10 +143,16 @@ class ContactViewModel(friend: Friend, async: Boolean = false) : MessageNotifier
|
|||
contact.postValue(friend)
|
||||
displayName.postValue(friend.name)
|
||||
isNativeContact.postValue(friend.refKey != null)
|
||||
presenceStatus.postValue(friend.consolidatedPresence)
|
||||
} else {
|
||||
contact.value = friend
|
||||
displayName.value = friend.name
|
||||
isNativeContact.value = friend.refKey != null
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
}
|
||||
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,14 @@ class AccountSettingsFragment : GenericSettingFragment<SettingsAccountFragmentBi
|
|||
}
|
||||
}
|
||||
|
||||
viewModel.publishPresenceToggledEvent.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume {
|
||||
sharedViewModel.publishPresenceToggled.value = true
|
||||
}
|
||||
}
|
||||
|
||||
view.doOnPreDraw {
|
||||
// Notifies fragment is ready to be drawn
|
||||
sharedViewModel.accountSettingsFragmentOpenedEvent.value = Event(true)
|
||||
|
|
|
@ -74,6 +74,10 @@ class AccountSettingsViewModel(val account: Account) : GenericSettingsViewModel(
|
|||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val publishPresenceToggledEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
||||
val displayUsernameInsteadOfIdentity = corePreferences.replaceSipUriByUsername
|
||||
|
||||
private var accountToDelete: Account? = null
|
||||
|
@ -436,6 +440,16 @@ class AccountSettingsViewModel(val account: Account) : GenericSettingsViewModel(
|
|||
}
|
||||
val limeServerUrl = MutableLiveData<String>()
|
||||
|
||||
val publishPresenceListener = object : SettingListenerStub() {
|
||||
override fun onBoolValueChanged(newValue: Boolean) {
|
||||
val params = account.params.clone()
|
||||
params.isPublishEnabled = newValue
|
||||
account.params = params
|
||||
publishPresenceToggledEvent.value = Event(true)
|
||||
}
|
||||
}
|
||||
val publishPresence = MutableLiveData<Boolean>()
|
||||
|
||||
init {
|
||||
update()
|
||||
account.addListener(listener)
|
||||
|
@ -496,6 +510,7 @@ class AccountSettingsViewModel(val account: Account) : GenericSettingsViewModel(
|
|||
limeServerUrl.value = params.limeServerUrl
|
||||
|
||||
hideLinkPhoneNumber.value = corePreferences.hideLinkPhoneNumber || params.identityAddress?.domain != corePreferences.defaultDomain
|
||||
publishPresence.value = params.isPublishEnabled
|
||||
}
|
||||
|
||||
private fun initTransportList() {
|
||||
|
|
|
@ -74,6 +74,12 @@ class SideMenuFragment : GenericFragment<SideMenuFragmentBinding>() {
|
|||
viewModel.updateAccountsList()
|
||||
}
|
||||
|
||||
sharedViewModel.publishPresenceToggled.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
viewModel.refreshConsolidatedPresence()
|
||||
}
|
||||
|
||||
viewModel.accountsSettingsListener = object : SettingListenerStub() {
|
||||
override fun onAccountClicked(identity: String) {
|
||||
val args = Bundle()
|
||||
|
|
|
@ -43,6 +43,8 @@ class SideMenuViewModel : ViewModel() {
|
|||
|
||||
val accounts = MutableLiveData<ArrayList<AccountSettingsViewModel>>()
|
||||
|
||||
val presenceStatus = MutableLiveData<ConsolidatedPresence>()
|
||||
|
||||
lateinit var accountsSettingsListener: SettingListenerStub
|
||||
|
||||
private val listener: CoreListenerStub = object : CoreListenerStub() {
|
||||
|
@ -69,6 +71,7 @@ class SideMenuViewModel : ViewModel() {
|
|||
LinphoneUtils.isRemoteConferencingAvailable()
|
||||
coreContext.core.addListener(listener)
|
||||
updateAccountsList()
|
||||
refreshConsolidatedPresence()
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
|
@ -78,6 +81,10 @@ class SideMenuViewModel : ViewModel() {
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
fun refreshConsolidatedPresence() {
|
||||
presenceStatus.value = coreContext.core.consolidatedPresence
|
||||
}
|
||||
|
||||
fun updateAccountsList() {
|
||||
defaultAccountFound.value = false // Do not assume a default account will still be found
|
||||
defaultAccountViewModel.value?.destroy()
|
||||
|
|
|
@ -88,9 +88,17 @@ class SharedMainViewModel : ViewModel() {
|
|||
|
||||
/* Accounts */
|
||||
|
||||
val defaultAccountChanged = MutableLiveData<Boolean>()
|
||||
val defaultAccountChanged: MutableLiveData<Boolean> by lazy {
|
||||
MutableLiveData<Boolean>()
|
||||
}
|
||||
|
||||
val accountRemoved = MutableLiveData<Boolean>()
|
||||
val accountRemoved: MutableLiveData<Boolean> by lazy {
|
||||
MutableLiveData<Boolean>()
|
||||
}
|
||||
|
||||
val publishPresenceToggled: MutableLiveData<Boolean> by lazy {
|
||||
MutableLiveData<Boolean>()
|
||||
}
|
||||
|
||||
val accountSettingsFragmentOpenedEvent: MutableLiveData<Event<Boolean>> by lazy {
|
||||
MutableLiveData<Event<Boolean>>()
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.linphone.LinphoneApplication.Companion.coreContext
|
|||
import org.linphone.activities.main.viewmodels.MessageNotifierViewModel
|
||||
import org.linphone.core.Address
|
||||
import org.linphone.core.ChatRoomSecurityLevel
|
||||
import org.linphone.core.ConsolidatedPresence
|
||||
import org.linphone.core.Friend
|
||||
import org.linphone.utils.LinphoneUtils
|
||||
|
||||
|
@ -39,6 +40,8 @@ interface ContactDataInterface {
|
|||
val showGroupChatAvatar: Boolean
|
||||
get() = false
|
||||
|
||||
val presenceStatus: MutableLiveData<ConsolidatedPresence>
|
||||
|
||||
val coroutineScope: CoroutineScope
|
||||
}
|
||||
|
||||
|
@ -46,10 +49,12 @@ open class GenericContactData(private val sipAddress: Address) : ContactDataInte
|
|||
final override val contact: MutableLiveData<Friend> = MutableLiveData<Friend>()
|
||||
final override val displayName: MutableLiveData<String> = MutableLiveData<String>()
|
||||
final override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
final override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
final override val coroutineScope: CoroutineScope = coreContext.coroutineScope
|
||||
|
||||
init {
|
||||
securityLevel.value = ChatRoomSecurityLevel.ClearText
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
contactLookup()
|
||||
}
|
||||
|
||||
|
@ -59,9 +64,13 @@ open class GenericContactData(private val sipAddress: Address) : ContactDataInte
|
|||
private fun contactLookup() {
|
||||
displayName.value = LinphoneUtils.getDisplayName(sipAddress)
|
||||
|
||||
val c = coreContext.contactsManager.findContactByAddress(sipAddress)
|
||||
if (c != null) {
|
||||
contact.value = c!!
|
||||
val friend = coreContext.contactsManager.findContactByAddress(sipAddress)
|
||||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,15 +79,24 @@ abstract class GenericContactViewModel(private val sipAddress: Address) : Messag
|
|||
final override val contact: MutableLiveData<Friend> = MutableLiveData<Friend>()
|
||||
final override val displayName: MutableLiveData<String> = MutableLiveData<String>()
|
||||
final override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
final override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
final override val coroutineScope: CoroutineScope = viewModelScope
|
||||
|
||||
init {
|
||||
securityLevel.value = ChatRoomSecurityLevel.ClearText
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
contactLookup()
|
||||
}
|
||||
|
||||
private fun contactLookup() {
|
||||
displayName.value = LinphoneUtils.getDisplayName(sipAddress)
|
||||
contact.value = coreContext.contactsManager.findContactByAddress(sipAddress)
|
||||
val friend = coreContext.contactsManager.findContactByAddress(sipAddress)
|
||||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ class ContactSelectionData(private val searchResult: SearchResult) : ContactData
|
|||
override val contact: MutableLiveData<Friend> = MutableLiveData<Friend>()
|
||||
override val displayName: MutableLiveData<String> = MutableLiveData<String>()
|
||||
override val securityLevel: MutableLiveData<ChatRoomSecurityLevel> = MutableLiveData<ChatRoomSecurityLevel>()
|
||||
override val presenceStatus: MutableLiveData<ConsolidatedPresence> = MutableLiveData<ConsolidatedPresence>()
|
||||
override val coroutineScope: CoroutineScope = coreContext.coroutineScope
|
||||
|
||||
val isDisabled: MutableLiveData<Boolean> by lazy {
|
||||
|
@ -57,6 +58,7 @@ class ContactSelectionData(private val searchResult: SearchResult) : ContactData
|
|||
init {
|
||||
isDisabled.value = false
|
||||
isSelected.value = false
|
||||
presenceStatus.value = ConsolidatedPresence.Offline
|
||||
searchMatchingContact()
|
||||
}
|
||||
|
||||
|
@ -65,14 +67,31 @@ class ContactSelectionData(private val searchResult: SearchResult) : ContactData
|
|||
if (friend != null) {
|
||||
contact.value = friend!!
|
||||
displayName.value = friend.name
|
||||
presenceStatus.value = friend.consolidatedPresence
|
||||
friend.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
} else {
|
||||
val address = searchResult.address
|
||||
if (address != null) {
|
||||
contact.value = coreContext.contactsManager.findContactByAddress(address)
|
||||
val found = coreContext.contactsManager.findContactByAddress(address)
|
||||
if (found != null) {
|
||||
contact.value = found!!
|
||||
presenceStatus.value = found.consolidatedPresence
|
||||
found.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
displayName.value = LinphoneUtils.getDisplayName(address)
|
||||
} else if (searchResult.phoneNumber != null) {
|
||||
contact.value =
|
||||
coreContext.contactsManager.findContactByPhoneNumber(searchResult.phoneNumber.orEmpty())
|
||||
val found = coreContext.contactsManager.findContactByPhoneNumber(searchResult.phoneNumber.orEmpty())
|
||||
if (found != null) {
|
||||
contact.value = found!!
|
||||
presenceStatus.value = found.consolidatedPresence
|
||||
found.addListener {
|
||||
presenceStatus.value = it.consolidatedPresence
|
||||
}
|
||||
}
|
||||
displayName.value = searchResult.phoneNumber.orEmpty()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -281,7 +281,7 @@ class ContactsManager(private val context: Context) {
|
|||
|
||||
@Synchronized
|
||||
private fun refreshContactOnPresenceReceived(friend: Friend) {
|
||||
Log.d("[Contacts Manager] Received presence information for contact $friend")
|
||||
Log.d("[Contacts Manager] Received presence information for contact [${friend.name}]: [${friend.consolidatedPresence}]")
|
||||
if (corePreferences.storePresenceInNativeContact && PermissionHelper.get().hasWriteContactsPermission()) {
|
||||
if (friend.refKey != null) {
|
||||
Log.i("[Contacts Manager] Storing presence in native contact ${friend.refKey}")
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.core
|
||||
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
|
@ -127,6 +128,8 @@ class CoreContext(
|
|||
private var previousCallState = Call.State.Idle
|
||||
private lateinit var phoneStateListener: PhoneStateInterface
|
||||
|
||||
private val activityMonitor = ActivityMonitor()
|
||||
|
||||
private val listener: CoreListenerStub = object : CoreListenerStub() {
|
||||
override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||
Log.i("[Context] Global state changed [$state]")
|
||||
|
@ -309,6 +312,8 @@ class CoreContext(
|
|||
|
||||
stopped = false
|
||||
_lifecycleRegistry.currentState = Lifecycle.State.CREATED
|
||||
|
||||
(context as Application).registerActivityLifecycleCallbacks(activityMonitor)
|
||||
Log.i("[Context] Ready")
|
||||
}
|
||||
|
||||
|
@ -374,6 +379,24 @@ class CoreContext(
|
|||
stopped = true
|
||||
_lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
|
||||
loggingService.removeListener(loggingServiceListener)
|
||||
|
||||
(context as Application).unregisterActivityLifecycleCallbacks(activityMonitor)
|
||||
}
|
||||
|
||||
fun onForeground() {
|
||||
// If presence publish is disabled and we call core.setConsolidatedPresence, it will enabled it!
|
||||
if (core.defaultAccount?.params?.isPublishEnabled == true) {
|
||||
Log.i("[Context] App is in foreground, setting consolidated presence to Online")
|
||||
core.consolidatedPresence = ConsolidatedPresence.Online
|
||||
}
|
||||
}
|
||||
|
||||
fun onBackground() {
|
||||
// If presence publish is disabled and we call core.setConsolidatedPresence, it will enabled it!
|
||||
if (core.defaultAccount?.params?.isPublishEnabled == true) {
|
||||
Log.i("[Context] App is in background, setting consolidated presence to Busy")
|
||||
core.consolidatedPresence = ConsolidatedPresence.Busy
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureCore() {
|
||||
|
@ -411,11 +434,30 @@ class CoreContext(
|
|||
|
||||
computeUserAgent()
|
||||
|
||||
val fiveOneMigrationRequired = core.config.getBool("app", "migration_5.1", true)
|
||||
core.config.setBool("app", "migration_5.1", false)
|
||||
|
||||
for (account in core.accountList) {
|
||||
if (account.params.identityAddress?.domain == corePreferences.defaultDomain) {
|
||||
var paramsChanged = false
|
||||
val params = account.params.clone()
|
||||
|
||||
if (fiveOneMigrationRequired) {
|
||||
val newExpire = 2629800 // 1 month
|
||||
if (account.params.expires != newExpire) {
|
||||
Log.i("[Context] Updating expire on proxy config ${params.identityAddress?.asString()} from ${account.params.expires} to newExpire")
|
||||
params.expires = newExpire
|
||||
paramsChanged = true
|
||||
}
|
||||
|
||||
// Enable presence publish/subscribe for new feature
|
||||
if (!account.params.isPublishEnabled) {
|
||||
Log.i("[Context] Enabling presence publish on proxy config ${params.identityAddress?.asString()}")
|
||||
params.isPublishEnabled = true
|
||||
paramsChanged = true
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure conference factory URI is set on sip.linphone.org proxy configs
|
||||
if (account.params.conferenceFactoryUri == null) {
|
||||
val uri = corePreferences.conferenceServerUri
|
||||
|
|
121
app/src/main/java/org/linphone/utils/ActivityMonitor.kt
Normal file
121
app/src/main/java/org/linphone/utils/ActivityMonitor.kt
Normal file
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2021 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.utils
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application.ActivityLifecycleCallbacks
|
||||
import android.os.Bundle
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.tools.service.AndroidDispatcher
|
||||
import org.linphone.core.tools.service.CoreManager
|
||||
|
||||
class ActivityMonitor : ActivityLifecycleCallbacks {
|
||||
private val activities = ArrayList<Activity>()
|
||||
private var mActive = false
|
||||
private var mRunningActivities = 0
|
||||
private var mLastChecker: InactivityChecker? = null
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
if (!activities.contains(activity)) activities.add(activity)
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
if (!activities.contains(activity)) {
|
||||
activities.add(activity)
|
||||
}
|
||||
mRunningActivities++
|
||||
checkActivity()
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
if (!activities.contains(activity)) {
|
||||
activities.add(activity)
|
||||
} else {
|
||||
mRunningActivities--
|
||||
checkActivity()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
activities.remove(activity)
|
||||
}
|
||||
|
||||
private fun startInactivityChecker() {
|
||||
if (mLastChecker != null) mLastChecker!!.cancel()
|
||||
AndroidDispatcher.dispatchOnUIThreadAfter(
|
||||
InactivityChecker().also { mLastChecker = it },
|
||||
2000
|
||||
)
|
||||
}
|
||||
|
||||
private fun checkActivity() {
|
||||
if (mRunningActivities == 0) {
|
||||
if (mActive) startInactivityChecker()
|
||||
} else if (mRunningActivities > 0) {
|
||||
if (!mActive) {
|
||||
mActive = true
|
||||
onForegroundMode()
|
||||
}
|
||||
if (mLastChecker != null) {
|
||||
mLastChecker!!.cancel()
|
||||
mLastChecker = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onBackgroundMode() {
|
||||
coreContext.onBackground()
|
||||
}
|
||||
|
||||
private fun onForegroundMode() {
|
||||
coreContext.onForeground()
|
||||
}
|
||||
|
||||
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
|
||||
internal inner class InactivityChecker : Runnable {
|
||||
private var isCanceled = false
|
||||
fun cancel() {
|
||||
isCanceled = true
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (CoreManager.isReady()) {
|
||||
synchronized(CoreManager.instance()) {
|
||||
if (!isCanceled) {
|
||||
if (mRunningActivities == 0 && mActive) {
|
||||
mActive = false
|
||||
onBackgroundMode()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
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/led_registration_in_progress"/>
|
||||
<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/led_registered"/>
|
||||
<size android:width="15dp" android:height="15dp"/>
|
||||
</shape>
|
|
@ -7,6 +7,7 @@
|
|||
<import type="android.view.View" />
|
||||
<import type="android.view.Gravity" />
|
||||
<import type="com.google.android.flexbox.JustifyContent" />
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="contextMenuClickListener"
|
||||
type="android.view.View.OnLongClickListener" />
|
||||
|
@ -75,6 +76,18 @@
|
|||
android:gravity="center"
|
||||
android:visibility="@{data.chatMessage.outgoing || selectionListViewModel.isEditionEnabled ? View.GONE : (data.hideAvatar ? View.INVISIBLE : View.VISIBLE)}" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="35dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.chatMessage.outgoing || selectionListViewModel.isEditionEnabled || data.hideAvatar || data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/background"
|
||||
backgroundImage="@{data.backgroundRes, default=@drawable/chat_bubble_outgoing_full}"
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<variable
|
||||
name="titleClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="menuClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -77,7 +75,6 @@
|
|||
android:paddingEnd="5dp">
|
||||
|
||||
<org.linphone.views.MarqueeTextView
|
||||
android:onClick="@{titleClickListener}"
|
||||
android:text="@{viewModel.oneToOneChatRoom ? (viewModel.contact.name ?? viewModel.displayName) : viewModel.subject, default=`Lorem Ipsum Dolor Sit Amet`}"
|
||||
style="@style/toolbar_small_title_font"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -86,17 +83,17 @@
|
|||
|
||||
<org.linphone.views.MarqueeTextView
|
||||
android:text="@{viewModel.participants, default=`John Doe`}"
|
||||
android:visibility="@{viewModel.oneToOneChatRoom ? View.GONE : View.VISIBLE}"
|
||||
android:visibility="@{viewModel.oneToOneChatRoom ? View.GONE : View.VISIBLE, default=gone}"
|
||||
style="@style/toolbar_small_title_font"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<org.linphone.views.MarqueeTextView
|
||||
android:id="@+id/sip_uri"
|
||||
android:text="@{viewModel.peerSipUri, default=`sip:john.doe@sip.linphone.org`}"
|
||||
android:visibility="gone"
|
||||
style="@style/sip_uri_small_font"
|
||||
android:id="@+id/last_seen_at"
|
||||
android:text="@{viewModel.lastPresenceInfo, default=`Online`}"
|
||||
android:visibility="@{viewModel.oneToOneChatRoom && viewModel.presenceStatus != ConsolidatedPresence.Offline ? View.VISIBLE : View.GONE}"
|
||||
style="@style/chat_last_seen_at_font"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="data"
|
||||
type="org.linphone.activities.main.chat.data.DevicesListGroupData" />
|
||||
|
@ -29,6 +30,7 @@
|
|||
android:layout_centerVertical="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar_icon"
|
||||
coilContact="@{data}"
|
||||
android:layout_width="@dimen/contact_avatar_size"
|
||||
android:layout_height="@dimen/contact_avatar_size"
|
||||
|
@ -38,6 +40,18 @@
|
|||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar_icon"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ChatRoomSecurityLevel"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="removeClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -27,6 +28,7 @@
|
|||
android:layout_centerVertical="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar_icon"
|
||||
coilContact="@{data}"
|
||||
android:layout_width="@dimen/contact_avatar_size"
|
||||
android:layout_height="@dimen/contact_avatar_size"
|
||||
|
@ -36,6 +38,18 @@
|
|||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar_icon"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<ImageView
|
||||
android:visibility="@{isEncrypted && data.securityLevel == ChatRoomSecurityLevel.ClearText ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="20dp"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="data"
|
||||
type="org.linphone.activities.main.chat.data.ImdnParticipantData" />
|
||||
|
@ -18,12 +19,25 @@
|
|||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/contact_avatar_size"
|
||||
android:layout_height="@dimen/contact_avatar_size"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="10dp"
|
||||
coilContact="@{data}"
|
||||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null"
|
||||
android:layout_centerVertical="true"/>
|
||||
android:contentDescription="@null"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginBottom="-3dp"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/time"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="clickListener"
|
||||
type="android.view.View.OnClickListener" />
|
||||
|
@ -50,6 +51,19 @@
|
|||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}"
|
||||
app:layout_constraintStart_toStartOf="@id/avatar"
|
||||
app:layout_constraintBottom_toBottomOf="@id/avatar"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/securityLevel"
|
||||
android:layout_width="20dp"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View" />
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="deleteClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -82,14 +83,31 @@
|
|||
android:orientation="vertical"
|
||||
android:paddingTop="20dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/contact_avatar_big_size"
|
||||
android:layout_height="@dimen/contact_avatar_big_size"
|
||||
coilContactBig="@{viewModel}"
|
||||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_width="@dimen/contact_avatar_big_size"
|
||||
android:layout_height="@dimen/contact_avatar_big_size"
|
||||
coilContactBig="@{viewModel}"
|
||||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_big_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_big_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="70dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:src="@{viewModel.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:text="@{viewModel.contact.name ?? viewModel.displayName}"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="clickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -43,6 +44,17 @@
|
|||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:src="@{viewModel.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/right"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="clickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -31,6 +32,7 @@
|
|||
android:layout_centerVertical="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar_icon"
|
||||
coilContact="@{data}"
|
||||
android:layout_width="@dimen/contact_avatar_size"
|
||||
android:layout_height="@dimen/contact_avatar_size"
|
||||
|
@ -40,6 +42,18 @@
|
|||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar_icon"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:contentDescription="@{data.presenceStatus == ConsolidatedPresence.Online ? @string/content_description_presence_online : @string/content_description_presence_offline}"
|
||||
android:src="@{data.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{data.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<ImageView
|
||||
android:visibility="@{data.hasLimeX3DHCapability ? View.VISIBLE : View.GONE, default=gone}"
|
||||
android:layout_width="20dp"
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="newContactClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -83,15 +84,32 @@
|
|||
android:paddingTop="10dp"
|
||||
android:paddingBottom="5dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="@dimen/contact_avatar_big_size"
|
||||
android:layout_height="@dimen/contact_avatar_big_size"
|
||||
coilContactBig="@{viewModel}"
|
||||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/avatar"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_width="@dimen/contact_avatar_big_size"
|
||||
android:layout_height="@dimen/contact_avatar_big_size"
|
||||
coilContactBig="@{viewModel}"
|
||||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_big_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_big_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="70dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:src="@{viewModel.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:text="@{viewModel.contact.name ?? viewModel.displayName}"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
<data>
|
||||
|
||||
<import type="android.view.View" />
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
|
||||
<variable
|
||||
name="clickListener"
|
||||
|
@ -92,6 +93,17 @@
|
|||
android:background="@drawable/generated_avatar_bg"
|
||||
android:src="@drawable/voip_single_contact_avatar" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="25dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:src="@{viewModel.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -127,6 +127,12 @@
|
|||
linphone:checked="@={viewModel.isDefault}"
|
||||
linphone:enabled="@{!viewModel.isDefault}"/>
|
||||
|
||||
<include
|
||||
layout="@layout/settings_widget_switch"
|
||||
linphone:title="@{@string/account_setting_publish_presence_title}"
|
||||
linphone:listener="@{viewModel.publishPresenceListener}"
|
||||
linphone:checked="@={viewModel.publishPresence}"/>
|
||||
|
||||
<include
|
||||
layout="@layout/settings_widget_basic"
|
||||
linphone:title="@{@string/account_settings_link_phone_number_title}"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
<data>
|
||||
<import type="android.view.View"/>
|
||||
<import type="org.linphone.core.ConsolidatedPresence"/>
|
||||
<variable
|
||||
name="selfPictureClickListener"
|
||||
type="android.view.View.OnClickListener"/>
|
||||
|
@ -68,6 +69,17 @@
|
|||
android:src="@drawable/avatar_border"
|
||||
android:visibility="@{viewModel.defaultAccountFound ? View.VISIBLE : View.GONE}" />
|
||||
|
||||
<ImageView
|
||||
android:layout_width="@dimen/contact_presence_badge_size"
|
||||
android:layout_height="@dimen/contact_presence_badge_size"
|
||||
android:layout_alignBottom="@id/avatar"
|
||||
android:layout_marginStart="45dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:background="@drawable/led_background"
|
||||
android:padding="2dp"
|
||||
android:src="@{viewModel.presenceStatus == ConsolidatedPresence.Online ? @drawable/led_online : @drawable/led_away, default=@drawable/led_online}"
|
||||
android:visibility="@{viewModel.presenceStatus == ConsolidatedPresence.Offline ? View.GONE : View.VISIBLE, default=gone}" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
|
|
|
@ -758,4 +758,11 @@
|
|||
<string name="call_screenshot_taken">Capture sauvegardée : %s</string>
|
||||
<string name="chat_message_voice_recording_received_notification">Vous avez reçu un message vocal</string>
|
||||
<string name="chat_message_voice_recording">Message vocal</string>
|
||||
<string name="content_description_presence_online">La personne est en ligne</string>
|
||||
<string name="content_description_presence_offline">La personne est hors ligne</string>
|
||||
<string name="account_setting_publish_presence_title">Publier la présence</string>
|
||||
<string name="chat_room_presence_online">En ligne</string>
|
||||
<string name="chat_room_presence_last_seen_online_today">En ligne aujourd\'hui à</string>
|
||||
<string name="chat_room_presence_last_seen_online_yesterday">En ligne hier à</string>
|
||||
<string name="chat_room_presence_last_seen_online">En ligne le</string>
|
||||
</resources>
|
|
@ -82,4 +82,6 @@
|
|||
<dimen name="mute_mic_grid_margin">10dp</dimen>
|
||||
<dimen name="chat_message_sending_icons_size">35dp</dimen>
|
||||
<dimen name="chat_message_sending_icons_margin">5dp</dimen>
|
||||
<dimen name="contact_presence_badge_size">12dp</dimen>
|
||||
<dimen name="contact_presence_big_badge_size">25dp</dimen>
|
||||
</resources>
|
|
@ -233,6 +233,10 @@
|
|||
<string name="chat_message_download_already_in_progress">Please wait for first download to finish before starting a new one</string>
|
||||
<string name="chat_message_voice_recording_received_notification">You have received a voice message</string>
|
||||
<string name="chat_message_voice_recording">Voice message</string>
|
||||
<string name="chat_room_presence_online">Online</string>
|
||||
<string name="chat_room_presence_last_seen_online_today">Online today at</string>
|
||||
<string name="chat_room_presence_last_seen_online_yesterday">Online yesterday at</string>
|
||||
<string name="chat_room_presence_last_seen_online">Online on</string>
|
||||
|
||||
<!-- Recordings -->
|
||||
<string name="recordings_empty_list">No recordings</string>
|
||||
|
@ -702,6 +706,7 @@
|
|||
<string name="account_setting_conference_factory_address">Conference factory URI</string>
|
||||
<string name="account_setting_audio_video_conference_factory_address">Audio/video conference factory URI</string>
|
||||
<string name="account_setting_end_to_end_encryption_keys_server_url">E2E encryption keys server URL</string>
|
||||
<string name="account_setting_publish_presence_title">Publish presence information</string>
|
||||
|
||||
<!-- Conferences settings -->
|
||||
<string name="conferences_settings_layout_title">Default layout</string>
|
||||
|
@ -890,4 +895,6 @@
|
|||
<string name="content_description_toggle_conference_info_details">Toggle meeting information details visibility</string>
|
||||
<string name="content_description_conference_participants">Group call participants</string>
|
||||
<string name="content_description_recording_export">Export recording</string>
|
||||
<string name="content_description_presence_online">User is online</string>
|
||||
<string name="content_description_presence_offline">User is offline</string>
|
||||
</resources>
|
||||
|
|
|
@ -422,6 +422,11 @@
|
|||
|
||||
<!-- UI various fonts -->
|
||||
|
||||
<style name="chat_last_seen_at_font" parent="@android:style/TextAppearance.Medium">
|
||||
<item name="android:textColor">?attr/primaryTextColor</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
</style>
|
||||
|
||||
<style name="accent_colored_title_font" parent="@android:style/TextAppearance.Medium">
|
||||
<item name="android:textColor">?attr/accentColor</item>
|
||||
<item name="android:textAllCaps">true</item>
|
||||
|
|
Loading…
Reference in a new issue