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 72cb21e99..ba33e9fd6 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 @@ -41,6 +41,7 @@ import org.linphone.ui.GenericActivity import org.linphone.ui.GenericFragment import org.linphone.ui.assistant.viewmodel.ThirdPartySipAccountLoginViewModel import org.linphone.ui.main.sso.fragment.SingleSignOnFragmentDirections +import org.linphone.utils.DialogUtils import org.linphone.utils.PhoneNumberUtils @UiThread @@ -98,6 +99,10 @@ class ThirdPartySipAccountLoginFragment : GenericFragment() { goBack() } + binding.setOutboundProxyTooltipClickListener { + showOutboundProxyInfoDialog() + } + viewModel.showPassword.observe(viewLifecycleOwner) { lifecycleScope.launch { delay(50) @@ -159,4 +164,9 @@ class ThirdPartySipAccountLoginFragment : GenericFragment() { private fun goBack() { findNavController().popBackStack() } + + private fun showOutboundProxyInfoDialog() { + val dialog = DialogUtils.getAccountOutboundProxyHelpDialog(requireActivity()) + dialog.show() + } } diff --git a/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt b/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt index 1b7c62adf..1e0ffb9db 100644 --- a/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt +++ b/app/src/main/java/org/linphone/ui/assistant/viewmodel/ThirdPartySipAccountLoginViewModel.kt @@ -67,6 +67,8 @@ class ThirdPartySipAccountLoginViewModel val expandAdvancedSettings = MutableLiveData() + val proxy = MutableLiveData() + val outboundProxy = MutableLiveData() val loginEnabled = MediatorLiveData() @@ -236,8 +238,27 @@ class ThirdPartySipAccountLoginViewModel } accountParams.identityAddress = identityAddress + val proxyServerValue = proxy.value.orEmpty().trim() + val proxyServerAddress = if (proxyServerValue.isNotEmpty()) { + val server = if (proxyServerValue.startsWith("sip:")) { + proxyServerValue + } else { + "sip:$proxyServerValue" + } + Factory.instance().createAddress(server) + } else { + domainAddress ?: Factory.instance().createAddress("sip:$domainWithoutSip") + } + proxyServerAddress?.transport = when (transport.value.orEmpty().trim()) { + TransportType.Tcp.name.uppercase(Locale.getDefault()) -> TransportType.Tcp + TransportType.Tls.name.uppercase(Locale.getDefault()) -> TransportType.Tls + else -> TransportType.Udp + } + Log.i("$TAG Created proxy server SIP address [${proxyServerAddress?.asStringUriOnly()}]") + accountParams.serverAddress = proxyServerAddress + val outboundProxyValue = outboundProxy.value.orEmpty().trim() - val serverAddress = if (outboundProxyValue.isNotEmpty()) { + val outboundProxyAddress = if (outboundProxyValue.isNotEmpty()) { val server = if (outboundProxyValue.startsWith("sip:")) { outboundProxyValue } else { @@ -245,16 +266,17 @@ class ThirdPartySipAccountLoginViewModel } Factory.instance().createAddress(server) } else { - domainAddress ?: Factory.instance().createAddress("sip:$domainWithoutSip") + null } - - serverAddress?.transport = when (transport.value.orEmpty().trim()) { - TransportType.Tcp.name.uppercase(Locale.getDefault()) -> TransportType.Tcp - TransportType.Tls.name.uppercase(Locale.getDefault()) -> TransportType.Tls - else -> TransportType.Udp + if (outboundProxyAddress != null) { + outboundProxyAddress.transport = when (transport.value.orEmpty().trim()) { + TransportType.Tcp.name.uppercase(Locale.getDefault()) -> TransportType.Tcp + TransportType.Tls.name.uppercase(Locale.getDefault()) -> TransportType.Tls + else -> TransportType.Udp + } + Log.i("$TAG Created outbound proxy server SIP address [${outboundProxyAddress?.asStringUriOnly()}]") + accountParams.setRoutesAddresses(arrayOf(outboundProxyAddress)) } - Log.i("$TAG Created proxy server SIP address [${serverAddress?.asStringUriOnly()}]") - accountParams.serverAddress = serverAddress val prefix = internationalPrefix.value.orEmpty().trim() val isoCountryCode = internationalPrefixIsoCountryCode.value.orEmpty() diff --git a/app/src/main/java/org/linphone/ui/main/settings/fragment/AccountSettingsFragment.kt b/app/src/main/java/org/linphone/ui/main/settings/fragment/AccountSettingsFragment.kt index 9279438f0..ceec8bbb9 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/fragment/AccountSettingsFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/fragment/AccountSettingsFragment.kt @@ -23,16 +23,12 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter import androidx.annotation.UiThread import androidx.core.view.doOnPreDraw import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs -import java.util.Locale import org.linphone.R -import org.linphone.core.TransportType import org.linphone.core.tools.Log import org.linphone.databinding.AccountSettingsFragmentBinding import org.linphone.ui.GenericActivity @@ -54,22 +50,6 @@ class AccountSettingsFragment : GenericMainFragment() { private lateinit var viewModel: AccountSettingsViewModel - private val transportDropdownListener = object : AdapterView.OnItemSelectedListener { - override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - val transport = viewModel.availableTransports[position] - val transportType = when (transport) { - TransportType.Tcp.name.uppercase(Locale.getDefault()) -> TransportType.Tcp - TransportType.Tls.name.uppercase(Locale.getDefault()) -> TransportType.Tls - else -> TransportType.Udp - } - Log.i("$TAG Selected transport updated [$transport] -> [${transportType.name}]") - viewModel.selectedTransport.value = transportType - } - - override fun onNothingSelected(parent: AdapterView<*>?) { - } - } - override fun goBack(): Boolean { try { return findNavController().popBackStack() @@ -110,13 +90,15 @@ class AccountSettingsFragment : GenericMainFragment() { showUpdatePasswordDialog() } + binding.setOutboundProxyTooltipClickListener { + showOutboundProxyInfoDialog() + } + viewModel.accountFoundEvent.observe(viewLifecycleOwner) { it.consume { found -> if (found) { (view.parent as? ViewGroup)?.doOnPreDraw { startPostponedEnterTransition() - - setupTransportDropdown() } } else { Log.e( @@ -159,20 +141,8 @@ class AccountSettingsFragment : GenericMainFragment() { dialog.show() } - private fun setupTransportDropdown() { - val adapter = ArrayAdapter( - requireContext(), - R.layout.drop_down_item, - viewModel.availableTransports - ) - adapter.setDropDownViewResource(R.layout.generic_dropdown_cell) - val currentTransport = viewModel.selectedTransport.value?.name?.uppercase( - Locale.getDefault() - ) - binding.accountAdvancedSettings.transportSpinner.adapter = adapter - binding.accountAdvancedSettings.transportSpinner.setSelection( - viewModel.availableTransports.indexOf(currentTransport) - ) - binding.accountAdvancedSettings.transportSpinner.onItemSelectedListener = transportDropdownListener + private fun showOutboundProxyInfoDialog() { + val dialog = DialogUtils.getAccountOutboundProxyHelpDialog(requireActivity()) + dialog.show() } } diff --git a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt index 57590fbd9..1aaafd211 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/AccountSettingsViewModel.kt @@ -62,7 +62,7 @@ class AccountSettingsViewModel val sipProxyServer = MutableLiveData() - val outboundProxyEnabled = MutableLiveData() + val outboundProxyServer = MutableLiveData() val stunServer = MutableLiveData() @@ -155,7 +155,7 @@ class AccountSettingsViewModel selectedTransport.postValue(transportType) sipProxyServer.postValue(params.serverAddress?.asStringUriOnly()) - outboundProxyEnabled.postValue(params.isOutboundProxyEnabled) + outboundProxyServer.postValue(params.routesAddresses.first().asStringUriOnly()) natPolicy = params.natPolicy ?: core.createNatPolicy() stunServer.postValue(natPolicy.stunServer) @@ -222,13 +222,28 @@ class AccountSettingsViewModel val server = sipProxyServer.value.orEmpty() if (server.isNotEmpty()) { + Log.i("$TAG Proxy server set to [$server]") val serverAddress = core.interpretUrl(server, false) if (serverAddress != null) { serverAddress.transport = selectedTransport.value newParams.serverAddress = serverAddress + } else { + Log.e("$TAG Failed to parse proxy server!") } } - newParams.isOutboundProxyEnabled = outboundProxyEnabled.value == true + val outboundProxy = outboundProxyServer.value.orEmpty() + if (outboundProxy.isNotEmpty()) { + Log.i("$TAG Outbound proxy server set to [$outboundProxy]") + val outboundProxyAddress = core.interpretUrl(outboundProxy, false) + if (outboundProxyAddress != null) { + outboundProxyAddress.transport = selectedTransport.value + newParams.setRoutesAddresses(arrayOf(outboundProxyAddress)) + } else { + Log.e("$TAG Failed to parse outbound proxy server!") + } + } else { + newParams.setRoutesAddresses(null) + } if (::natPolicy.isInitialized) { Log.i("$TAG Also applying changes to NAT policy") diff --git a/app/src/main/java/org/linphone/utils/DialogUtils.kt b/app/src/main/java/org/linphone/utils/DialogUtils.kt index a1f003e77..b5860177f 100644 --- a/app/src/main/java/org/linphone/utils/DialogUtils.kt +++ b/app/src/main/java/org/linphone/utils/DialogUtils.kt @@ -68,6 +68,7 @@ import org.linphone.ui.main.contacts.model.NumberOrAddressPickerDialogModel import org.linphone.ui.main.model.GroupSetOrEditSubjectDialogModel import androidx.core.graphics.drawable.toDrawable import org.linphone.databinding.DialogDeleteChatMessageBinding +import org.linphone.databinding.DialogManageAccountOutboundProxyHelpBinding import org.linphone.ui.main.chat.model.MessageDeleteDialogModel class DialogUtils { @@ -122,6 +123,23 @@ class DialogUtils { return dialog } + @UiThread + fun getAccountOutboundProxyHelpDialog(context: Context): Dialog { + val binding: DialogManageAccountOutboundProxyHelpBinding = DataBindingUtil.inflate( + LayoutInflater.from(context), + R.layout.dialog_manage_account_outbound_proxy_help, + null, + false + ) + val dialog = getDialog(context, binding) + + binding.setDismissClickListener { + dialog.dismiss() + } + + return dialog + } + @UiThread fun getConfirmAccountRemovalDialog( context: Context, diff --git a/app/src/main/res/layout-sw600dp/assistant_third_party_sip_account_login_fragment.xml b/app/src/main/res/layout-sw600dp/assistant_third_party_sip_account_login_fragment.xml index 705e52297..f8b472c21 100644 --- a/app/src/main/res/layout-sw600dp/assistant_third_party_sip_account_login_fragment.xml +++ b/app/src/main/res/layout-sw600dp/assistant_third_party_sip_account_login_fragment.xml @@ -9,6 +9,9 @@ + @@ -312,7 +315,7 @@ android:id="@+id/advanced_settings_group" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:constraint_referenced_ids="authentication_id_label, authentication_id, outbound_proxy_label, outbound_proxy" + app:constraint_referenced_ids="authentication_id_label, authentication_id, proxy, proxy_label, outbound_proxy_label, outbound_proxy, outbound_proxy_tooltip" android:visibility="@{viewModel.expandAdvancedSettings ? View.VISIBLE : View.GONE, default=gone}" /> + + + + + + + @@ -18,55 +21,6 @@ android:layout_height="wrap_content" android:background="@drawable/shape_squircle_white_background"> - - - - - - @@ -102,32 +56,53 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/sip_proxy_title"/> - - + app:layout_constraintEnd_toEndOf="parent"/> + + + + + app:layout_constraintTop_toBottomOf="@id/outbound_proxy" /> + @@ -310,6 +313,7 @@ android:visibility="@{viewModel.expandAdvancedSettings ? View.VISIBLE : View.GONE}" layout="@layout/account_advanced_settings" bind:updatePasswordClickListener="@{updatePasswordClickListener}" + bind:outboundProxyTooltipClickListener="@{outboundProxyTooltipClickListener}" bind:viewModel="@{viewModel}"/> diff --git a/app/src/main/res/layout/assistant_third_party_sip_account_login_fragment.xml b/app/src/main/res/layout/assistant_third_party_sip_account_login_fragment.xml index 43bcfe574..e1654d3e4 100644 --- a/app/src/main/res/layout/assistant_third_party_sip_account_login_fragment.xml +++ b/app/src/main/res/layout/assistant_third_party_sip_account_login_fragment.xml @@ -9,6 +9,9 @@ + @@ -261,7 +264,7 @@ android:id="@+id/advanced_settings_group" android:layout_width="wrap_content" android:layout_height="wrap_content" - app:constraint_referenced_ids="authentication_id_label, authentication_id, outbound_proxy_label, outbound_proxy" + app:constraint_referenced_ids="authentication_id_label, authentication_id, proxy_label, proxy, outbound_proxy_label, outbound_proxy, outbound_proxy_tooltip" android:visibility="@{viewModel.expandAdvancedSettings ? View.VISIBLE : View.GONE, default=gone}" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 6f50c63c4..4721f2293 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -357,13 +357,15 @@ Dernière connexion : Se déconnecter du compte ? Si vous souhaitez supprimer définitivement votre compte rendez-vous sur : https://sip.linphone.org + Proxy SIP sortant + Si ce champ est rempli, l\'outbound proxy sera activé automatiquement. Laissez-le vide pour le désactiver. Paramètres de compte Activer les notifications push Notifications push non disponibles Chiffrement obligatoire des conversations - URL du serveur mandataire - Serveur mandataire sortant + Registrar URI + URI du proxy SIP sortant Paramètres de politique NAT URL du serveur STUN/TURN Activer ICE diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 953fd9ac7..5f02db816 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -399,13 +399,15 @@ Last connection: Sign out of your account? If you wish to delete your account permanently, go to: https://sip.linphone.org + Outbound SIP Proxy + If this field is filled, the outbound proxy will be enabled automatically. Leave it empty to disable it. Account settings Allow push notifications Push notifications aren\'t available! IM encryption mandatory - SIP proxy server URL - Outbound proxy + Registrar URI + Outbound SIP Proxy URI NAT policy settings STUN/TURN server URL Enable ICE