Fixed compil with latest SDK from master that has more @Nullable tags
This commit is contained in:
parent
704df9d583
commit
8e9aa6117c
42 changed files with 238 additions and 166 deletions
|
@ -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() &&
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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?) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue