fixing timeline crash when rotating with the emoji window open

- guarding the emoji popup dismiss callback with a started lifecycle state
- the emoji popup dismiss callback also triggers onViewDetachedFromWindow which does not always finish before onDestroyView
This commit is contained in:
Adam Brown 2021-10-28 19:23:36 +01:00
parent dd6ac46659
commit e12d8c30d8

View file

@ -52,6 +52,7 @@ import androidx.core.view.forEach
import androidx.core.view.isInvisible import androidx.core.view.isInvisible
import androidx.core.view.isVisible import androidx.core.view.isVisible
import androidx.fragment.app.setFragmentResultListener import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
@ -639,17 +640,27 @@ class RoomDetailFragment @Inject constructor(
setImageResource(R.drawable.ic_keyboard) setImageResource(R.drawable.ic_keyboard)
} }
} }
.setOnEmojiPopupDismissListener { .setOnEmojiPopupDismissListenerLifecycleAware {
if (isAdded) { views.composerLayout.views.composerEmojiButton.apply {
views.composerLayout.views.composerEmojiButton.apply { contentDescription = getString(R.string.a11y_open_emoji_picker)
contentDescription = getString(R.string.a11y_open_emoji_picker) setImageResource(R.drawable.ic_insert_emoji)
setImageResource(R.drawable.ic_insert_emoji)
}
} }
} }
.build(views.composerLayout.views.composerEditText) .build(views.composerLayout.views.composerEditText)
} }
/**
* Ensure dismiss actions only trigger when the fragment is in the started state
* EmojiPopup by default dismisses onViewDetachedFromWindow, this can cause race conditions with onDestroyView
*/
private fun EmojiPopup.Builder.setOnEmojiPopupDismissListenerLifecycleAware(action: () -> Unit): EmojiPopup.Builder {
return setOnEmojiPopupDismissListener {
if (lifecycle.currentState == Lifecycle.State.STARTED) {
action()
}
}
}
private val permissionVoiceMessageLauncher = registerForPermissionsResult { allGranted, deniedPermanently -> private val permissionVoiceMessageLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) { if (allGranted) {
// In this case, let the user start again the gesture // In this case, let the user start again the gesture