diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt
index eaad0376f..2ad646194 100644
--- a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt
+++ b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactFragment.kt
@@ -24,22 +24,18 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.doOnPreDraw
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.navArgs
import androidx.navigation.navGraphViewModels
import androidx.transition.ChangeBounds
import org.linphone.R
import org.linphone.databinding.ContactFragmentBinding
import org.linphone.ui.contacts.viewmodel.ContactViewModel
-import org.linphone.ui.viewmodel.SharedMainViewModel
+import org.linphone.ui.fragment.GenericFragment
import org.linphone.utils.Event
-class ContactFragment : Fragment() {
+class ContactFragment : GenericFragment() {
private lateinit var binding: ContactFragmentBinding
- private lateinit var sharedViewModel: SharedMainViewModel
-
private val viewModel: ContactViewModel by navGraphViewModels(
R.id.contactFragment
)
@@ -57,11 +53,6 @@ class ContactFragment : Fragment() {
savedInstanceState: Bundle?
): View {
binding = ContactFragmentBinding.inflate(layoutInflater)
-
- sharedViewModel = requireActivity().run {
- ViewModelProvider(this)[SharedMainViewModel::class.java]
- }
-
return binding.root
}
diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt
index 024ec2303..cab1df8e6 100644
--- a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt
+++ b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsFragment.kt
@@ -24,34 +24,23 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.view.doOnPreDraw
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
import androidx.navigation.findNavController
import androidx.navigation.fragment.findNavController
import androidx.slidingpanelayout.widget.SlidingPaneLayout
-import androidx.transition.AutoTransition
import org.linphone.R
import org.linphone.databinding.ContactsFragmentBinding
-import org.linphone.ui.viewmodel.SharedMainViewModel
+import org.linphone.ui.fragment.GenericFragment
import org.linphone.utils.SlidingPaneBackPressedCallback
-class ContactsFragment : Fragment() {
+class ContactsFragment : GenericFragment() {
private lateinit var binding: ContactsFragmentBinding
- private lateinit var sharedViewModel: SharedMainViewModel
-
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = ContactsFragmentBinding.inflate(layoutInflater)
- sharedElementEnterTransition = AutoTransition()
-
- sharedViewModel = requireActivity().run {
- ViewModelProvider(this)[SharedMainViewModel::class.java]
- }
-
return binding.root
}
@@ -62,6 +51,7 @@ class ContactsFragment : Fragment() {
binding.root.doOnPreDraw {
val slidingPane = binding.slidingPaneLayout
+ slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED
sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable
@@ -69,8 +59,6 @@ class ContactsFragment : Fragment() {
viewLifecycleOwner,
SlidingPaneBackPressedCallback(slidingPane)
)
-
- slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED
}
sharedViewModel.closeSlidingPaneEvent.observe(
diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsListFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsListFragment.kt
index 533d1d4cc..06d61f2fe 100644
--- a/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsListFragment.kt
+++ b/app/src/main/java/org/linphone/ui/contacts/fragment/ContactsListFragment.kt
@@ -27,8 +27,6 @@ import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.core.view.doOnPreDraw
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.ViewModelProvider
import androidx.navigation.fragment.findNavController
import androidx.navigation.navGraphViewModels
import androidx.recyclerview.widget.LinearLayoutManager
@@ -37,17 +35,15 @@ import org.linphone.databinding.ContactsListFragmentBinding
import org.linphone.ui.MainActivity
import org.linphone.ui.contacts.adapter.ContactsListAdapter
import org.linphone.ui.contacts.viewmodel.ContactsListViewModel
-import org.linphone.ui.viewmodel.SharedMainViewModel
+import org.linphone.ui.fragment.GenericFragment
import org.linphone.utils.Event
import org.linphone.utils.hideKeyboard
import org.linphone.utils.setKeyboardInsetListener
import org.linphone.utils.showKeyboard
-class ContactsListFragment : Fragment() {
+class ContactsListFragment : GenericFragment() {
private lateinit var binding: ContactsListFragmentBinding
- private lateinit var sharedViewModel: SharedMainViewModel
-
private val listViewModel: ContactsListViewModel by navGraphViewModels(
R.id.contactsListFragment
)
@@ -69,11 +65,6 @@ class ContactsListFragment : Fragment() {
savedInstanceState: Bundle?
): View {
binding = ContactsListFragmentBinding.inflate(layoutInflater)
-
- sharedViewModel = requireActivity().run {
- ViewModelProvider(this)[SharedMainViewModel::class.java]
- }
-
return binding.root
}
diff --git a/app/src/main/java/org/linphone/ui/contacts/fragment/NewContactFragment.kt b/app/src/main/java/org/linphone/ui/contacts/fragment/NewContactFragment.kt
index 84a39ae4c..e7af5af12 100644
--- a/app/src/main/java/org/linphone/ui/contacts/fragment/NewContactFragment.kt
+++ b/app/src/main/java/org/linphone/ui/contacts/fragment/NewContactFragment.kt
@@ -24,11 +24,11 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
-import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import org.linphone.databinding.NewContactFragmentBinding
+import org.linphone.ui.fragment.GenericFragment
-class NewContactFragment : Fragment() {
+class NewContactFragment : GenericFragment() {
private lateinit var binding: NewContactFragmentBinding
override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? {
diff --git a/app/src/main/java/org/linphone/ui/fragment/GenericFragment.kt b/app/src/main/java/org/linphone/ui/fragment/GenericFragment.kt
new file mode 100644
index 000000000..fadf9ccf9
--- /dev/null
+++ b/app/src/main/java/org/linphone/ui/fragment/GenericFragment.kt
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010-2023 Belledonne Communications SARL.
+ *
+ * This file is part of linphone-android
+ * (see https://www.linphone.org).
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package org.linphone.ui.fragment
+
+import android.os.Bundle
+import android.view.View
+import android.widget.ImageView
+import androidx.activity.OnBackPressedCallback
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProvider
+import androidx.navigation.fragment.findNavController
+import org.linphone.R
+import org.linphone.core.tools.Log
+import org.linphone.ui.viewmodel.SharedMainViewModel
+
+abstract class GenericFragment : Fragment() {
+ protected lateinit var sharedViewModel: SharedMainViewModel
+
+ private val onBackPressedCallback = object : OnBackPressedCallback(false) {
+ override fun handleOnBackPressed() {
+ try {
+ val navController = findNavController()
+ Log.i("[Generic Fragment] ${getFragmentRealClassName()} handleOnBackPressed")
+ if (!navController.popBackStack()) {
+ Log.i("[Generic Fragment] ${getFragmentRealClassName()} couldn't pop")
+ if (!navController.navigateUp()) {
+ Log.i(
+ "[Generic Fragment] ${getFragmentRealClassName()} couldn't navigate up"
+ )
+ // Disable this callback & start a new back press event
+ isEnabled = false
+ goBack()
+ }
+ }
+ } catch (ise: IllegalStateException) {
+ Log.e(
+ "[Generic Fragment] ${getFragmentRealClassName()}.handleOnBackPressed() Can't go back: $ise"
+ )
+ }
+ }
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ sharedViewModel = requireActivity().run {
+ ViewModelProvider(this)[SharedMainViewModel::class.java]
+ }
+
+ sharedViewModel.isSlidingPaneSlideable.observe(viewLifecycleOwner) {
+ Log.i(
+ "[Generic Fragment] ${getFragmentRealClassName()} shared main VM sliding pane has changed"
+ )
+ onBackPressedCallback.isEnabled = backPressedCallBackEnabled()
+ }
+
+ setupBackPressCallback()
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+
+ onBackPressedCallback.remove()
+ }
+
+ private fun getFragmentRealClassName(): String {
+ return this.javaClass.name
+ }
+
+ protected fun goBack() {
+ try {
+ requireActivity().onBackPressedDispatcher.onBackPressed()
+ } catch (ise: IllegalStateException) {
+ Log.w("[Generic Fragment] ${getFragmentRealClassName()}.goBack() can't go back: $ise")
+ onBackPressedCallback.handleOnBackPressed()
+ }
+ }
+
+ private fun setupBackPressCallback() {
+ Log.i("[Generic Fragment] ${getFragmentRealClassName()} setupBackPressCallback")
+
+ val backButton = view?.findViewById(R.id.back)
+ if (backButton != null && backButton.visibility == View.VISIBLE) {
+ Log.i("[Generic Fragment] ${getFragmentRealClassName()} found back button")
+ // If popping navigation back stack entry would bring us to an "empty" fragment
+ // then don't do it if sliding pane layout isn't "flat"
+ onBackPressedCallback.isEnabled = backPressedCallBackEnabled()
+ backButton.setOnClickListener { goBack() }
+ } else {
+ onBackPressedCallback.isEnabled = false
+ }
+
+ requireActivity().onBackPressedDispatcher.addCallback(
+ viewLifecycleOwner,
+ onBackPressedCallback
+ )
+ }
+
+ private fun backPressedCallBackEnabled(): Boolean {
+ // This allow to navigate a SlidingPane child nav graph.
+ // This only concerns fragments for which the nav graph is inside a SlidingPane layout.
+ // In our case it's all graphs except the main one.
+ if (findNavController().graph.id == R.id.main_nav_graph) return false
+
+ val isSlidingPaneFlat = sharedViewModel.isSlidingPaneSlideable.value == false
+ Log.i(
+ "[Generic Fragment] ${getFragmentRealClassName()} isSlidingPaneFlat ? $isSlidingPaneFlat"
+ )
+ val isPreviousFragmentEmpty = findNavController().previousBackStackEntry?.destination?.id == R.id.emptyFragment
+ Log.i(
+ "[Generic Fragment] ${getFragmentRealClassName()} isPreviousFragmentEmpty ? $isPreviousFragmentEmpty"
+ )
+ val popBackStack = isSlidingPaneFlat || !isPreviousFragmentEmpty
+ Log.i("[Generic Fragment] ${getFragmentRealClassName()} popBackStack ? $popBackStack")
+ return popBackStack
+ }
+}
diff --git a/app/src/main/res/navigation/contact_right_nav_graph.xml b/app/src/main/res/navigation/contact_right_nav_graph.xml
index 1e1593fdb..a4297ad7c 100644
--- a/app/src/main/res/navigation/contact_right_nav_graph.xml
+++ b/app/src/main/res/navigation/contact_right_nav_graph.xml
@@ -21,7 +21,9 @@
app:argType="string" />
-
+
\ No newline at end of file