Prevent crashes due to various exceptions + fixed navigation issue

This commit is contained in:
Sylvain Berfini 2022-06-27 09:53:29 +02:00
parent 40de347237
commit 244885e0aa
7 changed files with 157 additions and 108 deletions

View file

@ -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()
}
}
}
}

View file

@ -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)

View file

@ -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()

View file

@ -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)

View file

@ -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()
}

View file

@ -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()
}

View file

@ -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