mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-24 10:25:51 +03:00
Merge pull request #8410 from vector-im/feature/bma/fixCrashes
Fix crashes
This commit is contained in:
commit
f9f341e0ed
9 changed files with 92 additions and 111 deletions
1
changelog.d/8410.bugfix
Normal file
1
changelog.d/8410.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix crash when opening "Protect access" screen, and various other issue with `repeatOnLifecycle`
|
|
@ -21,10 +21,9 @@ import android.text.Editable
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import androidx.autofill.HintConstants
|
import androidx.autofill.HintConstants
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.withResumed
|
||||||
import com.google.android.material.textfield.TextInputLayout
|
import com.google.android.material.textfield.TextInputLayout
|
||||||
import im.vector.app.core.platform.SimpleTextWatcher
|
import im.vector.app.core.platform.SimpleTextWatcher
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -88,7 +87,7 @@ fun TextInputLayout.setOnImeDoneListener(action: () -> Unit) {
|
||||||
fun TextInputLayout.setOnFocusLostListener(lifecycleOwner: LifecycleOwner, action: () -> Unit) {
|
fun TextInputLayout.setOnFocusLostListener(lifecycleOwner: LifecycleOwner, action: () -> Unit) {
|
||||||
editText().setOnFocusChangeListener { _, hasFocus ->
|
editText().setOnFocusChangeListener { _, hasFocus ->
|
||||||
when (hasFocus) {
|
when (hasFocus) {
|
||||||
false -> lifecycleOwner.lifecycleScope.launch { lifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) { action() } }
|
false -> lifecycleOwner.lifecycleScope.launch { lifecycleOwner.withResumed { action() } }
|
||||||
else -> {
|
else -> {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,8 @@ import androidx.core.view.isVisible
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.FragmentManager
|
import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.withResumed
|
||||||
import com.airbnb.mvrx.Mavericks
|
import com.airbnb.mvrx.Mavericks
|
||||||
import com.airbnb.mvrx.viewModel
|
import com.airbnb.mvrx.viewModel
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
@ -402,7 +401,9 @@ class HomeActivity :
|
||||||
private fun handleStartRecoverySetup() {
|
private fun handleStartRecoverySetup() {
|
||||||
// To avoid IllegalStateException in case the transaction was executed after onSaveInstanceState
|
// To avoid IllegalStateException in case the transaction was executed after onSaveInstanceState
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) { navigator.open4SSetup(this@HomeActivity, SetupMode.NORMAL) }
|
withResumed {
|
||||||
|
navigator.open4SSetup(this@HomeActivity, SetupMode.NORMAL)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,8 @@ import androidx.core.view.isInvisible
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.core.view.updatePadding
|
import androidx.core.view.updatePadding
|
||||||
import androidx.fragment.app.setFragmentResultListener
|
import androidx.fragment.app.setFragmentResultListener
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.withResumed
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
@ -1112,29 +1111,31 @@ class TimelineFragment :
|
||||||
private fun updateJumpToReadMarkerViewVisibility() {
|
private fun updateJumpToReadMarkerViewVisibility() {
|
||||||
if (isThreadTimeLine()) return
|
if (isThreadTimeLine()) return
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
withResumed {
|
||||||
val state = timelineViewModel.awaitState()
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
val showJumpToUnreadBanner = when (state.unreadState) {
|
val state = timelineViewModel.awaitState()
|
||||||
UnreadState.Unknown,
|
val showJumpToUnreadBanner = when (state.unreadState) {
|
||||||
UnreadState.HasNoUnread -> false
|
UnreadState.Unknown,
|
||||||
is UnreadState.ReadMarkerNotLoaded -> true
|
UnreadState.HasNoUnread -> false
|
||||||
is UnreadState.HasUnread -> {
|
is UnreadState.ReadMarkerNotLoaded -> true
|
||||||
if (state.canShowJumpToReadMarker) {
|
is UnreadState.HasUnread -> {
|
||||||
val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition()
|
if (state.canShowJumpToReadMarker) {
|
||||||
val positionOfReadMarker = withContext(Dispatchers.Default) {
|
val lastVisibleItem = layoutManager.findLastCompletelyVisibleItemPosition()
|
||||||
timelineEventController.getPositionOfReadMarker()
|
val positionOfReadMarker = withContext(Dispatchers.Default) {
|
||||||
}
|
timelineEventController.getPositionOfReadMarker()
|
||||||
if (positionOfReadMarker == null) {
|
}
|
||||||
false
|
if (positionOfReadMarker == null) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
positionOfReadMarker > lastVisibleItem
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
positionOfReadMarker > lastVisibleItem
|
false
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
views.jumpToReadMarkerView.isVisible = showJumpToUnreadBanner
|
||||||
}
|
}
|
||||||
views.jumpToReadMarkerView.isVisible = showJumpToUnreadBanner
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1625,14 +1626,16 @@ class TimelineFragment :
|
||||||
|
|
||||||
override fun onRoomCreateLinkClicked(url: String) {
|
override fun onRoomCreateLinkClicked(url: String) {
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
withResumed {
|
||||||
permalinkHandler
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
.launch(requireActivity(), url, object : NavigationInterceptor {
|
permalinkHandler
|
||||||
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
|
.launch(requireActivity(), url, object : NavigationInterceptor {
|
||||||
requireActivity().finish()
|
override fun navToRoom(roomId: String?, eventId: String?, deepLink: Uri?, rootThreadEventId: String?): Boolean {
|
||||||
return false
|
requireActivity().finish()
|
||||||
}
|
return false
|
||||||
})
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,9 +26,7 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
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.lifecycle.repeatOnLifecycle
|
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
@ -101,12 +99,10 @@ class LocationSharingFragment :
|
||||||
views.mapView.onCreate(savedInstanceState)
|
views.mapView.onCreate(savedInstanceState)
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
|
views.mapView.initialize(
|
||||||
views.mapView.initialize(
|
url = urlMapProvider.getMapUrl(),
|
||||||
url = urlMapProvider.getMapUrl(),
|
locationTargetChangeListener = this@LocationSharingFragment
|
||||||
locationTargetChangeListener = this@LocationSharingFragment
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
initLocateButton()
|
initLocateButton()
|
||||||
|
|
|
@ -22,9 +22,7 @@ import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
|
||||||
import com.airbnb.mvrx.args
|
import com.airbnb.mvrx.args
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
@ -81,9 +79,7 @@ class LocationPreviewFragment :
|
||||||
views.mapView.onCreate(savedInstanceState)
|
views.mapView.onCreate(savedInstanceState)
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) {
|
views.mapView.initialize(urlMapProvider.getMapUrl())
|
||||||
views.mapView.initialize(urlMapProvider.getMapUrl())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
observeViewEvents()
|
observeViewEvents()
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
package im.vector.app.features.settings
|
package im.vector.app.features.settings
|
||||||
|
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
@ -80,13 +78,13 @@ class VectorSettingsPinFragment :
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
updateBiometricPrefState(isPinCodeChecked = usePinCodePref.isChecked)
|
updateBiometricPrefState(isPinCodeChecked = usePinCodePref.isChecked)
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
|
refreshPinCodeStatus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindPref() {
|
override fun bindPref() {
|
||||||
refreshPinCodeStatus()
|
|
||||||
|
|
||||||
usePinCodePref.setOnPreferenceChangeListener { _, value ->
|
usePinCodePref.setOnPreferenceChangeListener { _, value ->
|
||||||
val isChecked = (value as? Boolean).orFalse()
|
val isChecked = (value as? Boolean).orFalse()
|
||||||
updateBiometricPrefState(isPinCodeChecked = isChecked)
|
updateBiometricPrefState(isPinCodeChecked = isChecked)
|
||||||
|
@ -130,38 +128,34 @@ class VectorSettingsPinFragment :
|
||||||
.onFailure { Timber.e(it) }
|
.onFailure { Timber.e(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshPinCodeStatus() {
|
private suspend fun refreshPinCodeStatus() {
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
val hasPinCode = pinCodeStore.hasEncodedPin()
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
usePinCodePref.isChecked = hasPinCode
|
||||||
val hasPinCode = pinCodeStore.hasEncodedPin()
|
usePinCodePref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
usePinCodePref.isChecked = hasPinCode
|
if (hasPinCode) {
|
||||||
usePinCodePref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
lifecycleScope.launch {
|
||||||
if (hasPinCode) {
|
pinCodeStore.deletePinCode()
|
||||||
lifecycleScope.launch {
|
refreshPinCodeStatus()
|
||||||
pinCodeStore.deletePinCode()
|
|
||||||
refreshPinCodeStatus()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
navigator.openPinCode(
|
|
||||||
requireContext(),
|
|
||||||
pinActivityResultLauncher,
|
|
||||||
PinMode.CREATE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
changePinCodePref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
|
||||||
if (hasPinCode) {
|
|
||||||
navigator.openPinCode(
|
|
||||||
requireContext(),
|
|
||||||
pinActivityResultLauncher,
|
|
||||||
PinMode.MODIFY
|
|
||||||
)
|
|
||||||
}
|
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
navigator.openPinCode(
|
||||||
|
requireContext(),
|
||||||
|
pinActivityResultLauncher,
|
||||||
|
PinMode.CREATE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
changePinCodePref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
if (hasPinCode) {
|
||||||
|
navigator.openPinCode(
|
||||||
|
requireContext(),
|
||||||
|
pinActivityResultLauncher,
|
||||||
|
PinMode.MODIFY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +164,6 @@ class VectorSettingsPinFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
private val pinActivityResultLauncher = registerStartForActivityResult {
|
private val pinActivityResultLauncher = registerStartForActivityResult {
|
||||||
refreshPinCodeStatus()
|
// Nothing to do, refreshPinCodeStatus() will be called by `onResume`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,9 +27,8 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.withResumed
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.SwitchPreference
|
import androidx.preference.SwitchPreference
|
||||||
|
@ -190,6 +189,10 @@ class VectorSettingsSecurityPrivacyFragment :
|
||||||
rawService
|
rawService
|
||||||
.getElementWellknown(session.sessionParams)
|
.getElementWellknown(session.sessionParams)
|
||||||
?.isE2EByDefault() == false
|
?.isE2EByDefault() == false
|
||||||
|
|
||||||
|
refreshXSigningStatus()
|
||||||
|
// My device name may have been updated
|
||||||
|
refreshMyDevice()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -288,19 +291,6 @@ class VectorSettingsSecurityPrivacyFragment :
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
lifecycleScope.launch {
|
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
|
||||||
refreshXSigningStatus()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lifecycleScope.launch {
|
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
|
||||||
// My device name may have been updated
|
|
||||||
refreshMyDevice()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
secureBackupPreference.icon = activity?.let {
|
secureBackupPreference.icon = activity?.let {
|
||||||
ThemeUtils.tintDrawable(
|
ThemeUtils.tintDrawable(
|
||||||
it,
|
it,
|
||||||
|
@ -429,16 +419,18 @@ class VectorSettingsSecurityPrivacyFragment :
|
||||||
|
|
||||||
private fun openPinCodePreferenceScreen() {
|
private fun openPinCodePreferenceScreen() {
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
withResumed {
|
||||||
val hasPinCode = pinCodeStore.hasEncodedPin()
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
if (hasPinCode) {
|
val hasPinCode = pinCodeStore.hasEncodedPin()
|
||||||
navigator.openPinCode(
|
if (hasPinCode) {
|
||||||
requireContext(),
|
navigator.openPinCode(
|
||||||
pinActivityResultLauncher,
|
requireContext(),
|
||||||
PinMode.AUTH
|
pinActivityResultLauncher,
|
||||||
)
|
PinMode.AUTH
|
||||||
} else {
|
)
|
||||||
doOpenPinCodePreferenceScreen()
|
} else {
|
||||||
|
doOpenPinCodePreferenceScreen()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,8 @@ import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ScrollView
|
import android.widget.ScrollView
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import androidx.lifecycle.Lifecycle
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.withResumed
|
||||||
import com.airbnb.mvrx.activityViewModel
|
import com.airbnb.mvrx.activityViewModel
|
||||||
import com.airbnb.mvrx.args
|
import com.airbnb.mvrx.args
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
|
@ -178,7 +177,7 @@ class UserListFragment :
|
||||||
// Scroll to the bottom when adding chips. When removing chips, do not scroll
|
// Scroll to the bottom when adding chips. When removing chips, do not scroll
|
||||||
if (newNumberOfChips >= currentNumberOfChips) {
|
if (newNumberOfChips >= currentNumberOfChips) {
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
withResumed {
|
||||||
views.chipGroupScrollView.fullScroll(ScrollView.FOCUS_DOWN)
|
views.chipGroupScrollView.fullScroll(ScrollView.FOCUS_DOWN)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue