From 7f10548ecbc88bca14543f3c1b14f030fda1104e Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Tue, 14 Nov 2023 00:29:39 +0100 Subject: [PATCH] Removed unseless Fragment only containing SlidingPaneLayout + using same values for SlidingPaneLayout childs width as on previous releases --- .../notifications/NotificationsManager.kt | 2 +- .../java/org/linphone/ui/main/MainActivity.kt | 24 +- .../chat/fragment/ConversationFragment.kt | 5 +- .../chat/fragment/ConversationsFragment.kt | 210 ------------ .../fragment/ConversationsListFragment.kt | 89 ++++- .../SendMessageInConversationViewModel.kt | 4 +- .../contacts/fragment/ContactsFragment.kt | 177 ---------- .../contacts/fragment/ContactsListFragment.kt | 57 +++- .../main/fragment/AbstractTopBarFragment.kt | 232 ++++++++++++- .../main/history/fragment/HistoryFragment.kt | 175 ---------- .../history/fragment/HistoryListFragment.kt | 58 ++-- .../main/meetings/fragment/MeetingFragment.kt | 2 +- .../meetings/fragment/MeetingsFragment.kt | 183 ---------- .../meetings/fragment/MeetingsListFragment.kt | 66 +++- .../ui/main/viewmodel/SharedMainViewModel.kt | 28 -- .../res/layout-land/chat_list_fragment.xml | 190 ++++++----- .../layout-land/contacts_list_fragment.xml | 292 ++++++++-------- .../res/layout-land/history_list_fragment.xml | 224 ++++++------ .../layout-land/meetings_list_fragment.xml | 214 ++++++------ app/src/main/res/layout/chat_fragment.xml | 32 -- .../main/res/layout/chat_list_fragment.xml | 208 +++++------ app/src/main/res/layout/contacts_fragment.xml | 32 -- .../res/layout/contacts_list_fragment.xml | 322 +++++++++--------- app/src/main/res/layout/history_fragment.xml | 32 -- .../main/res/layout/history_list_fragment.xml | 234 +++++++------ app/src/main/res/layout/meetings_fragment.xml | 32 -- .../res/layout/meetings_list_fragment.xml | 234 +++++++------ .../main/res/navigation/main_nav_graph.xml | 123 ++++--- app/src/main/res/values-land/dimen.xml | 3 - app/src/main/res/values/dimen.xml | 1 - 30 files changed, 1523 insertions(+), 1962 deletions(-) delete mode 100644 app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsFragment.kt delete mode 100644 app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt delete mode 100644 app/src/main/java/org/linphone/ui/main/history/fragment/HistoryFragment.kt delete mode 100644 app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsFragment.kt delete mode 100644 app/src/main/res/layout/chat_fragment.xml delete mode 100644 app/src/main/res/layout/contacts_fragment.xml delete mode 100644 app/src/main/res/layout/history_fragment.xml delete mode 100644 app/src/main/res/layout/meetings_fragment.xml diff --git a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt index 89c8d0002..cccf70105 100644 --- a/app/src/main/java/org/linphone/notifications/NotificationsManager.kt +++ b/app/src/main/java/org/linphone/notifications/NotificationsManager.kt @@ -1085,7 +1085,7 @@ class NotificationsManager @MainThread constructor(private val context: Context) return NavDeepLinkBuilder(context) .setComponentName(MainActivity::class.java) .setGraph(R.navigation.main_nav_graph) - .setDestination(R.id.conversationsFragment) + .setDestination(R.id.conversationsListFragment) .setArguments(args) .createPendingIntent() } diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt index 41ad4bbc6..6b9f647cc 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -194,27 +194,27 @@ class MainActivity : AppCompatActivity() { val startDestination = when (corePreferences.defaultFragment) { CONTACTS_FRAGMENT_ID -> { Log.i("$TAG Latest visited page is contacts, setting it as start destination") - R.id.contactsFragment + R.id.contactsListFragment } HISTORY_FRAGMENT_ID -> { Log.i( "$TAG Latest visited page is call history, setting it as start destination" ) - R.id.historyFragment + R.id.historyListFragment } CHAT_FRAGMENT_ID -> { Log.i( "$TAG Latest visited page is conversations, setting it as start destination" ) - R.id.conversationsFragment + R.id.conversationsListFragment } MEETINGS_FRAGMENT_ID -> { Log.i("$TAG Latest visited page is meetings, setting it as start destination") - R.id.meetingsFragment + R.id.meetingsListFragment } else -> { // Default Log.i("$TAG No latest visited page stored, using default one (call history)") - R.id.historyFragment + R.id.historyListFragment } } coreContext.postOnMainThread { @@ -230,16 +230,16 @@ class MainActivity : AppCompatActivity() { override fun onPause() { val defaultFragmentId = when (sharedViewModel.currentlyDisplayedFragment.value) { - R.id.contactsFragment -> { + R.id.contactsListFragment -> { CONTACTS_FRAGMENT_ID } - R.id.historyFragment -> { + R.id.historyListFragment -> { HISTORY_FRAGMENT_ID } - R.id.conversationsFragment -> { + R.id.conversationsListFragment -> { CHAT_FRAGMENT_ID } - R.id.meetingsFragment -> { + R.id.meetingsListFragment -> { MEETINGS_FRAGMENT_ID } else -> { // Default @@ -352,12 +352,12 @@ class MainActivity : AppCompatActivity() { if (isNewIntent) { Log.i("$TAG Going to Conversations fragment") findNavController().navigate( - R.id.action_global_conversationsFragment, + R.id.action_global_conversationsListFragment, intent.extras ) } else { Log.i("$TAG Going to Conversations fragment instead of default destination") - navGraph.setStartDestination(R.id.conversationsFragment) + navGraph.setStartDestination(R.id.conversationsListFragment) findNavController().setGraph(navGraph, intent.extras) } } else { @@ -415,7 +415,7 @@ class MainActivity : AppCompatActivity() { } val navGraph = findNavController().navInflater.inflate(R.navigation.main_nav_graph) - navGraph.setStartDestination(R.id.conversationsFragment) + navGraph.setStartDestination(R.id.conversationsListFragment) val paths = deferred.awaitAll() for (path in paths) { diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt index a1f5236cb..49cf7a5dd 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationFragment.kt @@ -172,7 +172,8 @@ class ConversationFragment : GenericFragment() { override fun goBack(): Boolean { coreContext.notificationsManager.resetCurrentlyDisplayedChatRoomId() sharedViewModel.closeSlidingPaneEvent.value = Event(true) - // If not done, when going back to ConversationsFragment this fragment will be created again + coreContext.notificationsManager.resetCurrentlyDisplayedChatRoomId() + // If not done, when going back to ConversationsListFragment this fragment will be created again return findNavController().popBackStack() } @@ -181,7 +182,6 @@ class ConversationFragment : GenericFragment() { isSlidingPaneChild = true super.onViewCreated(view, savedInstanceState) - // postponeEnterTransition() binding.lifecycleOwner = viewLifecycleOwner @@ -234,7 +234,6 @@ class ConversationFragment : GenericFragment() { } (view.parent as? ViewGroup)?.doOnPreDraw { - // startPostponedEnterTransition() sharedViewModel.openSlidingPaneEvent.value = Event(true) } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsFragment.kt deleted file mode 100644 index ac39dad3e..000000000 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsFragment.kt +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2010-2023 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.linphone.ui.main.chat.fragment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.AnimationUtils -import androidx.annotation.UiThread -import androidx.core.view.doOnPreDraw -import androidx.navigation.findNavController -import androidx.navigation.fragment.findNavController -import androidx.slidingpanelayout.widget.SlidingPaneLayout -import org.linphone.R -import org.linphone.core.tools.Log -import org.linphone.databinding.ChatFragmentBinding -import org.linphone.ui.main.fragment.GenericFragment -import org.linphone.utils.Event -import org.linphone.utils.SlidingPaneBackPressedCallback - -@UiThread -class ConversationsFragment : GenericFragment() { - companion object { - private const val TAG = "[Conversations Fragment]" - } - - private lateinit var binding: ChatFragmentBinding - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - binding = ChatFragmentBinding.inflate(layoutInflater) - return binding.root - } - - override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { - if ( - findNavController().currentDestination?.id == R.id.startConversationFragment || - findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment - ) { - // Holds fragment in place while new contact fragment slides over it - return AnimationUtils.loadAnimation(activity, R.anim.hold) - } - return super.onCreateAnimation(transit, enter, nextAnim) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - postponeEnterTransition() - super.onViewCreated(view, savedInstanceState) - - binding.lifecycleOwner = viewLifecycleOwner - - binding.root.doOnPreDraw { - val slidingPane = binding.slidingPaneLayout - slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED - - sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable - - requireActivity().onBackPressedDispatcher.addCallback( - viewLifecycleOwner, - SlidingPaneBackPressedCallback(slidingPane) - ) - } - - sharedViewModel.conversationsReadyEvent.observe(viewLifecycleOwner) { - it.consume { - (view.parent as? ViewGroup)?.doOnPreDraw { - startPostponedEnterTransition() - sharedViewModel.isFirstFragmentReady = true - } - } - } - - val args = arguments - if (args != null) { - val localSipUri = args.getString("LocalSipUri") - val remoteSipUri = args.getString("RemoteSipUri") - if (localSipUri != null && remoteSipUri != null) { - Log.i("$TAG Found local [$localSipUri] & remote [$remoteSipUri] URIs in arguments") - val pair = Pair(localSipUri, remoteSipUri) - sharedViewModel.showConversationEvent.value = Event(pair) - args.clear() - } - } - - sharedViewModel.closeSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Closing sliding pane") - binding.slidingPaneLayout.closePane() - } - } - } - - sharedViewModel.openSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (!binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Opening sliding pane") - binding.slidingPaneLayout.openPane() - } - } - } - - sharedViewModel.showStartConversationEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.conversationsFragment) { - Log.i("$TAG Navigating to start conversation fragment") - val action = - ConversationsFragmentDirections.actionConversationsFragmentToStartConversationFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.showConversationEvent.observe(viewLifecycleOwner) { - it.consume { pair -> - val localSipUri = pair.first - val remoteSipUri = pair.second - Log.i( - "$TAG Navigating to conversation fragment with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" - ) - val action = ConversationFragmentDirections.actionGlobalConversationFragment( - localSipUri, - remoteSipUri - ) - binding.chatNavContainer.findNavController().navigate(action) - } - } - - sharedViewModel.goToMeetingWaitingRoomEvent.observe(viewLifecycleOwner) { - it.consume { uri -> - if (findNavController().currentDestination?.id == R.id.conversationsFragment) { - Log.i("$TAG Navigating to meeting waiting room fragment with URI [$uri]") - val action = - ConversationsFragmentDirections.actionConversationsFragmentToMeetingWaitingRoomFragment( - uri - ) - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToContactsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.conversationsFragment) { - // To prevent any previously seen conversation to show up when navigating back to here later - binding.chatNavContainer.findNavController().popBackStack() - - val action = ConversationsFragmentDirections.actionConversationsFragmentToContactsFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToHistoryEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.conversationsFragment) { - // To prevent any previously seen conversation to show up when navigating back to here later - binding.chatNavContainer.findNavController().popBackStack() - - val action = ConversationsFragmentDirections.actionConversationsFragmentToHistoryFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToMeetingsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.conversationsFragment) { - // To prevent any previously seen conversation to show up when navigating back to here later - binding.chatNavContainer.findNavController().popBackStack() - - val action = ConversationsFragmentDirections.actionConversationsFragmentToMeetingsFragment() - findNavController().navigate(action) - } - } - } - } - - override fun onResume() { - super.onResume() - - sharedViewModel.currentlyDisplayedFragment.value = R.id.conversationsFragment - } -} diff --git a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt index e9c283110..b2d0b72db 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/fragment/ConversationsListFragment.kt @@ -19,14 +19,17 @@ */ package org.linphone.ui.main.chat.fragment -import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.Animation +import android.view.animation.AnimationUtils import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.R import org.linphone.core.tools.Log @@ -36,7 +39,6 @@ import org.linphone.ui.main.chat.viewmodel.ConversationsListViewModel import org.linphone.ui.main.fragment.AbstractTopBarFragment import org.linphone.ui.main.history.fragment.HistoryMenuDialogFragment import org.linphone.utils.Event -import org.linphone.utils.setKeyboardInsetListener @UiThread class ConversationsListFragment : AbstractTopBarFragment() { @@ -50,6 +52,24 @@ class ConversationsListFragment : AbstractTopBarFragment() { private lateinit var adapter: ConversationsListAdapter + override fun onDefaultAccountChanged() { + Log.i( + "$TAG Default account changed, updating avatar in top bar & re-computing conversations" + ) + listViewModel.applyFilter() + } + + override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { + if ( + findNavController().currentDestination?.id == R.id.startConversationFragment || + findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment + ) { + // Holds fragment in place while new contact fragment slides over it + return AnimationUtils.loadAnimation(activity, R.anim.hold) + } + return super.onCreateAnimation(transit, enter, nextAnim) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -118,7 +138,12 @@ class ConversationsListFragment : AbstractTopBarFragment() { } binding.setOnNewConversationClicked { - sharedViewModel.showStartConversationEvent.value = Event(true) + if (findNavController().currentDestination?.id == R.id.conversationsListFragment) { + Log.i("$TAG Navigating to start conversation fragment") + val action = + ConversationsListFragmentDirections.actionConversationsListFragmentToStartConversationFragment() + findNavController().navigate(action) + } } listViewModel.conversations.observe(viewLifecycleOwner) { @@ -132,7 +157,7 @@ class ConversationsListFragment : AbstractTopBarFragment() { (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() - sharedViewModel.conversationsReadyEvent.value = Event(true) + sharedViewModel.isFirstFragmentReady = true } } @@ -143,6 +168,36 @@ class ConversationsListFragment : AbstractTopBarFragment() { } } + sharedViewModel.showConversationEvent.observe(viewLifecycleOwner) { + it.consume { pair -> + val localSipUri = pair.first + val remoteSipUri = pair.second + Log.i( + "${ConversationsListFragment.TAG} Navigating to conversation fragment with local SIP URI [$localSipUri] and remote SIP URI [$remoteSipUri]" + ) + if (findNavController().currentDestination?.id == R.id.conversationsListFragment) { + val action = ConversationFragmentDirections.actionGlobalConversationFragment( + localSipUri, + remoteSipUri + ) + binding.chatNavContainer.findNavController().navigate(action) + } + } + } + + sharedViewModel.goToMeetingWaitingRoomEvent.observe(viewLifecycleOwner) { + it.consume { uri -> + if (findNavController().currentDestination?.id == R.id.conversationsListFragment) { + Log.i("$TAG Navigating to meeting waiting room fragment with URI [$uri]") + val action = + ConversationsListFragmentDirections.actionConversationsListFragmentToMeetingWaitingRoomFragment( + uri + ) + findNavController().navigate(action) + } + } + } + // TopBarFragment related setViewModelAndTitle( @@ -151,17 +206,23 @@ class ConversationsListFragment : AbstractTopBarFragment() { getString(R.string.bottom_navigation_conversations_label) ) - binding.root.setKeyboardInsetListener { keyboardVisible -> - val portraitOrientation = resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE - binding.bottomNavBar.root.visibility = if (!portraitOrientation || !keyboardVisible) View.VISIBLE else View.GONE - } + initBottomNavBar(binding.bottomNavBar.root) - sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i( - "$TAG Default account changed, updating avatar in top bar & re-computing conversations" - ) - listViewModel.applyFilter() + initSlidingPane(binding.slidingPaneLayout) + + initNavigation(R.id.conversationsListFragment) + + // Handle intent params if any + + val args = arguments + if (args != null) { + val localSipUri = args.getString("LocalSipUri") + val remoteSipUri = args.getString("RemoteSipUri") + if (localSipUri != null && remoteSipUri != null) { + Log.i("$TAG Found local [$localSipUri] & remote [$remoteSipUri] URIs in arguments") + val pair = Pair(localSipUri, remoteSipUri) + sharedViewModel.showConversationEvent.value = Event(pair) + args.clear() } } } diff --git a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt index d06065277..4fb642d72 100644 --- a/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/chat/viewmodel/SendMessageInConversationViewModel.kt @@ -265,7 +265,9 @@ class SendMessageInConversationViewModel @UiThread constructor() : ViewModel() { isParticipantsListOpen.postValue(false) isEmojiPickerOpen.postValue(false) - stopVoiceRecorder() + if (::voiceMessageRecorder.isInitialized) { + stopVoiceRecorder() + } voiceRecording.postValue(false) // Warning: do not delete files diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt deleted file mode 100644 index 19e1afe0e..000000000 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsFragment.kt +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2010-2023 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.linphone.ui.main.contacts.fragment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.AnimationUtils -import androidx.annotation.UiThread -import androidx.core.view.doOnPreDraw -import androidx.navigation.findNavController -import androidx.navigation.fragment.findNavController -import androidx.slidingpanelayout.widget.SlidingPaneLayout -import org.linphone.R -import org.linphone.core.tools.Log -import org.linphone.databinding.ContactsFragmentBinding -import org.linphone.ui.main.fragment.GenericFragment -import org.linphone.utils.SlidingPaneBackPressedCallback - -@UiThread -class ContactsFragment : GenericFragment() { - companion object { - private const val TAG = "[Contacts Fragment]" - } - - private lateinit var binding: ContactsFragmentBinding - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - binding = ContactsFragmentBinding.inflate(layoutInflater) - return binding.root - } - - override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { - if (findNavController().currentDestination?.id == R.id.newContactFragment) { - // Holds fragment in place while new contact fragment slides over it - return AnimationUtils.loadAnimation(activity, R.anim.hold) - } - return super.onCreateAnimation(transit, enter, nextAnim) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - postponeEnterTransition() - super.onViewCreated(view, savedInstanceState) - - binding.lifecycleOwner = viewLifecycleOwner - - binding.root.doOnPreDraw { - val slidingPane = binding.slidingPaneLayout - slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED - - sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable - - requireActivity().onBackPressedDispatcher.addCallback( - viewLifecycleOwner, - SlidingPaneBackPressedCallback(slidingPane) - ) - } - - sharedViewModel.contactsReadyEvent.observe(viewLifecycleOwner) { - it.consume { - (view.parent as? ViewGroup)?.doOnPreDraw { - startPostponedEnterTransition() - sharedViewModel.isFirstFragmentReady = true - } - } - } - - sharedViewModel.closeSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Closing sliding pane") - binding.slidingPaneLayout.closePane() - } - } - } - - sharedViewModel.openSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (!binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Opening sliding pane") - binding.slidingPaneLayout.openPane() - } - } - } - - sharedViewModel.showContactEvent.observe( - viewLifecycleOwner - ) { - it.consume { refKey -> - Log.i("$TAG Displaying contact with ref key [$refKey]") - val navController = binding.contactsNavContainer.findNavController() - val action = ContactFragmentDirections.actionGlobalContactFragment( - refKey - ) - navController.navigate(action) - } - } - - sharedViewModel.showNewContactEvent.observe( - viewLifecycleOwner - ) { - it.consume { - Log.i("$TAG Opening contact editor for creating new contact") - val action = ContactsFragmentDirections.actionContactsFragmentToNewContactFragment() - findNavController().navigate(action) - } - } - - sharedViewModel.navigateToHistoryEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.contactsFragment) { - // To prevent any previously seen contact to show up when navigating back to here later - binding.contactsNavContainer.findNavController().popBackStack() - - val action = ContactsFragmentDirections.actionContactsFragmentToHistoryFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToConversationsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.contactsFragment) { - // To prevent any previously seen contact to show up when navigating back to here later - binding.contactsNavContainer.findNavController().popBackStack() - - val action = ContactsFragmentDirections.actionContactsFragmentToConversationsFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToMeetingsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.contactsFragment) { - // To prevent any previously seen contact to show up when navigating back to here later - binding.contactsNavContainer.findNavController().popBackStack() - - val action = ContactsFragmentDirections.actionContactsFragmentToMeetingsFragment() - findNavController().navigate(action) - } - } - } - } - - override fun onResume() { - super.onResume() - sharedViewModel.currentlyDisplayedFragment.value = R.id.contactsFragment - } -} diff --git a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt index 8bff1a1fa..71c9c5363 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/fragment/ContactsListFragment.kt @@ -20,7 +20,6 @@ package org.linphone.ui.main.contacts.fragment import android.content.Intent -import android.content.res.Configuration import android.os.Bundle import android.provider.ContactsContract import android.view.Gravity @@ -33,6 +32,8 @@ import androidx.core.content.FileProvider import androidx.core.view.doOnPreDraw import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import java.io.File import org.linphone.LinphoneApplication.Companion.coreContext @@ -44,7 +45,6 @@ import org.linphone.ui.main.contacts.adapter.ContactsListAdapter import org.linphone.ui.main.contacts.viewmodel.ContactsListViewModel import org.linphone.ui.main.fragment.AbstractTopBarFragment import org.linphone.utils.Event -import org.linphone.utils.setKeyboardInsetListener @UiThread class ContactsListFragment : AbstractTopBarFragment() { @@ -59,6 +59,14 @@ class ContactsListFragment : AbstractTopBarFragment() { private lateinit var adapter: ContactsListAdapter private lateinit var favouritesAdapter: ContactsListAdapter + override fun onDefaultAccountChanged() { + Log.i( + "$TAG Default account changed, updating avatar in top bar & refreshing contacts list" + ) + listViewModel.update() + listViewModel.applyCurrentDefaultAccountFilter() + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -106,7 +114,7 @@ class ContactsListFragment : AbstractTopBarFragment() { (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() - sharedViewModel.contactsReadyEvent.value = Event(true) + sharedViewModel.isFirstFragmentReady = true } } @@ -136,6 +144,32 @@ class ContactsListFragment : AbstractTopBarFragment() { showFilterPopupMenu(binding.filter) } + sharedViewModel.showContactEvent.observe( + viewLifecycleOwner + ) { + it.consume { refKey -> + Log.i("$TAG Displaying contact with ref key [$refKey]") + val navController = binding.contactsNavContainer.findNavController() + val action = ContactFragmentDirections.actionGlobalContactFragment( + refKey + ) + navController.navigate(action) + } + } + + sharedViewModel.showNewContactEvent.observe( + viewLifecycleOwner + ) { + it.consume { + if (findNavController().currentDestination?.id == R.id.contactsListFragment) { + Log.i("$TAG Opening contact editor for creating new contact") + val action = + ContactsListFragmentDirections.actionContactsListFragmentToNewContactFragment() + findNavController().navigate(action) + } + } + } + // TopBarFragment related setViewModelAndTitle( @@ -144,20 +178,11 @@ class ContactsListFragment : AbstractTopBarFragment() { getString(R.string.bottom_navigation_contacts_label) ) - binding.root.setKeyboardInsetListener { keyboardVisible -> - val portraitOrientation = resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE - binding.bottomNavBar.root.visibility = if (!portraitOrientation || !keyboardVisible) View.VISIBLE else View.GONE - } + initBottomNavBar(binding.bottomNavBar.root) - sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i( - "$TAG Default account changed, updating avatar in top bar & refreshing contacts list" - ) - listViewModel.update() - listViewModel.applyCurrentDefaultAccountFilter() - } - } + initSlidingPane(binding.slidingPaneLayout) + + initNavigation(R.id.contactsListFragment) } private fun configureAdapter(adapter: ContactsListAdapter) { diff --git a/app/src/main/java/org/linphone/ui/main/fragment/AbstractTopBarFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/AbstractTopBarFragment.kt index 90706385c..105dde48d 100644 --- a/app/src/main/java/org/linphone/ui/main/fragment/AbstractTopBarFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/fragment/AbstractTopBarFragment.kt @@ -19,17 +19,73 @@ */ package org.linphone.ui.main.fragment +import android.content.res.Configuration +import android.view.View +import androidx.annotation.IdRes import androidx.annotation.UiThread +import androidx.core.view.doOnPreDraw +import androidx.navigation.NavDirections +import androidx.navigation.fragment.findNavController +import androidx.slidingpanelayout.widget.SlidingPaneLayout import com.google.android.material.textfield.TextInputLayout import org.linphone.R +import org.linphone.core.tools.Log import org.linphone.ui.main.MainActivity +import org.linphone.ui.main.chat.fragment.ConversationsListFragmentDirections +import org.linphone.ui.main.contacts.fragment.ContactsListFragmentDirections +import org.linphone.ui.main.history.fragment.HistoryListFragmentDirections +import org.linphone.ui.main.meetings.fragment.MeetingsListFragmentDirections import org.linphone.ui.main.viewmodel.AbstractTopBarViewModel -import org.linphone.utils.Event +import org.linphone.utils.SlidingPaneBackPressedCallback import org.linphone.utils.hideKeyboard +import org.linphone.utils.setKeyboardInsetListener import org.linphone.utils.showKeyboard @UiThread abstract class AbstractTopBarFragment : GenericFragment() { + companion object { + private const val TAG = "[Abstract TobBar Fragment]" + } + + private var currentFragmentId: Int = 0 + + abstract fun onDefaultAccountChanged() + + fun initSlidingPane(slidingPane: SlidingPaneLayout) { + view?.doOnPreDraw { + slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED + + sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable + + requireActivity().onBackPressedDispatcher.addCallback( + viewLifecycleOwner, + SlidingPaneBackPressedCallback(slidingPane) + ) + } + + sharedViewModel.closeSlidingPaneEvent.observe( + viewLifecycleOwner + ) { + it.consume { + if (slidingPane.isOpen) { + Log.i("$TAG Closing sliding pane") + slidingPane.closePane() + } + } + } + + sharedViewModel.openSlidingPaneEvent.observe( + viewLifecycleOwner + ) { + it.consume { + if (!slidingPane.isOpen) { + Log.i("$TAG Opening sliding pane") + slidingPane.openPane() + } + } + } + } + fun setViewModelAndTitle( searchBar: TextInputLayout, viewModel: AbstractTopBarViewModel, @@ -59,34 +115,42 @@ abstract class AbstractTopBarFragment : GenericFragment() { } viewModel.navigateToContactsEvent.observe(viewLifecycleOwner) { - if (sharedViewModel.currentlyDisplayedFragment.value != R.id.contactsFragment) { - sharedViewModel.navigateToContactsEvent.value = Event(true) + it.consume { + if (currentFragmentId != R.id.contactsListFragment) { + goToContactsList() + } } } viewModel.navigateToHistoryEvent.observe(viewLifecycleOwner) { - if (sharedViewModel.currentlyDisplayedFragment.value != R.id.historyFragment) { - sharedViewModel.navigateToHistoryEvent.value = Event(true) + it.consume { + if (currentFragmentId != R.id.historyListFragment) { + goToHistoryList() + } } } viewModel.navigateToConversationsEvent.observe(viewLifecycleOwner) { - if (sharedViewModel.currentlyDisplayedFragment.value != R.id.conversationsFragment) { - sharedViewModel.navigateToConversationsEvent.value = Event(true) + it.consume { + if (currentFragmentId != R.id.conversationsListFragment) { + goToConversationsList() + } } } viewModel.navigateToMeetingsEvent.observe(viewLifecycleOwner) { - if (sharedViewModel.currentlyDisplayedFragment.value != R.id.meetingsFragment) { - sharedViewModel.navigateToMeetingsEvent.value = Event(true) + it.consume { + if (currentFragmentId != R.id.meetingsListFragment) { + goToMeetingsList() + } } } sharedViewModel.currentlyDisplayedFragment.observe(viewLifecycleOwner) { - viewModel.contactsSelected.value = it == R.id.contactsFragment - viewModel.callsSelected.value = it == R.id.historyFragment - viewModel.conversationsSelected.value = it == R.id.conversationsFragment - viewModel.meetingsSelected.value = it == R.id.meetingsFragment + viewModel.contactsSelected.value = it == R.id.contactsListFragment + viewModel.callsSelected.value = it == R.id.historyListFragment + viewModel.conversationsSelected.value = it == R.id.conversationsListFragment + viewModel.meetingsSelected.value = it == R.id.meetingsListFragment } sharedViewModel.resetMissedCallsCountEvent.observe(viewLifecycleOwner) { @@ -96,8 +160,146 @@ abstract class AbstractTopBarFragment : GenericFragment() { } sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { - // Do not consume it! - viewModel.updateAvailableMenus() + it.consume { + Log.i("$TAG Default account changed") + viewModel.updateAvailableMenus() + onDefaultAccountChanged() + } + } + } + + fun initBottomNavBar(navBar: View) { + view?.setKeyboardInsetListener { keyboardVisible -> + val portraitOrientation = resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE + navBar.visibility = if (!portraitOrientation || !keyboardVisible) View.VISIBLE else View.GONE + } + } + + fun initNavigation(@IdRes fragmentId: Int) { + currentFragmentId = fragmentId + + sharedViewModel.navigateToContactsEvent.observe(viewLifecycleOwner) { + it.consume { + goToContactsList() + } + } + + sharedViewModel.navigateToHistoryEvent.observe(viewLifecycleOwner) { + it.consume { + goToHistoryList() + } + } + + sharedViewModel.navigateToConversationsEvent.observe(viewLifecycleOwner) { + it.consume { + goToConversationsList() + } + } + + sharedViewModel.navigateToMeetingsEvent.observe(viewLifecycleOwner) { + it.consume { + goToMeetingsList() + } + } + } + + override fun onResume() { + super.onResume() + + if (currentFragmentId > 0) { + sharedViewModel.currentlyDisplayedFragment.value = currentFragmentId + } + } + + private fun goToContactsList() { + Log.i("$TAG Navigating to contacts list") + when (currentFragmentId) { + R.id.conversationsListFragment -> { + Log.i("$TAG Leaving conversations list") + val action = ConversationsListFragmentDirections.actionConversationsListFragmentToContactsListFragment() + navigateTo(action) + } + R.id.meetingsListFragment -> { + Log.i("$TAG Leaving meetings list") + val action = MeetingsListFragmentDirections.actionMeetingsListFragmentToContactsListFragment() + navigateTo(action) + } + R.id.historyListFragment -> { + Log.i("$TAG Leaving history list") + val action = HistoryListFragmentDirections.actionHistoryListFragmentToContactsListFragment() + navigateTo(action) + } + } + } + + private fun goToHistoryList() { + Log.i("$TAG Navigating to history list") + when (currentFragmentId) { + R.id.conversationsListFragment -> { + Log.i("$TAG Leaving conversations list") + val action = ConversationsListFragmentDirections.actionConversationsListFragmentToHistoryListFragment() + navigateTo(action) + } + R.id.contactsListFragment -> { + Log.i("$TAG Leaving contacts list") + val action = ContactsListFragmentDirections.actionContactsListFragmentToHistoryListFragment() + navigateTo(action) + } + R.id.meetingsListFragment -> { + Log.i("$TAG Leaving meetings list") + val action = MeetingsListFragmentDirections.actionMeetingsListFragmentToHistoryListFragment() + navigateTo(action) + } + } + } + + private fun goToConversationsList() { + Log.i("$TAG Navigating to conversations list") + when (currentFragmentId) { + R.id.contactsListFragment -> { + Log.i("$TAG Leaving contacts list") + val action = ContactsListFragmentDirections.actionContactsListFragmentToConversationsListFragment() + navigateTo(action) + } + R.id.meetingsListFragment -> { + Log.i("$TAG Leaving meetings list") + val action = MeetingsListFragmentDirections.actionMeetingsListFragmentToConversationsListFragment() + navigateTo(action) + } + R.id.historyListFragment -> { + Log.i("$TAG Leaving history list") + val action = HistoryListFragmentDirections.actionHistoryListFragmentToConversationsListFragment() + navigateTo(action) + } + } + } + + private fun goToMeetingsList() { + Log.i("$TAG Navigating to meetings list") + when (currentFragmentId) { + R.id.conversationsListFragment -> { + Log.i("$TAG Leaving conversations list") + val action = ConversationsListFragmentDirections.actionConversationsListFragmentToMeetingsListFragment() + navigateTo(action) + } + R.id.contactsListFragment -> { + Log.i("$TAG Leaving contacts list") + val action = ContactsListFragmentDirections.actionContactsListFragmentToMeetingsListFragment() + navigateTo(action) + } + R.id.historyListFragment -> { + Log.i("$TAG Leaving history list") + val action = HistoryListFragmentDirections.actionHistoryListFragmentToMeetingsListFragment() + navigateTo(action) + } + } + } + + private fun navigateTo(action: NavDirections) { + try { + findNavController().navigate(action) + } catch (e: Exception) { + Log.e("$TAG Failed to navigate: $e") } } } diff --git a/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryFragment.kt b/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryFragment.kt deleted file mode 100644 index 26374a30e..000000000 --- a/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryFragment.kt +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (c) 2010-2023 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.linphone.ui.main.history.fragment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.AnimationUtils -import androidx.annotation.UiThread -import androidx.core.view.doOnPreDraw -import androidx.navigation.findNavController -import androidx.navigation.fragment.findNavController -import androidx.slidingpanelayout.widget.SlidingPaneLayout -import org.linphone.R -import org.linphone.core.tools.Log -import org.linphone.databinding.HistoryFragmentBinding -import org.linphone.ui.main.fragment.GenericFragment -import org.linphone.utils.SlidingPaneBackPressedCallback - -@UiThread -class HistoryFragment : GenericFragment() { - companion object { - private const val TAG = "[Calls Fragment]" - } - - private lateinit var binding: HistoryFragmentBinding - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - binding = HistoryFragmentBinding.inflate(layoutInflater) - return binding.root - } - - override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { - if (findNavController().currentDestination?.id == R.id.startCallFragment) { - // Holds fragment in place while new contact fragment slides over it - return AnimationUtils.loadAnimation(activity, R.anim.hold) - } - return super.onCreateAnimation(transit, enter, nextAnim) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - postponeEnterTransition() - super.onViewCreated(view, savedInstanceState) - - binding.lifecycleOwner = viewLifecycleOwner - - binding.root.doOnPreDraw { - val slidingPane = binding.slidingPaneLayout - slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED - - sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable - - requireActivity().onBackPressedDispatcher.addCallback( - viewLifecycleOwner, - SlidingPaneBackPressedCallback(slidingPane) - ) - } - - sharedViewModel.historyReadyEvent.observe(viewLifecycleOwner) { - it.consume { - (view.parent as? ViewGroup)?.doOnPreDraw { - startPostponedEnterTransition() - sharedViewModel.isFirstFragmentReady = true - } - } - } - - sharedViewModel.closeSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Closing sliding pane") - binding.slidingPaneLayout.closePane() - } - } - } - - sharedViewModel.openSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (!binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Opening sliding pane") - binding.slidingPaneLayout.openPane() - } - } - } - - sharedViewModel.showStartCallEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i("$TAG Navigating to start call fragment") - val action = HistoryFragmentDirections.actionHistoryFragmentToStartCallFragment() - findNavController().navigate(action) - } - } - - sharedViewModel.showCallLogEvent.observe( - viewLifecycleOwner - ) { - it.consume { callId -> - Log.i("$TAG Displaying call log with call ID [$callId]") - val navController = binding.historyNavContainer.findNavController() - val action = HistoryContactFragmentDirections.actionGlobalHistoryContactFragment( - callId - ) - navController.navigate(action) - } - } - - sharedViewModel.navigateToContactsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.historyFragment) { - // To prevent any previously seen call log to show up when navigating back to here later - binding.historyNavContainer.findNavController().popBackStack() - - val action = HistoryFragmentDirections.actionHistoryFragmentToContactsFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToConversationsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.historyFragment) { - // To prevent any previously seen call log to show up when navigating back to here later - binding.historyNavContainer.findNavController().popBackStack() - - val action = HistoryFragmentDirections.actionHistoryFragmentToConversationsFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToMeetingsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.historyFragment) { - // To prevent any previously seen call log to show up when navigating back to here later - binding.historyNavContainer.findNavController().popBackStack() - - val action = HistoryFragmentDirections.actionHistoryFragmentToMeetingsFragment() - findNavController().navigate(action) - } - } - } - } - - override fun onResume() { - super.onResume() - sharedViewModel.currentlyDisplayedFragment.value = R.id.historyFragment - } -} diff --git a/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryListFragment.kt b/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryListFragment.kt index 1a3ca6448..0f4609407 100644 --- a/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/history/fragment/HistoryListFragment.kt @@ -22,17 +22,20 @@ package org.linphone.ui.main.history.fragment import android.content.ClipData import android.content.ClipboardManager import android.content.Context -import android.content.res.Configuration import android.os.Bundle import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.Animation +import android.view.animation.AnimationUtils import android.widget.PopupWindow import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.databinding.DataBindingUtil import androidx.lifecycle.ViewModelProvider +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R @@ -46,7 +49,6 @@ import org.linphone.ui.main.history.model.ConfirmationDialogModel import org.linphone.ui.main.history.viewmodel.HistoryListViewModel import org.linphone.utils.DialogUtils import org.linphone.utils.Event -import org.linphone.utils.setKeyboardInsetListener @UiThread class HistoryListFragment : AbstractTopBarFragment() { @@ -60,6 +62,22 @@ class HistoryListFragment : AbstractTopBarFragment() { private lateinit var adapter: HistoryListAdapter + override fun onDefaultAccountChanged() { + Log.i( + "$TAG Default account changed, updating avatar in top bar & re-computing call logs" + ) + listViewModel.update() + listViewModel.applyFilter() + } + + override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { + if (findNavController().currentDestination?.id == R.id.startCallFragment) { + // Holds fragment in place while new contact fragment slides over it + return AnimationUtils.loadAnimation(activity, R.anim.hold) + } + return super.onCreateAnimation(transit, enter, nextAnim) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -130,8 +148,14 @@ class HistoryListFragment : AbstractTopBarFragment() { adapter.callLogClickedEvent.observe(viewLifecycleOwner) { it.consume { model -> - Log.i("$TAG Show details for call log with ID [${model.id}]") - sharedViewModel.showCallLogEvent.value = Event(model.id ?: "") + val uri = model.id + Log.i("$TAG Show details for call log with ID [$uri]") + if (!uri.isNullOrEmpty()) { + val navController = binding.historyNavContainer.findNavController() + val action = + HistoryContactFragmentDirections.actionGlobalHistoryContactFragment(uri) + navController.navigate(action) + } } } @@ -155,7 +179,7 @@ class HistoryListFragment : AbstractTopBarFragment() { (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() - sharedViewModel.historyReadyEvent.value = Event(true) + sharedViewModel.isFirstFragmentReady = true } } @@ -180,7 +204,12 @@ class HistoryListFragment : AbstractTopBarFragment() { } binding.setStartCallClickListener { - sharedViewModel.showStartCallEvent.value = Event(true) + if (findNavController().currentDestination?.id == R.id.historyListFragment) { + Log.i("$TAG Navigating to start call fragment") + val action = + HistoryListFragmentDirections.actionHistoryListFragmentToStartCallFragment() + findNavController().navigate(action) + } } // TopBarFragment related @@ -191,20 +220,11 @@ class HistoryListFragment : AbstractTopBarFragment() { getString(R.string.bottom_navigation_calls_label) ) - binding.root.setKeyboardInsetListener { keyboardVisible -> - val portraitOrientation = resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE - binding.bottomNavBar.root.visibility = if (!portraitOrientation || !keyboardVisible) View.VISIBLE else View.GONE - } + initBottomNavBar(binding.bottomNavBar.root) - sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i( - "$TAG Default account changed, updating avatar in top bar & re-computing call logs" - ) - listViewModel.update() - listViewModel.applyFilter() - } - } + initSlidingPane(binding.slidingPaneLayout) + + initNavigation(R.id.historyListFragment) } override fun onResume() { diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt index caffb64d0..83512dedb 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingFragment.kt @@ -66,7 +66,7 @@ class MeetingFragment : GenericFragment() { override fun goBack(): Boolean { sharedViewModel.closeSlidingPaneEvent.value = Event(true) - // If not done, when going back to ConversationsFragment this fragment will be created again + // If not done, when going back to MeetingsListFragment this fragment will be created again return findNavController().popBackStack() } diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsFragment.kt deleted file mode 100644 index c6133b063..000000000 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsFragment.kt +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2010-2023 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.linphone.ui.main.meetings.fragment - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.animation.Animation -import android.view.animation.AnimationUtils -import androidx.annotation.UiThread -import androidx.core.view.doOnPreDraw -import androidx.navigation.findNavController -import androidx.navigation.fragment.findNavController -import androidx.slidingpanelayout.widget.SlidingPaneLayout -import org.linphone.R -import org.linphone.core.tools.Log -import org.linphone.databinding.MeetingsFragmentBinding -import org.linphone.ui.main.fragment.GenericFragment -import org.linphone.utils.SlidingPaneBackPressedCallback - -@UiThread -class MeetingsFragment : GenericFragment() { - companion object { - private const val TAG = "[Meetings Fragment]" - } - - private lateinit var binding: MeetingsFragmentBinding - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - binding = MeetingsFragmentBinding.inflate(layoutInflater) - return binding.root - } - - override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { - if ( - findNavController().currentDestination?.id == R.id.scheduleMeetingFragment || - findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment - ) { - // Holds fragment in place while new contact fragment slides over it - return AnimationUtils.loadAnimation(activity, R.anim.hold) - } - return super.onCreateAnimation(transit, enter, nextAnim) - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - postponeEnterTransition() - super.onViewCreated(view, savedInstanceState) - - binding.lifecycleOwner = viewLifecycleOwner - - binding.root.doOnPreDraw { - val slidingPane = binding.slidingPaneLayout - slidingPane.lockMode = SlidingPaneLayout.LOCK_MODE_LOCKED - - sharedViewModel.isSlidingPaneSlideable.value = slidingPane.isSlideable - - requireActivity().onBackPressedDispatcher.addCallback( - viewLifecycleOwner, - SlidingPaneBackPressedCallback(slidingPane) - ) - } - - sharedViewModel.meetingsReadyEvent.observe(viewLifecycleOwner) { - it.consume { - (view.parent as? ViewGroup)?.doOnPreDraw { - startPostponedEnterTransition() - sharedViewModel.isFirstFragmentReady = true - } - } - } - - sharedViewModel.closeSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Closing sliding pane") - binding.slidingPaneLayout.closePane() - } - } - } - - sharedViewModel.openSlidingPaneEvent.observe( - viewLifecycleOwner - ) { - it.consume { - if (!binding.slidingPaneLayout.isOpen) { - Log.i("$TAG Opening sliding pane") - binding.slidingPaneLayout.openPane() - } - } - } - - sharedViewModel.showScheduleMeetingEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i("$TAG Navigating to schedule meeting fragment") - val action = MeetingsFragmentDirections.actionMeetingsFragmentToScheduleMeetingFragment() - findNavController().navigate(action) - } - } - - sharedViewModel.goToMeetingWaitingRoomEvent.observe(viewLifecycleOwner) { - it.consume { uri -> - Log.i("$TAG Navigating to meeting waiting room fragment with URI [$uri]") - val action = MeetingsFragmentDirections.actionMeetingsFragmentToMeetingWaitingRoomFragment( - uri - ) - findNavController().navigate(action) - } - } - - sharedViewModel.showMeetingEvent.observe(viewLifecycleOwner) { - it.consume { uri -> - Log.i("$TAG Navigating to meeting fragment with URI [$uri]") - val action = MeetingFragmentDirections.actionGlobalMeetingFragment(uri) - binding.meetingsNavContainer.findNavController().navigate(action) - } - } - - sharedViewModel.navigateToContactsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.meetingsFragment) { - // To prevent any previously seen meeting to show up when navigating back to here later - binding.meetingsNavContainer.findNavController().popBackStack() - - val action = MeetingsFragmentDirections.actionMeetingsFragmentToContactsFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToHistoryEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.meetingsFragment) { - // To prevent any previously seen meeting to show up when navigating back to here later - binding.meetingsNavContainer.findNavController().popBackStack() - - val action = MeetingsFragmentDirections.actionMeetingsFragmentToHistoryFragment() - findNavController().navigate(action) - } - } - } - - sharedViewModel.navigateToConversationsEvent.observe(viewLifecycleOwner) { - it.consume { - if (findNavController().currentDestination?.id == R.id.meetingsFragment) { - // To prevent any previously seen meeting to show up when navigating back to here later - binding.meetingsNavContainer.findNavController().popBackStack() - - val action = MeetingsFragmentDirections.actionMeetingsFragmentToConversationsFragment() - findNavController().navigate(action) - } - } - } - } - - override fun onResume() { - super.onResume() - sharedViewModel.currentlyDisplayedFragment.value = R.id.meetingsFragment - } -} diff --git a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt index 8b0f3497d..f14bad2ca 100644 --- a/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/meetings/fragment/MeetingsListFragment.kt @@ -19,14 +19,17 @@ */ package org.linphone.ui.main.meetings.fragment -import android.content.res.Configuration import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.view.animation.Animation +import android.view.animation.AnimationUtils import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider +import androidx.navigation.findNavController +import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import org.linphone.R import org.linphone.core.tools.Log @@ -35,9 +38,7 @@ import org.linphone.ui.main.fragment.AbstractTopBarFragment import org.linphone.ui.main.meetings.adapter.MeetingsListAdapter import org.linphone.ui.main.meetings.viewmodel.MeetingsListViewModel import org.linphone.utils.AppUtils -import org.linphone.utils.Event import org.linphone.utils.RecyclerViewHeaderDecoration -import org.linphone.utils.setKeyboardInsetListener @UiThread class MeetingsListFragment : AbstractTopBarFragment() { @@ -51,6 +52,24 @@ class MeetingsListFragment : AbstractTopBarFragment() { private lateinit var adapter: MeetingsListAdapter + override fun onDefaultAccountChanged() { + Log.i( + "$TAG Default account changed, updating avatar in top bar & re-computing meetings list" + ) + listViewModel.applyFilter() + } + + override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { + if ( + findNavController().currentDestination?.id == R.id.scheduleMeetingFragment || + findNavController().currentDestination?.id == R.id.meetingWaitingRoomFragment + ) { + // Holds fragment in place while new contact fragment slides over it + return AnimationUtils.loadAnimation(activity, R.anim.hold) + } + return super.onCreateAnimation(transit, enter, nextAnim) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -78,7 +97,12 @@ class MeetingsListFragment : AbstractTopBarFragment() { binding.meetingsList.layoutManager = LinearLayoutManager(requireContext()) binding.setNewMeetingClicked { - sharedViewModel.showScheduleMeetingEvent.value = Event(true) + if (findNavController().currentDestination?.id == R.id.meetingsListFragment) { + Log.i("$TAG Navigating to schedule meeting fragment") + val action = + MeetingsListFragmentDirections.actionMeetingsListFragmentToScheduleMeetingFragment() + findNavController().navigate(action) + } } binding.setTodayClickListener { @@ -88,7 +112,8 @@ class MeetingsListFragment : AbstractTopBarFragment() { adapter.meetingClickedEvent.observe(viewLifecycleOwner) { it.consume { model -> Log.i("$TAG Show conversation with ID [${model.id}]") - sharedViewModel.showMeetingEvent.value = Event(model.id) + val action = MeetingFragmentDirections.actionGlobalMeetingFragment(model.id) + binding.meetingsNavContainer.findNavController().navigate(action) } } @@ -100,7 +125,7 @@ class MeetingsListFragment : AbstractTopBarFragment() { if (currentCount < it.size) { (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() - sharedViewModel.meetingsReadyEvent.value = Event(true) + sharedViewModel.isFirstFragmentReady = true scrollToToday() } } @@ -113,6 +138,19 @@ class MeetingsListFragment : AbstractTopBarFragment() { } } + sharedViewModel.goToMeetingWaitingRoomEvent.observe(viewLifecycleOwner) { + it.consume { uri -> + if (findNavController().currentDestination?.id == R.id.meetingsListFragment) { + Log.i("$TAG Navigating to meeting waiting room fragment with URI [$uri]") + val action = + MeetingsListFragmentDirections.actionMeetingsListFragmentToMeetingWaitingRoomFragment( + uri + ) + findNavController().navigate(action) + } + } + } + // TopBarFragment related setViewModelAndTitle( @@ -121,19 +159,11 @@ class MeetingsListFragment : AbstractTopBarFragment() { getString(R.string.bottom_navigation_meetings_label) ) - binding.root.setKeyboardInsetListener { keyboardVisible -> - val portraitOrientation = resources.configuration.orientation != Configuration.ORIENTATION_LANDSCAPE - binding.bottomNavBar.root.visibility = if (!portraitOrientation || !keyboardVisible) View.VISIBLE else View.GONE - } + initBottomNavBar(binding.bottomNavBar.root) - sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { - it.consume { - Log.i( - "$TAG Default account changed, updating avatar in top bar & re-computing meetings list" - ) - listViewModel.applyFilter() - } - } + initSlidingPane(binding.slidingPaneLayout) + + initNavigation(R.id.meetingsListFragment) } private fun scrollToToday() { diff --git a/app/src/main/java/org/linphone/ui/main/viewmodel/SharedMainViewModel.kt b/app/src/main/java/org/linphone/ui/main/viewmodel/SharedMainViewModel.kt index f1127ffdd..6bc11c5d7 100644 --- a/app/src/main/java/org/linphone/ui/main/viewmodel/SharedMainViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/viewmodel/SharedMainViewModel.kt @@ -76,8 +76,6 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() { /* Contacts related */ - val contactsReadyEvent = MutableLiveData>() - val showContactEvent: MutableLiveData> by lazy { MutableLiveData>() } @@ -90,16 +88,6 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() { /* Call logs related */ - val historyReadyEvent = MutableLiveData>() - - val showStartCallEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - - val showCallLogEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - val forceRefreshCallLogsListEvent: MutableLiveData> by lazy { MutableLiveData>() } @@ -110,12 +98,6 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() { /* Conversation related */ - val conversationsReadyEvent = MutableLiveData>() - - val showStartConversationEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - val filesToShareFromIntent = MutableLiveData>() var displayedChatRoom: ChatRoom? = null // Prevents the need to go look for the chat room @@ -128,16 +110,6 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() { /* Meetings related */ - val meetingsReadyEvent = MutableLiveData>() - - val showScheduleMeetingEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - - val showMeetingEvent: MutableLiveData> by lazy { - MutableLiveData>() - } - val forceRefreshMeetingsListEvent: MutableLiveData> by lazy { MutableLiveData>() } diff --git a/app/src/main/res/layout-land/chat_list_fragment.xml b/app/src/main/res/layout-land/chat_list_fragment.xml index 01248af56..216b9cc34 100644 --- a/app/src/main/res/layout-land/chat_list_fragment.xml +++ b/app/src/main/res/layout-land/chat_list_fragment.xml @@ -16,107 +16,123 @@ type="org.linphone.ui.main.chat.viewmodel.ConversationsListViewModel" /> - - + android:layout_height="match_parent"> - - - + android:background="@color/orange_main_500"> - + - + - + - + - + - + - + - + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/contacts_list_fragment.xml b/app/src/main/res/layout-land/contacts_list_fragment.xml index 4b1813777..6e252c324 100644 --- a/app/src/main/res/layout-land/contacts_list_fragment.xml +++ b/app/src/main/res/layout-land/contacts_list_fragment.xml @@ -16,162 +16,178 @@ type="org.linphone.ui.main.contacts.viewmodel.ContactsListViewModel" /> - - + android:layout_height="match_parent"> - - - + android:background="@color/orange_main_500"> - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-land/history_list_fragment.xml b/app/src/main/res/layout-land/history_list_fragment.xml index 18cb55905..ffd272aba 100644 --- a/app/src/main/res/layout-land/history_list_fragment.xml +++ b/app/src/main/res/layout-land/history_list_fragment.xml @@ -22,120 +22,136 @@ type="org.linphone.ui.main.history.viewmodel.HistoryListViewModel" /> - - + android:layout_height="match_parent"> - - - + android:background="@color/orange_main_500"> + + + + + + + + + + + + + + + + + + + + + layout="@layout/operation_in_progress" + bind:visibility="@{viewModel.fetchInProgress}" /> - + - + - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout-land/meetings_list_fragment.xml b/app/src/main/res/layout-land/meetings_list_fragment.xml index ba2b7629c..5c01d8ed4 100644 --- a/app/src/main/res/layout-land/meetings_list_fragment.xml +++ b/app/src/main/res/layout-land/meetings_list_fragment.xml @@ -19,120 +19,136 @@ type="org.linphone.ui.main.meetings.viewmodel.MeetingsListViewModel" /> - - + android:layout_height="match_parent"> - - - + android:background="@color/orange_main_500"> - + - + - + - + - + - + - + - + - + - + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/chat_fragment.xml b/app/src/main/res/layout/chat_fragment.xml deleted file mode 100644 index c842ffcc0..000000000 --- a/app/src/main/res/layout/chat_fragment.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/chat_list_fragment.xml b/app/src/main/res/layout/chat_list_fragment.xml index 0d2287a2d..d2764a69b 100644 --- a/app/src/main/res/layout/chat_list_fragment.xml +++ b/app/src/main/res/layout/chat_list_fragment.xml @@ -16,107 +16,123 @@ type="org.linphone.ui.main.chat.viewmodel.ConversationsListViewModel" /> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/chat_nav_graph"/> - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/contacts_fragment.xml b/app/src/main/res/layout/contacts_fragment.xml deleted file mode 100644 index 62ffef7f3..000000000 --- a/app/src/main/res/layout/contacts_fragment.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/contacts_list_fragment.xml b/app/src/main/res/layout/contacts_list_fragment.xml index 48783f863..8a89d2924 100644 --- a/app/src/main/res/layout/contacts_list_fragment.xml +++ b/app/src/main/res/layout/contacts_list_fragment.xml @@ -16,164 +16,180 @@ type="org.linphone.ui.main.contacts.viewmodel.ContactsListViewModel" /> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/contacts_nav_graph"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/history_fragment.xml b/app/src/main/res/layout/history_fragment.xml deleted file mode 100644 index b31826fac..000000000 --- a/app/src/main/res/layout/history_fragment.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/history_list_fragment.xml b/app/src/main/res/layout/history_list_fragment.xml index d8b55aa5b..f89116411 100644 --- a/app/src/main/res/layout/history_list_fragment.xml +++ b/app/src/main/res/layout/history_list_fragment.xml @@ -22,120 +22,136 @@ type="org.linphone.ui.main.history.viewmodel.HistoryListViewModel" /> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/history_nav_graph"/> - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/app/src/main/res/layout/meetings_fragment.xml b/app/src/main/res/layout/meetings_fragment.xml deleted file mode 100644 index 9ce57120b..000000000 --- a/app/src/main/res/layout/meetings_fragment.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/meetings_list_fragment.xml b/app/src/main/res/layout/meetings_list_fragment.xml index 74f0dcedd..41ad2e65e 100644 --- a/app/src/main/res/layout/meetings_list_fragment.xml +++ b/app/src/main/res/layout/meetings_list_fragment.xml @@ -19,120 +19,136 @@ type="org.linphone.ui.main.meetings.viewmodel.MeetingsListViewModel" /> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + android:layout_weight="1" + app:defaultNavHost="false" + app:navGraph="@navigation/meetings_nav_graph"/> - - - - - - - - - - - - - - - - - - - - - - - + \ 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 a461b8a87..72fe2929a 100644 --- a/app/src/main/res/navigation/main_nav_graph.xml +++ b/app/src/main/res/navigation/main_nav_graph.xml @@ -1,36 +1,35 @@ - + app:startDestination="@id/historyListFragment"> + android:id="@+id/contactsListFragment" + android:name="org.linphone.ui.main.contacts.fragment.ContactsListFragment" + android:label="ContactsListFragment" + tools:layout="@layout/contacts_list_fragment"> + android:id="@+id/historyListFragment" + android:name="org.linphone.ui.main.history.fragment.HistoryListFragment" + android:label="HistoryListFragment" + tools:layout="@layout/history_list_fragment"> + android:id="@+id/conversationsListFragment" + android:name="org.linphone.ui.main.chat.fragment.ConversationsListFragment" + android:label="ConversationsListFragment" + tools:layout="@layout/chat_list_fragment" > + android:id="@+id/meetingsListFragment" + android:name="org.linphone.ui.main.meetings.fragment.MeetingsListFragment" + android:label="MeetingsListFragment" + tools:layout="@layout/meetings_list_fragment"> - - 450dp - 0dp - 110dp 125dp 235dp diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index 0cdc33642..05290e043 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -5,7 +5,6 @@ 32dp 75dp - 300dp 300dp 14dp