Fixed compil with latest SDK from master that has more @Nullable tags

This commit is contained in:
Sylvain Berfini 2020-07-07 11:41:33 +02:00
parent 704df9d583
commit 8e9aa6117c
42 changed files with 238 additions and 166 deletions

View file

@ -155,7 +155,7 @@ class PhoneAccountCreationViewModel(accountCreator: AccountCreator) : AbstractPh
private fun isCreateButtonEnabled(): Boolean {
val usernameRegexp = corePreferences.config.getString("assistant", "username_regex", "^[a-z0-9+_.\\-]*\$")
return isPhoneNumberOk() &&
return isPhoneNumberOk() && usernameRegexp != null &&
(useUsername.value == false ||
username.value.orEmpty().matches(Regex(usernameRegexp)) &&
username.value.orEmpty().isNotEmpty() &&

View file

@ -58,9 +58,11 @@ class QrCodeViewModel : ViewModel() {
}
}
val first = coreContext.core.videoDevicesList[0]
Log.i("[QR Code] Using first camera found: $first")
coreContext.core.videoDevice = first
val first = coreContext.core.videoDevicesList.firstOrNull()
if (first != null) {
Log.i("[QR Code] Using first camera found: $first")
coreContext.core.videoDevice = first
}
}
fun switchCamera() {

View file

@ -97,8 +97,9 @@ open class CallViewModel(val call: Call) : GenericContactViewModel(call.remoteAd
}
fun removeFromConference() {
if (call.conference != null) {
call.conference.removeParticipant(call.remoteAddress)
val conference = call.conference
if (conference != null) {
conference.removeParticipant(call.remoteAddress)
if (call.core.conferenceSize <= 1) call.core.leaveConference()
}
}

View file

@ -52,10 +52,11 @@ class CallsViewModel : ViewModel() {
callPausedByRemote.value = state == Call.State.PausedByRemote
isConferencePaused.value = !coreContext.core.isInConference
if (core.currentCall == null) {
val currentCall = core.currentCall
if (currentCall == null) {
currentCallViewModel.value = null
} else if (currentCallViewModel.value == null) {
currentCallViewModel.value = CallViewModel(core.currentCall)
currentCallViewModel.value = CallViewModel(currentCall)
}
if (state == Call.State.End || state == Call.State.Released || state == Call.State.Error) {

View file

@ -171,7 +171,7 @@ class ControlsViewModel : ViewModel() {
fun terminateCall() {
val core = coreContext.core
when {
core.currentCall != null -> core.currentCall.terminate()
core.currentCall != null -> core.currentCall?.terminate()
core.isInConference -> core.terminateConference()
else -> core.terminateAllCalls()
}
@ -180,13 +180,14 @@ class ControlsViewModel : ViewModel() {
fun toggleVideo() {
val core = coreContext.core
val currentCall = core.currentCall
val conference = core.conference
if (core.conference != null && core.isInConference) {
if (conference != null && core.isInConference) {
val params = core.createConferenceParams()
val videoEnabled = core.conference.currentParams.videoEnabled()
val videoEnabled = conference.currentParams.videoEnabled()
params.enableVideo(!videoEnabled)
Log.i("[Controls VM] Conference current param for video is $videoEnabled")
core.conference.updateParams(params)
conference.updateParams(params)
} else if (currentCall != null) {
val state = currentCall.state
if (state == Call.State.End || state == Call.State.Released || state == Call.State.Error)
@ -194,7 +195,7 @@ class ControlsViewModel : ViewModel() {
isVideoUpdateInProgress.value = true
val params = core.createCallParams(currentCall)
params.enableVideo(!currentCall.currentParams.videoEnabled())
params?.enableVideo(!currentCall.currentParams.videoEnabled())
currentCall.update(params)
}
}
@ -254,7 +255,7 @@ class ControlsViewModel : ViewModel() {
val conference = core.createConferenceWithParams(params)
for (call in core.calls) {
conference.addParticipant(call)
conference?.addParticipant(call)
}
toggleOptionsMenu()
@ -341,8 +342,9 @@ class ControlsViewModel : ViewModel() {
private fun updateVideoAvailable() {
val core = coreContext.core
val currentCall = core.currentCall
isVideoAvailable.value = (core.videoCaptureEnabled() || core.videoPreviewEnabled()) &&
((core.currentCall != null && !core.currentCall.mediaInProgress()) ||
((currentCall != null && !currentCall.mediaInProgress()) ||
(core.conference != null && core.isInConference))
}

View file

@ -44,7 +44,7 @@ class IncomingCallViewModel(call: Call) : CallViewModel(call) {
init {
screenLocked.value = false
inviteWithVideo.value = call.currentParams.videoEnabled()
earlyMediaVideoEnabled.value = call.state == Call.State.IncomingEarlyMedia && call.currentParams?.videoEnabled() ?: false
earlyMediaVideoEnabled.value = call.state == Call.State.IncomingEarlyMedia && call.currentParams.videoEnabled()
}
fun answer(doAction: Boolean) {

View file

@ -53,6 +53,7 @@ class StatItemViewModel(val type: StatType) : ViewModel() {
fun update(call: Call, stats: CallStats) {
val payloadType = if (stats.type == StreamType.Audio) call.currentParams.usedAudioPayloadType else call.currentParams.usedVideoPayloadType
payloadType ?: return
value.value = when (type) {
StatType.CAPTURE -> if (stats.type == StreamType.Audio) call.core.captureDevice else call.core.videoDevice
StatType.PLAYBACK -> if (stats.type == StreamType.Audio) call.core.playbackDevice else call.core.videoDisplayFilter

View file

@ -127,6 +127,7 @@ class ChatMessagesListAdapter(val selectionViewModel: ListTopBarViewModel) : Lif
with(binding) {
if (eventLog.type == EventLog.Type.ConferenceChatMessage) {
val chatMessage = eventLog.chatMessage
chatMessage ?: return
val chatMessageViewModel = ChatMessageViewModel(chatMessage, contentClickedListener)
viewModel = chatMessageViewModel
@ -150,7 +151,7 @@ class ChatMessagesListAdapter(val selectionViewModel: ListTopBarViewModel) : Lif
val previousItem = getItem(adapterPosition - 1)
if (previousItem.type == EventLog.Type.ConferenceChatMessage) {
val previousMessage = previousItem.chatMessage
if (previousMessage.fromAddress.weakEqual(chatMessage.fromAddress)) {
if (previousMessage != null && previousMessage.fromAddress.weakEqual(chatMessage.fromAddress)) {
if (chatMessage.time - previousMessage.time < MAX_TIME_TO_GROUP_MESSAGES) {
hasPrevious = true
}
@ -162,7 +163,7 @@ class ChatMessagesListAdapter(val selectionViewModel: ListTopBarViewModel) : Lif
val nextItem = getItem(adapterPosition + 1)
if (nextItem.type == EventLog.Type.ConferenceChatMessage) {
val nextMessage = nextItem.chatMessage
if (nextMessage.fromAddress.weakEqual(chatMessage.fromAddress)) {
if (nextMessage != null && nextMessage.fromAddress.weakEqual(chatMessage.fromAddress)) {
if (nextMessage.time - chatMessage.time < MAX_TIME_TO_GROUP_MESSAGES) {
hasNext = true
}
@ -314,8 +315,8 @@ private class ChatMessageDiffCallback : DiffUtil.ItemCallback<EventLog>() {
): Boolean {
return if (oldItem.type == EventLog.Type.ConferenceChatMessage &&
newItem.type == EventLog.Type.ConferenceChatMessage) {
oldItem.chatMessage.time == newItem.chatMessage.time &&
oldItem.chatMessage.isOutgoing == newItem.chatMessage.isOutgoing
oldItem.chatMessage?.time == newItem.chatMessage?.time &&
oldItem.chatMessage?.isOutgoing == newItem.chatMessage?.isOutgoing
} else oldItem.notifyId == newItem.notifyId
}
@ -324,7 +325,7 @@ private class ChatMessageDiffCallback : DiffUtil.ItemCallback<EventLog>() {
newItem: EventLog
): Boolean {
return if (newItem.type == EventLog.Type.ConferenceChatMessage) {
newItem.chatMessage.state == ChatMessage.State.Displayed
newItem.chatMessage?.state == ChatMessage.State.Displayed
} else false
}
}

View file

@ -73,7 +73,8 @@ class ChatRoomCreationContactsAdapter : LifecycleListAdapter<SearchResult, ChatR
selectedAddresses.observe(this@ViewHolder, Observer {
val selected = it.find { address ->
if (searchResult.address != null) address.weakEqual(searchResult.address) else false
val searchAddress = searchResult.address
if (searchAddress != null) address.weakEqual(searchAddress) else false
}
searchResultViewModel.isSelected.value = selected != null
})
@ -91,7 +92,8 @@ class ChatRoomCreationContactsAdapter : LifecycleListAdapter<SearchResult, ChatR
viewModel: ChatRoomCreationContactViewModel,
securityEnabled: Boolean
) {
val isMyself = securityEnabled && searchResult.address != null && coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(searchResult.address) ?: false
val searchAddress = searchResult.address
val isMyself = securityEnabled && searchAddress != null && coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(searchAddress) ?: false
val limeCheck = !securityEnabled || (securityEnabled && searchResult.hasCapability(FriendCapability.LimeX3Dh))
val groupCheck = !groupChatEnabled || (groupChatEnabled && searchResult.hasCapability(FriendCapability.GroupChat))
val disabled = if (searchResult.friend != null) !limeCheck || !groupCheck || isMyself else false // Generated entry from search filter
@ -111,7 +113,9 @@ private class SearchResultDiffCallback : DiffUtil.ItemCallback<SearchResult>() {
oldItem: SearchResult,
newItem: SearchResult
): Boolean {
return if (oldItem.address != null && newItem.address != null) oldItem.address.weakEqual(newItem.address) else false
val oldAddress = oldItem.address
val newAddress = newItem.address
return if (oldAddress != null && newAddress != null) oldAddress.weakEqual(newAddress) else false
}
override fun areContentsTheSame(

View file

@ -67,7 +67,7 @@ class ImdnFragment : Fragment() {
if (arguments != null) {
val messageId = arguments?.getString("MessageId")
val message = chatRoom.findMessage(messageId)
val message = if (messageId != null) chatRoom.findMessage(messageId) else null
if (message != null) {
Log.i("[IMDN] Found message $message with id $messageId")
viewModel = ViewModelProvider(

View file

@ -58,17 +58,18 @@ class ChatMessageContentViewModel(
init {
if (content.isFile || (content.isFileTransfer && chatMessage.isOutgoing)) {
downloadable.value = content.filePath.isEmpty()
val filePath = content.filePath ?: ""
downloadable.value = filePath.isEmpty()
if (content.filePath.isNotEmpty()) {
Log.i("[Content] Found displayable content: ${content.filePath}")
isImage.value = FileUtils.isExtensionImage(content.filePath)
isVideo.value = FileUtils.isExtensionVideo(content.filePath)
if (filePath.isNotEmpty()) {
Log.i("[Content] Found displayable content: $filePath")
isImage.value = FileUtils.isExtensionImage(filePath)
isVideo.value = FileUtils.isExtensionVideo(filePath)
if (isVideo.value == true) {
viewModelScope.launch {
withContext(Dispatchers.IO) {
videoPreview.postValue(ImageUtils.getVideoPreview(content.filePath))
videoPreview.postValue(ImageUtils.getVideoPreview(filePath))
}
}
}
@ -88,18 +89,22 @@ class ChatMessageContentViewModel(
}
fun download() {
if (content.isFileTransfer && (content.filePath == null || content.filePath.isEmpty())) {
val file = FileUtils.getFileStoragePath(content.name)
content.filePath = file.path
downloadEnabled.value = false
val filePath = content.filePath
if (content.isFileTransfer && (filePath == null || filePath.isEmpty())) {
val contentName = content.name
if (contentName != null) {
val file = FileUtils.getFileStoragePath(contentName)
content.filePath = file.path
downloadEnabled.value = false
Log.i("[Content] Started downloading ${content.name} into ${content.filePath}")
chatMessage.downloadContent(content)
Log.i("[Content] Started downloading $contentName into ${content.filePath}")
chatMessage.downloadContent(content)
}
}
}
fun openFile() {
listener?.onContentClicked(content.filePath)
listener?.onContentClicked(content.filePath.orEmpty())
}
}

View file

@ -101,8 +101,9 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
val isBasicChatRoom: Boolean = chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt())
val message: ChatMessage = chatRoom.createEmptyMessage()
if (textToSend.value.orEmpty().isNotEmpty()) {
message.addTextContent(textToSend.value)
val toSend = textToSend.value
if (toSend != null && toSend.isNotEmpty()) {
message.addTextContent(toSend)
}
for (attachment in attachments.value.orEmpty()) {
@ -134,6 +135,6 @@ class ChatMessageSendingViewModel(private val chatRoom: ChatRoom) : ViewModel()
fun transferMessage(chatMessage: ChatMessage) {
val message = chatRoom.createForwardMessage(chatMessage)
message?.send()
message.send()
}
}

View file

@ -63,7 +63,8 @@ class ChatMessageViewModel(
val ephemeralLifetime = MutableLiveData<String>()
val text: Spanned? by lazy {
if (chatMessage.textContent != null) AppUtils.getTextWithHttpLinks(chatMessage.textContent) else null
val textContent = chatMessage.textContent
if (textContent != null) AppUtils.getTextWithHttpLinks(textContent) else null
}
private var countDownTimer: CountDownTimer? = null

View file

@ -79,6 +79,7 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() {
if (eventLog.type == EventLog.Type.ConferenceChatMessage) {
val chatMessage = eventLog.chatMessage
chatMessage ?: return
chatMessage.userData = position
chatMessage.addListener(chatMessageListener)
@ -101,6 +102,7 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() {
if (eventLog.type == EventLog.Type.ConferenceChatMessage) {
val chatMessage = eventLog.chatMessage
chatMessage ?: return
chatMessage.userData = position
chatMessage.addListener(chatMessageListener)
}
@ -138,7 +140,9 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() {
override fun onEphemeralMessageDeleted(chatRoom: ChatRoom, eventLog: EventLog) {
Log.i("[Chat Messages] An ephemeral chat message has expired, removing it from event list")
deleteMessage(eventLog.chatMessage)
val chatMessage = eventLog.chatMessage
chatMessage ?: return
deleteMessage(chatMessage)
}
override fun onEphemeralEvent(chatRoom: ChatRoom, eventLog: EventLog) {
@ -160,7 +164,7 @@ class ChatMessagesListViewModel(private val chatRoom: ChatRoom) : ViewModel() {
fun resendMessage(chatMessage: ChatMessage) {
val position: Int = chatMessage.userData as Int
chatMessage.resend()
chatMessage.send()
messageUpdatedEvent.value = Event(position)
}

View file

@ -31,11 +31,8 @@ class ChatRoomCreationContactViewModel(private val searchResult: SearchResult) :
override val contact = MutableLiveData<Contact>()
override val displayName: String by lazy {
when {
searchResult.friend != null -> searchResult.friend.name
searchResult.address != null -> LinphoneUtils.getDisplayName(searchResult.address)
else -> searchResult.phoneNumber
}
val address = searchResult.address
searchResult.friend?.name ?: if (address != null) LinphoneUtils.getDisplayName(address) else searchResult.phoneNumber.orEmpty()
}
val isDisabled: MutableLiveData<Boolean> by lazy {
@ -47,14 +44,14 @@ class ChatRoomCreationContactViewModel(private val searchResult: SearchResult) :
}
val isLinphoneUser: Boolean by lazy {
searchResult.friend?.getPresenceModelForUriOrTel(searchResult.phoneNumber ?: searchResult.address.asStringUriOnly())?.basicStatus == PresenceBasicStatus.Open
searchResult.friend?.getPresenceModelForUriOrTel(searchResult.phoneNumber ?: searchResult.address?.asStringUriOnly() ?: "")?.basicStatus == PresenceBasicStatus.Open
}
val sipUri: String by lazy {
searchResult.phoneNumber ?: searchResult.address.asStringUriOnly()
searchResult.phoneNumber ?: searchResult.address?.asStringUriOnly() ?: ""
}
val address: Address by lazy {
val address: Address? by lazy {
searchResult.address
}
@ -70,11 +67,11 @@ class ChatRoomCreationContactViewModel(private val searchResult: SearchResult) :
}
private fun searchMatchingContact() {
if (searchResult.address != null) {
contact.value =
coreContext.contactsManager.findContactByAddress(searchResult.address)
val address = searchResult.address
if (address != null) {
contact.value = coreContext.contactsManager.findContactByAddress(address)
} else if (searchResult.phoneNumber != null) {
contact.value = coreContext.contactsManager.findContactByPhoneNumber(searchResult.phoneNumber)
contact.value = coreContext.contactsManager.findContactByPhoneNumber(searchResult.phoneNumber.orEmpty())
}
}
}

View file

@ -118,8 +118,9 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
}
fun toggleSelectionForSearchResult(searchResult: SearchResult) {
if (searchResult.address != null) {
toggleSelectionForAddress(searchResult.address)
val address = searchResult.address
if (address != null) {
toggleSelectionForAddress(address)
}
}
@ -147,7 +148,7 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
val defaultProxyConfig = coreContext.core.defaultProxyConfig
var room: ChatRoom?
val address = searchResult.address ?: coreContext.core.interpretUrl(searchResult.phoneNumber)
val address = searchResult.address ?: coreContext.core.interpretUrl(searchResult.phoneNumber ?: "")
if (address == null) {
Log.e("[Chat Room Creation] Can't get a valid address from search result $searchResult")
onErrorEvent.value = Event(R.string.chat_room_creation_failed_snack)
@ -168,23 +169,23 @@ class ChatRoomCreationViewModel : ErrorReportingViewModel() {
val participants = arrayOf(searchResult.address)
// Use proxy config contact instead of identity because we need GRUU if FlexisipChat backend
room = coreContext.core.searchChatRoom(params, defaultProxyConfig.contact, null, participants)
room = coreContext.core.searchChatRoom(params, defaultProxyConfig?.contact, null, participants)
if (room == null) {
Log.w("[Chat Room Creation] Couldn't find existing 1-1 chat room with remote ${searchResult.address.asStringUriOnly()}, encryption=$encrypted and local identity ${defaultProxyConfig.contact.asStringUriOnly()}")
Log.w("[Chat Room Creation] Couldn't find existing 1-1 chat room with remote ${searchResult.address?.asStringUriOnly()}, encryption=$encrypted and local identity ${defaultProxyConfig?.contact?.asStringUriOnly()}")
// Use proxy config contact instead of identity because we need GRUU if FlexisipChat backend
room = coreContext.core.createChatRoom(params, defaultProxyConfig.contact, participants)
room = coreContext.core.createChatRoom(params, defaultProxyConfig?.contact, participants)
if (encrypted) {
room?.addListener(listener)
} else {
if (room != null) {
chatRoomCreatedEvent.value = Event(room)
} else {
Log.e("[Chat Room Creation] Couldn't create chat room with remote ${searchResult.address.asStringUriOnly()} and local identity ${defaultProxyConfig.contact.asStringUriOnly()}")
Log.e("[Chat Room Creation] Couldn't create chat room with remote ${searchResult.address?.asStringUriOnly()} and local identity ${defaultProxyConfig?.contact?.asStringUriOnly()}")
}
waitForChatRoomCreation.value = false
}
} else {
Log.i("[Chat Room Creation] Found existing 1-1 chat room with remote ${searchResult.address.asStringUriOnly()}, encryption=$encrypted and local identity ${defaultProxyConfig.contact.asStringUriOnly()}")
Log.i("[Chat Room Creation] Found existing 1-1 chat room with remote ${searchResult.address?.asStringUriOnly()}, encryption=$encrypted and local identity ${defaultProxyConfig?.contact?.asStringUriOnly()}")
chatRoomCreatedEvent.value = Event(room)
waitForChatRoomCreation.value = false
}

View file

@ -49,7 +49,7 @@ class ChatRoomViewModel(val chatRoom: ChatRoom) : ViewModel(), ContactViewModelI
when {
chatRoom.hasCapability(ChatRoomCapabilities.Basic.toInt()) -> LinphoneUtils.getDisplayName(chatRoom.peerAddress)
chatRoom.hasCapability(ChatRoomCapabilities.OneToOne.toInt()) -> LinphoneUtils.getDisplayName(chatRoom.participants.firstOrNull()?.address ?: chatRoom.peerAddress)
chatRoom.hasCapability(ChatRoomCapabilities.Conference.toInt()) -> chatRoom.subject
chatRoom.hasCapability(ChatRoomCapabilities.Conference.toInt()) -> chatRoom.subject.orEmpty()
else -> chatRoom.peerAddress.asStringUriOnly()
}
}

View file

@ -127,13 +127,13 @@ class ChatRoomsListViewModel : ErrorReportingViewModel() {
fun deleteChatRooms(chatRooms: ArrayList<ChatRoom>) {
chatRoomsToDeleteCount = chatRooms.size
for (chatRoom in chatRooms) {
for (eventLog in chatRoom.getHistoryMessageEvents(0).orEmpty()) {
for (eventLog in chatRoom.getHistoryMessageEvents(0)) {
LinphoneUtils.deleteFilesAttachedToEventLog(eventLog)
}
Compatibility.removeChatRoomShortcut(chatRoom)
chatRoom.addListener(chatRoomListener)
chatRoom.core?.deleteChatRoom(chatRoom)
chatRoom.core.deleteChatRoom(chatRoom)
}
}

View file

@ -26,7 +26,7 @@ import org.linphone.core.ChatRoomSecurityLevel
import org.linphone.core.ParticipantDevice
class DevicesListChildViewModel(private val device: ParticipantDevice) : ViewModel() {
val deviceName: String = device.name
val deviceName: String = device.name.orEmpty()
val securityLevelIcon: Int by lazy {
when (device.securityLevel) {

View file

@ -23,7 +23,7 @@ import androidx.lifecycle.ViewModel
class EphemeralDurationViewModel(
val textResource: Int,
private val selectedDuration: Long,
selectedDuration: Long,
private val duration: Long,
private val listener: DurationItemClicked
) : ViewModel() {

View file

@ -139,7 +139,7 @@ class GroupInfoViewModel(val chatRoom: ChatRoom?) : ErrorReportingViewModel() {
val newSubject = subject.value.orEmpty()
if (newSubject.isNotEmpty() && newSubject != chatRoom.subject) {
Log.i("[Chat Room Group Info] Subject changed to $newSubject")
chatRoom.subject = newSubject
chatRoom.setSubject(newSubject)
}
// Removed participants

View file

@ -23,7 +23,7 @@ import org.linphone.contact.GenericContactViewModel
import org.linphone.core.ParticipantImdnState
import org.linphone.utils.TimestampUtils
class ImdnParticipantViewModel(private val imdnState: ParticipantImdnState) : GenericContactViewModel(imdnState.participant.address) {
class ImdnParticipantViewModel(imdnState: ParticipantImdnState) : GenericContactViewModel(imdnState.participant.address) {
val sipUri: String = imdnState.participant.address.asStringUriOnly()
val time: String = TimestampUtils.toString(imdnState.stateChangeTime)

View file

@ -98,39 +98,38 @@ class ContactEditorViewModel(val c: Contact?) : ViewModel(), ContactViewModelInt
.commit()
} else {
val friend = contact.friend ?: coreContext.core.createFriend()
if (friend != null) {
friend.edit()
friend.name = "${firstName.value.orEmpty()} ${lastName.value.orEmpty()}"
friend.edit()
friend.setName("${firstName.value.orEmpty()} ${lastName.value.orEmpty()}")
for (address in friend.addresses) {
friend.removeAddress(address)
}
for (address in addresses.value.orEmpty()) {
val parsed = coreContext.core.interpretUrl(address.newValue.value.orEmpty())
if (parsed != null) friend.addAddress(parsed)
}
for (address in friend.addresses) {
friend.removeAddress(address)
}
for (address in addresses.value.orEmpty()) {
val parsed = coreContext.core.interpretUrl(address.newValue.value.orEmpty())
if (parsed != null) friend.addAddress(parsed)
}
for (phone in friend.phoneNumbers) {
friend.removePhoneNumber(phone)
}
for (phone in numbers.value.orEmpty()) {
if (phone.newValue.value?.isNotEmpty() == true) {
friend.addPhoneNumber(phone.newValue.value)
}
for (phone in friend.phoneNumbers) {
friend.removePhoneNumber(phone)
}
for (phone in numbers.value.orEmpty()) {
val phoneNumber = phone.newValue.value
if (phoneNumber?.isNotEmpty() == true) {
friend.addPhoneNumber(phoneNumber)
}
}
val vCard = friend.vcard
if (vCard != null) {
vCard.organization = organization.value.orEmpty()
vCard.familyName = lastName.value.orEmpty()
vCard.givenName = firstName.value.orEmpty()
}
friend.done()
val vCard = friend.vcard
if (vCard != null) {
vCard.organization = organization.value.orEmpty()
vCard.familyName = lastName.value.orEmpty()
vCard.givenName = firstName.value.orEmpty()
}
friend.done()
if (contact.friend == null) {
contact.friend = friend
coreContext.core.defaultFriendList.addLocalFriend(friend)
}
if (contact.friend == null) {
contact.friend = friend
coreContext.core.defaultFriendList?.addLocalFriend(friend)
}
}

View file

@ -178,7 +178,7 @@ class ContactViewModel(private val c: Contact) : ErrorReportingViewModel(), Cont
val hasPresence = presenceModel != null && presenceModel.basicStatus == PresenceBasicStatus.Open
val contactAddress = presenceModel?.contact ?: number
val address = coreContext.core.interpretUrl(contactAddress)
val isMe = coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(address) ?: false
val isMe = if (address != null) coreContext.core.defaultProxyConfig?.identityAddress?.weakEqual(address) ?: false else false
val secureChatAllowed = !isMe && c.friend?.getPresenceModelForUriOrTel(number)?.hasCapability(FriendCapability.LimeX3Dh) ?: false
val noa = ContactNumberOrAddressViewModel(address, hasPresence, number, isSip = false, showSecureChat = secureChatAllowed, listener = listener)
list.add(noa)

View file

@ -65,7 +65,7 @@ class RecordingViewModel(val path: String) : ViewModel(), Comparable<RecordingVi
private val tickerChannel = ticker(1000, 1000)
private var player: Player
private lateinit var player: Player
private val listener = PlayerListener {
Log.i("[Recording] End of file reached")
stop()
@ -95,7 +95,9 @@ class RecordingViewModel(val path: String) : ViewModel(), Comparable<RecordingVi
}
}
}
player = coreContext.core.createLocalPlayer(speakerCard ?: earpieceCard, null, null)
val localPlayer = coreContext.core.createLocalPlayer(speakerCard ?: earpieceCard, null, null)
if (localPlayer != null) player = localPlayer
else Log.e("[Recording VM] Couldn't create local player!")
player.addListener(listener)
}

View file

@ -38,11 +38,11 @@ class AccountSettingsViewModelFactory(private val identity: String) :
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
for (proxy in coreContext.core.proxyConfigList) {
if (proxy.identityAddress.asStringUriOnly() == identity) {
if (proxy.identityAddress?.asStringUriOnly() == identity) {
return AccountSettingsViewModel(proxy) as T
}
}
return AccountSettingsViewModel(coreContext.core.defaultProxyConfig) as T
return AccountSettingsViewModel(coreContext.core.defaultProxyConfig!!) as T
}
}
@ -115,7 +115,7 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val displayNameListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.identityAddress.displayName = newValue
proxyConfig.identityAddress?.displayName = newValue
}
}
// displayName mutable is above
@ -138,9 +138,11 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
private fun deleteProxyConfig(cfg: ProxyConfig) {
val authInfo = cfg.findAuthInfo()
core.removeProxyConfig(cfg)
core.removeAuthInfo(authInfo)
proxyConfigRemovedEvent.value = Event(true)
if (authInfo != null) {
core.removeProxyConfig(cfg)
core.removeAuthInfo(authInfo)
proxyConfigRemovedEvent.value = Event(true)
}
}
val deleteListener = object : SettingListenerStub() {
@ -207,7 +209,7 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val stunServerListener = object : SettingListenerStub() {
override fun onTextValueChanged(newValue: String) {
proxyConfig.natPolicy.stunServer = newValue
proxyConfig.natPolicy?.stunServer = newValue
if (newValue.isEmpty()) ice.value = false
stunServer.value = newValue
}
@ -216,7 +218,7 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
val iceListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
proxyConfig.natPolicy.enableIce(newValue)
proxyConfig.natPolicy?.enableIce(newValue)
}
}
val ice = MutableLiveData<Boolean>()
@ -276,8 +278,11 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
private fun update() {
isDefault.value = core.defaultProxyConfig == proxyConfig
displayName.value = LinphoneUtils.getDisplayName(proxyConfig.identityAddress)
identity.value = proxyConfig.identityAddress.asStringUriOnly()
val identityAddress = proxyConfig.identityAddress
if (identityAddress != null) {
displayName.value = LinphoneUtils.getDisplayName(identityAddress)
identity.value = identityAddress.asStringUriOnly()
}
iconResource.value = when (proxyConfig.state) {
RegistrationState.Ok -> R.drawable.led_connected
@ -292,14 +297,14 @@ class AccountSettingsViewModel(val proxyConfig: ProxyConfig) : GenericSettingsVi
else -> R.string.status_not_connected
}
userName.value = proxyConfig.identityAddress.username
userName.value = proxyConfig.identityAddress?.username
userId.value = proxyConfig.findAuthInfo()?.userid
domain.value = proxyConfig.identityAddress.domain
domain.value = proxyConfig.identityAddress?.domain
disable.value = !proxyConfig.registerEnabled()
pushNotification.value = proxyConfig.isPushNotificationAllowed
pushNotificationsAvailable.value = core.isPushNotificationAvailable
proxy.value = proxyConfig.serverAddr
outboundProxy.value = proxyConfig.serverAddr == proxyConfig.route
outboundProxy.value = proxyConfig.serverAddr == proxyConfig.routes.firstOrNull()
stunServer.value = proxyConfig.natPolicy?.stunServer
ice.value = proxyConfig.natPolicy?.iceEnabled()
avpf.value = proxyConfig.avpfEnabled()

View file

@ -168,6 +168,9 @@ class AudioSettingsViewModel : GenericSettingsViewModel() {
core.removeListener(listener)
when (status) {
EcCalibratorStatus.InProgress -> {
echoCalibration.value = prefs.getString(R.string.audio_settings_echo_cancellation_calibration_started)
}
EcCalibratorStatus.DoneNoEcho -> {
echoCalibration.value = prefs.getString(R.string.audio_settings_echo_cancellation_calibration_no_echo)
}

View file

@ -50,7 +50,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
val useDualModeListener = object : SettingListenerStub() {
override fun onBoolValueChanged(newValue: Boolean) {
val tunnel = core.tunnel
tunnel.enableDualMode(newValue)
tunnel?.enableDualMode(newValue)
}
}
val useDualMode = MutableLiveData<Boolean>()
@ -77,7 +77,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
val modeListener = object : SettingListenerStub() {
override fun onListValueChanged(position: Int) {
core.tunnel.mode = when (position) {
core.tunnel?.mode = when (position) {
0 -> Tunnel.Mode.Disable
1 -> Tunnel.Mode.Enable
else -> Tunnel.Mode.Auto
@ -93,7 +93,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
hostnameUrl.value = config.host
port.value = config.port
useDualMode.value = tunnel.dualModeEnabled()
useDualMode.value = tunnel?.dualModeEnabled()
hostnameUrl2.value = config.host2
port2.value = config.port2
@ -102,9 +102,9 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
private fun getTunnelConfig(): TunnelConfig {
val tunnel = core.tunnel
val configs = tunnel.servers
val configs = tunnel?.servers.orEmpty()
return if (configs.isNotEmpty()) {
configs[0]
configs.first()
} else {
Factory.instance().createTunnelConfig()
}
@ -112,9 +112,9 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
private fun updateTunnelConfig(config: TunnelConfig) {
val tunnel = core.tunnel
tunnel.cleanServers()
tunnel?.cleanServers()
if (config.host?.isNotEmpty() == true) {
tunnel.addServer(config)
tunnel?.addServer(config)
}
}
@ -125,7 +125,7 @@ class TunnelSettingsViewModel : GenericSettingsViewModel() {
labels.add(prefs.getString(R.string.tunnel_settings_auto_mode))
modeLabels.value = labels
modeIndex.value = when (core.tunnel.mode) {
modeIndex.value = when (core.tunnel?.mode) {
Tunnel.Mode.Disable -> 0
Tunnel.Mode.Enable -> 1
else -> 2

View file

@ -72,7 +72,7 @@ class VideoSettingsViewModel : GenericSettingsViewModel() {
val videoSizeListener = object : SettingListenerStub() {
override fun onListValueChanged(position: Int) {
core.preferredVideoDefinition = Factory.instance().createVideoDefinitionFromName(videoSizeLabels.value.orEmpty()[position])
core.setPreferredVideoDefinition(Factory.instance().createVideoDefinitionFromName(videoSizeLabels.value.orEmpty()[position]))
}
}
val videoSizeIndex = MutableLiveData<Int>()
@ -135,8 +135,10 @@ class VideoSettingsViewModel : GenericSettingsViewModel() {
if (index == -1) {
val firstDevice = cameraDeviceLabels.value.orEmpty().firstOrNull()
Log.w("[Video Settings] Device not found in labels list: ${core.videoDevice}, replace it by $firstDevice")
cameraDeviceIndex.value = 0
core.videoDevice = firstDevice
if (firstDevice != null) {
cameraDeviceIndex.value = 0
core.videoDevice = firstDevice
}
} else {
cameraDeviceIndex.value = index
}
@ -146,11 +148,11 @@ class VideoSettingsViewModel : GenericSettingsViewModel() {
val labels = arrayListOf<String>()
for (size in Factory.instance().supportedVideoDefinitions) {
labels.add(size.name)
labels.add(size.name.orEmpty())
}
videoSizeLabels.value = labels
videoSizeIndex.value = labels.indexOf(core.preferredVideoDefinition.name)
videoSizeIndex.value = labels.indexOf(core.preferredVideoDefinition?.name)
}
private fun initVideoPresetList() {

View file

@ -71,8 +71,9 @@ open class StatusViewModel : ViewModel() {
core.addListener(listener)
var state: RegistrationState = RegistrationState.None
if (core.defaultProxyConfig != null) {
state = core.defaultProxyConfig.state
val defaultProxyConfig = core.defaultProxyConfig
if (defaultProxyConfig != null) {
state = defaultProxyConfig.state
}
updateDefaultProxyConfigRegistrationStatus(state)
}

View file

@ -61,6 +61,11 @@ class Api21Compatibility {
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
val fileName = content.name
@ -92,6 +97,11 @@ class Api21Compatibility {
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
val fileName = content.name
@ -124,6 +134,11 @@ class Api21Compatibility {
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
val fileName = content.name

View file

@ -35,6 +35,11 @@ class Api29Compatibility {
companion object {
suspend fun addImageToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_PICTURES}/$appName"
val fileName = content.name
@ -72,6 +77,11 @@ class Api29Compatibility {
suspend fun addVideoToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_MOVIES}/$appName"
val fileName = content.name
@ -110,6 +120,11 @@ class Api29Compatibility {
suspend fun addAudioToMediaStore(context: Context, content: Content): Boolean {
val filePath = content.filePath
if (filePath == null) {
Log.e("[Chat Message] Content doesn't have a file path!")
return false
}
val appName = AppUtils.getString(R.string.app_name)
val relativePath = "${Environment.DIRECTORY_MUSIC}/$appName"
val fileName = content.name

View file

@ -54,7 +54,8 @@ class AsyncContactsLoader(private val context: Context) :
if (core.isFriendListSubscriptionEnabled) {
val rls: String = corePreferences.rlsUri
for (list in core.friendsLists) {
if (list.rlsAddress == null || list.rlsAddress.asStringUriOnly() != rls) {
val rlsAddress = list.rlsAddress
if (rlsAddress == null || rlsAddress.asStringUriOnly() != rls) {
Log.i("[Contacts Loader] Friend list RLS URI updated to: $rls")
list.rlsUri = rls
}

View file

@ -29,7 +29,6 @@ import android.os.AsyncTask
import android.os.AsyncTask.THREAD_POOL_EXECUTOR
import android.provider.ContactsContract
import android.util.Patterns
import com.google.android.gms.tasks.Tasks.await
import kotlinx.coroutines.*
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences

View file

@ -175,7 +175,8 @@ class NativeContact(val nativeId: String, private val lookupKey: String? = null)
val friend = this.friend
if (friend != null) {
friend.edit()
friend.name = fullName
val fn = fullName
if (fn != null) friend.setName(fn)
val vCard = friend.vcard
if (vCard != null) {

View file

@ -57,8 +57,8 @@ class CoreContext(val context: Context, coreConfig: Config) {
}
val sdkVersion: String by lazy {
val sdkVersion = context.getString(org.linphone.R.string.linphone_sdk_version)
val sdkBranch = context.getString(org.linphone.R.string.linphone_sdk_branch)
val sdkVersion = context.getString(R.string.linphone_sdk_version)
val sdkBranch = context.getString(R.string.linphone_sdk_branch)
"$sdkVersion ($sdkBranch)"
}
@ -250,12 +250,12 @@ class CoreContext(val context: Context, coreConfig: Config) {
computeUserAgent()
for (lpc in core.proxyConfigList) {
if (lpc.identityAddress.domain == corePreferences.defaultDomain) {
if (lpc.identityAddress?.domain == corePreferences.defaultDomain) {
// Ensure conference URI is set on sip.linphone.org proxy configs
if (lpc.conferenceFactoryUri == null) {
lpc.edit()
val uri = corePreferences.conferenceServerUri
Log.i("[Context] Setting conference factory on proxy config ${lpc.identityAddress.asString()} to default value: $uri")
Log.i("[Context] Setting conference factory on proxy config ${lpc.identityAddress?.asString()} to default value: $uri")
lpc.conferenceFactoryUri = uri
lpc.done()
}
@ -277,11 +277,11 @@ class CoreContext(val context: Context, coreConfig: Config) {
private fun computeUserAgent() {
val deviceName: String = corePreferences.deviceName
val appName: String = context.resources.getString(org.linphone.R.string.app_name)
val appName: String = context.resources.getString(R.string.app_name)
val androidVersion = org.linphone.BuildConfig.VERSION_NAME
val userAgent = "$appName/$androidVersion ($deviceName) LinphoneSDK"
val sdkVersion = context.getString(org.linphone.R.string.linphone_sdk_version)
val sdkBranch = context.getString(org.linphone.R.string.linphone_sdk_branch)
val sdkVersion = context.getString(R.string.linphone_sdk_version)
val sdkBranch = context.getString(R.string.linphone_sdk_branch)
val sdkUserAgent = "$sdkVersion ($sdkBranch)"
core.setUserAgent(userAgent, sdkUserAgent)
}
@ -302,7 +302,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
fun answerCall(call: Call) {
Log.i("[Context] Answering call $call")
val params = core.createCallParams(call)
params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(call.remoteAddress)
params?.recordFile = LinphoneUtils.getRecordingFilePathForAddress(call.remoteAddress)
call.acceptWithParams(params)
}
@ -356,11 +356,15 @@ class CoreContext(val context: Context, coreConfig: Config) {
val params = core.createCallParams(null)
if (forceZRTP) {
params.mediaEncryption = MediaEncryption.ZRTP
params?.mediaEncryption = MediaEncryption.ZRTP
}
params.recordFile = LinphoneUtils.getRecordingFilePathForAddress(address)
params?.recordFile = LinphoneUtils.getRecordingFilePathForAddress(address)
val call = core.inviteAddressWithParams(address, params)
val call = if (params != null) {
core.inviteAddressWithParams(address, params)
} else {
core.inviteAddress(address)
}
Log.i("[Context] Starting call $call")
}
@ -368,8 +372,7 @@ class CoreContext(val context: Context, coreConfig: Config) {
val currentDevice = core.videoDevice
Log.i("[Context] Current camera device is $currentDevice")
val devices = core.videoDevicesList
for (camera in devices) {
for (camera in core.videoDevicesList) {
if (camera != currentDevice && camera != "StaticImage: Static picture") {
Log.i("[Context] New camera device will be $camera")
core.videoDevice = camera
@ -390,12 +393,13 @@ class CoreContext(val context: Context, coreConfig: Config) {
}
fun showSwitchCameraButton(): Boolean {
return core.videoDevicesList.orEmpty().size > 2 // Count StaticImage camera
return core.videoDevicesList.size > 2 // Count StaticImage camera
}
fun isVideoCallOrConferenceActive(): Boolean {
return if (core.conference != null && core.isInConference) {
core.conference.currentParams.videoEnabled()
val conference = core.conference
return if (conference != null && core.isInConference) {
conference.currentParams.videoEnabled()
} else {
core.currentCall?.currentParams?.videoEnabled() ?: false
}

View file

@ -107,7 +107,7 @@ class CorePreferences constructor(private val context: Context) {
}
var deviceName: String
get() = config.getString("app", "device_name", Compatibility.getDeviceName(context))
get() = config.getString("app", "device_name", Compatibility.getDeviceName(context))!!
set(value) = config.setString("app", "device_name", value)
var chatRoomShortcuts: Boolean
@ -207,10 +207,10 @@ class CorePreferences constructor(private val context: Context) {
/* Read only application settings previously in non_localizable_custom */
val defaultDomain: String
get() = config.getString("app", "default_domain", "sip.linphone.org")
get() = config.getString("app", "default_domain", "sip.linphone.org")!!
val debugPopupCode: String
get() = config.getString("app", "debug_popup_magic", "#1234#")
get() = config.getString("app", "debug_popup_magic", "#1234#")!!
val fetchContactsFromDefaultDirectory: Boolean
get() = config.getBool("app", "fetch_contacts_from_default_directory", true)
@ -219,13 +219,13 @@ class CorePreferences constructor(private val context: Context) {
get() = config.getBool("app", "hide_contacts_without_presence", false)
val rlsUri: String
get() = config.getString("app", "rls_uri", "sip:rls@sip.linphone.org")
get() = config.getString("app", "rls_uri", "sip:rls@sip.linphone.org")!!
val conferenceServerUri: String
get() = config.getString("app", "default_conference_factory_uri", "sip:conference-factory@sip.linphone.org")
get() = config.getString("app", "default_conference_factory_uri", "sip:conference-factory@sip.linphone.org")!!
val limeX3dhServerUrl: String
get() = config.getString("app", "default_lime_x3dh_server_url", "https://lime.linphone.org/lime-server/lime-server.php")
get() = config.getString("app", "default_lime_x3dh_server_url", "https://lime.linphone.org/lime-server/lime-server.php")!!
val allowMultipleFilesAndTextInSameMessage: Boolean
get() = config.getBool("app", "allow_multiple_files_and_text_in_same_message", true)

View file

@ -35,6 +35,10 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
if (intent.action == NotificationsManager.INTENT_REPLY_NOTIF_ACTION || intent.action == NotificationsManager.INTENT_MARK_AS_READ_ACTION) {
val remoteSipAddress: String? = coreContext.notificationsManager.getSipUriForChatNotificationId(notificationId)
if (remoteSipAddress == null) {
Log.e("[Notification Broadcast Receiver] Couldn't find remote address $remoteSipAddress for notification id $notificationId")
return
}
val core: Core = coreContext.core
val remoteAddress = core.interpretUrl(remoteSipAddress)
@ -75,7 +79,7 @@ class NotificationBroadcastReceiver : BroadcastReceiver() {
val remoteAddress: String? = coreContext.notificationsManager.getSipUriForCallNotificationId(notificationId)
val core: Core = coreContext.core
val call = core.findCallFromUri(remoteAddress)
val call = if (remoteAddress != null) core.findCallFromUri(remoteAddress) else null
if (call == null) {
Log.e("[Notification Broadcast Receiver] Couldn't find call from remote address $remoteAddress")
return

View file

@ -122,7 +122,7 @@ class NotificationsManager(private val context: Context) {
Call.State.IncomingEarlyMedia, Call.State.IncomingReceived -> displayIncomingCallNotification(call)
Call.State.End, Call.State.Error -> dismissCallNotification(call)
Call.State.Released -> {
if (call.callLog?.status == Call.Status.Missed) {
if (call.callLog.status == Call.Status.Missed) {
displayMissedCallNotification(call)
}
}
@ -133,12 +133,12 @@ class NotificationsManager(private val context: Context) {
override fun onMessageReceived(core: Core, room: ChatRoom, message: ChatMessage) {
if (message.isOutgoing) return
if (currentlyDisplayedChatRoomAddress == room.peerAddress?.asStringUriOnly()) {
if (currentlyDisplayedChatRoomAddress == room.peerAddress.asStringUriOnly()) {
Log.i("[Notifications Manager] Chat room is currently displayed, do not notify received message")
return
}
if (message.errorInfo?.reason == Reason.UnsupportedContent) {
if (message.errorInfo.reason == Reason.UnsupportedContent) {
Log.w("[Notifications Manager] Received message with unsupported content, do not notify")
return
}
@ -500,7 +500,7 @@ class NotificationsManager(private val context: Context) {
}
private fun dismissCallNotification(call: Call) {
val address = call.remoteAddress?.asStringUriOnly()
val address = call.remoteAddress.asStringUriOnly()
val notifiable: Notifiable? = callNotificationsMap[address]
if (notifiable != null) {
cancel(notifiable.notificationId)
@ -536,10 +536,10 @@ class NotificationsManager(private val context: Context) {
val notifiable = getNotifiableForRoom(room)
var text = ""
if (message.hasTextContent()) text = message.textContent
if (message.hasTextContent()) text = message.textContent.orEmpty()
else {
for (content in message.contents) {
text = content.name
text += content.name
}
}
val notifiableMessage = NotifiableMessage(text, contact, displayName, message.time, senderAvatar = roundPicture)
@ -592,7 +592,7 @@ class NotificationsManager(private val context: Context) {
Log.i("[Notifications Manager] Updating message notification with reply for notification ${notifiable.notificationId}")
val reply = NotifiableMessage(
message.textContent,
message.textContent.orEmpty(),
null,
notifiable.myself ?: LinphoneUtils.getDisplayName(message.fromAddress),
System.currentTimeMillis()

View file

@ -354,7 +354,7 @@ fun addPrefixEditTextValidation(editText: EditText, enabled: Boolean) {
@BindingAdapter("assistantUsernameValidation")
fun addUsernameEditTextValidation(editText: EditText, enabled: Boolean) {
if (!enabled) return
val usernameRegexp = corePreferences.config.getString("assistant", "username_regex", "^[a-z0-9+_.\\-]*\$")
val usernameRegexp = corePreferences.config.getString("assistant", "username_regex", "^[a-z0-9+_.\\-]*\$")!!
val usernameMaxLength = corePreferences.config.getInt("assistant", "username_max_length", 64)
editText.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {

View file

@ -35,7 +35,7 @@ class LinphoneUtils {
private const val RECORDING_DATE_PATTERN = "dd-MM-yyyy-HH-mm-ss"
fun getDisplayName(address: Address): String {
return address.displayName ?: address.username
return address.displayName ?: address.username ?: ""
}
fun isLimeAvailable(): Boolean {

View file

@ -175,7 +175,7 @@ class ShortcutsHelper(val context: Context) {
personsList.add(contact.getPerson())
}
}
subject = chatRoom.subject
subject = chatRoom.subject.orEmpty()
icon = IconCompat.createWithResource(context, R.drawable.chat_group_avatar)
}