Added GenericFragment logic from current app

This commit is contained in:
Sylvain Berfini 2023-08-07 15:19:13 +02:00
parent 29298ef978
commit 11f4ff4594
6 changed files with 147 additions and 41 deletions

View file

@ -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
}

View file

@ -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(

View file

@ -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
}

View file

@ -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? {

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<ImageView>(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
}
}

View file

@ -21,7 +21,9 @@
app:argType="string" />
</fragment>
<action android:id="@+id/action_global_contactFragment"
app:destination="@id/contactFragment"/>
<action
android:id="@+id/action_global_contactFragment"
app:destination="@id/contactFragment"
app:launchSingleTop="true" />
</navigation>