diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationReactionDelegate.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationReactionDelegate.java index 85ed14a257..949f1516e8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationReactionDelegate.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationReactionDelegate.java @@ -47,10 +47,6 @@ public final class ConversationReactionDelegate { overlayStub.get().hide(); } - public void hideForReactWithAny() { - overlayStub.get().hideForReactWithAny(); - } - public void setOnReactionSelectedListener(@NonNull ConversationReactionOverlay.OnReactionSelectedListener onReactionSelectedListener) { this.onReactionSelectedListener = onReactionSelectedListener; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt index 0b9d217d1b..51e48d28f0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt @@ -86,6 +86,7 @@ import io.reactivex.rxjava3.disposables.Disposable import io.reactivex.rxjava3.kotlin.subscribeBy import io.reactivex.rxjava3.schedulers.Schedulers import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch @@ -511,13 +512,18 @@ class ConversationFragment : private lateinit var threadHeaderMarginDecoration: ThreadHeaderMarginDecoration private lateinit var conversationItemDecorations: ConversationItemDecorations private lateinit var optionsMenuCallback: ConversationOptionsMenuCallback - private lateinit var backPressedCallback: BackPressedDelegate private var animationsAllowed = false private var actionMode: ActionMode? = null private var pinnedShortcutReceiver: BroadcastReceiver? = null private var searchMenuItem: MenuItem? = null + private var isSearchRequested: Boolean = false + set(value) { + field = value + viewModel.setIsSearchRequested(value) + } + private var previousPage: KeyboardPage? = null private var previousPages: Set? = null private var reShowScheduleMessagesBar: Boolean = false @@ -939,8 +945,16 @@ class ConversationFragment : activity?.supportStartPostponedEnterTransition() - backPressedCallback = BackPressedDelegate() - requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback) + val backPressedDelegate = BackPressedDelegate() + requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedDelegate) + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.RESUMED) { + viewModel.backPressedState.collectLatest { + backPressedDelegate.isEnabled = it.shouldHandleBackPressed() + } + } + } menuProvider?.afterFirstRenderMode = true @@ -2217,6 +2231,7 @@ class ConversationFragment : reactionDelegate.setOnActionSelectedListener(onActionSelectedListener) reactionDelegate.setOnHideListener(onHideListener) reactionDelegate.show(requireActivity(), viewModel.recipientSnapshot!!, conversationMessage, conversationGroupViewModel.isNonAdminInAnnouncementGroup(), selectedConversationModel) + viewModel.setIsReactionDelegateShowing(true) composeText.clearFocus() } @@ -2344,18 +2359,15 @@ class ConversationFragment : } } - private inner class BackPressedDelegate : OnBackPressedCallback(true) { + private inner class BackPressedDelegate : OnBackPressedCallback(false) { override fun handleOnBackPressed() { Log.d(TAG, "onBackPressed()") - if (reactionDelegate.isShowing) { + val state = viewModel.backPressedState.value + + if (state.isReactionDelegateShowing) { reactionDelegate.hide() - } else if (isSearchRequested) { + } else if (state.isSearchRequested) { searchMenuItem?.collapseActionView() - } else if (args.conversationScreenType.isInBubble) { - isEnabled = false - requireActivity().onBackPressed() - } else { - requireActivity().finish() } } } @@ -3255,6 +3267,8 @@ class ConversationFragment : } override fun onHide() { + viewModel.setIsReactionDelegateShowing(false) + if (!lifecycle.currentState.isAtLeast(Lifecycle.State.STARTED) || activity == null || activity?.isFinishing == true) { return } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt index 629dcfc1e5..bd63cb370e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationViewModel.kt @@ -32,11 +32,14 @@ import io.reactivex.rxjava3.subjects.PublishSubject import io.reactivex.rxjava3.subjects.Subject import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.rx3.asFlow import org.signal.core.util.orNull @@ -191,6 +194,9 @@ class ConversationViewModel( val jumpToDateValidator: JumpToDateValidator get() = _jumpToDateValidator + private val internalBackPressedState = MutableStateFlow(BackPressedState()) + val backPressedState: StateFlow = internalBackPressedState + init { disposables += recipient .subscribeBy { @@ -604,4 +610,23 @@ class ConversationViewModel( .getEarliestMessageSentDate(threadId) .observeOn(AndroidSchedulers.mainThread()) } + + fun setIsReactionDelegateShowing(isReactionDelegateShowing: Boolean) { + internalBackPressedState.update { + it.copy(isReactionDelegateShowing = isReactionDelegateShowing) + } + } + + fun setIsSearchRequested(isSearchRequested: Boolean) { + internalBackPressedState.update { + it.copy(isSearchRequested = isSearchRequested) + } + } + + data class BackPressedState( + val isReactionDelegateShowing: Boolean = false, + val isSearchRequested: Boolean = false + ) { + fun shouldHandleBackPressed() = isSearchRequested || isReactionDelegateShowing + } }