From 41a15cf6eebfcd22b10efcdf3bddd524243c3d3c Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 17 Jun 2021 14:28:24 +0200 Subject: [PATCH] Reworked app to use SlidingPane and simplify navigation --- app/build.gradle | 7 +- .../linphone/activities/GenericActivity.kt | 54 +++ .../linphone/activities/GenericFragment.kt | 24 ++ .../org/linphone/activities/Navigation.kt | 312 +++++------------- .../assistant/fragments/TopBarFragment.kt | 11 +- .../linphone/activities/main/MainActivity.kt | 18 +- .../activities/main/about/AboutFragment.kt | 3 +- .../fragments/ChatRoomCreationFragment.kt | 9 +- .../chat/fragments/DetailChatRoomFragment.kt | 21 +- .../main/chat/fragments/DevicesFragment.kt | 2 +- .../main/chat/fragments/EphemeralFragment.kt | 4 +- .../main/chat/fragments/GroupInfoFragment.kt | 3 +- .../main/chat/fragments/ImdnFragment.kt | 4 +- .../chat/fragments/MasterChatRoomsFragment.kt | 41 +++ .../fragments/ContactEditorFragment.kt | 2 +- .../fragments/DetailContactFragment.kt | 9 +- .../fragments/MasterContactsFragment.kt | 42 ++- .../dialer/fragments/ConfigViewerFragment.kt | 3 +- .../files/fragments/AudioViewerFragment.kt | 2 +- .../main/files/fragments/TopBarFragment.kt | 3 +- .../files/fragments/VideoViewerFragment.kt | 2 +- .../fragments/DetailCallLogFragment.kt | 14 +- .../fragments/MasterCallLogsFragment.kt | 40 ++- .../fragments/RecordingsFragment.kt | 5 +- .../fragments/AccountSettingsFragment.kt | 9 +- .../fragments/AdvancedSettingsFragment.kt | 16 +- .../fragments/AudioSettingsFragment.kt | 16 +- .../fragments/CallSettingsFragment.kt | 16 +- .../fragments/ChatSettingsFragment.kt | 16 +- .../fragments/ContactsSettingsFragment.kt | 16 +- .../fragments/NetworkSettingsFragment.kt | 16 +- .../settings/fragments/SettingsFragment.kt | 35 +- .../fragments/TunnelSettingsFragment.kt | 16 +- .../fragments/VideoSettingsFragment.kt | 16 +- .../main/viewmodels/SharedMainViewModel.kt | 4 + .../utils/RecyclerViewHeaderDecoration.kt | 11 +- .../drawable-xhdpi/chat_group_new_default.png | Bin 5984 -> 16861 bytes .../res/drawable-xhdpi/chat_new_default.png | Bin 4067 -> 14072 bytes .../layout-land/history_detail_fragment.xml | 210 ------------ .../history_detail_fragment.xml | 192 ----------- .../layout-sw533dp-land/settings_fragment.xml | 209 ------------ .../chat_room_master_fragment.xml | 175 ---------- .../contact_master_fragment.xml | 202 ------------ .../history_master_fragment.xml | 165 --------- .../res/layout-sw533dp/settings_fragment.xml | 209 ------------ .../res/layout/chat_room_detail_fragment.xml | 6 +- .../res/layout/chat_room_master_fragment.xml | 33 +- .../res/layout/contact_detail_fragment.xml | 4 + .../res/layout/contact_master_fragment.xml | 272 ++++++++------- .../res/layout/history_detail_fragment.xml | 4 + .../res/layout/history_master_fragment.xml | 203 +++++++----- .../res/layout/settings_account_fragment.xml | 6 +- .../res/layout/settings_advanced_fragment.xml | 6 +- .../res/layout/settings_audio_fragment.xml | 6 +- .../res/layout/settings_call_fragment.xml | 6 +- .../res/layout/settings_chat_fragment.xml | 6 +- .../res/layout/settings_contacts_fragment.xml | 6 +- app/src/main/res/layout/settings_fragment.xml | 305 +++++++++-------- .../res/layout/settings_network_fragment.xml | 6 +- .../res/layout/settings_tunnel_fragment.xml | 6 +- .../res/layout/settings_video_fragment.xml | 6 +- .../res/navigation-sw533dp/chat_nav_graph.xml | 87 ----- .../navigation-sw533dp/contacts_nav_graph.xml | 47 --- .../navigation-sw533dp/history_nav_graph.xml | 24 -- .../main/res/navigation/chat_nav_graph.xml | 22 +- .../res/navigation/contacts_nav_graph.xml | 21 +- .../main/res/navigation/history_nav_graph.xml | 22 +- .../main/res/navigation/main_nav_graph.xml | 221 ++----------- 68 files changed, 1096 insertions(+), 2413 deletions(-) delete mode 100644 app/src/main/res/layout-land/history_detail_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp-land/history_detail_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp-land/settings_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp/chat_room_master_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp/contact_master_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp/history_master_fragment.xml delete mode 100644 app/src/main/res/layout-sw533dp/settings_fragment.xml delete mode 100644 app/src/main/res/navigation-sw533dp/chat_nav_graph.xml delete mode 100644 app/src/main/res/navigation-sw533dp/contacts_nav_graph.xml delete mode 100644 app/src/main/res/navigation-sw533dp/history_nav_graph.xml diff --git a/app/build.gradle b/app/build.gradle index 9810fcd74..5ec831479 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -235,13 +235,16 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.3.0' implementation 'androidx.media:media:1.2.0' - implementation 'androidx.fragment:fragment-ktx:1.3.4' - implementation 'androidx.core:core-ktx:1.6.0-beta02' + implementation 'androidx.fragment:fragment-ktx:1.4.0-alpha03' + implementation 'androidx.core:core-ktx:1.6.0-rc01' def nav_version = "2.3.5" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" implementation "androidx.navigation:navigation-ui-ktx:$nav_version" + implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0-alpha02" + implementation "androidx.window:window:1.0.0-alpha08" + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' diff --git a/app/src/main/java/org/linphone/activities/GenericActivity.kt b/app/src/main/java/org/linphone/activities/GenericActivity.kt index 5441ca9e9..2ea9f174e 100644 --- a/app/src/main/java/org/linphone/activities/GenericActivity.kt +++ b/app/src/main/java/org/linphone/activities/GenericActivity.kt @@ -23,13 +23,20 @@ import android.annotation.SuppressLint import android.content.pm.ActivityInfo import android.content.res.Configuration import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.util.DisplayMetrics import android.view.Display import android.view.Surface import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate +import androidx.core.util.Consumer import androidx.navigation.ActivityNavigator +import androidx.window.FoldingFeature +import androidx.window.WindowLayoutInfo +import androidx.window.WindowManager import java.util.* +import java.util.concurrent.Executor import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.LinphoneApplication.Companion.ensureCoreExists @@ -42,10 +49,57 @@ abstract class GenericActivity : AppCompatActivity() { val isDestructionPending: Boolean get() = _isDestructionPending + private lateinit var windowManagerX: WindowManager + + inner class LayoutStateChangeCallback : Consumer { + override fun accept(newLayoutInfo: WindowLayoutInfo) { + Log.i("[Layout State Change] $newLayoutInfo") + + if (newLayoutInfo.displayFeatures.isEmpty()) { + onLayoutChanges(null) + } else { + for (feature in newLayoutInfo.displayFeatures) { + val foldingFeature = feature as? FoldingFeature + if (foldingFeature != null) { + onLayoutChanges(foldingFeature) + } + } + } + } + } + private val layoutStateChangeCallback = LayoutStateChangeCallback() + + private fun runOnUiThreadExecutor(): Executor { + val handler = Handler(Looper.getMainLooper()) + return Executor() { + handler.post(it) + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + + windowManagerX.registerLayoutChangeCallback( + runOnUiThreadExecutor(), + layoutStateChangeCallback + ) + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + + windowManagerX.unregisterLayoutChangeCallback(layoutStateChangeCallback) + } + + open fun onLayoutChanges(foldingFeature: FoldingFeature?) { + } + @SuppressLint("SourceLockedOrientationActivity") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + windowManagerX = WindowManager(this) + ensureCoreExists(applicationContext) requestedOrientation = if (corePreferences.forcePortrait) { diff --git a/app/src/main/java/org/linphone/activities/GenericFragment.kt b/app/src/main/java/org/linphone/activities/GenericFragment.kt index b88ffde0c..0f68b1cd1 100644 --- a/app/src/main/java/org/linphone/activities/GenericFragment.kt +++ b/app/src/main/java/org/linphone/activities/GenericFragment.kt @@ -23,14 +23,23 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.OnBackPressedCallback +import androidx.activity.addCallback import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.fragment.app.Fragment +import androidx.navigation.fragment.findNavController abstract class GenericFragment : Fragment() { private var _binding: T? = null protected val binding get() = _binding!! + private val onBackPressedCallback = object : OnBackPressedCallback(true) { + override fun handleOnBackPressed() { + goBack() + } + } + abstract fun getLayoutId(): Int override fun onCreateView( @@ -42,8 +51,23 @@ abstract class GenericFragment : Fragment() { return _binding!!.root } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + requireActivity().onBackPressedDispatcher.addCallback(this, onBackPressedCallback) + } + override fun onDestroyView() { super.onDestroyView() _binding = null } + + protected open fun goBack() { + if (!findNavController().popBackStack()) { + if (!findNavController().navigateUp()) { + onBackPressedCallback.isEnabled = false + requireActivity().onBackPressed() + } + } + } } diff --git a/app/src/main/java/org/linphone/activities/Navigation.kt b/app/src/main/java/org/linphone/activities/Navigation.kt index ed36a6cf1..75a8d7bb6 100644 --- a/app/src/main/java/org/linphone/activities/Navigation.kt +++ b/app/src/main/java/org/linphone/activities/Navigation.kt @@ -50,11 +50,7 @@ import org.linphone.contact.NativeContact import org.linphone.core.Address internal fun Fragment.findMasterNavController(): NavController { - return if (!resources.getBoolean(R.bool.isTablet)) { - findNavController() - } else { - parentFragment?.parentFragment?.findNavController() ?: findNavController() - } + return parentFragment?.parentFragment?.findNavController() ?: findNavController() } fun getRightToLeftAnimationNavOptions( @@ -149,6 +145,16 @@ fun getLeftTopToRightBottomNoPopAnimationNavOptions( .build() } +fun popupTo( + popUpTo: Int = -1, + popUpInclusive: Boolean = false, + singleTop: Boolean = true +): NavOptions { + val builder = NavOptions.Builder() + builder.setPopUpTo(popUpTo, popUpInclusive).setLaunchSingleTop(singleTop) + return builder.build() +} + /* Main activity related */ internal fun MainActivity.navigateToDialer(args: Bundle?) { @@ -263,21 +269,20 @@ internal fun DialerFragment.navigateToConfigFileViewer() { /* Chat related */ internal fun MasterChatRoomsFragment.navigateToChatRoom(args: Bundle) { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.masterChatRoomsFragment) { - findNavController().navigate( - R.id.action_masterChatRoomsFragment_to_detailChatRoomFragment, - args, - getRightToLeftAnimationNavOptions() - ) - } - } else { - val navHostFragment = - childFragmentManager.findFragmentById(R.id.chat_nav_container) as NavHostFragment + val navHostFragment = + childFragmentManager.findFragmentById(R.id.chat_nav_container) as NavHostFragment + val previousBackStackEntry = navHostFragment.navController.currentBackStackEntry + if (previousBackStackEntry == null || previousBackStackEntry.destination.id == R.id.emptyChatFragment) { navHostFragment.navController.navigate( R.id.action_global_detailChatRoomFragment, args, - getRightToLeftAnimationNavOptions(R.id.emptyChatFragment, true) + popupTo(R.id.emptyChatFragment, true) + ) + } else { + navHostFragment.navController.navigate( + R.id.action_global_detailChatRoomFragment, + args, + popupTo(R.id.chatRoomCreationFragment, true) ) } } @@ -286,21 +291,20 @@ internal fun MasterChatRoomsFragment.navigateToChatRoomCreation( createGroupChatRoom: Boolean = false ) { val bundle = bundleOf("createGroup" to createGroupChatRoom) - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.masterChatRoomsFragment) { - findNavController().navigate( - R.id.action_masterChatRoomsFragment_to_chatRoomCreationFragment, - bundle, - getRightToLeftAnimationNavOptions() - ) - } - } else { - val navHostFragment = - childFragmentManager.findFragmentById(R.id.chat_nav_container) as NavHostFragment + val navHostFragment = + childFragmentManager.findFragmentById(R.id.chat_nav_container) as NavHostFragment + val previousBackStackEntry = navHostFragment.navController.currentBackStackEntry + if (previousBackStackEntry == null || previousBackStackEntry.destination.id == R.id.emptyChatFragment) { navHostFragment.navController.navigate( R.id.action_global_chatRoomCreationFragment, bundle, - getRightToLeftAnimationNavOptions(R.id.emptyChatFragment, true) + popupTo(R.id.emptyChatFragment, true) + ) + } else { + navHostFragment.navController.navigate( + R.id.action_global_chatRoomCreationFragment, + bundle, + popupTo(R.id.detailChatRoomFragment, true) ) } } @@ -310,14 +314,6 @@ internal fun DetailChatRoomFragment.navigateToContacts(sipUriToAdd: String) { findMasterNavController().navigate(Uri.parse(deepLink), getLeftToRightAnimationNavOptions()) } -internal fun DetailChatRoomFragment.navigateToChatRooms() { - findMasterNavController().navigate( - R.id.action_global_masterChatRoomsFragment, - null, - getLeftToRightAnimationNavOptions(R.id.masterChatRoomsFragment) - ) -} - internal fun DetailChatRoomFragment.navigateToImdn(args: Bundle?) { if (findNavController().currentDestination?.id == R.id.detailChatRoomFragment) { findNavController().navigate( @@ -415,19 +411,11 @@ internal fun ChatRoomCreationFragment.navigateToGroupInfo() { internal fun ChatRoomCreationFragment.navigateToChatRoom(args: Bundle) { if (findNavController().currentDestination?.id == R.id.chatRoomCreationFragment) { - if (!resources.getBoolean(R.bool.isTablet)) { - findNavController().navigate( - R.id.action_chatRoomCreationFragment_to_detailChatRoomFragment, - args, - getRightToLeftAnimationNavOptions() - ) - } else { - findNavController().navigate( - R.id.action_chatRoomCreationFragment_to_detailChatRoomFragment, - args, - getRightToLeftAnimationNavOptions(R.id.emptyFragment, true) - ) - } + findNavController().navigate( + R.id.action_chatRoomCreationFragment_to_detailChatRoomFragment, + args, + getRightToLeftAnimationNavOptions(R.id.emptyFragment, true) + ) } } @@ -442,59 +430,37 @@ internal fun GroupInfoFragment.navigateToChatRoomCreation(args: Bundle?) { internal fun GroupInfoFragment.navigateToChatRoom(args: Bundle?) { if (findNavController().currentDestination?.id == R.id.groupInfoFragment) { - if (!resources.getBoolean(R.bool.isTablet)) { - findNavController().navigate( - R.id.action_groupInfoFragment_to_detailChatRoomFragment, - args, - getRightToLeftAnimationNavOptions() - ) - } else { - findNavController().navigate( - R.id.action_groupInfoFragment_to_detailChatRoomFragment, - args, - getRightToLeftAnimationNavOptions(R.id.emptyFragment, true) - ) - } + findNavController().navigate( + R.id.action_groupInfoFragment_to_detailChatRoomFragment, + args, + getRightToLeftAnimationNavOptions(R.id.emptyFragment, true) + ) } } /* Contacts related */ internal fun MasterContactsFragment.navigateToContact() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.masterContactsFragment) { - findNavController().navigate(R.id.action_masterContactsFragment_to_detailContactFragment, - null, - getRightToLeftAnimationNavOptions()) - } - } else { + if (findNavController().currentDestination?.id == R.id.masterContactsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.contacts_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_detailContactFragment, null, - getRightToLeftAnimationNavOptions(R.id.emptyContactFragment, true) + popupTo(R.id.emptyContactFragment, true) ) } } internal fun MasterContactsFragment.navigateToContactEditor(sipUriToAdd: String? = null) { - val bundle = if (sipUriToAdd != null) bundleOf("SipUri" to sipUriToAdd) else Bundle() - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.masterContactsFragment) { - findNavController().navigate( - R.id.action_masterContactsFragment_to_contactEditorFragment, - bundle, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.masterContactsFragment) { + val bundle = if (sipUriToAdd != null) bundleOf("SipUri" to sipUriToAdd) else Bundle() val navHostFragment = childFragmentManager.findFragmentById(R.id.contacts_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_contactEditorFragment, bundle, - getRightToLeftAnimationNavOptions() + popupTo() ) } } @@ -505,24 +471,16 @@ internal fun ContactEditorFragment.navigateToContact(contact: NativeContact) { findNavController().navigate( R.id.action_contactEditorFragment_to_detailContactFragment, bundle, - getRightToLeftAnimationNavOptions(R.id.masterContactsFragment, false) + popupTo(R.id.masterContactsFragment, false) ) } internal fun DetailContactFragment.navigateToChatRoom(args: Bundle?) { - if (!resources.getBoolean(R.bool.isTablet)) { - findNavController().navigate( - R.id.action_detailContactFragment_to_detailChatRoomFragment, - args, - getRightBottomToLeftTopAnimationNavOptions() - ) - } else { - findMasterNavController().navigate( - R.id.action_global_masterChatRoomsFragment, - args, - getRightBottomToLeftTopAnimationNavOptions() - ) - } + findMasterNavController().navigate( + R.id.action_global_masterChatRoomsFragment, + args, + getRightBottomToLeftTopAnimationNavOptions() + ) } internal fun DetailContactFragment.navigateToDialer(args: Bundle?) { @@ -538,7 +496,7 @@ internal fun DetailContactFragment.navigateToContactEditor() { findNavController().navigate( R.id.action_detailContactFragment_to_contactEditorFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } @@ -546,21 +504,13 @@ internal fun DetailContactFragment.navigateToContactEditor() { /* History related */ internal fun MasterCallLogsFragment.navigateToCallHistory() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.masterCallLogsFragment) { - findNavController().navigate( - R.id.action_masterCallLogsFragment_to_detailCallLogFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.masterCallLogsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.history_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_detailCallLogFragment, null, - getRightToLeftAnimationNavOptions(R.id.emptyFragment, true) + popupTo(R.id.emptyFragment, true) ) } } @@ -579,18 +529,8 @@ internal fun DetailCallLogFragment.navigateToContacts(sipUriToAdd: String) { } internal fun DetailCallLogFragment.navigateToContact(contact: NativeContact) { - if (!resources.getBoolean(R.bool.isTablet)) { - val args = Bundle() - args.putString("id", contact.nativeId) - findMasterNavController().navigate( - R.id.action_detailCallLogFragment_to_detailContactFragment, - args, - getRightBottomToLeftTopAnimationNavOptions() - ) - } else { - val deepLink = "linphone-android://contact/view/${contact.nativeId}" - findMasterNavController().navigate(Uri.parse(deepLink), getRightBottomToLeftTopAnimationNavOptions()) - } + val deepLink = "linphone-android://contact/view/${contact.nativeId}" + findMasterNavController().navigate(Uri.parse(deepLink), getRightBottomToLeftTopAnimationNavOptions()) } internal fun DetailCallLogFragment.navigateToFriend(friendAddress: Address) { @@ -599,19 +539,11 @@ internal fun DetailCallLogFragment.navigateToFriend(friendAddress: Address) { } internal fun DetailCallLogFragment.navigateToChatRoom(args: Bundle?) { - if (!resources.getBoolean(R.bool.isTablet)) { - findNavController().navigate( - R.id.action_detailCallLogFragment_to_detailChatRoomFragment, - args, - getRightBottomToLeftTopAnimationNavOptions() - ) - } else { - findMasterNavController().navigate( - R.id.action_global_masterChatRoomsFragment, - args, - getRightBottomToLeftTopAnimationNavOptions() - ) - } + findMasterNavController().navigate( + R.id.action_global_masterChatRoomsFragment, + args, + getRightBottomToLeftTopAnimationNavOptions() + ) } internal fun DetailCallLogFragment.navigateToDialer(args: Bundle?) { @@ -625,182 +557,110 @@ internal fun DetailCallLogFragment.navigateToDialer(args: Bundle?) { /* Settings related */ internal fun SettingsFragment.navigateToAccountSettings(identity: String) { - val bundle = bundleOf("Identity" to identity) - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_accountSettingsFragment, - bundle, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { + val bundle = bundleOf("Identity" to identity) val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_accountSettingsFragment, bundle, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToTunnelSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_tunnelSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_tunnelSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToAudioSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_audioSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_audioSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToVideoSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_videoSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_videoSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToCallSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_callSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_callSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToChatSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_chatSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_chatSettingsFragment, null, - getRightToLeftAnimationNavOptions() - ) + popupTo() + ) } } internal fun SettingsFragment.navigateToNetworkSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_networkSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_networkSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToContactsSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_contactsSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_contactsSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } internal fun SettingsFragment.navigateToAdvancedSettings() { - if (!resources.getBoolean(R.bool.isTablet)) { - if (findNavController().currentDestination?.id == R.id.settingsFragment) { - findNavController().navigate( - R.id.action_settingsFragment_to_advancedSettingsFragment, - null, - getRightToLeftAnimationNavOptions() - ) - } - } else { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { val navHostFragment = childFragmentManager.findFragmentById(R.id.settings_nav_container) as NavHostFragment navHostFragment.navController.navigate( R.id.action_global_advancedSettingsFragment, null, - getRightToLeftAnimationNavOptions() + popupTo() ) } } @@ -810,7 +670,7 @@ internal fun AccountSettingsFragment.navigateToPhoneLinking(args: Bundle?) { findNavController().navigate( R.id.action_accountSettingsFragment_to_phoneAccountLinkingFragment, args, - getRightToLeftAnimationNavOptions() + popupTo() ) } } @@ -820,7 +680,7 @@ internal fun PhoneAccountLinkingFragment.navigateToPhoneAccountValidation(args: findNavController().navigate( R.id.action_phoneAccountLinkingFragment_to_phoneAccountValidationFragment, args, - getRightToLeftAnimationNavOptions() + popupTo() ) } } diff --git a/app/src/main/java/org/linphone/activities/assistant/fragments/TopBarFragment.kt b/app/src/main/java/org/linphone/activities/assistant/fragments/TopBarFragment.kt index 8ad5dde06..93eb41b8e 100644 --- a/app/src/main/java/org/linphone/activities/assistant/fragments/TopBarFragment.kt +++ b/app/src/main/java/org/linphone/activities/assistant/fragments/TopBarFragment.kt @@ -21,7 +21,6 @@ package org.linphone.activities.assistant.fragments import android.os.Bundle import android.view.View -import androidx.activity.addCallback import androidx.navigation.fragment.findNavController import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R @@ -31,14 +30,6 @@ import org.linphone.databinding.AssistantTopBarFragmentBinding class TopBarFragment : GenericFragment() { override fun getLayoutId(): Int = R.layout.assistant_top_bar_fragment - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - requireActivity().onBackPressedDispatcher.addCallback(this) { - goBack() - } - } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -49,7 +40,7 @@ class TopBarFragment : GenericFragment() { } } - private fun goBack() { + override fun goBack() { if (!findNavController().popBackStack()) { requireActivity().finish() if (corePreferences.enableAnimations) { diff --git a/app/src/main/java/org/linphone/activities/main/MainActivity.kt b/app/src/main/java/org/linphone/activities/main/MainActivity.kt index 5fc48438b..c9378d6f4 100644 --- a/app/src/main/java/org/linphone/activities/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/activities/main/MainActivity.kt @@ -35,6 +35,7 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.findNavController +import androidx.window.FoldingFeature import com.google.android.material.snackbar.Snackbar import java.io.UnsupportedEncodingException import java.net.URLDecoder @@ -54,6 +55,7 @@ import org.linphone.contact.ContactsUpdatedListenerStub import org.linphone.core.tools.Log import org.linphone.databinding.MainActivityBinding import org.linphone.utils.AppUtils +import org.linphone.utils.Event import org.linphone.utils.FileUtils class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestinationChangedListener { @@ -81,6 +83,10 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin private var initPosY = 0f private var overlay: View? = null + override fun onLayoutChanges(foldingFeature: FoldingFeature?) { + sharedViewModel.layoutChangedEvent.value = Event(true) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -170,11 +176,19 @@ class MainActivity : GenericActivity(), SnackBarActivity, NavController.OnDestin when (destination.id) { R.id.masterCallLogsFragment, R.id.masterContactsFragment, R.id.dialerFragment, R.id.masterChatRoomsFragment -> - tabsFragment.visibility = View.VISIBLE - else -> tabsFragment.visibility = View.GONE + showTabsFragment() + else -> hideTabsFragment() } } + fun showTabsFragment() { + tabsFragment.visibility = View.VISIBLE + } + + fun hideTabsFragment() { + tabsFragment.visibility = View.GONE + } + fun hideStatusFragment() { statusFragment.visibility = View.GONE } diff --git a/app/src/main/java/org/linphone/activities/main/about/AboutFragment.kt b/app/src/main/java/org/linphone/activities/main/about/AboutFragment.kt index 40778a32c..6429185f6 100644 --- a/app/src/main/java/org/linphone/activities/main/about/AboutFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/about/AboutFragment.kt @@ -24,7 +24,6 @@ import android.net.Uri import android.os.Bundle import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.main.fragments.SecureFragment import org.linphone.databinding.AboutFragmentBinding @@ -42,7 +41,7 @@ class AboutFragment : SecureFragment() { viewModel = ViewModelProvider(this).get(AboutViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } + binding.setBackClickListener { goBack() } binding.setPrivacyPolicyClickListener { val browserIntent = Intent( diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/ChatRoomCreationFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/ChatRoomCreationFragment.kt index 46a526e03..6a90019e8 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/ChatRoomCreationFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/ChatRoomCreationFragment.kt @@ -37,6 +37,7 @@ import org.linphone.activities.navigateToGroupInfo import org.linphone.core.tools.Log import org.linphone.databinding.ChatRoomCreationFragmentBinding import org.linphone.utils.AppUtils +import org.linphone.utils.Event import org.linphone.utils.PermissionHelper class ChatRoomCreationFragment : SecureFragment() { @@ -76,7 +77,7 @@ class ChatRoomCreationFragment : SecureFragment binding.contactsList.addItemDecoration(AppUtils.getDividerDecoration(requireContext(), layoutManager)) binding.setBackClickListener { - findNavController().popBackStack() + goBack() } binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE @@ -146,6 +147,12 @@ class ChatRoomCreationFragment : SecureFragment } } + override fun goBack() { + if (!findNavController().popBackStack()) { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } + } + override fun onRequestPermissionsResult( requestCode: Int, permissions: Array, diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt index 14d433001..1f64e139b 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/DetailChatRoomFragment.kt @@ -30,7 +30,6 @@ import android.view.MenuInflater import android.view.MenuItem import android.view.MotionEvent import android.view.View -import androidx.activity.addCallback import androidx.appcompat.view.menu.MenuBuilder import androidx.appcompat.view.menu.MenuPopupHelper import androidx.core.content.FileProvider @@ -55,7 +54,6 @@ import org.linphone.activities.main.chat.viewmodels.* import org.linphone.activities.main.fragments.MasterFragment import org.linphone.activities.main.viewmodels.DialogViewModel import org.linphone.activities.main.viewmodels.SharedMainViewModel -import org.linphone.activities.navigateToChatRooms import org.linphone.activities.navigateToContacts import org.linphone.activities.navigateToImageFileViewer import org.linphone.activities.navigateToImdn @@ -94,14 +92,6 @@ class DetailChatRoomFragment : MasterFragment() { binding.viewModel = listViewModel binding.setBackClickListener { - findNavController().popBackStack() + goBack() } } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/EphemeralFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/EphemeralFragment.kt index 1b313a844..e4d41059b 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/EphemeralFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/EphemeralFragment.kt @@ -64,12 +64,12 @@ class EphemeralFragment : SecureFragment() { binding.viewModel = viewModel binding.setBackClickListener { - findNavController().popBackStack() + goBack() } binding.setValidClickListener { viewModel.updateChatRoomEphemeralDuration() - findNavController().popBackStack() + goBack() } } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/GroupInfoFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/GroupInfoFragment.kt index dc9a50180..603d3e375 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/GroupInfoFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/GroupInfoFragment.kt @@ -23,7 +23,6 @@ import android.app.Dialog import android.os.Bundle import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.R import org.linphone.activities.main.MainActivity @@ -107,7 +106,7 @@ class GroupInfoFragment : SecureFragment() { addParticipantsFromSharedViewModel() binding.setBackClickListener { - findNavController().popBackStack() + goBack() } viewModel.createdChatRoomEvent.observe(viewLifecycleOwner, { diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/ImdnFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/ImdnFragment.kt index 5ac773e4a..eedb6a044 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/ImdnFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/ImdnFragment.kt @@ -94,7 +94,7 @@ class ImdnFragment : SecureFragment() { binding.participantsList.addItemDecoration(AppUtils.getDividerDecoration(requireContext(), layoutManager)) // Displays state header - val headerItemDecoration = RecyclerViewHeaderDecoration(adapter) + val headerItemDecoration = RecyclerViewHeaderDecoration(requireContext(), adapter) binding.participantsList.addItemDecoration(headerItemDecoration) viewModel.participants.observe(viewLifecycleOwner, { @@ -102,7 +102,7 @@ class ImdnFragment : SecureFragment() { }) binding.setBackClickListener { - findNavController().popBackStack() + goBack() } } } diff --git a/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt b/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt index 7a00b177b..088a803ce 100644 --- a/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/chat/fragments/MasterChatRoomsFragment.kt @@ -23,10 +23,12 @@ import android.app.Dialog import android.os.Bundle import android.view.View import androidx.core.content.ContextCompat +import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.slidingpanelayout.widget.SlidingPaneLayout import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.activities.GenericActivity @@ -80,10 +82,45 @@ class MasterChatRoomsFragment : MasterFragment(), S binding.viewModel = viewModel binding.setBackClickListener { - findNavController().popBackStack() + goBack() } binding.setAvatarClickListener { diff --git a/app/src/main/java/org/linphone/activities/main/contact/fragments/DetailContactFragment.kt b/app/src/main/java/org/linphone/activities/main/contact/fragments/DetailContactFragment.kt index 3bc96f5e6..343b75018 100644 --- a/app/src/main/java/org/linphone/activities/main/contact/fragments/DetailContactFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/contact/fragments/DetailContactFragment.kt @@ -40,6 +40,7 @@ import org.linphone.activities.navigateToDialer import org.linphone.core.tools.Log import org.linphone.databinding.ContactDetailFragmentBinding import org.linphone.utils.DialogUtils +import org.linphone.utils.Event class DetailContactFragment : GenericFragment() { private lateinit var viewModel: ContactViewModel @@ -55,6 +56,7 @@ class DetailContactFragment : GenericFragment() { sharedViewModel = requireActivity().run { ViewModelProvider(this).get(SharedMainViewModel::class.java) } + binding.sharedMainViewModel = sharedViewModel val id = arguments?.getString("id") arguments?.clear() @@ -108,9 +110,8 @@ class DetailContactFragment : GenericFragment() { }) binding.setBackClickListener { - findNavController().popBackStack() + goBack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE binding.setEditClickListener { navigateToContactEditor() @@ -127,6 +128,10 @@ class DetailContactFragment : GenericFragment() { }) } + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } + private fun confirmContactRemoval() { val dialogViewModel = DialogViewModel(getString(R.string.contact_delete_one_dialog)) val dialog: Dialog = DialogUtils.getDialog(requireContext(), dialogViewModel) diff --git a/app/src/main/java/org/linphone/activities/main/contact/fragments/MasterContactsFragment.kt b/app/src/main/java/org/linphone/activities/main/contact/fragments/MasterContactsFragment.kt index 56ea20bd9..62d8ea571 100644 --- a/app/src/main/java/org/linphone/activities/main/contact/fragments/MasterContactsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/contact/fragments/MasterContactsFragment.kt @@ -24,10 +24,12 @@ import android.content.pm.PackageManager import android.os.Bundle import android.view.View import androidx.core.content.ContextCompat +import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.slidingpanelayout.widget.SlidingPaneLayout import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.activities.main.MainActivity @@ -68,10 +70,45 @@ class MasterContactsFragment : MasterFragment() { isSecure = arguments?.getBoolean("Secure") ?: false binding.setBackClickListener { - findNavController().popBackStack() + goBack() } binding.setExportClickListener { diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/AudioViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/AudioViewerFragment.kt index 9c2d6d140..9ddf17bce 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/AudioViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/AudioViewerFragment.kt @@ -69,7 +69,7 @@ class AudioViewerFragment : GenericViewerFragment() { binding.lifecycleOwner = this binding.setBackClickListener { - findNavController().popBackStack() + goBack() } binding.setExportClickListener { diff --git a/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt b/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt index 9673fe4db..861ee7bfd 100644 --- a/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/files/fragments/VideoViewerFragment.kt @@ -61,7 +61,7 @@ class VideoViewerFragment : GenericViewerFragment() { private lateinit var viewModel: CallLogViewModel @@ -51,6 +52,7 @@ class DetailCallLogFragment : GenericFragment() { sharedViewModel = requireActivity().run { ViewModelProvider(this).get(SharedMainViewModel::class.java) } + binding.sharedMainViewModel = sharedViewModel val callLogGroup = sharedViewModel.selectedCallLogGroup.value if (callLogGroup == null) { @@ -69,9 +71,8 @@ class DetailCallLogFragment : GenericFragment() { viewModel.relatedCallLogs.value = callLogGroup.callLogs binding.setBackClickListener { - findNavController().popBackStack() + goBack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE binding.setNewContactClickListener { val copy = viewModel.callLog.remoteAddress.clone() @@ -101,7 +102,10 @@ class DetailCallLogFragment : GenericFragment() { val args = Bundle() args.putString("URI", address.asStringUriOnly()) args.putBoolean("Transfer", sharedViewModel.pendingCallTransfer) - args.putBoolean("SkipAutoCallStart", true) // If auto start call setting is enabled, ignore it + args.putBoolean( + "SkipAutoCallStart", + true + ) // If auto start call setting is enabled, ignore it navigateToDialer(args) } else { val localAddress = callLog.localAddress @@ -125,4 +129,8 @@ class DetailCallLogFragment : GenericFragment() { } }) } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/history/fragments/MasterCallLogsFragment.kt b/app/src/main/java/org/linphone/activities/main/history/fragments/MasterCallLogsFragment.kt index 5496dca1b..546006c71 100644 --- a/app/src/main/java/org/linphone/activities/main/history/fragments/MasterCallLogsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/history/fragments/MasterCallLogsFragment.kt @@ -23,10 +23,12 @@ import android.app.Dialog import android.os.Bundle import android.view.View import androidx.core.content.ContextCompat +import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView +import androidx.slidingpanelayout.widget.SlidingPaneLayout import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.activities.main.fragments.MasterFragment @@ -71,10 +73,45 @@ class MasterCallLogsFragment : MasterFragment @@ -157,6 +194,7 @@ class MasterCallLogsFragment : MasterFragment sharedViewModel.selectedCallLogGroup.value = callLog + binding.slidingPane.openPane() navigateToCallHistory() } }) diff --git a/app/src/main/java/org/linphone/activities/main/recordings/fragments/RecordingsFragment.kt b/app/src/main/java/org/linphone/activities/main/recordings/fragments/RecordingsFragment.kt index 2e31f2791..eb972cac8 100644 --- a/app/src/main/java/org/linphone/activities/main/recordings/fragments/RecordingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/recordings/fragments/RecordingsFragment.kt @@ -23,7 +23,6 @@ import android.os.Bundle import android.view.MotionEvent import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.R import org.linphone.activities.main.fragments.MasterFragment @@ -66,14 +65,14 @@ class RecordingsFragment : MasterFragment adapter.submitList(recordings) }) - binding.setBackClickListener { findNavController().popBackStack() } + binding.setBackClickListener { goBack() } binding.setEditClickListener { listSelectionViewModel.isEditionEnabled.value = true } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/AccountSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/AccountSettingsFragment.kt index 36e002fa0..19396a88b 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/AccountSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/AccountSettingsFragment.kt @@ -31,6 +31,7 @@ import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.activities.navigateToPhoneLinking import org.linphone.core.tools.Log import org.linphone.databinding.SettingsAccountFragmentBinding +import org.linphone.utils.Event class AccountSettingsFragment : GenericFragment() { private lateinit var sharedViewModel: SharedMainViewModel @@ -46,6 +47,7 @@ class AccountSettingsFragment : GenericFragment( sharedViewModel = requireActivity().run { ViewModelProvider(this).get(SharedMainViewModel::class.java) } + binding.sharedMainViewModel = sharedViewModel val identity = arguments?.getString("Identity") if (identity == null) { @@ -58,8 +60,7 @@ class AccountSettingsFragment : GenericFragment( viewModel = ViewModelProvider(this, AccountSettingsViewModelFactory(identity)).get(AccountSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } viewModel.linkPhoneNumberEvent.observe(viewLifecycleOwner, { it.consume { @@ -83,4 +84,8 @@ class AccountSettingsFragment : GenericFragment( } }) } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/AdvancedSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/AdvancedSettingsFragment.kt index 9f2d79965..a85c15f60 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/AdvancedSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/AdvancedSettingsFragment.kt @@ -27,18 +27,20 @@ import android.view.View import androidx.appcompat.app.AppCompatDelegate import androidx.core.content.ContextCompat import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.MainActivity import org.linphone.activities.main.settings.viewmodels.AdvancedSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.core.tools.Log import org.linphone.core.tools.compatibility.DeviceUtils import org.linphone.databinding.SettingsAdvancedFragmentBinding import org.linphone.utils.AppUtils +import org.linphone.utils.Event import org.linphone.utils.PowerManagerUtils class AdvancedSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: AdvancedSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_advanced_fragment @@ -48,11 +50,15 @@ class AdvancedSettingsFragment : GenericFragment @@ -126,4 +132,8 @@ class AdvancedSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: AudioSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_audio_fragment @@ -47,11 +49,15 @@ class AudioSettingsFragment : GenericFragment() { binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(AudioSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } viewModel.askAudioRecordPermissionForEchoCancellerCalibrationEvent.observe(viewLifecycleOwner, { it.consume { @@ -110,4 +116,8 @@ class AudioSettingsFragment : GenericFragment() { } viewModel.audioCodecs.value = list } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/CallSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/CallSettingsFragment.kt index 08e6a751e..8ddab9f76 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/CallSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/CallSettingsFragment.kt @@ -26,15 +26,17 @@ import android.os.Bundle import android.provider.Settings import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.settings.viewmodels.CallSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.compatibility.Compatibility import org.linphone.databinding.SettingsCallFragmentBinding import org.linphone.mediastream.Version +import org.linphone.utils.Event class CallSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: CallSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_call_fragment @@ -44,11 +46,15 @@ class CallSettingsFragment : GenericFragment() { binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(CallSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } viewModel.systemWideOverlayEnabledEvent.observe(viewLifecycleOwner, { it.consume { @@ -84,4 +90,8 @@ class CallSettingsFragment : GenericFragment() { viewModel.systemWideOverlayListener.onBoolValueChanged(false) } } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/ChatSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/ChatSettingsFragment.kt index 597616b6e..7d7fb4602 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/ChatSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/ChatSettingsFragment.kt @@ -25,15 +25,17 @@ import android.os.Bundle import android.provider.Settings import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.settings.viewmodels.ChatSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.compatibility.Compatibility import org.linphone.databinding.SettingsChatFragmentBinding import org.linphone.mediastream.Version +import org.linphone.utils.Event class ChatSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: ChatSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_chat_fragment @@ -43,11 +45,15 @@ class ChatSettingsFragment : GenericFragment() { binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(ChatSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } viewModel.launcherShortcutsEvent.observe(viewLifecycleOwner, { it.consume { newValue -> @@ -76,4 +82,8 @@ class ChatSettingsFragment : GenericFragment() { } } }) } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/ContactsSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/ContactsSettingsFragment.kt index 9b4685ba2..99f3ea538 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/ContactsSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/ContactsSettingsFragment.kt @@ -23,18 +23,20 @@ import android.content.pm.PackageManager import android.os.Bundle import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.settings.viewmodels.ContactsSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.compatibility.Compatibility import org.linphone.core.tools.Log import org.linphone.databinding.SettingsContactsFragmentBinding +import org.linphone.utils.Event import org.linphone.utils.PermissionHelper class ContactsSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: ContactsSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_contacts_fragment @@ -44,11 +46,15 @@ class ContactsSettingsFragment : GenericFragment @@ -105,4 +111,8 @@ class ContactsSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: NetworkSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_network_fragment @@ -38,10 +40,18 @@ class NetworkSettingsFragment : GenericFragment( binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(NetworkSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } + } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/SettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/SettingsFragment.kt index 139bddbed..0c031abcb 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/SettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/SettingsFragment.kt @@ -21,8 +21,9 @@ package org.linphone.activities.main.settings.fragments import android.os.Bundle import android.view.View +import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController +import androidx.slidingpanelayout.widget.SlidingPaneLayout import org.linphone.R import org.linphone.activities.* import org.linphone.activities.main.fragments.SecureFragment @@ -47,14 +48,34 @@ class SettingsFragment : SecureFragment() { binding.lifecycleOwner = this + /* Shared view model & sliding pane related */ + sharedViewModel = requireActivity().run { ViewModelProvider(this).get(SharedMainViewModel::class.java) } + view.doOnPreDraw { sharedViewModel.canSlidingPaneBeClosed.value = binding.slidingPane.isSlideable } + + sharedViewModel.closeSlidingPaneEvent.observe(viewLifecycleOwner, { + it.consume { + if (!binding.slidingPane.closePane()) { + goBack() + } + } + }) + sharedViewModel.layoutChangedEvent.observe(viewLifecycleOwner, { + it.consume { + sharedViewModel.canSlidingPaneBeClosed.value = binding.slidingPane.isSlideable + } + }) + binding.slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED + + /* End of hared view model & sliding pane related */ + viewModel = ViewModelProvider(this).get(SettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } + binding.setBackClickListener { goBack() } sharedViewModel.accountRemoved.observe(viewLifecycleOwner, { Log.i("[Settings] Account removed, update accounts list") @@ -65,60 +86,70 @@ class SettingsFragment : SecureFragment() { if (identity != null) { Log.i("[Settings] Found identity parameter in arguments: $identity") arguments?.clear() + binding.slidingPane.openPane() navigateToAccountSettings(identity) } viewModel.accountsSettingsListener = object : SettingListenerStub() { override fun onAccountClicked(identity: String) { Log.i("[Settings] Navigation to settings for account with identity: $identity") + binding.slidingPane.openPane() navigateToAccountSettings(identity) } } viewModel.tunnelSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToTunnelSettings() } } viewModel.audioSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToAudioSettings() } } viewModel.videoSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToVideoSettings() } } viewModel.callSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToCallSettings() } } viewModel.chatSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToChatSettings() } } viewModel.networkSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToNetworkSettings() } } viewModel.contactsSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToContactsSettings() } } viewModel.advancedSettingsListener = object : SettingListenerStub() { override fun onClicked() { + binding.slidingPane.openPane() navigateToAdvancedSettings() } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/TunnelSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/TunnelSettingsFragment.kt index 84a7b2814..24dab5c38 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/TunnelSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/TunnelSettingsFragment.kt @@ -22,13 +22,15 @@ package org.linphone.activities.main.settings.fragments import android.os.Bundle import android.view.View import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.settings.viewmodels.TunnelSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.databinding.SettingsTunnelFragmentBinding +import org.linphone.utils.Event class TunnelSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: TunnelSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_tunnel_fragment @@ -38,10 +40,18 @@ class TunnelSettingsFragment : GenericFragment() binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(TunnelSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } + } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) } } diff --git a/app/src/main/java/org/linphone/activities/main/settings/fragments/VideoSettingsFragment.kt b/app/src/main/java/org/linphone/activities/main/settings/fragments/VideoSettingsFragment.kt index b12a8070b..102963770 100644 --- a/app/src/main/java/org/linphone/activities/main/settings/fragments/VideoSettingsFragment.kt +++ b/app/src/main/java/org/linphone/activities/main/settings/fragments/VideoSettingsFragment.kt @@ -26,18 +26,20 @@ import android.view.View import androidx.databinding.DataBindingUtil import androidx.databinding.ViewDataBinding import androidx.lifecycle.ViewModelProvider -import androidx.navigation.fragment.findNavController import org.linphone.BR import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.activities.GenericFragment import org.linphone.activities.main.settings.SettingListenerStub import org.linphone.activities.main.settings.viewmodels.VideoSettingsViewModel +import org.linphone.activities.main.viewmodels.SharedMainViewModel import org.linphone.core.tools.Log import org.linphone.databinding.SettingsVideoFragmentBinding +import org.linphone.utils.Event import org.linphone.utils.PermissionHelper class VideoSettingsFragment : GenericFragment() { + private lateinit var sharedViewModel: SharedMainViewModel private lateinit var viewModel: VideoSettingsViewModel override fun getLayoutId(): Int = R.layout.settings_video_fragment @@ -47,11 +49,15 @@ class VideoSettingsFragment : GenericFragment() { binding.lifecycleOwner = this + sharedViewModel = requireActivity().run { + ViewModelProvider(this).get(SharedMainViewModel::class.java) + } + binding.sharedMainViewModel = sharedViewModel + viewModel = ViewModelProvider(this).get(VideoSettingsViewModel::class.java) binding.viewModel = viewModel - binding.setBackClickListener { findNavController().popBackStack() } - binding.back.visibility = if (resources.getBoolean(R.bool.isTablet)) View.INVISIBLE else View.VISIBLE + binding.setBackClickListener { goBack() } initVideoCodecsList() @@ -100,4 +106,8 @@ class VideoSettingsFragment : GenericFragment() { } viewModel.videoCodecs.value = list } + + override fun goBack() { + sharedViewModel.closeSlidingPaneEvent.value = Event(true) + } } diff --git a/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt b/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt index e68162ca4..b30a8042b 100644 --- a/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/viewmodels/SharedMainViewModel.kt @@ -29,6 +29,10 @@ import org.linphone.utils.Event class SharedMainViewModel : ViewModel() { val toggleDrawerEvent = MutableLiveData>() + val layoutChangedEvent = MutableLiveData>() + var canSlidingPaneBeClosed = MutableLiveData() + val closeSlidingPaneEvent = MutableLiveData>() + /* Call history */ val selectedCallLogGroup = MutableLiveData() diff --git a/app/src/main/java/org/linphone/utils/RecyclerViewHeaderDecoration.kt b/app/src/main/java/org/linphone/utils/RecyclerViewHeaderDecoration.kt index 7e2b3b47a..a4f682376 100644 --- a/app/src/main/java/org/linphone/utils/RecyclerViewHeaderDecoration.kt +++ b/app/src/main/java/org/linphone/utils/RecyclerViewHeaderDecoration.kt @@ -26,9 +26,8 @@ import android.util.SparseArray import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView -import org.linphone.R -class RecyclerViewHeaderDecoration(private val adapter: HeaderAdapter) : RecyclerView.ItemDecoration() { +class RecyclerViewHeaderDecoration(private val context: Context, private val adapter: HeaderAdapter) : RecyclerView.ItemDecoration() { private val headers: SparseArray = SparseArray() override fun getItemOffsets( @@ -54,10 +53,8 @@ class RecyclerViewHeaderDecoration(private val adapter: HeaderAdapter) : Recycle view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) } - val displayMetrics = parent.context.resources.displayMetrics - val width = if (view.resources.getBoolean(R.bool.isTablet)) displayMetrics.widthPixels / 2 else displayMetrics.widthPixels - val widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY) - val heightSpec = View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels, View.MeasureSpec.EXACTLY) + val widthSpec = View.MeasureSpec.makeMeasureSpec(parent.width, View.MeasureSpec.EXACTLY) + val heightSpec = View.MeasureSpec.makeMeasureSpec(parent.height, View.MeasureSpec.EXACTLY) val childWidth = ViewGroup.getChildMeasureSpec(widthSpec, parent.paddingLeft + parent.paddingRight, view.layoutParams.width) val childHeight = ViewGroup.getChildMeasureSpec(heightSpec, parent.paddingTop + parent.paddingBottom, view.layoutParams.height) @@ -71,7 +68,7 @@ class RecyclerViewHeaderDecoration(private val adapter: HeaderAdapter) : Recycle val position = parent.getChildAdapterPosition(child) if (position != RecyclerView.NO_POSITION && adapter.displayHeaderForPosition(position)) { canvas.save() - val headerView: View = headers.get(position) ?: adapter.getHeaderViewForPosition(parent.context, position) + val headerView: View = headers.get(position) ?: adapter.getHeaderViewForPosition(context, position) canvas.translate(0f, child.y - headerView.height) headerView.draw(canvas) canvas.restore() diff --git a/app/src/main/res/drawable-xhdpi/chat_group_new_default.png b/app/src/main/res/drawable-xhdpi/chat_group_new_default.png index 50d061eede66290b62747012f44004db7382b176..7fbb9ae8f4f9a37c062b322911a55fa76f74f0c9 100644 GIT binary patch literal 16861 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 literal 4067 zcmV<94;=7`P)jvdP!IdbGsAQ(d$P5JC-aAam?uBXis zQuVTB%igAZELtC_&y1x}y0xjOsK{EiYSk5hbT8nZ<<~y?|DFE#4;eD#Pw;Gx#OGTF zG#-2@;5JZEfv5K$&P8texM=%F4Qn*!sRkk6I+w4{C01 zeu##bm>P5O=9iR|{Mdd-rZv!jaR*@h+5kiow0oB?U;YSyxZ$ zPs-LCaS?ycMSN7~X$$n&v13m;eE9Icu(6{G0Khf?(6|*VRxDNNiR6b5A3h4c3*noq z@i|C1I-{zp>OWapMcNdP969nB#^@l+Sof+RK^DL)epdmuK9=ri>5-luJ!;gbqN7KT zZWa)Y17&}e}b301QRRk!L4+q7xZ&lOknMy;_7$XDum<89j+cHL*wr%judQ&(3v z5MT;yTD)h*<$DGV8nl52p2YkN!o)0wkrN3aC#$?fpR|n8#LSN|bf9W1K;O>8?+Kxm zmX`KtXlSS*TP)=Sj}4tVb-JXovU0cZ;o&#~pdZ(GZb-Wr&FyXiI4Y7J)+5wG`eH5eZ>{`5eyIsKJdf53O&hYDQ^ReWtwafN7 z?SLlc_Ogvr&Rdmy1{Y(2T23?%zdx%y0RA(zEcvv17-DoU40YHEZJSEK>ne%kS3;iv z-S@+gzPsTuk4ecgl|K`eFSy_;DgA&3?GD4WbE8Yt)qW653aHHV!T=xL>>%Y!IrC4UdXJ^&CTr< z2+#Vpz4`rmJT{L}$EgEIjTY8Q-sf#}4|Oug>yR9%`OD zU?%cpLEdq|<7xWe;vfc4K!5S%=M1bKz~*}s4jnR7g1Kybnn2!%Vb|bA=Q4_z>jknX zCw08R5SZQHhe!n!byDtO$CW6W?66D)91%aHYq&Ia19_U+q; zc6bu@Xq0{!1N1b$F z?9<$J!vUpCcq+%~k{8h6HH`YxaE_gjR_hKzT_$VTC!vSD<#YugmvU~e@N#6~Q#p9> z;5*?Hru+72hDrq}C}27+79jr;0Tp2h0c7yX3cT_@ja3tIxZC2zi=z(F0Qx0>xmN8D z7}L@94Zy2{9-eSW8|uE|^fgIdf|2R8jEr(Q$8xM-CucnGht#W$eLoDDPM5;S0kSB_ zE&aGEAc(y1w2W8TWm`I^G*_NGq9-7g>lM%jaPihdcYrMIsOw5PlXM}e4=F0h=+{ho zsGy)=v<|ZH^bIt^#|s1XfHp^e6-ur5n-`wKTkmhuL2ZL4mjLG5&`wn8R{lo%cQw%c zkZS039uMfdc{}N-iGjl-O${Q@hU;})QPYe}Z|18kya6WsaIu)UbPzhBM&2T-p#5lH z!eZ<6CCw@sS-iya=!0loe0em6bijxLl{rAvGX{QFr3IN6-XcTgDLRNQDvk1~fLsGD zE|B3Z&zlXL8&rNuUKaV+6W5=F_C2QEr!e-vF&2=8hcAytplNclJy}y*QB-&n3S`<| zBxU=sbotaS1F`_z&MwDthDSAND!2YFQ3^bs8#z-P2JpgwzX%=4j8t2gd7eF`Bxh^IKaWwK3 zIxyH}35rHq5Q;-3@1`ahx-R+o`ESuq7PpKCbq!L_1(`xP8o*FgUJnR?Z0rya(U(UP zr*?CT>MHcm2}vlsWQZ=R9P6oHO01Rzc=3LT*&XEe=b~)myp}LFaxa!SeJYr;}q zUfzY5M)Zk7BV))DF!W$DG-q9*oZ{t{sh zZ`NNLm}VLyi?;)0(V;bfET;GZ+QOh#!$OLe8)!k1OuS7x1SKy}KE8p*n-=Su5CbO> z8$*jVdR-!A;VHaz9wr_1HZ7&>8|XfL`p7I$R=dCCDj|qGJY}cE5jH6Av~&nU zMACWa3*s>gT(@prGrz0rOoyRbr-6lqg>_rEZv9B3`zqqiQ}E_lhR#p&;EiwAU|^Ce zl5dX|1#@z8z9^nLsiQpB?PpLM;XV?G?g85n!L` z*WevHb_}3zp{YL?;66*XuX%upXR>L&faaDSOnMLH<^t%c9!fUhd7pdK#X|l!jbz=y zbeslpuIM1Tm>RS+T3j9>p@0ROhw-ReFvPPj!>*&GX{;msHW7mX@h4o!7f6vF+OkgZ zBr*FgeT6L%*+KV>WPn2!MxO=9OEFq@Rw9A?CiOpJ$$%9iD)xni3BuQvN;3bDb9tt|nAeuu!u`?Hg2H-cAKf z*))zKH3_3m zHc4+IY&~tNKVCE=c(yX^Xgr7)J!JwJV~*g#ceAE@L8?F&y+oGCME*UZgRQH57F|VW z(cPxCgtMndizkc19!h@9uSO>>S+ZoKM}11jyj)%^<8_3EUouw(;|RC36wfw#H1Tje zo-tchTFFP2hoMByaeMq#0Ig&RdE~$E}*&P`r*lc^avMEvHLqdS&RFA z>=#``C&Gv;CR<@-uGr*5A>4*9avM(5=`E>DxO)L7xz3=| zyIhPRvXgG8O9{#0(d=SON2&{CXjPp%cfKJd8YLja($Td}E;jMWpPwbbI^nKik7m}F z&%10};pljMid#~)-EN z*VSkA(MP8xyDUqJ`34~_P+$St~#x?mOX6Qm1=urIx{(7U#iy{n#caVRZ>`JD!D;YAmhD$*! z<%b`uj{_LC4WsWcym%-&_w?f9VY65BKvUY0>+ zoI_s=z~~G~c>Xu^|CA)5MuvyGXtRq8A|sds_3LQ2BYtQgvlq!WL-=q-W zTJ3=y>rr0*8strO%im=q_y1Qq#a20h)@92VVCw7ZOHf$0^h;3qT+X3eUT@n1%8lsx z0eZ*>4Qu(9QLTJfr3L5}QXwMHx{~s8__l4^`Y{eI#+d%3VvLiAlH^a&+b5%pygl&U zguG4UHXM;?FP?D$9Z7lZGtXe7O1Cufb#*$@)a0)pvt6bGhdw96zQLTXwzbk{{c_h Vt~BC?kqrO<002ovPDHLkV1jj%)dm0n diff --git a/app/src/main/res/layout-land/history_detail_fragment.xml b/app/src/main/res/layout-land/history_detail_fragment.xml deleted file mode 100644 index 12546a67f..000000000 --- a/app/src/main/res/layout-land/history_detail_fragment.xml +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw533dp-land/history_detail_fragment.xml b/app/src/main/res/layout-sw533dp-land/history_detail_fragment.xml deleted file mode 100644 index d92e5400f..000000000 --- a/app/src/main/res/layout-sw533dp-land/history_detail_fragment.xml +++ /dev/null @@ -1,192 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw533dp-land/settings_fragment.xml b/app/src/main/res/layout-sw533dp-land/settings_fragment.xml deleted file mode 100644 index 30c78816c..000000000 --- a/app/src/main/res/layout-sw533dp-land/settings_fragment.xml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout-sw533dp/chat_room_master_fragment.xml b/app/src/main/res/layout-sw533dp/chat_room_master_fragment.xml deleted file mode 100644 index 72fb86946..000000000 --- a/app/src/main/res/layout-sw533dp/chat_room_master_fragment.xml +++ /dev/null @@ -1,175 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw533dp/contact_master_fragment.xml b/app/src/main/res/layout-sw533dp/contact_master_fragment.xml deleted file mode 100644 index 8b36fd95b..000000000 --- a/app/src/main/res/layout-sw533dp/contact_master_fragment.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw533dp/history_master_fragment.xml b/app/src/main/res/layout-sw533dp/history_master_fragment.xml deleted file mode 100644 index 1667df406..000000000 --- a/app/src/main/res/layout-sw533dp/history_master_fragment.xml +++ /dev/null @@ -1,165 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout-sw533dp/settings_fragment.xml b/app/src/main/res/layout-sw533dp/settings_fragment.xml deleted file mode 100644 index 30c78816c..000000000 --- a/app/src/main/res/layout-sw533dp/settings_fragment.xml +++ /dev/null @@ -1,209 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/chat_room_detail_fragment.xml b/app/src/main/res/layout/chat_room_detail_fragment.xml index f13d6ed1f..c40af9770 100644 --- a/app/src/main/res/layout/chat_room_detail_fragment.xml +++ b/app/src/main/res/layout/chat_room_detail_fragment.xml @@ -32,6 +32,9 @@ + + android:paddingLeft="15dp"> + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -24,9 +25,16 @@ type="org.linphone.activities.main.chat.viewmodels.ChatRoomsListViewModel" /> - + android:layout_height="match_parent" + tools:context=".MainActivity"> + + + + + + + + diff --git a/app/src/main/res/layout/contact_detail_fragment.xml b/app/src/main/res/layout/contact_detail_fragment.xml index 1bcfe850b..0e26c8c39 100644 --- a/app/src/main/res/layout/contact_detail_fragment.xml +++ b/app/src/main/res/layout/contact_detail_fragment.xml @@ -17,6 +17,9 @@ + + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -21,147 +22,178 @@ type="org.linphone.activities.main.contact.viewmodels.ContactsListViewModel" /> - + android:layout_height="match_parent" + tools:context=".MainActivity"> - + - + - + android:layout_weight="0.2"> + + + + + + + + + + + + + + - - - - + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="0.2" /> + + + + + + + + + + + + + + + + + android:text="@string/no_sip_contact" + android:visibility="@{viewModel.sipContactsSelected && viewModel.contactsList.empty ? View.VISIBLE : View.GONE}" /> - + android:layout_height="wrap_content" + android:layout_centerVertical="true" + android:gravity="center" + android:text="@string/no_contact" + android:visibility="@{!viewModel.sipContactsSelected && viewModel.contactsList.empty ? View.VISIBLE : View.GONE}" /> + android:layout_alignParentRight="true" + android:background="?attr/dividerColor" /> - - - - - + + android:id="@+id/contacts_nav_container" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="300dp" + android:layout_height="match_parent" + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/contacts_nav_graph"/> - - - - - - - - - - - + diff --git a/app/src/main/res/layout/history_detail_fragment.xml b/app/src/main/res/layout/history_detail_fragment.xml index d92e5400f..106672939 100644 --- a/app/src/main/res/layout/history_detail_fragment.xml +++ b/app/src/main/res/layout/history_detail_fragment.xml @@ -17,6 +17,9 @@ + + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto"> @@ -18,114 +19,138 @@ type="org.linphone.activities.main.history.viewmodels.CallLogsListViewModel" /> - + android:layout_height="match_parent" + tools:context=".MainActivity"> - + - + - + android:layout_weight="0.2"> + + + + + + + + + + + + + + - - - - + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="0.4" /> + android:src="@drawable/delete" /> - + - + + + + + + + + android:layout_alignParentRight="true" + android:background="?attr/dividerColor" /> - - - + + android:id="@+id/history_nav_container" + android:name="androidx.navigation.fragment.NavHostFragment" + android:layout_width="300dp" + android:layout_height="match_parent" + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/history_nav_graph"/> - - - - - - - + diff --git a/app/src/main/res/layout/settings_account_fragment.xml b/app/src/main/res/layout/settings_account_fragment.xml index de9dc871d..f2dfba0b6 100644 --- a/app/src/main/res/layout/settings_account_fragment.xml +++ b/app/src/main/res/layout/settings_account_fragment.xml @@ -12,6 +12,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_advanced_fragment.xml b/app/src/main/res/layout/settings_advanced_fragment.xml index 20166266f..1f6571f1a 100644 --- a/app/src/main/res/layout/settings_advanced_fragment.xml +++ b/app/src/main/res/layout/settings_advanced_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_audio_fragment.xml b/app/src/main/res/layout/settings_audio_fragment.xml index b90c07f0c..30c9214fb 100644 --- a/app/src/main/res/layout/settings_audio_fragment.xml +++ b/app/src/main/res/layout/settings_audio_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_call_fragment.xml b/app/src/main/res/layout/settings_call_fragment.xml index 9dcee1ab6..b6878790c 100644 --- a/app/src/main/res/layout/settings_call_fragment.xml +++ b/app/src/main/res/layout/settings_call_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_chat_fragment.xml b/app/src/main/res/layout/settings_chat_fragment.xml index 6bb583f7e..7c9e8dc29 100644 --- a/app/src/main/res/layout/settings_chat_fragment.xml +++ b/app/src/main/res/layout/settings_chat_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_contacts_fragment.xml b/app/src/main/res/layout/settings_contacts_fragment.xml index 9da63cbe3..f7a191527 100644 --- a/app/src/main/res/layout/settings_contacts_fragment.xml +++ b/app/src/main/res/layout/settings_contacts_fragment.xml @@ -10,6 +10,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_fragment.xml b/app/src/main/res/layout/settings_fragment.xml index 472febcc8..7f2bd98a7 100644 --- a/app/src/main/res/layout/settings_fragment.xml +++ b/app/src/main/res/layout/settings_fragment.xml @@ -1,6 +1,7 @@ + xmlns:linphone="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> @@ -13,170 +14,194 @@ type="org.linphone.activities.main.settings.viewmodels.SettingsViewModel" /> - + android:layout_height="match_parent" + tools:context=".MainActivity"> - - - - - - - - - - - + + android:layout_height="@dimen/main_activity_top_bar_size" + android:layout_gravity="center_horizontal" + android:background="?attr/lightToolbarBackgroundColor" + android:orientation="horizontal"> + + + style="@style/accent_colored_title_font" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="0.6" + android:gravity="center" + android:singleLine="true" + android:ellipsize="end" + android:padding="15dp" + android:text="@string/settings"/> - + - + - + + android:paddingTop="5dp" + android:paddingBottom="5dp" + android:orientation="vertical"> - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/settings_network_fragment.xml b/app/src/main/res/layout/settings_network_fragment.xml index 164554c02..067f4ceb3 100644 --- a/app/src/main/res/layout/settings_network_fragment.xml +++ b/app/src/main/res/layout/settings_network_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_tunnel_fragment.xml b/app/src/main/res/layout/settings_tunnel_fragment.xml index 35b84bc97..e6eac5db5 100644 --- a/app/src/main/res/layout/settings_tunnel_fragment.xml +++ b/app/src/main/res/layout/settings_tunnel_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/layout/settings_video_fragment.xml b/app/src/main/res/layout/settings_video_fragment.xml index e1d08a581..c50870e2d 100644 --- a/app/src/main/res/layout/settings_video_fragment.xml +++ b/app/src/main/res/layout/settings_video_fragment.xml @@ -11,6 +11,9 @@ + + android:visibility="@{sharedMainViewModel.canSlidingPaneBeClosed ? View.INVISIBLE : View.GONE}" /> diff --git a/app/src/main/res/navigation-sw533dp/chat_nav_graph.xml b/app/src/main/res/navigation-sw533dp/chat_nav_graph.xml deleted file mode 100644 index b073b3b01..000000000 --- a/app/src/main/res/navigation-sw533dp/chat_nav_graph.xml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation-sw533dp/contacts_nav_graph.xml b/app/src/main/res/navigation-sw533dp/contacts_nav_graph.xml deleted file mode 100644 index 5c1c9a794..000000000 --- a/app/src/main/res/navigation-sw533dp/contacts_nav_graph.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation-sw533dp/history_nav_graph.xml b/app/src/main/res/navigation-sw533dp/history_nav_graph.xml deleted file mode 100644 index d10270905..000000000 --- a/app/src/main/res/navigation-sw533dp/history_nav_graph.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation/chat_nav_graph.xml b/app/src/main/res/navigation/chat_nav_graph.xml index 0383787db..2a3b2abab 100644 --- a/app/src/main/res/navigation/chat_nav_graph.xml +++ b/app/src/main/res/navigation/chat_nav_graph.xml @@ -3,7 +3,13 @@ xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/chat_nav_graph.xml" - app:startDestination="@id/detailChatRoomFragment"> + app:startDestination="@id/emptyChatFragment"> + + + android:label="ChatRoomCreationFragment" > + + + + + + + + + app:startDestination="@id/emptyContactFragment"> + + - + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/history_nav_graph.xml b/app/src/main/res/navigation/history_nav_graph.xml index a4100bb5b..d10270905 100644 --- a/app/src/main/res/navigation/history_nav_graph.xml +++ b/app/src/main/res/navigation/history_nav_graph.xml @@ -3,22 +3,22 @@ xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/history_nav_graph.xml" - app:startDestination="@id/detailCallLogFragment"> + app:startDestination="@id/emptyFragment"> + + + android:label="DetailCallLogFragment" /> - - - - - + \ No newline at end of file diff --git a/app/src/main/res/navigation/main_nav_graph.xml b/app/src/main/res/navigation/main_nav_graph.xml index 15c1055fd..9e6204476 100644 --- a/app/src/main/res/navigation/main_nav_graph.xml +++ b/app/src/main/res/navigation/main_nav_graph.xml @@ -19,12 +19,6 @@ - - + - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - - + \ No newline at end of file