Fixed first sliding pane child fragment not being poped-up when closing sliding pane, manually navigating to empty fragment to workaround that

This commit is contained in:
Sylvain Berfini 2023-12-05 10:32:31 +01:00
parent 9eb4458c73
commit e9b1bfd2a0
13 changed files with 110 additions and 53 deletions

View file

@ -146,7 +146,7 @@ class NotificationsManager @MainThread constructor(private val context: Context)
if (corePreferences.disableChat) return
val id = LinphoneUtils.getChatRoomId(chatRoom)
if (id == currentlyDisplayedChatRoomId) {
if (currentlyDisplayedChatRoomId.isNotEmpty() && id == currentlyDisplayedChatRoomId) {
Log.i(
"$TAG Do not notify received messages for currently displayed conversation [$id]"
)
@ -188,12 +188,12 @@ class NotificationsManager @MainThread constructor(private val context: Context)
if (corePreferences.disableChat) return
val id = LinphoneUtils.getChatRoomId(chatRoom)
if (id == currentlyDisplayedChatRoomId) {
/*if (id == currentlyDisplayedChatRoomId) {
Log.i(
"$TAG Do not notify received reaction for currently displayed conversation [$id]"
)
return
}
}*/
if (chatRoom.muted) {
Log.i("$TAG Conversation $id has been muted")
@ -337,12 +337,16 @@ class NotificationsManager @MainThread constructor(private val context: Context)
@AnyThread
fun setCurrentlyDisplayedChatRoomId(id: String) {
Log.i(
"$TAG Currently displayed conversation is [$id], messages received in it won't be notified"
)
currentlyDisplayedChatRoomId = id
}
@AnyThread
fun resetCurrentlyDisplayedChatRoomId() {
currentlyDisplayedChatRoomId = ""
Log.i("$TAG Reset currently displayed conversation")
}
@MainThread

View file

@ -204,11 +204,13 @@ class ConversationFragment : SlidingPaneChildFragment() {
}
override fun goBack(): Boolean {
coreContext.notificationsManager.resetCurrentlyDisplayedChatRoomId()
sharedViewModel.closeSlidingPaneEvent.value = Event(true)
coreContext.notificationsManager.resetCurrentlyDisplayedChatRoomId()
// If not done, when going back to ConversationsListFragment this fragment will be created again
return findNavController().popBackStack()
// If not done this fragment won't be paused, which will cause us issues
val action = ConversationFragmentDirections.actionConversationFragmentToEmptyFragment()
findNavController().navigate(action)
return true
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -294,6 +296,12 @@ class ConversationFragment : SlidingPaneChildFragment() {
}
}
viewModel.scrollToBottomEvent.observe(viewLifecycleOwner) {
it.consume {
binding.eventsList.scrollToPosition(adapter.itemCount - 1)
}
}
binding.messageBottomSheet.bottomSheetList.setHasFixedSize(true)
val bottomSheetLayoutManager = LinearLayoutManager(requireContext())
binding.messageBottomSheet.bottomSheetList.layoutManager = bottomSheetLayoutManager
@ -540,6 +548,8 @@ class ConversationFragment : SlidingPaneChildFragment() {
}
override fun onPause() {
super.onPause()
coreContext.postOnCoreThread {
bottomSheetReactionsModel?.destroy()
bottomSheetDeliveryModel?.destroy()
@ -562,8 +572,6 @@ class ConversationFragment : SlidingPaneChildFragment() {
val bottomSheetBehavior = BottomSheetBehavior.from(binding.messageBottomSheet.root)
bottomSheetBehavior.removeBottomSheetCallback(bottomSheetCallback)
currentChatMessageModelForBottomSheet = null
super.onPause()
}
private fun scrollToFirstUnreadMessageOrBottom(smooth: Boolean): Boolean {

View file

@ -26,6 +26,8 @@ import androidx.lifecycle.ViewModel
import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.R
import org.linphone.core.Address
import org.linphone.core.ChatMessage
import org.linphone.core.ChatMessageReaction
import org.linphone.core.ChatRoom
import org.linphone.core.ChatRoomListenerStub
import org.linphone.core.EventLog
@ -83,6 +85,10 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
MutableLiveData<Event<String>>()
}
val scrollToBottomEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
val chatRoomFoundEvent = MutableLiveData<Event<Boolean>>()
lateinit var chatRoom: ChatRoom
@ -132,18 +138,7 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
override fun onChatMessageSent(chatRoom: ChatRoom, eventLog: EventLog) {
val message = eventLog.chatMessage
Log.i("$TAG Message [$message] has been sent")
}
@WorkerThread
override fun onIsComposingReceived(
chatRoom: ChatRoom,
remoteAddress: Address,
isComposing: Boolean
) {
Log.i(
"$TAG Remote [${remoteAddress.asStringUriOnly()}] is ${if (isComposing) "composing" else "no longer composing"}"
)
computeComposingLabel()
scrollToBottomEvent.postValue(Event(true))
}
@WorkerThread
@ -178,6 +173,33 @@ class ConversationViewModel @UiThread constructor() : ViewModel() {
chatRoom.markAsRead()
}
@WorkerThread
override fun onNewMessageReaction(
chatRoom: ChatRoom,
message: ChatMessage,
reaction: ChatMessageReaction
) {
Log.i(
"$TAG A reaction [${reaction.body}] was received from [${reaction.fromAddress.asStringUriOnly()}]"
)
if (message == (events.value.orEmpty().lastOrNull()?.model as? MessageModel)?.chatMessage) {
// Scrolling to bottom to ensure reaction is visible
scrollToBottomEvent.postValue(Event(true))
}
}
@WorkerThread
override fun onIsComposingReceived(
chatRoom: ChatRoom,
remoteAddress: Address,
isComposing: Boolean
) {
Log.i(
"$TAG Remote [${remoteAddress.asStringUriOnly()}] is ${if (isComposing) "composing" else "no longer composing"}"
)
computeComposingLabel()
}
@WorkerThread
override fun onEphemeralEvent(chatRoom: ChatRoom, eventLog: EventLog) {
Log.i("$TAG Adding new ephemeral event [${eventLog.type}]")

View file

@ -77,8 +77,11 @@ class ContactFragment : SlidingPaneChildFragment() {
override fun goBack(): Boolean {
sharedViewModel.closeSlidingPaneEvent.value = Event(true)
// If not done, when going back to ContactsFragment this fragment will be created again
return findNavController().popBackStack()
// If not done this fragment won't be paused, which will cause us issues
val action = ContactFragmentDirections.actionContactFragmentToEmptyFragment()
findNavController().navigate(action)
return true
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -44,15 +44,16 @@ abstract class GenericFragment : Fragment() {
}
protected fun getFragmentRealClassName(): String {
return this.javaClass.name
return "[${this.javaClass.name}]"
}
protected open fun goBack(): Boolean {
Log.d("$TAG ${getFragmentRealClassName()} Going back")
try {
Log.d("$TAG ${getFragmentRealClassName()} Calling onBackPressed on activity dispatcher")
requireActivity().onBackPressedDispatcher.onBackPressed()
} catch (ise: IllegalStateException) {
Log.w("$TAG ${getFragmentRealClassName()}.goBack() can't go back: $ise")
Log.w("$TAG ${getFragmentRealClassName()} Can't go back: $ise")
return false
}
return true

View file

@ -38,30 +38,20 @@ abstract class SlidingPaneChildFragment : GenericFragment() {
try {
if (!goBack()) {
Log.d(
"$TAG ${getFragmentRealClassName()}'s goBack() method returned false, trying other things"
"$TAG ${getFragmentRealClassName()}'s goBack() method returned false, disabling back pressed callback and trying again"
)
val navController = findNavController()
if (!navController.popBackStack()) {
Log.d("$TAG ${getFragmentRealClassName()} couldn't pop")
if (!navController.navigateUp()) {
Log.d(
"$TAG ${getFragmentRealClassName()} couldn't navigate up"
)
// Disable this callback & start a new back press event
isEnabled = false
try {
requireActivity().onBackPressedDispatcher.onBackPressed()
} catch (ise: IllegalStateException) {
Log.w(
"$TAG ${getFragmentRealClassName()}.goBack() can't go back: $ise"
)
}
}
isEnabled = false
try {
requireActivity().onBackPressedDispatcher.onBackPressed()
} catch (ise: IllegalStateException) {
Log.w(
"$TAG ${getFragmentRealClassName()} Can't go back: $ise"
)
}
}
} catch (ise: IllegalStateException) {
Log.e(
"$TAG ${getFragmentRealClassName()}.handleOnBackPressed() Can't go back: $ise"
"$TAG ${getFragmentRealClassName()} Can't go back: $ise"
)
}
}
@ -91,14 +81,16 @@ abstract class SlidingPaneChildFragment : GenericFragment() {
}
override fun goBack(): Boolean {
if (!super.goBack()) {
if (onBackPressedCallback.isEnabled) {
onBackPressedCallback.handleOnBackPressed()
return true
if (!findNavController().popBackStack()) {
Log.d("$TAG ${getFragmentRealClassName()} Couldn't pop back stack")
if (!findNavController().navigateUp()) {
Log.d("$TAG ${getFragmentRealClassName()} Couldn't navigate up")
onBackPressedCallback.isEnabled = false
return super.goBack()
}
return false
}
return true
return false
}
private fun backPressedCallBackEnabled(slideable: Boolean): Boolean {

View file

@ -63,8 +63,11 @@ class HistoryContactFragment : SlidingPaneChildFragment() {
override fun goBack(): Boolean {
sharedViewModel.closeSlidingPaneEvent.value = Event(true)
// If not done, when going back to CallsFragment this fragment will be created again
return findNavController().popBackStack()
// If not done this fragment won't be paused, which will cause us issues
val action = HistoryContactFragmentDirections.actionHistoryContactFragmentToEmptyFragment()
findNavController().navigate(action)
return true
}
override fun onCreate(savedInstanceState: Bundle?) {

View file

@ -69,8 +69,11 @@ class MeetingFragment : SlidingPaneChildFragment() {
override fun goBack(): Boolean {
sharedViewModel.closeSlidingPaneEvent.value = Event(true)
// If not done, when going back to MeetingsListFragment this fragment will be created again
return findNavController().popBackStack()
// If not done this fragment won't be paused, which will cause us issues
val action = MeetingFragmentDirections.actionMeetingFragmentToEmptyFragment()
findNavController().navigate(action)
return true
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {

View file

@ -34,6 +34,7 @@
android:adjustViewBounds="true"
android:padding="15dp"
android:src="@drawable/caret_left"
android:visibility="@{viewModel.showBackButton ? View.VISIBLE : View.GONE}"
app:tint="?attr/color_main1_500"
app:layout_constraintBottom_toBottomOf="@id/title"
app:layout_constraintStart_toStartOf="parent"

View file

@ -30,12 +30,17 @@
app:exitAnim="@anim/slide_out_left"
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right" />
<action
android:id="@+id/action_conversationFragment_to_emptyFragment"
app:destination="@id/emptyFragment"
app:popUpTo="@id/conversationFragment"
app:popUpToInclusive="true"/>
</fragment>
<action
android:id="@+id/action_global_conversationFragment"
app:destination="@id/conversationFragment"
app:launchSingleTop="true" />
app:launchSingleTop="true"/>
<fragment
android:id="@+id/conversationInfoFragment"

View file

@ -28,6 +28,11 @@
app:popEnterAnim="@anim/slide_in_left"
app:popExitAnim="@anim/slide_out_right"
app:launchSingleTop="true" />
<action
android:id="@+id/action_contactFragment_to_emptyFragment"
app:destination="@id/emptyFragment"
app:popUpTo="@id/contactFragment"
app:popUpToInclusive="true" />
</fragment>
<action

View file

@ -20,6 +20,11 @@
<argument
android:name="callId"
app:argType="string" />
<action
android:id="@+id/action_historyContactFragment_to_emptyFragment"
app:destination="@id/emptyFragment"
app:popUpTo="@id/historyContactFragment"
app:popUpToInclusive="true" />
</fragment>
<action

View file

@ -19,6 +19,11 @@
<argument
android:name="conferenceUri"
app:argType="string" />
<action
android:id="@+id/action_meetingFragment_to_emptyFragment"
app:destination="@id/emptyFragment"
app:popUpTo="@id/meetingFragment"
app:popUpToInclusive="true" />
</fragment>
<action