From 24a5ae81229b29c874ea1148a260ab36a2b7711b Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Wed, 13 Sep 2023 11:52:12 +0200 Subject: [PATCH] Added help layout --- .../java/org/linphone/LinphoneApplication.kt | 4 +- .../java/org/linphone/core/CorePreferences.kt | 7 + .../ui/assistant/fragment/LoginFragment.kt | 30 +- .../ui/assistant/fragment/RegisterFragment.kt | 6 +- .../ThirdPartySipAccountWarningFragment.kt | 7 +- .../java/org/linphone/ui/main/MainActivity.kt | 26 +- .../ui/main/settings/fragment/HelpFragment.kt | 119 +++++++ .../main/settings/viewmodel/HelpViewModel.kt | 172 +++++++++ .../main/java/org/linphone/utils/AppUtils.kt | 27 ++ app/src/main/res/drawable/file_text.xml | 9 + .../res/drawable/globe_hemisphere_west.xml | 9 + app/src/main/res/drawable/wrench.xml | 9 + .../res/layout/assistant_login_fragment.xml | 3 +- .../layout/assistant_register_fragment.xml | 6 +- ...third_party_sip_account_login_fragment.xml | 2 + ...ird_party_sip_account_warning_fragment.xml | 2 +- app/src/main/res/layout/help_fragment.xml | 325 ++++++++++++++++++ app/src/main/res/values/dimen.xml | 1 + app/src/main/res/values/strings.xml | 30 ++ 19 files changed, 757 insertions(+), 37 deletions(-) create mode 100644 app/src/main/java/org/linphone/ui/main/settings/viewmodel/HelpViewModel.kt create mode 100644 app/src/main/res/drawable/file_text.xml create mode 100644 app/src/main/res/drawable/globe_hemisphere_west.xml create mode 100644 app/src/main/res/drawable/wrench.xml diff --git a/app/src/main/java/org/linphone/LinphoneApplication.kt b/app/src/main/java/org/linphone/LinphoneApplication.kt index ac992ded0..47ac73384 100644 --- a/app/src/main/java/org/linphone/LinphoneApplication.kt +++ b/app/src/main/java/org/linphone/LinphoneApplication.kt @@ -70,7 +70,9 @@ class LinphoneApplication : Application(), ImageLoaderFactory { val appName = context.getString(R.string.app_name) Factory.instance().setLoggerDomain(appName) Factory.instance().enableLogcatLogs(true) - Factory.instance().loggingService.setLogLevel(LogLevel.Message) + if (corePreferences.debugLogs) { + Factory.instance().loggingService.setLogLevel(LogLevel.Message) + } coreContext = CoreContext(context) coreContext.start() diff --git a/app/src/main/java/org/linphone/core/CorePreferences.kt b/app/src/main/java/org/linphone/core/CorePreferences.kt index d0e600aee..3c4f92856 100644 --- a/app/src/main/java/org/linphone/core/CorePreferences.kt +++ b/app/src/main/java/org/linphone/core/CorePreferences.kt @@ -41,6 +41,13 @@ class CorePreferences @UiThread constructor(private val context: Context) { _config = value } + @get:WorkerThread @set:WorkerThread + var debugLogs: Boolean + get() = config.getBool("app", "debug", org.linphone.BuildConfig.DEBUG) + set(value) { + config.setBool("app", "debug", value) + } + @get:WorkerThread @set:WorkerThread var conditionsAndPrivacyPolicyAccepted: Boolean get() = config.getBool("app", "read_and_agree_terms_and_privacy", false) diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt index 19daa71bc..4de0da4f1 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/LoginFragment.kt @@ -83,12 +83,14 @@ class LoginFragment : Fragment() { } binding.setForgottenPasswordClickListener { + val url = getString(R.string.users_web_platform) try { - val url = "https://subscribe.linphone.org" val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(browserIntent) } catch (ise: IllegalStateException) { - Log.e("$TAG Can't start ACTION_VIEW intent, IllegalStateException: $ise") + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) } } @@ -199,28 +201,28 @@ class LoginFragment : Fragment() { model.privacyPolicyClickedEvent.observe(viewLifecycleOwner) { it.consume { - val browserIntent = Intent( - Intent.ACTION_VIEW, - Uri.parse("https://www.linphone.org/privacy-policy") - ) + val url = getString(R.string.privacy_policy_url) try { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(browserIntent) - } catch (e: Exception) { - Log.e("$TAG Can't start activity: $e") + } catch (ise: IllegalStateException) { + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) } } } model.generalTermsClickedEvent.observe(viewLifecycleOwner) { it.consume { - val browserIntent = Intent( - Intent.ACTION_VIEW, - Uri.parse("https://www.linphone.org/general-terms") - ) + val url = getString(R.string.terms_and_conditions_url) try { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(browserIntent) - } catch (e: Exception) { - Log.e("$TAG Can't start activity: $e") + } catch (ise: IllegalStateException) { + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) } } } diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt index df959632f..0b015c778 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/RegisterFragment.kt @@ -85,12 +85,14 @@ class RegisterFragment : Fragment() { } binding.setOpenSubscribeWebPageClickListener { + val url = getString(R.string.users_web_platform) try { - val url = "https://subscribe.linphone.org" val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(browserIntent) } catch (ise: IllegalStateException) { - Log.e("$TAG Can't start ACTION_VIEW intent, IllegalStateException: $ise") + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) } } diff --git a/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountWarningFragment.kt b/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountWarningFragment.kt index c1fdb2f64..39b783fa4 100644 --- a/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountWarningFragment.kt +++ b/app/src/main/java/org/linphone/ui/assistant/fragment/ThirdPartySipAccountWarningFragment.kt @@ -28,6 +28,7 @@ import android.view.ViewGroup import androidx.annotation.UiThread import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController +import org.linphone.R import org.linphone.core.tools.Log import org.linphone.databinding.AssistantThirdPartySipAccountWarningFragmentBinding @@ -58,12 +59,14 @@ class ThirdPartySipAccountWarningFragment : Fragment() { } binding.setContactClickListener { + val url = getString(R.string.website_contact_page) try { - val url = "https://linphone.org/contact" val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) startActivity(browserIntent) } catch (ise: IllegalStateException) { - Log.e("$TAG Can't start ACTION_VIEW intent, IllegalStateException: $ise") + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) } } 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 19a34ce08..dd62cb59e 100644 --- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt +++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt @@ -24,8 +24,6 @@ import android.annotation.SuppressLint 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 androidx.annotation.DrawableRes import androidx.annotation.UiThread @@ -38,7 +36,7 @@ import androidx.navigation.findNavController import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R import org.linphone.databinding.MainActivityBinding -import org.linphone.databinding.ToastBinding +import org.linphone.utils.AppUtils import org.linphone.utils.slideInToastFromTopForDuration @UiThread @@ -140,17 +138,7 @@ class MainActivity : AppCompatActivity() { } fun showGreenToast(message: String, @DrawableRes icon: Int) { - val greenToast: ToastBinding = DataBindingUtil.inflate( - LayoutInflater.from(this), - R.layout.toast, - binding.toastsArea, - false - ) - greenToast.message = message - greenToast.icon = icon - greenToast.shadowColor = R.drawable.shape_toast_green_shadow - greenToast.textColor = R.color.green_online - greenToast.root.visibility = View.GONE + val greenToast = AppUtils.getGreenToast(this, binding.toastsArea, message, icon) binding.toastsArea.addView(greenToast.root) greenToast.root.slideInToastFromTopForDuration( @@ -159,6 +147,16 @@ class MainActivity : AppCompatActivity() { ) } + fun showRedToast(message: String, @DrawableRes icon: Int) { + val redToast = AppUtils.getRedToast(this, binding.toastsArea, message, icon) + binding.toastsArea.addView(redToast.root) + + redToast.root.slideInToastFromTopForDuration( + binding.toastsArea as ViewGroup, + lifecycleScope + ) + } + private fun loadContacts() { coreContext.contactsManager.loadContacts(this) diff --git a/app/src/main/java/org/linphone/ui/main/settings/fragment/HelpFragment.kt b/app/src/main/java/org/linphone/ui/main/settings/fragment/HelpFragment.kt index d5f1c5576..f471d7d76 100644 --- a/app/src/main/java/org/linphone/ui/main/settings/fragment/HelpFragment.kt +++ b/app/src/main/java/org/linphone/ui/main/settings/fragment/HelpFragment.kt @@ -1,17 +1,36 @@ package org.linphone.ui.main.settings.fragment +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.annotation.UiThread +import androidx.navigation.navGraphViewModels +import org.linphone.R +import org.linphone.core.tools.Log import org.linphone.databinding.HelpFragmentBinding +import org.linphone.ui.main.MainActivity import org.linphone.ui.main.fragment.GenericFragment +import org.linphone.ui.main.settings.viewmodel.HelpViewModel +import org.linphone.utils.AppUtils @UiThread class HelpFragment : GenericFragment() { + companion object { + private const val TAG = "[Help Fragment]" + } + private lateinit var binding: HelpFragmentBinding + val viewModel: HelpViewModel by navGraphViewModels( + R.id.main_nav_graph + ) + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -24,9 +43,109 @@ class HelpFragment : GenericFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) binding.lifecycleOwner = viewLifecycleOwner + binding.viewModel = viewModel binding.setBackClickListener { goBack() } + + binding.setPrivacyPolicyClickListener { + val url = getString(R.string.privacy_policy_url) + try { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + startActivity(browserIntent) + } catch (ise: IllegalStateException) { + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) + } + } + + binding.setLicensesClickListener { + val url = getString(R.string.open_source_licences_usage_url) + try { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + startActivity(browserIntent) + } catch (ise: IllegalStateException) { + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) + } + } + + binding.setTranslateClickListener { + val url = getString(R.string.translate_weblate_url) + try { + val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + startActivity(browserIntent) + } catch (ise: IllegalStateException) { + Log.e( + "$TAG Can't start ACTION_VIEW intent for URL [$url], IllegalStateException: $ise" + ) + } + } + + viewModel.newVersionAvailableEvent.observe(viewLifecycleOwner) { + it.consume { version -> + (requireActivity() as MainActivity).showGreenToast( + getString(R.string.help_update_available_toast_message, version), + R.drawable.info + ) + } + } + + viewModel.versionUpToDateEvent.observe(viewLifecycleOwner) { + it.consume { + (requireActivity() as MainActivity).showGreenToast( + getString(R.string.help_version_up_to_date_toast_message), + R.drawable.info + ) + } + } + + viewModel.errorEvent.observe(viewLifecycleOwner) { + it.consume { + (requireActivity() as MainActivity).showRedToast( + getString(R.string.help_error_checking_version_toast_message), + R.drawable.warning_circle + ) + } + } + + viewModel.debugLogsCleanedEvent.observe(viewLifecycleOwner) { + it.consume { + (requireActivity() as MainActivity).showGreenToast( + getString(R.string.help_advanced_debug_logs_cleaned_toast_message), + R.drawable.info + ) + } + } + + viewModel.uploadDebugLogsFinishedEvent.observe(viewLifecycleOwner) { + it.consume { url -> + val clipboard = + requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("Logs url", url) + clipboard.setPrimaryClip(clip) + + (requireActivity() as MainActivity).showGreenToast( + getString( + R.string.help_advanced_debug_logs_url_copied_into_clipboard_toast_message + ), + R.drawable.info + ) + + AppUtils.shareUploadedLogsUrl(requireActivity(), url) + } + } + + viewModel.uploadDebugLogsErrorEvent.observe(viewLifecycleOwner) { + it.consume { + (requireActivity() as MainActivity).showRedToast( + getString(R.string.help_advanced_debug_logs_upload_error_toast_message), + R.drawable.warning_circle + ) + } + } } } diff --git a/app/src/main/java/org/linphone/ui/main/settings/viewmodel/HelpViewModel.kt b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/HelpViewModel.kt new file mode 100644 index 000000000..1c8f328ae --- /dev/null +++ b/app/src/main/java/org/linphone/ui/main/settings/viewmodel/HelpViewModel.kt @@ -0,0 +1,172 @@ +/* + * 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.settings.viewmodel + +import androidx.annotation.UiThread +import androidx.annotation.WorkerThread +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import org.linphone.BuildConfig +import org.linphone.LinphoneApplication.Companion.coreContext +import org.linphone.LinphoneApplication.Companion.corePreferences +import org.linphone.core.Core +import org.linphone.core.CoreListenerStub +import org.linphone.core.Factory +import org.linphone.core.LogLevel +import org.linphone.core.VersionUpdateCheckResult +import org.linphone.core.tools.Log +import org.linphone.utils.Event + +class HelpViewModel @UiThread constructor() : ViewModel() { + companion object { + private const val TAG = "[Help ViewModel]" + } + + val version = MutableLiveData() + + val debugModeEnabled = MutableLiveData() + + val newVersionAvailableEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val versionUpToDateEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val errorEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val debugLogsCleanedEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val uploadDebugLogsFinishedEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + val uploadDebugLogsErrorEvent: MutableLiveData> by lazy { + MutableLiveData>() + } + + private val coreListener = object : CoreListenerStub() { + @WorkerThread + override fun onVersionUpdateCheckResultReceived( + core: Core, + result: VersionUpdateCheckResult, + version: String?, + url: String? + ) { + when (result) { + VersionUpdateCheckResult.NewVersionAvailable -> { + Log.i("$TAG Update available, version [$version], url [$url]") + if (!version.isNullOrEmpty()) { + newVersionAvailableEvent.postValue(Event(version)) + } + } + VersionUpdateCheckResult.UpToDate -> { + Log.i("$TAG This version is up-to-date") + versionUpToDateEvent.postValue(Event(true)) + } + else -> { + Log.e("$TAG Can't check for update, an error happened [$result]") + errorEvent.postValue(Event(true)) + } + } + } + + @WorkerThread + override fun onLogCollectionUploadStateChanged( + core: Core, + state: Core.LogCollectionUploadState, + info: String + ) { + Log.i("$TAG Logs upload state changed [$state]") + if (state == Core.LogCollectionUploadState.Delivered) { + uploadDebugLogsFinishedEvent.postValue(Event(info)) + } else if (state == Core.LogCollectionUploadState.NotDelivered) { + uploadDebugLogsErrorEvent.postValue(Event(true)) + } + } + } + + init { + val currentVersion = BuildConfig.VERSION_NAME + version.value = currentVersion + + coreContext.postOnCoreThread { core -> + core.addListener(coreListener) + debugModeEnabled.postValue(corePreferences.debugLogs) + } + } + + @UiThread + override fun onCleared() { + super.onCleared() + + coreContext.postOnCoreThread { core -> + core.removeListener(coreListener) + } + } + + @UiThread + fun toggleDebugMode() { + val enabled = debugModeEnabled.value == false + debugModeEnabled.value = enabled + + if (!enabled) { + cleanLogs() + } + + coreContext.postOnCoreThread { + corePreferences.debugLogs = enabled + val logLevel = if (enabled) LogLevel.Message else LogLevel.Error + Factory.instance().loggingService.setLogLevel(logLevel) + Log.i("$TAG Debug logs have been ${if (enabled) "enabled" else "disabled"}") + } + } + + @UiThread + fun cleanLogs() { + coreContext.postOnCoreThread { core -> + core.resetLogCollection() + Log.i("$TAG Debug logs have been cleaned") + debugLogsCleanedEvent.postValue(Event(true)) + } + } + + @UiThread + fun shareLogs() { + coreContext.postOnCoreThread { core -> + Log.i("$TAG Uploading debug logs for sharing") + core.uploadLogCollection() + } + } + + @UiThread + fun checkForUpdate() { + val currentVersion = version.value.orEmpty() + coreContext.postOnCoreThread { core -> + Log.i("[$TAG] Checking for update using current version [$currentVersion]") + core.checkForUpdate(currentVersion) + } + } +} diff --git a/app/src/main/java/org/linphone/utils/AppUtils.kt b/app/src/main/java/org/linphone/utils/AppUtils.kt index 644966462..2f3d1bfed 100644 --- a/app/src/main/java/org/linphone/utils/AppUtils.kt +++ b/app/src/main/java/org/linphone/utils/AppUtils.kt @@ -20,7 +20,9 @@ package org.linphone.utils import android.app.Activity +import android.content.ActivityNotFoundException import android.content.Context +import android.content.Intent import android.util.DisplayMetrics import android.util.Rational import android.view.LayoutInflater @@ -34,6 +36,7 @@ import androidx.annotation.StringRes import androidx.databinding.DataBindingUtil import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R +import org.linphone.core.tools.Log import org.linphone.databinding.ToastBinding class AppUtils { @@ -151,5 +154,29 @@ class AppUtils { blueToast.root.visibility = View.GONE return blueToast } + + @AnyThread + fun shareUploadedLogsUrl(activity: Activity, info: String) { + val appName = activity.getString(R.string.app_name) + val intent = Intent(Intent.ACTION_SEND) + intent.putExtra( + Intent.EXTRA_EMAIL, + arrayOf(activity.getString(R.string.help_advanced_send_debug_logs_email_address)) + ) + intent.putExtra(Intent.EXTRA_SUBJECT, "$appName Logs") + intent.putExtra(Intent.EXTRA_TEXT, info) + intent.type = "text/plain" + + try { + activity.startActivity( + Intent.createChooser( + intent, + activity.getString(R.string.help_advanced_share_logs_dialog_title) + ) + ) + } catch (ex: ActivityNotFoundException) { + Log.e(ex) + } + } } } diff --git a/app/src/main/res/drawable/file_text.xml b/app/src/main/res/drawable/file_text.xml new file mode 100644 index 000000000..da26bb18b --- /dev/null +++ b/app/src/main/res/drawable/file_text.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/globe_hemisphere_west.xml b/app/src/main/res/drawable/globe_hemisphere_west.xml new file mode 100644 index 000000000..6390028f6 --- /dev/null +++ b/app/src/main/res/drawable/globe_hemisphere_west.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/wrench.xml b/app/src/main/res/drawable/wrench.xml new file mode 100644 index 000000000..6c926c018 --- /dev/null +++ b/app/src/main/res/drawable/wrench.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/assistant_login_fragment.xml b/app/src/main/res/layout/assistant_login_fragment.xml index 6793cd5bb..c5ae6cf7c 100644 --- a/app/src/main/res/layout/assistant_login_fragment.xml +++ b/app/src/main/res/layout/assistant_login_fragment.xml @@ -304,7 +304,7 @@ android:layout_height="wrap_content" android:layout_marginTop="40dp" android:layout_marginStart="20dp" - android:layout_marginBottom="20dp" + android:layout_marginBottom="32dp" android:paddingTop="@dimen/primary_secondary_buttons_label_padding" android:paddingBottom="@dimen/primary_secondary_buttons_label_padding" android:paddingStart="20dp" @@ -314,6 +314,7 @@ android:textColor="@color/secondary_button_label_color" android:gravity="center" android:background="@drawable/secondary_button_background" + app:layout_constraintVertical_bias="1" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/no_account_yet" app:layout_constraintTop_toBottomOf="@id/third_party_sip_account" diff --git a/app/src/main/res/layout/assistant_register_fragment.xml b/app/src/main/res/layout/assistant_register_fragment.xml index cc0794ba0..1e5add134 100644 --- a/app/src/main/res/layout/assistant_register_fragment.xml +++ b/app/src/main/res/layout/assistant_register_fragment.xml @@ -33,7 +33,8 @@ + android:layout_height="match_parent" + android:fillViewport="true"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimen.xml b/app/src/main/res/values/dimen.xml index a72af6d12..27c15034a 100644 --- a/app/src/main/res/values/dimen.xml +++ b/app/src/main/res/values/dimen.xml @@ -28,6 +28,7 @@ 55dp 70dp + 5dp 28dp 48dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 89b7ba198..63d06b6bd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -14,6 +14,17 @@ linphone_notification_incoming_call_id linphone_notification_service_id + GNU General Public License v3.0 + © Belledonne Communications 2010-2023 + linphone-android@belledonne-communications.com + + https://linphone.org/contact + https://linphone.org/privacy-policy + https://linphone.org/general-terms + https://subscribe.linphone.org + https://weblate.linphone.org/ + https://wiki.linphone.org/xwiki/wiki/public/view/Linphone/Third%20party%20components%20/#Hlinphone-android + SIP address Display name Domain @@ -106,7 +117,26 @@ Settings Recordings + Help + About &appName; + Privacy policy + What information &appName; collects and uses + Version + Check update + Contribute on &appName; translation + Advanced + Enable/disable debug logs + Blah + Clean logs + Share logs + Share debug logs link using… + A new version is available: %s + Your version is up-to-date + An error occurred while checking for update + Debug logs have been cleaned + Debug logs URL copied into clipboard + Failed to upload debug logs Manage account Details