From 29a47b87cd55133608b0ee91505b46ecfa46ebc1 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 6 Sep 2023 16:10:03 +0200 Subject: [PATCH] Made accounts switch work --- .../assets/assistant_linphone_default_values | 10 -- .../assistant_third_party_default_values | 17 -- .../ThirdPartySipAccountLoginFragment.kt | 1 - .../java/org/linphone/ui/main/MainActivity.kt | 95 ++--------- .../main/calls/fragment/CallsListFragment.kt | 10 ++ .../contacts/fragment/ContactsListFragment.kt | 10 ++ .../viewmodel/ContactsListViewModel.kt | 2 +- .../ui/main/fragment/DrawerMenuFragment.kt | 151 ++++++++++++++++++ .../linphone/ui/main/model/AccountModel.kt | 10 +- .../main/viewmodel/AbstractTopBarViewModel.kt | 23 ++- .../ui/main/viewmodel/DrawerMenuViewModel.kt | 22 ++- .../ui/main/viewmodel/SharedMainViewModel.kt | 4 + app/src/main/res/layout/main_activity.xml | 27 +--- 13 files changed, 226 insertions(+), 156 deletions(-) create mode 100644 app/src/main/java/org/linphone/ui/main/fragment/DrawerMenuFragment.kt diff --git a/app/src/main/assets/assistant_linphone_default_values b/app/src/main/assets/assistant_linphone_default_values index 613e3109c..f3723d7a9 100644 --- a/app/src/main/assets/assistant_linphone_default_values +++ b/app/src/main/assets/assistant_linphone_default_values @@ -33,14 +33,4 @@
1
-
- sip.linphone.org - SHA-256 - -1 - 1 - -1 - 64 - 1 - ^[a-z0-9+_.\-]*$ -
diff --git a/app/src/main/assets/assistant_third_party_default_values b/app/src/main/assets/assistant_third_party_default_values index 5800203a4..78927cf4e 100644 --- a/app/src/main/assets/assistant_third_party_default_values +++ b/app/src/main/assets/assistant_third_party_default_values @@ -22,21 +22,4 @@ 0 -
- - -
-
- 0 -
-
- - MD5 - -1 - 0 - -1 - 128 - 1 - ^[a-zA-Z0-9+_.\-]*$ -
diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountLoginFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountLoginFragment.kt index ded2b1265..0f21741a2 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountLoginFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountLoginFragment.kt @@ -31,7 +31,6 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.navGraphViewModels import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import org.linphone.LinphoneApplication import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.core.tools.Log 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 fb0188b0f..a892c98c3 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -25,27 +25,18 @@ import android.content.Intent import android.content.pm.PackageManager import android.os.Bundle import android.view.Gravity -import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import android.widget.PopupWindow import androidx.annotation.DrawableRes import androidx.annotation.UiThread import androidx.appcompat.app.AppCompatActivity import androidx.core.view.WindowCompat import androidx.databinding.DataBindingUtil -import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope +import androidx.navigation.NavController import androidx.navigation.findNavController import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R -import org.linphone.core.Account -import org.linphone.databinding.AccountPopupMenuBinding import org.linphone.databinding.MainActivityBinding -import org.linphone.ui.assistant.AssistantActivity -import org.linphone.ui.main.settings.fragment.AccountProfileFragmentDirections -import org.linphone.ui.main.viewmodel.DrawerMenuViewModel import org.linphone.ui.welcome.WelcomeActivity import org.linphone.utils.slideInToastFromTopForDuration @@ -60,7 +51,6 @@ class MainActivity : AppCompatActivity() { } private lateinit var binding: MainActivityBinding - private lateinit var drawerMenuViewModel: DrawerMenuViewModel override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, true) @@ -78,48 +68,6 @@ class MainActivity : AppCompatActivity() { binding = DataBindingUtil.setContentView(this, R.layout.main_activity) binding.lifecycleOwner = this - - binding.setSettingsClickedListener { - val navController = findNavController(R.id.main_nav_host_fragment) - navController.navigate(R.id.action_global_settingsFragment) - binding.drawerMenu.close() - } - - binding.setRecordingsClickListener { - val navController = findNavController(R.id.main_nav_host_fragment) - navController.navigate(R.id.action_global_recordingsFragment) - binding.drawerMenu.close() - } - - binding.setHelpClickedListener { - val navController = findNavController(R.id.main_nav_host_fragment) - navController.navigate(R.id.action_global_helpFragment) - binding.drawerMenu.close() - } - - drawerMenuViewModel = run { - ViewModelProvider(this)[DrawerMenuViewModel::class.java] - } - binding.drawerMenuViewModel = drawerMenuViewModel - - drawerMenuViewModel.startAssistantEvent.observe(this) { - it.consume { - startActivity(Intent(baseContext, AssistantActivity::class.java)) - binding.drawerMenu.close() - } - } - - drawerMenuViewModel.closeDrawerEvent.observe(this) { - it.consume { - binding.drawerMenu.close() - } - } - - drawerMenuViewModel.showAccountPopupMenuEvent.observe(this) { - it.consume { pair -> - showAccountPopupMenu(pair.first, pair.second) - } - } } override fun onPostCreate(savedInstanceState: Bundle?) { @@ -174,12 +122,20 @@ class MainActivity : AppCompatActivity() { @SuppressLint("RtlHardcoded") fun toggleDrawerMenu() { if (binding.drawerMenu.isDrawerOpen(Gravity.LEFT)) { - binding.drawerMenu.closeDrawer(binding.drawerMenuContent, true) + closeDrawerMenu() } else { binding.drawerMenu.openDrawer(binding.drawerMenuContent, true) } } + fun closeDrawerMenu() { + binding.drawerMenu.closeDrawer(binding.drawerMenuContent, true) + } + + fun findNavController(): NavController { + return findNavController(R.id.main_nav_host_fragment) + } + fun showGreenToast(message: String, @DrawableRes icon: Int) { binding.greenToast.message = message binding.greenToast.icon = icon @@ -211,35 +167,4 @@ class MainActivity : AppCompatActivity() { } }*/ } - - private fun showAccountPopupMenu(view: View, account: Account) { - val popupView: AccountPopupMenuBinding = DataBindingUtil.inflate( - LayoutInflater.from(baseContext), - R.layout.account_popup_menu, - null, - false - ) - - val popupWindow = PopupWindow( - popupView.root, - WRAP_CONTENT, - WRAP_CONTENT, - true - ) - - popupView.setManageProfileClickListener { - val navController = findNavController(R.id.main_nav_host_fragment) - val identity = account.params.identityAddress?.asStringUriOnly().orEmpty() - val action = AccountProfileFragmentDirections.actionGlobalAccountProfileFragment( - identity - ) - navController.navigate(action) - popupWindow.dismiss() - binding.drawerMenu.close() - } - - // Elevation is for showing a shadow around the popup - popupWindow.elevation = 20f - popupWindow.showAsDropDown(view, 0, 0, Gravity.BOTTOM) - } } diff --git a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt index f89e00c47..fa5bcb640 100644 --- a/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/calls/fragment/CallsListFragment.kt @@ -189,6 +189,16 @@ class CallsListFragment : GenericFragment() { findNavController().navigate(R.id.action_global_startCallFragment) } + sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { + it.consume { + Log.i( + "$TAG Default account changed, updating avatar in top bar & re-computing call logs" + ) + listViewModel.updateDefaultAccount() + listViewModel.applyFilter() + } + } + // TopBarFragment related listViewModel.openDrawerMenuEvent.observe(viewLifecycleOwner) { 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 c14a090f7..1d7dd9542 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 @@ -148,6 +148,16 @@ class ContactsListFragment : GenericFragment() { listViewModel.toggleContactsFilter() } + sharedViewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { + it.consume { + Log.i( + "$TAG Default account changed, updating avatar in top bar & refreshing contacts list" + ) + listViewModel.updateDefaultAccount() + listViewModel.applyFilter() + } + } + // TopBarFragment related listViewModel.openDrawerMenuEvent.observe(viewLifecycleOwner) { diff --git a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt index fecc8c653..e6d9faa4d 100644 --- a/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/contacts/viewmodel/ContactsListViewModel.kt @@ -164,7 +164,7 @@ class ContactsListViewModel @UiThread constructor() : AbstractTopBarViewModel() } @UiThread - fun applyFilter(filter: String) { + fun applyFilter(filter: String = currentFilter) { isListFiltered.value = filter.isNotEmpty() coreContext.postOnCoreThread { applyFilter( diff --git a/app/src/main/java/org/linphone/ui/main/fragment/DrawerMenuFragment.kt b/app/src/main/java/org/linphone/ui/main/fragment/DrawerMenuFragment.kt new file mode 100644 index 000000000..87526b271 --- /dev/null +++ b/app/src/main/java/org/linphone/ui/main/fragment/DrawerMenuFragment.kt @@ -0,0 +1,151 @@ +/* + * 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.fragment + +import android.content.Intent +import android.os.Bundle +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.PopupWindow +import androidx.annotation.UiThread +import androidx.databinding.DataBindingUtil +import androidx.lifecycle.ViewModelProvider +import org.linphone.R +import org.linphone.core.Account +import org.linphone.core.tools.Log +import org.linphone.databinding.AccountPopupMenuBinding +import org.linphone.databinding.DrawerMenuBinding +import org.linphone.ui.assistant.AssistantActivity +import org.linphone.ui.main.MainActivity +import org.linphone.ui.main.settings.fragment.AccountProfileFragmentDirections +import org.linphone.ui.main.viewmodel.DrawerMenuViewModel +import org.linphone.utils.Event + +@UiThread +class DrawerMenuFragment : GenericFragment() { + companion object { + private const val TAG = "[Drawer Menu Fragment]" + } + + private lateinit var binding: DrawerMenuBinding + + private lateinit var viewModel: DrawerMenuViewModel + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = DrawerMenuBinding.inflate(layoutInflater) + return binding.root + } + + override fun goBack() { + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel = requireActivity().run { + ViewModelProvider(this)[DrawerMenuViewModel::class.java] + } + + binding.lifecycleOwner = viewLifecycleOwner + binding.viewModel = viewModel + + viewModel.startAssistantEvent.observe(viewLifecycleOwner) { + it.consume { + startActivity(Intent(requireContext(), AssistantActivity::class.java)) + (requireActivity() as MainActivity).closeDrawerMenu() + } + } + + viewModel.closeDrawerEvent.observe(viewLifecycleOwner) { + it.consume { + (requireActivity() as MainActivity).closeDrawerMenu() + } + } + + viewModel.showAccountPopupMenuEvent.observe(viewLifecycleOwner) { + it.consume { pair -> + showAccountPopupMenu(pair.first, pair.second) + } + } + + viewModel.defaultAccountChangedEvent.observe(viewLifecycleOwner) { + it.consume { identity -> + Log.w("$TAG Default account has changed, now is [$identity]") + sharedViewModel.defaultAccountChangedEvent.value = Event(true) + } + } + + binding.setSettingsClickedListener { + val navController = (requireActivity() as MainActivity).findNavController() + navController.navigate(R.id.action_global_settingsFragment) + (requireActivity() as MainActivity).closeDrawerMenu() + } + + binding.setRecordingsClickListener { + val navController = (requireActivity() as MainActivity).findNavController() + navController.navigate(R.id.action_global_recordingsFragment) + (requireActivity() as MainActivity).closeDrawerMenu() + } + + binding.setHelpClickedListener { + val navController = (requireActivity() as MainActivity).findNavController() + navController.navigate(R.id.action_global_helpFragment) + (requireActivity() as MainActivity).closeDrawerMenu() + } + } + + private fun showAccountPopupMenu(view: View, account: Account) { + val popupView: AccountPopupMenuBinding = DataBindingUtil.inflate( + LayoutInflater.from(requireContext()), + R.layout.account_popup_menu, + null, + false + ) + + val popupWindow = PopupWindow( + popupView.root, + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + true + ) + + popupView.setManageProfileClickListener { + val navController = (requireActivity() as MainActivity).findNavController() + val identity = account.params.identityAddress?.asStringUriOnly().orEmpty() + val action = AccountProfileFragmentDirections.actionGlobalAccountProfileFragment( + identity + ) + Log.i("$TAG Going to account [$identity] profile") + navController.navigate(action) + popupWindow.dismiss() + (requireActivity() as MainActivity).closeDrawerMenu() + } + + // Elevation is for showing a shadow around the popup + popupWindow.elevation = 20f + popupWindow.showAsDropDown(view, 0, 0, Gravity.BOTTOM) + } +} diff --git a/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt b/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt index c47a8aa40..c585271c1 100644 --- a/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt +++ b/app/src/main/java/org/linphone/ui/main/model/AccountModel.kt @@ -31,8 +31,9 @@ import org.linphone.core.tools.Log import org.linphone.utils.LinphoneUtils class AccountModel @WorkerThread constructor( - private val account: Account, - private val onMenuClicked: ((view: View, account: Account) -> Unit)? = null + val account: Account, + private val onMenuClicked: ((view: View, account: Account) -> Unit)? = null, + private val onSetAsDefault: ((account: Account) -> Unit)? = null ) { companion object { private const val TAG = "[Account Model]" @@ -85,8 +86,9 @@ class AccountModel @WorkerThread constructor( fun setAsDefault() { coreContext.postOnCoreThread { core -> core.defaultAccount = account - isDefault.postValue(true) } + isDefault.value = true + onSetAsDefault?.invoke(account) } @UiThread @@ -135,5 +137,5 @@ class AccountModel @WorkerThread constructor( fun Account.isInSecureMode(): Boolean { // TODO FIXME - return true + return params.identityAddress?.domain == "sip.linphone.org" } diff --git a/app/src/main/java/org/linphone/ui/main/viewmodel/AbstractTopBarViewModel.kt b/app/src/main/java/org/linphone/ui/main/viewmodel/AbstractTopBarViewModel.kt index b44d0853b..c64d6b727 100644 --- a/app/src/main/java/org/linphone/ui/main/viewmodel/AbstractTopBarViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/viewmodel/AbstractTopBarViewModel.kt @@ -20,7 +20,6 @@ package org.linphone.ui.main.viewmodel import androidx.annotation.UiThread -import androidx.annotation.WorkerThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import org.linphone.LinphoneApplication.Companion.coreContext @@ -52,11 +51,7 @@ open class AbstractTopBarViewModel @UiThread constructor() : ViewModel() { init { searchBarVisible.value = false - // TODO FIXME: update default account displayed here when uses clicks on another account - - coreContext.postOnCoreThread { - updateDefaultAccount() - } + updateDefaultAccount() } @UiThread @@ -91,14 +86,16 @@ open class AbstractTopBarViewModel @UiThread constructor() : ViewModel() { searchFilter.value = "" } - @WorkerThread - private fun updateDefaultAccount() { - Log.i("$TAG Updating displayed default account") + @UiThread + fun updateDefaultAccount() { + coreContext.postOnCoreThread { + Log.i("$TAG Updating displayed default account") - val core = coreContext.core - if (core.accountList.isNotEmpty()) { - val defaultAccount = core.defaultAccount ?: core.accountList.first() - account.postValue(AccountModel(defaultAccount)) + val core = coreContext.core + if (core.accountList.isNotEmpty()) { + val defaultAccount = core.defaultAccount ?: core.accountList.first() + account.postValue(AccountModel(defaultAccount)) + } } } } diff --git a/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt b/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt index a61b5f2a0..546c196b9 100644 --- a/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/viewmodel/DrawerMenuViewModel.kt @@ -49,6 +49,10 @@ class DrawerMenuViewModel @UiThread constructor() : ViewModel() { MutableLiveData>>() } + val defaultAccountChangedEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + init { // TODO FIXME: update accounts list when a new account is added or when removing one coreContext.postOnCoreThread { @@ -80,9 +84,23 @@ class DrawerMenuViewModel @UiThread constructor() : ViewModel() { val list = arrayListOf() for (account in coreContext.core.accountList) { - val model = AccountModel(account) { view, account -> + val model = AccountModel(account, { view, account -> + // onClicked showAccountPopupMenuEvent.postValue(Event(Pair(view, account))) - } + }, { account -> + // onSetAsDefault + Log.i( + "$TAG Account [${account.params.identityAddress?.asStringUriOnly()}] has been set as default by user" + ) + for (model in accounts.value.orEmpty()) { + if (model.account != account) { + model.isDefault.value = false + } + } + defaultAccountChangedEvent.postValue( + Event(account.params.identityAddress?.asStringUriOnly() ?: "") + ) + }) list.add(model) } accounts.postValue(list) 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 d6bd05c06..8528e4c8f 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 @@ -57,6 +57,10 @@ class SharedMainViewModel @UiThread constructor() : ViewModel() { MutableLiveData>() } + val defaultAccountChangedEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + /* Contacts related */ val contactsListReadyToBeDisplayedEvent = MutableLiveData>() diff --git a/app/src/main/res/layout/main_activity.xml b/app/src/main/res/layout/main_activity.xml index ba88f6fe7..6f45c19d0 100644 --- a/app/src/main/res/layout/main_activity.xml +++ b/app/src/main/res/layout/main_activity.xml @@ -5,18 +5,6 @@ - - - - - - - - - + android:layout_gravity="start" + app:layout="@layout/drawer_menu" />