Prevent crashes due to various exceptions + fixed navigation issue
This commit is contained in:
parent
40de347237
commit
244885e0aa
7 changed files with 157 additions and 108 deletions
|
@ -24,6 +24,7 @@ import android.content.Context.CLIPBOARD_SERVICE
|
|||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.activities.GenericFragment
|
||||
|
@ -73,12 +74,16 @@ class PhoneAccountValidationFragment : GenericFragment<AssistantPhoneAccountVali
|
|||
}
|
||||
}
|
||||
viewModel.isLinking.value == true -> {
|
||||
val args = Bundle()
|
||||
args.putString(
|
||||
"Identity",
|
||||
"sip:${viewModel.accountCreator.username}@${viewModel.accountCreator.domain}"
|
||||
)
|
||||
navigateToAccountSettings(args)
|
||||
if (findNavController().graph.id == R.id.settings_nav_graph_xml) {
|
||||
val args = Bundle()
|
||||
args.putString(
|
||||
"Identity",
|
||||
"sip:${viewModel.accountCreator.username}@${viewModel.accountCreator.domain}"
|
||||
)
|
||||
navigateToAccountSettings(args)
|
||||
} else {
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.linphone.activities.assistant.viewmodels.WelcomeViewModel
|
|||
import org.linphone.activities.navigateToAccountLogin
|
||||
import org.linphone.activities.navigateToEmailAccountCreation
|
||||
import org.linphone.activities.navigateToRemoteProvisioning
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.AssistantWelcomeFragmentBinding
|
||||
|
||||
class WelcomeFragment : GenericFragment<AssistantWelcomeFragmentBinding>() {
|
||||
|
@ -99,7 +100,11 @@ class WelcomeFragment : GenericFragment<AssistantWelcomeFragmentBinding>() {
|
|||
Intent.ACTION_VIEW,
|
||||
Uri.parse(getString(R.string.assistant_general_terms_link))
|
||||
)
|
||||
startActivity(browserIntent)
|
||||
try {
|
||||
startActivity(browserIntent)
|
||||
} catch (e: Exception) {
|
||||
Log.e("[Welcome] Can't start activity: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
spannable.setSpan(clickableSpan, termsMatcher.start(0), termsMatcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
@ -113,7 +118,11 @@ class WelcomeFragment : GenericFragment<AssistantWelcomeFragmentBinding>() {
|
|||
Intent.ACTION_VIEW,
|
||||
Uri.parse(getString(R.string.assistant_privacy_policy_link))
|
||||
)
|
||||
startActivity(browserIntent)
|
||||
try {
|
||||
startActivity(browserIntent)
|
||||
} catch (e: Exception) {
|
||||
Log.e("[Welcome] Can't start activity: $e")
|
||||
}
|
||||
}
|
||||
}
|
||||
spannable.setSpan(clickableSpan, policyMatcher.start(0), policyMatcher.end(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
||||
|
|
|
@ -241,24 +241,32 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
)
|
||||
val swipeListener = object : RecyclerViewSwipeListener {
|
||||
override fun onLeftToRightSwipe(viewHolder: RecyclerView.ViewHolder) {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[Chat Room] Index is out of bound, can't reply to chat message")
|
||||
} else {
|
||||
adapter.notifyItemChanged(index)
|
||||
|
||||
val chatMessageEventLog = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
val chatMessage = chatMessageEventLog.eventLog.chatMessage
|
||||
if (chatMessage != null) {
|
||||
chatSendingViewModel.pendingChatMessageToReplyTo.value?.destroy()
|
||||
chatSendingViewModel.pendingChatMessageToReplyTo.value =
|
||||
ChatMessageData(chatMessage)
|
||||
chatSendingViewModel.isPendingAnswer.value = true
|
||||
val chatMessageEventLog = adapter.currentList[index]
|
||||
val chatMessage = chatMessageEventLog.eventLog.chatMessage
|
||||
if (chatMessage != null) {
|
||||
chatSendingViewModel.pendingChatMessageToReplyTo.value?.destroy()
|
||||
chatSendingViewModel.pendingChatMessageToReplyTo.value =
|
||||
ChatMessageData(chatMessage)
|
||||
chatSendingViewModel.isPendingAnswer.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRightToLeftSwipe(viewHolder: RecyclerView.ViewHolder) {
|
||||
val position = viewHolder.bindingAdapterPosition
|
||||
// adapter.notifyItemRemoved(viewHolder.bindingAdapterPosition)
|
||||
|
||||
val eventLog = adapter.currentList[position]
|
||||
addDeleteMessageTaskToQueue(eventLog, position)
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[Chat Room] Index is out of bound, can't delete chat message")
|
||||
} else {
|
||||
// adapter.notifyItemRemoved(index)
|
||||
val eventLog = adapter.currentList[index]
|
||||
addDeleteMessageTaskToQueue(eventLog, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
RecyclerViewSwipeUtils(ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT, swipeConfiguration, swipeListener)
|
||||
|
@ -421,7 +429,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
var path = content.filePath.orEmpty()
|
||||
|
||||
if (path.isNotEmpty() && !File(path).exists()) {
|
||||
Log.e("[Chat Message] File not found: $path")
|
||||
Log.e("[Chat Room] File not found: $path")
|
||||
(requireActivity() as MainActivity).showSnackBar(R.string.chat_room_file_not_found)
|
||||
} else {
|
||||
if (path.isEmpty()) {
|
||||
|
@ -431,18 +439,18 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
FileUtils.writeIntoFile(content.buffer, file)
|
||||
path = file.absolutePath
|
||||
content.filePath = path
|
||||
Log.i("[Chat Message] Content file path was empty, created file from buffer at $path")
|
||||
Log.i("[Chat Room] Content file path was empty, created file from buffer at $path")
|
||||
} else if (content.isIcalendar) {
|
||||
val name = "conference.ics"
|
||||
val file = FileUtils.getFileStoragePath(name)
|
||||
FileUtils.writeIntoFile(content.buffer, file)
|
||||
path = file.absolutePath
|
||||
content.filePath = path
|
||||
Log.i("[Chat Message] Content file path was empty, created conference.ics from buffer at $path")
|
||||
Log.i("[Chat Room] Content file path was empty, created conference.ics from buffer at $path")
|
||||
}
|
||||
}
|
||||
|
||||
Log.i("[Chat Message] Opening file: $path")
|
||||
Log.i("[Chat Room] Opening file: $path")
|
||||
sharedViewModel.contentToOpen.value = content
|
||||
|
||||
if (corePreferences.useInAppFileViewerForNonEncryptedFiles || content.isFileEncrypted) {
|
||||
|
@ -466,7 +474,7 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
)
|
||||
else -> {
|
||||
if (content.isFileEncrypted) {
|
||||
Log.w("[Chat Message] File is encrypted and can't be opened in one of our viewers...")
|
||||
Log.w("[Chat Room] File is encrypted and can't be opened in one of our viewers...")
|
||||
showDialogForUserConsentBeforeExportingFileInThirdPartyApp(
|
||||
content
|
||||
)
|
||||
|
@ -654,11 +662,11 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
viewLifecycleOwner
|
||||
) {
|
||||
it.consume { uri ->
|
||||
Log.i("[Chat] Found rich content URI: $uri")
|
||||
Log.i("[Chat Room] Found rich content URI: $uri")
|
||||
lifecycleScope.launch {
|
||||
withContext(Dispatchers.Main) {
|
||||
val path = FileUtils.getFilePath(requireContext(), uri)
|
||||
Log.i("[Chat] Rich content URI: $uri matching path is: $path")
|
||||
Log.i("[Chat Room] Rich content URI: $uri matching path is: $path")
|
||||
if (path != null) {
|
||||
chatSendingViewModel.addAttachment(path)
|
||||
}
|
||||
|
@ -1053,18 +1061,22 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
val tempFileName = System.currentTimeMillis().toString() + ".jpeg"
|
||||
val file = FileUtils.getFileStoragePath(tempFileName)
|
||||
chatSendingViewModel.temporaryFileUploadPath = file
|
||||
val publicUri = FileProvider.getUriForFile(
|
||||
requireContext(),
|
||||
requireContext().getString(R.string.file_provider),
|
||||
file
|
||||
)
|
||||
capturePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, publicUri)
|
||||
capturePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
capturePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
intentsList.add(capturePictureIntent)
|
||||
try {
|
||||
val publicUri = FileProvider.getUriForFile(
|
||||
requireContext(),
|
||||
requireContext().getString(R.string.file_provider),
|
||||
file
|
||||
)
|
||||
capturePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, publicUri)
|
||||
capturePictureIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||
capturePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
intentsList.add(capturePictureIntent)
|
||||
|
||||
val captureVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
|
||||
intentsList.add(captureVideoIntent)
|
||||
val captureVideoIntent = Intent(MediaStore.ACTION_VIDEO_CAPTURE)
|
||||
intentsList.add(captureVideoIntent)
|
||||
} catch (e: Exception) {
|
||||
Log.e("[Chat Room] Failed to pick file: $e")
|
||||
}
|
||||
}
|
||||
|
||||
val chooserIntent =
|
||||
|
@ -1109,10 +1121,10 @@ class DetailChatRoomFragment : MasterFragment<ChatRoomDetailFragmentBinding, Cha
|
|||
lifecycleScope.launch {
|
||||
Log.w("[Chat Room] Content is encrypted, requesting plain file path")
|
||||
val plainFilePath = content.exportPlainFile()
|
||||
Log.i("[Cht Room] Making a copy of [$plainFilePath] to the cache directory before exporting it")
|
||||
Log.i("[Chat Room] Making a copy of [$plainFilePath] to the cache directory before exporting it")
|
||||
val cacheCopyPath = FileUtils.copyFileToCache(plainFilePath)
|
||||
if (cacheCopyPath != null) {
|
||||
Log.i("[Cht Room] Cache copy has been made: $cacheCopyPath")
|
||||
Log.i("[Chat Room] Cache copy has been made: $cacheCopyPath")
|
||||
FileUtils.deleteFile(plainFilePath)
|
||||
if (!FileUtils.openFileInThirdPartyApp(requireActivity(), cacheCopyPath)) {
|
||||
showDialogToSuggestOpeningFileAsText()
|
||||
|
|
|
@ -188,36 +188,47 @@ class MasterChatRoomsFragment : MasterFragment<ChatRoomMasterFragmentBinding, Ch
|
|||
)
|
||||
val swipeListener = object : RecyclerViewSwipeListener {
|
||||
override fun onLeftToRightSwipe(viewHolder: RecyclerView.ViewHolder) {
|
||||
val chatRoom = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
chatRoom.markAsRead()
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[Chat] Index is out of bound, can't mark chat room as read")
|
||||
} else {
|
||||
val chatRoom = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
chatRoom.markAsRead()
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRightToLeftSwipe(viewHolder: RecyclerView.ViewHolder) {
|
||||
val viewModel = DialogViewModel(getString(R.string.chat_room_delete_one_dialog))
|
||||
val dialog: Dialog = DialogUtils.getDialog(requireContext(), viewModel)
|
||||
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedChatRoom = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
listViewModel.deleteChatRoom(deletedChatRoom)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedChatRoom == sharedViewModel.selectedChatRoom.value
|
||||
) {
|
||||
Log.i("[Chat] Currently displayed chat room has been deleted, removing detail fragment")
|
||||
clearDisplayedChatRoom()
|
||||
}
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[Chat] Index is out of bound, can't delete chat room")
|
||||
} else {
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedChatRoom =
|
||||
adapter.currentList[index]
|
||||
listViewModel.deleteChatRoom(deletedChatRoom)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedChatRoom == sharedViewModel.selectedChatRoom.value
|
||||
) {
|
||||
Log.i("[Chat] Currently displayed chat room has been deleted, removing detail fragment")
|
||||
clearDisplayedChatRoom()
|
||||
}
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
RecyclerViewSwipeUtils(ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT, swipeConfiguration, swipeListener)
|
||||
|
|
|
@ -173,35 +173,41 @@ class MasterContactsFragment : MasterFragment<ContactMasterFragmentBinding, Cont
|
|||
val viewModel = DialogViewModel(getString(R.string.contact_delete_one_dialog))
|
||||
val dialog: Dialog = DialogUtils.getDialog(requireContext(), viewModel)
|
||||
|
||||
val contactViewModel = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
if (contactViewModel.isNativeContact.value == false) {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
val activity = requireActivity() as MainActivity
|
||||
activity.showSnackBar(R.string.contact_cant_be_deleted)
|
||||
return
|
||||
}
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[Contacts] Index is out of bound, can't delete contact")
|
||||
} else {
|
||||
val contactViewModel = adapter.currentList[index]
|
||||
if (contactViewModel.isNativeContact.value == false) {
|
||||
adapter.notifyItemChanged(index)
|
||||
val activity = requireActivity() as MainActivity
|
||||
activity.showSnackBar(R.string.contact_cant_be_deleted)
|
||||
return
|
||||
}
|
||||
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedContact = adapter.currentList[viewHolder.bindingAdapterPosition].contact.value
|
||||
if (deletedContact != null) {
|
||||
listViewModel.deleteContact(deletedContact)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedContact == sharedViewModel.selectedContact.value
|
||||
) {
|
||||
Log.i("[Contacts] Currently displayed contact has been deleted, removing detail fragment")
|
||||
clearDisplayedContact()
|
||||
}
|
||||
}
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(index)
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
}
|
||||
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedContact =
|
||||
adapter.currentList[index].contact.value
|
||||
if (deletedContact != null) {
|
||||
listViewModel.deleteContact(deletedContact)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedContact == sharedViewModel.selectedContact.value
|
||||
) {
|
||||
Log.i("[Contacts] Currently displayed contact has been deleted, removing detail fragment")
|
||||
clearDisplayedContact()
|
||||
}
|
||||
}
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
|
|
@ -159,25 +159,30 @@ class MasterCallLogsFragment : MasterFragment<HistoryMasterFragmentBinding, Call
|
|||
val viewModel = DialogViewModel(getString(R.string.history_delete_one_dialog))
|
||||
val dialog: Dialog = DialogUtils.getDialog(requireContext(), viewModel)
|
||||
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(viewHolder.bindingAdapterPosition)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedCallGroup = adapter.currentList[viewHolder.bindingAdapterPosition]
|
||||
listViewModel.deleteCallLogGroup(deletedCallGroup)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedCallGroup.lastCallLog.callId == sharedViewModel.selectedCallLogGroup.value?.lastCallLog?.callId
|
||||
) {
|
||||
Log.i("[History] Currently displayed history has been deleted, removing detail fragment")
|
||||
clearDisplayedCallHistory()
|
||||
}
|
||||
val index = viewHolder.bindingAdapterPosition
|
||||
if (index < 0 || index >= adapter.currentList.size) {
|
||||
Log.e("[History] Index is out of bound, can't delete call log")
|
||||
} else {
|
||||
viewModel.showCancelButton {
|
||||
adapter.notifyItemChanged(index)
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
}
|
||||
|
||||
viewModel.showDeleteButton(
|
||||
{
|
||||
val deletedCallGroup = adapter.currentList[index]
|
||||
listViewModel.deleteCallLogGroup(deletedCallGroup)
|
||||
if (!binding.slidingPane.isSlideable &&
|
||||
deletedCallGroup.lastCallLog.callId == sharedViewModel.selectedCallLogGroup.value?.lastCallLog?.callId
|
||||
) {
|
||||
Log.i("[History] Currently displayed history has been deleted, removing detail fragment")
|
||||
clearDisplayedCallHistory()
|
||||
}
|
||||
dialog.dismiss()
|
||||
},
|
||||
getString(R.string.dialog_delete)
|
||||
)
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/settings_nav_graph_xml"
|
||||
app:startDestination="@id/emptySettingsFragment">
|
||||
|
||||
<fragment
|
||||
|
|
Loading…
Reference in a new issue