From 99870eced252085713d0e1632fa9c34d2ded5b6d Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Thu, 3 Apr 2025 17:21:43 +0200 Subject: [PATCH] Added hidden developer settings --- .../java/org/linphone/core/CorePreferences.kt | 11 ++ .../ui/main/help/viewmodel/HelpViewModel.kt | 21 +++ .../fragment/SettingsDeveloperFragment.kt | 63 +++++++++ .../settings/fragment/SettingsFragment.kt | 10 +- .../settings/viewmodel/SettingsViewModel.kt | 50 +++++-- app/src/main/res/layout/help_fragment.xml | 3 +- .../res/layout/settings_advanced_calls.xml | 30 +---- .../layout/settings_developer_fragment.xml | 123 ++++++++++++++++++ app/src/main/res/layout/settings_fragment.xml | 25 +++- .../main/res/navigation/main_nav_graph.xml | 14 ++ app/src/main/res/values-fr/strings.xml | 5 + app/src/main/res/values/strings.xml | 5 + 12 files changed, 316 insertions(+), 44 deletions(-) create mode 100644 app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsDeveloperFragment.kt create mode 100644 app/src/main/res/layout/settings_developer_fragment.xml diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index 625d6dd1b..2ef148d0a 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -109,6 +109,13 @@ class CorePreferences config.setString("app", "device", value.trim()) } + @get:WorkerThread @set:WorkerThread + var showDeveloperSettings: Boolean + get() = config.getBool("ui", "show_developer_settings", false) + set(value) { + config.setBool("ui", "show_developer_settings", value) + } + // Call settings // This won't be done if bluetooth or wired headset is used @@ -306,6 +313,10 @@ class CorePreferences val hideAccountSettings: Boolean get() = config.getBool("ui", "hide_account_settings", false) + @get:WorkerThread + val hideAdvancedSettings: Boolean + get() = config.getBool("ui", "hide_advanced_settings", false) + @get:WorkerThread val hideAssistantCreateAccount: Boolean get() = config.getBool("ui", "assistant_hide_create_account", false) diff --git a/app/src/main/java/org/linphone/ui/main/help/viewmodel/HelpViewModel.kt b/app/src/main/java/org/linphone/ui/main/help/viewmodel/HelpViewModel.kt index 52b39ee7f..32dab37fe 100644 --- a/app/src/main/java/org/linphone/ui/main/help/viewmodel/HelpViewModel.kt +++ b/app/src/main/java/org/linphone/ui/main/help/viewmodel/HelpViewModel.kt @@ -63,6 +63,8 @@ class HelpViewModel val logsUploadInProgress = MutableLiveData() + val versionClickCount = MutableLiveData() + val newVersionAvailableEvent: MutableLiveData>> by lazy { MutableLiveData>>() } @@ -137,6 +139,7 @@ class HelpViewModel init { val currentVersion = BuildConfig.VERSION_NAME version.value = currentVersion + versionClickCount.value = 0 val versionCode = BuildConfig.VERSION_CODE val appGitDescribe = AppUtils.getString(R.string.linphone_app_version) @@ -166,6 +169,24 @@ class HelpViewModel } } + @UiThread + fun versionClicked() { + if (corePreferences.showDeveloperSettings == true) { + showRedToast(R.string.settings_developer_already_enabled_toast, R.drawable.warning_circle) + return + } + + versionClickCount.value = (versionClickCount.value ?: 0) + 1 + if (versionClickCount.value == 7) { + coreContext.postOnCoreThread { + Log.w("$TAG Version was clicked seven times, enabling developer settings") + corePreferences.showDeveloperSettings = true + + showGreenToast(R.string.settings_developer_enabled_toast, R.drawable.gear) + } + } + } + @UiThread fun toggleLogcat() { val newValue = logcat.value == false diff --git a/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsDeveloperFragment.kt b/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsDeveloperFragment.kt new file mode 100644 index 000000000..36556bee0 --- /dev/null +++ b/app/src/main/java/org/linphone/ui/main/settings/fragment/SettingsDeveloperFragment.kt @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2010-2025 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.settings.fragment + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.UiThread +import androidx.lifecycle.ViewModelProvider +import org.linphone.databinding.SettingsDeveloperFragmentBinding +import org.linphone.ui.main.fragment.GenericMainFragment +import org.linphone.ui.main.settings.viewmodel.SettingsViewModel + +@UiThread +class SettingsDeveloperFragment : GenericMainFragment() { + private lateinit var binding: SettingsDeveloperFragmentBinding + + private lateinit var viewModel: SettingsViewModel + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = SettingsDeveloperFragmentBinding.inflate(layoutInflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + postponeEnterTransition() + super.onViewCreated(view, savedInstanceState) + + viewModel = ViewModelProvider(this)[SettingsViewModel::class.java] + + binding.lifecycleOwner = viewLifecycleOwner + binding.viewModel = viewModel + observeToastEvents(viewModel) + + binding.setBackClickListener { + goBack() + } + + startPostponedEnterTransition() + } +} 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 3b7e7fba6..e02492381 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 @@ -90,7 +90,7 @@ class SettingsFragment : GenericMainFragment() { val label = viewModel.availableColorsNames[position] val value = viewModel.availableColorsValues[position] Log.i("$TAG Selected color is now [$label] ($value)") - // Be carefull not to create an infinite loop + // Be careful not to create an infinite loop if (value != viewModel.color.value.orEmpty()) { viewModel.setColor(value) requireActivity().recreate() @@ -140,6 +140,13 @@ class SettingsFragment : GenericMainFragment() { } } + binding.setDeveloperSettingsClickListener { + if (findNavController().currentDestination?.id == R.id.settingsFragment) { + val action = SettingsFragmentDirections.actionSettingsFragmentToSettingsDeveloperFragment() + findNavController().navigate(action) + } + } + viewModel.recreateActivityEvent.observe(viewLifecycleOwner) { it.consume { Log.w("$TAG Recreate Activity") @@ -313,6 +320,7 @@ class SettingsFragment : GenericMainFragment() { viewModel.reloadLdapServers() viewModel.reloadConfiguredCardDavServers() + viewModel.reloadShowDeveloperSettings() } override fun 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 b70c1cd49..14b8df59d 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 @@ -188,6 +188,8 @@ class SettingsViewModel ) // Advanced settings + val showAdvancedSettings = MutableLiveData() + val startAtBoot = MutableLiveData() val keepAliveThirdPartyAccountsService = MutableLiveData() val useSmffForCallRecording = MutableLiveData() @@ -202,7 +204,6 @@ class SettingsViewModel val mediaEncryptionLabels = arrayListOf() private val mediaEncryptionValues = arrayListOf() val mediaEncryptionMandatory = MutableLiveData() - val createEndToEndEncryptedConferences = MutableLiveData() val acceptEarlyMedia = MutableLiveData() val ringDuringEarlyMedia = MutableLiveData() val allowOutgoingEarlyMedia = MutableLiveData() @@ -223,6 +224,11 @@ class SettingsViewModel val expandVideoCodecs = MutableLiveData() val videoCodecs = MutableLiveData>() + // Developer settings + val showDeveloperSettings = MutableLiveData() + + val createEndToEndEncryptedConferences = MutableLiveData() + private val coreListener = object : CoreListenerStub() { @WorkerThread override fun onAudioDevicesListUpdated(core: Core) { @@ -249,6 +255,8 @@ class SettingsViewModel ldapAvailable.postValue(core.ldapAvailable()) showThemeSelector.postValue(corePreferences.darkModeAllowed) showColorSelector.postValue(corePreferences.changeMainColorAllowed) + showAdvancedSettings.postValue(!corePreferences.hideAdvancedSettings) + showDeveloperSettings.postValue(corePreferences.showDeveloperSettings) } showContactsSettings.value = true @@ -328,7 +336,6 @@ class SettingsViewModel fileSharingServerUrl.postValue(core.fileTransferServer) remoteProvisioningUrl.postValue(core.provisioningUri) - createEndToEndEncryptedConferences.postValue(corePreferences.createEndToEndEncryptedMeetingsAndGroupCalls) acceptEarlyMedia.postValue(corePreferences.acceptEarlyMedia) ringDuringEarlyMedia.postValue(core.ringDuringIncomingEarlyMedia) allowOutgoingEarlyMedia.postValue(corePreferences.allowOutgoingEarlyMedia) @@ -338,6 +345,8 @@ class SettingsViewModel setupMediaEncryption() setupAudioDevices() setupCodecs() + + createEndToEndEncryptedConferences.postValue(corePreferences.createEndToEndEncryptedMeetingsAndGroupCalls) } } @@ -792,16 +801,6 @@ class SettingsViewModel } } - @UiThread - fun toggleConferencesEndToEndEncryption() { - val newValue = createEndToEndEncryptedConferences.value == false - - coreContext.postOnCoreThread { core -> - corePreferences.createEndToEndEncryptedMeetingsAndGroupCalls = newValue - createEndToEndEncryptedConferences.postValue(newValue) - } - } - @UiThread fun toggleAcceptEarlyMedia() { val newValue = acceptEarlyMedia.value == false @@ -1031,4 +1030,31 @@ class SettingsViewModel } calibratedEchoCancellerValue.postValue(value) } + + @UiThread + fun toggleDeveloperSettings() { + val newValue = showDeveloperSettings.value == false + + coreContext.postOnCoreThread { core -> + corePreferences.showDeveloperSettings = newValue + showDeveloperSettings.postValue(newValue) + } + } + + @UiThread + fun reloadShowDeveloperSettings() { + coreContext.postOnCoreThread { + showDeveloperSettings.postValue(corePreferences.showDeveloperSettings) + } + } + + @UiThread + fun toggleConferencesEndToEndEncryption() { + val newValue = createEndToEndEncryptedConferences.value == false + + coreContext.postOnCoreThread { core -> + corePreferences.createEndToEndEncryptedMeetingsAndGroupCalls = newValue + createEndToEndEncryptedConferences.postValue(newValue) + } + } } diff --git a/app/src/main/res/layout/help_fragment.xml b/app/src/main/res/layout/help_fragment.xml index a74dd4d4c..f8fd0e312 100644 --- a/app/src/main/res/layout/help_fragment.xml +++ b/app/src/main/res/layout/help_fragment.xml @@ -144,7 +144,8 @@ diff --git a/app/src/main/res/layout/settings_advanced_calls.xml b/app/src/main/res/layout/settings_advanced_calls.xml index bac6ae83e..241c37a2a 100644 --- a/app/src/main/res/layout/settings_advanced_calls.xml +++ b/app/src/main/res/layout/settings_advanced_calls.xml @@ -167,34 +167,6 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toBottomOf="@id/media_encryption" /> - - - - + app:layout_constraintTop_toBottomOf="@id/media_encryption_mandatory_switch" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/settings_fragment.xml b/app/src/main/res/layout/settings_fragment.xml index 81a23ef10..c9515b759 100644 --- a/app/src/main/res/layout/settings_fragment.xml +++ b/app/src/main/res/layout/settings_fragment.xml @@ -14,6 +14,9 @@ + @@ -315,10 +318,30 @@ android:text="@string/settings_advanced_title" android:drawableEnd="@drawable/caret_right" android:drawableTint="?attr/color_main2_600" + android:visibility="@{viewModel.showAdvancedSettings ? View.VISIBLE : View.GONE}" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/tunnel_settings"/> + + diff --git a/app/src/main/res/navigation/main_nav_graph.xml b/app/src/main/res/navigation/main_nav_graph.xml index 5d223456c..9684ce3f3 100644 --- a/app/src/main/res/navigation/main_nav_graph.xml +++ b/app/src/main/res/navigation/main_nav_graph.xml @@ -137,6 +137,14 @@ app:exitAnim="@anim/slide_out_left" app:popEnterAnim="@anim/slide_in_left" app:popExitAnim="@anim/slide_out_right" /> + + + \ 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 013cb5012..e039ef64e 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -289,6 +289,11 @@ Codecs vidéo Paramètres Android de &appName; + Paramètres développeurs + Afficher les paramètres développeurs + Paramètres développeurs activés + Paramètres développeurs déjà activés + Mon compte Détails diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5a1c1fba4..7d3ae15b7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -329,6 +329,11 @@ Video codecs &appName; Android settings + Developer settings + Show developer settings + Developer settings enabled + Developer settings already enabled + Manage account Details