From 76716503e98b33818dcd6e193684aaeed758fbeb Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 20 May 2024 16:01:43 +0200 Subject: [PATCH] Added Tunnel settings --- .../settings/fragment/SettingsFragment.kt | 31 +++ .../settings/viewmodel/SettingsViewModel.kt | 80 ++++++ app/src/main/res/layout/settings_fragment.xml | 60 +++-- app/src/main/res/layout/settings_tunnel.xml | 233 ++++++++++++++++++ app/src/main/res/values-fr/strings.xml | 10 + app/src/main/res/values/strings.xml | 10 + 6 files changed, 409 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/layout/settings_tunnel.xml diff --git a/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsFragment.kt b/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsFragment.kt index a4a5995b7..e762d2946 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsFragment.kt @@ -91,6 +91,15 @@ class SettingsFragment : GenericMainFragment() { } } + private val tunnelModeListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + viewModel.tunnelModeIndex.value = position + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + } + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -212,6 +221,20 @@ class SettingsFragment : GenericMainFragment() { binding.userInterfaceSettings.colorSpinner.onItemSelectedListener = colorListener } + // Tunnel mode + val tunnelModeAdapter = ArrayAdapter( + requireContext(), + R.layout.drop_down_item, + viewModel.tunnelModeLabels + ) + tunnelModeAdapter.setDropDownViewResource(R.layout.generic_dropdown_cell) + binding.tunnelSettings.tunnelModeSpinner.adapter = tunnelModeAdapter + binding.tunnelSettings.tunnelModeSpinner.onItemSelectedListener = tunnelModeListener + + viewModel.tunnelModeIndex.observe(viewLifecycleOwner) { index -> + binding.tunnelSettings.tunnelModeSpinner.setSelection(index) + } + startPostponedEnterTransition() } @@ -221,4 +244,12 @@ class SettingsFragment : GenericMainFragment() { viewModel.reloadLdapServers() viewModel.reloadConfiguredCardDavServers() } + + override fun onPause() { + if (viewModel.isTunnelAvailable.value == true) { + viewModel.saveTunnelConfig() + } + + super.onPause() + } } diff --git a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt index c03cf69f4..8206da1be 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/SettingsViewModel.kt @@ -30,7 +30,9 @@ import org.linphone.core.AudioDevice import org.linphone.core.Conference import org.linphone.core.Core import org.linphone.core.CoreListenerStub +import org.linphone.core.Factory import org.linphone.core.FriendList +import org.linphone.core.Tunnel import org.linphone.core.VFS import org.linphone.core.tools.Log import org.linphone.ui.GenericViewModel @@ -51,6 +53,8 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { val expandMeetings = MutableLiveData() val expandNetwork = MutableLiveData() val expandUserInterface = MutableLiveData() + val expandTunnel = MutableLiveData() + val isTunnelAvailable = MutableLiveData() val recreateActivityEvent: MutableLiveData> by lazy { MutableLiveData>() @@ -148,6 +152,19 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { "purple" ) + // Tunnel settings + val tunnelMainHost = MutableLiveData() + val tunnelMainPort = MutableLiveData() + val tunnelDualMode = MutableLiveData() + val tunnelDualHost = MutableLiveData() + val tunnelDualPort = MutableLiveData() + val tunnelModeIndex = MutableLiveData() + val tunnelModeLabels = arrayListOf( + AppUtils.getString(R.string.settings_tunnel_mode_disabled_label), + AppUtils.getString(R.string.settings_tunnel_mode_always_label), + AppUtils.getString(R.string.settings_tunnel_mode_auto_label) + ) + // Advanced settings val keepAliveThirdPartyAccountsService = MutableLiveData() @@ -180,6 +197,7 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { coreContext.postOnCoreThread { core -> core.addListener(coreListener) + isTunnelAvailable.postValue(core.tunnelAvailable()) showConversationsSettings.postValue(!corePreferences.disableChat) showMeetingsSettings.postValue(!corePreferences.disableMeetings) ldapAvailable.postValue(core.ldapAvailable()) @@ -195,6 +213,7 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { expandMeetings.value = false expandNetwork.value = false expandUserInterface.value = false + expandTunnel.value = false expandAudioDevices.value = false expandAudioCodecs.value = false expandVideoCodecs.value = false @@ -227,6 +246,10 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { theme.postValue(corePreferences.darkMode) color.postValue(corePreferences.themeMainColor) + if (core.tunnelAvailable()) { + setupTunnel() + } + keepAliveThirdPartyAccountsService.postValue(corePreferences.keepServiceAlive) remoteProvisioningUrl.postValue(core.provisioningUri) @@ -465,6 +488,63 @@ class SettingsViewModel @UiThread constructor() : GenericViewModel() { color.value = colorName } + @UiThread + fun toggleTunnelExpand() { + expandTunnel.value = expandTunnel.value == false + } + + @WorkerThread + private fun setupTunnel() { + // Tunnel mode values are 0, 1 and 2, we can use selected item position directly + val tunnelConfig = coreContext.core.tunnel + if (tunnelConfig != null) { + val mainTunnel = tunnelConfig.servers.firstOrNull() + if (mainTunnel != null) { + tunnelMainHost.postValue(mainTunnel.host) + tunnelMainPort.postValue(mainTunnel.port.toString()) + if (tunnelConfig.isDualModeEnabled) { + tunnelDualHost.postValue(mainTunnel.host2) + tunnelDualPort.postValue(mainTunnel.port2.toString()) + } + } + tunnelDualMode.postValue(tunnelConfig.isDualModeEnabled) + tunnelModeIndex.postValue(tunnelConfig.mode.ordinal) + } else { + Log.w("$TAG No tunnel config found!") + tunnelModeIndex.postValue(0) + } + } + + @UiThread + fun toggleTunnelDualMode() { + tunnelDualMode.value = tunnelDualMode.value == false + } + + @UiThread + fun saveTunnelConfig() { + coreContext.postOnCoreThread { core -> + if (core.tunnelAvailable()) { + val tunnel = core.tunnel + tunnel?.cleanServers() + + val config = Factory.instance().createTunnelConfig() + config.host = tunnelMainHost.value.orEmpty() + config.port = tunnelMainPort.value?.toInt() ?: 0 + + tunnel?.isDualModeEnabled = tunnelDualMode.value == true + if (tunnelDualMode.value == true) { + config.host2 = tunnelDualHost.value.orEmpty() + config.port2 = tunnelDualPort.value?.toInt() ?: 0 + } + + tunnel?.mode = Tunnel.Mode.fromInt(tunnelModeIndex.value ?: 0) + + tunnel?.addServer(config) + Log.i("$TAG Tunnel configuration added into Core") + } + } + } + @UiThread fun toggleKeepAliveThirdPartyAccountService() { val newValue = keepAliveThirdPartyAccountsService.value == false diff --git a/app/src/main/res/layout/settings_fragment.xml b/app/src/main/res/layout/settings_fragment.xml index 40e387811..3e9ad2d37 100644 --- a/app/src/main/res/layout/settings_fragment.xml +++ b/app/src/main/res/layout/settings_fragment.xml @@ -63,8 +63,8 @@ + + + + diff --git a/app/src/main/res/layout/settings_tunnel.xml b/app/src/main/res/layout/settings_tunnel.xml new file mode 100644 index 000000000..f214a1de7 --- /dev/null +++ b/app/src/main/res/layout/settings_tunnel.xml @@ -0,0 +1,233 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 cf422a36a..aca25d215 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -273,6 +273,16 @@ Clair Auto Couleur principale + Tunnel + Hôte + Port + Utiliser deux serveurs + Hôte second serveur + Port second serveur + Mode + Désactivé + Toujours + Auto Paramètres avancés Garder l\'app en vie via un Service diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d5ad324c4..4dd68da65 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -308,6 +308,16 @@ Light theme Auto Main color + Tunnel + Host + Port + Use two servers + Second host + Second port + Mode + Disabled + Always + Auto Advanced settings Keep app alive using Service